/*-----------------------------------------------------------------*/
/* forward definition of some functions */
-operand *geniCodeDivision (operand *, operand *);
operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *,int);
-operand *geniCodeArray2Ptr (operand *);
+static operand *geniCodeArray (operand *, operand *,int);
+static operand *geniCodeArray2Ptr (operand *);
operand *geniCodeRValue (operand *, bool);
operand *geniCodeDerefPtr (operand *,int);
int isLvaluereq(int lvl);
(TYPE_UDWORD) operandLitValue (right));
break;
case EQ_OP:
- /* this op doesn't care about signedness */
- {
- TYPE_UDWORD l, r;
-
- l = (TYPE_UDWORD) operandLitValue (left);
- if (IS_CHAR(OP_VALUE(left)->type))
- l &= 0xff;
- else if (!IS_LONG (OP_VALUE(left)->type))
- l &= 0xffff;
- r = (TYPE_UDWORD) operandLitValue (right);
- if (IS_CHAR(OP_VALUE(right)->type))
- r &= 0xff;
- else if (!IS_LONG (OP_VALUE(right)->type))
- r &= 0xffff;
- retval = operandFromLit (l == r);
- }
+ if (IS_FLOAT (let) ||
+ IS_FLOAT (ret))
+ {
+ retval = operandFromLit (operandLitValue (left) ==
+ operandLitValue (right));
+ }
+ else
+ {
+ /* this op doesn't care about signedness */
+ TYPE_UDWORD l, r;
+
+ l = (TYPE_UDWORD) operandLitValue (left);
+ r = (TYPE_UDWORD) operandLitValue (right);
+ /* In order to correctly compare 'signed int' and 'unsigned int' it's
+ neccessary to strip them to 16 bit.
+ Literals are reduced to their cheapest type, therefore left and
+ right might have different types. It's neccessary to find a
+ common type: int (used for char too) or long */
+ if (!IS_LONG (let) &&
+ !IS_LONG (ret))
+ {
+ r = (TYPE_UWORD) r;
+ l = (TYPE_UWORD) l;
+ }
+ retval = operandFromLit (l == r);
+ }
break;
case '<':
retval = operandFromLit (operandLitValue (left) <
and before liveRange calculation */
sym->reqv = newiTempOperand (sym->type, 0);
sym->reqv->key = sym->key;
+ OP_SYMBOL (sym->reqv)->prereqv = sym;
OP_SYMBOL (sym->reqv)->key = sym->key;
OP_SYMBOL (sym->reqv)->isreqv = 1;
OP_SYMBOL (sym->reqv)->islocal = 1;
}
}
+
/*-----------------------------------------------------------------*/
/* Get size in byte of ptr need to access an array */
/*-----------------------------------------------------------------*/
-int
+static int
getArraySizePtr (operand * op)
{
sym_link *ltype = operandType(op);
/*-----------------------------------------------------------------*/
/* perform "usual binary conversions" */
/*-----------------------------------------------------------------*/
+
static sym_link *
usualBinaryConversions (operand ** op1, operand ** op2,
- bool promoteCharToInt, bool isMul)
+ RESULT_TYPE resultType, int op)
{
sym_link *ctype;
sym_link *rtype = operandType (*op2);
sym_link *ltype = operandType (*op1);
- ctype = computeType (ltype, rtype, promoteCharToInt);
+ ctype = computeType (ltype, rtype, resultType, op);
- /* special for multiplication:
- This if for 'mul a,b', which takes two chars and returns an int */
- if ( isMul
- /* && promoteCharToInt superfluous, already handled by computeType() */
- && IS_INT (getSpec (ctype)))
+ switch (op)
{
- sym_link *retype = getSpec (rtype);
- sym_link *letype = getSpec (ltype);
-
- if ( IS_CHAR (letype)
- && IS_CHAR (retype)
- && IS_UNSIGNED (letype)
- && IS_UNSIGNED (retype))
- {
- return ctype;
- }
+ case '*':
+ case '/':
+ case '%':
+ if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
+ {
+ /* one byte operations: keep signedness for code generator */
+ return ctype;
+ }
+ break;
+ default:
+ break;
}
+
*op1 = geniCodeCast (ctype, *op1, TRUE);
*op2 = geniCodeCast (ctype, *op2, TRUE);
-
+
return ctype;
}
return op;
}
+ if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
+ {
+ geniCodeArray2Ptr (op);
+ op->isaddr = 0;
+ }
+
/* if the operand is already the desired type then do nothing */
if (compareType (type, optype) == 1)
return op;
}
/* if they are the same size create an assignment */
+
+ /* This seems very dangerous to me, since there are several */
+ /* optimizations (for example, gcse) that don't notice the */
+ /* cast hidden in this assignement and may simplify an */
+ /* iCode to use the original (uncasted) operand. */
+ /* Unfortunately, other things break when this cast is */
+ /* made explicit. Need to fix this someday. */
+ /* -- EEP, 2004/01/21 */
if (getSize (type) == getSize (optype) &&
!IS_BITFIELD (type) &&
!IS_FLOAT (type) &&
/* preserve the storage class & output class */
/* of the original variable */
restype = getSpec (operandType (IC_RESULT (ic)));
- if (!IS_LITERAL(opetype))
+ if (!IS_LITERAL(opetype) &&
+ !IS_BIT(opetype))
SPEC_SCLS (restype) = SPEC_SCLS (opetype);
SPEC_OCLS (restype) = SPEC_OCLS (opetype);
/*-----------------------------------------------------------------*/
/* geniCodeMultiply - gen intermediate code for multiplication */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeMultiply (operand * left, operand * right, int resultIsInt)
+static operand *
+geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int p2 = 0;
p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
}
- resType = usualBinaryConversions (&left, &right, resultIsInt, TRUE);
+ resType = usualBinaryConversions (&left, &right, resultType, '*');
#if 1
rtype = operandType (right);
retype = getSpec (rtype);
/* 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 (p2 && !IS_FLOAT (letype)
+ && !((resultType != RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
+ && (port->support.muldiv == 1))
+ && strcmp (port->target, "pic14") != 0 /* don't shift for pic */
+ && strcmp (port->target, "pic16") != 0)
{
- if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
+ if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
{
/* LEFT_OP need same size for left and result, */
left = geniCodeCast (resType, left, TRUE);
/*-----------------------------------------------------------------*/
/* geniCodeDivision - gen intermediate code for division */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeDivision (operand * left, operand * right)
+static operand *
+geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int p2 = 0;
sym_link *ltype = operandType (left);
sym_link *letype = getSpec (ltype);
- resType = usualBinaryConversions (&left, &right,
- (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE,
- FALSE);
+ resType = usualBinaryConversions (&left, &right, resultType, '/');
/* if the right is a literal & power of 2
and left is unsigned then make it a
/*-----------------------------------------------------------------*/
/* geniCodeModulus - gen intermediate code for modulus */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeModulus (operand * left, operand * right)
+static operand *
+geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
sym_link *resType;
return operandFromValue (valMod (left->operand.valOperand,
right->operand.valOperand));
- resType = usualBinaryConversions (&left, &right,
- (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE,
- FALSE);
+ resType = usualBinaryConversions (&left, &right, resultType, '%');
/* now they are the same size */
ic = newiCode ('%', left, right);
// should we really do this? is this ANSI?
return geniCodeDivision (result,
- operandFromLit (getSize (ltype->next)));
+ operandFromLit (getSize (ltype->next)),
+ FALSE);
}
/*-----------------------------------------------------------------*/
/* geniCodeSubtract - generates code for subtraction */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeSubtract (operand * left, operand * right)
+static operand *
+geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int isarray = 0;
{
isarray = left->isaddr;
right = geniCodeMultiply (right,
- operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+ operandFromLit (getSize (ltype->next)),
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
}
else
{ /* make them the same size */
- resType = usualBinaryConversions (&left, &right, FALSE, FALSE);
+ resType = usualBinaryConversions (&left, &right, resultType, '-');
}
ic = newiCode ('-', left, right);
/*-----------------------------------------------------------------*/
/* geniCodeAdd - generates iCode for addition */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeAdd (operand * left, operand * right, int lvl)
+static operand *
+geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
{
iCode *ic;
sym_link *resType;
size = operandFromLit (getSize (ltype->next));
SPEC_USIGN (getSpec (operandType (size))) = 1;
indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
- right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
+ right = geniCodeMultiply (right,
+ size,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
/* Even if right is a 'unsigned char',
the result will be a 'signed int' due to the promotion rules.
It doesn't make sense when accessing arrays, so let's fix it here: */
}
else
{ // make them the same size
- resType = usualBinaryConversions (&left, &right, FALSE, FALSE);
+ resType = usualBinaryConversions (&left, &right, resultType, '+');
}
/* if they are both literals then we know */
/*-----------------------------------------------------------------*/
/* geniCodeArray2Ptr - array to pointer */
/*-----------------------------------------------------------------*/
-operand *
+static operand *
geniCodeArray2Ptr (operand * op)
{
sym_link *optype = operandType (op);
/*-----------------------------------------------------------------*/
/* geniCodeArray - array access */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeArray (operand * left, operand * right,int lvl)
+static operand *
+geniCodeArray (operand * left, operand * right, int lvl)
{
iCode *ic;
operand *size;
left = geniCodeRValue (left, FALSE);
}
- return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
+ return geniCodeDerefPtr (geniCodeAdd (left,
+ right,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR,
+ lvl),
+ lvl);
}
size = operandFromLit (getSize (ltype->next));
SPEC_USIGN (getSpec (operandType (size))) = 1;
indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
- right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
+ right = geniCodeMultiply (right,
+ size,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
/* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
It doesn't make sense when accessing arrays, so let's fix it here: */
if (indexUnsigned)
SPEC_USIGN (getSpec (operandType (right))) = 1;
/* we can check for limits here */
+ /* already done in SDCCast.c
if (isOperandLiteral (right) &&
IS_ARRAY (ltype) &&
DCL_ELEM (ltype) &&
(operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
{
- werror (E_ARRAY_BOUND);
- right = operandFromLit (0);
+ werror (W_IDX_OUT_OF_BOUNDS,
+ (int) operandLitValue (right) / getSize (ltype->next),
+ DCL_ELEM (ltype));
}
+ */
ic = newiCode ('+', left, right);
/* geniCodeLeftShift - gen i code for left shift */
/*-----------------------------------------------------------------*/
operand *
-geniCodeLeftShift (operand * left, operand * right)
+geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
+ sym_link *resType;
ic = newiCode (LEFT_OP, left, right);
- IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
+
+ resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
+ IC_RESULT (ic) = newiTempOperand (resType, 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
}
}
}
- ctype = usualBinaryConversions (&left, &right, FALSE, FALSE);
+ ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
ic = newiCode (op, left, right);
IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
/*-----------------------------------------------------------------*/
value *
geniCodeParms (ast * parms, value *argVals, int *stack,
- sym_link * fetype, symbol * func,int lvl)
+ sym_link * ftype, int lvl)
{
iCode *ic;
operand *pval;
if (argVals==NULL) {
// first argument
- argVals=FUNC_ARGS(func->type);
+ argVals = FUNC_ARGS (ftype);
}
/* 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);
+ argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
+ argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
return argVals;
}
}
/* if register parm then make it a send */
- if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
- IFFUNC_ISBUILTIN(func->type))
+ if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
+ IFFUNC_ISBUILTIN(ftype))
{
ic = newiCode (SEND, pval, NULL);
ic->argreg = SPEC_ARGREG(parms->etype);
- ic->builtinSEND = FUNC_ISBUILTIN(func->type);
+ ic->builtinSEND = FUNC_ISBUILTIN(ftype);
ADDTOCHAIN (ic);
}
else
{
/* now decide whether to push or assign */
- if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
+ if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
{
/* assign */
iCode *ic;
operand *result;
sym_link *type, *etype;
+ sym_link *ftype;
int stack = 0;
if (!IS_FUNC(OP_SYMBOL(left)->type) &&
of overlaying function parameters */
geniCodeSEParms (parms,lvl);
+ ftype = operandType (left);
+ if (IS_CODEPTR (ftype))
+ ftype = ftype->next;
+
/* first the parameters */
- geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
+ geniCodeParms (parms, NULL, &stack, ftype, lvl);
/* now call : if symbol then pcall */
if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
ic = newiCode (CALL, left, NULL);
}
- type = copyLinkChain (operandType (left)->next);
+ type = copyLinkChain (ftype->next);
etype = getSpec (type);
SPEC_EXTR (etype) = 0;
IC_RESULT (ic) = result = newiTempOperand (type, 1);
/* if the min is not zero then we no make it zero */
if (min)
{
- cond = geniCodeSubtract (cond, operandFromLit (min));
+ cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
if (!IS_LITERAL(getSpec(operandType(cond))))
setOperandType (cond, UCHARTYPE);
}
/*-----------------------------------------------------------------*/
/* geniCodeArrayInit - intermediate code for array initializer */
/*-----------------------------------------------------------------*/
-static void
+static void
geniCodeArrayInit (ast * tree, operand *array)
{
iCode *ic;
case '/':
return geniCodeDivision (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
case '%':
return geniCodeModulus (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
case '*':
if (right)
return geniCodeMultiply (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
else
return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
case '-':
if (right)
return geniCodeSubtract (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
else
return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
case '+':
if (right)
return geniCodeAdd (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE),lvl);
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype),
+ lvl);
else
return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
case LEFT_OP:
return geniCodeLeftShift (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
case RIGHT_OP:
return geniCodeRightShift (geniCodeRValue (left, FALSE),
geniCodeAssign (left,
geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
FALSE),
- geniCodeRValue (right, FALSE),FALSE), 0);
+ geniCodeRValue (right, FALSE), FALSE),
+ getResultTypeFromType (tree->ftype));
case DIV_ASSIGN:
return
geniCodeAssign (left,
geniCodeDivision (geniCodeRValue (operandFromOperand (left),
FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0);
case MOD_ASSIGN:
return
geniCodeAssign (left,
geniCodeModulus (geniCodeRValue (operandFromOperand (left),
FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0);
case ADD_ASSIGN:
{
sym_link *rtype = operandType (right);
return geniCodeAssign (left,
geniCodeAdd (geniCodeRValue (operandFromOperand (left),
FALSE),
- right,lvl), 0);
+ right,
+ getResultTypeFromType (tree->ftype),
+ lvl),
+ 0);
}
case SUB_ASSIGN:
{
geniCodeAssign (left,
geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
FALSE),
- right), 0);
+ right,
+ getResultTypeFromType (tree->ftype)),
+ 0);
}
case LEFT_ASSIGN:
return
geniCodeAssign (left,
geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
,FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0);
case RIGHT_ASSIGN:
return
geniCodeAssign (left,