#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 (SPEC_SHORT(sl)) 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 (1 || 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) &&
+ (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) &&
+ (SPEC_SIGNED(etype) || SPEC_USIGN(etype))) {
+ // signed or unsigned for float double or void
+ werror (E_SIGNED_OR_UNSIGNED_INVALID, noun, name);
+ }
+
+ if (!SPEC_NOUN(etype)) {
+ // special case for just "signed" or "unsigned" or "long"
+ if (SPEC_SIGNED(etype) || SPEC_USIGN(etype) || SPEC_LONG(etype)) {
+ SPEC_NOUN(etype)=V_INT;
+ }
+ // special case for just "short"
+ if (SPEC_SHORT(etype)) {
+ SPEC_NOUN(etype)=V_CHAR; // or maybe V_INT
+ SPEC_SHORT(etype)=0;
+ }
+ }
+
+ // if still no noun (e.g. "const a;" or "data b;") assume an int
+ if (!SPEC_NOUN(etype)) {
+ SPEC_NOUN(etype)=V_INT;
+ }
+
+ if (SPEC_SIGNED(etype) && SPEC_USIGN(etype)) {
+ // signed AND unsigned
+ werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name);
+ }
+ if (SPEC_SHORT(etype) && 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(dest) == S_REGISTER) &&
- 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);
SPEC_USIGN (dest) |= SPEC_USIGN (src);
+ SPEC_SIGNED (dest) |= SPEC_SIGNED (src);
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 ()
symbol *sym = symHead;
symbol *csym = NULL;
+
for (; sym != NULL; sym = sym->next)
{
changePointer(sym);
+
/* if already exists in the symbol table then check if
the previous was an extern definition if yes then
then check if the type match, if the types match then
werror (W_EXTERN_MISMATCH, csym->name);
}
}
-
addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
}
}
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)))
{
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;
case V_INT:
if (IS_LONG (type))
fprintf (of, "long ");
- else if (IS_SHORT (type))
+ 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;
}
}
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]);