148 lines
5.2 KiB
C
148 lines
5.2 KiB
C
|
/****************************************************************
|
||
|
* *
|
||
|
* Copyright 2001, 2011 Fidelity Information Services, Inc *
|
||
|
* *
|
||
|
* This source code contains the intellectual property *
|
||
|
* of its copyright holder(s), and is made available *
|
||
|
* under a license. If you do not know the terms of *
|
||
|
* the license, please stop and do not read further. *
|
||
|
* *
|
||
|
****************************************************************/
|
||
|
|
||
|
#include "mdef.h"
|
||
|
#include "gtm_string.h"
|
||
|
#include "compiler.h"
|
||
|
#include "opcode.h"
|
||
|
#include "toktyp.h"
|
||
|
#include "indir_enum.h"
|
||
|
#include "cache.h"
|
||
|
#include "hashtab_mname.h"
|
||
|
#include "hashtab_objcode.h"
|
||
|
#include "op.h"
|
||
|
#include "valid_mname.h"
|
||
|
#include "stack_frame.h"
|
||
|
#include "stringpool.h"
|
||
|
|
||
|
GBLREF boolean_t mstr_native_align;
|
||
|
GBLREF hash_table_objcode cache_table;
|
||
|
GBLREF stack_frame *frame_pointer;
|
||
|
GBLREF char window_token;
|
||
|
|
||
|
error_def(ERR_VAREXPECTED);
|
||
|
|
||
|
void op_indlvadr(mval *target)
|
||
|
{
|
||
|
boolean_t rval;
|
||
|
char *ptr;
|
||
|
icode_str indir_src;
|
||
|
mname_entry *targ_key;
|
||
|
mstr object, *obj;
|
||
|
mval *saved_indx;
|
||
|
oprtype v;
|
||
|
triple *s;
|
||
|
uint4 align_padlen, len;
|
||
|
DCL_THREADGBL_ACCESS;
|
||
|
|
||
|
SETUP_THREADGBL_ACCESS;
|
||
|
MV_FORCE_STR(target);
|
||
|
indir_src.str = target->str;
|
||
|
indir_src.code = indir_lvadr;
|
||
|
saved_indx = NULL;
|
||
|
if (NULL == (obj = cache_get(&indir_src)))
|
||
|
{
|
||
|
comp_init(&target->str);
|
||
|
switch (window_token)
|
||
|
{
|
||
|
case TK_IDENT:
|
||
|
rval = lvn(&v, OC_SAVPUTINDX, NULL);
|
||
|
s = v.oprval.tref; /* this ugliness serves to return a flag compiled code can use to adjust flow */
|
||
|
if (OC_SAVPUTINDX != s->opcode)
|
||
|
{ /* this block grabs a way to look up the name later and is similar to some code in op_savputindx */
|
||
|
assert(MVAR_REF == s->operand->oprclass);
|
||
|
saved_indx = (mval *)malloc(SIZEOF(mval) + SIZEOF(mname_entry) + SIZEOF(mident_fixed));
|
||
|
saved_indx->mvtype = MV_STR;
|
||
|
ptr = (char *)saved_indx + SIZEOF(mval);
|
||
|
saved_indx->str.addr = ptr;
|
||
|
targ_key = (mname_entry *)ptr;
|
||
|
ptr += SIZEOF(mname_entry);
|
||
|
targ_key->var_name.addr = ptr;
|
||
|
len = s->operand[0].oprval.vref->mvname.len;
|
||
|
assert(SIZEOF(mident_fixed) > len);
|
||
|
memcpy(ptr, s->operand[0].oprval.vref->mvname.addr, len);
|
||
|
targ_key->var_name.len = len;
|
||
|
saved_indx->str.len = SIZEOF(mname_entry) + len;
|
||
|
COMPUTE_HASH_MNAME(targ_key);
|
||
|
targ_key->marked = FALSE;
|
||
|
MANAGE_FOR_INDX(frame_pointer, TREF(for_nest_level), saved_indx);
|
||
|
}
|
||
|
break;
|
||
|
case TK_ATSIGN:
|
||
|
if (rval = indirection(&v))
|
||
|
{ /* if the indirection nests, for_ctrl_indr_subs doesn't matter until we get the "real" lvn */
|
||
|
s = newtriple(OC_INDLVADR);
|
||
|
s->operand[0] = v;
|
||
|
v = put_tref(s);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
stx_error(ERR_VAREXPECTED);
|
||
|
break;
|
||
|
}
|
||
|
if (comp_fini(rval, &object, OC_IRETMVAD, &v, target->str.len))
|
||
|
{ /* before cache and execute, tack a little something on at end of object */
|
||
|
assert(indir_src.str.addr == target->str.addr);
|
||
|
len = SIZEOF(uint4) * 2;
|
||
|
if (NULL != saved_indx)
|
||
|
len += SIZEOF(mval) + SIZEOF(mname_entry) + SIZEOF(mident_fixed); /* overlength, but ends aligned */
|
||
|
align_padlen = mstr_native_align ? PADLEN(stringpool.free, NATIVE_WSIZE) : 0;
|
||
|
len += align_padlen;
|
||
|
ptr = object.addr + object.len + align_padlen;
|
||
|
assert((char *)stringpool.free - align_padlen == ptr);
|
||
|
assert(ptr + len <= (char *)stringpool.top); /* ind_code, called by comp_fini, reserves to prevent gc */
|
||
|
if (NULL != saved_indx)
|
||
|
{ /* it's an unsubscripted name, so save the name infomation with the cached object */
|
||
|
memcpy(ptr, (char *)saved_indx, SIZEOF(mval) + saved_indx->str.len);
|
||
|
ptr += (len - (SIZEOF(uint4) * 2));
|
||
|
*(uint4 *)ptr = align_padlen;
|
||
|
}
|
||
|
ptr += SIZEOF(uint4);
|
||
|
*(uint4 *)ptr = len;
|
||
|
stringpool.free += len;
|
||
|
assert((ptr + SIZEOF(uint4)) == (char *)stringpool.free);
|
||
|
object.len += len;
|
||
|
cache_put(&indir_src, &object); /* this copies the "extended" object to the cache */
|
||
|
comp_indr(&object);
|
||
|
}
|
||
|
} else
|
||
|
{ /* if cached, the object has stuff at the end that might need pulling into the run-time context */
|
||
|
ptr = (char *)(obj->addr + obj->len);
|
||
|
len = *(uint4 *)(ptr - SIZEOF(uint4));
|
||
|
if (SIZEOF(mval) < len) /* not nested and not subscripted ? */
|
||
|
{ /* grab the name information at the end of the cached indirect object and copy it to be useful to FOR */
|
||
|
align_padlen = *(uint4 *)(ptr - (SIZEOF(uint4) * 2));
|
||
|
assert(NATIVE_WSIZE > align_padlen);
|
||
|
assert(SIZEOF(mval) + SIZEOF(mname_entry) + SIZEOF(mident_fixed) + (SIZEOF(uint4) * 2)
|
||
|
+ NATIVE_WSIZE > len);
|
||
|
ptr -= (len + align_padlen);
|
||
|
saved_indx = (mval *)ptr;
|
||
|
assert(MV_STR == saved_indx->mvtype);
|
||
|
len = SIZEOF(mval) + saved_indx->str.len;
|
||
|
ptr = malloc(len);
|
||
|
memcpy(ptr, (char *)saved_indx, len);
|
||
|
saved_indx = (mval *)ptr;
|
||
|
ptr += SIZEOF(mval);
|
||
|
saved_indx->str.addr = ptr;
|
||
|
assert(MAX_MIDENT_LEN >= ((mname_entry *)(saved_indx->str.addr))->var_name.len);
|
||
|
assert((SIZEOF(mname_entry) + ((mname_entry *)(saved_indx->str.addr))->var_name.len)
|
||
|
== saved_indx->str.len);
|
||
|
ptr += SIZEOF(mname_entry);
|
||
|
((mname_entry *)(saved_indx->str.addr))->var_name.addr = ptr;
|
||
|
len = SIZEOF(mval) + SIZEOF(mname_entry) + SIZEOF(mident_fixed) + (SIZEOF(uint4) * 2);
|
||
|
assert(*(uint4 *)(obj->addr + obj->len - SIZEOF(uint4)) == len);
|
||
|
MANAGE_FOR_INDX(frame_pointer, TREF(for_nest_level), saved_indx);
|
||
|
}
|
||
|
comp_indr(obj);
|
||
|
}
|
||
|
return;
|
||
|
}
|