#include "common.h"
#include "newalloc.h"
+#include "math.h"
/*-----------------------------------------------------------------*/
/* global variables */
int lineno;
int block;
int scopeLevel;
-int lvaluereq;
symbol *returnLabel; /* function return label */
symbol *entryLabel; /* function entry label */
+
/*-----------------------------------------------------------------*/
/* forward definition of some functions */
operand *geniCodeDivision (operand *, operand *);
operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *);
+operand *geniCodeArray (operand *, operand *,int);
operand *geniCodeArray2Ptr (operand *);
operand *geniCodeRValue (operand *, bool);
-operand *geniCodeDerefPtr (operand *);
+operand *geniCodeDerefPtr (operand *,int);
+int isLvaluereq(int lvl);
#define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
/* forward definition of ic print functions */
{IFX, "if", picIfx, NULL},
{INLINEASM, "", picInline, NULL},
{RECEIVE, "recv", picReceive, NULL},
- {SEND, "send", picGenericOne, NULL}
+ {SEND, "send", picGenericOne, NULL},
+ {ARRAYINIT, "arrayInit", picGenericOne, NULL},
};
+/*-----------------------------------------------------------------*/
+/* 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;
+ 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 0 // temporary disabled, leaving the warning as a reminder
+ if (warnings) {
+ SNPRINTF (message, sizeof(message), "for %s %s in %s",
+ SPEC_USIGN(ltype) ? "unsigned" : "signed",
+ nounName(ltype), msg);
+ werror (W_CONST_RANGE, message);
+
+ if (pedantic>1)
+ fatalError++;
+ }
+#endif
+}
/*-----------------------------------------------------------------*/
/* operandName - returns the name of the operand */
case SYMBOL:
#define REGA 1
#ifdef REGA
- fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
+ fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d ru%d dp%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->isaddr, OP_SYMBOL (op)->isreqv,
+ OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
+ OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
);
{
fprintf (file, "{");
if (!IC_RESULT (ic) && !IC_LEFT (ic))
fprintf (of, s);
+ if (ic->op == SEND || ic->op == RECEIVE) {
+ fprintf(of,"{argreg = %d}",ic->argreg);
+ }
fprintf (of, "\n");
}
{
operand *op;
- op = Safe_calloc (1, sizeof (operand));
+ op = Safe_alloc ( sizeof (operand));
op->key = 0;
return op;
{
iCode *ic;
- ic = Safe_calloc (1, sizeof (iCode));
+ ic = Safe_alloc ( sizeof (iCode));
ic->lineno = lineno;
ic->filename = filename;
{
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 = newiCode (op, NULL, NULL);
ic->op = op;
- ic->argLabel.label = label;
+ ic->label = label;
IC_LEFT (ic) = NULL;
IC_RIGHT (ic) = NULL;
IC_RESULT (ic) = NULL;
symbol *itmp;
if (s)
- sprintf (buffer, "%s", s);
+ {
+ SNPRINTF (buffer, sizeof(buffer), "%s", s);
+ }
else
- sprintf (buffer, "iTemp%d", iTempNum++);
+ {
+ SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
+ }
+
itmp = newSymbol (buffer, 1);
- strcpy (itmp->rname, itmp->name);
+ strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
itmp->isitmp = 1;
return itmp;
return itmplbl;
if (s)
- itmplbl = newSymbol (s, 1);
+ {
+ itmplbl = newSymbol (s, 1);
+ }
else
{
- sprintf (buffer, "iTempLbl%d", iTempLblNum++);
+ SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
itmplbl = newSymbol (buffer, 1);
}
itmplbl->isitmp = 1;
itmplbl->islbl = 1;
itmplbl->key = labelKey++;
- addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
+ addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
return itmplbl;
}
{
symbol *itmplbl;
- sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
+ SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
itmplbl = newSymbol (buffer, 1);
itmplbl->isitmp = 1;
itmplbl->islbl = 1;
itmplbl->key = labelKey++;
- addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
+ addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
return itmplbl;
}
case PCALL:
IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
- IC_ARGS (nic) = IC_ARGS (ic);
break;
case INLINEASM:
IC_INLINE (nic) = IC_INLINE (ic);
break;
+ case ARRAYINIT:
+ IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
+ break;
+
default:
IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
{
value *tval = args;
+ wassert (IS_SYMOP(op));
+
while (tval)
{
if (tval->sym &&
if (IS_ITEMP (op))
return 0;
- if (op->type == SYMBOL &&
+ if (IS_SYMOP(op) &&
(op->operand.symOperand->level == 0 ||
IS_STATIC (op->operand.symOperand->etype) ||
IS_EXTERN (op->operand.symOperand->etype))
return 0;
}
+
/*-----------------------------------------------------------------*/
/* isOperandInFarSpace - will return true if operand is in farSpace */
/*-----------------------------------------------------------------*/
return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
}
+/*------------------------------------------------------------------*/
+/* isOperandInDirSpace - will return true if operand is in dirSpace */
+/*------------------------------------------------------------------*/
+bool
+isOperandInDirSpace (operand * op)
+{
+ sym_link *etype;
+
+ if (!op)
+ return FALSE;
+
+ if (!IS_SYMOP (op))
+ return FALSE;
+
+ if (!IS_TRUE_SYMOP (op))
+ {
+ if (SPIL_LOC (op))
+ etype = SPIL_LOC (op)->etype;
+ else
+ return FALSE;
+ }
+ else
+ {
+ etype = getSpec (operandType (op));
+ }
+ return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
+/*--------------------------------------------------------------------*/
+/* isOperandInCodeSpace - will return true if operand is in codeSpace */
+/*--------------------------------------------------------------------*/
+bool
+isOperandInCodeSpace (operand * op)
+{
+ sym_link *etype;
+
+ if (!op)
+ return FALSE;
+
+ if (!IS_SYMOP (op))
+ return FALSE;
+
+ etype = getSpec (operandType (op));
+
+ if (!IS_TRUE_SYMOP (op))
+ {
+ if (SPIL_LOC (op))
+ etype = SPIL_LOC (op)->etype;
+ else
+ return FALSE;
+ }
+ else
+ {
+ etype = getSpec (operandType (op));
+ }
+ return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
/*-----------------------------------------------------------------*/
/* isOperandOnStack - will return true if operand is on stack */
/*-----------------------------------------------------------------*/
return FALSE;
etype = getSpec (operandType (op));
+ if (IN_STACK (etype) ||
+ OP_SYMBOL(op)->onStack ||
+ (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
+ return TRUE;
- return ((IN_STACK (etype)) ? TRUE : FALSE);
+ return FALSE;
}
/*-----------------------------------------------------------------*/
return floatFromVal (op->operand.valOperand);
}
+/*-----------------------------------------------------------------*/
+/* getBuiltInParms - returns parameters to a builtin functions */
+/*-----------------------------------------------------------------*/
+iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
+{
+ sym_link *ftype;
+
+ *pcount = 0;
+ /* builtin functions uses only SEND for parameters */
+ while (ic->op != CALL) {
+ assert(ic->op == SEND && ic->builtinSEND);
+ ic->generated = 1; /* mark the icode as generated */
+ parms[*pcount] = IC_LEFT(ic);
+ ic = ic->next;
+ (*pcount)++;
+ }
+
+ ic->generated = 1;
+ /* make sure this is a builtin function call */
+ assert(IS_SYMOP(IC_LEFT(ic)));
+ ftype = operandType(IC_LEFT(ic));
+ assert(IFFUNC_ISBUILTIN(ftype));
+ return ic;
+}
+
/*-----------------------------------------------------------------*/
/* operandOperation - perforoms operations on operands */
/*-----------------------------------------------------------------*/
operandOperation (operand * left, operand * right,
int op, sym_link * type)
{
+ sym_link *let , *ret=NULL;
operand *retval = (operand *) 0;
-
+
assert (isOperandLiteral (left));
- if (right)
+ let = getSpec(operandType(left));
+ if (right) {
assert (isOperandLiteral (right));
+ ret = getSpec(operandType(left));
+ }
switch (op)
{
operandLitValue (right)));
break;
case '%':
- if ((unsigned long) operandLitValue (right) == 0)
- {
+ if ((unsigned long) operandLitValue (right) == 0) {
werror (E_DIVIDE_BY_ZERO);
retval = right;
- }
- else
- retval = operandFromLit ((unsigned long) operandLitValue (left) %
- (unsigned long) operandLitValue (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 ((unsigned long) operandLitValue (left) <<
- (unsigned long) operandLitValue (right));
+ 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 ((unsigned long) operandLitValue (left) >>
- (unsigned long) operandLitValue (right));
+ case RIGHT_OP: {
+ double lval = operandLitValue(left), rval = operandLitValue(right);
+ double res=0;
+ switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0))
+ {
+ case 0: // left=unsigned right=unsigned
+ res=(unsigned long)lval >> (unsigned long)rval;
+ break;
+ case 1: // left=unsigned right=signed
+ res=(unsigned long)lval >> (signed long)rval;
+ break;
+ case 2: // left=signed right=unsigned
+ res=(signed long)lval >> (unsigned long)rval;
+ break;
+ case 3: // left=signed right=signed
+ res=(signed long)lval >> (signed long)rval;
+ break;
+ }
+ retval = operandFromLit (res);
break;
+ }
case EQ_OP:
retval = operandFromLit (operandLitValue (left) ==
operandLitValue (right));
operandLitValue (right));
break;
case BITWISEAND:
- retval = operandFromLit ((unsigned long) operandLitValue (left) &
- (unsigned long) operandLitValue (right));
+ retval = operandFromLit ((long)operandLitValue(left) &
+ (long)operandLitValue(right));
break;
case '|':
- retval = operandFromLit ((unsigned long) operandLitValue (left) |
- (unsigned long) operandLitValue (right));
+ retval = operandFromLit ((long)operandLitValue (left) |
+ (long)operandLitValue (right));
break;
case '^':
- retval = operandFromLit ((unsigned long) operandLitValue (left) ^
- (unsigned long) operandLitValue (right));
+ retval = operandFromLit ((long)operandLitValue (left) ^
+ (long)operandLitValue (right));
break;
case AND_OP:
retval = operandFromLit (operandLitValue (left) &&
break;
case RRC:
{
- long i = operandLitValue (left);
+ long i = (long) operandLitValue (left);
retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
(i << 1));
break;
case RLC:
{
- long i = operandLitValue (left);
+ long i = (long) operandLitValue (left);
retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
(i >> 1));
return (floatFromVal (left->operand.valOperand) ==
floatFromVal (right->operand.valOperand));
case TYPE:
- if (checkType (left->operand.typeOperand,
+ if (compareType (left->operand.typeOperand,
right->operand.typeOperand) == 1)
return 1;
}
return 0;
}
-/*-----------------------------------------------------------------*/
-/* isiCodeEqual - comapres two iCodes are returns true if yes */
-/*-----------------------------------------------------------------*/
+/*-------------------------------------------------------------------*/
+/* isiCodeEqual - compares two iCodes are equal, returns true if yes */
+/*-------------------------------------------------------------------*/
int
isiCodeEqual (iCode * left, iCode * right)
{
if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
return 0;
}
+
return 1;
}
return 0;
nop->isvolatile = op->isvolatile;
nop->isGlobal = op->isGlobal;
nop->isLiteral = op->isLiteral;
- nop->noSpilLoc = op->noSpilLoc;
nop->usesDefs = op->usesDefs;
nop->isParm = op->isParm;
return nop;
nop->isvolatile = op->isvolatile;
nop->isGlobal = op->isGlobal;
nop->isLiteral = op->isLiteral;
- nop->noSpilLoc = op->noSpilLoc;
nop->usesDefs = op->usesDefs;
nop->isParm = op->isParm;
/* 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)) && (!TARGET_IS_DS390)) &&
+ (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+ (!(options.model == MODEL_FLAT24)) ) &&
options.stackAuto == 0)
ok = 0;
!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 register euivalence */
+ !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 */
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;
}
else
IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
- IC_RESULT (ic)->operand.symOperand->args = sym->args;
-
ADDTOCHAIN (ic);
return IC_RESULT (ic);
/* operandFromLit - makes an operand from a literal value */
/*-----------------------------------------------------------------*/
operand *
-operandFromLit (float i)
+operandFromLit (double i)
{
return operandFromValue (valueFromLit (i));
}
/* operandFromAst - creates an operand from an ast */
/*-----------------------------------------------------------------*/
operand *
-operandFromAst (ast * tree)
+operandFromAst (ast * tree,int lvl)
{
if (!tree)
switch (tree->type)
{
case EX_OP:
- return ast2iCode (tree);
+ return ast2iCode (tree,lvl+1);
break;
case EX_VALUE:
{
if (IS_INTEGRAL (operandType (op)))
{
- if (getSize (operandType (op)) < INTSIZE)
+ if (getSize (operandType (op)) < (unsigned int) INTSIZE)
{
/* Widen to int. */
return geniCodeCast (INTTYPE, op, TRUE);
sym_link *
usualBinaryConversions (operand ** op1, operand ** op2)
{
- if (!options.ANSIint)
- {
- /* "Classic" SDCC behavior. */
- 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;
- }
-
- *op1 = usualUnaryConversions (*op1);
- *op2 = usualUnaryConversions (*op2);
-
- /* Try to make the two operands of the same type, following
- * the "usual binary conversions" promotion rules.
- *
- * NB: floating point types are not yet properly handled; we
- * follow the "classic" behavior.
- */
-
- if (IS_FLOAT (operandType (*op1)) || IS_FLOAT (operandType (*op2)))
- {
- return newFloatLink ();
- }
-
- if (!IS_INTEGRAL (operandType (*op1)) || !IS_INTEGRAL (operandType (*op2)))
- {
- /* if either is not an integer type, we're done. */
- return copyLinkChain (operandType (*op1)); /* Punt! we should never get here. */
- }
-
- /* If either is an unsigned long, make sure both are. */
- if (SPEC_USIGN (operandType (*op1)) && IS_LONG (operandType (*op1)))
- {
- if (!SPEC_USIGN (operandType (*op2)) || !IS_LONG (operandType (*op2)))
- {
- *op2 = geniCodeCast (ULONGTYPE, *op2, TRUE);
- }
- return copyLinkChain (operandType (*op1));
- }
-
- if (SPEC_USIGN (operandType (*op2)) && IS_LONG (operandType (*op2)))
- {
- if (!SPEC_USIGN (operandType (*op1)) || !IS_LONG (operandType (*op1)))
- {
- *op1 = geniCodeCast (ULONGTYPE, *op1, TRUE);
- }
- return copyLinkChain (operandType (*op2));
- }
-
- /* Next, if one is long and the other is int (signed or un),
- * cast both to long.
- *
- * Note that because in our environment a long can hold all
- * the values of an unsigned int, the "long/unsigned int" pair
- * in the ANSI conversion table is unnecessary; this test
- * handles that case implicitly.
- */
- if (IS_LONG (operandType (*op1)))
- {
- /* NB: because of the unary conversions, op2 cannot
- * be smaller than int. Therefore, if it is not
- * long, it is a regular int.
- */
- if (!IS_LONG (operandType (*op2)))
- {
- *op2 = geniCodeCast (LONGTYPE, *op2, TRUE);
- }
- return copyLinkChain (operandType (*op1));
- }
-
- if (IS_LONG (operandType (*op2)))
- {
- /* NB: because of the unary conversions, op2 cannot
- * be smaller than int. Therefore, if it is not
- * long, it is a regular int.
- */
- if (!IS_LONG (operandType (*op1)))
- {
- *op1 = geniCodeCast (LONGTYPE, *op1, TRUE);
- }
- return copyLinkChain (operandType (*op2));
- }
-
- /* All right, neither is long; they must both be integers.
-
- * Only remaining issue is signed vs. unsigned; if one is unsigned
- * and the other isn't, convert both to unsigned.
- */
- if (SPEC_USIGN (operandType (*op1)))
- {
- if (!SPEC_USIGN (operandType (*op2)))
- {
- *op2 = geniCodeCast (UINTTYPE, *op2, TRUE);
- }
- return copyLinkChain (operandType (*op1));
- }
-
- if (SPEC_USIGN (operandType (*op2)))
- {
- if (!SPEC_USIGN (operandType (*op1)))
- {
- *op1 = geniCodeCast (UINTTYPE, *op1, TRUE);
- }
- return copyLinkChain (operandType (*op2));
- }
+ sym_link *ctype;
+ sym_link *rtype = operandType (*op2);
+ sym_link *ltype = operandType (*op1);
+
+ ctype = computeType (ltype, rtype);
- /* Done! */
- return copyLinkChain (operandType (*op1));
+ *op1 = geniCodeCast (ctype, *op1, TRUE);
+ *op2 = geniCodeCast (ctype, *op2, TRUE);
+
+ return ctype;
}
-
/*-----------------------------------------------------------------*/
/* geniCodeValueAtAddress - generate intermeditate code for value */
/* at address */
if (IS_SPEC (type) &&
IS_TRUE_SYMOP (op) &&
- (!IN_FARSPACE (SPEC_OCLS (etype)) || TARGET_IS_DS390))
+ (!IN_FARSPACE (SPEC_OCLS (etype)) ||
+ (options.model == MODEL_FLAT24) ))
{
op = operandFromOperand (op);
op->isaddr = 0;
/* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
- /* if the right is a symbol */
- if (op->type == SYMBOL)
- IC_RESULT (ic)->operand.symOperand->args =
- op->operand.symOperand->args;
ADDTOCHAIN (ic);
return IC_RESULT (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))
}
/* if the operand is already the desired type then do nothing */
- if (checkType (type, optype) == 1)
+ if (compareType (type, optype) == 1)
return op;
/* if this is a literal then just change the type & return */
return operandFromValue (valCastLiteral (type,
operandLitValue (op)));
- /* if casting to some pointer type &&
- the destination is not a generic pointer
- then give a warning : (only for implicit casts) */
- if (IS_PTR (optype) && implicit &&
- (DCL_TYPE (optype) != DCL_TYPE (type)) &&
- !IS_GENPTR (type))
- {
- werror (E_INCOMPAT_CAST);
- werror (E_CONTINUE, "from type '");
- printTypeChain (optype, stderr);
- fprintf (stderr, "' to type '");
- printTypeChain (type, stderr);
- fprintf (stderr, "'\n");
+ /* 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) &&
/* preserve the storage class & output class */
/* of the original variable */
restype = getSpec (operandType (IC_RESULT (ic)));
- SPEC_SCLS (restype) = SPEC_SCLS (opetype);
+ if (!IS_LITERAL(opetype))
+ SPEC_SCLS (restype) = SPEC_SCLS (opetype);
SPEC_OCLS (restype) = SPEC_OCLS (opetype);
ADDTOCHAIN (ic);
{
iCode *ic;
int p2 = 0;
- int saveOption=0;
sym_link *resType;
LRTYPE;
p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
}
- if (resultIsInt)
- {
- saveOption = options.ANSIint;
- options.ANSIint = 0;
- }
resType = usualBinaryConversions (&left, &right);
#if 1
rtype = operandType (right);
#endif
if (resultIsInt)
{
- options.ANSIint = saveOption;
SPEC_NOUN(getSpec(resType))=V_INT;
- SPEC_SHORT(getSpec(resType))=0;
}
/* if the right is a literal & power of 2 */
if port has 1 byte muldiv */
if (p2 && !IS_FLOAT (letype) &&
!((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
- (port->muldiv.native_below == 1)))
+ (port->support.muldiv == 1)))
{
if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
{
resType = usualBinaryConversions (&left, &right);
- /* if the right is a literal & power of 2 */
- /* then make it a right shift */
+ /* if the right is a literal & power of 2
+ and left is unsigned then make it a
+ right shift */
if (IS_LITERAL (retype) &&
!IS_FLOAT (letype) &&
+ SPEC_USIGN(letype) &&
(p2 = powof2 ((unsigned long)
- floatFromVal (right->operand.valOperand))))
- ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
+ floatFromVal (right->operand.valOperand)))) {
+ ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
+ }
else
{
ic = newiCode ('/', left, right); /* normal division */
ADDTOCHAIN (ic);
subtractExit:
+ if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
+ return result;
+ }
+
+ // should we really do this? is this ANSI?
return geniCodeDivision (result,
operandFromLit (getSize (ltype->next)));
}
/* geniCodeAdd - generates iCode for addition */
/*-----------------------------------------------------------------*/
operand *
-geniCodeAdd (operand * left, operand * right)
+geniCodeAdd (operand * left, operand * right, int lvl)
{
iCode *ic;
sym_link *resType;
int isarray = 0;
LRTYPE;
+#if 0
/* if left is an array then array access */
if (IS_ARRAY (ltype))
- return geniCodeArray (left, right);
+ return geniCodeArray (left, right,lvl);
+#endif
/* if the right side is LITERAL zero */
/* return the left side */
if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
return right;
- /* if left is an array or pointer then size */
- if (IS_PTR (ltype))
+ /* if left is a pointer then size */
+ if (IS_PTR (ltype) || IS_ARRAY(ltype))
{
isarray = left->isaddr;
// there is no need to multiply with 1
resType = copyLinkChain (ltype);
}
else
- { /* make them the same size */
+ { // make them the same size
resType = usualBinaryConversions (&left, &right);
}
/* geniCodeArray - array access */
/*-----------------------------------------------------------------*/
operand *
-geniCodeArray (operand * left, operand * right)
+geniCodeArray (operand * left, operand * right,int lvl)
{
iCode *ic;
sym_link *ltype = operandType (left);
{
left = geniCodeRValue (left, FALSE);
}
- return geniCodeDerefPtr (geniCodeAdd (left, right));
+ return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
}
right = geniCodeMultiply (right,
symbol *element = getStructElement (SPEC_STRUCT (etype),
right->operand.symOperand);
+ wassert(IS_SYMOP(right));
+
/* add the offset */
ic = newiCode ('+', left, operandFromLit (element->offset));
}
rOp = newiTempOperand (rvtype, 0);
- rOp->noSpilLoc = 1;
+ OP_SYMBOL(rOp)->noSpilLoc = 1;
if (IS_ITEMP (rv))
- rv->noSpilLoc = 1;
+ OP_SYMBOL(rv)->noSpilLoc = 1;
geniCodeAssign (rOp, rv, 0);
/* if this is not an address we have trouble */
if (!op->isaddr)
{
- werror (E_LVALUE_REQUIRED, "++");
+ werror (E_LVALUE_REQUIRED, "--");
return op;
}
rOp = newiTempOperand (rvtype, 0);
- rOp->noSpilLoc = 1;
+ OP_SYMBOL(rOp)->noSpilLoc = 1;
if (IS_ITEMP (rv))
- rv->noSpilLoc = 1;
+ OP_SYMBOL(rv)->noSpilLoc = 1;
geniCodeAssign (rOp, rv, 0);
if (!op->isaddr)
{
- werror (E_LVALUE_REQUIRED, "++");
+ werror (E_LVALUE_REQUIRED, "--");
return op;
}
/* geniCodeDerefPtr - dereference pointer with '*' */
/*-----------------------------------------------------------------*/
operand *
-geniCodeDerefPtr (operand * op)
+geniCodeDerefPtr (operand * op,int lvl)
{
sym_link *rtype, *retype;
sym_link *optype = operandType (op);
}
/* now get rid of the pointer part */
- if (lvaluereq && IS_ITEMP (op))
+ if (isLvaluereq(lvl) && IS_ITEMP (op))
{
retype = getSpec (rtype = copyLinkChain (optype));
}
IS_CHAR (rtype) ||
IS_FLOAT (rtype));
- if (!lvaluereq)
+ if (!isLvaluereq(lvl))
op = geniCodeRValue (op, TRUE);
setOperandType (op, rtype);
{
iCode *ic;
-
- /* Note that we don't use the usual binary conversions for the
- * shift operations, in accordance with our ANSI friends.
- */
- if (options.ANSIint)
- {
- right = usualUnaryConversions (right);
- left = usualUnaryConversions (left);
- }
-
ic = newiCode (LEFT_OP, left, right);
IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
ADDTOCHAIN (ic);
{
iCode *ic;
-
- /* Note that we don't use the usual binary conversions for the
- * shift operations, in accordance with our ANSI friends.
- */
- if (options.ANSIint)
- {
- right = usualUnaryConversions (right);
- left = usualUnaryConversions (left);
- }
-
ic = newiCode (RIGHT_OP, left, right);
IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
}
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define LONG_LONG __int64
-#else
-#define LONG_LONG long long
-#endif
-
/*-----------------------------------------------------------------*/
/* geniCodeLogic- logic code */
/*-----------------------------------------------------------------*/
/* left is integral type and right is literal then
check if the literal value is within bounds */
- if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
+ if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
{
- int nbits = bitsForType (ltype);
- long v = operandLitValue (right);
-
- if (v > ((LONG_LONG) 1 << nbits) && v > 0)
- werror (W_CONST_RANGE, " compare operation ");
+ checkConstantRange(ltype,
+ OP_VALUE(right), "compare operation", 1);
}
ctype = usualBinaryConversions (&left, &right);
/* geniCodeConditional - geniCode for '?' ':' operation */
/*-----------------------------------------------------------------*/
operand *
-geniCodeConditional (ast * tree)
+geniCodeConditional (ast * tree,int lvl)
{
iCode *ic;
symbol *falseLabel = newiTempLabel (NULL);
symbol *exitLabel = newiTempLabel (NULL);
- operand *cond = ast2iCode (tree->left);
+ 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);
+ true = ast2iCode (tree->right->left,lvl+1);
/* move the value to a new Operand */
- result = newiTempOperand (operandType (true), 0);
+ result = newiTempOperand (tree->right->ftype, 0);
geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
/* generate an unconditional goto */
/* now for the right side */
geniCodeLabel (falseLabel);
- false = ast2iCode (tree->right->right);
+ false = ast2iCode (tree->right->right,lvl+1);
geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
/* create the exit label */
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
{
- int nbits = bitsForType (ltype);
- long v = operandLitValue (right);
-
- if (v > ((LONG_LONG) 1 << nbits) && v > 0)
- werror (W_CONST_RANGE, " = operation");
+ checkConstantRange(ltype,
+ OP_VALUE(right), "= operation", 0);
}
/* if the left & right type don't exactly match */
/* first check the type for pointer assignement */
if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
- checkType (ltype, rtype) < 0)
+ compareType (ltype, rtype) <= 0)
{
- if (checkType (ltype->next, rtype) < 0)
+ if (compareType (ltype->next, rtype) < 0)
right = geniCodeCast (ltype->next, right, TRUE);
}
- else if (checkType (ltype, rtype) < 0)
+ else if (compareType (ltype, rtype) < 0)
right = geniCodeCast (ltype, right, TRUE);
/* if left is a true symbol & ! volatile
/* geniCodeSEParms - generate code for side effecting fcalls */
/*-----------------------------------------------------------------*/
static void
-geniCodeSEParms (ast * parms)
+geniCodeSEParms (ast * parms,int lvl)
{
if (!parms)
return;
if (parms->type == EX_OP && parms->opval.op == PARAM)
{
- geniCodeSEParms (parms->left);
- geniCodeSEParms (parms->right);
+ geniCodeSEParms (parms->left,lvl);
+ geniCodeSEParms (parms->right,lvl);
return;
}
IS_ADDRESS_OF_OP (parms->right))
parms->right->left->lvalue = 1;
- parms->opval.oprnd =
- geniCodeRValue (ast2iCode (parms), FALSE);
-
+ parms->opval.oprnd =
+ geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
+
parms->type = EX_OPERAND;
+ AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
+ SPEC_ARGREG(parms->ftype);
}
/*-----------------------------------------------------------------*/
/* geniCodeParms - generates parameters */
/*-----------------------------------------------------------------*/
-static void
-geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
+value *
+geniCodeParms (ast * parms, value *argVals, int *stack,
+ sym_link * fetype, symbol * func,int lvl)
{
iCode *ic;
operand *pval;
if (!parms)
- return;
+ 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)
{
- geniCodeParms (parms->left, stack, fetype, func);
- geniCodeParms (parms->right, stack, fetype, func);
- return;
+ argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
+ argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
+ return argVals;
}
/* get the parameter value */
IS_ADDRESS_OF_OP (parms->right))
parms->right->left->lvalue = 1;
- pval = geniCodeRValue (ast2iCode (parms), FALSE);
+ pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
}
/* if register parm then make it a send */
- if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
- IS_REGPARM (parms->etype)) && !func->hasVargs)
+ if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
+ IFFUNC_ISBUILTIN(func->type))
{
ic = newiCode (SEND, pval, NULL);
+ ic->argreg = SPEC_ARGREG(parms->etype);
+ ic->builtinSEND = FUNC_ISBUILTIN(func->type);
ADDTOCHAIN (ic);
}
else
{
/* now decide whether to push or assign */
- if (!(options.stackAuto || IS_RENT (fetype)))
+ if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
{
/* assign */
- operand *top = operandFromSymbol (parms->argSym);
+ operand *top = operandFromSymbol (argVals->sym);
+ /* clear useDef and other bitVectors */
+ OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
geniCodeAssign (top, pval, 1);
}
else
}
}
+ argVals=argVals->next;
+ return argVals;
}
/*-----------------------------------------------------------------*/
/* geniCodeCall - generates temp code for calling */
/*-----------------------------------------------------------------*/
operand *
-geniCodeCall (operand * left, ast * parms)
+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);
+ geniCodeSEParms (parms,lvl);
/* first the parameters */
- geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left));
+ 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))
+ if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
ic = newiCode (PCALL, left, NULL);
- else
+ } else {
ic = newiCode (CALL, left, NULL);
+ }
- IC_ARGS (ic) = left->operand.symOperand->args;
type = copyLinkChain (operandType (left)->next);
etype = getSpec (type);
SPEC_EXTR (etype) = 0;
/* for all arguments that are passed in registers */
while (args)
{
-
+ int first = 1;
if (IS_REGPARM (args->etype))
{
operand *opr = operandFromValue (args);
if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
options.stackAuto == 0 &&
- !TARGET_IS_DS390)
+ (!(options.model == MODEL_FLAT24)) )
{
}
else
}
}
- ic = newiCode (RECEIVE, NULL, NULL);
- currFunc->recvSize = getSize (sym->etype);
+ ic = newiCode (RECEIVE, NULL, NULL);
+ ic->argreg = SPEC_ARGREG(args->etype);
+ if (first) {
+ currFunc->recvSize = getSize (sym->type);
+ first = 0;
+ }
IC_RESULT (ic) = opr;
ADDTOCHAIN (ic);
}
/* geniCodeFunctionBody - create the function body */
/*-----------------------------------------------------------------*/
void
-geniCodeFunctionBody (ast * tree)
+geniCodeFunctionBody (ast * tree,int lvl)
{
iCode *ic;
operand *func;
iTempLblNum = 0;
operandKey = 0;
iCodeKey = 0;
- func = ast2iCode (tree->left);
+ func = ast2iCode (tree->left,lvl+1);
fetype = getSpec (operandType (func));
savelineno = lineno;
/* 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;
+ lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
ADDTOCHAIN (ic);
geniCodeReceive (tree->values.args);
/* generate code for the body */
- ast2iCode (tree->right);
+ ast2iCode (tree->right,lvl+1);
/* create a label for return */
geniCodeLabel (returnLabel);
/* geniCodeIfx - generates code for extended if statement */
/*-----------------------------------------------------------------*/
void
-geniCodeIfx (ast * tree)
+geniCodeIfx (ast * tree,int lvl)
{
iCode *ic;
- operand *condition = ast2iCode (tree->left);
+ operand *condition = ast2iCode (tree->left,lvl+1);
sym_link *cetype;
/* if condition is null then exit */
if (tree->trueLabel)
geniCodeGoto (tree->trueLabel);
else
- assert (1);
+ assert (0);
}
else
{
if (tree->falseLabel)
geniCodeGoto (tree->falseLabel);
else
- assert (1);
+ assert (0);
}
goto exit;
}
}
exit:
- ast2iCode (tree->right);
+ ast2iCode (tree->right,lvl+1);
}
/*-----------------------------------------------------------------*/
/* 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",
+ SNPRINTF (buffer, sizeof(buffer),
+ "_case_%d_%d",
tree->values.switchVals.swNum,
min);
addSet (&labels, newiTempLabel (buffer));
{
if (((t = (int) floatFromVal (vch)) - max) != 1)
return 0;
- sprintf (buffer, "_case_%d_%d",
+ SNPRINTF (buffer, sizeof(buffer),
+ "_case_%d_%d",
tree->values.switchVals.swNum,
t);
addSet (&labels, newiTempLabel (buffer));
return 0;
if (tree->values.switchVals.swDefault)
- sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+ {
+ SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+ }
else
- sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
+ {
+ SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+ }
+
falseLabel = newiTempLabel (buffer);
/* geniCodeSwitch - changes a switch to a if statement */
/*-----------------------------------------------------------------*/
void
-geniCodeSwitch (ast * tree)
+geniCodeSwitch (ast * tree,int lvl)
{
iCode *ic;
- operand *cond = geniCodeRValue (ast2iCode (tree->left), FALSE);
+ operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
value *caseVals = tree->values.switchVals.swVals;
symbol *trueLabel, *falseLabel;
operandFromValue (caseVals),
EQ_OP);
- sprintf (buffer, "_case_%d_%d",
+ SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
tree->values.switchVals.swNum,
(int) floatFromVal (caseVals));
trueLabel = newiTempLabel (buffer);
/* if default is present then goto break else break */
if (tree->values.switchVals.swDefault)
- sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+ {
+ SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+ }
else
- sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
+ {
+ SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+ }
falseLabel = newiTempLabel (buffer);
geniCodeGoto (falseLabel);
jumpTable:
- ast2iCode (tree->right);
+ ast2iCode (tree->right,lvl+1);
}
/*-----------------------------------------------------------------*/
ADDTOCHAIN (ic);
}
+/*-----------------------------------------------------------------*/
+/* geniCodeArrayInit - intermediate code for array initializer */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeArrayInit (ast * tree, operand *array)
+{
+ iCode *ic;
+
+ 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;
+}
+
/*-----------------------------------------------------------------*/
/* ast2iCode - creates an icodeList from an ast */
/*-----------------------------------------------------------------*/
operand *
-ast2iCode (ast * tree)
+ast2iCode (ast * tree,int lvl)
{
operand *left = NULL;
operand *right = NULL;
-
if (!tree)
return NULL;
/* if we find a nullop */
if (tree->type == EX_OP &&
- (tree->opval.op == NULLOP ||
- tree->opval.op == BLOCK))
+ (tree->opval.op == NULLOP ||
+ tree->opval.op == BLOCK))
{
- ast2iCode (tree->left);
- ast2iCode (tree->right);
+ ast2iCode (tree->left,lvl+1);
+ ast2iCode (tree->right,lvl+1);
return NULL;
}
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)
- {
- lvaluereq++;
- if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
- (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
- {
- int olvr = lvaluereq;
- lvaluereq = 0;
- left = operandFromAst (tree->left);
- lvaluereq = olvr - 1;
- }
- else
- {
- left = operandFromAst (tree->left);
- lvaluereq--;
- }
- if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
- left = geniCodeRValue (left, TRUE);
- }
- else
- {
- left = operandFromAst (tree->left);
- }
- if (tree->opval.op == INC_OP ||
- tree->opval.op == DEC_OP)
- {
- lvaluereq++;
- right = operandFromAst (tree->right);
- lvaluereq--;
- }
- else
- {
- right = operandFromAst (tree->right);
- }
- }
+ 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 */
case '[': /* array operation */
{
- sym_link *ltype = operandType (left);
- left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+ //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);
+ return geniCodeArray (left, right,lvl);
case '.': /* structure dereference */
if (IS_PTR (operandType (left)))
return geniCodeMultiply (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
else
- return geniCodeDerefPtr (geniCodeRValue (left, FALSE));
+ return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
case '-':
if (right)
case '+':
if (right)
return geniCodeAdd (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),lvl);
else
return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
geniCodeRValue (right, FALSE),
tree->opval.op);
case '?':
- return geniCodeConditional (tree);
+ return geniCodeConditional (tree,lvl);
case SIZEOF:
return operandFromLit (getSize (tree->right->ftype));
sym_link *rtype = operandType (right);
sym_link *ltype = operandType (left);
if (IS_PTR (rtype) && IS_ITEMP (right)
- && right->isaddr && checkType (rtype->next, ltype) == 1)
+ && right->isaddr && compareType (rtype->next, ltype) == 1)
right = geniCodeRValue (right, TRUE);
else
right = geniCodeRValue (right, FALSE);
sym_link *rtype = operandType (right);
sym_link *ltype = operandType (left);
if (IS_PTR (rtype) && IS_ITEMP (right)
- && right->isaddr && checkType (rtype->next, ltype) == 1)
+ && 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), 0);
+ right,lvl), 0);
}
case SUB_ASSIGN:
{
sym_link *rtype = operandType (right);
sym_link *ltype = operandType (left);
if (IS_PTR (rtype) && IS_ITEMP (right)
- && right->isaddr && checkType (rtype->next, ltype) == 1)
+ && right->isaddr && compareType (rtype->next, ltype) == 1)
{
right = geniCodeRValue (right, TRUE);
}
return geniCodeRValue (right, FALSE);
case CALL:
- return geniCodeCall (ast2iCode (tree->left),
- tree->right);
+ return geniCodeCall (ast2iCode (tree->left,lvl+1),
+ tree->right,lvl);
case LABEL:
- geniCodeLabel (ast2iCode (tree->left)->operand.symOperand);
- return ast2iCode (tree->right);
+ geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+ return ast2iCode (tree->right,lvl+1);
case GOTO:
- geniCodeGoto (ast2iCode (tree->left)->operand.symOperand);
- return ast2iCode (tree->right);
+ geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+ return ast2iCode (tree->right,lvl+1);
case FUNCTION:
- geniCodeFunctionBody (tree);
+ geniCodeFunctionBody (tree,lvl);
return NULL;
case RETURN:
return NULL;
case IFX:
- geniCodeIfx (tree);
+ geniCodeIfx (tree,lvl);
return NULL;
case SWITCH:
- geniCodeSwitch (tree);
+ geniCodeSwitch (tree,lvl);
return NULL;
case INLINEASM:
geniCodeInline (tree);
return NULL;
+
+ case ARRAYINIT:
+ geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
+ return NULL;
}
return NULL;
{
returnLabel = newiTempLabel ("_return");
entryLabel = newiTempLabel ("_entry");
- ast2iCode (tree);
+ ast2iCode (tree,0);
return reverseiCChain ();
}
+
+static const char *opTypeToStr(OPTYPE op)
+{
+ switch(op)
+ {
+ case SYMBOL: return "symbol";
+ case VALUE: return "value";
+ case TYPE: return "type";
+ }
+ return "undefined type";
+}
+
+
+operand *validateOpType(operand *op,
+ const char *macro,
+ const char *args,
+ OPTYPE type,
+ const char *file,
+ unsigned line)
+{
+ if (op && op->type == type)
+ {
+ return op;
+ }
+ fprintf(stderr,
+ "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
+ " expected %s, got %s\n",
+ macro, args, file, line,
+ opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
+ exit(-1);
+ return op; // never reached, makes compiler happy.
+}