#include "common.h"
#include "newalloc.h"
+value *aggregateToPointer (value *val);
+void printTypeChainRaw (sym_link * start, FILE * of);
+
+void printFromToType(sym_link *from, sym_link *to) {
+ fprintf (stderr, "from type '");
+ printTypeChain (from, stderr);
+ fprintf (stderr, "'\nto type '");
+ printTypeChain (to, stderr);
+ fprintf (stderr, "'\n");
+}
+
+/* noun strings */
+char *nounName(sym_link *sl) {
+ switch (SPEC_NOUN(sl))
+ {
+ case V_INT: {
+ if (SPEC_LONG(sl)) return "long";
+ if (sl->select.s._short) return "short";
+ return "int";
+ }
+ case V_FLOAT: return "float";
+ case V_CHAR: return "char";
+ case V_VOID: return "void";
+ case V_STRUCT: return "struct";
+ case V_LABEL: return "label";
+ case V_BITFIELD: return "bitfield";
+ case V_BIT: return "bit";
+ case V_SBIT: return "sbit";
+ case V_DOUBLE: return "double";
+ }
+ return "unknown";
+};
+
bucket *SymbolTab[256]; /* the symbol table */
bucket *StructTab[256]; /* the structure table */
bucket *TypedefTab[256]; /* the typedef table */
{
bucket *bp;
- bp = Safe_calloc (1, sizeof (bucket));
+ bp = Safe_alloc ( sizeof (bucket));
return bp;
}
void *sym,
char *sname,
int level,
- int block)
+ int block,
+ int checkType)
{
int i; /* index into the hash Table */
bucket *bp; /* temp bucket * */
+ if (checkType) {
+ symbol *csym = (symbol *)sym;
+
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "addSym: %s ", sname);
+ }
+ /* make sure the type is complete and sane */
+ checkTypeSanity(csym->etype, csym->name);
+ }
+
+ /* prevent overflow of the (r)name buffers */
+ if (strlen(sname)>SDCC_SYMNAME_MAX) {
+ werror (W_SYMBOL_NAME_TOO_LONG, SDCC_SYMNAME_MAX);
+ sname[SDCC_SYMNAME_MAX]='\0';
+ }
+
/* the symbols are always added at the head of the list */
i = hashKey (sname);
/* get a free entry */
- bp = Safe_calloc (1, sizeof (bucket));
+ bp = Safe_alloc ( sizeof (bucket));
bp->sym = sym; /* update the symbol pointer */
bp->level = level; /* update the nest level */
bp->block = block;
- strcpy (bp->name, sname); /* 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)
**/
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 hsould also match */
+ /* 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 */
{
symbol *sym;
- sym = Safe_calloc (1, sizeof (symbol));
+ sym = Safe_alloc ( sizeof (symbol));
- strcpy (sym->name, name); /* copy the name */
+ strncpyz (sym->name, name, sizeof(sym->name)); /* copy the name */
sym->level = scope; /* set the level */
sym->block = currBlockno;
- sym->lineDef = yylineno; /* set the line number */
+ sym->lineDef = mylineno; /* set the line number */
return sym;
}
/* newLink - creates a new link (declarator,specifier) */
/*------------------------------------------------------------------*/
sym_link *
-newLink ()
+newLink (SYM_LINK_CLASS select)
{
sym_link *p;
- p = Safe_calloc (1, sizeof (sym_link));
+ p = Safe_alloc ( sizeof (sym_link));
+ p->class=select;
return p;
}
{
structdef *s;
- s = Safe_calloc (1, sizeof (structdef));
+ s = Safe_alloc ( sizeof (structdef));
- strcpy (s->tag, 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 */
+/* unexpected cases */
+/*------------------------------------------------------------------*/
+STORAGE_CLASS
+sclsFromPtr(sym_link *ptr)
+{
+ switch (DCL_TYPE (ptr))
+ {
+ case POINTER:
+ return S_DATA;
+ case GPOINTER:
+ return S_FIXED;
+ case FPOINTER:
+ return S_XDATA;
+ case CPOINTER:
+ return S_CODE;
+ case IPOINTER:
+ return S_IDATA;
+ case PPOINTER:
+ return S_PDATA;
+ case EEPPOINTER:
+ return S_EEPROM;
+ case FUNCTION:
+ return S_CODE;
+ default:
+ return S_FIXED;
+ }
+}
/*------------------------------------------------------------------*/
/* pointerTypes - do the computation for the pointer types */
ptr = ptr->next;
/* could not find it */
- if (!ptr || IS_SPEC (ptr) ||
- DCL_TYPE (ptr) != UPOINTER)
+ if (!ptr || IS_SPEC (ptr))
+ return;
+
+ if (IS_PTR(ptr) && DCL_TYPE(ptr)!=UPOINTER) {
+ pointerTypes (ptr->next, type);
return;
+ }
/* change the pointer type depending on the
storage class of the type */
if (IS_SPEC (type))
{
- DCL_PTR_CONST (ptr) = SPEC_CONST (type);
- DCL_PTR_VOLATILE (ptr) = SPEC_VOLATILE (type);
switch (SPEC_SCLS (type))
{
case S_XDATA:
DCL_TYPE (ptr) = POINTER;
break;
case S_CODE:
- DCL_PTR_CONST (ptr) = port->mem.code_ro;
DCL_TYPE (ptr) = CPOINTER;
break;
case S_EEPROM:
DCL_TYPE (ptr) = EEPPOINTER;
break;
default:
- DCL_TYPE (ptr) = GPOINTER;
+ DCL_TYPE (ptr) = port->unqualified_pointer;
break;
}
/* the storage class of type ends here */
- SPEC_SCLS (type) =
- SPEC_CONST (type) =
- SPEC_VOLATILE (type) = 0;
+ SPEC_SCLS (type) = 0;
}
/* now change all the remaining unknown pointers
while (ptr)
{
if (!IS_SPEC (ptr) && DCL_TYPE (ptr) == UPOINTER)
- DCL_TYPE (ptr) = GPOINTER;
+ DCL_TYPE (ptr) = port->unqualified_pointer;
ptr = ptr->next;
}
while (type)
{
if (!IS_SPEC (type) && DCL_TYPE (type) == UPOINTER)
- DCL_TYPE (type) = GPOINTER;
+ DCL_TYPE (type) = port->unqualified_pointer;
type = type->next;
}
-
}
/*------------------------------------------------------------------*/
sym_link *tail;
sym_link *t;
+ if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+ fprintf (stderr, "SDCCsymt.c:addDecl(%s,%d,%p)\n", sym->name, type, p);
+
/* if we are passed a link then set head & tail */
if (p)
{
}
else
{
- head = tail = newLink ();
+ head = tail = newLink (DECLARATOR);
DCL_TYPE (head) = type;
}
{
if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail)
{
- sym->etype = mergeSpec (sym->etype, head);
+ sym->etype = mergeSpec (sym->etype, head, sym->name);
}
else
{
}
}
- /* if the type is a unknown pointer and has
+ /* if the type is an unknown pointer and has
a tspec then take the storage class const & volatile
attribute from the tspec & make it those of this
symbol */
if (p &&
!IS_SPEC (p) &&
- DCL_TYPE (p) == UPOINTER &&
+ //DCL_TYPE (p) == UPOINTER &&
DCL_TSPEC (p))
{
if (!IS_SPEC (sym->etype))
{
- sym->etype = sym->etype->next = newLink ();
- sym->etype->class = SPECIFIER;
+ sym->etype = sym->etype->next = newLink (SPECIFIER);
}
SPEC_SCLS (sym->etype) = SPEC_SCLS (DCL_TSPEC (p));
- SPEC_CONST (sym->etype) = SPEC_CONST (DCL_TSPEC (p));
- SPEC_VOLATILE (sym->etype) = SPEC_VOLATILE (DCL_TSPEC (p));
DCL_TSPEC (p) = NULL;
}
+
+ // if there is a function in this type chain
+ if (p && funcInChain(sym->type)) {
+ processFuncArgs (sym);
+ }
+
return;
}
+/*------------------------------------------------------------------
+ checkTypeSanity: prevent the user from doing e.g.:
+ unsigned float uf;
+ ------------------------------------------------------------------*/
+void checkTypeSanity(sym_link *etype, char *name) {
+ char *noun;
+
+ if (!etype) {
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "sanity check skipped for %s (etype==0)\n", name);
+ }
+ return;
+ }
+
+ if (!IS_SPEC(etype)) {
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "sanity check skipped for %s (!IS_SPEC)\n", name);
+ }
+ return;
+ }
+
+ noun=nounName(etype);
+
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "checking sanity for %s %p\n", name, etype);
+ }
+
+ if ((SPEC_NOUN(etype)==V_CHAR ||
+ SPEC_NOUN(etype)==V_FLOAT ||
+ SPEC_NOUN(etype)==V_DOUBLE ||
+ SPEC_NOUN(etype)==V_VOID) &&
+ (etype->select.s._short || SPEC_LONG(etype))) {
+ // long or short for char float double or void
+ werror (E_LONG_OR_SHORT_INVALID, noun, name);
+ }
+ if ((SPEC_NOUN(etype)==V_FLOAT ||
+ SPEC_NOUN(etype)==V_DOUBLE ||
+ SPEC_NOUN(etype)==V_VOID) &&
+ (etype->select.s._signed || SPEC_USIGN(etype))) {
+ // signed or unsigned for float double or void
+ werror (E_SIGNED_OR_UNSIGNED_INVALID, noun, name);
+ }
+
+ // special case for "short"
+ if (etype->select.s._short) {
+ SPEC_NOUN(etype) = options.shortis8bits ? V_CHAR : V_INT;
+ etype->select.s._short = 0;
+ }
+
+ /* if no noun e.g.
+ "const a;" or "data b;" or "signed s" or "long l"
+ assume an int */
+ if (!SPEC_NOUN(etype)) {
+ SPEC_NOUN(etype)=V_INT;
+ }
+
+ if (etype->select.s._signed && SPEC_USIGN(etype)) {
+ // signed AND unsigned
+ werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name);
+ }
+ if (etype->select.s._short && SPEC_LONG(etype)) {
+ // short AND long
+ werror (E_LONG_AND_SHORT_INVALID, noun, name);
+ }
+
+}
+
/*------------------------------------------------------------------*/
-/* mergeSpec - merges two specifiers and returns the new one */
+/* mergeSpec - merges two specifiers and returns the new one */
/*------------------------------------------------------------------*/
sym_link *
-mergeSpec (sym_link * dest, sym_link * src)
+mergeSpec (sym_link * dest, sym_link * src, char *name)
{
- /* if noun different then src overrides */
- if (SPEC_NOUN (dest) != SPEC_NOUN (src) && !SPEC_NOUN (dest))
- SPEC_NOUN (dest) = SPEC_NOUN (src);
-
- /* if destination has no storage class */
- if (!SPEC_SCLS (dest) ||
- ((SPEC_SCLS(dest) == S_CONSTANT || SPEC_SCLS(dest) == S_REGISTER) &&
- SPEC_SCLS (src)))
- SPEC_SCLS (dest) = SPEC_SCLS (src);
- /* special case for const */
+ if (!IS_SPEC(dest) || !IS_SPEC(src)) {
+#if 0
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "cannot merge declarator");
+ exit (1);
+#else
+ werror (E_SYNTAX_ERROR, yytext);
+ // the show must go on
+ return newIntLink();
+#endif
+ }
+
+ if (SPEC_NOUN(src)) {
+ if (!SPEC_NOUN(dest)) {
+ SPEC_NOUN(dest)=SPEC_NOUN(src);
+ } else {
+ /* we shouldn't redeclare the type */
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "mergeSpec: ");
+ }
+ werror(E_TWO_OR_MORE_DATA_TYPES, name);
+ }
+ }
+
+ if (SPEC_SCLS(src)) {
+ /* if destination has no storage class */
+ if (!SPEC_SCLS (dest) || SPEC_SCLS(dest)==S_REGISTER) {
+ SPEC_SCLS (dest) = SPEC_SCLS (src);
+ } else {
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "mergeSpec: ");
+ }
+ werror(E_TWO_OR_MORE_STORAGE_CLASSES, name);
+ }
+ }
+
/* copy all the specifications */
+
+ // we really should do:
+#if 0
+ if (SPEC_what(src)) {
+ if (SPEC_what(dest)) {
+ werror(W_DUPLICATE_SPEC, "what");
+ }
+ SPEC_what(dst)|=SPEC_what(src);
+ }
+#endif
+ // but there are more important thing right now
+
SPEC_LONG (dest) |= SPEC_LONG (src);
- SPEC_SHORT (dest) |= SPEC_SHORT (src);
+ dest->select.s._short|=src->select.s._short;
SPEC_USIGN (dest) |= SPEC_USIGN (src);
+ dest->select.s._signed|=src->select.s._signed;
SPEC_STAT (dest) |= SPEC_STAT (src);
SPEC_EXTR (dest) |= SPEC_EXTR (src);
+ SPEC_CONST(dest) |= SPEC_CONST (src);
SPEC_ABSA (dest) |= SPEC_ABSA (src);
- SPEC_RENT (dest) |= SPEC_RENT (src);
- SPEC_INTN (dest) |= SPEC_INTN (src);
- SPEC_BANK (dest) |= SPEC_BANK (src);
SPEC_VOLATILE (dest) |= SPEC_VOLATILE (src);
- SPEC_CRTCL (dest) |= SPEC_CRTCL (src);
SPEC_ADDR (dest) |= SPEC_ADDR (src);
SPEC_OCLS (dest) = SPEC_OCLS (src);
SPEC_BLEN (dest) |= SPEC_BLEN (src);
SPEC_BSTR (dest) |= SPEC_BSTR (src);
SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
- SPEC_NONBANKED (dest) |= SPEC_NONBANKED (src);
-
+ 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);
- return dest;
-}
-
-/*------------------------------------------------------------------*/
-/* cloneSpec - copies the entire spec and returns a new spec */
-/*------------------------------------------------------------------*/
-sym_link *
-cloneSpec (sym_link * src)
-{
- sym_link *spec;
-
- /* go thru chain till we find the specifier */
- while (src && src->class != SPECIFIER)
- src = src->next;
+ /* 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);
+ FUNC_ISCRITICAL(dest) |= FUNC_ISCRITICAL(src);
+ FUNC_ISREENT(dest) |= FUNC_ISREENT(src);
+ FUNC_ISNAKED(dest) |= FUNC_ISNAKED(src);
+ FUNC_ISISR(dest) |= FUNC_ISISR(src);
+ FUNC_ISJAVANATIVE(dest) |= FUNC_ISJAVANATIVE(src);
+ FUNC_ISBUILTIN(dest) |= FUNC_ISBUILTIN(src);
+ FUNC_ISOVERLAY(dest) |= FUNC_ISOVERLAY(src);
+ FUNC_INTNO(dest) |= FUNC_INTNO(src);
+ FUNC_REGBANK(dest) |= FUNC_REGBANK(src);
- spec = newLink ();
- memcpy (spec, src, sizeof (sym_link));
- return spec;
+ return dest;
}
/*------------------------------------------------------------------*/
static int gCount = 0;
static char gname[SDCC_NAME_MAX + 1];
- sprintf (gname, "__%04d%04d", level, gCount++);
+ SNPRINTF (gname, sizeof(gname), "__%04d%04d", level, gCount++);
return gname;
}
}
/*------------------------------------------------------------------*/
-/* newCharLink() - creates an int type */
+/* newCharLink() - creates an char type */
/*------------------------------------------------------------------*/
sym_link *
newCharLink ()
{
sym_link *p;
- p = newLink ();
- p->class = SPECIFIER;
+ p = newLink (SPECIFIER);
SPEC_NOUN (p) = V_CHAR;
return p;
{
sym_link *p;
- p = newLink ();
- p->class = SPECIFIER;
+ p = newLink (SPECIFIER);
SPEC_NOUN (p) = V_FLOAT;
return p;
{
sym_link *p;
- p = newLink ();
- p->class = SPECIFIER;
+ p = newLink (SPECIFIER);
SPEC_NOUN (p) = V_INT;
SPEC_LONG (p) = 1;
{
sym_link *p;
- p = newLink ();
- p->class = SPECIFIER;
+ p = newLink (SPECIFIER);
SPEC_NOUN (p) = V_INT;
return p;
switch (SPEC_NOUN (p))
{ /* depending on the specifier type */
case V_INT:
- return (IS_LONG (p) ? LONGSIZE : (IS_SHORT (p) ? SHORTSIZE : INTSIZE));
+ return (IS_LONG (p) ? LONGSIZE : INTSIZE);
case V_FLOAT:
return FLOATSIZE;
case V_CHAR:
case V_LABEL:
return 0;
case V_SBIT:
- return BITSIZE;
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 */
switch (DCL_TYPE (p))
{
- case FUNCTION:
- return 2;
case ARRAY:
- return DCL_ELEM (p) * getSize (p->next);
+ if (DCL_ELEM(p)) {
+ return DCL_ELEM (p) * getSize (p->next);
+ } else {
+ // werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ // "can not tell the size of an array[]");
+ return 0;
+ }
case IPOINTER:
case PPOINTER:
case POINTER:
case EEPPOINTER:
case FPOINTER:
case CPOINTER:
+ case FUNCTION:
return (FPTRSIZE);
case GPOINTER:
return (GPTRSIZE);
switch (SPEC_NOUN (p))
{ /* depending on the specifier type */
case V_INT:
- return (IS_LONG (p) ? LONGSIZE * 8 : (IS_SHORT (p) ? SHORTSIZE * 8 : INTSIZE * 8));
+ return (IS_LONG (p) ? LONGSIZE * 8 : INTSIZE * 8);
case V_FLOAT:
return FLOATSIZE * 8;
case V_CHAR:
case V_LABEL:
return 0;
case V_SBIT:
- return 1;
case V_BIT:
+ return 1;
+ case V_BITFIELD:
return SPEC_BLEN (p);
default:
return 0;
/* this is a specifier */
switch (DCL_TYPE (p))
{
- case FUNCTION:
- return 2;
case ARRAY:
return DCL_ELEM (p) * getSize (p->next) * 8;
case IPOINTER:
case EEPPOINTER:
case FPOINTER:
case CPOINTER:
+ case FUNCTION:
return (FPTRSIZE * 8);
case GPOINTER:
return (GPTRSIZE * 8);
dest->type = copyLinkChain (src->type);
dest->etype = getSpec (dest->type);
dest->next = NULL;
- dest->args = copyValueChain (src->args);
dest->key = src->key;
- dest->calleeSave = src->calleeSave;
dest->allocreq = src->allocreq;
return dest;
}
{
symbol *sym = symHead;
symbol *csym = NULL;
+ int error = 0;
for (; sym != NULL; sym = sym->next)
{
changePointer(sym);
+ checkTypeSanity(sym->etype, sym->name);
+
+ if (!sym->level && !(IS_SPEC(sym->etype) && IS_TYPEDEF(sym->etype)))
+ checkDecl (sym, 0);
+
/* if already exists in the symbol table then check if
- the previous was an extern definition if yes then
+ 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 ((csym = findSymWithLevel (SymbolTab, sym)) &&
- csym->level == sym->level)
- {
+ csym->level == sym->level) {
+
+ /* 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);
+ }
- /* previous definition extern ? */
- if (IS_EXTERN (csym->etype))
- {
- /* do types match ? */
- if (checkType (csym->type, sym->type) != 1)
- /* no then error */
- werror (E_DUPLICATE, csym->name);
-
- /* delete current entry */
- deleteSym (SymbolTab, csym, csym->name);
- /* add new entry */
- addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
- }
- else /* not extern */
+ #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);
+ 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");
continue;
}
- /* check if previously defined */
- if (csym && csym->level == sym->level)
- {
- /* if the previous one was declared as extern */
- /* then check the type with the current one */
- if (IS_EXTERN (csym->etype))
- {
- if (checkType (csym->type, sym->type) <= 0)
- werror (W_EXTERN_MISMATCH, csym->name);
- }
- }
+ if (csym->ival && !sym->ival)
+ sym->ival = csym->ival;
- addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+ /* delete current entry */
+ deleteSym (SymbolTab, csym, csym->name);
+ deleteFromSeg(csym);
+ }
+
+ /* add new entry */
+ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
}
}
}
/*------------------------------------------------------------------*/
-/* structElemType - returns the type info of a sturct member */
+/* structElemType - returns the type info of a struct member */
/*------------------------------------------------------------------*/
sym_link *
-structElemType (sym_link * stype, value * id, value ** argsp)
+structElemType (sym_link * stype, value * id)
{
symbol *fields = (SPEC_STRUCT (stype) ? SPEC_STRUCT (stype)->fields : NULL);
sym_link *type, *etype;
sym_link *petype = getSpec (stype);
- if (!fields || !id)
- return NULL;
+ 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 (IS_SPEC (type))
+ SPEC_CONST (type) |= SPEC_CONST (stype);
+ else
+ DCL_PTR_CONST (type) |= SPEC_CONST (stype);
+ return type;
+ }
+ fields = fields->next;
+ }
+ }
- /* look for the id */
- while (fields)
- {
- if (strcmp (fields->rname, id->name) == 0)
- {
- if (argsp)
- {
- *argsp = fields->args;
- }
- type = copyLinkChain (fields->type);
- etype = getSpec (type);
- SPEC_SCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ?
- SPEC_SCLS (etype) : SPEC_SCLS (petype));
- return type;
- }
- fields = fields->next;
- }
werror (E_NOT_MEMBER, id->name);
-
- return NULL;
+
+ // the show must go on
+ return newIntLink();
}
/*------------------------------------------------------------------*/
while (loop) {
/* create the internal name for this variable */
- sprintf (loop->rname, "_%s", loop->name);
- loop->offset = (su == UNION ? sum = 0 : sum);
+ 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_BIT;
+ SPEC_NOUN (loop->etype) = V_BITFIELD;
SPEC_USIGN (loop->etype) = 1;
- /* check if this fit into the remaining */
- /* bits of this byte else align it to the */
- /* next byte boundary */
- if ((SPEC_BLEN (loop->etype) = loop->bitVar) <= (8 - bitOffset)) {
- SPEC_BSTR (loop->etype) = bitOffset;
- if ((bitOffset += (loop->bitVar % 8)) == 8)
- sum++;
+ 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 /* does not fit */ {
- bitOffset = 0;
- SPEC_BSTR (loop->etype) = bitOffset;
- sum += (loop->bitVar / 8);
- bitOffset += (loop->bitVar % 8);
- }
- /* if this is the last field then pad */
- if (!loop->next && bitOffset && bitOffset != 8) {
- bitOffset = 0;
- 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 {
- checkDecl (loop);
+ /* This is a non-bit field. Make sure we are */
+ /* byte aligned first */
+ if (bitOffset) {
+ sum++;
+ loop->offset = (su == UNION ? sum = 0 : sum);
+ bitOffset = 0;
+ }
+ loop->offset = sum;
+ checkDecl (loop, 1);
sum += getSize (loop->type);
}
- /* if function then do the arguments for it */
- if (funcInChain (loop->type)) {
- processFuncArgs (loop, 1);
- }
-
loop = loop->next;
- /* if this is not a bitfield but the */
- /* previous one was and did not take */
- /* the whole byte then pad the rest */
- if ((loop && !loop->bitVar) && bitOffset) {
- bitOffset = 0;
- sum++;
- }
-
/* if union then size = sizeof larget field */
- if (su == UNION)
+ 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);
}
/* checkSClass - check the storage class specification */
/*------------------------------------------------------------------*/
static void
-checkSClass (symbol * sym)
+checkSClass (symbol * sym, int isProto)
{
- /* type is literal can happen foe enums change
+ sym_link *t;
+
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "checkSClass: %s \n", sym->name);
+ }
+
+ /* 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 the initial value will be xlated */
- /* to an absolute address */
+
+ /* 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;
- /* if initial value given */
- if (sym->ival)
- {
- SPEC_ABSA (sym->etype) = 1;
- SPEC_ADDR (sym->etype) =
- (int) list2int (sym->ival);
- sym->ival = NULL;
- }
}
-
+
/* if absolute address given then it mark it as
- volatile */
- if (IS_ABSOLUTE (sym->etype))
- SPEC_VOLATILE (sym->etype) = 1;
+ volatile -- except in the PIC port */
+
+#if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
+ /* The PIC port uses a different peep hole optimizer based on "pCode" */
+ if (!TARGET_IS_PIC && !TARGET_IS_PIC16)
+#endif
+
+ if (IS_ABSOLUTE (sym->etype))
+ SPEC_VOLATILE (sym->etype) = 1;
+
+ /* If code memory is read only, then pointers to code memory */
+ /* implicitly point to constants -- make this explicit */
+ t = sym->type;
+ while (t && t->next) {
+ if (IS_CODEPTR(t) && port->mem.code_ro) {
+ if (IS_SPEC(t->next)) {
+ SPEC_CONST (t->next) = 1;
+ } else {
+ DCL_PTR_CONST (t->next) = 1;
+ }
+ }
+ t = t->next;
+ }
/* global variables declared const put into code */
+ /* if no other storage class specified */
if (sym->level == 0 &&
- SPEC_SCLS (sym->etype) == S_CONSTANT)
- {
+ SPEC_SCLS(sym->etype) == S_FIXED &&
+ !IS_FUNC(sym->type)) {
+ /* find the first non-array link */
+ t = sym->type;
+ while (IS_ARRAY(t))
+ t = t->next;
+ if (IS_CONSTANT (t)) {
SPEC_SCLS (sym->etype) = S_CODE;
- SPEC_CONST (sym->etype) = 1;
}
+ }
/* global variable in code space is a constant */
if (sym->level == 0 &&
SPEC_SCLS (sym->etype) == S_CODE &&
- port->mem.code_ro)
- SPEC_CONST (sym->etype) = 1;
-
+ port->mem.code_ro) {
+ /* find the first non-array link */
+ t = sym->type;
+ while (IS_ARRAY(t))
+ t = t->next;
+ if (IS_SPEC(t)) {
+ SPEC_CONST (t) = 1;
+ } else {
+ DCL_PTR_CONST (t) = 1;
+ }
+ }
/* if bit variable then no storage class can be */
/* specified since bit is already a storage */
sym->ival = NULL;
}
- /* if this is an automatic symbol then */
- /* storage class will be ignored and */
- /* symbol will be allocated on stack/ */
- /* data depending on flag */
- if (sym->level &&
- (options.stackAuto || reentrant) &&
- (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_CONSTANT))
- {
-
- werror (E_AUTO_ASSUMED, sym->name);
+ /* 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);
+ }
}
+ }
/* automatic symbols cannot be given */
/* an absolute address ignore it */
if ((IS_ARRAY (sym->type) || IS_PTR (sym->type)) &&
(SPEC_NOUN (sym->etype) == V_BIT ||
SPEC_NOUN (sym->etype) == V_SBIT ||
+ SPEC_NOUN (sym->etype) == V_BITFIELD ||
SPEC_SCLS (sym->etype) == S_SFR))
werror (E_BIT_ARRAY, sym->name);
SPEC_BSTR (sym->etype) = 0;
}
- /* 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))
- werror (E_CODE_NO_INIT, sym->name);
+ if (!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))
+ 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)
+ if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED &&
+ !IS_STATIC(sym->etype))
{
- if (options.stackAuto || (currFunc && IS_RENT (currFunc->etype)))
+ if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type)))
{
SPEC_SCLS (sym->etype) = (options.useXstack ?
S_XSTACK : S_STACK);
* 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 ? 1 : options.useXstack;
+ bool useXdata = (TARGET_IS_DS390 || TARGET_IS_DS400) ?
+ 1 : options.useXstack;
SPEC_SCLS (sym->etype) = (useXdata ?
S_XDATA : S_FIXED);
}
for (p = sym->type; p; p = p->next)
{
if (!IS_SPEC (p) && DCL_TYPE (p) == UPOINTER)
- DCL_TYPE (p) = GPOINTER;
+ DCL_TYPE (p) = port->unqualified_pointer;
if (IS_PTR (p) && IS_FUNC (p->next))
DCL_TYPE (p) = CPOINTER;
}
/* checkDecl - does semantic validation of a declaration */
/*------------------------------------------------------------------*/
int
-checkDecl (symbol * sym)
+checkDecl (symbol * sym, int isProto)
{
- checkSClass (sym); /* check the storage class */
+ checkSClass (sym, isProto); /* check the storage class */
changePointer (sym); /* change pointers if required */
/* if this is an array without any dimension
sym_link *head, *curr, *loop;
curr = p;
- head = loop = (curr ? newLink () : (void *) NULL);
+ head = loop = (curr ? newLink (p->class) : (void *) NULL);
while (curr)
{
memcpy (loop, curr, sizeof (sym_link)); /* copy it */
- loop->next = (curr->next ? newLink () : (void *) NULL);
+ loop->next = (curr->next ? newLink (curr->next->class) : (void *) NULL);
loop = loop->next;
curr = curr->next;
}
/* computeType - computes the resultant type from two types */
/*------------------------------------------------------------------*/
sym_link *
-computeType (sym_link * type1, sym_link * type2)
+computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
{
sym_link *rType;
sym_link *reType;
else if (IS_BITVAR (etype2) && !IS_BITVAR (etype1))
rType = copyLinkChain (type1);
else
- /* if one of them is a pointer then that
+ /* if one of them is a pointer or array then that
prevails */
- if (IS_PTR (type1))
+ if (IS_PTR (type1) || IS_ARRAY (type1))
rType = copyLinkChain (type1);
- else if (IS_PTR (type2))
+ else if (IS_PTR (type2) || IS_ARRAY (type2))
rType = copyLinkChain (type2);
else if (getSize (type1) > getSize (type2))
rType = copyLinkChain (type1);
reType = getSpec (rType);
- /* if either of them unsigned then make this unsigned */
- if ((SPEC_USIGN (etype1) || SPEC_USIGN (etype2)) && !IS_FLOAT (reType))
+ /* avoid conflicting types */
+ reType->select.s._signed = 0;
+
+ if (IS_CHAR (reType) && promoteCharToInt)
+ SPEC_NOUN (reType) = V_INT;
+
+ if ( ( ( SPEC_USIGN (etype1)
+ && (getSize (etype1) >= getSize (reType)))
+ || ( SPEC_USIGN (etype2)
+ && (getSize (etype2) >= getSize (reType))))
+ && !IS_FLOAT (reType))
SPEC_USIGN (reType) = 1;
+ else
+ SPEC_USIGN (reType) = 0;
/* if result is a literal then make not so */
if (IS_LITERAL (reType))
return rType;
}
-/*------------------------------------------------------------------*/
-/* checkType - will do type check return 1 if match */
-/*------------------------------------------------------------------*/
-int
-checkType (sym_link * dest, sym_link * src)
+/*--------------------------------------------------------------------*/
+/* compareType - will do type check return 1 if match, -1 if castable */
+/*--------------------------------------------------------------------*/
+int
+compareType (sym_link * dest, sym_link * src)
{
if (!dest && !src)
return 1;
{
if (IS_DECL (src))
{
- if (DCL_TYPE (src) == DCL_TYPE (dest))
- return checkType (dest->next, src->next);
- else if (IS_PTR (src) && IS_PTR (dest))
- return -1;
- else if (IS_PTR (dest) && IS_ARRAY (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;
- else if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src))
- return -1 * checkType (dest->next, src);
- else
- return 0;
+ 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;
SPEC_NOUN (src) == V_VOID)
return -1;
- /* char === to short */
- if (SPEC_NOUN (dest) == V_CHAR &&
- SPEC_NOUN (src) == V_INT &&
- SPEC_SHORT (src))
- return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2);
-
- if (SPEC_NOUN (src) == V_CHAR &&
- SPEC_NOUN (dest) == V_INT &&
- SPEC_SHORT (dest))
- return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2);
-
/* if they are both bitfields then if the lengths
and starts don't match */
if (IS_BITFIELD (dest) && IS_BITFIELD (src) &&
if (SPEC_LONG (dest) != SPEC_LONG (src))
return -1;
- if (SPEC_SHORT (dest) != SPEC_SHORT (src))
+ if (SPEC_USIGN (dest) != SPEC_USIGN (src))
return -1;
- if (SPEC_USIGN (dest) != SPEC_USIGN (src))
- 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 calle save list */
+/* inCalleeSaveList - return 1 if found in callee save list */
/*------------------------------------------------------------------*/
-bool
-inCalleeSaveList (char *s)
+static int
+calleeCmp(void *p1, void *p2)
{
- int i;
-
- for (i = 0; options.calleeSaves[i]; i++)
- if (strcmp (options.calleeSaves[i], s) == 0)
- return 1;
+ return (strcmp((char *)p1, (char *)(p2)) == 0);
+}
- return 0;
+bool
+inCalleeSaveList(char *s)
+{
+ if (options.all_callee_saves)
+ return 1;
+ return isinSetWith(options.calleeSavesSet, s, calleeCmp);
}
/*-----------------------------------------------------------------*/
-/* aggregateArgToPointer: change an agggregate type function */
+/* aggregateToPointer: change an agggregate type function */
/* argument to a pointer to that type. */
/*-----------------------------------------------------------------*/
-void
-aggregateArgToPointer (value * val)
+value *
+aggregateToPointer (value * val)
{
if (IS_AGGREGATE (val->type))
{
sym_link *p = val->type;
werror (W_STRUCT_AS_ARG, val->name);
- val->type = newLink ();
+ val->type = newLink (DECLARATOR);
val->type->next = p;
}
DCL_TYPE (val->type) = PPOINTER;
break;
case S_FIXED:
- if (TARGET_IS_DS390)
- {
- /* The AUTO and REGISTER classes should probably
- * also become generic pointers, but I haven't yet
- * devised a test case for that.
- */
- DCL_TYPE (val->type) = GPOINTER;
- break;
- }
- /* fall through! */
+ 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) = EEPPOINTER;
break;
default:
- DCL_TYPE (val->type) = GPOINTER;
+ 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->etype = getSpec (val->sym->type);
}
}
+ return val;
}
/*------------------------------------------------------------------*/
/* checkFunction - does all kinds of check on a function */
/*------------------------------------------------------------------*/
int
-checkFunction (symbol * sym)
+checkFunction (symbol * sym, symbol *csym)
{
- symbol *csym;
value *exargs, *acargs;
+ value *checkValue;
int argCnt = 0;
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "checkFunction: %s ", sym->name);
+ }
+
+ if (!IS_DECL(sym->type) || DCL_TYPE(sym->type)!=FUNCTION)
+ {
+ werror(E_SYNTAX_ERROR, sym->name);
+ return 0;
+ }
+
+ /* make sure the type is complete and sane */
+ checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
+
/* if not type then some kind of error */
if (!sym->type)
return 0;
/* check if this function is defined as calleeSaves
then mark it as such */
- sym->calleeSave = inCalleeSaveList (sym->name);
+ FUNC_CALLEESAVES(sym->type) = inCalleeSaveList (sym->name);
/* if interrupt service routine */
/* then it cannot have arguments */
- if (sym->args && IS_ISR (sym->etype) && !IS_VOID (sym->args->type))
+ if (IFFUNC_ARGS(sym->type) && FUNC_ISISR (sym->type))
{
- werror (E_INT_ARGS, sym->name);
- sym->args = NULL;
+ if (!IS_VOID(FUNC_ARGS(sym->type)->type)) {
+ werror (E_INT_ARGS, sym->name);
+ FUNC_ARGS(sym->type)=NULL;
+ }
+ }
+
+ for (argCnt=1, acargs = FUNC_ARGS(sym->type);
+ acargs;
+ acargs=acargs->next, argCnt++) {
+ 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
+ SNPRINTF (acargs->name, sizeof(acargs->name), "_%s_PARM_%d", sym->name, argCnt);
+ acargs->sym = newSymbol (acargs->name, 1);
+ SPEC_OCLS (acargs->etype) = istack;
+ acargs->sym->type = copyLinkChain (acargs->type);
+ 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) {
+ // synthesized name
+ werror(E_PARAM_NAME_OMITTED, sym->name, argCnt);
}
+ }
+ argCnt--;
- if (!(csym = findSym (SymbolTab, sym, sym->name)))
+ if (!csym && !(csym = findSym (SymbolTab, sym, sym->name)))
return 1; /* not defined nothing more to check */
/* check if body already present */
- if (csym && csym->fbody)
+ if (csym && IFFUNC_HASBODY(csym->type))
{
werror (E_FUNC_BODY, sym->name);
return 0;
}
/* check the return value type */
- if (checkType (csym->type, sym->type) <= 0)
+ if (compareType (csym->type, sym->type) <= 0)
{
werror (E_PREV_DEF_CONFLICT, csym->name, "type");
- werror (E_CONTINUE, "previous defintion type ");
- printTypeChain (csym->type, stderr);
- fprintf (stderr, "\n");
- werror (E_CONTINUE, "current definition type ");
- printTypeChain (sym->type, stderr);
- fprintf (stderr, "\n");
+ printFromToType(csym->type, sym->type);
return 0;
}
- if (SPEC_INTRTN (csym->etype) != SPEC_INTRTN (sym->etype))
+ if (FUNC_ISISR (csym->type) != FUNC_ISISR (sym->type))
{
werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt");
- return 0;
}
- if (SPEC_BANK (csym->etype) != SPEC_BANK (sym->etype))
+ if (FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type))
{
werror (E_PREV_DEF_CONFLICT, csym->name, "using");
- return 0;
}
- /* compare expected agrs with actual args */
- exargs = csym->args;
- acargs = sym->args;
+ if (IFFUNC_ISNAKED (csym->type) != IFFUNC_ISNAKED (sym->type))
+ {
+ 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 */
+ /* lax checking is ok (but may not be true for in future ports) */
+ if (IFFUNC_ISREENT (csym->type) != IFFUNC_ISREENT (sym->type)
+ && argCnt>1)
+ {
+ //printf("argCnt = %d\n",argCnt);
+ werror (E_PREV_DEF_CONFLICT, csym->name, "reentrant");
+ }
+
+ /* compare expected args with actual args */
+ exargs = FUNC_ARGS(csym->type);
+ acargs = FUNC_ARGS(sym->type);
/* for all the expected args do */
for (argCnt = 1;
exargs && acargs;
exargs = exargs->next, acargs = acargs->next, argCnt++)
{
- value *checkValue;
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "checkFunction: %s ", exargs->name);
+ }
+ /* make sure the type is complete and sane */
+ checkTypeSanity(exargs->etype, exargs->name);
+
/* If the actual argument is an array, any prototype
* will have modified it to a pointer. Duplicate that
* change here.
if (IS_AGGREGATE (acargs->type))
{
checkValue = copyValue (acargs);
- aggregateArgToPointer (checkValue);
+ aggregateToPointer (checkValue);
}
else
{
checkValue = acargs;
}
- if (checkType (exargs->type, checkValue->type) <= 0)
+ if (compareType (exargs->type, checkValue->type) <= 0)
{
werror (E_ARG_TYPE, argCnt);
+ printFromToType(exargs->type, checkValue->type);
return 0;
}
}
/* replace with this defition */
sym->cdef = csym->cdef;
deleteSym (SymbolTab, csym, csym->name);
- addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+ deleteFromSeg(csym);
+ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
if (IS_EXTERN (csym->etype) && !
IS_EXTERN (sym->etype))
{
return 1;
}
+/*------------------------------------------------------------------*/
+/* cdbStructBlock - calls struct printing for a blcks */
+/*------------------------------------------------------------------*/
+void cdbStructBlock (int block)
+{
+ int i;
+ bucket **table = StructTab;
+ bucket *chain;
+
+ /* go thru the entire table */
+ 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);
+ }
+ }
+ }
+}
+
/*-----------------------------------------------------------------*/
/* processFuncArgs - does some processing with function args */
/*-----------------------------------------------------------------*/
void
-processFuncArgs (symbol * func, int ignoreName)
+processFuncArgs (symbol * func)
{
value *val;
int pNum = 1;
+ sym_link *funcType=func->type;
+
+ 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)) {
+ funcType=funcType->next;
+ }
/* if this function has variable argument list */
/* then make the function a reentrant one */
- if (func->hasVargs)
- SPEC_RENT (func->etype) = 1;
+ if (IFFUNC_HASVARARGS(funcType) || (options.stackAuto && !func->cdef))
+ FUNC_ISREENT(funcType)=1;
/* check if this function is defined as calleeSaves
then mark it as such */
- func->calleeSave = inCalleeSaveList (func->name);
+ FUNC_CALLEESAVES(funcType) = inCalleeSaveList (func->name);
- val = func->args; /* loop thru all the arguments */
+ /* loop thru all the arguments */
+ val = FUNC_ARGS(funcType);
/* if it is void then remove parameters */
if (val && IS_VOID (val->type))
{
- func->args = NULL;
+ FUNC_ARGS(funcType) = NULL;
return;
}
/* change it to pointer to the same type */
while (val)
{
+ int argreg = 0;
/* mark it as a register parameter if
the function does not have VA_ARG
- and as port dictates
- not inhibited by command line option or #pragma */
- if (!func->hasVargs &&
- !IS_RENT (func->etype) &&
- (*port->reg_parm) (val->type))
+ 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;
}
if (IS_AGGREGATE (val->type))
{
- aggregateArgToPointer (val);
+ aggregateToPointer (val);
}
+
val = val->next;
pNum++;
}
if (func->cdef) {
/* ignore --stack-auto for this one, we don't know how it is compiled */
/* simply trust on --int-long-reent or --float-reent */
- if (IS_RENT(func->etype)) {
+ if (IFFUNC_ISREENT(funcType)) {
return;
}
} else {
/* if this function is reentrant or */
/* automatics r 2b stacked then nothing */
- if (IS_RENT (func->etype) || options.stackAuto)
+ if (IFFUNC_ISREENT (funcType) || options.stackAuto)
return;
}
- val = func->args;
+ val = FUNC_ARGS(funcType);
pNum = 1;
while (val)
{
/* synthesize a variable name */
if (!val->sym)
{
-
- sprintf (val->name, "_%s_PARM_%d", func->name, pNum++);
+ 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;
- strcpy (val->sym->rname, val->name);
- SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
- SPEC_STAT (func->etype);
+ 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 */
{
- sprintf (val->name, "_%s_PARM_%d", func->name, pNum++);
- strcpy (val->sym->rname, val->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);
- SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
- SPEC_STAT (func->etype);
+
+ #if 0
+ /* ?? static functions shouldn't imply static parameters - EEP */
+ if (IS_SPEC(func->etype)) {
+ SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
+ SPEC_STAT (func->etype);
+ }
+ #endif
}
+ if (!isinSet(operKeyReset, val->sym)) {
+ addSet (&operKeyReset, val->sym);
+ applyToSet (operKeyReset, resetParmKey);
+ }
val = val->next;
}
}
/*-----------------------------------------------------------------*/
/* printTypeChain - prints the type chain in human readable form */
/*-----------------------------------------------------------------*/
-void
-printTypeChain (sym_link * type, FILE * of)
+void
+printTypeChain (sym_link * start, FILE * of)
{
int nlr = 0;
+ value *args;
+ sym_link * type, * search;
+ STORAGE_CLASS scls;
if (!of)
{
nlr = 1;
}
+ if (start==NULL) {
+ fprintf (of, "void");
+ return;
+ }
+
+ /* Print the chain as it is written in the source: */
+ /* start with the last entry. */
+ /* However, the storage class at the end of the */
+ /* chain reall applies to the first in the chain! */
+
+ for (type = start; type && type->next; type = type->next)
+ ;
+ if (IS_SPEC (type))
+ scls=SPEC_SCLS(type);
+ else
+ scls=0;
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;
+ }
+ }
+
if (IS_DECL (type))
{
- if (DCL_PTR_VOLATILE(type)) {
- fprintf (of, "volatile ");
+ 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 ");
+ 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 * ");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "generic* ");
break;
case CPOINTER:
- fprintf (of, "_code * ");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "code* ");
break;
case FPOINTER:
- fprintf (of, "_far * ");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "xdata* ");
break;
case EEPPOINTER:
- fprintf (of, "_eeprom * ");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "eeprom* ");
break;
-
case POINTER:
- fprintf (of, "_near * ");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "near* ");
break;
case IPOINTER:
- fprintf (of, "_idata *");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "idata* ");
break;
case PPOINTER:
- fprintf (of, "_pdata *");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "pdata* ");
break;
case UPOINTER:
- fprintf (of, " _unkown *");
- if (DCL_PTR_CONST (type))
- fprintf (of, "const ");
+ fprintf (of, "unknown* ");
break;
case ARRAY:
- fprintf (of, "array of ");
+ if (DCL_ELEM(type)) {
+ fprintf (of, "[%d] ", DCL_ELEM(type));
+ } else {
+ fprintf (of, "[] ");
+ }
break;
}
}
else
{
if (SPEC_VOLATILE (type))
- fprintf (of, "volatile ");
- if (SPEC_USIGN (type))
- fprintf (of, "unsigned ");
+ fprintf (of, "volatile-");
if (SPEC_CONST (type))
- fprintf (of, "const ");
-
+ fprintf (of, "const-");
+ if (SPEC_USIGN (type))
+ fprintf (of, "unsigned-");
switch (SPEC_NOUN (type))
{
case V_INT:
if (IS_LONG (type))
- fprintf (of, "long ");
- else if (IS_SHORT (type))
- fprintf (of, "short ");
- else
- fprintf (of, "int ");
+ fprintf (of, "long-");
+ fprintf (of, "int");
break;
case V_CHAR:
- fprintf (of, "char ");
+ fprintf (of, "char");
break;
case V_VOID:
- fprintf (of, "void ");
+ fprintf (of, "void");
break;
case V_FLOAT:
- fprintf (of, "float ");
+ fprintf (of, "float");
break;
case V_STRUCT:
break;
case V_SBIT:
- fprintf (of, "sbit ");
+ fprintf (of, "sbit");
break;
case V_BIT:
- fprintf (of, "bit {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
+ 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;
}
}
- type = type->next;
+ /* search entry in list before "type" */
+ for (search = start; search && search->next != type;)
+ search = search->next;
+ type = search;
+ if (type)
+ fputc (' ', of);
}
if (nlr)
fprintf (of, "\n");
}
-/*-----------------------------------------------------------------*/
-/* cdbTypeInfo - print the type information for debugger */
-/*-----------------------------------------------------------------*/
-void
-cdbTypeInfo (sym_link * type, FILE * of)
+/*--------------------------------------------------------------------*/
+/* printTypeChainRaw - prints the type chain in human readable form */
+/* in the raw data structure ordering */
+/*--------------------------------------------------------------------*/
+void
+printTypeChainRaw (sym_link * start, FILE * of)
{
- fprintf (of, "{%d}", getSize (type));
+ int nlr = 0;
+ value *args;
+ sym_link * type;
+
+ if (!of)
+ {
+ of = stdout;
+ nlr = 1;
+ }
+
+ if (start==NULL) {
+ fprintf (of, "void");
+ return;
+ }
+
+ 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, "DF,");
+ 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, "DG,");
+ fprintf (of, "generic* ");
break;
case CPOINTER:
- fprintf (of, "DC,");
+ fprintf (of, "code* ");
break;
case FPOINTER:
- fprintf (of, "DX,");
+ fprintf (of, "xdata* ");
+ break;
+ case EEPPOINTER:
+ fprintf (of, "eeprom* ");
break;
case POINTER:
- fprintf (of, "DD,");
+ fprintf (of, "near* ");
break;
case IPOINTER:
- fprintf (of, "DI,");
+ fprintf (of, "idata* ");
break;
case PPOINTER:
- fprintf (of, "DP,");
+ fprintf (of, "pdata* ");
break;
- case EEPPOINTER:
- fprintf (of, "DA,");
+ case UPOINTER:
+ fprintf (of, "unknown* ");
break;
case ARRAY:
- fprintf (of, "DA%d,", DCL_ELEM (type));
- break;
- default:
+ 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
+ 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, "SL");
- else if (IS_SHORT (type))
- fprintf (of, "SS");
- else
- fprintf (of, "SI");
+ fprintf (of, "long-");
+ fprintf (of, "int");
break;
case V_CHAR:
- fprintf (of, "SC");
+ fprintf (of, "char");
break;
case V_VOID:
- fprintf (of, "SV");
+ fprintf (of, "void");
break;
case V_FLOAT:
- fprintf (of, "SF");
+ fprintf (of, "float");
break;
case V_STRUCT:
- fprintf (of, "ST%s", SPEC_STRUCT (type)->tag);
+ fprintf (of, "struct %s", SPEC_STRUCT (type)->tag);
break;
case V_SBIT:
- fprintf (of, "SX");
+ fprintf (of, "sbit");
break;
case V_BIT:
- fprintf (of, "SB%d$%d", SPEC_BSTR (type), SPEC_BLEN (type));
+ fprintf (of, "bit");
break;
- default:
+ case V_BITFIELD:
+ fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
break;
- }
- fputs (":", of);
- if (SPEC_USIGN (type))
- fputs ("U", of);
- else
- fputs ("S", of);
- }
- type = type->next;
- }
-}
-/*-----------------------------------------------------------------*/
-/* cdbSymbol - prints a symbol & its type information for debugger */
-/*-----------------------------------------------------------------*/
-void
-cdbSymbol (symbol * sym, FILE * of, int isStructSym, int isFunc)
-{
- memmap *map;
- if (!sym)
- return;
- if (!of)
- of = stdout;
+ case V_DOUBLE:
+ fprintf (of, "double");
+ break;
- if (isFunc)
- fprintf (of, "F:");
- else
- fprintf (of, "S:"); /* symbol record */
- /* if this is not a structure symbol then
- we need to figure out the scope information */
- if (!isStructSym)
- {
- if (!sym->level)
- {
- /* global */
- if (IS_STATIC (sym->etype))
- fprintf (of, "F%s$", moduleName); /* scope is file */
- else
- fprintf (of, "G$"); /* scope is global */
+ default:
+ fprintf (of, "unknown type");
+ break;
+ }
}
else
- /* symbol is local */
- fprintf (of, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
- }
- else
- fprintf (of, "S$"); /* scope is structure */
-
- /* print the name, & mangled name */
- fprintf (of, "%s$%d$%d(", sym->name,
- sym->level, sym->block);
-
- cdbTypeInfo (sym->type, of);
- fprintf (of, "),");
-
- /* print the address space */
- map = SPEC_OCLS (sym->etype);
- fprintf (of, "%c,%d,%d",
- (map ? map->dbName : 'Z'), sym->onStack, SPEC_STAK (sym->etype));
-
- /* if assigned to registers then output register names */
- /* if this is a function then print
- if is it an interrupt routine & interrupt number
- and the register bank it is using */
- if (isFunc)
- fprintf (of, ",%d,%d,%d", SPEC_INTRTN (sym->etype),
- SPEC_INTN (sym->etype), SPEC_BANK (sym->etype));
- /* alternate location to find this symbol @ : eg registers
- or spillication */
-
- if (!isStructSym)
- fprintf (of, "\n");
-}
-
-/*-----------------------------------------------------------------*/
-/* cdbStruct - print a structure for debugger */
-/*-----------------------------------------------------------------*/
-void
-cdbStruct (structdef * sdef, int block, FILE * of,
- int inStruct, char *tag)
-{
- symbol *sym;
-
- fprintf (of, "T:");
- /* if block # then must have function scope */
- fprintf (of, "F%s$", moduleName);
- fprintf (of, "%s[", (tag ? tag : sdef->tag));
- for (sym = sdef->fields; sym; sym = sym->next)
- {
- fprintf (of, "({%d}", sym->offset);
- cdbSymbol (sym, of, TRUE, FALSE);
- fprintf (of, ")");
+ fprintf (of, "NOT_SPEC_OR_DECL");
+ type = type->next;
+ if (type)
+ fputc (' ', of);
}
- fprintf (of, "]");
- if (!inStruct)
+ if (nlr)
fprintf (of, "\n");
}
-/*------------------------------------------------------------------*/
-/* cdbStructBlock - calls struct printing for a blcks */
-/*------------------------------------------------------------------*/
-void
-cdbStructBlock (int block, FILE * of)
-{
- int i;
- bucket **table = StructTab;
- bucket *chain;
- wassert (of);
-
- /* go thru the entire table */
- for (i = 0; i < 256; i++)
- {
- for (chain = table[i]; chain; chain = chain->next)
- {
- if (chain->block >= block)
- {
- cdbStruct ((structdef *) chain->sym, chain->block, of, 0, NULL);
- }
- }
- }
-}
/*-----------------------------------------------------------------*/
/* powof2 - returns power of two for the number if number is pow 2 */
/*-----------------------------------------------------------------*/
-int
-powof2 (unsigned long num)
+int
+powof2 (TYPE_UDWORD num)
{
int nshifts = 0;
int n1s = 0;
sym_link *__multypes[3][2];
/* Dims: to/from float, BYTE/WORD/DWORD, SIGNED/USIGNED */
symbol *__conv[2][3][2];
+/* Dims: shift left/shift right, BYTE/WORD/DWORD, SIGNED/UNSIGNED */
+symbol *__rlrr[2][3][2];
sym_link *floatType;
-static void
-_makeRegParam (symbol * sym)
+static char *
+_mangleFunctionName(char *in)
{
- value *val;
-
- val = sym->args; /* loop thru all the arguments */
-
- /* reset regparm for the port */
- (*port->reset_regparms) ();
- while (val)
+ if (port->getMangledFunctionName)
{
- SPEC_REGPARM (val->etype) = 1;
- val = val->next;
+ return port->getMangledFunctionName(in);
}
+ else
+ {
+ return 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) */
+/* modifiers - 'u' - unsigned */
+/* pointer modifiers - 'g' - generic */
+/* 'x' - xdata */
+/* 'p' - code */
+/* 'd' - data */
+/* 'F' - function */
+/* examples : "ig*" - generic int * */
+/* "cx*" - char xdata * */
+/* "ui" - unsigned int */
+/*-----------------------------------------------------------------*/
+sym_link *typeFromStr (char *s)
+{
+ sym_link *r = newLink(DECLARATOR);
+ 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++;
+ } while (*s);
+ return r;
}
/*-----------------------------------------------------------------*/
{
"s", "u"
};
+ const char *srlrr[] =
+ {
+ "rl", "rr"
+ };
- int bwd, su, muldivmod, tofrom;
+ int bwd, su, muldivmod, tofrom, rlrr;
+
+ if (getenv("SDCC_NO_C_SUPPORT")) {
+ /* for debugging only */
+ return;
+ }
floatType = newFloatLink ();
for (bwd = 0; bwd < 3; bwd++)
{
- sym_link *l;
+ sym_link *l = NULL;
switch (bwd)
{
case 0:
{
if (tofrom)
{
- sprintf (buffer, "__fs2%s%s", ssu[su], sbwd[bwd]);
+ 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
{
- sprintf (buffer, "__%s%s2fs", ssu[su], sbwd[bwd]);
+ 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 (muldivmod = 0; muldivmod < 3; muldivmod++)
{
for (bwd = 0; bwd < 3; bwd++)
{
for (su = 0; su < 2; su++)
{
- sprintf (buffer, "_%s%s%s",
+ SNPRINTF (buffer, sizeof(buffer),
+ "_%s%s%s",
smuldivmod[muldivmod],
ssu[su],
sbwd[bwd]);
- __muldiv[muldivmod][bwd][su] = funcOfType (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
- SPEC_NONBANKED (__muldiv[muldivmod][bwd][su]->etype) = 1;
- if (bwd < port->muldiv.force_reg_param_below)
- _makeRegParam (__muldiv[muldivmod][bwd][su]);
+ __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;
}
}
}
+
+ 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++)
+ {
+ /* muluchar and mulschar are still separate functions, because e.g. the z80
+ port is sign/zero-extending to int before calling mulint() */
+ 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;
+ }
+ /* signed only */
+ su = 0;
+ /* word and doubleword */
+ for (bwd = 1; bwd < 3; bwd++)
+ {
+ /* mul, int/long */
+ SNPRINTF (buffer, sizeof(buffer),
+ "_%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 */
+ __muldiv[muldivmod][bwd][1] = __muldiv[muldivmod][bwd][0];
+ }
+
+ 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]);
+ __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;
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* initBuiltIns - create prototypes for builtin functions */
+/*-----------------------------------------------------------------*/
+void initBuiltIns()
+{
+ int i;
+ symbol *sym;
+
+ 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_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;
+ }
+ 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);
+ return l; // never reached, makes compiler happy.
+}
+
+/*--------------------------------------------------------------------*/
+/* newEnumType - create an integer type compatible with enumerations */
+/*--------------------------------------------------------------------*/
+sym_link *
+newEnumType (symbol *enumlist)
+{
+ int min, max, v;
+ symbol *sym;
+ sym_link *type;
+
+ if (!enumlist)
+ {
+ type = newLink (SPECIFIER);
+ SPEC_NOUN (type) = V_INT;
+ return type;
+ }
+
+ /* Determine the range of the enumerated values */
+ sym = enumlist;
+ min = max = (int) floatFromVal (valFromType (sym->type));
+ for (sym = sym->next; sym; sym = sym->next)
+ {
+ v = (int) floatFromVal (valFromType (sym->type));
+ if (v<min)
+ min = v;
+ if (v>max)
+ 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;
}