X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCsymt.c;h=c7623d458dd7e37206ce3f4a01c85522535bd461;hb=fd94924a3d743c1c82f4b370d9401d7239172789;hp=d4376dc18fca08d19ed211c1b8cff96e57e5c4d5;hpb=fe37b31ed6385e317511c76eb6812acf37e96d57;p=fw%2Fsdcc diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index d4376dc1..c7623d45 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -23,6 +23,7 @@ #include "common.h" #include "newalloc.h" +#include "dbuf_string.h" #include "SDCCsymt.h" @@ -39,14 +40,15 @@ void printFromToType(sym_link *from, sym_link *to) { /* noun strings */ char *nounName(sym_link *sl) { - switch (SPEC_NOUN(sl)) + switch (SPEC_NOUN(sl)) { case V_INT: { if (SPEC_LONG(sl)) return "long"; - if (sl->select.s._short) return "short"; + if (SPEC_SHORT(sl)) return "short"; return "int"; } case V_FLOAT: return "float"; + case V_FIXED16X16: return "fixed16x16"; case V_CHAR: return "char"; case V_VOID: return "void"; case V_STRUCT: return "struct"; @@ -68,7 +70,7 @@ bucket *enumTab[256]; /* enumerated table */ /*------------------------------------------------------------------*/ /* initSymt () - initialises symbol table related stuff */ /*------------------------------------------------------------------*/ -void +void initSymt () { int i = 0; @@ -79,7 +81,7 @@ initSymt () } /*-----------------------------------------------------------------*/ -/* newBucket - allocates & returns a new bucket */ +/* newBucket - allocates & returns a new bucket */ /*-----------------------------------------------------------------*/ bucket * newBucket () @@ -94,7 +96,7 @@ newBucket () /*-----------------------------------------------------------------*/ /* hashKey - computes the hashkey given a symbol name */ /*-----------------------------------------------------------------*/ -int +int hashKey (const char *s) { unsigned long key = 0; @@ -107,7 +109,7 @@ hashKey (const char *s) /*-----------------------------------------------------------------*/ /* addSym - adds a symbol to the hash Table */ /*-----------------------------------------------------------------*/ -void +void addSym (bucket ** stab, void *sym, char *sname, @@ -116,7 +118,7 @@ addSym (bucket ** stab, int checkType) { int i; /* index into the hash Table */ - bucket *bp; /* temp bucket * */ + bucket *bp; /* temp bucket * */ if (checkType) { symbol *csym = (symbol *)sym; @@ -139,8 +141,8 @@ addSym (bucket ** stab, /* get a free entry */ bp = Safe_alloc ( sizeof (bucket)); - bp->sym = sym; /* update the symbol pointer */ - bp->level = level; /* update the nest level */ + bp->sym = sym; /* update the symbol pointer */ + bp->level = level; /* update the nest level */ bp->block = block; strncpyz (bp->name, sname, sizeof(bp->name)); /* copy the name into place */ @@ -161,9 +163,9 @@ addSym (bucket ** stab, } /*-----------------------------------------------------------------*/ -/* deleteSym - deletes a symbol from the hash Table entry */ +/* deleteSym - deletes a symbol from the hash Table entry */ /*-----------------------------------------------------------------*/ -void +void deleteSym (bucket ** stab, void *sym, char *sname) { int i = 0; @@ -182,6 +184,7 @@ deleteSym (bucket ** stab, void *sym, char *sname) if (!bp) /* did not find it */ return; + /* if this is the first one in the chain */ if (!bp->prev) { @@ -197,11 +200,10 @@ deleteSym (bucket ** stab, void *sym, char *sname) bp->prev->next = bp->next; } - } /*-----------------------------------------------------------------*/ -/* findSym - finds a symbol in a table */ +/* findSym - finds a symbol in a table */ /*-----------------------------------------------------------------*/ void * findSym (bucket ** stab, void *sym, const char *sname) @@ -291,11 +293,11 @@ newSymbol (char *name, int scope) sym = Safe_alloc ( sizeof (symbol)); - strncpyz (sym->name, name, sizeof(sym->name)); /* copy the name */ - sym->level = scope; /* set the level */ + strncpyz (sym->name, name, sizeof(sym->name)); /* copy the name */ + sym->level = scope; /* set the level */ sym->block = currBlockno; - sym->lineDef = mylineno; /* set the line number */ - sym->fileDef = currFname; + sym->lineDef = lexLineno; /* set the line number */ + sym->fileDef = lexFilename; return sym; } @@ -326,7 +328,7 @@ newStruct (char *tag) strncpyz (s->tag, tag, sizeof(s->tag)); /* copy the tag */ return s; } - + /*------------------------------------------------------------------*/ /* sclsFromPtr - Return the storage class a pointer points into. */ /* S_FIXED is returned for generic pointers or other */ @@ -361,7 +363,7 @@ sclsFromPtr(sym_link *ptr) /*------------------------------------------------------------------*/ /* pointerTypes - do the computation for the pointer types */ /*------------------------------------------------------------------*/ -void +void pointerTypes (sym_link * ptr, sym_link * type) { if (IS_SPEC (ptr)) @@ -374,7 +376,7 @@ pointerTypes (sym_link * ptr, sym_link * type) /* could not find it */ if (!ptr || IS_SPEC (ptr)) return; - + if (IS_PTR(ptr) && DCL_TYPE(ptr)!=UPOINTER) { pointerTypes (ptr->next, type); return; @@ -434,9 +436,10 @@ pointerTypes (sym_link * ptr, sym_link * type) /*------------------------------------------------------------------*/ /* addDecl - adds a declarator @ the end of a chain */ /*------------------------------------------------------------------*/ -void +void addDecl (symbol * sym, int type, sym_link * p) { + static sym_link *empty = NULL; sym_link *head; sym_link *tail; sym_link *t; @@ -444,6 +447,9 @@ addDecl (symbol * sym, int type, sym_link * p) if (getenv("SDCC_DEBUG_FUNCTION_POINTERS")) fprintf (stderr, "SDCCsymt.c:addDecl(%s,%d,%p)\n", sym->name, type, p); + if (empty == NULL) + empty = newLink(SPECIFIER); + /* if we are passed a link then set head & tail */ if (p) { @@ -463,28 +469,28 @@ addDecl (symbol * sym, int type, sym_link * p) sym->type = head; sym->etype = tail; } + else if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail) + { + sym->etype = mergeSpec (sym->etype, head, sym->name); + } + else if (IS_SPEC (sym->etype) && !IS_SPEC (head) && head == tail) + { + t = sym->type; + while (t->next != sym->etype) + t = t->next; + t->next = head; + tail->next = sym->etype; + } + else if (IS_FUNC (sym->type) && IS_SPEC (sym->type->next) && + !memcmp(sym->type->next, empty, sizeof(sym_link))) + { + sym->type->next = head; + sym->etype = tail; + } else { - if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail) - { - sym->etype = mergeSpec (sym->etype, head, sym->name); - } - else - { - if (IS_SPEC (sym->etype) && !IS_SPEC (head) && head == tail) - { - t = sym->type; - while (t->next != sym->etype) - t = t->next; - t->next = head; - tail->next = sym->etype; - } - else - { - sym->etype->next = head; - sym->etype = tail; - } - } + sym->etype->next = head; + sym->etype = tail; } /* if the type is an unknown pointer and has @@ -539,29 +545,31 @@ void checkTypeSanity(sym_link *etype, char *name) { fprintf (stderr, "checking sanity for %s %p\n", name, etype); } - if ((SPEC_NOUN(etype)==V_CHAR || - SPEC_NOUN(etype)==V_FLOAT || - SPEC_NOUN(etype)==V_DOUBLE || + if ((SPEC_NOUN(etype)==V_CHAR || + SPEC_NOUN(etype)==V_FLOAT || + SPEC_NOUN(etype)==V_FIXED16X16 || + SPEC_NOUN(etype)==V_DOUBLE || SPEC_NOUN(etype)==V_VOID) && - (etype->select.s._short || SPEC_LONG(etype))) { + (SPEC_SHORT(etype) || 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))) { + if ((SPEC_NOUN(etype)==V_FLOAT || + SPEC_NOUN(etype)==V_FIXED16X16 || + SPEC_NOUN(etype)==V_DOUBLE || + SPEC_NOUN(etype)==V_VOID) && + (etype->select.s.b_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) { + if (SPEC_SHORT(etype)) { SPEC_NOUN(etype) = options.shortis8bits ? V_CHAR : V_INT; - etype->select.s._short = 0; + SPEC_SHORT(etype) = 0; } - /* if no noun e.g. + /* if no noun e.g. "const a;" or "data b;" or "signed s" or "long l" assume an int */ if (!SPEC_NOUN(etype)) { @@ -572,19 +580,18 @@ void checkTypeSanity(sym_link *etype, char *name) { /* a "plain" int bitfield is unsigned */ if (SPEC_NOUN(etype)==V_BIT || SPEC_NOUN(etype)==V_SBIT) { - if (!etype->select.s._signed) + if (!etype->select.s.b_signed) SPEC_USIGN(etype) = 1; } - if (etype->select.s._signed && SPEC_USIGN(etype)) { - // signed AND unsigned + if (etype->select.s.b_signed && SPEC_USIGN(etype)) { + // signed AND unsigned werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name); } - if (etype->select.s._short && SPEC_LONG(etype)) { + if (SPEC_SHORT(etype) && SPEC_LONG(etype)) { // short AND long werror (E_LONG_AND_SHORT_INVALID, noun, name); } - } /*------------------------------------------------------------------*/ @@ -615,7 +622,7 @@ mergeSpec (sym_link * dest, sym_link * src, char *name) 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) { @@ -630,7 +637,7 @@ mergeSpec (sym_link * dest, sym_link * src, char *name) /* copy all the specifications */ - // we really should do: + // we really should do: #if 0 if (SPEC_what(src)) { if (SPEC_what(dest)) { @@ -642,14 +649,16 @@ mergeSpec (sym_link * dest, sym_link * src, char *name) // but there are more important thing right now SPEC_LONG (dest) |= SPEC_LONG (src); - dest->select.s._short|=src->select.s._short; + SPEC_SHORT(dest) |= SPEC_SHORT(src); SPEC_USIGN (dest) |= SPEC_USIGN (src); - dest->select.s._signed|=src->select.s._signed; + dest->select.s.b_signed|=src->select.s.b_signed; SPEC_STAT (dest) |= SPEC_STAT (src); SPEC_EXTR (dest) |= SPEC_EXTR (src); + SPEC_INLINE (dest) |= SPEC_INLINE (src); SPEC_CONST(dest) |= SPEC_CONST (src); SPEC_ABSA (dest) |= SPEC_ABSA (src); SPEC_VOLATILE (dest) |= SPEC_VOLATILE (src); + SPEC_RESTRICT (dest) |= SPEC_RESTRICT (src); SPEC_ADDR (dest) |= SPEC_ADDR (src); SPEC_OCLS (dest) = SPEC_OCLS (src); SPEC_BLEN (dest) |= SPEC_BLEN (src); @@ -658,11 +667,11 @@ mergeSpec (sym_link * dest, sym_link * src, char *name) SPEC_ENUM (dest) |= SPEC_ENUM (src); if (SPEC_ARGREG(src) && !SPEC_ARGREG(dest)) SPEC_ARGREG(dest) = SPEC_ARGREG(src); - + if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL) SPEC_STRUCT (dest) = SPEC_STRUCT (src); - /* these are the only function attributes that will be set + /* these are the only function attributes that will be set in a specifier while parsing */ FUNC_NONBANKED(dest) |= FUNC_NONBANKED(src); FUNC_BANKED(dest) |= FUNC_BANKED(src); @@ -675,13 +684,14 @@ mergeSpec (sym_link * dest, sym_link * src, char *name) FUNC_ISOVERLAY(dest) |= FUNC_ISOVERLAY(src); FUNC_INTNO(dest) |= FUNC_INTNO(src); FUNC_REGBANK(dest) |= FUNC_REGBANK(src); + FUNC_ISINLINE (dest) |= FUNC_ISINLINE (src); return dest; } -/*------------------------------------------------------------------*/ +/*-------------------------------------------------------------------*/ /* genSymName - generates and returns a name used for anonymous vars */ -/*------------------------------------------------------------------*/ +/*-------------------------------------------------------------------*/ char * genSymName (int level) { @@ -735,6 +745,20 @@ newFloatLink () return p; } +/*------------------------------------------------------------------*/ +/* newFixed16x16Link - a new Float type */ +/*------------------------------------------------------------------*/ +sym_link * +newFixed16x16Link () +{ + sym_link *p; + + p = newLink (SPECIFIER); + SPEC_NOUN (p) = V_FIXED16X16; + + return p; +} + /*------------------------------------------------------------------*/ /* newLongLink() - new long type */ /*------------------------------------------------------------------*/ @@ -765,9 +789,23 @@ newIntLink () } /*------------------------------------------------------------------*/ -/* getSize - returns size of a type chain in bits */ +/* newBoolLink() - creates an bool type */ +/*------------------------------------------------------------------*/ +sym_link * +newBoolLink () +{ + sym_link *p; + + p = newLink (SPECIFIER); + SPEC_NOUN (p) = V_BIT; + + return p; +} + +/*------------------------------------------------------------------*/ +/* getSize - returns size of a type chain in bytes */ /*------------------------------------------------------------------*/ -unsigned int +unsigned int getSize (sym_link * p) { /* if nothing return 0 */ @@ -781,6 +819,8 @@ getSize (sym_link * p) return (IS_LONG (p) ? LONGSIZE : INTSIZE); case V_FLOAT: return FLOATSIZE; + case V_FIXED16X16: + return (4); case V_CHAR: return CHARSIZE; case V_VOID: @@ -806,7 +846,7 @@ getSize (sym_link * p) if (DCL_ELEM(p)) { return DCL_ELEM (p) * getSize (p->next); } else { - // werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + // werror (E_INTERNAL_ERROR, __FILE__, __LINE__, // "can not tell the size of an array[]"); return 0; } @@ -818,7 +858,7 @@ getSize (sym_link * p) case FPOINTER: case CPOINTER: case FUNCTION: - return (FPTRSIZE); + return (IFFUNC_BANKED (p) ? GPTRSIZE : FPTRSIZE); case GPOINTER: return (GPTRSIZE); @@ -827,35 +867,47 @@ getSize (sym_link * p) } } -/*---------------------------------------------------------------------*/ -/* getAllocSize - returns size of a type chain in bytes for allocation */ -/*---------------------------------------------------------------------*/ -unsigned int -getAllocSize (sym_link *p) +/*------------------------------------------------------------------*/ +/* checkStructFlexArray - check tree behind a struct */ +/*------------------------------------------------------------------*/ +static bool +checkStructFlexArray (symbol *sym, sym_link *p) { - if (IS_STRUCT (p) && SPEC_STRUCT (p)->type == STRUCT) - { - /* if this is a struct specifier then */ - /* calculate the size as it could end */ - /* with an array of unspecified length */ - symbol *sflds = SPEC_STRUCT (p)->fields; + /* if nothing return FALSE */ + if (!p) + return FALSE; - while (sflds && sflds->next) - sflds = sflds->next; + if (IS_SPEC (p)) + { + /* (nested) struct with flexible array member? */ + if (IS_STRUCT (p) && SPEC_STRUCT (p)->b_flexArrayMember) + { + werror (W_INVALID_FLEXARRAY); + return FALSE; + } + return FALSE; + } - if (sflds && !IS_BITFIELD (sflds->type)) - return sflds->offset + getAllocSize (sflds->type); - else - return SPEC_STRUCT (p)->size; + /* this is a declarator */ + if (IS_ARRAY (p)) + { + /* flexible array member? */ + if (!DCL_ELEM(p)) + { + if (!options.std_c99) + werror (W_C89_NO_FLEXARRAY); + return TRUE; + } + /* walk tree */ + return checkStructFlexArray (sym, p->next); } - else - return getSize (p); + return FALSE; } /*------------------------------------------------------------------*/ /* bitsForType - returns # of bits required to store this type */ /*------------------------------------------------------------------*/ -unsigned int +unsigned int bitsForType (sym_link * p) { /* if nothing return 0 */ @@ -871,6 +923,8 @@ bitsForType (sym_link * p) return (IS_LONG (p) ? LONGSIZE * 8 : INTSIZE * 8); case V_FLOAT: return FLOATSIZE * 8; + case V_FIXED16X16: + return (32); case V_CHAR: return CHARSIZE * 8; case V_VOID: @@ -952,7 +1006,7 @@ copySymbol (symbol * src) } /*------------------------------------------------------------------*/ -/* reverseSyms - reverses the links for a symbol chain */ +/* reverseSyms - reverses the links for a symbol chain */ /*------------------------------------------------------------------*/ symbol * reverseSyms (symbol * sym) @@ -977,7 +1031,7 @@ reverseSyms (symbol * sym) } /*------------------------------------------------------------------*/ -/* reverseLink - reverses the links for a type chain */ +/* reverseLink - reverses the links for a type chain */ /*------------------------------------------------------------------*/ sym_link * reverseLink (sym_link * type) @@ -1004,11 +1058,12 @@ reverseLink (sym_link * type) /*------------------------------------------------------------------*/ /* addSymChain - adds a symbol chain to the symboltable */ /*------------------------------------------------------------------*/ -void -addSymChain (symbol * symHead) +void +addSymChain (symbol ** symHead) { - symbol *sym = symHead; + symbol *sym = *symHead; symbol *csym = NULL; + symbol **symPtrPtr; int error = 0; for (; sym != NULL; sym = sym->next) @@ -1018,76 +1073,103 @@ addSymChain (symbol * symHead) if (!sym->level && !(IS_SPEC(sym->etype) && IS_TYPEDEF(sym->etype))) checkDecl (sym, 0); - - /* if already exists in the symbol table then check if - one of them is an extern definition if yes then - then check if the type match, if the types match then - delete the current entry and add the new entry */ + else + { + /* if this is an array without any dimension + then update the dimension from the initial value */ + if (IS_ARRAY (sym->type) && !DCL_ELEM (sym->type)) + DCL_ELEM (sym->type) = getNelements (sym->type, sym->ival); + } + + /* if already exists in the symbol table on the same level */ if ((csym = findSymWithLevel (SymbolTab, sym)) && - csym->level == sym->level) { + csym->level == sym->level) + { + /* if not formal parameter and not in file scope + then show symbol redefined error + else check if symbols have compatible types */ + if (!sym->_isparm && sym->level > 0) + error = 1; + else + { + /* If the previous definition was for an array with incomplete + type, and the new definition has completed the type, update + the original type to match */ + if (IS_DECL(csym->type) && DCL_TYPE(csym->type)==ARRAY + && IS_DECL(sym->type) && DCL_TYPE(sym->type)==ARRAY) + { + if (!DCL_ELEM(csym->type) && DCL_ELEM(sym->type)) + DCL_ELEM(csym->type) = DCL_ELEM(sym->type); + } - /* If the previous definition was for an array with incomplete */ - /* type, and the new definition has completed the type, update */ - /* the original type to match */ - if (IS_DECL(csym->type) && DCL_TYPE(csym->type)==ARRAY - && IS_DECL(sym->type) && DCL_TYPE(sym->type)==ARRAY) - { - if (!DCL_ELEM(csym->type) && DCL_ELEM(sym->type)) - 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 - #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; - if (compareTypeExact (csym->type, sym->type, sym->level) != 1) - error = 1; - - if (error) { - /* one definition extern ? */ - if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype)) - 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)) - 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; - } + error = 0; + if (csym->ival && sym->ival) + error = 1; + if (compareTypeExact (csym->type, sym->type, sym->level) != 1) + error = 1; + } - if (csym->ival && !sym->ival) - sym->ival = csym->ival; + if (error) + { + /* one definition extern ? */ + if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype)) + 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)) + 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; + } + + if (csym->ival && !sym->ival) + sym->ival = csym->ival; + + if (!csym->cdef && !sym->cdef && IS_EXTERN (sym->etype)) + { + /* if none of symbols is a compiler defined function + and at least one is not extern + then set the new symbol to non extern */ + SPEC_EXTR(sym->etype) = SPEC_EXTR(csym->etype); + } + + /* delete current entry */ + deleteSym (SymbolTab, csym, csym->name); + deleteFromSeg(csym); + + symPtrPtr = symHead; + while (*symPtrPtr && *symPtrPtr != csym) + symPtrPtr = &(*symPtrPtr)->next; + if (*symPtrPtr == csym) + *symPtrPtr = csym->next; + } - /* delete current entry */ - deleteSym (SymbolTab, csym, csym->name); - deleteFromSeg(csym); - } - /* add new entry */ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1); } @@ -1097,7 +1179,7 @@ addSymChain (symbol * symHead) /*------------------------------------------------------------------*/ /* funcInChain - DCL Type 'FUNCTION' found in type chain */ /*------------------------------------------------------------------*/ -int +int funcInChain (sym_link * lnk) { while (lnk) @@ -1120,7 +1202,7 @@ structElemType (sym_link * stype, value * id) sym_link *petype = getSpec (stype); if (fields && id) { - + /* look for the id */ while (fields) { @@ -1130,6 +1212,8 @@ structElemType (sym_link * stype, value * id) etype = getSpec (type); SPEC_SCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ? SPEC_SCLS (etype) : SPEC_SCLS (petype)); + SPEC_OCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ? + SPEC_OCLS (etype) : SPEC_OCLS (petype)); if (IS_SPEC (type)) SPEC_CONST (type) |= SPEC_CONST (stype); else @@ -1141,7 +1225,7 @@ structElemType (sym_link * stype, value * id) } werror (E_NOT_MEMBER, id->name); - + // the show must go on return newIntLink(); } @@ -1166,103 +1250,137 @@ getStructElement (structdef * sdef, symbol * sym) /*------------------------------------------------------------------*/ /* compStructSize - computes the size of a structure */ /*------------------------------------------------------------------*/ -int +int compStructSize (int su, structdef * sdef) { - int sum = 0, usum = 0; - int bitOffset = 0; - symbol *loop; - - /* for the identifiers */ - loop = sdef->fields; - while (loop) { + int sum = 0, usum = 0; + int bitOffset = 0; + symbol *loop; + + /* for the identifiers */ + loop = sdef->fields; + while (loop) { + + /* create the internal name for this variable */ + SNPRINTF (loop->rname, sizeof(loop->rname), "_%s", loop->name); + if (su == UNION) { + sum = 0; + bitOffset = 0; + } + SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0); + + /* if this is a bit field */ + if (loop->bitVar) { + + SPEC_BUNNAMED (loop->etype) = loop->bitUnnamed; + + /* change it to a unsigned bit */ + SPEC_NOUN (loop->etype) = V_BITFIELD; + /* ISO/IEC 9899 J.3.9 implementation defined behaviour: */ + /* a "plain" int bitfield is unsigned */ + if (!loop->etype->select.s.b_signed) + SPEC_USIGN(loop->etype) = 1; + + if (loop->bitVar == BITVAR_PAD) { + /* A zero length bitfield forces padding */ + SPEC_BLEN (loop->etype) = 0; + SPEC_BSTR (loop->etype) = bitOffset; + if (bitOffset > 0) + bitOffset = 8; /* padding is not needed when at bit 0 */ + loop->offset = sum; + } + else { + SPEC_BLEN (loop->etype) = loop->bitVar; - /* create the internal name for this variable */ - SNPRINTF (loop->rname, sizeof(loop->rname), "_%s", loop->name); - if (su == UNION) { - sum = 0; - bitOffset = 0; + if (bitOffset == 8) { + bitOffset = 0; + sum++; } - SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0); - - /* if this is a bit field */ - if (loop->bitVar) { - - /* change it to a unsigned bit */ - SPEC_NOUN (loop->etype) = V_BITFIELD; - SPEC_USIGN (loop->etype) = 1; - SPEC_BLEN (loop->etype) = loop->bitVar; - - if (loop->bitVar == BITVAR_PAD) { - /* A zero length bitfield forces padding */ - SPEC_BSTR (loop->etype) = bitOffset; - SPEC_BLEN (loop->etype) = 0; - bitOffset = 8; - loop->offset = sum; - } - else { - if (bitOffset == 8) { - bitOffset = 0; - sum++; - } - /* check if this fit into the remaining */ - /* bits of this byte else align it to the */ - /* next byte boundary */ - if (loop->bitVar <= (8 - bitOffset)) { - /* fits into current byte */ - loop->offset = sum; - SPEC_BSTR (loop->etype) = bitOffset; - bitOffset += loop->bitVar; - } - else if (!bitOffset) { - /* does not fit, but is already byte aligned */ - loop->offset = sum; - SPEC_BSTR (loop->etype) = bitOffset; - bitOffset += loop->bitVar; - } - else { - /* does not fit; need to realign first */ - sum++; - loop->offset = (su == UNION ? sum = 0 : sum); - bitOffset = 0; - SPEC_BSTR (loop->etype) = bitOffset; - bitOffset += loop->bitVar; - } - while (bitOffset>8) { - bitOffset -= 8; - sum++; - } - } + /* check if this fit into the remaining */ + /* bits of this byte else align it to the */ + /* next byte boundary */ + if (loop->bitVar <= (8 - bitOffset)) { + /* fits into current byte */ + loop->offset = sum; + SPEC_BSTR (loop->etype) = bitOffset; + bitOffset += loop->bitVar; + } + else if (!bitOffset) { + /* does not fit, but is already byte aligned */ + loop->offset = sum; + SPEC_BSTR (loop->etype) = bitOffset; + bitOffset += loop->bitVar; } else { - /* This is a non-bit field. Make sure we are */ - /* byte aligned first */ - if (bitOffset) { - sum++; - loop->offset = (su == UNION ? sum = 0 : sum); - bitOffset = 0; - } - loop->offset = sum; - checkDecl (loop, 1); - sum += getSize (loop->type); + if( TARGET_IS_PIC16 && getenv("PIC16_PACKED_BITFIELDS") ) { + /* if PIC16 && enviroment variable is set, then + * tightly pack bitfields, this means that when a + * bitfield goes beyond byte alignment, do not + * automatically start allocatint from next byte, + * but also use the available bits first */ + fprintf(stderr, ": packing bitfields in structures\n"); + SPEC_BSTR (loop->etype) = bitOffset; + bitOffset += loop->bitVar; + loop->offset = (su == UNION ? sum = 0 : sum); + } else { + /* does not fit; need to realign first */ + sum++; + loop->offset = (su == UNION ? sum = 0 : sum); + bitOffset = 0; + SPEC_BSTR (loop->etype) = bitOffset; + bitOffset += loop->bitVar; + } } - - loop = loop->next; - - /* if union then size = sizeof largest field */ - if (su == UNION) { - /* For UNION, round up after each field */ - sum += ((bitOffset+7)/8); - usum = max (usum, sum); + while (bitOffset>8) { + bitOffset -= 8; + sum++; } + } + } + else { + /* This is a non-bit field. Make sure we are */ + /* byte aligned first */ + if (bitOffset) { + sum++; + loop->offset = (su == UNION ? sum = 0 : sum); + bitOffset = 0; + } + loop->offset = sum; + checkDecl (loop, 1); + sum += getSize (loop->type); + + /* search for "flexibel array members" */ + /* and do some syntax checks */ + if ( su == STRUCT + && checkStructFlexArray (loop, loop->type)) + { + /* found a "flexible array member" */ + sdef->b_flexArrayMember = TRUE; + /* is another struct-member following? */ + if (loop->next) + werror (E_FLEXARRAY_NOTATEND); + /* is it the first struct-member? */ + else if (loop == sdef->fields) + werror (E_FLEXARRAY_INEMPTYSTRCT); + } + } + loop = loop->next; + + /* if union then size = sizeof largest field */ + if (su == UNION) { + /* For UNION, round up after each field */ + sum += ((bitOffset+7)/8); + usum = max (usum, sum); } - - /* For STRUCT, round up after all fields processed */ - if (su != UNION) - sum += ((bitOffset+7)/8); - return (su == UNION ? usum : sum); + } + + /* For STRUCT, round up after all fields processed */ + if (su != UNION) + sum += ((bitOffset+7)/8); + + return (su == UNION ? usum : sum); } /*-------------------------------------------------------------------*/ @@ -1289,12 +1407,12 @@ promoteAnonStructs (int su, structdef * sdef) /* 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 (;;) { @@ -1313,7 +1431,7 @@ promoteAnonStructs (int su, structdef * sdef) } dupfield = dupfield->next; } - + subfield->offset += base; if (subfield->next) subfield = subfield->next; @@ -1333,27 +1451,44 @@ promoteAnonStructs (int su, structdef * sdef) /*------------------------------------------------------------------*/ /* checkSClass - check the storage class specification */ /*------------------------------------------------------------------*/ -static void +static void checkSClass (symbol * sym, int isProto) { sym_link *t; - + if (getenv("DEBUG_SANITY")) { fprintf (stderr, "checkSClass: %s \n", sym->name); } - - /* type is literal can happen for enums change - to auto */ + + /* type is literal can happen for 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 */ if (SPEC_SCLS (sym->etype) == S_SBIT || SPEC_SCLS (sym->etype) == S_SFR) { SPEC_VOLATILE (sym->etype) = 1; } - + + /* make sure restrict is only used with pointers */ + if (SPEC_RESTRICT (sym->etype)) + { + werrorfl (sym->fileDef, sym->lineDef, E_BAD_RESTRICT); + SPEC_RESTRICT (sym->etype) = 0; + } + t = sym->type; + while (t) + { + if (IS_DECL (t) && DCL_PTR_RESTRICT (t) && !IS_PTR (t)) + { + werrorfl (sym->fileDef, sym->lineDef, E_BAD_RESTRICT); + DCL_PTR_RESTRICT (t) = 0; + break; + } + t = t->next; + } + /* if absolute address given then it mark it as volatile -- except in the PIC port */ @@ -1364,7 +1499,27 @@ checkSClass (symbol * sym, int isProto) if (IS_ABSOLUTE (sym->etype)) SPEC_VOLATILE (sym->etype) = 1; - + + if (TARGET_IS_MCS51 && + IS_ABSOLUTE (sym->etype) && + SPEC_SCLS (sym->etype) == S_SFR) + { + int n, size; + unsigned addr; + + if (SPEC_NOUN (sym->etype) == V_CHAR) + size = 8; + else if (SPEC_LONG (sym->etype) == 0) + size = 16; + else + size = 32; + + addr = SPEC_ADDR (sym->etype); + for (n=0; n> n) & 0xFF) < 0x80) + werror (W_SFR_ABSRANGE, sym->name); + } + /* If code memory is read only, then pointers to code memory */ /* implicitly point to constants -- make this explicit */ t = sym->type; @@ -1429,23 +1584,25 @@ checkSClass (symbol * sym, int isProto) /* if this is an automatic 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); + if (SPEC_SCLS (sym->etype) != S_BIT) { + 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); + } } } } /* automatic symbols cannot be given */ /* an absolute address ignore it */ - if (sym->level && + if (sym->level && !IS_STATIC(sym->etype) && SPEC_ABSA (sym->etype) && (options.stackAuto || reentrant)) { @@ -1456,6 +1613,7 @@ checkSClass (symbol * sym, int isProto) /* arrays & pointers cannot be defined for bits */ /* SBITS or SFRs or BIT */ if ((IS_ARRAY (sym->type) || IS_PTR (sym->type)) && + !IS_FUNCPTR (sym->type) && (SPEC_NOUN (sym->etype) == V_BIT || SPEC_NOUN (sym->etype) == V_SBIT || SPEC_NOUN (sym->etype) == V_BITFIELD || @@ -1479,14 +1637,16 @@ checkSClass (symbol * sym, int isProto) //!sym->level && port->mem.code_ro && !IS_EXTERN (sym->etype) && + !SPEC_ABSA (sym->etype) && !funcInChain (sym->type)) werror (E_CODE_NO_INIT, sym->name); } /* 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 && - !IS_STATIC(sym->etype)) + if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED + && !IS_STATIC(sym->etype) + ) { if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type))) { @@ -1499,7 +1659,7 @@ checkSClass (symbol * sym, int isProto) * control this allocation, but the code was originally that way, and * changing it for non-390 ports breaks the compiler badly. */ - bool useXdata = (TARGET_IS_DS390 || TARGET_IS_DS400) ? + bool useXdata = (TARGET_IS_DS390 || TARGET_IS_DS400) ? 1 : options.useXstack; SPEC_SCLS (sym->etype) = (useXdata ? S_XDATA : S_FIXED); @@ -1510,32 +1670,33 @@ checkSClass (symbol * sym, int isProto) /*------------------------------------------------------------------*/ /* changePointer - change pointer to functions */ /*------------------------------------------------------------------*/ -void +void changePointer (sym_link * p) { /* go thru the chain of declarations */ /* if we find a pointer to a function */ - /* unconditionally change it to a ptr */ - /* to code area */ + /* change it to a ptr to code area */ + /* unless the function is banked. */ for (; p; p = p->next) { if (!IS_SPEC (p) && DCL_TYPE (p) == UPOINTER) DCL_TYPE (p) = port->unqualified_pointer; if (IS_PTR (p) && IS_FUNC (p->next)) + if (!IFFUNC_BANKED(p->next)) DCL_TYPE (p) = CPOINTER; } } /*------------------------------------------------------------------*/ -/* checkDecl - does semantic validation of a declaration */ +/* checkDecl - does semantic validation of a declaration */ /*------------------------------------------------------------------*/ -int +int checkDecl (symbol * sym, int isProto) { - checkSClass (sym, isProto); /* check the storage class */ - changePointer (sym->type); /* change pointers if required */ + checkSClass (sym, isProto); /* check the storage class */ + changePointer (sym->type); /* change pointers if required */ /* if this is an array without any dimension then update the dimension from the initial value */ @@ -1553,6 +1714,7 @@ copyLinkChain (sym_link * p) { sym_link *head, *curr, *loop; + /* note: v_struct and v_struct->fields are not copied! */ curr = p; head = loop = (curr ? newLink (p->class) : (void *) NULL); while (curr) @@ -1570,7 +1732,7 @@ copyLinkChain (sym_link * p) /* cleanUpBlock - cleansup the symbol table specified for all the */ /* symbols in the given block */ /*------------------------------------------------------------------*/ -void +void cleanUpBlock (bucket ** table, int block) { int i; @@ -1593,7 +1755,7 @@ cleanUpBlock (bucket ** table, int block) /* cleanUpLevel - cleansup the symbol table specified for all the */ /* symbols in the given level */ /*------------------------------------------------------------------*/ -void +void cleanUpLevel (bucket ** table, int level) { int i; @@ -1627,7 +1789,7 @@ computeTypeOr (sym_link * etype1, sym_link * etype2, sym_link * reType) SPEC_USIGN (reType) = SPEC_USIGN (etype1); return reType; } - + if (SPEC_USIGN (etype1)) { if ( IS_LITERAL (etype2) @@ -1700,15 +1862,20 @@ computeType (sym_link * type1, sym_link * type2, /* which ever is greater in size */ 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 both are fixed16x16 then result is float */ + else if (IS_FIXED16X16(etype1) && IS_FIXED16X16(etype2)) + rType = newFixed16x16Link(); + else if (IS_FIXED16X16(etype1) && IS_FLOAT (etype2)) + rType = newFloatLink (); + else if (IS_FLOAT (etype1) && IS_FIXED16X16 (etype2) ) + rType = newFloatLink (); + + /* if both are bitvars choose the larger one */ + else if (IS_BITVAR (etype1) && IS_BITVAR (etype2)) + rType = SPEC_BLEN (etype1) >= SPEC_BLEN (etype2) ? + copyLinkChain (type1) : copyLinkChain (type2); + + /* if only one of them is a bit variable then the other one prevails */ else if (IS_BITVAR (etype1) && !IS_BITVAR (etype2)) { rType = copyLinkChain (type2); @@ -1723,10 +1890,9 @@ computeType (sym_link * type1, sym_link * type2, if (getSize (etype2) > 1) SPEC_NOUN (getSpec (rType)) = V_INT; } - else - /* if one of them is a pointer or array then that - prevails */ - if (IS_PTR (type1) || IS_ARRAY (type1)) + /* if one of them is a pointer or array then that + prevails */ + else if (IS_PTR (type1) || IS_ARRAY (type1)) rType = copyLinkChain (type1); else if (IS_PTR (type2) || IS_ARRAY (type2)) rType = copyLinkChain (type2); @@ -1738,7 +1904,7 @@ computeType (sym_link * type1, sym_link * type2, reType = getSpec (rType); /* avoid conflicting types */ - reType->select.s._signed = 0; + reType->select.s.b_signed = 0; /* if result is a literal then make not so */ if (IS_LITERAL (reType)) @@ -1746,6 +1912,17 @@ computeType (sym_link * type1, sym_link * type2, switch (resultType) { + case RESULT_TYPE_IFX: + if (TARGET_IS_HC08) + break; + //fallthrough + case RESULT_TYPE_BIT: + if (op == ':') + { + SPEC_NOUN (reType) = V_BIT; + return rType; + } + break; case RESULT_TYPE_CHAR: if (IS_BITVAR (reType)) { @@ -1776,28 +1953,34 @@ computeType (sym_link * type1, sym_link * type2, } else if (IS_CHAR (reType)) { - if (op == '|' || op == '^') - return computeTypeOr (etype1, etype2, reType); - else if ( op == '&' - && SPEC_USIGN (etype1) != SPEC_USIGN (etype2)) + /* promotion of some special cases */ + switch (op) { - SPEC_USIGN (reType) = 1; - return rType; - } - else if (op == '*') - { - SPEC_NOUN (reType) = V_INT; - SPEC_USIGN (reType) = 0; - return rType; - } - /* TODO: should be in SDCCast.c */ - else if ( op == '/' - && ( !SPEC_USIGN (etype1) - || !SPEC_USIGN (etype2))) - { - SPEC_NOUN (reType) = V_INT; - SPEC_USIGN (reType) = 0; - return rType; + case '|': + case '^': + return computeTypeOr (etype1, etype2, reType); + case '&': + if (SPEC_USIGN (etype1) != SPEC_USIGN (etype2)) + { + SPEC_USIGN (reType) = 1; + return rType; + } + break; + case '*': + SPEC_NOUN (reType) = V_INT; + SPEC_USIGN (reType) = 0; + return rType; + case '/': + /* if both are unsigned char then no promotion required */ + if (!(SPEC_USIGN (etype1) && SPEC_USIGN (etype2))) + { + SPEC_NOUN (reType) = V_INT; + SPEC_USIGN (reType) = 0; + return rType; + } + break; + default: + break; } } break; @@ -1835,7 +2018,7 @@ computeType (sym_link * type1, sym_link * type2, 2 * 100 = 200; - ToDo: document '|', '^' and '&' - + Homework: - why is (200 * 200 < 0) true? - why is { char l = 200, r = 200; (r * l > 0) } true? */ @@ -1844,12 +2027,12 @@ computeType (sym_link * type1, sym_link * type2, && ( (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)) + && !(bitsForType (etype1) < bitsForType (reType)) /* char require special handling */ && !IS_CHAR (etype1)) - || /* same for 2nd operand */ + || /* same for 2nd operand */ (SPEC_USIGN (etype2) - && !(getSize (etype2) < getSize (reType)) + && !(bitsForType (etype2) < bitsForType (reType)) && !IS_CHAR (etype2)) || /* if both are 'unsigned char' and not promoted let the result be unsigned too */ @@ -1865,8 +2048,28 @@ computeType (sym_link * type1, sym_link * type2, return rType; } +int +comparePtrType (sym_link * dest, sym_link * src, bool bMustCast) +{ + int res; + + if (IS_VOID (src->next) && IS_VOID (dest->next)) + return bMustCast ? -1 : 1; + if ((IS_VOID (src->next) && !IS_VOID (dest->next)) || + (!IS_VOID (src->next) && IS_VOID (dest->next)) ) + return -1; + res = compareType (dest->next, src->next); + if (res == 1) + return bMustCast ? -1 : 1; + else if (res == -2) + return -2; + else + return 0; +} + /*--------------------------------------------------------------------*/ -/* compareType - will do type check return 1 if match, -1 if castable */ +/* compareType - will do type check return 1 if match, 0 if no match, */ +/* -1 if castable, -2 if only signedness differs */ /*--------------------------------------------------------------------*/ int compareType (sym_link * dest, sym_link * src) @@ -1885,24 +2088,43 @@ compareType (sym_link * dest, sym_link * src) { if (IS_DECL (src)) { - if (DCL_TYPE (src) == DCL_TYPE (dest)) { - if (IS_FUNC(src)) { - //checkFunction(src,dest); + /* banked function pointer */ + if (IS_GENPTR (dest) && IS_GENPTR (src)) + { + if (IS_FUNC (src->next) && IS_VOID(dest->next)) + return -1; + if (IS_FUNC (dest->next) && IS_VOID(src->next)) + return -1; + return comparePtrType(dest, src, FALSE); + } + + if (DCL_TYPE (src) == DCL_TYPE (dest)) + { + if (IS_FUNC(src)) + { + //checkFunction(src,dest); + } + return comparePtrType(dest, src, FALSE); + } + if (IS_PTR (dest) && IS_GENPTR (src) && IS_VOID(src->next)) + { + return -1; + } + if (IS_PTR (src) && + (IS_GENPTR (dest) || + ((DCL_TYPE(src) == POINTER) && (DCL_TYPE(dest) == IPOINTER)) + )) + { + return comparePtrType(dest, src, TRUE); + } + if (IS_PTR (dest) && IS_ARRAY (src)) + { + value *val=aggregateToPointer (valFromType(src)); + int res=compareType (dest, val->type); + Safe_free(val->type); + Safe_free(val); + return res; } - return compareType (dest->next, src->next); - } - if (IS_PTR (dest) && IS_GENPTR (src) && IS_VOID(src->next)) { - return -1; - } - if (IS_PTR (src) && IS_GENPTR (dest)) - return -1; - if (IS_PTR (dest) && IS_ARRAY (src)) { - value *val=aggregateToPointer (valFromType(src)); - int res=compareType (dest, val->type); - Safe_free(val->type); - Safe_free(val); - return res; - } if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src)) return compareType (dest->next, src); return 0; @@ -1913,6 +2135,9 @@ compareType (sym_link * dest, sym_link * src) return 0; } + if (IS_PTR (src) && IS_VOID (dest)) + return -1; + /* if one is a specifier and the other is not */ if ((IS_SPEC (src) && !IS_SPEC (dest)) || (IS_SPEC (dest) && !IS_SPEC (src))) @@ -1944,7 +2169,7 @@ compareType (sym_link * dest, sym_link * src) instead of the next two lines, but the regression tests fail with them; I guess it's a problem with replaceCheaperOp */ getSize (dest) == getSize (src) && - !(!IS_BIT (dest) && IS_BIT (src))) + (IS_BIT (dest) == IS_BIT (src))) return 1; else if (IS_ARITHMETIC (dest) && IS_ARITHMETIC (src)) return -1; @@ -1962,7 +2187,7 @@ compareType (sym_link * dest, sym_link * src) return -1; if (SPEC_USIGN (dest) != SPEC_USIGN (src)) - return -1; + return -2; return 1; } @@ -1974,7 +2199,7 @@ int compareTypeExact (sym_link * dest, sym_link * src, int level) { STORAGE_CLASS srcScls, destScls; - + if (!dest && !src) return 1; @@ -2040,7 +2265,7 @@ compareTypeExact (sym_link * dest, sym_link * src, int level) /* if one them ended we have a problem */ if ((exargs && !acargs && !IS_VOID (exargs->type)) || (!exargs && acargs && !IS_VOID (acargs->type))) - return 0; + return 0; return 1; } return compareTypeExact (dest->next, src->next, level); @@ -2077,7 +2302,7 @@ compareTypeExact (sym_link * dest, sym_link * src, int level) if (SPEC_SHORT (dest) != SPEC_SHORT (src)) return 0; } - + if (IS_STRUCT (dest)) { if (SPEC_STRUCT (dest) != SPEC_STRUCT (src)) @@ -2094,10 +2319,10 @@ compareTypeExact (sym_link * dest, sym_link * src, int level) return 0; if (SPEC_ABSA (dest) && SPEC_ADDR (dest) != SPEC_ADDR (src)) return 0; - + destScls = SPEC_SCLS (dest); srcScls = SPEC_SCLS (src); - + /* Compensate for const to const code change in checkSClass() */ if (!level & port->mem.code_ro && SPEC_CONST (dest)) { @@ -2107,12 +2332,12 @@ compareTypeExact (sym_link * dest, sym_link * src, int level) srcScls = S_CODE; } - /* compensate for allocGlobal() */ + /* compensate for allocGlobal() */ if ((srcScls == S_FIXED || srcScls == S_AUTO) && port->mem.default_globl_map == xdata && !level) srcScls = S_XDATA; - + if (level>0 && !SPEC_STAT (dest)) { /* Compensate for hack-o-matic in checkSClass() */ @@ -2142,12 +2367,12 @@ compareTypeExact (sym_link * dest, sym_link * src, int level) #endif return 0; } - + return 1; } /*------------------------------------------------------------------*/ -/* inCalleeSaveList - return 1 if found in callee save list */ +/* inCalleeSaveList - return 1 if found in callee save list */ /*------------------------------------------------------------------*/ static int calleeCmp(void *p1, void *p2) @@ -2164,8 +2389,8 @@ inCalleeSaveList(char *s) } /*-----------------------------------------------------------------*/ -/* aggregateToPointer: change an agggregate type function */ -/* argument to a pointer to that type. */ +/* aggregateToPointer: change an aggregate type function */ +/* argument to a pointer to that type. */ /*-----------------------------------------------------------------*/ value * aggregateToPointer (value * val) @@ -2203,6 +2428,8 @@ aggregateToPointer (value * val) } break; case S_AUTO: + DCL_TYPE (val->type) = PTR_TYPE(SPEC_OCLS(val->etype)); + break; case S_DATA: case S_REGISTER: DCL_TYPE (val->type) = POINTER; @@ -2219,7 +2446,7 @@ aggregateToPointer (value * val) default: DCL_TYPE (val->type) = port->unqualified_pointer; } - + /* is there is a symbol associated then */ /* change the type of the symbol as well */ if (val->sym) @@ -2233,7 +2460,7 @@ aggregateToPointer (value * val) /*------------------------------------------------------------------*/ /* checkFunction - does all kinds of check on a function */ /*------------------------------------------------------------------*/ -int +int checkFunction (symbol * sym, symbol *csym) { value *exargs, *acargs; @@ -2249,7 +2476,14 @@ checkFunction (symbol * sym, symbol *csym) werror(E_SYNTAX_ERROR, sym->name); return 0; } - + + /* move inline specifier from return type to function attributes */ + if (IS_INLINE (sym->etype)) + { + SPEC_INLINE (sym->etype) = 0; + FUNC_ISINLINE (sym->type) = 1; + } + /* make sure the type is complete and sane */ checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name); @@ -2268,13 +2502,6 @@ checkFunction (symbol * sym, symbol *csym) return 0; } - /* function cannot return bit */ - if (IS_BITVAR (sym->type->next)) - { - werror (E_FUNC_BIT, sym->name); - return 0; - } - /* check if this function is defined as calleeSaves then mark it as such */ FUNC_CALLEESAVES(sym->type) = inCalleeSaveList (sym->name); @@ -2289,10 +2516,15 @@ checkFunction (symbol * sym, symbol *csym) } } - for (argCnt=1, acargs = FUNC_ARGS(sym->type); - acargs; + if (IFFUNC_ISSHADOWREGS(sym->type) && !FUNC_ISISR (sym->type)) + { + werror (E_SHADOWREGS_NO_ISR, sym->name); + } + + for (argCnt=1, acargs = FUNC_ARGS(sym->type); + acargs; acargs=acargs->next, argCnt++) { - if (!acargs->sym) { + if (!acargs->sym) { // this can happen for reentrant functions werror(E_PARAM_NAME_OMITTED, sym->name, argCnt); // the show must go on: synthesize a name and symbol @@ -2303,13 +2535,16 @@ checkFunction (symbol * sym, symbol *csym) acargs->sym->etype = getSpec (acargs->sym->type); acargs->sym->_isparm = 1; strncpyz (acargs->sym->rname, acargs->name, sizeof(acargs->sym->rname)); - } else if (strcmp(acargs->sym->name, acargs->sym->rname)==0) { + } else if (strcmp(acargs->sym->name, acargs->sym->rname)==0) { // synthesized name werror(E_PARAM_NAME_OMITTED, sym->name, argCnt); } } argCnt--; + /*JCF: Mark the register bank as used*/ + RegBankUsed[FUNC_REGBANK (sym->type)] = 1; + if (!csym && !(csym = findSym (SymbolTab, sym, sym->name))) return 1; /* not defined nothing more to check */ @@ -2333,7 +2568,10 @@ checkFunction (symbol * sym, symbol *csym) werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt"); } - if (FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type)) + /* I don't think this is necessary for interrupts. An isr is a */ + /* root in the calling tree. */ + if ((FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type)) && + (!FUNC_ISISR (sym->type))) { werror (E_PREV_DEF_CONFLICT, csym->name, "using"); } @@ -2342,7 +2580,7 @@ checkFunction (symbol * sym, symbol *csym) { werror (E_PREV_DEF_CONFLICT, csym->name, "_naked"); } - + /* Really, reentrant should match regardless of argCnt, but */ /* this breaks some existing code (the fp lib functions). If */ /* the first argument is always passed the same way, this */ @@ -2354,6 +2592,17 @@ checkFunction (symbol * sym, symbol *csym) werror (E_PREV_DEF_CONFLICT, csym->name, "reentrant"); } + if (IFFUNC_ISWPARAM (csym->type) != IFFUNC_ISWPARAM (sym->type)) + { + werror (E_PREV_DEF_CONFLICT, csym->name, "wparam"); + } + + if (IFFUNC_ISSHADOWREGS (csym->type) != IFFUNC_ISSHADOWREGS (sym->type)) + { + werror (E_PREV_DEF_CONFLICT, csym->name, "shadowregs"); + } + + /* compare expected args with actual args */ exargs = FUNC_ARGS(csym->type); acargs = FUNC_ARGS(sym->type); @@ -2432,10 +2681,26 @@ void cdbStructBlock (int block) } } +/*-----------------------------------------------------------------*/ +/* processFuncPtrArgs - does some processing with args of func ptrs*/ +/*-----------------------------------------------------------------*/ +void +processFuncPtrArgs (sym_link * funcType) +{ + value *val = FUNC_ARGS(funcType); + + /* if it is void then remove parameters */ + if (val && IS_VOID (val->type)) + { + FUNC_ARGS(funcType) = NULL; + return; + } +} + /*-----------------------------------------------------------------*/ /* processFuncArgs - does some processing with function args */ /*-----------------------------------------------------------------*/ -void +void processFuncArgs (symbol * func) { value *val; @@ -2477,15 +2742,15 @@ processFuncArgs (symbol * func) { int argreg = 0; char buffer[SDCC_NAME_MAX+1]; - + SNPRINTF (buffer, sizeof(buffer), "%s parameter %d", func->name, pNum); checkTypeSanity (val->etype, buffer); - + /* mark it as a register parameter if the function does not have VA_ARG and as port dictates */ if (!IFFUNC_HASVARARGS(funcType) && - (argreg = (*port->reg_parm) (val->type))) + (argreg = (*port->reg_parm) (val->type, FUNC_ISREENT(funcType)))) { SPEC_REGPARM (val->etype) = 1; SPEC_ARGREG(val->etype) = argreg; @@ -2525,10 +2790,13 @@ processFuncArgs (symbol * func) /* synthesize a variable name */ if (!val->sym) { - SNPRINTF (val->name, sizeof(val->name), + SNPRINTF (val->name, sizeof(val->name), "_%s_PARM_%d", func->name, pNum++); val->sym = newSymbol (val->name, 1); - SPEC_OCLS (val->etype) = port->mem.default_local_map; + if (SPEC_SCLS(val->etype) == S_BIT) + SPEC_OCLS (val->etype) = bit; + else + SPEC_OCLS (val->etype) = port->mem.default_local_map; val->sym->type = copyLinkChain (val->type); val->sym->etype = getSpec (val->sym->type); val->sym->_isparm = 1; @@ -2540,7 +2808,7 @@ processFuncArgs (symbol * func) SPEC_STAT (func->etype); } #endif - addSymChain (val->sym); + addSymChain (&val->sym); } else /* symbol name given create synth name */ @@ -2549,9 +2817,12 @@ processFuncArgs (symbol * func) SNPRINTF (val->name, sizeof(val->name), "_%s_PARM_%d", func->name, pNum++); strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname)); val->sym->_isparm = 1; - SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = - (options.model != MODEL_SMALL ? xdata : data); - + if (SPEC_SCLS(val->etype) == S_BIT) + SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = bit; + else + SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = + port->mem.default_local_map; + #if 0 /* ?? static functions shouldn't imply static parameters - EEP */ if (IS_SPEC(func->etype)) { @@ -2560,6 +2831,8 @@ processFuncArgs (symbol * func) } #endif } + if (SPEC_OCLS (val->sym->etype) == pdata) + val->sym->iaccess = 1; if (!isinSet(operKeyReset, val->sym)) { addSet (&operKeyReset, val->sym); applyToSet (operKeyReset, resetParmKey); @@ -2571,7 +2844,7 @@ processFuncArgs (symbol * func) /*-----------------------------------------------------------------*/ /* isSymbolEqual - compares two symbols return 1 if they match */ /*-----------------------------------------------------------------*/ -int +int isSymbolEqual (symbol * dest, symbol * src) { /* if pointers match then equal */ @@ -2600,10 +2873,8 @@ void PT(sym_link *type) void printTypeChain (sym_link * start, FILE * of) { + struct dbuf_s dbuf; int nlr = 0; - value *args; - sym_link * type, * search; - STORAGE_CLASS scls; if (!of) { @@ -2611,8 +2882,23 @@ printTypeChain (sym_link * start, FILE * of) nlr = 1; } + dbuf_init (&dbuf, 1024); + dbuf_printTypeChain (start, &dbuf); + dbuf_write_and_destroy (&dbuf, of); + + if (nlr) + putc ('\n', of); +} + +void +dbuf_printTypeChain (sym_link * start, struct dbuf_s *dbuf) +{ + value *args; + sym_link * type, * search; + STORAGE_CLASS scls; + if (start==NULL) { - fprintf (of, "void"); + dbuf_append_str (dbuf, "void"); return; } @@ -2630,20 +2916,20 @@ printTypeChain (sym_link * start, FILE * of) while (type) { if (type==start) { - switch (scls) + switch (scls) { - case S_DATA: fprintf (of, "data-"); break; - case S_XDATA: fprintf (of, "xdata-"); break; - case S_SFR: fprintf (of, "sfr-"); break; - case S_SBIT: fprintf (of, "sbit-"); break; - case S_CODE: fprintf (of, "code-"); break; - case S_IDATA: fprintf (of, "idata-"); break; - case S_PDATA: fprintf (of, "pdata-"); break; - case S_LITERAL: fprintf (of, "literal-"); break; - case S_STACK: fprintf (of, "stack-"); break; - case S_XSTACK: fprintf (of, "xstack-"); break; - case S_BIT: fprintf (of, "bit-"); break; - case S_EEPROM: fprintf (of, "eeprom-"); break; + case S_DATA: dbuf_append_str (dbuf, "data-"); break; + case S_XDATA: dbuf_append_str (dbuf, "xdata-"); break; + case S_SFR: dbuf_append_str (dbuf, "sfr-"); break; + case S_SBIT: dbuf_append_str (dbuf, "sbit-"); break; + case S_CODE: dbuf_append_str (dbuf, "code-"); break; + case S_IDATA: dbuf_append_str (dbuf, "idata-"); break; + case S_PDATA: dbuf_append_str (dbuf, "pdata-"); break; + case S_LITERAL: dbuf_append_str (dbuf, "literal-"); break; + case S_STACK: dbuf_append_str (dbuf, "stack-"); break; + case S_XSTACK: dbuf_append_str (dbuf, "xstack-"); break; + case S_BIT: dbuf_append_str (dbuf, "bit-"); break; + case S_EEPROM: dbuf_append_str (dbuf, "eeprom-"); break; default: break; } } @@ -2652,57 +2938,60 @@ printTypeChain (sym_link * start, FILE * of) { if (!IS_FUNC(type)) { if (DCL_PTR_VOLATILE (type)) { - fprintf (of, "volatile-"); + dbuf_append_str (dbuf, "volatile-"); } if (DCL_PTR_CONST (type)) { - fprintf (of, "const-"); + dbuf_append_str (dbuf, "const-"); + } + if (DCL_PTR_RESTRICT (type)) { + dbuf_append_str (dbuf, "restrict-"); } } switch (DCL_TYPE (type)) { case FUNCTION: - fprintf (of, "function %s %s", + dbuf_printf (dbuf, "function %s %s", (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "), (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " ")); - fprintf (of, "( "); - for (args = FUNC_ARGS(type); - args; + dbuf_append_str (dbuf, "( "); + for (args = FUNC_ARGS(type); + args; args=args->next) { - printTypeChain(args->type, of); + dbuf_printTypeChain(args->type, dbuf); if (args->next) - fprintf(of, ", "); + dbuf_append_str (dbuf, ", "); } - fprintf (of, ") "); + dbuf_append_str (dbuf, ") "); break; case GPOINTER: - fprintf (of, "generic* "); + dbuf_append_str (dbuf, "generic* "); break; case CPOINTER: - fprintf (of, "code* "); + dbuf_append_str (dbuf, "code* "); break; case FPOINTER: - fprintf (of, "xdata* "); + dbuf_append_str (dbuf, "xdata* "); break; case EEPPOINTER: - fprintf (of, "eeprom* "); + dbuf_append_str (dbuf, "eeprom* "); break; case POINTER: - fprintf (of, "near* "); + dbuf_append_str (dbuf, "near* "); break; case IPOINTER: - fprintf (of, "idata* "); + dbuf_append_str (dbuf, "idata* "); break; case PPOINTER: - fprintf (of, "pdata* "); + dbuf_append_str (dbuf, "pdata* "); break; case UPOINTER: - fprintf (of, "unknown* "); + dbuf_append_str (dbuf, "unknown* "); break; case ARRAY: if (DCL_ELEM(type)) { - fprintf (of, "[%d] ", DCL_ELEM(type)); + dbuf_printf (dbuf, "[%d] ", DCL_ELEM(type)); } else { - fprintf (of, "[] "); + dbuf_append_str (dbuf, "[] "); } break; } @@ -2710,53 +2999,57 @@ printTypeChain (sym_link * start, FILE * of) else { if (SPEC_VOLATILE (type)) - fprintf (of, "volatile-"); + dbuf_append_str (dbuf, "volatile-"); if (SPEC_CONST (type)) - fprintf (of, "const-"); + dbuf_append_str (dbuf, "const-"); if (SPEC_USIGN (type)) - fprintf (of, "unsigned-"); + dbuf_append_str (dbuf, "unsigned-"); switch (SPEC_NOUN (type)) { case V_INT: if (IS_LONG (type)) - fprintf (of, "long-"); - fprintf (of, "int"); + dbuf_append_str (dbuf, "long-"); + dbuf_append_str (dbuf, "int"); break; case V_CHAR: - fprintf (of, "char"); + dbuf_append_str (dbuf, "char"); break; case V_VOID: - fprintf (of, "void"); + dbuf_append_str (dbuf, "void"); break; case V_FLOAT: - fprintf (of, "float"); + dbuf_append_str (dbuf, "float"); + break; + + case V_FIXED16X16: + dbuf_append_str (dbuf, "fixed16x16"); break; case V_STRUCT: - fprintf (of, "struct %s", SPEC_STRUCT (type)->tag); + dbuf_printf (dbuf, "struct %s", SPEC_STRUCT (type)->tag); break; case V_SBIT: - fprintf (of, "sbit"); + dbuf_append_str (dbuf, "sbit"); break; case V_BIT: - fprintf (of, "bit"); + dbuf_append_str (dbuf, "bit"); break; case V_BITFIELD: - fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); + dbuf_printf (dbuf, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); break; case V_DOUBLE: - fprintf (of, "double"); + dbuf_append_str (dbuf, "double"); break; default: - fprintf (of, "unknown type"); + dbuf_append_str (dbuf, "unknown type"); break; } } @@ -2765,10 +3058,8 @@ printTypeChain (sym_link * start, FILE * of) search = search->next; type = search; if (type) - fputc (' ', of); + dbuf_append_char(dbuf, ' '); } - if (nlr) - fprintf (of, "\n"); } /*--------------------------------------------------------------------*/ @@ -2794,7 +3085,7 @@ printTypeChainRaw (sym_link * start, FILE * of) } type = start; - + while (type) { if (IS_DECL (type)) @@ -2806,16 +3097,22 @@ printTypeChainRaw (sym_link * start, FILE * of) if (DCL_PTR_CONST (type)) { fprintf (of, "const-"); } + if (DCL_PTR_RESTRICT (type)) { + fprintf (of, "restrict-"); + } } switch (DCL_TYPE (type)) { case FUNCTION: - fprintf (of, "function %s %s", + if (IFFUNC_ISINLINE(type)) { + fprintf (of, "inline-"); + } + fprintf (of, "function %s %s", (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "), (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " ")); fprintf (of, "( "); - for (args = FUNC_ARGS(type); - args; + for (args = FUNC_ARGS(type); + args; args=args->next) { printTypeChain(args->type, of); if (args->next) @@ -2864,7 +3161,7 @@ printTypeChainRaw (sym_link * start, FILE * of) } else if (IS_SPEC (type)) { - switch (SPEC_SCLS (type)) + switch (SPEC_SCLS (type)) { case S_DATA: fprintf (of, "data-"); break; case S_XDATA: fprintf (of, "xdata-"); break; @@ -2906,6 +3203,10 @@ printTypeChainRaw (sym_link * start, FILE * of) fprintf (of, "float"); break; + case V_FIXED16X16: + fprintf (of, "fixed16x16"); + break; + case V_STRUCT: fprintf (of, "struct %s", SPEC_STRUCT (type)->tag); break; @@ -2946,7 +3247,7 @@ printTypeChainRaw (sym_link * start, FILE * of) /* powof2 - returns power of two for the number if number is pow 2 */ /*-----------------------------------------------------------------*/ int -powof2 (TYPE_UDWORD num) +powof2 (TYPE_TARGET_ULONG num) { int nshifts = 0; int n1s = 0; @@ -2960,7 +3261,7 @@ powof2 (TYPE_UDWORD num) } if (n1s > 1 || nshifts == 0) - return 0; + return -1; return nshifts - 1; } @@ -2975,16 +3276,30 @@ symbol *__fslteq; symbol *__fsgt; symbol *__fsgteq; -/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED */ -symbol *__muldiv[3][3][2]; +symbol *__fps16x16_add; +symbol *__fps16x16_sub; +symbol *__fps16x16_mul; +symbol *__fps16x16_div; +symbol *__fps16x16_eq; +symbol *__fps16x16_neq; +symbol *__fps16x16_lt; +symbol *__fps16x16_lteq; +symbol *__fps16x16_gt; +symbol *__fps16x16_gteq; + +/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED/BOTH */ +symbol *__muldiv[3][3][4]; /* Dims: BYTE/WORD/DWORD SIGNED/UNSIGNED */ sym_link *__multypes[3][2]; /* Dims: to/from float, BYTE/WORD/DWORD, SIGNED/USIGNED */ symbol *__conv[2][3][2]; +/* Dims: to/from fixed16x16, BYTE/WORD/DWORD/FLOAT, SIGNED/USIGNED */ +symbol *__fp16x16conv[2][4][2]; /* Dims: shift left/shift right, BYTE/WORD/DWORD, SIGNED/UNSIGNED */ symbol *__rlrr[2][3][2]; sym_link *floatType; +sym_link *fixed16x16Type; static char * _mangleFunctionName(char *in) @@ -3006,14 +3321,15 @@ _mangleFunctionName(char *in) /* 'i' - int */ /* 'l' - long */ /* 'f' - float */ +/* 'q' - fixed16x16 */ /* 'v' - void */ /* '*' - pointer - default (GPOINTER) */ /* modifiers - 'u' - unsigned */ /* pointer modifiers - 'g' - generic */ /* 'x' - xdata */ /* 'p' - code */ -/* 'd' - data */ -/* 'F' - function */ +/* 'd' - data */ +/* 'F' - function */ /* examples : "ig*" - generic int * */ /* "cx*" - char xdata * */ /* "ui" - unsigned int */ @@ -3026,7 +3342,7 @@ sym_link *typeFromStr (char *s) do { sym_link *nr; switch (*s) { - case 'u' : + case 'u' : usign = 1; s++; continue ; @@ -3049,6 +3365,10 @@ sym_link *typeFromStr (char *s) r->class = SPECIFIER; SPEC_NOUN(r) = V_FLOAT; break; + case 'q': + r->class = SPECIFIER; + SPEC_NOUN(r) = V_FIXED16X16; + break; case 'v': r->class = SPECIFIER; SPEC_NOUN(r) = V_VOID; @@ -3089,7 +3409,7 @@ sym_link *typeFromStr (char *s) s++; break; default: - werror(E_INTERNAL_ERROR, __FILE__, __LINE__, + werror(E_INTERNAL_ERROR, __FILE__, __LINE__, "typeFromStr: unknown type"); break; } @@ -3105,7 +3425,7 @@ sym_link *typeFromStr (char *s) /*-----------------------------------------------------------------*/ /* initCSupport - create functions for C support routines */ /*-----------------------------------------------------------------*/ -void +void initCSupport () { const char *smuldivmod[] = @@ -3114,11 +3434,15 @@ initCSupport () }; const char *sbwd[] = { - "char", "int", "long" + "char", "int", "long", "fixed16x16", + }; + const char *fp16x16sbwd[] = + { + "char", "int", "long", "float", }; const char *ssu[] = { - "s", "u" + "s", "su", "us", "u" }; const char *srlrr[] = { @@ -3133,6 +3457,7 @@ initCSupport () } floatType = newFloatLink (); + fixed16x16Type = newFixed16x16Link (); for (bwd = 0; bwd < 3; bwd++) { @@ -3167,6 +3492,18 @@ initCSupport () __fsgt = funcOfType ("__fsgt", CHARTYPE, floatType, 2, options.float_rent); __fsgteq = funcOfType ("__fsgteq", CHARTYPE, floatType, 2, options.float_rent); + __fps16x16_add = funcOfType ("__fps16x16_add", fixed16x16Type, fixed16x16Type, 2, options.float_rent); + __fps16x16_sub = funcOfType ("__fps16x16_sub", fixed16x16Type, fixed16x16Type, 2, options.float_rent); + __fps16x16_mul = funcOfType ("__fps16x16_mul", fixed16x16Type, fixed16x16Type, 2, options.float_rent); + __fps16x16_div = funcOfType ("__fps16x16_div", fixed16x16Type, fixed16x16Type, 2, options.float_rent); + __fps16x16_eq = funcOfType ("__fps16x16_eq", CHARTYPE, fixed16x16Type, 2, options.float_rent); + __fps16x16_neq = funcOfType ("__fps16x16_neq", CHARTYPE, fixed16x16Type, 2, options.float_rent); + __fps16x16_lt = funcOfType ("__fps16x16_lt", CHARTYPE, fixed16x16Type, 2, options.float_rent); + __fps16x16_lteq = funcOfType ("__fps16x16_lteq", CHARTYPE, fixed16x16Type, 2, options.float_rent); + __fps16x16_gt = funcOfType ("__fps16x16_gt", CHARTYPE, fixed16x16Type, 2, options.float_rent); + __fps16x16_gteq = funcOfType ("__fps16x16_gteq", CHARTYPE, fixed16x16Type, 2, options.float_rent); + + for (tofrom = 0; tofrom < 2; tofrom++) { for (bwd = 0; bwd < 3; bwd++) @@ -3175,18 +3512,44 @@ initCSupport () { if (tofrom) { - SNPRINTF (buffer, sizeof(buffer), "__fs2%s%s", ssu[su], sbwd[bwd]); + SNPRINTF (buffer, sizeof(buffer), "__fs2%s%s", ssu[su*3], sbwd[bwd]); __conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], floatType, 1, options.float_rent); } else { - SNPRINTF (buffer, sizeof(buffer), "__%s%s2fs", ssu[su], sbwd[bwd]); + SNPRINTF (buffer, sizeof(buffer), "__%s%s2fs", ssu[su*3], sbwd[bwd]); __conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent); } } } } + for (tofrom = 0; tofrom < 2; tofrom++) + { + for (bwd = 0; bwd < 4; bwd++) + { + for (su = 0; su < 2; su++) + { + if (tofrom) + { + SNPRINTF (buffer, sizeof(buffer), "__fps16x162%s%s", ssu[su*3], fp16x16sbwd[bwd]); + if(bwd == 3) { + __fp16x16conv[tofrom][bwd][su] = funcOfType (buffer, floatType, fixed16x16Type, 1, options.float_rent); + } else + __fp16x16conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], fixed16x16Type, 1, options.float_rent); + } + else + { + SNPRINTF (buffer, sizeof(buffer), "__%s%s2fps16x16", ssu[su*3], fp16x16sbwd[bwd]); + if(bwd == 3) { + __fp16x16conv[tofrom][bwd][su] = funcOfType (buffer, fixed16x16Type, floatType, 1, options.float_rent); + } else + __fp16x16conv[tofrom][bwd][su] = funcOfType (buffer, fixed16x16Type, __multypes[bwd][su], 1, options.float_rent); + } + } + } + } + /* for (muldivmod = 0; muldivmod < 3; muldivmod++) { @@ -3197,7 +3560,7 @@ initCSupport () SNPRINTF (buffer, sizeof(buffer), "_%s%s%s", smuldivmod[muldivmod], - ssu[su], + ssu[su*3], sbwd[bwd]); __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent); FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; @@ -3209,39 +3572,85 @@ initCSupport () Therefore they've been merged into mulint() and mullong(). */ - for (bwd = 0; bwd < 3; bwd++) + /* byte */ + bwd = 0; + for (su = 0; su < 4; su++) { - for (su = 0; su < 2; su++) + for (muldivmod = 0; muldivmod < 3; muldivmod++) { - for (muldivmod = 1; muldivmod < 3; muldivmod++) + /* muluchar, mulschar, mulsuchar and muluschar are separate functions, because e.g. the z80 + port is sign/zero-extending to int before calling mulint() */ + /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */ + if (!TARGET_IS_PIC16 || muldivmod != 1 || su != 0) { - /* div and mod */ SNPRINTF (buffer, sizeof(buffer), - "_%s%s%s", - smuldivmod[muldivmod], - ssu[su], - sbwd[bwd]); - __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent); + "_%s%s%s", + smuldivmod[muldivmod], + ssu[su], + sbwd[bwd]); + __muldiv[muldivmod][bwd][su] = funcOfType ( + _mangleFunctionName(buffer), + __multypes[bwd][su%2], + __multypes[bwd][su/2], + 2, + options.intlong_rent); FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; } } } - /* mul only */ - muldivmod = 0; - /* byte */ - bwd = 0; - for (su = 0; su < 2; su++) + + for (bwd = 1; bwd < 3; bwd++) { - /* muluchar and mulschar are still separate functions, because e.g. the z80 - port is sign/zero-extending to int before calling mulint() */ + for (su = 0; su < 2; su++) + { + for (muldivmod = 1; muldivmod < 3; muldivmod++) + { + /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */ + if (!TARGET_IS_PIC16 || muldivmod != 1 || bwd != 0 || su != 0) + { + SNPRINTF (buffer, sizeof(buffer), + "_%s%s%s", + smuldivmod[muldivmod], + ssu[su*3], + sbwd[bwd]); + __muldiv[muldivmod][bwd][su] = funcOfType ( + _mangleFunctionName(buffer), + __multypes[bwd][su], + __multypes[bwd][su], + 2, + options.intlong_rent); + FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; + } + } + } + } + + if (TARGET_IS_PIC16) + { + /* PIC16 port wants __divschar/__modschar to return an int, so that both + * 100 / -4 = -25 and -128 / -1 = 128 can be handled correctly + * (first one would have to be sign extended, second one must not be). + * Similarly, modschar should be handled, but the iCode introduces cast + * here and forces '% : s8 x s8 -> s8' ... */ + su = 0; bwd = 0; + for (muldivmod = 1; muldivmod < 2; muldivmod++) { SNPRINTF (buffer, sizeof(buffer), - "_%s%s%s", - smuldivmod[muldivmod], - ssu[su], - sbwd[bwd]); - __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent); + "_%s%s%s", + smuldivmod[muldivmod], + ssu[su], + sbwd[bwd]); + __muldiv[muldivmod][bwd][su] = funcOfType ( + _mangleFunctionName(buffer), + __multypes[1][su], + __multypes[bwd][su], + 2, + options.intlong_rent); FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; } + } + + /* mul only */ + muldivmod = 0; /* signed only */ su = 0; /* word and doubleword */ @@ -3267,7 +3676,7 @@ initCSupport () SNPRINTF (buffer, sizeof(buffer), "_%s%s%s", srlrr[rlrr], - ssu[su], + ssu[su*3], sbwd[bwd]); __rlrr[rlrr][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[0][0], 2, options.intlong_rent); FUNC_NONBANKED (__rlrr[rlrr][bwd][su]->type) = 1; @@ -3294,23 +3703,23 @@ void initBuiltIns() } } -sym_link *validateLink(sym_link *l, +sym_link *validateLink(sym_link *l, const char *macro, const char *args, const char select, - const char *file, + const char *file, unsigned line) -{ +{ if (l && l->class==select) { return l; } - fprintf(stderr, + fprintf(stderr, "Internal error: validateLink failed in %s(%s) @ %s:%u:" " expected %s, got %s\n", - macro, args, file, line, + macro, args, file, line, DECLSPEC2TXT(select), l ? DECLSPEC2TXT(l->class) : "null-link"); - exit(-1); + exit(EXIT_FAILURE); return l; // never reached, makes compiler happy. } @@ -3330,13 +3739,13 @@ newEnumType (symbol *enumlist) SPEC_NOUN (type) = V_INT; return type; } - + /* Determine the range of the enumerated values */ sym = enumlist; - min = max = (int) floatFromVal (valFromType (sym->type)); + min = max = (int) ulFromVal (valFromType (sym->type)); for (sym = sym->next; sym; sym = sym->next) { - v = (int) floatFromVal (valFromType (sym->type)); + v = (int) ulFromVal (valFromType (sym->type)); if (vmax) @@ -3370,6 +3779,6 @@ newEnumType (symbol *enumlist) if (min>=0) SPEC_USIGN (type) = 1; } - - return type; + + return type; }