X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCsymt.c;h=4ceceaf007bd50c5a55f08ee18cb4d8d12a879cb;hb=67613b6eceb41c8a242c2556a0f59311adb0b388;hp=f68a60e57c48fdc6055d9d004abceb32f74c6c00;hpb=25c4a7800e873aaef74e88ab0ff0df0c3ba63bd6;p=fw%2Fsdcc diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index f68a60e5..4ceceaf0 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -24,6 +24,8 @@ #include "common.h" #include "newalloc.h" +#include "SDCCsymt.h" + value *aggregateToPointer (value *val); void printTypeChainRaw (sym_link * start, FILE * of); @@ -293,6 +295,7 @@ newSymbol (char *name, int scope) sym->level = scope; /* set the level */ sym->block = currBlockno; sym->lineDef = mylineno; /* set the line number */ + sym->fileDef = currFname; return sym; } @@ -565,6 +568,14 @@ void checkTypeSanity(sym_link *etype, char *name) { 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); @@ -1000,6 +1011,23 @@ addSymChain (symbol * symHead) DCL_ELEM(csym->type) = DCL_ELEM(sym->type); } + #if 0 + /* If only one of the definitions used the "at" keyword, copy */ + /* the address to the other. */ + if (IS_SPEC(csym->etype) && SPEC_ABSA(csym->etype) + && IS_SPEC(sym->etype) && !SPEC_ABSA(sym->etype)) + { + SPEC_ABSA (sym->etype) = 1; + SPEC_ADDR (sym->etype) = SPEC_ADDR (csym->etype); + } + if (IS_SPEC(csym->etype) && !SPEC_ABSA(csym->etype) + && IS_SPEC(sym->etype) && SPEC_ABSA(sym->etype)) + { + SPEC_ABSA (csym->etype) = 1; + SPEC_ADDR (csym->etype) = SPEC_ADDR (sym->etype); + } + #endif + error = 0; if (csym->ival && sym->ival) error = 1; @@ -1012,7 +1040,18 @@ addSymChain (symbol * symHead) werror (E_EXTERN_MISMATCH, sym->name); else werror (E_DUPLICATE, sym->name); - printFromToType (csym->type, sym->type); + 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)) + fprintf(stderr, " at 0x%x", SPEC_ADDR (csym->etype)); + fprintf (stderr, "'\nto type '"); + printTypeChain (sym->type, stderr); + if (IS_SPEC (sym->etype) && SPEC_ABSA (sym->etype)) + fprintf(stderr, " at 0x%x", SPEC_ADDR (sym->etype)); + fprintf (stderr, "'\n"); + #endif continue; } @@ -1201,6 +1240,71 @@ compStructSize (int su, structdef * sdef) 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 */ /*------------------------------------------------------------------*/ @@ -1313,7 +1417,7 @@ checkSClass (symbol * sym, int isProto) } } } - + /* automatic symbols cannot be given */ /* an absolute address ignore it */ if (sym->level && @@ -1484,16 +1588,86 @@ cleanUpLevel (bucket ** table, int level) } } +/*------------------------------------------------------------------*/ +/* 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) +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 */ @@ -1502,12 +1676,28 @@ computeType (sym_link * type1, sym_link * type2) 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 */ @@ -1521,22 +1711,122 @@ computeType (sym_link * type1, sym_link * type2) rType = copyLinkChain (type2); reType = getSpec (rType); -#if 0 - if (SPEC_NOUN (reType) == V_CHAR) - 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)) - SPEC_USIGN (reType) = 1; - else - SPEC_USIGN (reType) = 0; + /* avoid conflicting types */ + reType->select.s._signed = 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; } @@ -2115,10 +2405,9 @@ processFuncArgs (symbol * func) 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 */ @@ -2198,10 +2487,13 @@ processFuncArgs (symbol * func) val->sym->etype = getSpec (val->sym->type); val->sym->_isparm = 1; strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname)); + #if 0 + /* ?? static functions shouldn't imply static parameters - EEP */ if (IS_SPEC(func->etype)) { SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) = SPEC_STAT (func->etype); } + #endif addSymChain (val->sym); } @@ -2213,10 +2505,14 @@ processFuncArgs (symbol * func) val->sym->_isparm = 1; SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = (options.model != MODEL_SMALL ? xdata : data); + + #if 0 + /* ?? static functions shouldn't imply static parameters - EEP */ if (IS_SPEC(func->etype)) { SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) = SPEC_STAT (func->etype); } + #endif } if (!isinSet(operKeyReset, val->sym)) { addSet (&operKeyReset, val->sym); @@ -2603,8 +2899,8 @@ printTypeChainRaw (sym_link * start, FILE * of) /*-----------------------------------------------------------------*/ /* 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; @@ -2647,7 +2943,7 @@ sym_link *floatType; static char * _mangleFunctionName(char *in) { - if (port->getMangledFunctionName) + if (port->getMangledFunctionName) { return port->getMangledFunctionName(in); } @@ -2971,3 +3267,63 @@ sym_link *validateLink(sym_link *l, exit(-1); return l; // never reached, makes compiler happy. } + +/*--------------------------------------------------------------------*/ +/* newEnumType - create an integer type compatible with enumerations */ +/*--------------------------------------------------------------------*/ +sym_link * +newEnumType (symbol *enumlist) +{ + int min, max, v; + symbol *sym; + sym_link *type; + + if (!enumlist) + { + type = newLink (SPECIFIER); + SPEC_NOUN (type) = V_INT; + return type; + } + + /* Determine the range of the enumerated values */ + sym = enumlist; + min = max = (int) floatFromVal (valFromType (sym->type)); + for (sym = sym->next; sym; sym = sym->next) + { + v = (int) floatFromVal (valFromType (sym->type)); + if (vmax) + max = v; + } + + /* Determine the smallest integer type that is compatible with this range */ + type = newLink (SPECIFIER); + if (min>=0 && max<=255) + { + SPEC_NOUN (type) = V_CHAR; + SPEC_USIGN (type) = 1; + } + else if (min>=-128 && max<=127) + { + SPEC_NOUN (type) = V_CHAR; + } + else if (min>=0 && max<=65535) + { + SPEC_NOUN (type) = V_INT; + SPEC_USIGN (type) = 1; + } + else if (min>=-32768 && max<=32767) + { + SPEC_NOUN (type) = V_INT; + } + else + { + SPEC_NOUN (type) = V_INT; + SPEC_LONG (type) = 1; + if (min>=0) + SPEC_USIGN (type) = 1; + } + + return type; +}