#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 */
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) {
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "addSym: %s ", sname);
+ }
+ /* 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 */
{
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
{
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 %x\n", name, (int)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 */
/*------------------------------------------------------------------*/
+#define LAST_MINUTE_2_3_0_FIX
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 */
+
+#ifdef LAST_MINUTE_2_3_0_FIX
+ sym_link *symlink;
+
+ if (!IS_SPEC(dest)) {
+ // This should not happen
+ fprintf (stderr, "*** internal error: can't merge declarators\n");
+ }
+ if (!IS_SPEC(src)) {
+ // here we have a declarator as source, reverse them
+ symlink=src;
+ src=dest;
+ dest=symlink;
+ while (!IS_SPEC(dest)) {
+ // and find the specifier
+ dest=dest->next;
+ }
+ } else {
+ symlink=dest;
+ }
+#endif
+
+ if (getenv("DEBUG_mergeSpec")) {
+ fprintf (stderr, "mergeSpec: \"%s\"\n", name);
+ }
+
+ 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_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);
+#ifdef LAST_MINUTE_2_3_0_FIX
+ return symlink;
+#else
return dest;
+#endif
}
/*------------------------------------------------------------------*/
}
/*------------------------------------------------------------------*/
-/* 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
then check if the type match, if the types match then
if (IS_EXTERN (csym->etype))
{
/* do types match ? */
- if (checkType (csym->type, sym->type) != 1)
+ if (compareType (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);
+ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
}
else /* not extern */
werror (E_DUPLICATE, sym->name);
/* then check the type with the current one */
if (IS_EXTERN (csym->etype))
{
- if (checkType (csym->type, sym->type) <= 0)
+ if (compareType (csym->type, sym->type) <= 0)
werror (W_EXTERN_MISMATCH, csym->name);
}
}
-
- addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
}
}
static void
checkSClass (symbol * sym)
{
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "checkSClass: %s \n", sym->name);
+ }
+ if (strcmp(sym->name, "_testsGlobal")==0) {
+ printf ("oach\n");
+ }
+
/* type is literal can happen foe 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 */
sym->ival = NULL;
}
}
-
+
/* if absolute address given then it mark it as
volatile */
if (IS_ABSOLUTE (sym->etype))
SPEC_VOLATILE (sym->etype) = 1;
-
+
/* global variables declared const put into code */
if (sym->level == 0 &&
- SPEC_SCLS (sym->etype) == S_CONSTANT)
- {
- SPEC_SCLS (sym->etype) = S_CODE;
- SPEC_CONST (sym->etype) = 1;
- }
-
+ SPEC_CONST (sym->etype)) {
+ SPEC_SCLS (sym->etype) = S_CODE;
+ }
+
/* 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;
-
+
/* if bit variable then no storage class can be */
/* specified since bit is already a storage */
sym->ival = NULL;
}
+#if 0
/* if this is an automatic symbol then */
/* storage class will be ignored and */
/* symbol will be allocated on stack/ */
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))
+ SPEC_SCLS (sym->etype) != S_XSTACK))
{
-
werror (E_AUTO_ASSUMED, sym->name);
SPEC_SCLS (sym->etype) = S_AUTO;
}
-
+#else
+ /* if this is an atomatic 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);
+ }
+ }
+ }
+#endif
+
/* automatic symbols cannot be given */
/* an absolute address ignore it */
if (sym->level &&
/* 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)))
{
}
/*------------------------------------------------------------------*/
-/* checkType - will do type check return 1 if match */
+/* compareType - will do type check return 1 if match */
/*------------------------------------------------------------------*/
int
-checkType (sym_link * dest, sym_link * src)
+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);
+ return compareType (dest->next, src->next);
else if (IS_PTR (src) && IS_PTR (dest))
return -1;
else if (IS_PTR (dest) && IS_ARRAY (src))
return -1;
else if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src))
- return -1 * checkType (dest->next, src);
+ return -1 * compareType (dest->next, src);
else
return 0;
}
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;
}
/*------------------------------------------------------------------*/
-/* inCalleeSaveList - return 1 if found in calle save list */
+/* inCalleeSaveList - return 1 if found in callee save list */
/*------------------------------------------------------------------*/
bool
inCalleeSaveList (char *s)
{
symbol *csym;
value *exargs, *acargs;
+ value *checkValue;
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;
}
/* 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 ");
+ werror (E_CONTINUE, "previous definition type ");
printTypeChain (csym->type, stderr);
fprintf (stderr, "\n");
werror (E_CONTINUE, "current definition type ");
if (SPEC_INTRTN (csym->etype) != SPEC_INTRTN (sym->etype))
{
werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt");
- return 0;
}
if (SPEC_BANK (csym->etype) != SPEC_BANK (sym->etype))
{
werror (E_PREV_DEF_CONFLICT, csym->name, "using");
- return 0;
+ }
+
+ if (SPEC_NAKED (csym->etype) != SPEC_NAKED (sym->etype))
+ {
+ werror (E_PREV_DEF_CONFLICT, csym->name, "_naked");
}
/* compare expected agrs with actual args */
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.
checkValue = acargs;
}
- if (checkType (exargs->type, checkValue->type) <= 0)
+ if (compareType (exargs->type, checkValue->type) <= 0)
{
werror (E_ARG_TYPE, argCnt);
return 0;
/* replace with this defition */
sym->cdef = csym->cdef;
deleteSym (SymbolTab, csym, csym->name);
- addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
if (IS_EXTERN (csym->etype) && !
IS_EXTERN (sym->etype))
{
{
/* 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 &&
- !IS_RENT (func->etype) &&
(*port->reg_parm) (val->type))
{
SPEC_REGPARM (val->etype) = 1;
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;
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;
}
}
{
"s", "u"
};
+ const char *srlrr[] =
+ {
+ "rl", "rr"
+ };
- int bwd, su, muldivmod, tofrom;
+ int bwd, su, muldivmod, tofrom, rlrr;
floatType = newFloatLink ();
if (tofrom)
{
sprintf (buffer, "__fs2%s%s", ssu[su], sbwd[bwd]);
- __conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], floatType, 1, options.float_rent);
+ __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], floatType, 1, options.float_rent);
}
else
{
sprintf (buffer, "__%s%s2fs", ssu[su], sbwd[bwd]);
- __conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent);
+ __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), floatType, __multypes[bwd][su], 1, options.float_rent);
}
}
}
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 (_mangleFunctionName(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]);
+ }
+ }
+ }
+
+ for (rlrr = 0; rlrr < 2; rlrr++)
+ {
+ for (bwd = 0; bwd < 3; bwd++)
+ {
+ for (su = 0; su < 2; su++)
+ {
+ sprintf (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);
+ SPEC_NONBANKED (__rlrr[rlrr][bwd][su]->etype) = 1;
}
}
}