#include "common.h"
#include "newalloc.h"
+/* noun strings */
+char *nounName(sym_link *sl) {
+ switch (SPEC_NOUN(sl))
+ {
+ case V_INT: {
+ if (SPEC_LONG(sl)) return "long";
+ if (sl->select.s._short) return "short";
+ return "int";
+ }
+ case V_FLOAT: return "float";
+ case V_CHAR: return "char";
+ case V_VOID: return "void";
+ case V_STRUCT: return "struct";
+ case V_LABEL: return "label";
+ case V_BIT: return "bit";
+ case V_SBIT: return "sbit";
+ case V_DOUBLE: return "double";
+ }
+ return "unknown";
+};
+
bucket *SymbolTab[256]; /* the symbol table */
bucket *StructTab[256]; /* the structure table */
bucket *TypedefTab[256]; /* the typedef table */
int i; /* index into the hash Table */
bucket *bp; /* temp bucket * */
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "addSym: %s ", sname);
+ }
+ /* Make sure sym is a symbol and not a structdef */
+ if (StructTab!=stab) {
+ /* make sure the type is complete and sane */
+ checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
+ }
+
/* the symbols are always added at the head of the list */
i = hashKey (sname);
/* get a free entry */
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\n", name);
+ }
+
+ 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.shortisint ? V_INT : V_CHAR;
+ 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)
{
- /* 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 (src)))
- SPEC_SCLS (dest) = SPEC_SCLS (src);
- /* special case for const */
+
+ 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, yylval.yychar);
+ }
+ }
+
+ 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, yylval.yychar);
+ }
+ }
+
/* copy all the specifications */
+
+ // we really should do:
+#if 0
+ if (SPEC_what(src)) {
+ if (SPEC_what(dest)) {
+ werror(W_DUPLICATE_SPEC, "what");
+ }
+ SPEC_what(dst)|=SPEC_what(src);
+ }
+#endif
+ // but there are more important thing right now
+
SPEC_LONG (dest) |= SPEC_LONG (src);
- SPEC_SHORT (dest) |= SPEC_SHORT (src);
+ dest->select.s._short|=src->select.s._short;
SPEC_USIGN (dest) |= SPEC_USIGN (src);
+ dest->select.s._signed|=src->select.s._signed;
SPEC_STAT (dest) |= SPEC_STAT (src);
SPEC_EXTR (dest) |= SPEC_EXTR (src);
SPEC_ABSA (dest) |= SPEC_ABSA (src);
SPEC_BSTR (dest) |= SPEC_BSTR (src);
SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
SPEC_NONBANKED (dest) |= SPEC_NONBANKED (src);
+ SPEC_NAKED (dest) |= SPEC_NAKED (src);
if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
SPEC_STRUCT (dest) = SPEC_STRUCT (src);
}
/*------------------------------------------------------------------*/
-/* newCharLink() - creates an int type */
+/* newCharLink() - creates an char type */
/*------------------------------------------------------------------*/
sym_link *
newCharLink ()
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:
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:
symbol *sym = symHead;
symbol *csym = NULL;
+
for (; sym != NULL; sym = sym->next)
{
+ changePointer(sym);
/* if already exists in the symbol table then check if
the previous was an extern definition if yes then
werror (W_EXTERN_MISMATCH, csym->name);
}
}
-
addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
}
}
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 */
- sprintf (loop->rname, "_%s", loop->name);
- loop->offset = (su == UNION ? sum = 0 : sum);
- SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0);
-
- /* if this is a bit field */
- if (loop->bitVar)
- {
-
- /* change it to a unsigned bit */
- SPEC_NOUN (loop->etype) = V_BIT;
- 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++;
+ 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 */
+ sprintf (loop->rname, "_%s", loop->name);
+ loop->offset = (su == UNION ? sum = 0 : sum);
+ SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0);
+
+ /* if this is a bit field */
+ if (loop->bitVar) {
+
+ /* change it to a unsigned bit */
+ SPEC_NOUN (loop->etype) = V_BIT;
+ 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++;
}
- else
- /* does not fit */
- {
- bitOffset = 0;
- SPEC_BSTR (loop->etype) = bitOffset;
- sum += (loop->bitVar / 8);
- bitOffset += (loop->bitVar % 8);
+ 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++;
+ /* if this is the last field then pad */
+ if (!loop->next && bitOffset && bitOffset != 8) {
+ bitOffset = 0;
+ sum++;
}
}
- else
- {
- checkDecl (loop);
- sum += getSize (loop->type);
+ else {
+ checkDecl (loop);
+ sum += getSize (loop->type);
}
- /* if function then do the arguments for it */
- if (funcInChain (loop->type))
- {
- processFuncArgs (loop, 1);
+ /* if function then do the arguments for it */
+ if (funcInChain (loop->type)) {
+ processFuncArgs (loop, 1);
}
- loop = loop->next;
+ 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 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)
- usum = max (usum, sum);
+ /* if union then size = sizeof larget field */
+ if (su == UNION)
+ usum = max (usum, sum);
}
- return (su == UNION ? usum : sum);
+ return (su == UNION ? usum : sum);
}
/*------------------------------------------------------------------*/
SPEC_SCLS (sym->etype) != S_XSTACK &&
SPEC_SCLS (sym->etype) != S_CONSTANT))
{
-
werror (E_AUTO_ASSUMED, sym->name);
SPEC_SCLS (sym->etype) = S_AUTO;
}
/* 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)))
{
* control this allcoation, but the code was originally that way, and
* changing it for non-390 ports breaks the compiler badly.
*/
- bool useXdata = IS_DS390_PORT ? options.model : options.useXstack;
+ bool useXdata = TARGET_IS_DS390 ? 1 : options.useXstack;
SPEC_SCLS (sym->etype) = (useXdata ?
S_XDATA : S_FIXED);
}
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))
- return -1;
-
if (SPEC_USIGN (dest) != SPEC_USIGN (src))
return -2;
DCL_TYPE (val->type) = PPOINTER;
break;
case S_FIXED:
- if (IS_DS390_PORT)
+ if (TARGET_IS_DS390)
{
/* The AUTO and REGISTER classes should probably
* also become generic pointers, but I haven't yet
value *exargs, *acargs;
int argCnt = 0;
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "checkFunction: %s ", sym->name);
+ }
+
+ /* make sure the type is complete and sane */
+ checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
+
/* if not type then some kind of error */
if (!sym->type)
return 0;
if (checkType (csym->type, sym->type) <= 0)
{
werror (E_PREV_DEF_CONFLICT, csym->name, "type");
- werror (E_CONTINUE, "previous defintion type ");
+ werror (E_CONTINUE, "previous definition type ");
printTypeChain (csym->type, stderr);
fprintf (stderr, "\n");
werror (E_CONTINUE, "current definition type ");
value *val;
int pNum = 1;
-
/* if this function has variable argument list */
/* then make the function a reentrant one */
if (func->hasVargs)
{
/* mark it as a register parameter if
the function does not have VA_ARG
- and as port dictates
- not inhibited by command line option or #pragma */
+ and as port dictates */
if (!func->hasVargs &&
- !options.noregparms &&
- !IS_RENT (func->etype) &&
(*port->reg_parm) (val->type))
{
SPEC_REGPARM (val->etype) = 1;
pNum++;
}
- /* if this function is reentrant or */
- /* automatics r 2b stacked then nothing */
- if (IS_RENT (func->etype) || options.stackAuto)
- return;
+ /* if this is an internal generated function call */
+ 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)) {
+ return;
+ }
+ } else {
+ /* if this function is reentrant or */
+ /* automatics r 2b stacked then nothing */
+ if (IS_RENT (func->etype) || options.stackAuto)
+ return;
+ }
val = func->args;
pNum = 1;
{
if (IS_DECL (type))
{
+ if (DCL_PTR_VOLATILE(type)) {
+ fprintf (of, "volatile ");
+ }
switch (DCL_TYPE (type))
{
case FUNCTION:
if (DCL_PTR_CONST (type))
fprintf (of, "const ");
break;
-
case ARRAY:
fprintf (of, "array of ");
break;
case V_INT:
if (IS_LONG (type))
fprintf (of, "long ");
- else if (IS_SHORT (type))
- fprintf (of, "short ");
- else
- fprintf (of, "int ");
+ fprintf (of, "int ");
break;
case V_CHAR:
fprintf (of, "bit {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
break;
+ case V_DOUBLE:
+ fprintf (of, "double ");
+ break;
+
default:
+ fprintf (of, "unknown type ");
break;
}
}
case V_INT:
if (IS_LONG (type))
fprintf (of, "SL");
- else if (IS_SHORT (type))
- fprintf (of, "SS");
else
fprintf (of, "SI");
break;
while (val)
{
SPEC_REGPARM (val->etype) = 1;
- sym->argStack -= getSize (val->type);
val = val->next;
}
}
smuldivmod[muldivmod],
ssu[su],
sbwd[bwd]);
- __muldiv[muldivmod][bwd][su] = funcOfType (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
+ __muldiv[muldivmod][bwd][su] = funcOfType (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]);