gbdk-releases/sdcc/src/SDCCicode.c

3610 lines
95 KiB
C
Raw Permalink Normal View History

2015-01-10 16:25:06 +01:00
/*-------------------------------------------------------------------------
2015-01-10 16:25:09 +01:00
SDCCicode.c - intermediate code generation etc.
2015-01-10 16:25:06 +01:00
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
2015-01-10 16:25:09 +01:00
what you give them. Help stamp out software-hoarding!
2015-01-10 16:25:06 +01:00
-------------------------------------------------------------------------*/
#include "common.h"
2015-01-10 16:25:09 +01:00
#include "newalloc.h"
#include "math.h"
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* global variables */
2015-01-10 16:25:09 +01:00
set *iCodeChain = NULL;
2015-01-10 16:25:06 +01:00
int iTempNum = 0;
int iTempLblNum = 0;
2015-01-10 16:25:09 +01:00
int operandKey = 0;
2015-01-10 16:25:06 +01:00
int iCodeKey = 0;
2015-01-10 16:25:09 +01:00
char *filename;
int lineno;
2015-01-10 16:25:06 +01:00
int block;
int scopeLevel;
2015-01-10 16:25:09 +01:00
symbol *returnLabel; /* function return label */
symbol *entryLabel; /* function entry label */
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* forward definition of some functions */
2015-01-10 16:25:09 +01:00
operand *geniCodeDivision (operand *, operand *);
operand *geniCodeAssign (operand *, operand *, int);
operand *geniCodeArray (operand *, operand *,int);
2015-01-10 16:25:06 +01:00
operand *geniCodeArray2Ptr (operand *);
2015-01-10 16:25:09 +01:00
operand *geniCodeRValue (operand *, bool);
operand *geniCodeDerefPtr (operand *,int);
int isLvaluereq(int lvl);
2015-01-10 16:25:06 +01:00
#define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
2015-01-10 16:25:09 +01:00
/* forward definition of ic print functions */
PRINTFUNC (picGetValueAtAddr);
PRINTFUNC (picSetValueAtAddr);
PRINTFUNC (picAddrOf);
PRINTFUNC (picGeneric);
PRINTFUNC (picGenericOne);
PRINTFUNC (picCast);
PRINTFUNC (picAssign);
PRINTFUNC (picLabel);
PRINTFUNC (picGoto);
PRINTFUNC (picIfx);
PRINTFUNC (picJumpTable);
PRINTFUNC (picInline);
PRINTFUNC (picReceive);
iCodeTable codeTable[] =
{
{'!', "not", picGenericOne, NULL},
{'~', "~", picGenericOne, NULL},
{RRC, "rrc", picGenericOne, NULL},
{RLC, "rlc", picGenericOne, NULL},
{GETHBIT, "ghbit", picGenericOne, NULL},
{UNARYMINUS, "-", picGenericOne, NULL},
{IPUSH, "push", picGenericOne, NULL},
{IPOP, "pop", picGenericOne, NULL},
{CALL, "call", picGenericOne, NULL},
{PCALL, "pcall", picGenericOne, NULL},
{FUNCTION, "proc", picGenericOne, NULL},
{ENDFUNCTION, "eproc", picGenericOne, NULL},
{RETURN, "ret", picGenericOne, NULL},
{'+', "+", picGeneric, NULL},
{'-', "-", picGeneric, NULL},
{'*', "*", picGeneric, NULL},
{'/', "/", picGeneric, NULL},
{'%', "%", picGeneric, NULL},
{'>', ">", picGeneric, NULL},
{'<', "<", picGeneric, NULL},
{LE_OP, "<=", picGeneric, NULL},
{GE_OP, ">=", picGeneric, NULL},
{EQ_OP, "==", picGeneric, NULL},
{NE_OP, "!=", picGeneric, NULL},
{AND_OP, "&&", picGeneric, NULL},
{OR_OP, "||", picGeneric, NULL},
{'^', "^", picGeneric, NULL},
{'|', "|", picGeneric, NULL},
{BITWISEAND, "&", picGeneric, NULL},
{LEFT_OP, "<<", picGeneric, NULL},
{RIGHT_OP, ">>", picGeneric, NULL},
{GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
{ADDRESS_OF, "&", picAddrOf, NULL},
{CAST, "<>", picCast, NULL},
{'=', ":=", picAssign, NULL},
{LABEL, "", picLabel, NULL},
{GOTO, "", picGoto, NULL},
{JUMPTABLE, "jtab", picJumpTable, NULL},
{IFX, "if", picIfx, NULL},
{INLINEASM, "", picInline, NULL},
{RECEIVE, "recv", picReceive, NULL},
{SEND, "send", picGenericOne, NULL},
{ARRAYINIT, "arrayInit", picGenericOne, NULL},
2015-01-10 16:25:06 +01:00
};
2015-01-10 16:25:09 +01:00
/*-----------------------------------------------------------------*/
/* checkConstantRange: check a constant against the type */
/*-----------------------------------------------------------------*/
/* pedantic=0: allmost anything is allowed as long as the absolute
value is within the bit range of the type, and -1 is treated as
0xf..f for unsigned types (e.g. in assign)
pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
pedantic>1: "char c=200" is not allowed (evaluates to -56)
*/
void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
double max;
char message[132]="";
int warnings=0;
int negative=0;
long v;
max = pow ((double)2.0, (double)bitsForType(ltype));
if (SPEC_LONG(val->type)) {
if (SPEC_USIGN(val->type)) {
v=SPEC_CVAL(val->type).v_ulong;
} else {
v=SPEC_CVAL(val->type).v_long;
}
} else {
if (SPEC_USIGN(val->type)) {
v=SPEC_CVAL(val->type).v_uint;
} else {
v=SPEC_CVAL(val->type).v_int;
}
}
#if 0
// this could be a good idea
if (options.pedantic)
pedantic=2;
#endif
if (SPEC_NOUN(ltype)==FLOAT) {
// anything will do
return;
}
if (!SPEC_USIGN(val->type) && v<0) {
negative=1;
if (SPEC_USIGN(ltype) && (pedantic>1)) {
warnings++;
}
v=-v;
}
// if very pedantic: "char c=200" is not allowed
if (pedantic>1 && !SPEC_USIGN(ltype)) {
max = max/2 + negative;
}
if (v >= max) {
warnings++;
}
if (warnings) {
sprintf (message, "for %s %s in %s",
SPEC_USIGN(ltype) ? "unsigned" : "signed",
nounName(ltype), msg);
werror (W_CONST_RANGE, message);
if (pedantic>1)
fatalError++;
}
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* operandName - returns the name of the operand */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
printOperand (operand * op, FILE * file)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *opetype;
int pnl = 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!op)
return 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!file)
{
file = stdout;
pnl = 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
switch (op->type)
{
2015-01-10 16:25:06 +01:00
case VALUE:
2015-01-10 16:25:09 +01:00
opetype = getSpec (operandType (op));
if (SPEC_NOUN (opetype) == V_FLOAT)
fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
else
fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
printTypeChain (operandType (op), file);
fprintf (file, "}");
break;
case SYMBOL:
2015-01-10 16:25:06 +01:00
#define REGA 1
2015-01-10 16:25:09 +01:00
#ifdef REGA
fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
(OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
op->key,
OP_LIVEFROM (op), OP_LIVETO (op),
OP_SYMBOL (op)->stack,
op->isaddr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc
);
{
fprintf (file, "{");
printTypeChain (operandType (op), file);
if (SPIL_LOC (op) && IS_ITEMP (op))
fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
fprintf (file, "}");
}
/* if assigned to registers */
if (OP_SYMBOL (op)->nRegs)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (OP_SYMBOL (op)->isspilt)
{
if (!OP_SYMBOL (op)->remat)
if (OP_SYMBOL (op)->usl.spillLoc)
fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
OP_SYMBOL (op)->usl.spillLoc->rname :
OP_SYMBOL (op)->usl.spillLoc->name));
2015-01-10 16:25:06 +01:00
else
2015-01-10 16:25:09 +01:00
fprintf (file, "[err]");
else
fprintf (file, "[remat]");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
int i;
fprintf (file, "[");
for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
fprintf (file, "]");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
}
2015-01-10 16:25:06 +01:00
#else
2015-01-10 16:25:09 +01:00
fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
/* if assigned to registers */
if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
{
int i;
fprintf (file, "[");
for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
OP_SYMBOL (op)->regs[i]->name :
"err"));
fprintf (file, "]");
}
2015-01-10 16:25:06 +01:00
#endif
2015-01-10 16:25:09 +01:00
break;
2015-01-10 16:25:06 +01:00
case TYPE:
2015-01-10 16:25:09 +01:00
fprintf (file, "(");
printTypeChain (op->operand.typeOperand, file);
fprintf (file, ")");
break;
}
if (pnl)
fprintf (file, "\n");
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* print functions */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
PRINTFUNC (picGetValueAtAddr)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
printOperand (IC_RESULT (ic), of);
fprintf (of, " = ");
fprintf (of, "@[");
printOperand (IC_LEFT (ic), of);
fprintf (of, "]");
fprintf (of, "\n");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picSetValueAtAddr)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
fprintf (of, "*[");
printOperand (IC_LEFT (ic), of);
fprintf (of, "] = ");
printOperand (IC_RIGHT (ic), of);
fprintf (of, "\n");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picAddrOf)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
printOperand (IC_RESULT (ic), of);
if (IS_ITEMP (IC_LEFT (ic)))
fprintf (of, " = ");
else
fprintf (of, " = &[");
printOperand (IC_LEFT (ic), of);
if (IC_RIGHT (ic))
{
if (IS_ITEMP (IC_LEFT (ic)))
fprintf (of, " offsetAdd ");
else
fprintf (of, " , ");
printOperand (IC_RIGHT (ic), of);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IS_ITEMP (IC_LEFT (ic)))
fprintf (of, "\n");
else
fprintf (of, "]\n");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picJumpTable)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
symbol *sym;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
fprintf (of, "%s\t", s);
printOperand (IC_JTCOND (ic), of);
fprintf (of, "\n");
for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
sym = setNextItem (IC_JTLABELS (ic)))
fprintf (of, "\t\t\t%s\n", sym->name);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picGeneric)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
printOperand (IC_RESULT (ic), of);
fprintf (of, " = ");
printOperand (IC_LEFT (ic), of);
fprintf (of, " %s ", s);
printOperand (IC_RIGHT (ic), of);
fprintf (of, "\n");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picGenericOne)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
if (IC_RESULT (ic))
{
printOperand (IC_RESULT (ic), of);
fprintf (of, " = ");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IC_LEFT (ic))
{
fprintf (of, "%s ", s);
printOperand (IC_LEFT (ic), of);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (!IC_RESULT (ic) && !IC_LEFT (ic))
fprintf (of, s);
fprintf (of, "\n");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picCast)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
printOperand (IC_RESULT (ic), of);
fprintf (of, " = ");
printOperand (IC_LEFT (ic), of);
printOperand (IC_RIGHT (ic), of);
fprintf (of, "\n");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picAssign)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
fprintf (of, "*(");
printOperand (IC_RESULT (ic), of);
if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
fprintf (of, ")");
fprintf (of, " %s ", s);
printOperand (IC_RIGHT (ic), of);
fprintf (of, "\n");
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picLabel)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picGoto)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "\t");
fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picIfx)
{
fprintf (of, "\t");
fprintf (of, "if ");
printOperand (IC_COND (ic), of);
if (!IC_TRUE (ic))
fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
else
{
fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
if (IC_FALSE (ic))
fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picInline)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
fprintf (of, "%s", IC_INLINE (ic));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
PRINTFUNC (picReceive)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
printOperand (IC_RESULT (ic), of);
fprintf (of, " = %s ", s);
printOperand (IC_LEFT (ic), of);
fprintf (of, "\n");
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* piCode - prints one iCode */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
piCode (void *item, FILE * of)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic = item;
iCodeTable *icTab;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!of)
of = stdout;
icTab = getTableEntry (ic->op);
fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
ic->filename, ic->lineno,
ic->seq, ic->key, ic->depth, ic->supportRtn);
icTab->iCodePrint (of, ic, icTab->printName);
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
void PICC(iCode *ic)
{
printiCChain(ic,stdout);
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* printiCChain - prints intermediate code for humans */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
printiCChain (iCode * icChain, FILE * of)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *loop;
iCodeTable *icTab;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!of)
of = stdout;
for (loop = icChain; loop; loop = loop->next)
{
if ((icTab = getTableEntry (loop->op)))
{
fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
loop->filename, loop->lineno,
loop->seq, loop->key, loop->depth, loop->supportRtn);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
icTab->iCodePrint (of, loop, icTab->printName);
2015-01-10 16:25:06 +01:00
}
}
}
/*-----------------------------------------------------------------*/
/* newOperand - allocate, init & return a new iCode */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
newOperand ()
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
operand *op;
op = Safe_alloc ( sizeof (operand));
op->key = 0;
return op;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newiCode - create and return a new iCode entry initialised */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
iCode *
newiCode (int op, operand * left, operand * right)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
ic = Safe_alloc ( sizeof (iCode));
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
ic->lineno = lineno;
ic->filename = filename;
ic->block = block;
ic->level = scopeLevel;
ic->op = op;
ic->key = iCodeKey++;
IC_LEFT (ic) = left;
IC_RIGHT (ic) = right;
return ic;
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* newiCode for conditional statements */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
iCode *
newiCodeCondition (operand * condition,
symbol * trueLabel,
symbol * falseLabel)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
if (IS_VOID(operandType(condition))) {
werror(E_VOID_VALUE_USED);
}
ic = newiCode (IFX, NULL, NULL);
IC_COND (ic) = condition;
IC_TRUE (ic) = trueLabel;
IC_FALSE (ic) = falseLabel;
return ic;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newiCodeLabelGoto - unconditional goto statement| label stmnt */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
iCode *
newiCodeLabelGoto (int op, symbol * label)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
ic = newiCode (op, NULL, NULL);
ic->op = op;
ic->argLabel.label = label;
IC_LEFT (ic) = NULL;
IC_RIGHT (ic) = NULL;
IC_RESULT (ic) = NULL;
return ic;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newiTemp - allocate & return a newItemp Variable */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
symbol *
newiTemp (char *s)
{
symbol *itmp;
if (s)
sprintf (buffer, "%s", s);
else
sprintf (buffer, "iTemp%d", iTempNum++);
itmp = newSymbol (buffer, 1);
strcpy (itmp->rname, itmp->name);
itmp->isitmp = 1;
return itmp;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newiTempLabel - creates a temp variable label */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
symbol *
newiTempLabel (char *s)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
symbol *itmplbl;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* check if this alredy exists */
if (s && (itmplbl = findSym (LabelTab, NULL, s)))
return itmplbl;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (s)
itmplbl = newSymbol (s, 1);
else
{
sprintf (buffer, "iTempLbl%d", iTempLblNum++);
itmplbl = newSymbol (buffer, 1);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
itmplbl->isitmp = 1;
itmplbl->islbl = 1;
itmplbl->key = labelKey++;
addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
return itmplbl;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newiTempPreheaderLabel - creates a new preheader label */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
symbol *
newiTempPreheaderLabel ()
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
symbol *itmplbl;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
itmplbl = newSymbol (buffer, 1);
itmplbl->isitmp = 1;
itmplbl->islbl = 1;
itmplbl->key = labelKey++;
addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
return itmplbl;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* initiCode - initialises some iCode related stuff */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
initiCode ()
2015-01-10 16:25:06 +01:00
{
}
/*-----------------------------------------------------------------*/
/* copyiCode - make a copy of the iCode given */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
iCode *
copyiCode (iCode * ic)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *nic = newiCode (ic->op, NULL, NULL);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
nic->lineno = ic->lineno;
nic->filename = ic->filename;
nic->block = ic->block;
nic->level = ic->level;
nic->parmBytes = ic->parmBytes;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* deal with the special cases first */
switch (ic->op)
{
2015-01-10 16:25:06 +01:00
case IFX:
2015-01-10 16:25:09 +01:00
IC_COND (nic) = operandFromOperand (IC_COND (ic));
IC_TRUE (nic) = IC_TRUE (ic);
IC_FALSE (nic) = IC_FALSE (ic);
break;
2015-01-10 16:25:06 +01:00
case JUMPTABLE:
2015-01-10 16:25:09 +01:00
IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
IC_JTLABELS (nic) = IC_JTLABELS (ic);
break;
2015-01-10 16:25:06 +01:00
case CALL:
case PCALL:
2015-01-10 16:25:09 +01:00
IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
IC_ARGS (nic) = IC_ARGS (ic);
break;
2015-01-10 16:25:06 +01:00
case INLINEASM:
2015-01-10 16:25:09 +01:00
IC_INLINE (nic) = IC_INLINE (ic);
break;
case ARRAYINIT:
IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
break;
2015-01-10 16:25:06 +01:00
default:
2015-01-10 16:25:09 +01:00
IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return nic;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* getTableEntry - gets the table entry for the given operator */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
iCodeTable *
getTableEntry (int oper)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
int i;
for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
if (oper == codeTable[i].icode)
return &codeTable[i];
return NULL;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newiTempOperand - new intermediate temp operand */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
newiTempOperand (sym_link * type, char throwType)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
symbol *itmp;
operand *op = newOperand ();
sym_link *etype;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
op->type = SYMBOL;
itmp = newiTemp (NULL);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
etype = getSpec (type);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (IS_LITERAL (etype))
throwType = 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* copy the type information */
if (type)
itmp->etype = getSpec (itmp->type = (throwType ? type :
copyLinkChain (type)));
if (IS_LITERAL (itmp->etype))
{
SPEC_SCLS (itmp->etype) = S_REGISTER;
SPEC_OCLS (itmp->etype) = reg;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
op->operand.symOperand = itmp;
op->key = itmp->key = ++operandKey;
return op;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandType - returns the type chain for an operand */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
sym_link *
operandType (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
/* depending on type of operand */
switch (op->type)
{
case VALUE:
return op->operand.valOperand->type;
2015-01-10 16:25:06 +01:00
case SYMBOL:
2015-01-10 16:25:09 +01:00
return op->operand.symOperand->type;
case TYPE:
return op->operand.typeOperand;
2015-01-10 16:25:07 +01:00
default:
2015-01-10 16:25:09 +01:00
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
" operand type not known ");
assert (0); /* should never come here */
/* Just to keep the compiler happy */
return (sym_link *) 0;
2015-01-10 16:25:06 +01:00
}
}
/*-----------------------------------------------------------------*/
/* isParamterToCall - will return 1 if op is a parameter to args */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
isParameterToCall (value * args, operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
value *tval = args;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
while (tval)
{
if (tval->sym &&
isSymbolEqual (op->operand.symOperand, tval->sym))
return 1;
tval = tval->next;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* isOperandGlobal - return 1 if operand is a global variable */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
isOperandGlobal (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (!op)
return 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (IS_ITEMP (op))
2015-01-10 16:25:06 +01:00
return 0;
2015-01-10 16:25:09 +01:00
if (op->type == SYMBOL &&
(op->operand.symOperand->level == 0 ||
IS_STATIC (op->operand.symOperand->etype) ||
IS_EXTERN (op->operand.symOperand->etype))
)
return 1;
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* isOperandVolatile - return 1 if the operand is volatile */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
isOperandVolatile (operand * op, bool chkTemp)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *optype;
sym_link *opetype;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (IS_ITEMP (op) && !chkTemp)
return 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
opetype = getSpec (optype = operandType (op));
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
return 1;
if (IS_VOLATILE (opetype))
return 1;
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* isOperandLiteral - returns 1 if an operand contains a literal */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
isOperandLiteral (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *opetype;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!op)
2015-01-10 16:25:06 +01:00
return 0;
2015-01-10 16:25:09 +01:00
opetype = getSpec (operandType (op));
if (IS_LITERAL (opetype))
return 1;
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
/* isOperandInFarSpace - will return true if operand is in farSpace */
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
bool
isOperandInFarSpace (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *etype;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!op)
return FALSE;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!IS_SYMOP (op))
return FALSE;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!IS_TRUE_SYMOP (op))
{
if (SPIL_LOC (op))
etype = SPIL_LOC (op)->etype;
else
return FALSE;
}
else
{
etype = getSpec (operandType (op));
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
}
/*-----------------------------------------------------------------*/
/* isOperandOnStack - will return true if operand is on stack */
/*-----------------------------------------------------------------*/
bool
isOperandOnStack (operand * op)
{
sym_link *etype;
if (!op)
return FALSE;
if (!IS_SYMOP (op))
return FALSE;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
etype = getSpec (operandType (op));
return ((IN_STACK (etype)) ? TRUE : FALSE);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandLitValue - literal value of an operand */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
double
operandLitValue (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
assert (isOperandLiteral (op));
return floatFromVal (op->operand.valOperand);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandOperation - perforoms operations on operands */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
operandOperation (operand * left, operand * right,
int op, sym_link * type)
{
sym_link *let , *ret=NULL;
operand *retval = (operand *) 0;
assert (isOperandLiteral (left));
let = getSpec(operandType(left));
if (right) {
assert (isOperandLiteral (right));
ret = getSpec(operandType(left));
}
switch (op)
{
case '+':
retval = operandFromValue (valCastLiteral (type,
operandLitValue (left) +
operandLitValue (right)));
break;
case '-':
retval = operandFromValue (valCastLiteral (type,
operandLitValue (left) -
operandLitValue (right)));
break;
2015-01-10 16:25:06 +01:00
case '*':
2015-01-10 16:25:09 +01:00
retval = operandFromValue (valCastLiteral (type,
operandLitValue (left) *
operandLitValue (right)));
break;
2015-01-10 16:25:06 +01:00
case '/':
2015-01-10 16:25:09 +01:00
if ((unsigned long) operandLitValue (right) == 0)
{
werror (E_DIVIDE_BY_ZERO);
retval = right;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
retval = operandFromValue (valCastLiteral (type,
operandLitValue (left) /
operandLitValue (right)));
break;
case '%':
if ((unsigned long) operandLitValue (right) == 0) {
werror (E_DIVIDE_BY_ZERO);
retval = right;
}
else
retval = operandFromLit ((SPEC_USIGN(let) ?
(unsigned long) operandLitValue (left) :
(long) operandLitValue (left)) %
(SPEC_USIGN(ret) ?
(unsigned long) operandLitValue (right) :
(long) operandLitValue (right)));
break;
case LEFT_OP:
retval = operandFromLit ((SPEC_USIGN(let) ?
(unsigned long) operandLitValue (left) :
(long) operandLitValue (left)) <<
(SPEC_USIGN(ret) ?
(unsigned long) operandLitValue (right) :
(long) operandLitValue (right)));
break;
case RIGHT_OP:
retval = operandFromLit ((SPEC_USIGN(let) ?
(unsigned long) operandLitValue (left) :
(long) operandLitValue (left)) >>
(SPEC_USIGN(ret) ?
(unsigned long) operandLitValue (right) :
(long) operandLitValue (right)));
break;
case EQ_OP:
retval = operandFromLit (operandLitValue (left) ==
operandLitValue (right));
break;
case '<':
retval = operandFromLit (operandLitValue (left) <
operandLitValue (right));
break;
case LE_OP:
retval = operandFromLit (operandLitValue (left) <=
operandLitValue (right));
break;
case NE_OP:
retval = operandFromLit (operandLitValue (left) !=
operandLitValue (right));
break;
case '>':
retval = operandFromLit (operandLitValue (left) >
operandLitValue (right));
break;
case GE_OP:
retval = operandFromLit (operandLitValue (left) >=
operandLitValue (right));
break;
case BITWISEAND:
retval = operandFromLit ((long)operandLitValue(left) &
(long)operandLitValue(right));
break;
case '|':
retval = operandFromLit ((long)operandLitValue (left) |
(long)operandLitValue (right));
break;
case '^':
retval = operandFromLit ((long)operandLitValue (left) ^
(long)operandLitValue (right));
break;
2015-01-10 16:25:06 +01:00
case AND_OP:
2015-01-10 16:25:09 +01:00
retval = operandFromLit (operandLitValue (left) &&
operandLitValue (right));
break;
2015-01-10 16:25:06 +01:00
case OR_OP:
2015-01-10 16:25:09 +01:00
retval = operandFromLit (operandLitValue (left) ||
operandLitValue (right));
break;
2015-01-10 16:25:06 +01:00
case RRC:
2015-01-10 16:25:09 +01:00
{
long i = (long) operandLitValue (left);
retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
(i << 1));
}
break;
2015-01-10 16:25:06 +01:00
case RLC:
2015-01-10 16:25:09 +01:00
{
long i = (long) operandLitValue (left);
retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
(i >> 1));
}
break;
2015-01-10 16:25:06 +01:00
case UNARYMINUS:
2015-01-10 16:25:09 +01:00
retval = operandFromLit (-1 * operandLitValue (left));
break;
2015-01-10 16:25:06 +01:00
case '~':
2015-01-10 16:25:09 +01:00
retval = operandFromLit (~((long) operandLitValue (left)));
break;
2015-01-10 16:25:06 +01:00
case '!':
2015-01-10 16:25:09 +01:00
retval = operandFromLit (!operandLitValue (left));
break;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
default:
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
" operandOperation invalid operator ");
assert (0);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return retval;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* isOperandEqual - compares two operand & return 1 if they r = */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
isOperandEqual (operand * left, operand * right)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
/* if the pointers are equal then they are equal */
if (left == right)
return 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if either of them null then false */
if (!left || !right)
return 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (left->type != right->type)
return 0;
if (IS_SYMOP (left) && IS_SYMOP (right))
return left->key == right->key;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if types are the same */
switch (left->type)
{
case SYMBOL:
return isSymbolEqual (left->operand.symOperand,
right->operand.symOperand);
case VALUE:
return (floatFromVal (left->operand.valOperand) ==
floatFromVal (right->operand.valOperand));
case TYPE:
if (compareType (left->operand.typeOperand,
right->operand.typeOperand) == 1)
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 0;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/*-------------------------------------------------------------------*/
/* isiCodeEqual - compares two iCodes are equal, returns true if yes */
/*-------------------------------------------------------------------*/
int
isiCodeEqual (iCode * left, iCode * right)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
/* if the same pointer */
if (left == right)
return 1;
/* if either of them null */
if (!left || !right)
return 0;
/* if operand are the same */
if (left->op == right->op)
{
/* compare all the elements depending on type */
if (left->op != IFX)
{
if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
return 0;
if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
return 0;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
if (!isOperandEqual (IC_COND (left), IC_COND (right)))
return 0;
if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
return 0;
if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
return 0;
}
return 1;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newiTempFromOp - create a temp Operand with same attributes */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
newiTempFromOp (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
operand *nop;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!op)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!IS_ITEMP (op))
return op;
nop = newiTempOperand (operandType (op), TRUE);
nop->isaddr = op->isaddr;
nop->isvolatile = op->isvolatile;
nop->isGlobal = op->isGlobal;
nop->isLiteral = op->isLiteral;
nop->usesDefs = op->usesDefs;
nop->isParm = op->isParm;
return nop;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operand from operand - creates an operand holder for the type */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
operandFromOperand (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
operand *nop;
if (!op)
return NULL;
nop = newOperand ();
nop->type = op->type;
nop->isaddr = op->isaddr;
nop->key = op->key;
nop->isvolatile = op->isvolatile;
nop->isGlobal = op->isGlobal;
nop->isLiteral = op->isLiteral;
nop->usesDefs = op->usesDefs;
nop->isParm = op->isParm;
switch (nop->type)
{
case SYMBOL:
nop->operand.symOperand = op->operand.symOperand;
break;
case VALUE:
nop->operand.valOperand = op->operand.valOperand;
break;
case TYPE:
nop->operand.typeOperand = op->operand.typeOperand;
break;
}
return nop;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* opFromOpWithDU - makes a copy of the operand and DU chains */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
operand *nop = operandFromOperand (op);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (nop->type == SYMBOL)
{
OP_SYMBOL (nop)->defs = bitVectCopy (defs);
OP_SYMBOL (nop)->uses = bitVectCopy (uses);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return nop;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandFromSymbol - creates an operand from a symbol */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
operandFromSymbol (symbol * sym)
{
operand *op;
iCode *ic;
int ok = 1;
/* if the symbol's type is a literal */
/* then it is an enumerator type */
if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
return operandFromValue (valFromType (sym->etype));
if (!sym->key)
sym->key = ++operandKey;
/* if this an implicit variable, means struct/union */
/* member so just return it */
if (sym->implicit || IS_FUNC (sym->type))
{
op = newOperand ();
op->type = SYMBOL;
op->operand.symOperand = sym;
op->key = sym->key;
op->isvolatile = isOperandVolatile (op, TRUE);
op->isGlobal = isOperandGlobal (op);
return op;
}
/* under the following conditions create a
register equivalent for a local symbol */
if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
(IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
(!(options.model == MODEL_FLAT24)) ) &&
options.stackAuto == 0)
ok = 0;
if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
!IS_FUNC (sym->type) && /* not a function */
!sym->_isparm && /* not a parameter */
sym->level && /* is a local variable */
!sym->addrtaken && /* whose address has not been taken */
!sym->reqv && /* does not already have a reg equivalence */
!IS_VOLATILE (sym->etype) && /* not declared as volatile */
!IS_STATIC (sym->etype) && /* and not declared static */
!sym->islbl && /* not a label */
ok && /* farspace check */
!IS_BITVAR (sym->etype) /* not a bit variable */
)
{
/* we will use it after all optimizations
and before liveRange calculation */
sym->reqv = newiTempOperand (sym->type, 0);
sym->reqv->key = sym->key;
OP_SYMBOL (sym->reqv)->key = sym->key;
OP_SYMBOL (sym->reqv)->isreqv = 1;
OP_SYMBOL (sym->reqv)->islocal = 1;
OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
SPIL_LOC (sym->reqv) = sym;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (!IS_AGGREGATE (sym->type))
{
op = newOperand ();
op->type = SYMBOL;
op->operand.symOperand = sym;
op->isaddr = 1;
op->key = sym->key;
op->isvolatile = isOperandVolatile (op, TRUE);
op->isGlobal = isOperandGlobal (op);
op->isPtr = IS_PTR (operandType (op));
op->isParm = sym->_isparm;
return op;
}
/* create :- */
/* itemp = &[_symbol] */
ic = newiCode (ADDRESS_OF, newOperand (), NULL);
IC_LEFT (ic)->type = SYMBOL;
IC_LEFT (ic)->operand.symOperand = sym;
IC_LEFT (ic)->key = sym->key;
(IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
(IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
/* create result */
IC_RESULT (ic) = newiTempOperand (sym->type, 0);
if (IS_ARRAY (sym->type))
{
IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
IC_RESULT (ic)->isaddr = 0;
}
else
IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandFromValue - creates an operand from value */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
operandFromValue (value * val)
{
operand *op;
/* if this is a symbol then do the symbol thing */
if (val->sym)
return operandFromSymbol (val->sym);
/* this is not a symbol */
op = newOperand ();
op->type = VALUE;
op->operand.valOperand = val;
op->isLiteral = isOperandLiteral (op);
return op;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandFromLink - operand from typeChain */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
operandFromLink (sym_link * type)
{
operand *op;
/* operand from sym_link */
if (!type)
return NULL;
op = newOperand ();
op->type = TYPE;
op->operand.typeOperand = copyLinkChain (type);
return op;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandFromLit - makes an operand from a literal value */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
operandFromLit (double i)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
return operandFromValue (valueFromLit (i));
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* operandFromAst - creates an operand from an ast */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
operandFromAst (ast * tree,int lvl)
{
if (!tree)
return NULL;
/* depending on type do */
switch (tree->type)
{
case EX_OP:
return ast2iCode (tree,lvl+1);
break;
case EX_VALUE:
return operandFromValue (tree->opval.val);
break;
case EX_LINK:
return operandFromLink (tree->opval.lnk);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
assert (0);
/* Just to keep the comiler happy */
return (operand *) 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* setOperandType - sets the operand's type to the given type */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
setOperandType (operand * op, sym_link * type)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
/* depending on the type of operand */
switch (op->type)
{
case VALUE:
op->operand.valOperand->etype =
getSpec (op->operand.valOperand->type =
copyLinkChain (type));
return;
case SYMBOL:
if (op->operand.symOperand->isitmp)
op->operand.symOperand->etype =
getSpec (op->operand.symOperand->type =
copyLinkChain (type));
else
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"attempt to modify type of source");
return;
case TYPE:
op->operand.typeOperand = copyLinkChain (type);
return;
}
}
/*-----------------------------------------------------------------*/
/* Get size in byte of ptr need to access an array */
/*-----------------------------------------------------------------*/
int
getArraySizePtr (operand * op)
{
sym_link *ltype = operandType(op);
if(IS_PTR(ltype))
{
int size = getSize(ltype);
return(IS_GENPTR(ltype)?(size-1):size);
}
if(IS_ARRAY(ltype))
{
sym_link *letype = getSpec(ltype);
switch (PTR_TYPE (SPEC_OCLS (letype)))
{
case IPOINTER:
case PPOINTER:
case POINTER:
return (PTRSIZE);
case EEPPOINTER:
case FPOINTER:
case CPOINTER:
case FUNCTION:
return (FPTRSIZE);
case GPOINTER:
return (GPTRSIZE-1);
default:
return (FPTRSIZE);
}
}
return (FPTRSIZE);
}
/*-----------------------------------------------------------------*/
/* perform "usual unary conversions" */
/*-----------------------------------------------------------------*/
operand *
usualUnaryConversions (operand * op)
{
if (IS_INTEGRAL (operandType (op)))
{
if (getSize (operandType (op)) < (unsigned int) INTSIZE)
{
/* Widen to int. */
return geniCodeCast (INTTYPE, op, TRUE);
}
}
return op;
}
/*-----------------------------------------------------------------*/
/* perform "usual binary conversions" */
/*-----------------------------------------------------------------*/
sym_link *
usualBinaryConversions (operand ** op1, operand ** op2)
{
sym_link *ctype;
sym_link *rtype = operandType (*op2);
sym_link *ltype = operandType (*op1);
ctype = computeType (ltype, rtype);
*op1 = geniCodeCast (ctype, *op1, TRUE);
*op2 = geniCodeCast (ctype, *op2, TRUE);
return ctype;
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* geniCodeValueAtAddress - generate intermeditate code for value */
/* at address */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeRValue (operand * op, bool force)
{
iCode *ic;
sym_link *type = operandType (op);
sym_link *etype = getSpec (type);
/* if this is an array & already */
/* an address then return this */
if (IS_AGGREGATE (type) ||
(IS_PTR (type) && !force && !op->isaddr))
return operandFromOperand (op);
/* if this is not an address then must be */
/* rvalue already so return this one */
if (!op->isaddr)
return op;
/* if this is not a temp symbol then */
if (!IS_ITEMP (op) &&
!force &&
!IN_FARSPACE (SPEC_OCLS (etype)))
{
op = operandFromOperand (op);
op->isaddr = 0;
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (IS_SPEC (type) &&
IS_TRUE_SYMOP (op) &&
(!IN_FARSPACE (SPEC_OCLS (etype)) ||
/* TARGET_IS_DS390)) */
(options.model == MODEL_FLAT24) ))
{
op = operandFromOperand (op);
op->isaddr = 0;
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
if (IS_PTR (type) && op->isaddr && force)
type = type->next;
type = copyLinkChain (type);
IC_RESULT (ic) = newiTempOperand (type, 1);
IC_RESULT (ic)->isaddr = 0;
2015-01-10 16:25:06 +01:00
/* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
2015-01-10 16:25:09 +01:00
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeCast - changes the value from one type to another */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeCast (sym_link * type, operand * op, bool implicit)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
sym_link *optype;
sym_link *opetype = getSpec (optype = operandType (op));
sym_link *restype;
int errors=0;
/* one of them has size zero then error */
if (IS_VOID (optype))
{
werror (E_CAST_ZERO);
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if the operand is already the desired type then do nothing */
if (compareType (type, optype) == 1)
return op;
/* if this is a literal then just change the type & return */
if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
return operandFromValue (valCastLiteral (type,
operandLitValue (op)));
/* if casting to/from pointers, do some checking */
if (IS_PTR(type)) { // to a pointer
if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
if (IS_INTEGRAL(optype)) {
// maybe this is NULL, than it's ok.
if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
// no way to set the storage
if (IS_LITERAL(optype)) {
werror(E_LITERAL_GENERIC);
errors++;
} else {
werror(E_NONPTR2_GENPTR);
errors++;
}
} else if (implicit) {
werror(W_INTEGRAL2PTR_NOCAST);
errors++;
}
}
} else {
// shouldn't do that with float, array or structure unless to void
if (!IS_VOID(getSpec(type)) &&
!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
werror(E_INCOMPAT_TYPES);
errors++;
}
}
} else { // from a pointer to a pointer
if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
// if not a pointer to a function
if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
if (implicit) { // if not to generic, they have to match
if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
werror(E_INCOMPAT_PTYPES);
errors++;
}
}
}
}
}
} else { // to a non pointer
if (IS_PTR(optype)) { // from a pointer
if (implicit) { // sneaky
if (IS_INTEGRAL(type)) {
werror(W_PTR2INTEGRAL_NOCAST);
errors++;
} else { // shouldn't do that with float, array or structure
werror(E_INCOMPAT_TYPES);
errors++;
}
}
}
}
if (errors) {
printFromToType (optype, type);
}
/* if they are the same size create an assignment */
if (getSize (type) == getSize (optype) &&
!IS_BITFIELD (type) &&
!IS_FLOAT (type) &&
!IS_FLOAT (optype) &&
((IS_SPEC (type) && IS_SPEC (optype)) ||
(!IS_SPEC (type) && !IS_SPEC (optype))))
{
ic = newiCode ('=', NULL, op);
IC_RESULT (ic) = newiTempOperand (type, 0);
SPIL_LOC (IC_RESULT (ic)) =
(IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
IC_RESULT (ic)->isaddr = 0;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
ic = newiCode (CAST, operandFromLink (type),
geniCodeRValue (op, FALSE));
IC_RESULT (ic) = newiTempOperand (type, 0);
}
/* preserve the storage class & output class */
/* of the original variable */
restype = getSpec (operandType (IC_RESULT (ic)));
SPEC_SCLS (restype) = SPEC_SCLS (opetype);
SPEC_OCLS (restype) = SPEC_OCLS (opetype);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeLabel - will create a Label */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
geniCodeLabel (symbol * label)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
ic = newiCodeLabelGoto (LABEL, label);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeGoto - will create a Goto */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
geniCodeGoto (symbol * label)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
ic = newiCodeLabelGoto (GOTO, label);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeMultiply - gen intermediate code for multiplication */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeMultiply (operand * left, operand * right,int resultIsInt)
{
iCode *ic;
int p2 = 0;
sym_link *resType;
LRTYPE;
/* if they are both literal then we know the result */
if (IS_LITERAL (letype) && IS_LITERAL (retype))
return operandFromValue (valMult (left->operand.valOperand,
right->operand.valOperand));
if (IS_LITERAL(retype)) {
p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
}
resType = usualBinaryConversions (&left, &right);
#if 1
rtype = operandType (right);
retype = getSpec (rtype);
ltype = operandType (left);
letype = getSpec (ltype);
#endif
if (resultIsInt)
{
SPEC_NOUN(getSpec(resType))=V_INT;
}
/* if the right is a literal & power of 2 */
/* then make it a left shift */
/* code generated for 1 byte * 1 byte literal = 2 bytes result is more
efficient in most cases than 2 bytes result = 2 bytes << literal
if port has 1 byte muldiv */
if (p2 && !IS_FLOAT (letype) &&
!((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
(port->support.muldiv == 1)))
{
if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
{
/* LEFT_OP need same size for left and result, */
left = geniCodeCast (resType, left, TRUE);
ltype = operandType (left);
}
ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
}
else
{
ic = newiCode ('*', left, right); /* normal multiplication */
/* if the size left or right > 1 then support routine */
if (getSize (ltype) > 1 || getSize (rtype) > 1)
ic->supportRtn = 1;
}
IC_RESULT (ic) = newiTempOperand (resType, 1);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeDivision - gen intermediate code for division */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeDivision (operand * left, operand * right)
{
iCode *ic;
int p2 = 0;
sym_link *resType;
sym_link *rtype = operandType (right);
sym_link *retype = getSpec (rtype);
sym_link *ltype = operandType (left);
sym_link *letype = getSpec (ltype);
resType = usualBinaryConversions (&left, &right);
/* if the right is a literal & power of 2 */
/* then make it a right shift */
if (IS_LITERAL (retype) &&
!IS_FLOAT (letype) &&
(p2 = powof2 ((unsigned long)
floatFromVal (right->operand.valOperand)))) {
ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
}
else
{
ic = newiCode ('/', left, right); /* normal division */
/* if the size left or right > 1 then support routine */
if (getSize (ltype) > 1 || getSize (rtype) > 1)
ic->supportRtn = 1;
}
IC_RESULT (ic) = newiTempOperand (resType, 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeModulus - gen intermediate code for modulus */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeModulus (operand * left, operand * right)
{
iCode *ic;
sym_link *resType;
LRTYPE;
/* if they are both literal then we know the result */
if (IS_LITERAL (letype) && IS_LITERAL (retype))
return operandFromValue (valMod (left->operand.valOperand,
right->operand.valOperand));
resType = usualBinaryConversions (&left, &right);
/* now they are the same size */
ic = newiCode ('%', left, right);
/* if the size left or right > 1 then support routine */
if (getSize (ltype) > 1 || getSize (rtype) > 1)
ic->supportRtn = 1;
IC_RESULT (ic) = newiTempOperand (resType, 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodePtrPtrSubtract - subtracts pointer from pointer */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodePtrPtrSubtract (operand * left, operand * right)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
operand *result;
LRTYPE;
/* if they are both literals then */
if (IS_LITERAL (letype) && IS_LITERAL (retype))
{
result = operandFromValue (valMinus (left->operand.valOperand,
right->operand.valOperand));
goto subtractExit;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
ic = newiCode ('-', left, right);
IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
ADDTOCHAIN (ic);
subtractExit:
return geniCodeDivision (result,
operandFromLit (getSize (ltype->next)));
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeSubtract - generates code for subtraction */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeSubtract (operand * left, operand * right)
{
iCode *ic;
int isarray = 0;
sym_link *resType;
LRTYPE;
/* if they both pointers then */
if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
(IS_PTR (rtype) || IS_ARRAY (rtype)))
return geniCodePtrPtrSubtract (left, right);
/* if they are both literal then we know the result */
if (IS_LITERAL (letype) && IS_LITERAL (retype)
&& left->isLiteral && right->isLiteral)
return operandFromValue (valMinus (left->operand.valOperand,
right->operand.valOperand));
/* if left is an array or pointer */
if (IS_PTR (ltype) || IS_ARRAY (ltype))
{
isarray = left->isaddr;
right = geniCodeMultiply (right,
operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
}
else
{ /* make them the same size */
resType = usualBinaryConversions (&left, &right);
}
ic = newiCode ('-', left, right);
IC_RESULT (ic) = newiTempOperand (resType, 1);
IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if left or right is a float */
if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
ic->supportRtn = 1;
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeAdd - generates iCode for addition */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeAdd (operand * left, operand * right,int lvl)
{
iCode *ic;
sym_link *resType;
operand *size;
int isarray = 0;
LRTYPE;
/* if left is an array then array access */
if (IS_ARRAY (ltype))
return geniCodeArray (left, right,lvl);
/* if the right side is LITERAL zero */
/* return the left side */
if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
return left;
/* if left is literal zero return right */
if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
return right;
/* if left is an array or pointer then size */
if (IS_PTR (ltype))
{
isarray = left->isaddr;
// there is no need to multiply with 1
if (getSize(ltype->next)!=1) {
size = operandFromLit (getSize (ltype->next));
right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
}
resType = copyLinkChain (ltype);
}
else
{ /* make them the same size */
resType = usualBinaryConversions (&left, &right);
}
/* if they are both literals then we know */
if (IS_LITERAL (letype) && IS_LITERAL (retype)
&& left->isLiteral && right->isLiteral)
return operandFromValue (valPlus (valFromType (letype),
valFromType (retype)));
ic = newiCode ('+', left, right);
IC_RESULT (ic) = newiTempOperand (resType, 1);
IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
/* if left or right is a float then support
routine */
if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
ic->supportRtn = 1;
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* aggrToPtr - changes an aggregate to pointer to an aggregate */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
sym_link *
aggrToPtr (sym_link * type, bool force)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *etype;
sym_link *ptype;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (IS_PTR (type) && !force)
return type;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
etype = getSpec (type);
ptype = newLink ();
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
ptype->next = type;
/* if the output class is generic */
if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
DCL_PTR_CONST (ptype) = port->mem.code_ro;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if the variable was declared a constant */
/* then the pointer points to a constant */
if (IS_CONSTANT (etype))
DCL_PTR_CONST (ptype) = 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* the variable was volatile then pointer to volatile */
if (IS_VOLATILE (etype))
DCL_PTR_VOLATILE (ptype) = 1;
return ptype;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeArray2Ptr - array to pointer */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeArray2Ptr (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
sym_link *optype = operandType (op);
sym_link *opetype = getSpec (optype);
2015-01-10 16:25:07 +01:00
2015-01-10 16:25:09 +01:00
/* set the pointer depending on the storage class */
if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
DCL_PTR_CONST (optype) = port->mem.code_ro;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if the variable was declared a constant */
/* then the pointer points to a constant */
if (IS_CONSTANT (opetype))
DCL_PTR_CONST (optype) = 1;
/* the variable was volatile then pointer to volatile */
if (IS_VOLATILE (opetype))
DCL_PTR_VOLATILE (optype) = 1;
op->isaddr = 0;
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* geniCodeArray - array access */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeArray (operand * left, operand * right,int lvl)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
sym_link *ltype = operandType (left);
if (IS_PTR (ltype))
{
if (IS_PTR (ltype->next) && left->isaddr)
{
left = geniCodeRValue (left, FALSE);
}
return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
right = geniCodeMultiply (right,
operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* we can check for limits here */
if (isOperandLiteral (right) &&
IS_ARRAY (ltype) &&
DCL_ELEM (ltype) &&
(operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
{
werror (E_ARRAY_BOUND);
right = operandFromLit (0);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
ic = newiCode ('+', left, right);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
!IS_AGGREGATE (ltype->next) &&
!IS_PTR (ltype->next))
? ltype : ltype->next), 0);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeStruct - generates intermediate code for structres */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeStruct (operand * left, operand * right, bool islval)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
sym_link *type = operandType (left);
sym_link *etype = getSpec (type);
sym_link *retype;
symbol *element = getStructElement (SPEC_STRUCT (etype),
right->operand.symOperand);
/* add the offset */
ic = newiCode ('+', left, operandFromLit (element->offset));
IC_RESULT (ic) = newiTempOperand (element->type, 0);
/* preserve the storage & output class of the struct */
/* as well as the volatile attribute */
retype = getSpec (operandType (IC_RESULT (ic)));
SPEC_SCLS (retype) = SPEC_SCLS (etype);
SPEC_OCLS (retype) = SPEC_OCLS (etype);
SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
if (IS_PTR (element->type))
setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
ADDTOCHAIN (ic);
return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodePostInc - generate int code for Post increment */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodePostInc (operand * op)
{
iCode *ic;
operand *rOp;
sym_link *optype = operandType (op);
operand *result;
operand *rv = (IS_ITEMP (op) ?
geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
op);
sym_link *rvtype = operandType (rv);
int size = 0;
/* if this is not an address we have trouble */
if (!op->isaddr)
{
werror (E_LVALUE_REQUIRED, "++");
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
rOp = newiTempOperand (rvtype, 0);
OP_SYMBOL(rOp)->noSpilLoc = 1;
if (IS_ITEMP (rv))
OP_SYMBOL(rv)->noSpilLoc = 1;
geniCodeAssign (rOp, rv, 0);
size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
if (IS_FLOAT (rvtype))
ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
else
ic = newiCode ('+', rv, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
ADDTOCHAIN (ic);
geniCodeAssign (op, result, 0);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return rOp;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodePreInc - generate code for preIncrement */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodePreInc (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
sym_link *optype = operandType (op);
operand *rop = (IS_ITEMP (op) ?
geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
op);
sym_link *roptype = operandType (rop);
operand *result;
int size = 0;
if (!op->isaddr)
{
werror (E_LVALUE_REQUIRED, "++");
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
if (IS_FLOAT (roptype))
ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
else
ic = newiCode ('+', rop, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return geniCodeAssign (op, result, 0);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodePostDec - generates code for Post decrement */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodePostDec (operand * op)
{
iCode *ic;
operand *rOp;
sym_link *optype = operandType (op);
operand *result;
operand *rv = (IS_ITEMP (op) ?
geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
op);
sym_link *rvtype = operandType (rv);
int size = 0;
/* if this is not an address we have trouble */
if (!op->isaddr)
{
werror (E_LVALUE_REQUIRED, "--");
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
rOp = newiTempOperand (rvtype, 0);
OP_SYMBOL(rOp)->noSpilLoc = 1;
if (IS_ITEMP (rv))
OP_SYMBOL(rv)->noSpilLoc = 1;
geniCodeAssign (rOp, rv, 0);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
if (IS_FLOAT (rvtype))
ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
else
ic = newiCode ('-', rv, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
ADDTOCHAIN (ic);
geniCodeAssign (op, result, 0);
return rOp;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodePreDec - generate code for pre decrement */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodePreDec (operand * op)
{
iCode *ic;
sym_link *optype = operandType (op);
operand *rop = (IS_ITEMP (op) ?
geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
op);
sym_link *roptype = operandType (rop);
operand *result;
int size = 0;
if (!op->isaddr)
{
werror (E_LVALUE_REQUIRED, "--");
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
if (IS_FLOAT (roptype))
ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
else
ic = newiCode ('-', rop, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return geniCodeAssign (op, result, 0);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeBitwise - gen int code for bitWise operators */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeBitwise (operand * left, operand * right,
int oper, sym_link * resType)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
left = geniCodeCast (resType, left, TRUE);
right = geniCodeCast (resType, right, TRUE);
ic = newiCode (oper, left, right);
IC_RESULT (ic) = newiTempOperand (resType, 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeAddressOf - gens icode for '&' address of operator */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeAddressOf (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
sym_link *p;
sym_link *optype = operandType (op);
sym_link *opetype = getSpec (optype);
/* lvalue check already done in decorateType */
/* this must be a lvalue */
2015-01-10 16:25:07 +01:00
/* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2015-01-10 16:25:09 +01:00
/* werror (E_LVALUE_REQUIRED,"&"); */
/* return op; */
2015-01-10 16:25:07 +01:00
/* } */
2015-01-10 16:25:09 +01:00
p = newLink ();
p->class = DECLARATOR;
/* set the pointer depending on the storage class */
if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
DCL_PTR_CONST (p) = port->mem.code_ro;
/* make sure we preserve the const & volatile */
if (IS_CONSTANT (opetype))
DCL_PTR_CONST (p) = 1;
if (IS_VOLATILE (opetype))
DCL_PTR_VOLATILE (p) = 1;
p->next = copyLinkChain (optype);
/* if already a temp */
if (IS_ITEMP (op))
{
setOperandType (op, p);
op->isaddr = 0;
return op;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* other wise make this of the type coming in */
ic = newiCode (ADDRESS_OF, op, NULL);
IC_RESULT (ic) = newiTempOperand (p, 1);
IC_RESULT (ic)->isaddr = 0;
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* setOClass - sets the output class depending on the pointer type */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
setOClass (sym_link * ptr, sym_link * spec)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
switch (DCL_TYPE (ptr))
{
2015-01-10 16:25:06 +01:00
case POINTER:
2015-01-10 16:25:09 +01:00
SPEC_OCLS (spec) = data;
break;
2015-01-10 16:25:06 +01:00
case GPOINTER:
2015-01-10 16:25:09 +01:00
SPEC_OCLS (spec) = generic;
break;
2015-01-10 16:25:06 +01:00
case FPOINTER:
2015-01-10 16:25:09 +01:00
SPEC_OCLS (spec) = xdata;
break;
2015-01-10 16:25:06 +01:00
case CPOINTER:
2015-01-10 16:25:09 +01:00
SPEC_OCLS (spec) = code;
break;
2015-01-10 16:25:06 +01:00
case IPOINTER:
2015-01-10 16:25:09 +01:00
SPEC_OCLS (spec) = idata;
break;
2015-01-10 16:25:06 +01:00
case PPOINTER:
2015-01-10 16:25:09 +01:00
SPEC_OCLS (spec) = xstack;
break;
2015-01-10 16:25:07 +01:00
case EEPPOINTER:
2015-01-10 16:25:09 +01:00
SPEC_OCLS (spec) = eeprom;
break;
2015-01-10 16:25:07 +01:00
default:
2015-01-10 16:25:09 +01:00
break;
2015-01-10 16:25:07 +01:00
2015-01-10 16:25:06 +01:00
}
}
/*-----------------------------------------------------------------*/
/* geniCodeDerefPtr - dereference pointer with '*' */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeDerefPtr (operand * op,int lvl)
{
sym_link *rtype, *retype;
sym_link *optype = operandType (op);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if this is a pointer then generate the rvalue */
if (IS_PTR (optype))
{
if (IS_TRUE_SYMOP (op))
{
op->isaddr = 1;
op = geniCodeRValue (op, TRUE);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
op = geniCodeRValue (op, TRUE);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* now get rid of the pointer part */
if (isLvaluereq(lvl) && IS_ITEMP (op))
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
retype = getSpec (rtype = copyLinkChain (optype));
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
else
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
retype = getSpec (rtype = copyLinkChain (optype->next));
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if this is a pointer then outputclass needs 2b updated */
if (IS_PTR (optype))
setOClass (optype, retype);
op->isGptr = IS_GENPTR (optype);
/* if the pointer was declared as a constant */
/* then we cannot allow assignment to the derefed */
if (IS_PTR_CONST (optype))
SPEC_CONST (retype) = 1;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
op->isaddr = (IS_PTR (rtype) ||
IS_STRUCT (rtype) ||
IS_INT (rtype) ||
IS_CHAR (rtype) ||
IS_FLOAT (rtype));
2015-01-10 16:25:07 +01:00
2015-01-10 16:25:09 +01:00
if (!isLvaluereq(lvl))
op = geniCodeRValue (op, TRUE);
setOperandType (op, rtype);
return op;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeUnaryMinus - does a unary minus of the operand */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeUnaryMinus (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
sym_link *optype = operandType (op);
if (IS_LITERAL (optype))
return operandFromLit (-floatFromVal (op->operand.valOperand));
ic = newiCode (UNARYMINUS, op, NULL);
IC_RESULT (ic) = newiTempOperand (optype, 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeLeftShift - gen i code for left shift */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeLeftShift (operand * left, operand * right)
{
iCode *ic;
ic = newiCode (LEFT_OP, left, right);
IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeRightShift - gen i code for right shift */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeRightShift (operand * left, operand * right)
{
iCode *ic;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
ic = newiCode (RIGHT_OP, left, right);
IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* geniCodeLogic- logic code */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeLogic (operand * left, operand * right, int op)
{
iCode *ic;
sym_link *ctype;
sym_link *rtype = operandType (right);
sym_link *ltype = operandType (left);
/* left is integral type and right is literal then
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
{
checkConstantRange(ltype,
OP_VALUE(right), "compare operation", 1);
}
ctype = usualBinaryConversions (&left, &right);
ic = newiCode (op, left, right);
IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if comparing float
and not a '==' || '!=' || '&&' || '||' (these
will be inlined */
if (IS_FLOAT(ctype) &&
op != EQ_OP &&
op != NE_OP &&
op != AND_OP &&
op != OR_OP)
ic->supportRtn = 1;
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeUnary - for a a generic unary operation */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeUnary (operand * op, int oper)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic = newiCode (oper, op, NULL);
IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeConditional - geniCode for '?' ':' operation */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeConditional (ast * tree,int lvl)
{
iCode *ic;
symbol *falseLabel = newiTempLabel (NULL);
symbol *exitLabel = newiTempLabel (NULL);
operand *cond = ast2iCode (tree->left,lvl+1);
operand *true, *false, *result;
ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
NULL, falseLabel);
ADDTOCHAIN (ic);
true = ast2iCode (tree->right->left,lvl+1);
/* move the value to a new Operand */
result = newiTempOperand (operandType (true), 0);
geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
/* generate an unconditional goto */
geniCodeGoto (exitLabel);
/* now for the right side */
geniCodeLabel (falseLabel);
false = ast2iCode (tree->right->right,lvl+1);
geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
/* create the exit label */
geniCodeLabel (exitLabel);
return result;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeAssign - generate code for assignment */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeAssign (operand * left, operand * right, int nosupdate)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
sym_link *ltype = operandType (left);
sym_link *rtype = operandType (right);
if (!left->isaddr && !IS_ITEMP (left))
{
werror (E_LVALUE_REQUIRED, "assignment");
return left;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* left is integral type and right is literal then
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
{
checkConstantRange(ltype,
OP_VALUE(right), "= operation", 0);
}
/* if the left & right type don't exactly match */
/* if pointer set then make sure the check is
done with the type & not the pointer */
/* then cast rights type to left */
/* first check the type for pointer assignement */
if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
compareType (ltype, rtype) <= 0)
{
if (compareType (ltype->next, rtype) < 0)
right = geniCodeCast (ltype->next, right, TRUE);
}
else if (compareType (ltype, rtype) < 0)
right = geniCodeCast (ltype, right, TRUE);
/* if left is a true symbol & ! volatile
create an assignment to temporary for
the right & then assign this temporary
to the symbol this is SSA . isn't it simple
and folks have published mountains of paper on it */
if (IS_TRUE_SYMOP (left) &&
!isOperandVolatile (left, FALSE) &&
isOperandGlobal (left))
{
symbol *sym = NULL;
if (IS_TRUE_SYMOP (right))
sym = OP_SYMBOL (right);
ic = newiCode ('=', NULL, right);
IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
SPIL_LOC (right) = sym;
ADDTOCHAIN (ic);
}
ic = newiCode ('=', NULL, right);
IC_RESULT (ic) = left;
ADDTOCHAIN (ic);
/* if left isgptr flag is set then support
routine will be required */
if (left->isGptr)
ic->supportRtn = 1;
ic->nosupdate = nosupdate;
return left;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeSEParms - generate code for side effecting fcalls */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
static void
geniCodeSEParms (ast * parms,int lvl)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (!parms)
return;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (parms->type == EX_OP && parms->opval.op == PARAM)
{
geniCodeSEParms (parms->left,lvl);
geniCodeSEParms (parms->right,lvl);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* hack don't like this but too lazy to think of
something better */
if (IS_ADDRESS_OF_OP (parms))
parms->left->lvalue = 1;
if (IS_CAST_OP (parms) &&
IS_PTR (parms->ftype) &&
IS_ADDRESS_OF_OP (parms->right))
parms->right->left->lvalue = 1;
parms->opval.oprnd =
geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
parms->type = EX_OPERAND;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeParms - generates parameters */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
value *
geniCodeParms (ast * parms, value *argVals, int *stack,
sym_link * fetype, symbol * func,int lvl)
{
iCode *ic;
operand *pval;
if (!parms)
return argVals;
if (argVals==NULL) {
// first argument
argVals=FUNC_ARGS(func->type);
}
/* if this is a param node then do the left & right */
if (parms->type == EX_OP && parms->opval.op == PARAM)
{
argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
return argVals;
}
/* get the parameter value */
if (parms->type == EX_OPERAND)
pval = parms->opval.oprnd;
else
{
/* maybe this else should go away ?? */
/* hack don't like this but too lazy to think of
something better */
if (IS_ADDRESS_OF_OP (parms))
parms->left->lvalue = 1;
if (IS_CAST_OP (parms) &&
IS_PTR (parms->ftype) &&
IS_ADDRESS_OF_OP (parms->right))
parms->right->left->lvalue = 1;
pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
}
/* if register parm then make it a send */
if (IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type))
{
ic = newiCode (SEND, pval, NULL);
ADDTOCHAIN (ic);
}
else
{
/* now decide whether to push or assign */
if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
{
/* assign */
operand *top = operandFromSymbol (argVals->sym);
geniCodeAssign (top, pval, 1);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
sym_link *p = operandType (pval);
/* push */
ic = newiCode (IPUSH, pval, NULL);
ic->parmPush = 1;
/* update the stack adjustment */
*stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
argVals=argVals->next;
return argVals;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeCall - generates temp code for calling */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
geniCodeCall (operand * left, ast * parms,int lvl)
{
iCode *ic;
operand *result;
sym_link *type, *etype;
int stack = 0;
if (!IS_FUNC(OP_SYMBOL(left)->type) &&
!IS_CODEPTR(OP_SYMBOL(left)->type)) {
werror (E_FUNCTION_EXPECTED);
return NULL;
}
/* take care of parameters with side-effecting
function calls in them, this is required to take care
of overlaying function parameters */
geniCodeSEParms (parms,lvl);
/* first the parameters */
geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
/* now call : if symbol then pcall */
if (IS_OP_POINTER (left) || IS_ITEMP(left))
ic = newiCode (PCALL, left, NULL);
else
ic = newiCode (CALL, left, NULL);
IC_ARGS (ic) = FUNC_ARGS(left->operand.symOperand->type);
type = copyLinkChain (operandType (left)->next);
etype = getSpec (type);
SPEC_EXTR (etype) = 0;
IC_RESULT (ic) = result = newiTempOperand (type, 1);
ADDTOCHAIN (ic);
/* stack adjustment after call */
ic->parmBytes = stack;
return result;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeReceive - generate intermediate code for "receive" */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
static void
geniCodeReceive (value * args)
{
/* for all arguments that are passed in registers */
while (args)
{
if (IS_REGPARM (args->etype))
{
operand *opr = operandFromValue (args);
operand *opl;
symbol *sym = OP_SYMBOL (opr);
iCode *ic;
/* we will use it after all optimizations
and before liveRange calculation */
if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
{
if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
options.stackAuto == 0 &&
/* !TARGET_IS_DS390) */
(!(options.model == MODEL_FLAT24)) )
{
}
else
{
opl = newiTempOperand (args->type, 0);
sym->reqv = opl;
sym->reqv->key = sym->key;
OP_SYMBOL (sym->reqv)->key = sym->key;
OP_SYMBOL (sym->reqv)->isreqv = 1;
OP_SYMBOL (sym->reqv)->islocal = 0;
SPIL_LOC (sym->reqv) = sym;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
ic = newiCode (RECEIVE, NULL, NULL);
currFunc->recvSize = getSize (sym->etype);
IC_RESULT (ic) = opr;
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
args = args->next;
2015-01-10 16:25:06 +01:00
}
}
/*-----------------------------------------------------------------*/
/* geniCodeFunctionBody - create the function body */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
geniCodeFunctionBody (ast * tree,int lvl)
{
iCode *ic;
operand *func;
sym_link *fetype;
int savelineno;
/* reset the auto generation */
/* numbers */
iTempNum = 0;
iTempLblNum = 0;
operandKey = 0;
iCodeKey = 0;
func = ast2iCode (tree->left,lvl+1);
fetype = getSpec (operandType (func));
savelineno = lineno;
lineno = OP_SYMBOL (func)->lineDef;
/* create an entry label */
geniCodeLabel (entryLabel);
lineno = savelineno;
/* create a proc icode */
ic = newiCode (FUNCTION, func, NULL);
/* if the function has parmas then */
/* save the parameters information */
ic->argLabel.args = tree->values.args;
ic->lineno = OP_SYMBOL (func)->lineDef;
ADDTOCHAIN (ic);
/* for all parameters that are passed
on registers add a "receive" */
geniCodeReceive (tree->values.args);
/* generate code for the body */
ast2iCode (tree->right,lvl+1);
/* create a label for return */
geniCodeLabel (returnLabel);
/* now generate the end proc */
ic = newiCode (ENDFUNCTION, func, NULL);
ADDTOCHAIN (ic);
return;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeReturn - gen icode for 'return' statement */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
geniCodeReturn (operand * op)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
/* if the operand is present force an rvalue */
if (op)
op = geniCodeRValue (op, FALSE);
ic = newiCode (RETURN, op, NULL);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeIfx - generates code for extended if statement */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
geniCodeIfx (ast * tree,int lvl)
{
iCode *ic;
operand *condition = ast2iCode (tree->left,lvl+1);
sym_link *cetype;
/* if condition is null then exit */
if (!condition)
goto exit;
else
condition = geniCodeRValue (condition, FALSE);
cetype = getSpec (operandType (condition));
/* if the condition is a literal */
if (IS_LITERAL (cetype))
{
if (floatFromVal (condition->operand.valOperand))
{
if (tree->trueLabel)
geniCodeGoto (tree->trueLabel);
else
assert (0);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
if (tree->falseLabel)
geniCodeGoto (tree->falseLabel);
else
assert (0);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
goto exit;
}
if (tree->trueLabel)
{
ic = newiCodeCondition (condition,
tree->trueLabel,
NULL);
ADDTOCHAIN (ic);
if (tree->falseLabel)
geniCodeGoto (tree->falseLabel);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
{
ic = newiCodeCondition (condition,
NULL,
tree->falseLabel);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
exit:
ast2iCode (tree->right,lvl+1);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeJumpTable - tries to create a jump table for switch */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
int min = 0, max = 0, t, cnt = 0;
value *vch;
iCode *ic;
operand *boundary;
symbol *falseLabel;
set *labels = NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!tree || !caseVals)
return 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* the criteria for creating a jump table is */
/* all integer numbers between the maximum & minimum must */
/* be present , the maximum value should not exceed 255 */
min = max = (int) floatFromVal (vch = caseVals);
sprintf (buffer, "_case_%d_%d",
tree->values.switchVals.swNum,
min);
addSet (&labels, newiTempLabel (buffer));
/* if there is only one case value then no need */
if (!(vch = vch->next))
return 0;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
while (vch)
{
if (((t = (int) floatFromVal (vch)) - max) != 1)
2015-01-10 16:25:06 +01:00
return 0;
2015-01-10 16:25:09 +01:00
sprintf (buffer, "_case_%d_%d",
tree->values.switchVals.swNum,
t);
addSet (&labels, newiTempLabel (buffer));
max = t;
cnt++;
vch = vch->next;
}
/* if the number of case statements <= 2 then */
/* it is not economical to create the jump table */
/* since two compares are needed for boundary conditions */
if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
return 0;
if (tree->values.switchVals.swDefault)
sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
else
sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
falseLabel = newiTempLabel (buffer);
/* so we can create a jumptable */
/* first we rule out the boundary conditions */
/* if only optimization says so */
if (!optimize.noJTabBoundary)
{
sym_link *cetype = getSpec (operandType (cond));
/* no need to check the lower bound if
the condition is unsigned & minimum value is zero */
if (!(min == 0 && SPEC_USIGN (cetype)))
{
boundary = geniCodeLogic (cond, operandFromLit (min), '<');
ic = newiCodeCondition (boundary, falseLabel, NULL);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* now for upper bounds */
boundary = geniCodeLogic (cond, operandFromLit (max), '>');
ic = newiCodeCondition (boundary, falseLabel, NULL);
ADDTOCHAIN (ic);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if the min is not zero then we no make it zero */
if (min)
{
cond = geniCodeSubtract (cond, operandFromLit (min));
setOperandType (cond, UCHARTYPE);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* now create the jumptable */
ic = newiCode (JUMPTABLE, NULL, NULL);
IC_JTCOND (ic) = cond;
IC_JTLABELS (ic) = labels;
ADDTOCHAIN (ic);
return 1;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* geniCodeSwitch - changes a switch to a if statement */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
geniCodeSwitch (ast * tree,int lvl)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
value *caseVals = tree->values.switchVals.swVals;
symbol *trueLabel, *falseLabel;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if we can make this a jump table */
if (geniCodeJumpTable (cond, caseVals, tree))
goto jumpTable; /* no need for the comparison */
/* for the cases defined do */
while (caseVals)
{
operand *compare = geniCodeLogic (cond,
operandFromValue (caseVals),
EQ_OP);
sprintf (buffer, "_case_%d_%d",
tree->values.switchVals.swNum,
(int) floatFromVal (caseVals));
trueLabel = newiTempLabel (buffer);
ic = newiCodeCondition (compare, trueLabel, NULL);
ADDTOCHAIN (ic);
caseVals = caseVals->next;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* if default is present then goto break else break */
if (tree->values.switchVals.swDefault)
sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
else
sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
falseLabel = newiTempLabel (buffer);
geniCodeGoto (falseLabel);
jumpTable:
ast2iCode (tree->right,lvl+1);
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* geniCodeInline - intermediate code for inline assembler */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
static void
geniCodeInline (ast * tree)
{
iCode *ic;
ic = newiCode (INLINEASM, NULL, NULL);
IC_INLINE (ic) = tree->values.inlineasm;
ADDTOCHAIN (ic);
}
/*-----------------------------------------------------------------*/
/* geniCodeArrayInit - intermediate code for array initializer */
/*-----------------------------------------------------------------*/
static void
geniCodeArrayInit (ast * tree, operand *array)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *ic;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!getenv("TRY_THE_NEW_INITIALIZER")) {
ic = newiCode (ARRAYINIT, array, NULL);
IC_ARRAYILIST (ic) = tree->values.constlist;
} else {
operand *left=newOperand(), *right=newOperand();
left->type=right->type=SYMBOL;
OP_SYMBOL(left)=AST_SYMBOL(tree->left);
OP_SYMBOL(right)=AST_SYMBOL(tree->right);
ic = newiCode (ARRAYINIT, left, right);
}
ADDTOCHAIN (ic);
}
/*-----------------------------------------------------------------*/
/* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
/* particular case. Ie : assigning or dereferencing array or ptr */
/*-----------------------------------------------------------------*/
set * lvaluereqSet = NULL;
typedef struct lvalItem
{
int req;
int lvl;
}
lvalItem;
/*-----------------------------------------------------------------*/
/* addLvaluereq - add a flag for lvalreq for current ast level */
/*-----------------------------------------------------------------*/
void addLvaluereq(int lvl)
{
lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
lpItem->req=1;
lpItem->lvl=lvl;
addSetHead(&lvaluereqSet,lpItem);
}
/*-----------------------------------------------------------------*/
/* delLvaluereq - del a flag for lvalreq for current ast level */
/*-----------------------------------------------------------------*/
void delLvaluereq()
{
lvalItem * lpItem;
lpItem = getSet(&lvaluereqSet);
if(lpItem) Safe_free(lpItem);
}
/*-----------------------------------------------------------------*/
/* clearLvaluereq - clear lvalreq flag */
/*-----------------------------------------------------------------*/
void clearLvaluereq()
{
lvalItem * lpItem;
lpItem = peekSet(lvaluereqSet);
if(lpItem) lpItem->req = 0;
}
/*-----------------------------------------------------------------*/
/* getLvaluereq - get the last lvalreq level */
/*-----------------------------------------------------------------*/
int getLvaluereqLvl()
{
lvalItem * lpItem;
lpItem = peekSet(lvaluereqSet);
if(lpItem) return lpItem->lvl;
return 0;
}
/*-----------------------------------------------------------------*/
/* isLvaluereq - is lvalreq valid for this level ? */
/*-----------------------------------------------------------------*/
int isLvaluereq(int lvl)
{
lvalItem * lpItem;
lpItem = peekSet(lvaluereqSet);
if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* ast2iCode - creates an icodeList from an ast */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
operand *
ast2iCode (ast * tree,int lvl)
{
operand *left = NULL;
operand *right = NULL;
if (!tree)
return NULL;
/* set the global variables for filename & line number */
if (tree->filename)
filename = tree->filename;
if (tree->lineno)
lineno = tree->lineno;
if (tree->block)
block = tree->block;
if (tree->level)
scopeLevel = tree->level;
if (tree->type == EX_VALUE)
return operandFromValue (tree->opval.val);
if (tree->type == EX_LINK)
return operandFromLink (tree->opval.lnk);
/* if we find a nullop */
if (tree->type == EX_OP &&
(tree->opval.op == NULLOP ||
tree->opval.op == BLOCK))
{
ast2iCode (tree->left,lvl+1);
ast2iCode (tree->right,lvl+1);
return NULL;
}
/* special cases for not evaluating */
if (tree->opval.op != ':' &&
tree->opval.op != '?' &&
tree->opval.op != CALL &&
tree->opval.op != IFX &&
tree->opval.op != LABEL &&
tree->opval.op != GOTO &&
tree->opval.op != SWITCH &&
tree->opval.op != FUNCTION &&
tree->opval.op != INLINEASM)
{
if (IS_ASSIGN_OP (tree->opval.op) ||
IS_DEREF_OP (tree) ||
(tree->opval.op == '&' && !tree->right) ||
tree->opval.op == PTR_OP)
{
addLvaluereq(lvl);
if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
(IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
clearLvaluereq();
left = operandFromAst (tree->left,lvl);
delLvaluereq();
if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
left = geniCodeRValue (left, TRUE);
}
else
{
left = operandFromAst (tree->left,lvl);
}
if (tree->opval.op == INC_OP ||
tree->opval.op == DEC_OP)
{
addLvaluereq(lvl);
right = operandFromAst (tree->right,lvl);
delLvaluereq();
}
else
{
right = operandFromAst (tree->right,lvl);
}
}
/* now depending on the type of operand */
/* this will be a biggy */
switch (tree->opval.op)
{
case '[': /* array operation */
{
//sym_link *ltype = operandType (left);
//left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
left = geniCodeRValue (left, FALSE);
right = geniCodeRValue (right, TRUE);
}
return geniCodeArray (left, right,lvl);
case '.': /* structure dereference */
if (IS_PTR (operandType (left)))
left = geniCodeRValue (left, TRUE);
else
left = geniCodeRValue (left, FALSE);
return geniCodeStruct (left, right, tree->lvalue);
case PTR_OP: /* structure pointer dereference */
{
sym_link *pType;
pType = operandType (left);
left = geniCodeRValue (left, TRUE);
setOClass (pType, getSpec (operandType (left)));
}
return geniCodeStruct (left, right, tree->lvalue);
case INC_OP: /* increment operator */
if (left)
return geniCodePostInc (left);
else
return geniCodePreInc (right);
case DEC_OP: /* decrement operator */
if (left)
return geniCodePostDec (left);
else
return geniCodePreDec (right);
case '&': /* bitwise and or address of operator */
if (right)
{ /* this is a bitwise operator */
left = geniCodeRValue (left, FALSE);
right = geniCodeRValue (right, FALSE);
return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
else
return geniCodeAddressOf (left);
case '|': /* bitwise or & xor */
2015-01-10 16:25:06 +01:00
case '^':
2015-01-10 16:25:09 +01:00
return geniCodeBitwise (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),
tree->opval.op,
tree->ftype);
2015-01-10 16:25:06 +01:00
case '/':
2015-01-10 16:25:09 +01:00
return geniCodeDivision (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE));
case '%':
return geniCodeModulus (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE));
2015-01-10 16:25:06 +01:00
case '*':
2015-01-10 16:25:09 +01:00
if (right)
return geniCodeMultiply (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
else
return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
case '-':
if (right)
return geniCodeSubtract (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE));
else
return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
case '+':
if (right)
return geniCodeAdd (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),lvl);
else
return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
2015-01-10 16:25:06 +01:00
case LEFT_OP:
2015-01-10 16:25:09 +01:00
return geniCodeLeftShift (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE));
2015-01-10 16:25:06 +01:00
case RIGHT_OP:
2015-01-10 16:25:09 +01:00
return geniCodeRightShift (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE));
2015-01-10 16:25:06 +01:00
case CAST:
2015-01-10 16:25:09 +01:00
return geniCodeCast (operandType (left),
geniCodeRValue (right, FALSE), FALSE);
case '~':
case '!':
2015-01-10 16:25:06 +01:00
case RRC:
2015-01-10 16:25:09 +01:00
case RLC:
return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
2015-01-10 16:25:06 +01:00
case GETHBIT:
2015-01-10 16:25:09 +01:00
{
operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
setOperandType (op, UCHARTYPE);
return op;
}
case '>':
case '<':
2015-01-10 16:25:06 +01:00
case LE_OP:
case GE_OP:
case EQ_OP:
case NE_OP:
case AND_OP:
case OR_OP:
2015-01-10 16:25:09 +01:00
return geniCodeLogic (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),
tree->opval.op);
case '?':
return geniCodeConditional (tree,lvl);
2015-01-10 16:25:06 +01:00
case SIZEOF:
2015-01-10 16:25:09 +01:00
return operandFromLit (getSize (tree->right->ftype));
case '=':
{
sym_link *rtype = operandType (right);
sym_link *ltype = operandType (left);
if (IS_PTR (rtype) && IS_ITEMP (right)
&& right->isaddr && compareType (rtype->next, ltype) == 1)
right = geniCodeRValue (right, TRUE);
else
right = geniCodeRValue (right, FALSE);
geniCodeAssign (left, right, 0);
return right;
}
2015-01-10 16:25:06 +01:00
case MUL_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE),FALSE), 0);
2015-01-10 16:25:06 +01:00
case DIV_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeDivision (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE)), 0);
2015-01-10 16:25:06 +01:00
case MOD_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeModulus (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE)), 0);
case ADD_ASSIGN:
{
sym_link *rtype = operandType (right);
sym_link *ltype = operandType (left);
if (IS_PTR (rtype) && IS_ITEMP (right)
&& right->isaddr && compareType (rtype->next, ltype) == 1)
right = geniCodeRValue (right, TRUE);
else
right = geniCodeRValue (right, FALSE);
return geniCodeAssign (left,
geniCodeAdd (geniCodeRValue (operandFromOperand (left),
FALSE),
right,lvl), 0);
}
2015-01-10 16:25:06 +01:00
case SUB_ASSIGN:
2015-01-10 16:25:09 +01:00
{
sym_link *rtype = operandType (right);
sym_link *ltype = operandType (left);
if (IS_PTR (rtype) && IS_ITEMP (right)
&& right->isaddr && compareType (rtype->next, ltype) == 1)
{
right = geniCodeRValue (right, TRUE);
}
else
{
right = geniCodeRValue (right, FALSE);
}
return
geniCodeAssign (left,
geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
FALSE),
right), 0);
}
2015-01-10 16:25:06 +01:00
case LEFT_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
,FALSE),
geniCodeRValue (right, FALSE)), 0);
2015-01-10 16:25:06 +01:00
case RIGHT_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
,FALSE),
geniCodeRValue (right, FALSE)), 0);
2015-01-10 16:25:06 +01:00
case AND_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE),
BITWISEAND,
operandType (left)), 0);
2015-01-10 16:25:06 +01:00
case XOR_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE),
'^',
operandType (left)), 0);
2015-01-10 16:25:06 +01:00
case OR_ASSIGN:
2015-01-10 16:25:09 +01:00
return
geniCodeAssign (left,
geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
,FALSE),
geniCodeRValue (right, FALSE),
'|',
operandType (left)), 0);
case ',':
return geniCodeRValue (right, FALSE);
2015-01-10 16:25:06 +01:00
case CALL:
2015-01-10 16:25:09 +01:00
return geniCodeCall (ast2iCode (tree->left,lvl+1),
tree->right,lvl);
2015-01-10 16:25:06 +01:00
case LABEL:
2015-01-10 16:25:09 +01:00
geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
return ast2iCode (tree->right,lvl+1);
2015-01-10 16:25:06 +01:00
case GOTO:
2015-01-10 16:25:09 +01:00
geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
return ast2iCode (tree->right,lvl+1);
2015-01-10 16:25:06 +01:00
case FUNCTION:
2015-01-10 16:25:09 +01:00
geniCodeFunctionBody (tree,lvl);
return NULL;
2015-01-10 16:25:06 +01:00
case RETURN:
2015-01-10 16:25:09 +01:00
geniCodeReturn (right);
return NULL;
2015-01-10 16:25:06 +01:00
case IFX:
2015-01-10 16:25:09 +01:00
geniCodeIfx (tree,lvl);
return NULL;
2015-01-10 16:25:06 +01:00
case SWITCH:
2015-01-10 16:25:09 +01:00
geniCodeSwitch (tree,lvl);
return NULL;
2015-01-10 16:25:06 +01:00
case INLINEASM:
2015-01-10 16:25:09 +01:00
geniCodeInline (tree);
return NULL;
case ARRAYINIT:
geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
return NULL;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return NULL;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* reverseICChain - gets from the list and creates a linkedlist */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
iCode *
reverseiCChain ()
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
iCode *loop = NULL;
iCode *prev = NULL;
while ((loop = getSet (&iCodeChain)))
{
loop->next = prev;
if (prev)
prev->prev = loop;
prev = loop;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return prev;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* iCodeFromAst - given an ast will convert it to iCode */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
iCode *
iCodeFromAst (ast * tree)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
returnLabel = newiTempLabel ("_return");
entryLabel = newiTempLabel ("_entry");
ast2iCode (tree,0);
return reverseiCChain ();
2015-01-10 16:25:06 +01:00
}