fis-gtm/sr_port/op_indlvadr.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;
error_def(ERR_VAREXPECTED);
void op_indlvadr(mval *target)
{
char *ptr;
icode_str indir_src;
int rval;
mname_entry *targ_key;
mstr *obj, object;
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)))
{
obj = &object;
comp_init(&target->str);
switch (TREF(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 (EXPR_FAIL != (rval = indirection(&v))) /* NOTE assignment */
{ /* 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);
rval = EXPR_FAIL;
break;
}
if (EXPR_FAIL == comp_fini(rval, obj, OC_IRETMVAD, &v, target->str.len))
return;
/* 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 = obj->addr + obj->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);
obj->len += len;
cache_put(&indir_src, obj); /* this copies the "extended" object to the cache */
} 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;
}