#include "common.h"
#include "newalloc.h"
+#include "SDCCsymt.h"
+
value *aggregateToPointer (value *val);
void printTypeChainRaw (sym_link * start, FILE * of);
SPEC_NOUN(etype)=V_INT;
}
+ /* ISO/IEC 9899 J.3.9 implementation defined behaviour: */
+ /* a "plain" int bitfield is unsigned */
+ if (SPEC_NOUN(etype)==V_BIT ||
+ SPEC_NOUN(etype)==V_SBIT) {
+ if (!etype->select.s._signed)
+ SPEC_USIGN(etype) = 1;
+ }
+
if (etype->select.s._signed && SPEC_USIGN(etype)) {
// signed AND unsigned
werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name);
werror (E_EXTERN_MISMATCH, sym->name);
else
werror (E_DUPLICATE, sym->name);
+ werrorfl (csym->fileDef, csym->lineDef, E_PREVIOUS_DEF);
+ #if 0
fprintf (stderr, "from type '");
printTypeChain (csym->type, stderr);
if (IS_SPEC (csym->etype) && SPEC_ABSA (csym->etype))
if (IS_SPEC (sym->etype) && SPEC_ABSA (sym->etype))
fprintf(stderr, " at 0x%x", SPEC_ADDR (sym->etype));
fprintf (stderr, "'\n");
+ #endif
continue;
}
return (su == UNION ? usum : sum);
}
+/*-------------------------------------------------------------------*/
+/* promoteAnonStructs - promote anonymous struct/union's fields into */
+/* an enclosing struct/union */
+/*-------------------------------------------------------------------*/
+void
+promoteAnonStructs (int su, structdef * sdef)
+{
+ symbol *field;
+ symbol *subfield;
+ symbol **tofield;
+ symbol *nextfield;
+ symbol *dupfield;
+ int base;
+
+ tofield = &sdef->fields;
+ field = sdef->fields;
+ while (field)
+ {
+ nextfield = field->next;
+ if (!*field->name && IS_STRUCT (field->type))
+ {
+ /* Found an anonymous struct/union. Replace it */
+ /* with the fields it contains and adjust all */
+ /* the offsets */
+
+ base = field->offset;
+ subfield = copySymbolChain (SPEC_STRUCT (field->type)->fields);
+ if (!subfield)
+ continue; /* just in case it's empty */
+
+ *tofield = subfield;
+ for (;;)
+ {
+ /* check for field name conflicts resulting from promotion */
+ dupfield = sdef->fields;
+ while (dupfield && dupfield != subfield)
+ {
+ if (*subfield->name && !strcmp (dupfield->name, subfield->name))
+ {
+ werrorfl (subfield->fileDef, subfield->lineDef,
+ E_DUPLICATE_MEMBER,
+ su==STRUCT ? "struct" : "union",
+ subfield->name);
+ werrorfl (dupfield->fileDef, dupfield->lineDef,
+ E_PREVIOUS_DEF);
+ }
+ dupfield = dupfield->next;
+ }
+
+ subfield->offset += base;
+ if (subfield->next)
+ subfield = subfield->next;
+ else
+ break;
+ }
+ subfield->next = nextfield;
+ tofield = &subfield->next;
+ }
+ else
+ tofield = &field->next;
+ field = nextfield;
+ }
+}
+
+
/*------------------------------------------------------------------*/
/* checkSClass - check the storage class specification */
/*------------------------------------------------------------------*/
}
}
+/*------------------------------------------------------------------*/
+/* computeTypeOr - computes the resultant type from two types */
+/*------------------------------------------------------------------*/
+static sym_link *
+computeTypeOr (sym_link * etype1, sym_link * etype2, sym_link * reType)
+{
+ /* sanity check */
+ assert (IS_CHAR (etype1) && IS_CHAR (etype2));
+
+ if (SPEC_USIGN (etype1) == SPEC_USIGN (etype2))
+ {
+ SPEC_USIGN (reType) = SPEC_USIGN (etype1);
+ return reType;
+ }
+
+ if (SPEC_USIGN (etype1))
+ {
+ if ( IS_LITERAL (etype2)
+ && floatFromVal (valFromType (etype2)) >= 0)
+ SPEC_USIGN (reType) = 1;
+ else
+ {
+ /* promote to int */
+ SPEC_USIGN (reType) = 0;
+ SPEC_NOUN (reType) = V_INT;
+ }
+ }
+ else /* etype1 signed */
+ {
+ if ( IS_LITERAL (etype2)
+ && floatFromVal (valFromType (etype2)) <= 127)
+ SPEC_USIGN (reType) = 0;
+ else
+ {
+ /* promote to int */
+ SPEC_USIGN (reType) = 0;
+ SPEC_NOUN (reType) = V_INT;
+ }
+ }
+
+ if (SPEC_USIGN (etype2))
+ {
+ if ( IS_LITERAL (etype1)
+ && floatFromVal (valFromType (etype1)) >= 0)
+ SPEC_USIGN (reType) = 1;
+ else
+ {
+ /* promote to int */
+ SPEC_USIGN (reType) = 0;
+ SPEC_NOUN (reType) = V_INT;
+ }
+ }
+ else /* etype2 signed */
+ {
+ if ( IS_LITERAL (etype1)
+ && floatFromVal (valFromType (etype1)) <= 127)
+ SPEC_USIGN (reType) = 0;
+ else
+ {
+ /* promote to int */
+ SPEC_USIGN (reType) = 0;
+ SPEC_NOUN (reType) = V_INT;
+ }
+ }
+ return reType;
+}
+
/*------------------------------------------------------------------*/
/* computeType - computes the resultant type from two types */
/*------------------------------------------------------------------*/
sym_link *
-computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
+computeType (sym_link * type1, sym_link * type2,
+ RESULT_TYPE resultType, char op)
{
sym_link *rType;
sym_link *reType;
sym_link *etype1 = getSpec (type1);
- sym_link *etype2 = getSpec (type2);
+ sym_link *etype2;
+
+ etype2 = type2 ? getSpec (type2) : type1;
/* if one of them is a float then result is a float */
/* here we assume that the types passed are okay */
if (IS_FLOAT (etype1) || IS_FLOAT (etype2))
rType = newFloatLink ();
else
+ /* if both are bitvars choose the larger one */
+ if (IS_BITVAR (etype1) && IS_BITVAR (etype2))
+ {
+ rType = SPEC_BLEN (etype1) >= SPEC_BLEN (etype2) ?
+ copyLinkChain (type1) : copyLinkChain (type1);
+ }
/* if only one of them is a bit variable
then the other one prevails */
- if (IS_BITVAR (etype1) && !IS_BITVAR (etype2))
- rType = copyLinkChain (type2);
+ else if (IS_BITVAR (etype1) && !IS_BITVAR (etype2))
+ {
+ rType = copyLinkChain (type2);
+ /* bitfield can have up to 16 bits */
+ if (getSize (etype1) > 1)
+ SPEC_NOUN (getSpec (rType)) = V_INT;
+ }
else if (IS_BITVAR (etype2) && !IS_BITVAR (etype1))
- rType = copyLinkChain (type1);
+ {
+ rType = copyLinkChain (type1);
+ /* bitfield can have up to 16 bits */
+ if (getSize (etype2) > 1)
+ SPEC_NOUN (getSpec (rType)) = V_INT;
+ }
else
/* if one of them is a pointer or array then that
prevails */
/* avoid conflicting types */
reType->select.s._signed = 0;
- if (IS_CHAR (reType) && promoteCharToInt)
- SPEC_NOUN (reType) = V_INT;
-
- if ( ( ( SPEC_USIGN (etype1)
- /* if this operand is promoted to a larger
- type don't check it's signedness */
- && (getSize (etype1) >= getSize (reType))
- /* We store signed literals in the range 0...255 as
- 'unsigned char'. If there was no promotion to 'signed int'
- they must not force an unsigned operation: */
- && !(IS_CHAR (etype1) && IS_LITERAL (etype1)))
- || ( SPEC_USIGN (etype2)
- && (getSize (etype2) >= getSize (reType))
- && !(IS_CHAR (etype2) && IS_LITERAL (etype2))))
- && !IS_FLOAT (reType))
- SPEC_USIGN (reType) = 1;
- else
- SPEC_USIGN (reType) = 0;
-
/* if result is a literal then make not so */
if (IS_LITERAL (reType))
SPEC_SCLS (reType) = S_REGISTER;
+ switch (resultType)
+ {
+ case RESULT_TYPE_CHAR:
+ if (IS_BITVAR (reType))
+ {
+ SPEC_NOUN (reType) = V_CHAR;
+ SPEC_SCLS (reType) = 0;
+ SPEC_USIGN (reType) = 0;
+ return rType;
+ }
+ break;
+ case RESULT_TYPE_INT:
+ case RESULT_TYPE_NONE:
+ if (IS_BIT (reType))
+ {
+ SPEC_NOUN (reType) = V_CHAR;
+ SPEC_SCLS (reType) = 0;
+ SPEC_USIGN (reType) = 0;
+ return rType;
+ }
+ else if (IS_BITFIELD (reType))
+ {
+ /* could be smarter, but it depends on the op */
+ /* this is for the worst case: a multiplication of 4 * 4 bit */
+ SPEC_NOUN (reType) = SPEC_BLEN (reType) <= 4 ? V_CHAR : V_INT;
+ SPEC_SCLS (reType) = 0;
+ SPEC_USIGN (reType) = 0;
+ return rType;
+ }
+ else if (IS_CHAR (reType))
+ {
+ if (op == '|' || op == '^')
+ return computeTypeOr (etype1, etype2, reType);
+ else if ( op == '&'
+ && SPEC_USIGN (etype1) != SPEC_USIGN (etype2))
+ {
+ SPEC_USIGN (reType) = 1;
+ return rType;
+ }
+ else
+ {
+ SPEC_NOUN (reType) = V_INT;
+ SPEC_USIGN (reType) = 0;
+ return rType;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* SDCC's sign promotion:
+ - if one or both operands are unsigned, the resultant type will be unsigned
+ (except char, see below)
+ - if an operand is promoted to a larger type (char -> int, int -> long),
+ the larger type will be signed
+
+ SDCC tries hard to avoid promotion to int and does 8 bit calculation as
+ much as possible. We're leaving ISO IEC 9899 here and have to extrapolate
+ the standard. The standard demands, that the result has to be the same
+ "as if" the promotion would have been performed:
+
+ - if the result of an operation with two char's is promoted to a
+ larger type, the result will be signed.
+
+ More sophisticated are these:
+ - if the result of an operation with two char's is a char again,
+ the result will only then be unsigned, if both operands are
+ unsigned. In all other cases the result will be signed.
+
+ This seems to be contradictionary to the first two rules, but it makes
+ real sense (all types are char's):
+
+ A signed char can be negative; this must be preserved in the result
+ -1 * 100 = -100;
+
+ Only if both operands are unsigned it's safe to make the result
+ unsigned; this helps to avoid overflow:
+ 2 * 100 = 200;
+
+ - ToDo: document '|', '^' and '&'
+
+ Homework: - why is (200 * 200 < 0) true?
+ - why is { char l = 200, r = 200; (r * l > 0) } true?
+ */
+
+ if (!IS_FLOAT (reType)
+ && ( (SPEC_USIGN (etype1)
+ /* if this operand is promoted to a larger type,
+ then it will be promoted to a signed type */
+ && !(getSize (etype1) < getSize (reType))
+ /* char require special handling */
+ && !IS_CHAR (etype1))
+ || /* same for 2nd operand */
+ (SPEC_USIGN (etype2)
+ && !(getSize (etype2) < getSize (reType))
+ && !IS_CHAR (etype2))
+ || /* if both are 'unsigned char' and not promoted
+ let the result be unsigned too */
+ ( SPEC_USIGN (etype1)
+ && SPEC_USIGN (etype2)
+ && IS_CHAR (etype1)
+ && IS_CHAR (etype2)
+ && IS_CHAR (reType))))
+ SPEC_USIGN (reType) = 1;
+ else
+ SPEC_USIGN (reType) = 0;
+
return rType;
}
if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
fprintf (stderr, "SDCCsymt.c:processFuncArgs(%s)\n", func->name);
- // if this is a pointer to a function
- if (IS_PTR(funcType)) {
+ /* find the function declaration within the type */
+ while (funcType && !IS_FUNC(funcType))
funcType=funcType->next;
- }
/* if this function has variable argument list */
/* then make the function a reentrant one */