#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 '");
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";
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 */
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:
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
DCL_TYPE (type) = port->unqualified_pointer;
type = type->next;
}
-
}
/*------------------------------------------------------------------*/
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;
}
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;
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;
/* one definition extern ? */
if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype)) {
/* do types match ? */
- if (compareType (csym->type, sym->type) != 1) {
+ //checkDecl (sym, IS_EXTERN (sym->etype));
+ if (compareTypeExact (csym->type, sym->type, sym->level) != 1) {
/* no then error */
werror (E_EXTERN_MISMATCH, csym->name);
+ printFromToType (csym->type, sym->type);
continue;
}
} else {
/* not extern */
- if (compareType (csym->type, sym->type) != 1) {
+ //checkDecl (sym, 0);
+ if (compareTypeExact (csym->type, sym->type, sym->level) != 1) {
werror (E_DUPLICATE, sym->name);
+ printFromToType (csym->type, sym->type);
continue;
}
}
}
/*------------------------------------------------------------------*/
-/* 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)
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;
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;
SPEC_BLEN (loop->etype) = loop->bitVar;
static void
checkSClass (symbol * sym, int isProto)
{
+ sym_link *t;
+
if (getenv("DEBUG_SANITY")) {
fprintf (stderr, "checkSClass: %s \n", sym->name);
}
- /* type is literal can happen foe enums change
+ /* 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 (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_CONST (sym->etype) &&
SPEC_SCLS(sym->etype) == S_FIXED &&
!IS_FUNC(sym->type)) {
- SPEC_SCLS (sym->etype) = S_CODE;
+ /* 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;
+ }
}
/* global variable in code space is a constant */
if (sym->level == 0 &&
SPEC_SCLS (sym->etype) == S_CODE &&
port->mem.code_ro) {
- if (IS_SPEC(sym->type)) {
- SPEC_CONST (sym->type) = 1;
+ /* 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 (sym->type) = 1;
+ DCL_PTR_CONST (t) = 1;
}
}
sym->ival = NULL;
}
- /* if this is an atomatic symbol */
+ /* 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 ||
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);
rType = copyLinkChain (type2);
reType = getSpec (rType);
+#if 0
+ if (SPEC_NOUN (reType) == V_CHAR)
+ SPEC_NOUN (reType) = V_INT;
+#endif
/* if either of them unsigned but not val then make this unsigned */
- if (((/*!IS_LITERAL(type1) &&*/ SPEC_USIGN (etype1)) ||
- (/*!IS_LITERAL(type2) &&*/ SPEC_USIGN (etype2))) &&
+ if ((SPEC_USIGN (etype1) || SPEC_USIGN (etype2)) &&
!IS_FLOAT (reType))
SPEC_USIGN (reType) = 1;
else
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))
+ return compareTypeExact (dest->next, src->next, -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;
+
+ 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 0
+ if (srcScls != destScls)
+ {
+ 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);
+ return 0;
+ }
+ #endif
+
+ return 1;
+}
+
/*------------------------------------------------------------------*/
/* inCalleeSaveList - return 1 if found in callee save list */
/*------------------------------------------------------------------*/
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);
werror(E_PARAM_NAME_OMITTED, sym->name, argCnt);
}
}
+ argCnt--;
if (!csym && !(csym = findSym (SymbolTab, sym, sym->name)))
return 1; /* not defined nothing more to check */
{
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);
printTypeChain (sym_link * start, FILE * of)
{
int nlr = 0;
+ value *args;
sym_link * type, * search;
STORAGE_CLASS scls;
for (type = start; type && type->next; type = type->next)
;
- scls=SPEC_SCLS(type);
+ if (IS_SPEC (type))
+ scls=SPEC_SCLS(type);
+ else
+ scls=0;
while (type)
{
if (type==start) {
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* ");
fprintf (of, "pdata* ");
break;
case UPOINTER:
- fprintf (of, "unkown* ");
+ fprintf (of, "unknown* ");
break;
case ARRAY:
if (DCL_ELEM(type)) {
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, "\n");
}
+/*--------------------------------------------------------------------*/
+/* printTypeChainRaw - prints the type chain in human readable form */
+/* in the raw data structure ordering */
+/*--------------------------------------------------------------------*/
+void
+printTypeChainRaw (sym_link * start, FILE * of)
+{
+ 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, "function %s %s",
+ (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "),
+ (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " "));
+ fprintf (of, "( ");
+ for (args = FUNC_ARGS(type);
+ args;
+ args=args->next) {
+ printTypeChain(args->type, of);
+ if (args->next)
+ fprintf(of, ", ");
+ }
+ fprintf (of, ") ");
+ break;
+ case GPOINTER:
+ fprintf (of, "generic* ");
+ break;
+ case CPOINTER:
+ fprintf (of, "code* ");
+ break;
+ case FPOINTER:
+ fprintf (of, "xdata* ");
+ break;
+ case EEPPOINTER:
+ fprintf (of, "eeprom* ");
+ break;
+ case POINTER:
+ fprintf (of, "near* ");
+ break;
+ case IPOINTER:
+ fprintf (of, "idata* ");
+ break;
+ case PPOINTER:
+ fprintf (of, "pdata* ");
+ break;
+ case UPOINTER:
+ fprintf (of, "unknown* ");
+ break;
+ case ARRAY:
+ if (DCL_ELEM(type)) {
+ fprintf (of, "[%d] ", DCL_ELEM(type));
+ } else {
+ fprintf (of, "[] ");
+ }
+ break;
+ }
+ if (DCL_TSPEC(type))
+ {
+ fprintf (of, "{");
+ printTypeChainRaw(DCL_TSPEC(type), of);
+ fprintf (of, "}");
+ }
+ }
+ else if (IS_SPEC (type))
+ {
+ switch (SPEC_SCLS (type))
+ {
+ case S_DATA: fprintf (of, "data-"); break;
+ case S_XDATA: fprintf (of, "xdata-"); break;
+ case S_SFR: fprintf (of, "sfr-"); break;
+ case S_SBIT: fprintf (of, "sbit-"); break;
+ case S_CODE: fprintf (of, "code-"); break;
+ case S_IDATA: fprintf (of, "idata-"); break;
+ case S_PDATA: fprintf (of, "pdata-"); break;
+ case S_LITERAL: fprintf (of, "literal-"); break;
+ case S_STACK: fprintf (of, "stack-"); break;
+ case S_XSTACK: fprintf (of, "xstack-"); break;
+ case S_BIT: fprintf (of, "bit-"); break;
+ case S_EEPROM: fprintf (of, "eeprom-"); break;
+ default: break;
+ }
+ if (SPEC_VOLATILE (type))
+ fprintf (of, "volatile-");
+ if (SPEC_CONST (type))
+ fprintf (of, "const-");
+ if (SPEC_USIGN (type))
+ fprintf (of, "unsigned-");
+ switch (SPEC_NOUN (type))
+ {
+ case V_INT:
+ if (IS_LONG (type))
+ fprintf (of, "long-");
+ fprintf (of, "int");
+ break;
+
+ case V_CHAR:
+ fprintf (of, "char");
+ break;
+
+ case V_VOID:
+ fprintf (of, "void");
+ break;
+
+ case V_FLOAT:
+ fprintf (of, "float");
+ break;
+
+ case V_STRUCT:
+ fprintf (of, "struct %s", SPEC_STRUCT (type)->tag);
+ break;
+
+ case V_SBIT:
+ fprintf (of, "sbit");
+ break;
+
+ case V_BIT:
+ fprintf (of, "bit");
+ break;
+
+ case V_BITFIELD:
+ fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
+ break;
+
+ case V_DOUBLE:
+ fprintf (of, "double");
+ break;
+
+ default:
+ fprintf (of, "unknown type");
+ break;
+ }
+ }
+ else
+ fprintf (of, "NOT_SPEC_OR_DECL");
+ type = type->next;
+ if (type)
+ fputc (' ', of);
+ }
+ if (nlr)
+ fprintf (of, "\n");
+}
+
/*-----------------------------------------------------------------*/
/* powof2 - returns power of two for the number if number is pow 2 */