PRINTFUNC (picJumpTable);
PRINTFUNC (picInline);
PRINTFUNC (picReceive);
+PRINTFUNC (picDummyRead);
iCodeTable codeTable[] =
{
{RECEIVE, "recv", picReceive, NULL},
{SEND, "send", picGenericOne, NULL},
{ARRAYINIT, "arrayInit", picGenericOne, NULL},
+ {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, 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: "char c=200" is not allowed (evaluates to -56)
*/
-void checkConstantRange(sym_link *ltype, value *val, char *msg,
+void checkConstantRange(sym_link *ltype, value *val, char *msg,
int pedantic) {
double max;
int warnings=0;
if (SPEC_NOUN (opetype) == V_FLOAT)
fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
else
- fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
+ fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
printTypeChain (operandType (op), file);
fprintf (file, "}");
break;
fprintf (of, "\n");
}
+PRINTFUNC (picDummyRead)
+{
+ fprintf (of, "\t");
+ fprintf (of, "%s ", s);
+ printOperand (IC_RIGHT (ic), of);
+ fprintf (of, "\n");
+}
+
/*-----------------------------------------------------------------*/
/* piCode - prints one iCode */
/*-----------------------------------------------------------------*/
-int
+int
piCode (void *item, FILE * of)
{
iCode *ic = item;
/*-----------------------------------------------------------------*/
/* printiCChain - prints intermediate code for humans */
/*-----------------------------------------------------------------*/
-void
+void
printiCChain (iCode * icChain, FILE * of)
{
iCode *loop;
iCodeTable *
getTableEntry (int oper)
{
- int i;
+ unsigned i;
for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
if (oper == codeTable[i].icode)
/*-----------------------------------------------------------------*/
/* operandLitValue - literal value of an operand */
/*-----------------------------------------------------------------*/
-double
+double
operandLitValue (operand * op)
{
assert (isOperandLiteral (op));
}
/*-----------------------------------------------------------------*/
-/* operandOperation - perforoms operations on operands */
+/* operandOperation - performs operations on operands */
/*-----------------------------------------------------------------*/
operand *
operandOperation (operand * left, operand * right,
{
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));
+ ret = getSpec(operandType(right));
}
switch (op)
operandLitValue (right)));
break;
case '*':
+ /*
retval = operandFromValue (valCastLiteral (type,
operandLitValue (left) *
operandLitValue (right)));
+ This could be all we've to do, but with gcc we've to take care about
+ overflows. Two examples:
+ ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
+ significant bits are lost (52 in fraction, 63 bits would be
+ necessary to keep full precision).
+ If the resulting double value is greater than ULONG_MAX (resp.
+ USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
+ */
+
+ /* if it is not a specifier then we can assume that */
+ /* it will be an unsigned long */
+ if (IS_INT (type) ||
+ !IS_SPEC (type))
+ {
+ /* long is handled here, because it can overflow with double */
+ if (SPEC_LONG (type) ||
+ !IS_SPEC (type))
+ /* signed and unsigned mul are the same, as long as the precision
+ of the result isn't bigger than the precision of the operands. */
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD) operandLitValue (left) *
+ (TYPE_UDWORD) operandLitValue (right)));
+ else if (SPEC_USIGN (type)) /* unsigned int */
+ {
+ /* unsigned int is handled here in order to detect overflow */
+ TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
+ (TYPE_UWORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
+ if (!options.lessPedantic &&
+ ul != (TYPE_UWORD) ul)
+ werror (W_INT_OVL);
+ }
+ else /* int */
+ {
+ /* int is handled here in order to detect overflow */
+ TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
+ (TYPE_WORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
+ if (!options.lessPedantic &&
+ l != (TYPE_WORD) l)
+ werror (W_INT_OVL);
+ }
+ }
+ else
+ /* all others go here: */
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) *
+ operandLitValue (right)));
break;
case '/':
- if ((unsigned long) operandLitValue (right) == 0)
+ if ((TYPE_UDWORD) operandLitValue (right) == 0)
{
werror (E_DIVIDE_BY_ZERO);
retval = right;
operandLitValue (right)));
break;
case '%':
- if ((unsigned long) operandLitValue (right) == 0) {
+ if ((TYPE_UDWORD) 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)));
-
+ else
+ {
+ if (SPEC_USIGN(let) || SPEC_USIGN(ret))
+ /* one of the operands is unsigned */
+ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
+ (TYPE_UDWORD) operandLitValue (right));
+ else
+ /* both operands are signed */
+ retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
+ (TYPE_DWORD) 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)));
+ /* The number of left shifts is always unsigned. Signed doesn't make
+ sense here. Shifting by a negative number is impossible. */
+ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) <<
+ (TYPE_UDWORD) operandLitValue (right));
break;
- 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);
+ case RIGHT_OP:
+ /* The number of right shifts is always unsigned. Signed doesn't make
+ sense here. Shifting by a negative number is impossible. */
+ if (SPEC_USIGN(let))
+ /* unsigned: logic shift right */
+ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
+ (TYPE_UDWORD) operandLitValue (right));
+ else
+ /* signed: arithmetic shift right */
+ retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
+ (TYPE_UDWORD) operandLitValue (right));
break;
- }
case EQ_OP:
- retval = operandFromLit (operandLitValue (left) ==
- operandLitValue (right));
+ /* this op doesn't care about signedness */
+ {
+ TYPE_UDWORD l, r;
+
+ l = (TYPE_UDWORD) operandLitValue (left);
+ if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR)
+ l &= 0xff;
+ else if (!SPEC_LONG (OP_VALUE(left)->type))
+ l &= 0xffff;
+ r = (TYPE_UDWORD) operandLitValue (right);
+ if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR)
+ r &= 0xff;
+ else if (!SPEC_LONG (OP_VALUE(right)->type))
+ r &= 0xffff;
+ retval = operandFromLit (l == r);
+ }
break;
case '<':
retval = operandFromLit (operandLitValue (left) <
operandLitValue (right));
break;
case BITWISEAND:
- retval = operandFromLit ((long)operandLitValue(left) &
- (long)operandLitValue(right));
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) &
+ (TYPE_UDWORD)operandLitValue(right)));
break;
case '|':
- retval = operandFromLit ((long)operandLitValue (left) |
- (long)operandLitValue (right));
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) |
+ (TYPE_UDWORD)operandLitValue(right)));
break;
case '^':
- retval = operandFromLit ((long)operandLitValue (left) ^
- (long)operandLitValue (right));
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) ^
+ (TYPE_UDWORD)operandLitValue(right)));
break;
case AND_OP:
retval = operandFromLit (operandLitValue (left) &&
break;
case RRC:
{
- long i = (long) operandLitValue (left);
+ TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
(i << 1));
break;
case RLC:
{
- long i = (long) operandLitValue (left);
+ TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
(i >> 1));
break;
case UNARYMINUS:
- retval = operandFromLit (-1 * operandLitValue (left));
+ retval = operandFromValue (valCastLiteral (type,
+ -1 * operandLitValue (left)));
break;
case '~':
- retval = operandFromLit (~((long) operandLitValue (left)));
+ retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
break;
case '!':
/*-----------------------------------------------------------------*/
/* isOperandEqual - compares two operand & return 1 if they r = */
/*-----------------------------------------------------------------*/
-int
+int
isOperandEqual (operand * left, operand * right)
{
/* if the pointers are equal then they are equal */
/* 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
+ /* 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)) &&
+ !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
(port->support.muldiv == 1)))
{
if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
{
- checkConstantRange(ltype,
+ checkConstantRange(ltype,
OP_VALUE(right), "compare operation", 1);
}
/*-----------------------------------------------------------------*/
/* geniCodeSwitch - changes a switch to a if statement */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeSwitch (ast * tree,int lvl)
{
iCode *ic;
return geniCodeRightShift (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE));
case CAST:
-#if 1 // just in case Paul detects another sloc regression again :)
+#if 0 // this indeed needs a second thought
{
operand *op;
}
return op;
}
-#else // bug #604575
+#else // bug #604575, is it a bug ????
return geniCodeCast (operandType (left),
geniCodeRValue (right, FALSE), FALSE);
#endif
case '~':
- case '!':
case RRC:
case RLC:
return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
+ case '!':
case GETHBIT:
{
operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);