+2004-01-01 Bernhard Held <bernhard@bernhardheld.de>
+
+ Many signedness and type propagation fixes:
+ * src/SDCCicode.c: made geniCodeCast() static
+ replaced SPEC_ by IS_ (cosmetic)
+ (operandOperation): fixed div and mod operation
+ (usualBinaryConversions): added support for promotion of char
+ (geniCodeMultiply): replaced (unsigned long) by (TYPE_UDWORD)
+ (geniCodeDivision): replaced (unsigned long) by (TYPE_UDWORD)
+ (geniCodeAdd): an array index will stay unsigned, even if promoted
+ from char to int
+ (geniCodeArray): ditto
+ * src/SDCCicode.h: made geniCodeCast() static: removed prototype
+ * src/SDCCsymt.c (computeType): added more support for char;
+ promotion of char is selectable by promoteCharToInt, fixed signedness
+ for all cases
+ (powof2): replaced (unsigned long) by (TYPE_UDWORD)
+ * src/SDCCsymt.h (powof2): replaced (unsigned long) by (TYPE_UDWORD)
+ * src/SDCCval (val*): replaced signedness calculation by
+ computeType()
+ rearranged if-branches (cosmetic)
+ (valShift): added warning W_SHIFT_CHANGED
+ (valCompare): fixed problem with different types
+ * src/hc08/rallo.c (leastUsedLR): fixed gcc 3.3 warning
+ * support/regression/tests/literalop.c: added many cases
+ * support/regression/tests/ast_constant_folding.c: changed finally to
+ 'unsigned int'
+ * .version: new year, new version: 2.3.7
+
2004-01-01 Erik Petrich <epetrich@ivorytower.norman.ok.us>
* src/SDCCsymt.h: missing from yesterday's commits
2003-12-22 Frieder Ferlemann <Frieder.Ferlemann@web.de>
- * src/mcs51/gen.c (genPlus): added special handling for 256 byte
+ * src/mcs51/gen.c (genPlus): added special handling for 256 byte
aligned xdata arrays. Erik helped me with the if clause.
2003-12-20 Erik Petrich <epetrich@ivorytower.norman.ok.us>
2003-12-13 Frieder Ferlemann <Frieder.Ferlemann@web.de>
- * src/mcs51/main.c: fixed bug #737001 for the mcs51. SDCC clears
- xdata and data memory on startup. Set the environment variable
+ * src/mcs51/main.c: fixed bug #737001 for the mcs51. SDCC clears
+ xdata and data memory on startup. Set the environment variable
SDCC_NOGENRAMCLEAR to disable this.
* src/mcs51/peephole.def,
* src/ds390/peephole.def: using the atomic test and clear instruction jbc
/*-----------------------------------------------------------------*/
/* isAstEqual - compares two asts & returns 1 if they are equal */
/*-----------------------------------------------------------------*/
-int
+static int
isAstEqual (ast * t1, ast * t2)
{
if (!t1 && !t2)
}
TTYPE (tree) =
- computeType (LTYPE (tree), RTYPE (tree));
+ computeType (LTYPE (tree), RTYPE (tree), FALSE);
TETYPE (tree) = getSpec (TTYPE (tree));
/* if left is a literal exchange left & right */
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
/*------------------------------------------------------------------*/
/*----------------------------*/
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ TRUE));
/* if right is a literal and */
/* left is also a division by a literal then */
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ TRUE));
return tree;
/*------------------------------------------------------------------*/
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ TRUE));
/* promote result to int if left & right are char
this will facilitate hardware multiplies 8bit x 8bit = 16bit */
+ /* now done by computeType
if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) {
SPEC_NOUN(TETYPE(tree)) = V_INT;
}
+ */
return tree;
else
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
return tree;
/*------------------------------------------------------------------*/
else
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
LRVAL (tree) = RRVAL (tree) = 1;
}
/* if unsigned value < 0 then always false */
/* if (unsigned value) > 0 then (unsigned value) */
- if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree)) &&
- ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) {
-
- if (tree->opval.op == '<') {
+ if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree)) &&
+ ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
+ {
+ if (tree->opval.op == '<')
+ {
return tree->right;
- }
- if (tree->opval.op == '>') {
+ }
+ if (tree->opval.op == '>')
+ {
return tree->left;
- }
- }
+ }
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) &&
goto errorTreeReturn;
}
- TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree));
+ TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
werror (E_CODE_WRITE, "-=");
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
werror (E_CODE_WRITE, "+=");
fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
else
fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
- fprintf(outfile,", 0x%x, %g", (TYPE_UDWORD) floatFromVal(tree->opval.val),
+ fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
floatFromVal(tree->opval.val));
} else if (tree->opval.val->sym) {
/* if the undefined flag is set then give error message */
operand *geniCodeDerefPtr (operand *,int);
int isLvaluereq(int lvl);
void setOClass (sym_link * ptr, sym_link * spec);
+static operand *geniCodeCast (sym_link *, operand *, bool);
#define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
/* forward definition of ic print functions */
max = pow ((double)2.0, (double)bitsForType(ltype));
- if (SPEC_LONG(val->type)) {
- if (SPEC_USIGN(val->type)) {
+ if (IS_LONG(val->type)) {
+ if (IS_UNSIGNED(val->type)) {
v=SPEC_CVAL(val->type).v_ulong;
} else {
v=SPEC_CVAL(val->type).v_long;
}
} else {
- if (SPEC_USIGN(val->type)) {
+ if (IS_UNSIGNED(val->type)) {
v=SPEC_CVAL(val->type).v_uint;
} else {
v=SPEC_CVAL(val->type).v_int;
pedantic=2;
#endif
- if (SPEC_NOUN(ltype)==FLOAT) {
+ if (IS_FLOAT(ltype)) {
// anything will do
return;
}
- if (!SPEC_USIGN(val->type) && v<0) {
+ if (!IS_UNSIGNED(val->type) && v<0) {
negative=1;
- if (SPEC_USIGN(ltype) && (pedantic>1)) {
+ if (IS_UNSIGNED(ltype) && (pedantic>1)) {
warnings++;
}
v=-v;
}
// if very pedantic: "char c=200" is not allowed
- if (pedantic>1 && !SPEC_USIGN(ltype)) {
+ if (pedantic>1 && !IS_UNSIGNED(ltype)) {
max = max/2 + negative;
}
#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",
+ IS_UNSIGNED(ltype) ? "unsigned" : "signed",
nounName(ltype), msg);
werror (W_CONST_RANGE, message);
case VALUE:
opetype = getSpec (operandType (op));
- if (SPEC_NOUN (opetype) == V_FLOAT)
+ if (IS_FLOAT (opetype))
fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
else
fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
ic = ic->next;
(*pcount)++;
}
-
+
ic->generated = 1;
/* make sure this is a builtin function call */
assert(IS_SYMOP(IC_LEFT(ic)));
!IS_SPEC (type))
{
/* long is handled here, because it can overflow with double */
- if (SPEC_LONG (type) ||
+ if (IS_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 */
+ else if (IS_UNSIGNED (type)) /* unsigned int */
{
/* unsigned int is handled here in order to detect overflow */
TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
}
else
- retval = operandFromValue (valCastLiteral (type,
- operandLitValue (left) /
- operandLitValue (right)));
+ {
+ if (IS_UNSIGNED (type))
+ {
+ SPEC_USIGN (let) = 1;
+ SPEC_USIGN (ret) = 1;
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD) operandLitValue (left) /
+ (TYPE_UDWORD) operandLitValue (right)));
+ }
+ else
+ {
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) /
+ operandLitValue (right)));
+ }
+ }
break;
case '%':
- if ((TYPE_UDWORD) operandLitValue (right) == 0) {
+ if ((TYPE_UDWORD) operandLitValue (right) == 0)
+ {
werror (E_DIVIDE_BY_ZERO);
retval = right;
- }
+ }
else
{
- if (SPEC_USIGN(let) || SPEC_USIGN(ret))
- /* one of the operands is unsigned */
+ if (IS_UNSIGNED (type))
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));
}
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))
+ if (IS_UNSIGNED(let))
/* unsigned: logic shift right */
retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
(TYPE_UDWORD) operandLitValue (right));
TYPE_UDWORD l, r;
l = (TYPE_UDWORD) operandLitValue (left);
- if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR)
+ if (IS_CHAR(OP_VALUE(left)->type))
l &= 0xff;
- else if (!SPEC_LONG (OP_VALUE(left)->type))
+ else if (!IS_LONG (OP_VALUE(left)->type))
l &= 0xffff;
r = (TYPE_UDWORD) operandLitValue (right);
- if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR)
+ if (IS_CHAR(OP_VALUE(right)->type))
r &= 0xff;
- else if (!SPEC_LONG (OP_VALUE(right)->type))
+ else if (!IS_LONG (OP_VALUE(right)->type))
r &= 0xffff;
retval = operandFromLit (l == r);
}
/*-----------------------------------------------------------------*/
/* perform "usual binary conversions" */
/*-----------------------------------------------------------------*/
-sym_link *
-usualBinaryConversions (operand ** op1, operand ** op2)
+static sym_link *
+usualBinaryConversions (operand ** op1, operand ** op2,
+ bool promoteCharToInt, bool isMul)
{
sym_link *ctype;
sym_link *rtype = operandType (*op2);
sym_link *ltype = operandType (*op1);
-
- ctype = computeType (ltype, rtype);
+
+ ctype = computeType (ltype, rtype, promoteCharToInt);
+
+ /* 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_CHAR (getSpec (ltype))
+ && IS_CHAR (getSpec (rtype))
+ && !(IS_UNSIGNED (getSpec (rtype)) ^ IS_UNSIGNED (getSpec (ltype)))
+ && IS_INT (getSpec (ctype)))
+ return ctype;
*op1 = geniCodeCast (ctype, *op1, TRUE);
*op2 = geniCodeCast (ctype, *op2, TRUE);
-
+
return ctype;
}
/*-----------------------------------------------------------------*/
/* geniCodeCast - changes the value from one type to another */
/*-----------------------------------------------------------------*/
-operand *
+static operand *
geniCodeCast (sym_link * type, operand * op, bool implicit)
{
iCode *ic;
/* 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)));
+ {
+ 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_INTEGRAL(optype)) {
+ // maybe this is NULL, than it's ok.
if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
// no way to set the storage
errors++;
}
}
- } else {
+ } else {
// shouldn't do that with float, array or structure unless to void
- if (!IS_VOID(getSpec(type)) &&
+ if (!IS_VOID(getSpec(type)) &&
!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
werror(E_INCOMPAT_TYPES);
errors++;
if (port->s.gptr_size > port->s.fptr_size /*!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 (implicit) { // if not to generic, they have to match
if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
werror(E_INCOMPAT_PTYPES);
errors++;
((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);
+ (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
IC_RESULT (ic)->isaddr = 0;
}
else
/*-----------------------------------------------------------------*/
/* geniCodeLabel - will create a Label */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeLabel (symbol * label)
{
iCode *ic;
/*-----------------------------------------------------------------*/
/* geniCodeGoto - will create a Goto */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeGoto (symbol * label)
{
iCode *ic;
/* geniCodeMultiply - gen intermediate code for multiplication */
/*-----------------------------------------------------------------*/
operand *
-geniCodeMultiply (operand * left, operand * right,int resultIsInt)
+geniCodeMultiply (operand * left, operand * right, int resultIsInt)
{
iCode *ic;
int p2 = 0;
right->operand.valOperand));
if (IS_LITERAL(retype)) {
- p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
+ p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
}
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, resultIsInt, TRUE);
#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 */
sym_link *ltype = operandType (left);
sym_link *letype = getSpec (ltype);
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, TRUE, FALSE);
/* 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)
+ IS_UNSIGNED(letype) &&
+ (p2 = powof2 ((TYPE_UDWORD)
floatFromVal (right->operand.valOperand)))) {
ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
}
return operandFromValue (valMod (left->operand.valOperand,
right->operand.valOperand));
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, TRUE, FALSE);
/* now they are the same size */
ic = newiCode ('%', left, right);
}
else
{ /* make them the same size */
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, FALSE, FALSE);
}
ic = newiCode ('-', left, right);
sym_link *resType;
operand *size;
int isarray = 0;
+ bool indexUnsigned;
LRTYPE;
/* if the right side is LITERAL zero */
{
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));
- }
+ if (getSize (ltype->next) != 1)
+ {
+ size = operandFromLit (getSize (ltype->next));
+ indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
+ right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
+ /* 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;
+ }
resType = copyLinkChain (ltype);
}
else
{ // make them the same size
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, FALSE, FALSE);
}
/* if they are both literals then we know */
{
iCode *ic;
sym_link *ltype = operandType (left);
-
+ bool indexUnsigned;
+
if (IS_PTR (ltype))
{
if (IS_PTR (ltype->next) && left->isaddr)
{
left = geniCodeRValue (left, FALSE);
}
-
+
return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
}
-
+ indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
right = geniCodeMultiply (right,
operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
-
+ /* 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 */
if (isOperandLiteral (right) &&
IS_ARRAY (ltype) &&
}
/*-----------------------------------------------------------------*/
-/* geniCodeStruct - generates intermediate code for structres */
+/* geniCodeStruct - generates intermediate code for structures */
/*-----------------------------------------------------------------*/
operand *
geniCodeStruct (operand * left, operand * right, bool islval)
}
}
- ctype = usualBinaryConversions (&left, &right);
+ ctype = usualBinaryConversions (&left, &right, FALSE, FALSE);
ic = newiCode (op, left, right);
IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
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)))
+ if (!(min == 0 && IS_UNSIGNED (cetype)))
{
boundary = geniCodeLogic (cond, operandFromLit (min), '<');
ic = newiCodeCondition (boundary, falseLabel, NULL);
int isOperandGlobal (operand *);
void printiCChain (iCode *, FILE *);
operand *ast2iCode (ast *,int);
-operand *geniCodeCast (sym_link *, operand *, bool);
operand *geniCodePtrPtrSubtract (operand *, operand *);
void initiCode ();
iCode *iCodeFromAst (ast *);
}
}
}
-
+
/* automatic symbols cannot be given */
/* an absolute address ignore it */
if (sym->level &&
/* computeType - computes the resultant type from two types */
/*------------------------------------------------------------------*/
sym_link *
-computeType (sym_link * type1, sym_link * type2)
+computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
{
sym_link *rType;
sym_link *reType;
rType = copyLinkChain (type2);
reType = getSpec (rType);
-#if 0
- if (SPEC_NOUN (reType) == V_CHAR)
+
+ /* avoid conflicting types */
+ reType->select.s._signed = 0;
+
+ if (IS_CHAR (reType) && promoteCharToInt)
SPEC_NOUN (reType) = V_INT;
-#endif
- /* if either of them unsigned but not val then make this unsigned */
- if ((SPEC_USIGN (etype1) || SPEC_USIGN (etype2)) &&
- !IS_FLOAT (reType))
+ if ( ( ( SPEC_USIGN (etype1)
+ && (getSize (etype1) >= getSize (reType)))
+ || ( SPEC_USIGN (etype2)
+ && (getSize (etype2) >= getSize (reType))))
+ && !IS_FLOAT (reType))
SPEC_USIGN (reType) = 1;
else
SPEC_USIGN (reType) = 0;
/*-----------------------------------------------------------------*/
/* powof2 - returns power of two for the number if number is pow 2 */
/*-----------------------------------------------------------------*/
-int
-powof2 (unsigned long num)
+int
+powof2 (TYPE_UDWORD num)
{
int nshifts = 0;
int n1s = 0;
static char *
_mangleFunctionName(char *in)
{
- if (port->getMangledFunctionName)
+ if (port->getMangledFunctionName)
{
return port->getMangledFunctionName(in);
}
void addSymChain (symbol *);
sym_link *structElemType (sym_link *, value *);
symbol *getStructElement (structdef *, symbol *);
-sym_link *computeType (sym_link *, sym_link *);
+sym_link *computeType (sym_link *, sym_link *, bool promoteCharToInt);
void processFuncArgs (symbol *);
int isSymbolEqual (symbol *, symbol *);
-int powof2 (unsigned long);
+int powof2 (TYPE_UDWORD);
void printTypeChain (sym_link *, FILE *);
void printTypeChainRaw (sym_link *, FILE *);
void initCSupport ();
/*------------------------------------------------------------------*/
/* resolveIvalSym - resolve symbols in initial values */
/*------------------------------------------------------------------*/
-void
+void
resolveIvalSym (initList * ilist)
{
if (!ilist)
static value *cheapestVal (value *val)
{
- /* - signed/unsigned must no be changed.
+ /* - signed/unsigned must not be changed.
- long must not be changed.
the only possible reduction is from signed int to signed char,
IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */
SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
- /* both signed char and unsigned char are promoted to signed int */
- if (IS_CHAR (lval->etype))
- {
- SPEC_USIGN (lval->etype) = 0;
- SPEC_NOUN (lval->etype) = V_INT;
- }
- if (IS_CHAR (rval->etype))
- {
- SPEC_USIGN (rval->etype) = 0;
- SPEC_NOUN (rval->etype) = V_INT;
- }
- SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
+ SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype,
+ rval->etype,
+ TRUE));
if (IS_FLOAT (val->type))
SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval);
/* signed and unsigned mul are the same, as long as the precision of the
else if (SPEC_LONG (val->type))
SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) *
(TYPE_UDWORD) floatFromVal (rval);
- else if (SPEC_USIGN (val->type)) /* unsigned */
+ else if (SPEC_USIGN (val->type)) /* unsigned int */
{
TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) *
(TYPE_UWORD) floatFromVal (rval);
if (ul != (TYPE_UWORD) ul)
werror (W_INT_OVL);
}
- else /* int */
+ else /* signed int */
{
TYPE_DWORD l = (TYPE_WORD) floatFromVal (lval) *
(TYPE_WORD) floatFromVal (rval);
if (l != (TYPE_WORD) l)
werror (W_INT_OVL);
}
- return cheapestVal(val);
+ return cheapestVal (val);
}
/*------------------------------------------------------------------*/
SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
SPEC_SCLS (val->etype) = S_LITERAL;
- /* both signed char and unsigned char are promoted to signed int */
- if (IS_CHAR (lval->etype))
- {
- SPEC_USIGN (lval->etype) = 0;
- SPEC_NOUN (lval->etype) = V_INT;
- }
- if (IS_CHAR (rval->etype))
- {
- SPEC_USIGN (rval->etype) = 0;
- SPEC_NOUN (rval->etype) = V_INT;
- }
- SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
+ SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype,
+ rval->etype,
+ TRUE));
if (IS_FLOAT (val->type))
SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
+ else if (SPEC_LONG (val->type))
+ {
+ if (SPEC_USIGN (val->type))
+ SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) /
+ (TYPE_UDWORD) floatFromVal (rval);
+ else
+ SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) /
+ (TYPE_DWORD) floatFromVal (rval);
+ }
else
{
- if (SPEC_LONG (val->type))
- {
- if (SPEC_USIGN (val->type))
- SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) /
- (TYPE_UDWORD) floatFromVal (rval);
- else
- SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) /
- (TYPE_DWORD) floatFromVal (rval);
- }
+ if (SPEC_USIGN (val->type))
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) /
+ (TYPE_UWORD) floatFromVal (rval);
else
- {
- if (SPEC_USIGN (val->type)) {
- SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) /
- (TYPE_UWORD) floatFromVal (rval);
- } else {
- SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) /
- (TYPE_WORD) floatFromVal (rval);
- }
- }
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) /
+ (TYPE_WORD) floatFromVal (rval);
}
- return cheapestVal(val);
+ return cheapestVal (val);
}
/*------------------------------------------------------------------*/
val->type = val->etype = newLink (SPECIFIER);
SPEC_NOUN (val->type) = V_INT; /* type is int */
SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */
- SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
+ SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype,
+ rval->etype,
+ TRUE));
if (SPEC_LONG (val->type))
{
}
else
{
- if (SPEC_USIGN (val->type)) {
- SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) %
- (TYPE_UWORD) floatFromVal (rval);
- } else {
- SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) %
- (TYPE_WORD) floatFromVal (rval);
- }
+ if (SPEC_USIGN (val->type))
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) %
+ (TYPE_UWORD) floatFromVal (rval);
+ else
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) %
+ (TYPE_WORD) floatFromVal (rval);
}
-
- return cheapestVal(val);
+ return cheapestVal (val);
}
/*------------------------------------------------------------------*/
IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */
SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
- /* both signed char and unsigned char are promoted to signed int */
- if (IS_CHAR (lval->etype))
- {
- SPEC_USIGN (lval->etype) = 0;
- SPEC_NOUN (lval->etype) = V_INT;
- }
- if (IS_CHAR (rval->etype))
- {
- SPEC_USIGN (rval->etype) = 0;
- SPEC_NOUN (rval->etype) = V_INT;
- }
- SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
+ SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype,
+ rval->etype,
+ TRUE));
if (IS_FLOAT (val->type))
SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval);
+ else if (SPEC_LONG (val->type))
+ {
+ if (SPEC_USIGN (val->type))
+ SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) +
+ (TYPE_UDWORD) floatFromVal (rval);
+ else
+ SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) +
+ (TYPE_DWORD) floatFromVal (rval);
+ }
else
{
- if (SPEC_LONG (val->type))
- {
- if (SPEC_USIGN (val->type))
- SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) +
- (TYPE_UDWORD) floatFromVal (rval);
- else
- SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) +
- (TYPE_DWORD) floatFromVal (rval);
- }
+ if (SPEC_USIGN (val->type))
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) +
+ (TYPE_UWORD) floatFromVal (rval);
else
- {
- if (SPEC_USIGN (val->type)) {
- SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) +
- (TYPE_UWORD) floatFromVal (rval);
- } else {
- SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) +
- (TYPE_WORD) floatFromVal (rval);
- }
- }
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) +
+ (TYPE_WORD) floatFromVal (rval);
}
- return cheapestVal(val);
+ return cheapestVal (val);
}
/*------------------------------------------------------------------*/
IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */
SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
- /* both signed char and unsigned char are promoted to signed int */
- if (IS_CHAR (lval->etype))
- {
- SPEC_USIGN (lval->etype) = 0;
- SPEC_NOUN (lval->etype) = V_INT;
- }
- if (IS_CHAR (rval->etype))
- {
- SPEC_USIGN (rval->etype) = 0;
- SPEC_NOUN (rval->etype) = V_INT;
- }
- SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
+ SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype,
+ rval->etype,
+ FALSE));
if (IS_FLOAT (val->type))
SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval);
- else
+ else if (SPEC_LONG (val->type))
{
- if (SPEC_LONG (val->type))
- {
- if (SPEC_USIGN (val->type))
- SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) -
- (TYPE_UDWORD) floatFromVal (rval);
- else
- SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) -
- (TYPE_DWORD) floatFromVal (rval);
- }
+ if (SPEC_USIGN (val->type))
+ SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) -
+ (TYPE_UDWORD) floatFromVal (rval);
else
- {
- if (SPEC_USIGN (val->type)) {
- SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) -
- (TYPE_UWORD) floatFromVal (rval);
- } else {
- SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) -
- (TYPE_WORD) floatFromVal (rval);
- }
- }
+ SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) -
+ (TYPE_DWORD) floatFromVal (rval);
}
- return cheapestVal(val);
+ else
+ {
+ if (SPEC_USIGN (val->type))
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) -
+ (TYPE_UWORD) floatFromVal (rval);
+ else
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) -
+ (TYPE_WORD) floatFromVal (rval);
+ }
+ return cheapestVal (val);
}
/*------------------------------------------------------------------*/
SPEC_USIGN (val->type) = SPEC_USIGN (lval->etype);
SPEC_LONG (val->type) = SPEC_LONG (lval->etype);
+ if (getSize (lval->type) * 8 <= (TYPE_UDWORD) floatFromVal (rval) &&
+ /* left shift */
+ (lr ||
+ /* right shift and unsigned */
+ (!lr && SPEC_USIGN (rval->type))))
+ {
+ werror (W_SHIFT_CHANGED, (lr ? "left" : "right"));
+ }
+
if (SPEC_LONG (val->type))
{
if (SPEC_USIGN (val->type))
(TYPE_WORD) floatFromVal (lval) >> (TYPE_UWORD) floatFromVal (rval);
}
}
- return cheapestVal(val);
+ return cheapestVal (val);
}
/*------------------------------------------------------------------*/
TYPE_UDWORD l, r;
l = (TYPE_UDWORD) floatFromVal (lval);
- if (SPEC_NOUN(lval->type) == V_CHAR)
- l &= 0xffff; /* promote to int */
- else if (!SPEC_LONG (lval->type))
- l &= 0xffff;
-
r = (TYPE_UDWORD) floatFromVal (rval);
- if (SPEC_NOUN(rval->type) == V_CHAR)
- r &= 0xffff; /* promote to int */
- else if (!SPEC_LONG (rval->type))
- r &= 0xffff;
-
+ /* 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 (lval->etype) &&
+ !IS_LONG (rval->etype))
+ {
+ r = (TYPE_UWORD) r;
+ l = (TYPE_UWORD) l;
+ }
SPEC_CVAL (val->type).v_int = l == r;
}
break;
TYPE_UDWORD l, r;
l = (TYPE_UDWORD) floatFromVal (lval);
- if (SPEC_NOUN(lval->type) == V_CHAR)
- l &= 0xffff; /* promote to int */
- else if (!SPEC_LONG (lval->type))
- l &= 0xffff;
-
r = (TYPE_UDWORD) floatFromVal (rval);
- if (SPEC_NOUN(rval->type) == V_CHAR)
- r &= 0xffff; /* promote to int */
- else if (!SPEC_LONG (rval->type))
- r &= 0xffff;
-
+ /* 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 (lval->etype) &&
+ !IS_LONG (rval->etype))
+ {
+ r = (TYPE_UWORD) r;
+ l = (TYPE_UWORD) l;
+ }
SPEC_CVAL (val->type).v_int = l != r;
}
break;
}
- setToNull ((void **) &sset);
+ setToNull ((void *) &sset);
sym->blockSpil = 0;
return sym;
}
unsigned
foo_div (void)
{
- return 33971 / i / 5 / i / i / 12;
+ return 33971u / i / 5 / i / i / 12;
}
unsigned
typedef signed {type} stype;
typedef unsigned {type} utype;
-#define _{type}
-
#if defined(PORT_HOST) || defined(SDCC_z80) || defined(SDCC_gbz80)
# define idata
# define code
volatile char is8 = 8;
-signed char sc;
-signed short ss;
-signed LONG sl;
+ signed char sc;
+ signed short ss;
+ signed LONG sl;
unsigned char uc;
unsigned short us;
unsigned LONG ul;
void
testOpOp(void)
{
- /* mul ast */
+ /* mul signedness: usualBinaryConversions() */
+ vsc = 0x7f;
+ vuc = 0xfe;
+
+ sc = vsc * vsc;
+ ASSERT(sc == 1);
+ sc = vuc * vsc;
+ ASSERT(sc == 2);
+ sc = vuc * vuc;
+ ASSERT(sc == 4);
+
+ ss = vsc * vsc;
+ ASSERT(ss == 0x3f01);
+ ss = vuc * vsc;
+ ASSERT(ss == 0x7e02);
+ ss = vuc * vuc;
+ ASSERT(ss == (short) 0xfc04);
+ /* after promotion the result of the multiplication is 'signed int', which overflows! */
+ if (sizeof (int) == 2)
+ ASSERT(vuc * vuc < 1);
+ else
+ {
+ vus = 0xfffe;
+ ASSERT(vus * vus < 1);
+ }
+
+ /* mul ast: valMult() */
ASSERT((stype) -3 * (stype) -1 == (stype) 3);
ASSERT((stype) -3 * (stype) 1 == (stype) -3);
ASSERT((stype) 3 * (stype) -1 == (stype) -3);
ASSERT(1 * 40000 * is8 == 320000); /* LONG */
ASSERT(1 * 0x4000 * is8 == (sizeof(int) == 2 ? 0 : 0x20000)); /* unsigned */
- ASSERT(-1 * 1 < 0);
- ASSERT(-1 * 1u > 0);
-
-
- /* mul icode */
+ ASSERT(-2 * 1 < 1); /* comparison with 0 is optimized, so let's use 1 instead */
+ ASSERT(-2 * 1u > 1);
+ ASSERT(0x7fffu * 2 > 1);
+ ASSERT(0x7fffffffu * 2 > 1);
+ if (sizeof (int) == 2)
+ ASSERT(0x7fff * (unsigned char) 2 < 1);
+ else
+ ASSERT(0x7fffffff * (unsigned char) 2 < 1);
+ ASSERT(0x7fffffff * (unsigned short) 2 < 1);
+
+ /* mul icode: operandOperation() */
s = -3;
ASSERT(s * (stype) -1 == (stype) 3);
ASSERT(s * (stype) 1 == (stype) -3);
ASSERT((signed short) -2 * (unsigned short) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffefff8));
ASSERT((signed LONG ) -2 * (unsigned LONG ) 0x8004 == 0xfffefff8);
-
-
+ /* div ast: valDiv() */
ASSERT((stype) -12 / (stype) -3 == (stype) 4);
ASSERT((stype) -12 / (stype) 3 == (stype) -4);
ASSERT((stype) 12 / (stype) -3 == (stype) -4);
-// ASSERT((stype) -12 / (utype) -3 == (stype) 4);
-// ASSERT((utype) -12 / (stype) -3 == (stype) 4);
-// ASSERT((utype) -12 / (utype) -3 == (stype) 4);
+ ASSERT((unsigned char ) -12 / (signed char ) -3 == (sizeof(int) == 2 ? 0xffaf : 0xffffffaf));
+ ASSERT((unsigned short) -12 / (signed short) -3 == (sizeof(int) == 2 ? 0 : 0xffffaaaf));
+ ASSERT((unsigned LONG ) -12 / (signed LONG ) -3 == 0);
+ ASSERT((utype) -12 / (stype) 3 == (stype) 0x55555551);
+ ASSERT((unsigned char ) 12 / (signed char ) -3 == -4);
+ ASSERT((unsigned short) 12 / (signed short) -3 == (sizeof(int) == 2 ? 0 : 0xfffffffc));
+ ASSERT((unsigned LONG ) 12 / (signed LONG ) -3 == 0);
+ ASSERT((stype) -12 / (utype) -3 == 0);
+ ASSERT((signed char ) -12 / (unsigned char ) 3 == -4);
+ ASSERT((signed short) -12 / (unsigned short) 3 == (sizeof(int) == 2 ? 0x5551 : -4));
+ ASSERT((signed LONG ) -12 / (unsigned LONG ) 3 == 0x55555551);
+ ASSERT((stype) 12 / (utype) -3 == 0);
ASSERT(12u / 3 * 10000 == 40000);
ASSERT(-1 / 1 < 0);
+ /* div icode: operandOperation() */
+ s = -12;
+ ASSERT(s / (stype) -3 == (stype) 4);
+ s = -12;
+ ASSERT(s / (stype) 3 == (stype) -4);
+ s = 12;
+ ASSERT(s / (stype) -3 == (stype) -4);
+
+ uc = -12;
+ ASSERT(uc / (signed char ) -3 == (sizeof(int) == 2 ? 0xffaf : 0xffffffaf));
+ us = -12;
+ ASSERT(us / (signed short) -3 == (sizeof(int) == 2 ? 0 : 0xffffaaaf));
+ ul = -12;
+ ASSERT(ul / (signed LONG ) -3 == 0);
+ u = -12;
+ ASSERT(u / (stype) 3 == (stype) 0x55555551);
+ uc = 12;
+ ASSERT(uc / (signed char ) -3 == -4);
+ us = 12;
+ ASSERT(us / (signed short) -3 == (sizeof(int) == 2 ? 0 : 0xfffffffc));
+ ul = 12;
+ ASSERT(ul / (signed LONG ) -3 == 0);
+
+ s = -12;
+ ASSERT(s / (utype) -3 == 0);
+ sc = -12;
+ ASSERT(sc / (unsigned char ) 3 == -4);
+ ss = -12;
+ ASSERT(ss / (unsigned short) 3 == (sizeof(int) == 2 ? 0x5551 : -4));
+ sl = -12;
+ ASSERT(sl / (unsigned LONG ) 3 == 0x55555551);
+ s = 12;
+ ASSERT(s / (utype) -3 == 0);
+
+
+ /* mod ast: valMod() */
+ /* -11 : 0xfff5 */
+ /* -17 : 0xffef */
+ ASSERT((stype) -17 % (stype) -11 == (stype) -6);
+ ASSERT((stype) -17 % (stype) 11 == (stype) -6);
+ ASSERT((stype) 17 % (stype) -11 == (stype) 6);
+ ASSERT((unsigned char ) -17 % (signed char ) -11 == 8);
+ ASSERT((unsigned short) -17 % (signed short) -11 == (sizeof(int) == 2 ? -17 : 3));
+ ASSERT((unsigned LONG ) -17 % (signed LONG ) -11 == -17);
+ ASSERT((unsigned char ) -17 % (signed char ) 11 == 8);
+ ASSERT((unsigned short) -17 % (signed short) 11 == 3);
+ ASSERT((unsigned LONG ) -17 % (signed LONG ) 11 == 9);
+ ASSERT((unsigned char ) 17 % (signed char ) -11 == 6);
+ ASSERT((unsigned short) 17 % (signed short) -11 == (sizeof(int) == 2 ? 17 : 6));
+ ASSERT((unsigned LONG ) 17 % (signed LONG ) -11 == 17);
+ ASSERT(-3 % 2 < 0);
- ASSERT((stype) -14 % (stype) -3 == (stype) -2);
- ASSERT((stype) -14 % (stype) 3 == (stype) -2);
- ASSERT((stype) 14 % (stype) -3 == (stype) 2);
- ASSERT(-3 % 2 < 0);
+ /* add */
+ ASSERT( 80 + 80 == 160);
+ ASSERT(150 + 150 == 300);
+ ASSERT(160u + 160u == 320);
}