X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCsymt.c;h=6692939f2cb1e7442958e6012b44d7726fd11d1d;hb=eae1bd2f705a2c61e143c539f8c4d1e9c2b4efe6;hp=35360f205052fbecca4a9b47538cd5220e1a60bc;hpb=a58e36646751347e44c301b218135b3a9d4a6088;p=fw%2Fsdcc diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index 35360f20..6692939f 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -23,6 +23,9 @@ #include "common.h" #include "newalloc.h" +#include "dbuf_string.h" + +#include "SDCCsymt.h" value *aggregateToPointer (value *val); void printTypeChainRaw (sym_link * start, FILE * of); @@ -37,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"; @@ -57,16 +61,16 @@ char *nounName(sym_link *sl) { return "unknown"; }; -bucket *SymbolTab[256]; /* the symbol table */ -bucket *StructTab[256]; /* the structure table */ -bucket *TypedefTab[256]; /* the typedef table */ -bucket *LabelTab[256]; /* the Label table */ -bucket *enumTab[256]; /* enumerated table */ +bucket *SymbolTab[256]; /* the symbol table */ +bucket *StructTab[256]; /* the structure table */ +bucket *TypedefTab[256]; /* the typedef table */ +bucket *LabelTab[256]; /* the Label table */ +bucket *enumTab[256]; /* enumerated table */ /*------------------------------------------------------------------*/ /* initSymt () - initialises symbol table related stuff */ /*------------------------------------------------------------------*/ -void +void initSymt () { int i = 0; @@ -77,7 +81,7 @@ initSymt () } /*-----------------------------------------------------------------*/ -/* newBucket - allocates & returns a new bucket */ +/* newBucket - allocates & returns a new bucket */ /*-----------------------------------------------------------------*/ bucket * newBucket () @@ -92,7 +96,7 @@ newBucket () /*-----------------------------------------------------------------*/ /* hashKey - computes the hashkey given a symbol name */ /*-----------------------------------------------------------------*/ -int +int hashKey (const char *s) { unsigned long key = 0; @@ -105,16 +109,16 @@ hashKey (const char *s) /*-----------------------------------------------------------------*/ /* addSym - adds a symbol to the hash Table */ /*-----------------------------------------------------------------*/ -void +void addSym (bucket ** stab, - void *sym, - char *sname, - int level, - int block, - int checkType) + void *sym, + char *sname, + int level, + int block, + int checkType) { - int i; /* index into the hash Table */ - bucket *bp; /* temp bucket * */ + int i; /* index into the hash Table */ + bucket *bp; /* temp bucket * */ if (checkType) { symbol *csym = (symbol *)sym; @@ -137,15 +141,15 @@ 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 */ + strncpyz (bp->name, sname, sizeof(bp->name)); /* copy the name into place */ /* if this is the first entry */ if (stab[i] == NULL) { - bp->prev = bp->next = (void *) NULL; /* point to nothing */ + bp->prev = bp->next = (void *) NULL; /* point to nothing */ stab[i] = bp; } /* not first entry then add @ head of list */ @@ -159,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; @@ -173,33 +177,33 @@ deleteSym (bucket ** stab, void *sym, char *sname) /* find the symbol */ while (bp) { - if (bp->sym == sym) /* found it then break out */ - break; /* of the loop */ + if (bp->sym == sym) /* found it then break out */ + break; /* of the loop */ bp = bp->next; } - if (!bp) /* did not find it */ + if (!bp) /* did not find it */ return; + /* if this is the first one in the chain */ if (!bp->prev) { stab[i] = bp->next; - if (stab[i]) /* if chain ! empty */ - stab[i]->prev = (void *) NULL; + if (stab[i]) /* if chain ! empty */ + stab[i]->prev = (void *) NULL; } /* middle || end of chain */ else { - if (bp->next) /* if not end of chain */ - bp->next->prev = bp->prev; + if (bp->next) /* if not end of chain */ + bp->next->prev = bp->prev; 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) @@ -210,7 +214,7 @@ findSym (bucket ** stab, void *sym, const char *sname) while (bp) { if (bp->sym == sym || strcmp (bp->name, sname) == 0) - break; + break; bp = bp->next; } @@ -238,20 +242,20 @@ findSymWithLevel (bucket ** stab, symbol * sym) while (bp) { if (strcmp (bp->name, sym->name) == 0 && bp->level <= sym->level) - { - /* if this is parameter then nothing else need to be checked */ - if (((symbol *) (bp->sym))->_isparm) - return (bp->sym); - /* if levels match then block numbers should also match */ - if (bp->level && bp->level == sym->level && bp->block == sym->block) - return (bp->sym); - /* if levels don't match then we are okay */ - if (bp->level && bp->level != sym->level && bp->block <= sym->block) - return (bp->sym); - /* if this is a global variable then we are ok too */ - if (bp->level == 0) - return (bp->sym); - } + { + /* if this is parameter then nothing else need to be checked */ + if (((symbol *) (bp->sym))->_isparm) + return (bp->sym); + /* if levels match then block numbers should also match */ + if (bp->level && bp->level == sym->level && bp->block == sym->block) + return (bp->sym); + /* if levels don't match then we are okay */ + if (bp->level && bp->level != sym->level && bp->block <= sym->block) + return (bp->sym); + /* if this is a global variable then we are ok too */ + if (bp->level == 0) + return (bp->sym); + } bp = bp->next; } @@ -271,8 +275,8 @@ findSymWithBlock (bucket ** stab, symbol * sym, int block) while (bp) { if (strcmp (bp->name, sym->name) == 0 && - bp->block <= block) - break; + bp->block <= block) + break; bp = bp->next; } @@ -289,10 +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->lineDef = lexLineno; /* set the line number */ + sym->fileDef = lexFilename; return sym; } @@ -320,10 +325,10 @@ newStruct (char *tag) s = Safe_alloc ( sizeof (structdef)); - strncpyz (s->tag, tag, sizeof(s->tag)); /* copy the 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 */ @@ -358,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)) @@ -371,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; @@ -382,29 +387,29 @@ pointerTypes (sym_link * ptr, sym_link * type) if (IS_SPEC (type)) { switch (SPEC_SCLS (type)) - { - case S_XDATA: - DCL_TYPE (ptr) = FPOINTER; - break; - case S_IDATA: - DCL_TYPE (ptr) = IPOINTER; - break; - case S_PDATA: - DCL_TYPE (ptr) = PPOINTER; - break; - case S_DATA: - DCL_TYPE (ptr) = POINTER; - break; - case S_CODE: - DCL_TYPE (ptr) = CPOINTER; - break; - case S_EEPROM: - DCL_TYPE (ptr) = EEPPOINTER; - break; - default: - DCL_TYPE (ptr) = port->unqualified_pointer; - break; - } + { + case S_XDATA: + DCL_TYPE (ptr) = FPOINTER; + break; + case S_IDATA: + DCL_TYPE (ptr) = IPOINTER; + break; + case S_PDATA: + DCL_TYPE (ptr) = PPOINTER; + break; + case S_DATA: + DCL_TYPE (ptr) = POINTER; + break; + case S_CODE: + DCL_TYPE (ptr) = CPOINTER; + break; + case S_EEPROM: + DCL_TYPE (ptr) = EEPPOINTER; + break; + default: + DCL_TYPE (ptr) = port->unqualified_pointer; + break; + } /* the storage class of type ends here */ SPEC_SCLS (type) = 0; } @@ -414,7 +419,7 @@ pointerTypes (sym_link * ptr, sym_link * type) while (ptr) { if (!IS_SPEC (ptr) && DCL_TYPE (ptr) == UPOINTER) - DCL_TYPE (ptr) = port->unqualified_pointer; + DCL_TYPE (ptr) = port->unqualified_pointer; ptr = ptr->next; } @@ -423,7 +428,7 @@ pointerTypes (sym_link * ptr, sym_link * type) while (type) { if (!IS_SPEC (type) && DCL_TYPE (type) == UPOINTER) - DCL_TYPE (type) = port->unqualified_pointer; + DCL_TYPE (type) = port->unqualified_pointer; type = type->next; } } @@ -431,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; @@ -441,12 +447,15 @@ 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) { tail = head = p; while (tail->next) - tail = tail->next; + tail = tail->next; } else { @@ -460,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 @@ -494,9 +503,9 @@ addDecl (symbol * sym, int type, sym_link * p) DCL_TSPEC (p)) { if (!IS_SPEC (sym->etype)) - { - sym->etype = sym->etype->next = newLink (SPECIFIER); - } + { + sym->etype = sym->etype->next = newLink (SPECIFIER); + } SPEC_SCLS (sym->etype) = SPEC_SCLS (DCL_TSPEC (p)); DCL_TSPEC (p) = NULL; } @@ -536,44 +545,53 @@ 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)) { SPEC_NOUN(etype)=V_INT; } - if (etype->select.s._signed && SPEC_USIGN(etype)) { - // signed AND unsigned + /* 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.b_signed) + SPEC_USIGN(etype) = 1; + } + + 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); } - } /*------------------------------------------------------------------*/ @@ -599,19 +617,19 @@ mergeSpec (sym_link * dest, sym_link * src, char *name) } else { /* we shouldn't redeclare the type */ if (getenv("DEBUG_SANITY")) { - fprintf (stderr, "mergeSpec: "); + 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: "); + fprintf (stderr, "mergeSpec: "); } werror(E_TWO_OR_MORE_STORAGE_CLASSES, name); } @@ -619,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)) { @@ -631,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); @@ -647,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); @@ -664,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) { @@ -724,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 */ /*------------------------------------------------------------------*/ @@ -754,50 +789,66 @@ 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 */ if (!p) return 0; if (IS_SPEC (p)) - { /* if this is the specifier then */ + { /* if this is the specifier then */ switch (SPEC_NOUN (p)) - { /* depending on the specifier type */ - case V_INT: - return (IS_LONG (p) ? LONGSIZE : INTSIZE); - case V_FLOAT: - return FLOATSIZE; - case V_CHAR: - return CHARSIZE; - case V_VOID: - return 0; - case V_STRUCT: - return SPEC_STRUCT (p)->size; - case V_LABEL: - return 0; - case V_SBIT: - case V_BIT: - return BITSIZE; - case V_BITFIELD: - return ((SPEC_BLEN (p) / 8) + (SPEC_BLEN (p) % 8 ? 1 : 0)); - default: - return 0; - } - } - - /* this is a specifier */ + { /* depending on the specifier type */ + case V_INT: + return (IS_LONG (p) ? LONGSIZE : INTSIZE); + case V_FLOAT: + return FLOATSIZE; + case V_FIXED16X16: + return (4); + case V_CHAR: + return CHARSIZE; + case V_VOID: + return 0; + case V_STRUCT: + return SPEC_STRUCT (p)->size; + case V_LABEL: + return 0; + case V_SBIT: + case V_BIT: + return BITSIZE; + case V_BITFIELD: + return ((SPEC_BLEN (p) / 8) + (SPEC_BLEN (p) % 8 ? 1 : 0)); + default: + return 0; + } + } + + /* this is a declarator */ switch (DCL_TYPE (p)) { case ARRAY: if (DCL_ELEM(p)) { - return DCL_ELEM (p) * getSize (p->next); + return DCL_ELEM (p) * getSize (p->next); } else { - // werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - // "can not tell the size of an array[]"); - return 0; + // werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + // "can not tell the size of an array[]"); + return 0; } case IPOINTER: case PPOINTER: @@ -807,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); @@ -816,10 +867,47 @@ getSize (sym_link * p) } } +/*------------------------------------------------------------------*/ +/* checkStructFlexArray - check tree behind a struct */ +/*------------------------------------------------------------------*/ +static bool +checkStructFlexArray (symbol *sym, sym_link *p) +{ + /* if nothing return FALSE */ + if (!p) + return FALSE; + + 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; + } + + /* 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); + } + return FALSE; +} + /*------------------------------------------------------------------*/ /* bitsForType - returns # of bits required to store this type */ /*------------------------------------------------------------------*/ -unsigned int +unsigned int bitsForType (sym_link * p) { /* if nothing return 0 */ @@ -827,30 +915,32 @@ bitsForType (sym_link * p) return 0; if (IS_SPEC (p)) - { /* if this is the specifier then */ + { /* if this is the specifier then */ switch (SPEC_NOUN (p)) - { /* depending on the specifier type */ - case V_INT: - return (IS_LONG (p) ? LONGSIZE * 8 : INTSIZE * 8); - case V_FLOAT: - return FLOATSIZE * 8; - case V_CHAR: - return CHARSIZE * 8; - case V_VOID: - return 0; - case V_STRUCT: - return SPEC_STRUCT (p)->size * 8; - case V_LABEL: - return 0; - case V_SBIT: - case V_BIT: - return 1; - case V_BITFIELD: - return SPEC_BLEN (p); - default: - return 0; - } + { /* depending on the specifier type */ + case V_INT: + 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: + return 0; + case V_STRUCT: + return SPEC_STRUCT (p)->size * 8; + case V_LABEL: + return 0; + case V_SBIT: + case V_BIT: + return 1; + case V_BITFIELD: + return SPEC_BLEN (p); + default: + return 0; + } } /* this is a specifier */ @@ -916,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) @@ -941,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) @@ -968,43 +1058,117 @@ 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) { - changePointer(sym); + changePointer(sym->type); checkTypeSanity(sym->etype, sym->name); - /* 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 */ + if (!sym->level && !(IS_SPEC(sym->etype) && IS_TYPEDEF(sym->etype))) + checkDecl (sym, 0); + 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) { - - /* one definition extern ? */ - if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype)) { - /* do types match ? */ - if (compareType (csym->type, sym->type) != 1) { - /* no then error */ - werror (E_EXTERN_MISMATCH, csym->name); - continue; - } - } else { - /* not extern */ - if (compareType (csym->type, sym->type) != 1) { - werror (E_DUPLICATE, sym->name); - continue; - } - } - /* delete current entry */ - deleteSym (SymbolTab, csym, csym->name); - deleteFromSeg(csym); - } + 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 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; + } + + 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; + } /* add new entry */ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1); @@ -1015,13 +1179,13 @@ addSymChain (symbol * symHead) /*------------------------------------------------------------------*/ /* funcInChain - DCL Type 'FUNCTION' found in type chain */ /*------------------------------------------------------------------*/ -int +int funcInChain (sym_link * lnk) { while (lnk) { if (IS_FUNC (lnk)) - return 1; + return 1; lnk = lnk->next; } return 0; @@ -1038,28 +1202,30 @@ structElemType (sym_link * stype, value * id) sym_link *petype = getSpec (stype); if (fields && id) { - + /* look for the id */ while (fields) { - if (strcmp (fields->rname, id->name) == 0) - { - type = copyLinkChain (fields->type); - etype = getSpec (type); - SPEC_SCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ? - SPEC_SCLS (etype) : SPEC_SCLS (petype)); + if (strcmp (fields->rname, id->name) == 0) + { + type = copyLinkChain (fields->type); + 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 DCL_PTR_CONST (type) |= SPEC_CONST (stype); - return type; - } - fields = fields->next; + return type; + } + fields = fields->next; } } werror (E_NOT_MEMBER, id->name); - + // the show must go on return newIntLink(); } @@ -1084,129 +1250,245 @@ 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) { - - /* 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) { - - /* 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++; - } - } - } - 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); - } - - loop = loop->next; - - /* if union then size = sizeof larget 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); + 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; + + 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 { + 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; + } + } + 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); } +/*-------------------------------------------------------------------*/ +/* 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 */ /*------------------------------------------------------------------*/ -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 */ @@ -1217,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; @@ -1282,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)) { @@ -1309,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 || @@ -1327,68 +1632,71 @@ checkSClass (symbol * sym, int isProto) /* variables declared in CODE space must have */ /* initializers if not an extern */ if (SPEC_SCLS (sym->etype) == S_CODE && - sym->ival == NULL && - //!sym->level && - port->mem.code_ro && - !IS_EXTERN (sym->etype) && - !funcInChain (sym->type)) + sym->ival == NULL && + !sym->_isparm && + //!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))) - { - SPEC_SCLS (sym->etype) = (options.useXstack ? - S_XSTACK : S_STACK); - } + { + SPEC_SCLS (sym->etype) = (options.useXstack ? + S_XSTACK : S_STACK); + } else - { - /* hack-o-matic! I see no reason why the useXstack option should ever - * control this allcoation, 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) ? - 1 : options.useXstack; - SPEC_SCLS (sym->etype) = (useXdata ? - S_XDATA : S_FIXED); - } + { + /* hack-o-matic! I see no reason why the useXstack option should ever + * 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) ? + 1 : options.useXstack; + SPEC_SCLS (sym->etype) = (useXdata ? + S_XDATA : S_FIXED); + } } } /*------------------------------------------------------------------*/ /* changePointer - change pointer to functions */ /*------------------------------------------------------------------*/ -void -changePointer (symbol * sym) +void +changePointer (sym_link * p) { - 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 */ - for (p = sym->type; p; p = p->next) + /* 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; + DCL_TYPE (p) = port->unqualified_pointer; if (IS_PTR (p) && IS_FUNC (p->next)) - DCL_TYPE (p) = CPOINTER; + 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); /* 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 */ @@ -1406,11 +1714,12 @@ 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) { - memcpy (loop, curr, sizeof (sym_link)); /* copy it */ + memcpy (loop, curr, sizeof (sym_link)); /* copy it */ loop->next = (curr->next ? newLink (curr->next->class) : (void *) NULL); loop = loop->next; curr = curr->next; @@ -1419,12 +1728,11 @@ copyLinkChain (sym_link * p) return head; } - /*------------------------------------------------------------------*/ /* cleanUpBlock - cleansup the symbol table specified for all the */ /* symbols in the given block */ /*------------------------------------------------------------------*/ -void +void cleanUpBlock (bucket ** table, int block) { int i; @@ -1434,12 +1742,12 @@ cleanUpBlock (bucket ** table, int block) for (i = 0; i < 256; i++) { for (chain = table[i]; chain; chain = chain->next) - { - if (chain->block >= block) - { - deleteSym (table, chain->sym, chain->name); - } - } + { + if (chain->block >= block) + { + deleteSym (table, chain->sym, chain->name); + } + } } } @@ -1447,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; @@ -1457,25 +1765,96 @@ cleanUpLevel (bucket ** table, int level) for (i = 0; i < 256; i++) { for (chain = table[i]; chain; chain = chain->next) - { - if (chain->level >= level) - { - deleteSym (table, chain->sym, chain->name); - } - } + { + if (chain->level >= level) + { + deleteSym (table, chain->sym, chain->name); + } + } + } +} + +/*------------------------------------------------------------------*/ +/* 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_BIT (etype1)) + && (IS_CHAR (etype2) || IS_BIT (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, int 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 */ @@ -1483,17 +1862,37 @@ computeType (sym_link * type1, sym_link * type2) /* which ever is greater in size */ if (IS_FLOAT (etype1) || IS_FLOAT (etype2)) rType = newFloatLink (); - else - /* if only one of them is a bit variable - then the other one prevails */ - if (IS_BITVAR (etype1) && !IS_BITVAR (etype2)) - rType = copyLinkChain (type2); + /* 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); + /* 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); - else - /* if one of them is a pointer or array then that - prevails */ - if (IS_PTR (type1) || IS_ARRAY (type1)) + { + rType = copyLinkChain (type1); + /* bitfield can have up to 16 bits */ + if (getSize (etype2) > 1) + SPEC_NOUN (getSpec (rType)) = V_INT; + } + /* 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); @@ -1503,27 +1902,174 @@ 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.b_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_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)) + { + SPEC_NOUN (reType) = V_CHAR; + SPEC_SCLS (reType) = 0; + SPEC_USIGN (reType) = 0; + return rType; + } + break; + case RESULT_TYPE_INT: + case RESULT_TYPE_NONE: + case RESULT_TYPE_OTHER: + 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)) + { + /* promotion of some special cases */ + switch (op) + { + 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; + 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 */ + && !(bitsForType (etype1) < bitsForType (reType)) + /* char require special handling */ + && !IS_CHAR (etype1)) + || /* same for 2nd operand */ + (SPEC_USIGN (etype2) + && !(bitsForType (etype2) < bitsForType (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; } +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) @@ -1541,35 +2087,57 @@ compareType (sym_link * dest, sym_link * src) if (IS_DECL (dest)) { if (IS_DECL (src)) - { - if (DCL_TYPE (src) == DCL_TYPE (dest)) { - if (IS_FUNC(src)) { - //checkFunction(src,dest); - } - 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; - } + { + /* 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; + } + if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src)) + return compareType (dest->next, src); + return 0; + } else if (IS_PTR (dest) && IS_INTEGRAL (src)) - return -1; + return -1; else - return 0; + 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))) @@ -1595,32 +2163,216 @@ compareType (sym_link * dest, sym_link * src) if (SPEC_NOUN (dest) != SPEC_NOUN (src)) { if (SPEC_USIGN (dest) == SPEC_USIGN (src) && - IS_INTEGRAL (dest) && IS_INTEGRAL (src) && - getSize (dest) == getSize (src)) - return 1; + IS_INTEGRAL (dest) && IS_INTEGRAL (src) && + /* I would prefer + bitsForType (dest) == bitsForType (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))) + return 1; else if (IS_ARITHMETIC (dest) && IS_ARITHMETIC (src)) - return -1; + return -1; else - return 0; + return 0; } else if (IS_STRUCT (dest)) { if (SPEC_STRUCT (dest) != SPEC_STRUCT (src)) - return 0; + return 0; else - return 1; + return 1; } if (SPEC_LONG (dest) != SPEC_LONG (src)) return -1; if (SPEC_USIGN (dest) != SPEC_USIGN (src)) - return -1; + return -2; + + return 1; +} + +/*--------------------------------------------------------------------*/ +/* compareTypeExact - will do type check return 1 if match exactly */ +/*--------------------------------------------------------------------*/ +int +compareTypeExact (sym_link * dest, sym_link * src, int level) +{ + STORAGE_CLASS srcScls, destScls; + + if (!dest && !src) + return 1; + + if (dest && !src) + return 0; + + if (src && !dest) + return 0; + + /* if dest is a declarator then */ + if (IS_DECL (dest)) + { + if (IS_DECL (src)) + { + if (DCL_TYPE (src) == DCL_TYPE (dest)) { + if ((DCL_TYPE (src) == ARRAY) && (DCL_ELEM (src) != DCL_ELEM (dest))) + return 0; + if (DCL_PTR_CONST (src) != DCL_PTR_CONST (dest)) + return 0; + if (DCL_PTR_VOLATILE (src) != DCL_PTR_VOLATILE (dest)) + return 0; + if (IS_FUNC(src)) + { + value *exargs, *acargs, *checkValue; + + /* verify function return type */ + if (!compareTypeExact (dest->next, src->next, -1)) + return 0; + if (FUNC_ISISR (dest) != FUNC_ISISR (src)) + return 0; + if (FUNC_REGBANK (dest) != FUNC_REGBANK (src)) + return 0; + if (IFFUNC_ISNAKED (dest) != IFFUNC_ISNAKED (src)) + return 0; + #if 0 + if (IFFUNC_ISREENT (dest) != IFFUNC_ISREENT (src) && argCnt>1) + return 0; + #endif + + /* compare expected args with actual args */ + exargs = FUNC_ARGS(dest); + acargs = FUNC_ARGS(src); + + /* for all the expected args do */ + for (; exargs && acargs; exargs = exargs->next, acargs = acargs->next) + { + //checkTypeSanity(acargs->etype, acargs->name); + + if (IS_AGGREGATE (acargs->type)) + { + checkValue = copyValue (acargs); + aggregateToPointer (checkValue); + } + else + checkValue = acargs; + + #if 0 + if (!compareTypeExact (exargs->type, checkValue->type, -1)) + return 0; + #endif + } + + /* if one them ended we have a problem */ + if ((exargs && !acargs && !IS_VOID (exargs->type)) || + (!exargs && acargs && !IS_VOID (acargs->type))) + return 0; + return 1; + } + return compareTypeExact (dest->next, src->next, level); + } + return 0; + } + return 0; + } + + /* if one is a specifier and the other is not */ + if ((IS_SPEC (src) && !IS_SPEC (dest)) || + (IS_SPEC (dest) && !IS_SPEC (src))) + return 0; + + /* if one of them is a void then ok */ + if (SPEC_NOUN (dest) != SPEC_NOUN (src)) + return 0; + + /* if they are both bitfields then if the lengths + and starts don't match */ + if (IS_BITFIELD (dest) && IS_BITFIELD (src) && + (SPEC_BLEN (dest) != SPEC_BLEN (src) || + SPEC_BSTR (dest) != SPEC_BSTR (src))) + return 0; + + if (IS_INTEGRAL (dest)) + { + /* signedness must match */ + if (SPEC_USIGN (dest) != SPEC_USIGN (src)) + return 0; + /* size must match */ + if (SPEC_LONG (dest) != SPEC_LONG (src)) + return 0; + if (SPEC_SHORT (dest) != SPEC_SHORT (src)) + return 0; + } + + if (IS_STRUCT (dest)) + { + if (SPEC_STRUCT (dest) != SPEC_STRUCT (src)) + return 0; + } + + if (SPEC_CONST (dest) != SPEC_CONST (src)) + return 0; + if (SPEC_VOLATILE (dest) != SPEC_VOLATILE (src)) + return 0; + if (SPEC_STAT (dest) != SPEC_STAT (src)) + return 0; + if (SPEC_ABSA (dest) != SPEC_ABSA (src)) + 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)) + { + if (srcScls == S_CODE && destScls == S_FIXED) + destScls = S_CODE; + if (destScls == S_CODE && srcScls == S_FIXED) + srcScls = S_CODE; + } + + /* 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() */ + if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type))) + { + if (destScls == S_FIXED) + destScls = (options.useXstack ? S_XSTACK : S_STACK); + if (srcScls == S_FIXED) + srcScls = (options.useXstack ? S_XSTACK : S_STACK); + } + else if (TARGET_IS_DS390 || TARGET_IS_DS400 || options.useXstack) + { + if (destScls == S_FIXED) + destScls = S_XDATA; + if (srcScls == S_FIXED) + srcScls = S_XDATA; + } + } + + if (srcScls != destScls) + { + #if 0 + printf ("level = %d\n", level); + printf ("SPEC_SCLS (src) = %d, SPEC_SCLS (dest) = %d\n", + SPEC_SCLS (src), SPEC_SCLS (dest)); + printf ("srcScls = %d, destScls = %d\n",srcScls, destScls); + #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) @@ -1637,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) @@ -1648,65 +2400,67 @@ aggregateToPointer (value * val) /* if this is a structure */ /* then we need to add a new link */ if (IS_STRUCT (val->type)) - { - /* first lets add DECLARATOR type */ - sym_link *p = val->type; + { + /* first lets add DECLARATOR type */ + sym_link *p = val->type; - werror (W_STRUCT_AS_ARG, val->name); - val->type = newLink (DECLARATOR); - val->type->next = p; - } + werror (W_STRUCT_AS_ARG, val->name); + val->type = newLink (DECLARATOR); + val->type->next = p; + } /* change to a pointer depending on the */ /* storage class specified */ switch (SPEC_SCLS (val->etype)) - { - case S_IDATA: - DCL_TYPE (val->type) = IPOINTER; - break; - case S_PDATA: - DCL_TYPE (val->type) = PPOINTER; - break; - case S_FIXED: - if (SPEC_OCLS(val->etype)) { - DCL_TYPE(val->type)=PTR_TYPE(SPEC_OCLS(val->etype)); - } else { - // this happens for (external) function parameters - DCL_TYPE (val->type) = port->unqualified_pointer; - } - break; - case S_AUTO: - case S_DATA: - case S_REGISTER: - DCL_TYPE (val->type) = POINTER; - break; - case S_CODE: - DCL_TYPE (val->type) = CPOINTER; - break; - case S_XDATA: - DCL_TYPE (val->type) = FPOINTER; - break; - case S_EEPROM: - DCL_TYPE (val->type) = EEPPOINTER; - break; - default: - DCL_TYPE (val->type) = port->unqualified_pointer; - } - + { + case S_IDATA: + DCL_TYPE (val->type) = IPOINTER; + break; + case S_PDATA: + DCL_TYPE (val->type) = PPOINTER; + break; + case S_FIXED: + if (SPEC_OCLS(val->etype)) { + DCL_TYPE(val->type)=PTR_TYPE(SPEC_OCLS(val->etype)); + } else { + // this happens for (external) function parameters + DCL_TYPE (val->type) = port->unqualified_pointer; + } + 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; + break; + case S_CODE: + DCL_TYPE (val->type) = CPOINTER; + break; + case S_XDATA: + DCL_TYPE (val->type) = FPOINTER; + break; + case S_EEPROM: + DCL_TYPE (val->type) = EEPPOINTER; + break; + 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) - { - val->sym->type = copyLinkChain (val->type); - val->sym->etype = getSpec (val->sym->type); - } + { + val->sym->type = copyLinkChain (val->type); + val->sym->etype = getSpec (val->sym->type); + } } return val; } /*------------------------------------------------------------------*/ /* checkFunction - does all kinds of check on a function */ /*------------------------------------------------------------------*/ -int +int checkFunction (symbol * sym, symbol *csym) { value *exargs, *acargs; @@ -1717,6 +2471,19 @@ checkFunction (symbol * sym, symbol *csym) fprintf (stderr, "checkFunction: %s ", sym->name); } + if (!IS_DECL(sym->type) || DCL_TYPE(sym->type)!=FUNCTION) + { + 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); @@ -1735,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); @@ -1751,15 +2511,20 @@ checkFunction (symbol * sym, symbol *csym) if (IFFUNC_ARGS(sym->type) && FUNC_ISISR (sym->type)) { if (!IS_VOID(FUNC_ARGS(sym->type)->type)) { - werror (E_INT_ARGS, sym->name); - FUNC_ARGS(sym->type)=NULL; + werror (E_INT_ARGS, sym->name); + FUNC_ARGS(sym->type)=NULL; } } - 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 @@ -1770,15 +2535,18 @@ 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 */ + return 1; /* not defined nothing more to check */ /* check if body already present */ if (csym && IFFUNC_HASBODY(csym->type)) @@ -1800,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"); } @@ -1809,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 */ @@ -1821,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); @@ -1831,7 +2613,7 @@ checkFunction (symbol * sym, symbol *csym) exargs = exargs->next, acargs = acargs->next, argCnt++) { if (getenv("DEBUG_SANITY")) { - fprintf (stderr, "checkFunction: %s ", exargs->name); + fprintf (stderr, "checkFunction: %s ", exargs->name); } /* make sure the type is complete and sane */ checkTypeSanity(exargs->etype, exargs->name); @@ -1841,21 +2623,21 @@ checkFunction (symbol * sym, symbol *csym) * change here. */ if (IS_AGGREGATE (acargs->type)) - { - checkValue = copyValue (acargs); - aggregateToPointer (checkValue); - } + { + checkValue = copyValue (acargs); + aggregateToPointer (checkValue); + } else - { - checkValue = acargs; - } + { + checkValue = acargs; + } if (compareType (exargs->type, checkValue->type) <= 0) - { - werror (E_ARG_TYPE, argCnt); - printFromToType(exargs->type, checkValue->type); - return 0; - } + { + werror (E_ARG_TYPE, argCnt); + printFromToType(exargs->type, checkValue->type); + return 0; + } } /* if one them ended we have a problem */ @@ -1889,20 +2671,36 @@ void cdbStructBlock (int block) for (i = 0; i < 256; i++) { for (chain = table[i]; chain; chain = chain->next) - { - if (chain->block >= block) - { - if(debugFile) - debugFile->writeType((structdef *)chain->sym, chain->block, 0, NULL); - } - } + { + if (chain->block >= block) + { + if(debugFile) + debugFile->writeType((structdef *)chain->sym, chain->block, 0, NULL); + } + } + } +} + +/*-----------------------------------------------------------------*/ +/* 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; @@ -1912,10 +2710,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 */ @@ -1938,27 +2735,33 @@ processFuncArgs (symbol * func) /* reset regparm for the port */ (*port->reset_regparms) (); + /* if any of the arguments is an aggregate */ /* change it to pointer to the same type */ while (val) { - int argreg = 0; + 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))) - { - SPEC_REGPARM (val->etype) = 1; - SPEC_ARGREG(val->etype) = argreg; - } else if (IFFUNC_ISREENT(funcType)) { - FUNC_HASSTACKPARM(funcType) = 1; - } + (argreg = (*port->reg_parm) (val->type, FUNC_ISREENT(funcType)))) + { + SPEC_REGPARM (val->etype) = 1; + SPEC_ARGREG(val->etype) = argreg; + } else if (IFFUNC_ISREENT(funcType)) { + FUNC_HASSTACKPARM(funcType) = 1; + } if (IS_AGGREGATE (val->type)) - { - aggregateToPointer (val); - } + { + aggregateToPointer (val); + } val = val->next; pNum++; @@ -1986,38 +2789,53 @@ processFuncArgs (symbol * func) /* if a symbolname is not given */ /* synthesize a variable name */ if (!val->sym) - { - 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; - val->sym->type = copyLinkChain (val->type); - val->sym->etype = getSpec (val->sym->type); - val->sym->_isparm = 1; - strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname)); - if (IS_SPEC(func->etype)) { - SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) = - SPEC_STAT (func->etype); - } - addSymChain (val->sym); - - } - else /* symbol name given create synth name */ - { - - 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 (IS_SPEC(func->etype)) { - SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) = - SPEC_STAT (func->etype); - } - } + { + SNPRINTF (val->name, sizeof(val->name), + "_%s_PARM_%d", func->name, pNum++); + val->sym = newSymbol (val->name, 1); + 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; + 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); + + } + else /* symbol name given create synth name */ + { + + 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; + 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)) { + SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) = + SPEC_STAT (func->etype); + } + #endif + } + if (SPEC_OCLS (val->sym->etype) == pdata) + val->sym->iaccess = 1; if (!isinSet(operKeyReset, val->sym)) { - addSet (&operKeyReset, val->sym); - applyToSet (operKeyReset, resetParmKey); + addSet (&operKeyReset, val->sym); + applyToSet (operKeyReset, resetParmKey); } val = val->next; } @@ -2026,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 */ @@ -2047,7 +2865,7 @@ isSymbolEqual (symbol * dest, symbol * src) void PT(sym_link *type) { - printTypeChain(type,0); + printTypeChain(type,0); } /*-----------------------------------------------------------------*/ /* printTypeChain - prints the type chain in human readable form */ @@ -2055,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) { @@ -2066,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; } @@ -2085,145 +2916,150 @@ printTypeChain (sym_link * start, FILE * of) while (type) { if (type==start) { - 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; - default: break; - } + switch (scls) + { + 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; + } } if (IS_DECL (type)) - { - if (!IS_FUNC(type)) { - if (DCL_PTR_VOLATILE (type)) { - fprintf (of, "volatile-"); - } - if (DCL_PTR_CONST (type)) { - fprintf (of, "const-"); - } - } - switch (DCL_TYPE (type)) - { - case FUNCTION: - fprintf (of, "function %s %s", - (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "), - (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " ")); - fprintf (of, "( "); - for (args = FUNC_ARGS(type); - args; - args=args->next) { - printTypeChain(args->type, of); - if (args->next) - fprintf(of, ", "); - } - fprintf (of, ") "); - break; - case GPOINTER: - fprintf (of, "generic* "); - break; - case CPOINTER: - fprintf (of, "code* "); - break; - case FPOINTER: - fprintf (of, "xdata* "); - break; - case EEPPOINTER: - fprintf (of, "eeprom* "); - break; - case POINTER: - fprintf (of, "near* "); - break; - case IPOINTER: - fprintf (of, "idata* "); - break; - case PPOINTER: - fprintf (of, "pdata* "); - break; - case UPOINTER: - fprintf (of, "unknown* "); - break; - case ARRAY: - if (DCL_ELEM(type)) { - fprintf (of, "[%d] ", DCL_ELEM(type)); - } else { - fprintf (of, "[] "); - } - break; - } - } + { + if (!IS_FUNC(type)) { + if (DCL_PTR_VOLATILE (type)) { + dbuf_append_str (dbuf, "volatile-"); + } + if (DCL_PTR_CONST (type)) { + dbuf_append_str (dbuf, "const-"); + } + if (DCL_PTR_RESTRICT (type)) { + dbuf_append_str (dbuf, "restrict-"); + } + } + switch (DCL_TYPE (type)) + { + case FUNCTION: + dbuf_printf (dbuf, "function %s %s", + (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "), + (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " ")); + dbuf_append_str (dbuf, "( "); + for (args = FUNC_ARGS(type); + args; + args=args->next) { + dbuf_printTypeChain(args->type, dbuf); + if (args->next) + dbuf_append_str (dbuf, ", "); + } + dbuf_append_str (dbuf, ") "); + break; + case GPOINTER: + dbuf_append_str (dbuf, "generic* "); + break; + case CPOINTER: + dbuf_append_str (dbuf, "code* "); + break; + case FPOINTER: + dbuf_append_str (dbuf, "xdata* "); + break; + case EEPPOINTER: + dbuf_append_str (dbuf, "eeprom* "); + break; + case POINTER: + dbuf_append_str (dbuf, "near* "); + break; + case IPOINTER: + dbuf_append_str (dbuf, "idata* "); + break; + case PPOINTER: + dbuf_append_str (dbuf, "pdata* "); + break; + case UPOINTER: + dbuf_append_str (dbuf, "unknown* "); + break; + case ARRAY: + if (DCL_ELEM(type)) { + dbuf_printf (dbuf, "[%d] ", DCL_ELEM(type)); + } else { + dbuf_append_str (dbuf, "[] "); + } + break; + } + } else - { - if (SPEC_VOLATILE (type)) - fprintf (of, "volatile-"); - if (SPEC_CONST (type)) - fprintf (of, "const-"); - if (SPEC_USIGN (type)) - fprintf (of, "unsigned-"); - switch (SPEC_NOUN (type)) - { - case V_INT: - if (IS_LONG (type)) - fprintf (of, "long-"); - fprintf (of, "int"); - break; - - case V_CHAR: - fprintf (of, "char"); - break; - - case V_VOID: - fprintf (of, "void"); - break; - - case V_FLOAT: - fprintf (of, "float"); - break; - - case V_STRUCT: - fprintf (of, "struct %s", SPEC_STRUCT (type)->tag); - break; - - case V_SBIT: - fprintf (of, "sbit"); - break; - - case V_BIT: - fprintf (of, "bit"); - break; - - case V_BITFIELD: - fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); - break; - - case V_DOUBLE: - fprintf (of, "double"); - break; - - default: - fprintf (of, "unknown type"); - break; - } - } + { + if (SPEC_VOLATILE (type)) + dbuf_append_str (dbuf, "volatile-"); + if (SPEC_CONST (type)) + dbuf_append_str (dbuf, "const-"); + if (SPEC_USIGN (type)) + dbuf_append_str (dbuf, "unsigned-"); + switch (SPEC_NOUN (type)) + { + case V_INT: + if (IS_LONG (type)) + dbuf_append_str (dbuf, "long-"); + dbuf_append_str (dbuf, "int"); + break; + + case V_CHAR: + dbuf_append_str (dbuf, "char"); + break; + + case V_VOID: + dbuf_append_str (dbuf, "void"); + break; + + case V_FLOAT: + dbuf_append_str (dbuf, "float"); + break; + + case V_FIXED16X16: + dbuf_append_str (dbuf, "fixed16x16"); + break; + + case V_STRUCT: + dbuf_printf (dbuf, "struct %s", SPEC_STRUCT (type)->tag); + break; + + case V_SBIT: + dbuf_append_str (dbuf, "sbit"); + break; + + case V_BIT: + dbuf_append_str (dbuf, "bit"); + break; + + case V_BITFIELD: + dbuf_printf (dbuf, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); + break; + + case V_DOUBLE: + dbuf_append_str (dbuf, "double"); + break; + + default: + dbuf_append_str (dbuf, "unknown type"); + break; + } + } /* search entry in list before "type" */ for (search = start; search && search->next != type;) - search = search->next; + search = search->next; type = search; if (type) - fputc (' ', of); + dbuf_append_char(dbuf, ' '); } - if (nlr) - fprintf (of, "\n"); } /*--------------------------------------------------------------------*/ @@ -2249,148 +3085,158 @@ printTypeChainRaw (sym_link * start, FILE * of) } type = start; - + while (type) { if (IS_DECL (type)) - { - if (!IS_FUNC(type)) { - if (DCL_PTR_VOLATILE (type)) { - fprintf (of, "volatile-"); - } - if (DCL_PTR_CONST (type)) { - fprintf (of, "const-"); - } - } - switch (DCL_TYPE (type)) - { - case FUNCTION: - fprintf (of, "function %s %s", - (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "), - (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " ")); - fprintf (of, "( "); - for (args = FUNC_ARGS(type); - args; - args=args->next) { - printTypeChain(args->type, of); - if (args->next) - fprintf(of, ", "); - } - fprintf (of, ") "); - break; - case GPOINTER: - fprintf (of, "generic* "); - break; - case CPOINTER: - fprintf (of, "code* "); - break; - case FPOINTER: - fprintf (of, "xdata* "); - break; - case EEPPOINTER: - fprintf (of, "eeprom* "); - break; - case POINTER: - fprintf (of, "near* "); - break; - case IPOINTER: - fprintf (of, "idata* "); - break; - case PPOINTER: - fprintf (of, "pdata* "); - break; - case UPOINTER: - fprintf (of, "unknown* "); - break; - case ARRAY: - if (DCL_ELEM(type)) { - fprintf (of, "[%d] ", DCL_ELEM(type)); - } else { - fprintf (of, "[] "); - } - break; - } + { + if (!IS_FUNC(type)) { + if (DCL_PTR_VOLATILE (type)) { + fprintf (of, "volatile-"); + } + if (DCL_PTR_CONST (type)) { + fprintf (of, "const-"); + } + if (DCL_PTR_RESTRICT (type)) { + fprintf (of, "restrict-"); + } + } + switch (DCL_TYPE (type)) + { + case FUNCTION: + 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; + args=args->next) { + printTypeChain(args->type, of); + if (args->next) + fprintf(of, ", "); + } + fprintf (of, ") "); + break; + case GPOINTER: + fprintf (of, "generic* "); + break; + case CPOINTER: + fprintf (of, "code* "); + break; + case FPOINTER: + fprintf (of, "xdata* "); + break; + case EEPPOINTER: + fprintf (of, "eeprom* "); + break; + case POINTER: + fprintf (of, "near* "); + break; + case IPOINTER: + fprintf (of, "idata* "); + break; + case PPOINTER: + fprintf (of, "pdata* "); + break; + case UPOINTER: + fprintf (of, "unknown* "); + break; + case ARRAY: + if (DCL_ELEM(type)) { + fprintf (of, "[%d] ", DCL_ELEM(type)); + } else { + fprintf (of, "[] "); + } + break; + } if (DCL_TSPEC(type)) { fprintf (of, "{"); printTypeChainRaw(DCL_TSPEC(type), of); fprintf (of, "}"); } - } + } else if (IS_SPEC (type)) - { - switch (SPEC_SCLS (type)) - { - 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; - default: break; - } - if (SPEC_VOLATILE (type)) - fprintf (of, "volatile-"); - if (SPEC_CONST (type)) - fprintf (of, "const-"); - if (SPEC_USIGN (type)) - fprintf (of, "unsigned-"); - switch (SPEC_NOUN (type)) - { - case V_INT: - if (IS_LONG (type)) - fprintf (of, "long-"); - fprintf (of, "int"); - break; - - case V_CHAR: - fprintf (of, "char"); - break; - - case V_VOID: - fprintf (of, "void"); - break; - - case V_FLOAT: - fprintf (of, "float"); - break; - - case V_STRUCT: - fprintf (of, "struct %s", SPEC_STRUCT (type)->tag); - break; - - case V_SBIT: - fprintf (of, "sbit"); - break; - - case V_BIT: - fprintf (of, "bit"); - break; - - case V_BITFIELD: - fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); - break; - - case V_DOUBLE: - fprintf (of, "double"); - break; - - default: - fprintf (of, "unknown type"); - break; - } - } + { + switch (SPEC_SCLS (type)) + { + 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; + default: break; + } + if (SPEC_VOLATILE (type)) + fprintf (of, "volatile-"); + if (SPEC_CONST (type)) + fprintf (of, "const-"); + if (SPEC_USIGN (type)) + fprintf (of, "unsigned-"); + switch (SPEC_NOUN (type)) + { + case V_INT: + if (IS_LONG (type)) + fprintf (of, "long-"); + fprintf (of, "int"); + break; + + case V_CHAR: + fprintf (of, "char"); + break; + + case V_VOID: + fprintf (of, "void"); + break; + + case V_FLOAT: + fprintf (of, "float"); + break; + + case V_FIXED16X16: + fprintf (of, "fixed16x16"); + break; + + case V_STRUCT: + fprintf (of, "struct %s", SPEC_STRUCT (type)->tag); + break; + + case V_SBIT: + fprintf (of, "sbit"); + break; + + case V_BIT: + fprintf (of, "bit"); + break; + + case V_BITFIELD: + fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); + break; + + case V_DOUBLE: + fprintf (of, "double"); + break; + + default: + fprintf (of, "unknown type"); + break; + } + } else fprintf (of, "NOT_SPEC_OR_DECL"); type = type->next; if (type) - fputc (' ', of); + fputc (' ', of); } if (nlr) fprintf (of, "\n"); @@ -2400,8 +3246,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_TARGET_ULONG num) { int nshifts = 0; int n1s = 0; @@ -2409,13 +3255,13 @@ powof2 (unsigned long num) while (num) { if (num & 1) - n1s++; + n1s++; num >>= 1; nshifts++; } if (n1s > 1 || nshifts == 0) - return 0; + return -1; return nshifts - 1; } @@ -2430,21 +3276,35 @@ 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) { - if (port->getMangledFunctionName) + if (port->getMangledFunctionName) { return port->getMangledFunctionName(in); } @@ -2456,20 +3316,21 @@ _mangleFunctionName(char *in) /*-----------------------------------------------------------------*/ /* typeFromStr - create a typechain from an encoded string */ -/* basic types - 'c' - char */ -/* 's' - short */ -/* 'i' - int */ -/* 'l' - long */ -/* 'f' - float */ -/* 'v' - void */ -/* '*' - pointer - default (GPOINTER) */ +/* basic types - 'c' - char */ +/* 's' - short */ +/* '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 */ -/* examples : "ig*" - generic int * */ +/* 'd' - data */ +/* 'F' - function */ +/* examples : "ig*" - generic int * */ /* "cx*" - char xdata * */ /* "ui" - unsigned int */ /*-----------------------------------------------------------------*/ @@ -2479,80 +3340,84 @@ sym_link *typeFromStr (char *s) int usign = 0; do { - sym_link *nr; - switch (*s) { - case 'u' : - usign = 1; - s++; - continue ; - break ; - case 'c': - r->class = SPECIFIER; - SPEC_NOUN(r) = V_CHAR; - break; - case 's': - case 'i': - r->class = SPECIFIER; - SPEC_NOUN(r) = V_INT; - break; - case 'l': - r->class = SPECIFIER; - SPEC_NOUN(r) = V_INT; - SPEC_LONG(r) = 1; - break; - case 'f': - r->class = SPECIFIER; - SPEC_NOUN(r) = V_FLOAT; - break; - case 'v': - r->class = SPECIFIER; - SPEC_NOUN(r) = V_VOID; - break; - case '*': - DCL_TYPE(r) = port->unqualified_pointer; - break; - case 'g': - case 'x': - case 'p': - case 'd': - case 'F': - assert(*(s+1)=='*'); - nr = newLink(DECLARATOR); - nr->next = r; - r = nr; - switch (*s) { - case 'g': - DCL_TYPE(r) = GPOINTER; - break; - case 'x': - DCL_TYPE(r) = FPOINTER; - break; - case 'p': - DCL_TYPE(r) = CPOINTER; - break; - case 'd': - DCL_TYPE(r) = POINTER; - break; - case 'F': - DCL_TYPE(r) = FUNCTION; - nr = newLink(DECLARATOR); - nr->next = r; - r = nr; - DCL_TYPE(r) = CPOINTER; - break; - } - s++; - break; - default: - werror(E_INTERNAL_ERROR, __FILE__, __LINE__, - "typeFromStr: unknown type"); - break; - } - if (IS_SPEC(r) && usign) { - SPEC_USIGN(r) = 1; - usign = 0; - } - s++; + sym_link *nr; + switch (*s) { + case 'u' : + usign = 1; + s++; + continue ; + break ; + case 'c': + r->class = SPECIFIER; + SPEC_NOUN(r) = V_CHAR; + break; + case 's': + case 'i': + r->class = SPECIFIER; + SPEC_NOUN(r) = V_INT; + break; + case 'l': + r->class = SPECIFIER; + SPEC_NOUN(r) = V_INT; + SPEC_LONG(r) = 1; + break; + case 'f': + 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; + break; + case '*': + DCL_TYPE(r) = port->unqualified_pointer; + break; + case 'g': + case 'x': + case 'p': + case 'd': + case 'F': + assert(*(s+1)=='*'); + nr = newLink(DECLARATOR); + nr->next = r; + r = nr; + switch (*s) { + case 'g': + DCL_TYPE(r) = GPOINTER; + break; + case 'x': + DCL_TYPE(r) = FPOINTER; + break; + case 'p': + DCL_TYPE(r) = CPOINTER; + break; + case 'd': + DCL_TYPE(r) = POINTER; + break; + case 'F': + DCL_TYPE(r) = FUNCTION; + nr = newLink(DECLARATOR); + nr->next = r; + r = nr; + DCL_TYPE(r) = CPOINTER; + break; + } + s++; + break; + default: + werror(E_INTERNAL_ERROR, __FILE__, __LINE__, + "typeFromStr: unknown type"); + break; + } + if (IS_SPEC(r) && usign) { + SPEC_USIGN(r) = 1; + usign = 0; + } + s++; } while (*s); return r; } @@ -2560,7 +3425,7 @@ sym_link *typeFromStr (char *s) /*-----------------------------------------------------------------*/ /* initCSupport - create functions for C support routines */ /*-----------------------------------------------------------------*/ -void +void initCSupport () { const char *smuldivmod[] = @@ -2569,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[] = { @@ -2588,24 +3457,25 @@ initCSupport () } floatType = newFloatLink (); + fixed16x16Type = newFixed16x16Link (); for (bwd = 0; bwd < 3; bwd++) { sym_link *l = NULL; switch (bwd) - { - case 0: - l = newCharLink (); - break; - case 1: - l = newIntLink (); - break; - case 2: - l = newLongLink (); - break; - default: - assert (0); - } + { + case 0: + l = newCharLink (); + break; + case 1: + l = newIntLink (); + break; + case 2: + l = newLongLink (); + break; + default: + assert (0); + } __multypes[bwd][0] = l; __multypes[bwd][1] = copyLinkChain (l); SPEC_USIGN (__multypes[bwd][1]) = 1; @@ -2622,81 +3492,165 @@ 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++) - { - for (su = 0; su < 2; su++) - { - if (tofrom) - { - SNPRINTF (buffer, sizeof(buffer), "__fs2%s%s", ssu[su], 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]); - __conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent); - } - } - } + { + for (su = 0; su < 2; su++) + { + if (tofrom) + { + 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*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++) { for (bwd = 0; bwd < 3; bwd++) - { - for (su = 0; su < 2; su++) - { - SNPRINTF (buffer, sizeof(buffer), - "_%s%s%s", - smuldivmod[muldivmod], - ssu[su], - sbwd[bwd]); + { + for (su = 0; su < 2; su++) + { + 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; - } - } + FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; + } + } } muluint() and mulsint() resp. mululong() and mulslong() return the same result. Therefore they've been merged into mulint() and mullong(). */ - for (bwd = 0; bwd < 3; bwd++) - { - for (su = 0; su < 2; su++) - { - for (muldivmod = 1; muldivmod < 3; muldivmod++) - { - /* 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); - FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; - } - } - } - /* mul only */ - muldivmod = 0; /* byte */ bwd = 0; - for (su = 0; su < 2; su++) + for (su = 0; su < 4; su++) + { + for (muldivmod = 0; 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) + { + SNPRINTF (buffer, sizeof(buffer), + "_%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; + } + } + } + + 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 */ @@ -2704,9 +3658,9 @@ initCSupport () { /* mul, int/long */ SNPRINTF (buffer, sizeof(buffer), - "_%s%s", - smuldivmod[muldivmod], - sbwd[bwd]); + "_%s%s", + smuldivmod[muldivmod], + sbwd[bwd]); __muldiv[muldivmod][bwd][0] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent); FUNC_NONBANKED (__muldiv[muldivmod][bwd][0]->type) = 1; /* signed = unsigned */ @@ -2716,18 +3670,18 @@ initCSupport () for (rlrr = 0; rlrr < 2; rlrr++) { for (bwd = 0; bwd < 3; bwd++) - { - for (su = 0; su < 2; su++) - { - SNPRINTF (buffer, sizeof(buffer), - "_%s%s%s", - srlrr[rlrr], - ssu[su], - sbwd[bwd]); + { + for (su = 0; su < 2; su++) + { + SNPRINTF (buffer, sizeof(buffer), + "_%s%s%s", + srlrr[rlrr], + 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; - } - } + FUNC_NONBANKED (__rlrr[rlrr][bwd][su]->type) = 1; + } + } } } @@ -2742,29 +3696,89 @@ void initBuiltIns() if (!port->builtintable) return ; for (i = 0 ; port->builtintable[i].name ; i++) { - sym = funcOfTypeVarg(port->builtintable[i].name,port->builtintable[i].rtype, - port->builtintable[i].nParms,port->builtintable[i].parm_types); - FUNC_ISBUILTIN(sym->type) = 1; - FUNC_ISREENT(sym->type) = 0; /* can never be reentrant */ + sym = funcOfTypeVarg(port->builtintable[i].name,port->builtintable[i].rtype, + port->builtintable[i].nParms,port->builtintable[i].parm_types); + FUNC_ISBUILTIN(sym->type) = 1; + FUNC_ISREENT(sym->type) = 0; /* can never be reentrant */ } } -sym_link *validateLink(sym_link *l, - const char *macro, - const char *args, - const char select, - const char *file, - unsigned line) -{ +sym_link *validateLink(sym_link *l, + const char *macro, + const char *args, + const char select, + const char *file, + unsigned line) +{ if (l && l->class==select) { - return l; + return l; } - fprintf(stderr, - "Internal error: validateLink failed in %s(%s) @ %s:%u:" - " expected %s, got %s\n", - macro, args, file, line, - DECLSPEC2TXT(select), l ? DECLSPEC2TXT(l->class) : "null-link"); - exit(-1); + fprintf(stderr, + "Internal error: validateLink failed in %s(%s) @ %s:%u:" + " expected %s, got %s\n", + macro, args, file, line, + DECLSPEC2TXT(select), l ? DECLSPEC2TXT(l->class) : "null-link"); + exit(EXIT_FAILURE); 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) ulFromVal (valFromType (sym->type)); + for (sym = sym->next; sym; sym = sym->next) + { + v = (int) ulFromVal (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; +}