X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCsymt.c;h=f830136954bce1767e639ed8b77cac9d9f8f9db2;hb=626863c49dd94f2a84ee83f28d3f71f56ebe0e8e;hp=9349511d9f89ec36c717e8c112ad906a43ae8c82;hpb=5a10305aa25b3544b1a4a55e8cf6a1d21524adf3;p=fw%2Fsdcc diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index 9349511d..f8301369 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -24,6 +24,27 @@ #include "common.h" #include "newalloc.h" +/* noun strings */ +char *nounName(sym_link *sl) { + switch (SPEC_NOUN(sl)) + { + case V_INT: { + if (SPEC_LONG(sl)) return "long"; + if (sl->select.s._short) return "short"; + return "int"; + } + case V_FLOAT: return "float"; + case V_CHAR: return "char"; + case V_VOID: return "void"; + case V_STRUCT: return "struct"; + case V_LABEL: return "label"; + case V_BIT: return "bit"; + case V_SBIT: return "sbit"; + case V_DOUBLE: return "double"; + } + return "unknown"; +}; + bucket *SymbolTab[256]; /* the symbol table */ bucket *StructTab[256]; /* the structure table */ bucket *TypedefTab[256]; /* the typedef table */ @@ -77,11 +98,20 @@ addSym (bucket ** stab, void *sym, char *sname, int level, - int block) + int block, + int checkType) { int i; /* index into the hash Table */ bucket *bp; /* temp bucket * */ + if (checkType) { + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "addSym: %s ", sname); + } + /* make sure the type is complete and sane */ + checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name); + } + /* the symbols are always added at the head of the list */ i = hashKey (sname); /* get a free entry */ @@ -382,7 +412,7 @@ addDecl (symbol * sym, int type, sym_link * p) { if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail) { - sym->etype = mergeSpec (sym->etype, head); + sym->etype = mergeSpec (sym->etype, head, sym->name); } else { @@ -424,26 +454,147 @@ addDecl (symbol * sym, int type, sym_link * p) return; } +/*------------------------------------------------------------------ + checkTypeSanity: prevent the user from doing e.g.: + unsigned float uf; + ------------------------------------------------------------------*/ +void checkTypeSanity(sym_link *etype, char *name) { + char *noun; + + if (!etype) { + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "sanity check skipped for %s (etype==0)\n", name); + } + return; + } + + if (!IS_SPEC(etype)) { + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "sanity check skipped for %s (!IS_SPEC)\n", name); + } + return; + } + + noun=nounName(etype); + + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "checking sanity for %s %x\n", name, (int)etype); + } + + if ((SPEC_NOUN(etype)==V_CHAR || + SPEC_NOUN(etype)==V_FLOAT || + SPEC_NOUN(etype)==V_DOUBLE || + SPEC_NOUN(etype)==V_VOID) && + (etype->select.s._short || SPEC_LONG(etype))) { + // long or short for char float double or void + werror (E_LONG_OR_SHORT_INVALID, noun, name); + } + if ((SPEC_NOUN(etype)==V_FLOAT || + SPEC_NOUN(etype)==V_DOUBLE || + SPEC_NOUN(etype)==V_VOID) && + (etype->select.s._signed || SPEC_USIGN(etype))) { + // signed or unsigned for float double or void + werror (E_SIGNED_OR_UNSIGNED_INVALID, noun, name); + } + + // special case for "short" + if (etype->select.s._short) { + SPEC_NOUN(etype) = options.shortis8bits ? V_CHAR : V_INT; + etype->select.s._short = 0; + } + + /* if no noun e.g. + "const a;" or "data b;" or "signed s" or "long l" + assume an int */ + if (!SPEC_NOUN(etype)) { + SPEC_NOUN(etype)=V_INT; + } + + if (etype->select.s._signed && SPEC_USIGN(etype)) { + // signed AND unsigned + werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name); + } + if (etype->select.s._short && SPEC_LONG(etype)) { + // short AND long + werror (E_LONG_AND_SHORT_INVALID, noun, name); + } + +} + /*------------------------------------------------------------------*/ -/* mergeSpec - merges two specifiers and returns the new one */ +/* mergeSpec - merges two specifiers and returns the new one */ /*------------------------------------------------------------------*/ +#define LAST_MINUTE_2_3_0_FIX sym_link * -mergeSpec (sym_link * dest, sym_link * src) +mergeSpec (sym_link * dest, sym_link * src, char *name) { - /* if noun different then src overrides */ - if (SPEC_NOUN (dest) != SPEC_NOUN (src) && !SPEC_NOUN (dest)) - SPEC_NOUN (dest) = SPEC_NOUN (src); - - /* if destination has no storage class */ - if (!SPEC_SCLS (dest) || - ((SPEC_SCLS(dest) == S_CONSTANT || SPEC_SCLS(dest) == S_REGISTER) && - SPEC_SCLS (src))) - SPEC_SCLS (dest) = SPEC_SCLS (src); - /* special case for const */ + +#ifdef LAST_MINUTE_2_3_0_FIX + sym_link *symlink; + + if (!IS_SPEC(dest)) { + // This should not happen + fprintf (stderr, "*** internal error: can't merge declarators\n"); + } + if (!IS_SPEC(src)) { + // here we have a declarator as source, reverse them + symlink=src; + src=dest; + dest=symlink; + while (!IS_SPEC(dest)) { + // and find the specifier + dest=dest->next; + } + } else { + symlink=dest; + } +#endif + + if (getenv("DEBUG_mergeSpec")) { + fprintf (stderr, "mergeSpec: \"%s\"\n", name); + } + + if (SPEC_NOUN(src)) { + if (!SPEC_NOUN(dest)) { + SPEC_NOUN(dest)=SPEC_NOUN(src); + } else { + /* we shouldn't redeclare the type */ + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "mergeSpec: "); + } + werror(E_TWO_OR_MORE_DATA_TYPES, name); + } + } + + if (SPEC_SCLS(src)) { + /* if destination has no storage class */ + if (!SPEC_SCLS (dest) || SPEC_SCLS(dest)==S_REGISTER) { + SPEC_SCLS (dest) = SPEC_SCLS (src); + } else { + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "mergeSpec: "); + } + werror(E_TWO_OR_MORE_STORAGE_CLASSES, name); + } + } + /* copy all the specifications */ + + // we really should do: +#if 0 + if (SPEC_what(src)) { + if (SPEC_what(dest)) { + werror(W_DUPLICATE_SPEC, "what"); + } + SPEC_what(dst)|=SPEC_what(src); + } +#endif + // but there are more important thing right now + SPEC_LONG (dest) |= SPEC_LONG (src); - SPEC_SHORT (dest) |= SPEC_SHORT (src); + dest->select.s._short|=src->select.s._short; SPEC_USIGN (dest) |= SPEC_USIGN (src); + dest->select.s._signed|=src->select.s._signed; SPEC_STAT (dest) |= SPEC_STAT (src); SPEC_EXTR (dest) |= SPEC_EXTR (src); SPEC_ABSA (dest) |= SPEC_ABSA (src); @@ -458,11 +609,16 @@ mergeSpec (sym_link * dest, sym_link * src) SPEC_BSTR (dest) |= SPEC_BSTR (src); SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src); SPEC_NONBANKED (dest) |= SPEC_NONBANKED (src); + SPEC_NAKED (dest) |= SPEC_NAKED (src); if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL) SPEC_STRUCT (dest) = SPEC_STRUCT (src); +#ifdef LAST_MINUTE_2_3_0_FIX + return symlink; +#else return dest; +#endif } /*------------------------------------------------------------------*/ @@ -511,7 +667,7 @@ getSpec (sym_link * p) } /*------------------------------------------------------------------*/ -/* newCharLink() - creates an int type */ +/* newCharLink() - creates an char type */ /*------------------------------------------------------------------*/ sym_link * newCharLink () @@ -585,7 +741,7 @@ getSize (sym_link * p) switch (SPEC_NOUN (p)) { /* depending on the specifier type */ case V_INT: - return (IS_LONG (p) ? LONGSIZE : (IS_SHORT (p) ? SHORTSIZE : INTSIZE)); + return (IS_LONG (p) ? LONGSIZE : INTSIZE); case V_FLOAT: return FLOATSIZE; case V_CHAR: @@ -644,7 +800,7 @@ bitsForType (sym_link * p) switch (SPEC_NOUN (p)) { /* depending on the specifier type */ case V_INT: - return (IS_LONG (p) ? LONGSIZE * 8 : (IS_SHORT (p) ? SHORTSIZE * 8 : INTSIZE * 8)); + return (IS_LONG (p) ? LONGSIZE * 8 : INTSIZE * 8); case V_FLOAT: return FLOATSIZE * 8; case V_CHAR: @@ -788,9 +944,11 @@ addSymChain (symbol * symHead) symbol *sym = symHead; symbol *csym = NULL; + for (; sym != NULL; sym = sym->next) { changePointer(sym); + /* if already exists in the symbol table then check if the previous was an extern definition if yes then then check if the type match, if the types match then @@ -803,14 +961,14 @@ addSymChain (symbol * symHead) if (IS_EXTERN (csym->etype)) { /* do types match ? */ - if (checkType (csym->type, sym->type) != 1) + if (compareType (csym->type, sym->type) != 1) /* no then error */ werror (E_DUPLICATE, csym->name); /* delete current entry */ deleteSym (SymbolTab, csym, csym->name); /* add new entry */ - addSym (SymbolTab, sym, sym->name, sym->level, sym->block); + addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1); } else /* not extern */ werror (E_DUPLICATE, sym->name); @@ -824,12 +982,11 @@ addSymChain (symbol * symHead) /* then check the type with the current one */ if (IS_EXTERN (csym->etype)) { - if (checkType (csym->type, sym->type) <= 0) + if (compareType (csym->type, sym->type) <= 0) werror (W_EXTERN_MISMATCH, csym->name); } } - - addSym (SymbolTab, sym, sym->name, sym->level, sym->block); + addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1); } } @@ -981,11 +1138,18 @@ compStructSize (int su, structdef * sdef) static void checkSClass (symbol * sym) { + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "checkSClass: %s \n", sym->name); + } + if (strcmp(sym->name, "_testsGlobal")==0) { + printf ("oach\n"); + } + /* type is literal can happen foe enums change to auto */ if (SPEC_SCLS (sym->etype) == S_LITERAL && !SPEC_ENUM (sym->etype)) SPEC_SCLS (sym->etype) = S_AUTO; - + /* if sfr or sbit then must also be */ /* volatile the initial value will be xlated */ /* to an absolute address */ @@ -1002,26 +1166,24 @@ checkSClass (symbol * sym) sym->ival = NULL; } } - + /* if absolute address given then it mark it as volatile */ if (IS_ABSOLUTE (sym->etype)) SPEC_VOLATILE (sym->etype) = 1; - + /* global variables declared const put into code */ if (sym->level == 0 && - SPEC_SCLS (sym->etype) == S_CONSTANT) - { - SPEC_SCLS (sym->etype) = S_CODE; - SPEC_CONST (sym->etype) = 1; - } - + SPEC_CONST (sym->etype)) { + SPEC_SCLS (sym->etype) = S_CODE; + } + /* global variable in code space is a constant */ if (sym->level == 0 && SPEC_SCLS (sym->etype) == S_CODE && port->mem.code_ro) SPEC_CONST (sym->etype) = 1; - + /* if bit variable then no storage class can be */ /* specified since bit is already a storage */ @@ -1042,6 +1204,7 @@ checkSClass (symbol * sym) sym->ival = NULL; } +#if 0 /* if this is an automatic symbol then */ /* storage class will be ignored and */ /* symbol will be allocated on stack/ */ @@ -1052,14 +1215,29 @@ checkSClass (symbol * sym) SPEC_SCLS (sym->etype) != S_FIXED && SPEC_SCLS (sym->etype) != S_REGISTER && SPEC_SCLS (sym->etype) != S_STACK && - SPEC_SCLS (sym->etype) != S_XSTACK && - SPEC_SCLS (sym->etype) != S_CONSTANT)) + SPEC_SCLS (sym->etype) != S_XSTACK)) { - werror (E_AUTO_ASSUMED, sym->name); SPEC_SCLS (sym->etype) = S_AUTO; } - +#else + /* if this is an atomatic symbol */ + if (sym->level && (options.stackAuto || reentrant)) { + if ((SPEC_SCLS (sym->etype) == S_AUTO || + SPEC_SCLS (sym->etype) == S_FIXED || + SPEC_SCLS (sym->etype) == S_REGISTER || + SPEC_SCLS (sym->etype) == S_STACK || + SPEC_SCLS (sym->etype) == S_XSTACK)) { + SPEC_SCLS (sym->etype) = S_AUTO; + } else { + /* storage class may only be specified for statics */ + if (!IS_STATIC(sym->etype)) { + werror (E_AUTO_ASSUMED, sym->name); + } + } + } +#endif + /* automatic symbols cannot be given */ /* an absolute address ignore it */ if (sym->level && @@ -1098,7 +1276,8 @@ checkSClass (symbol * sym) /* if parameter or local variable then change */ /* the storage class to reflect where the var will go */ - if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED) + if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED && + !IS_STATIC(sym->etype)) { if (options.stackAuto || (currFunc && IS_RENT (currFunc->etype))) { @@ -1275,10 +1454,10 @@ computeType (sym_link * type1, sym_link * type2) } /*------------------------------------------------------------------*/ -/* checkType - will do type check return 1 if match */ +/* compareType - will do type check return 1 if match */ /*------------------------------------------------------------------*/ int -checkType (sym_link * dest, sym_link * src) +compareType (sym_link * dest, sym_link * src) { if (!dest && !src) return 1; @@ -1295,13 +1474,13 @@ checkType (sym_link * dest, sym_link * src) if (IS_DECL (src)) { if (DCL_TYPE (src) == DCL_TYPE (dest)) - return checkType (dest->next, src->next); + return compareType (dest->next, src->next); else if (IS_PTR (src) && IS_PTR (dest)) return -1; else if (IS_PTR (dest) && IS_ARRAY (src)) return -1; else if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src)) - return -1 * checkType (dest->next, src); + return -1 * compareType (dest->next, src); else return 0; } @@ -1325,17 +1504,6 @@ checkType (sym_link * dest, sym_link * src) SPEC_NOUN (src) == V_VOID) return -1; - /* char === to short */ - if (SPEC_NOUN (dest) == V_CHAR && - SPEC_NOUN (src) == V_INT && - SPEC_SHORT (src)) - return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2); - - if (SPEC_NOUN (src) == V_CHAR && - SPEC_NOUN (dest) == V_INT && - SPEC_SHORT (dest)) - return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2); - /* if they are both bitfields then if the lengths and starts don't match */ if (IS_BITFIELD (dest) && IS_BITFIELD (src) && @@ -1365,9 +1533,6 @@ checkType (sym_link * dest, sym_link * src) if (SPEC_LONG (dest) != SPEC_LONG (src)) return -1; - if (SPEC_SHORT (dest) != SPEC_SHORT (src)) - return -1; - if (SPEC_USIGN (dest) != SPEC_USIGN (src)) return -2; @@ -1375,7 +1540,7 @@ checkType (sym_link * dest, sym_link * src) } /*------------------------------------------------------------------*/ -/* inCalleeSaveList - return 1 if found in calle save list */ +/* inCalleeSaveList - return 1 if found in callee save list */ /*------------------------------------------------------------------*/ bool inCalleeSaveList (char *s) @@ -1466,8 +1631,16 @@ checkFunction (symbol * sym) { symbol *csym; value *exargs, *acargs; + value *checkValue; int argCnt = 0; + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "checkFunction: %s ", sym->name); + } + + /* make sure the type is complete and sane */ + checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name); + /* if not type then some kind of error */ if (!sym->type) return 0; @@ -1513,10 +1686,10 @@ checkFunction (symbol * sym) } /* check the return value type */ - if (checkType (csym->type, sym->type) <= 0) + if (compareType (csym->type, sym->type) <= 0) { werror (E_PREV_DEF_CONFLICT, csym->name, "type"); - werror (E_CONTINUE, "previous defintion type "); + werror (E_CONTINUE, "previous definition type "); printTypeChain (csym->type, stderr); fprintf (stderr, "\n"); werror (E_CONTINUE, "current definition type "); @@ -1528,13 +1701,16 @@ checkFunction (symbol * sym) if (SPEC_INTRTN (csym->etype) != SPEC_INTRTN (sym->etype)) { werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt"); - return 0; } if (SPEC_BANK (csym->etype) != SPEC_BANK (sym->etype)) { werror (E_PREV_DEF_CONFLICT, csym->name, "using"); - return 0; + } + + if (SPEC_NAKED (csym->etype) != SPEC_NAKED (sym->etype)) + { + werror (E_PREV_DEF_CONFLICT, csym->name, "_naked"); } /* compare expected agrs with actual args */ @@ -1546,7 +1722,12 @@ checkFunction (symbol * sym) exargs && acargs; exargs = exargs->next, acargs = acargs->next, argCnt++) { - value *checkValue; + if (getenv("DEBUG_SANITY")) { + fprintf (stderr, "checkFunction: %s ", exargs->name); + } + /* make sure the type is complete and sane */ + checkTypeSanity(exargs->etype, exargs->name); + /* If the actual argument is an array, any prototype * will have modified it to a pointer. Duplicate that * change here. @@ -1561,7 +1742,7 @@ checkFunction (symbol * sym) checkValue = acargs; } - if (checkType (exargs->type, checkValue->type) <= 0) + if (compareType (exargs->type, checkValue->type) <= 0) { werror (E_ARG_TYPE, argCnt); return 0; @@ -1576,7 +1757,7 @@ checkFunction (symbol * sym) /* replace with this defition */ sym->cdef = csym->cdef; deleteSym (SymbolTab, csym, csym->name); - addSym (SymbolTab, sym, sym->name, sym->level, sym->block); + addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1); if (IS_EXTERN (csym->etype) && ! IS_EXTERN (sym->etype)) { @@ -1620,8 +1801,7 @@ processFuncArgs (symbol * func, int ignoreName) { /* mark it as a register parameter if the function does not have VA_ARG - and as port dictates - not inhibited by command line option or #pragma */ + and as port dictates */ if (!func->hasVargs && (*port->reg_parm) (val->type)) { @@ -1799,10 +1979,7 @@ printTypeChain (sym_link * type, FILE * of) case V_INT: if (IS_LONG (type)) fprintf (of, "long "); - else if (IS_SHORT (type)) - fprintf (of, "short "); - else - fprintf (of, "int "); + fprintf (of, "int "); break; case V_CHAR: @@ -1829,7 +2006,12 @@ printTypeChain (sym_link * type, FILE * of) fprintf (of, "bit {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); break; + case V_DOUBLE: + fprintf (of, "double "); + break; + default: + fprintf (of, "unknown type "); break; } } @@ -1890,8 +2072,6 @@ cdbTypeInfo (sym_link * type, FILE * of) case V_INT: if (IS_LONG (type)) fprintf (of, "SL"); - else if (IS_SHORT (type)) - fprintf (of, "SS"); else fprintf (of, "SI"); break; @@ -2100,6 +2280,19 @@ _makeRegParam (symbol * sym) } } +static char * +_mangleFunctionName(char *in) +{ + if (port->getMangledFunctionName) + { + return port->getMangledFunctionName(in); + } + else + { + return in; + } +} + /*-----------------------------------------------------------------*/ /* initCSupport - create functions for C support routines */ /*-----------------------------------------------------------------*/ @@ -2165,12 +2358,12 @@ initCSupport () if (tofrom) { sprintf (buffer, "__fs2%s%s", ssu[su], sbwd[bwd]); - __conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], floatType, 1, options.float_rent); + __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], floatType, 1, options.float_rent); } else { sprintf (buffer, "__%s%s2fs", ssu[su], sbwd[bwd]); - __conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent); + __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), floatType, __multypes[bwd][su], 1, options.float_rent); } } } @@ -2186,7 +2379,7 @@ initCSupport () smuldivmod[muldivmod], ssu[su], sbwd[bwd]); - __muldiv[muldivmod][bwd][su] = funcOfType (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent); + __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent); SPEC_NONBANKED (__muldiv[muldivmod][bwd][su]->etype) = 1; if (bwd < port->muldiv.force_reg_param_below) _makeRegParam (__muldiv[muldivmod][bwd][su]);