fis-gtm/sr_port/exfunc.c

131 lines
4.7 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 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 "compiler.h"
#include "opcode.h"
#include "toktyp.h"
#include "mdq.h"
#include "advancewindow.h"
#define INDIR_DUMMY -1
error_def(ERR_ACTOFFSET);
int exfunc(oprtype *a, boolean_t alias_target)
{
triple *calltrip, *calltrip_opr1_tref, *counttrip, *funret, *labelref, *masktrip;
triple *oldchain, *ref0, *routineref, tmpchain, *triptr;
# if defined(USHBIN_SUPPORTED) || defined(VMS)
triple *tripsize;
# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
assert(TK_DOLLAR == TREF(window_token));
advancewindow();
dqinit(&tmpchain, exorder);
oldchain = setcurtchain(&tmpchain);
calltrip = entryref(OC_EXFUN, OC_EXTEXFUN, INDIR_DUMMY, TRUE, TRUE, FALSE);
setcurtchain(oldchain);
if (!calltrip)
return FALSE;
if (OC_EXFUN == calltrip->opcode)
{
assert(MLAB_REF == calltrip->operand[0].oprclass);
# if defined(USHBIN_SUPPORTED) || defined(VMS)
ref0 = newtriple(OC_PARAMETER);
ref0->operand[0] = put_tsiz(); /* Need size of following code gen triple here */
calltrip->operand[1] = put_tref(ref0);
tripsize = ref0->operand[0].oprval.tref;
assert(OC_TRIPSIZE == tripsize->opcode);
# else
ref0 = calltrip;
# endif
} else
{
assert(TRIP_REF == calltrip->operand[1].oprclass);
calltrip_opr1_tref = calltrip->operand[1].oprval.tref;
if (OC_EXTEXFUN == calltrip->opcode)
{
if (OC_CDLIT == calltrip_opr1_tref->opcode)
assert(CDLT_REF == calltrip_opr1_tref->operand[0].oprclass);
else
{
assert(OC_LABADDR == calltrip_opr1_tref->opcode);
assert(TRIP_REF == calltrip_opr1_tref->operand[1].oprclass);
assert(OC_PARAMETER == calltrip_opr1_tref->operand[1].oprval.tref->opcode);
assert(TRIP_REF == calltrip_opr1_tref->operand[1].oprval.tref->operand[0].oprclass);
assert(OC_ILIT == calltrip_opr1_tref->operand[1].oprval.tref->operand[0].oprval.tref->opcode);
assert(ILIT_REF
== calltrip_opr1_tref->operand[1].oprval.tref->operand[0].oprval.tref->operand[0].oprclass);
if (0 != calltrip_opr1_tref->operand[1].oprval.tref->operand[0].oprval.tref->operand[0].oprval.ilit)
{
stx_error(ERR_ACTOFFSET);
return FALSE;
}
}
} else /* indirect: $$@(glvn)[(actuallist)]; note disabiguating parens around glvn specifying dlabel*/
{
assert(OC_COMMARG == calltrip->opcode);
assert(TRIP_REF == calltrip->operand[1].oprclass);
assert(OC_ILIT == calltrip_opr1_tref->opcode);
assert(ILIT_REF == calltrip_opr1_tref->operand[0].oprclass);
assert(INDIR_DUMMY == calltrip_opr1_tref->operand[0].oprval.ilit);
assert(calltrip->exorder.fl == &tmpchain);
routineref = maketriple(OC_CURRHD);
labelref = maketriple(OC_LABADDR);
ref0 = maketriple(OC_PARAMETER);
dqins(calltrip->exorder.bl, exorder, routineref);
dqins(calltrip->exorder.bl, exorder, labelref);
dqins(calltrip->exorder.bl, exorder, ref0);
labelref->operand[0] = calltrip->operand[0];
labelref->operand[1] = put_tref(ref0);
ref0->operand[0] = calltrip->operand[1];
ref0->operand[0].oprval.tref->operand[0].oprval.ilit = 0;
ref0->operand[1] = put_tref(routineref);
calltrip->operand[0] = put_tref(routineref);
calltrip->operand[1] = put_tref(labelref);
calltrip->opcode = OC_EXTEXFUN;
}
ref0 = newtriple(OC_PARAMETER);
ref0->operand[0] = calltrip->operand[1];
calltrip->operand[1] = put_tref(ref0);
}
if (TK_LPAREN != TREF(window_token))
{
masktrip = newtriple(OC_PARAMETER);
counttrip = newtriple(OC_PARAMETER);
masktrip->operand[0] = put_ilit(0);
counttrip->operand[0] = put_ilit(0);
masktrip->operand[1] = put_tref(counttrip);
ref0->operand[1] = put_tref(masktrip);
} else
if (!actuallist(&ref0->operand[1]))
return FALSE;
triptr = oldchain->exorder.bl;
dqadd(triptr, &tmpchain, exorder); /*this is a violation of info hiding*/
if (OC_EXFUN == calltrip->opcode)
{
assert(MLAB_REF == calltrip->operand[0].oprclass);
triptr = newtriple(OC_JMP);
triptr->operand[0] = put_mfun(&calltrip->operand[0].oprval.lab->mvname);
calltrip->operand[0].oprclass = ILIT_REF; /* dummy placeholder */
# if defined(USHBIN_SUPPORTED) || defined(VMS)
tripsize->operand[0].oprval.tsize->ct = triptr;
# endif
}
/* If target is an alias, use special container-expecting routine OC_EXFUNRETALS, else regular OC_EXFUNRET */
funret = newtriple((alias_target ? OC_EXFUNRETALS : OC_EXFUNRET));
funret->operand[0] = *a = put_tref(calltrip);
return TRUE;
}