#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;
}
/*------------------------------------------------------------------*/
-/* 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;
/* create the internal name for this variable */
SNPRINTF (loop->rname, sizeof(loop->rname), "_%s", loop->name);
- loop->offset = (su == UNION ? sum = 0 : sum);
+ 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 {
+ /* 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);
}
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);
}
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
SPEC_USIGN (reType) = 0;
-
+
/* if result is a literal then make not so */
if (IS_LITERAL (reType))
SPEC_SCLS (reType) = S_REGISTER;
/*--------------------------------------------------------------------*/
/* compareType - will do type check return 1 if match, -1 if castable */
/*--------------------------------------------------------------------*/
-int
+int
compareType (sym_link * dest, sym_link * src)
{
if (!dest && !src)
/*------------------------------------------------------------------*/
/* inCalleeSaveList - return 1 if found in callee save list */
/*------------------------------------------------------------------*/
-bool
-inCalleeSaveList (char *s)
+static int
+calleeCmp(void *p1, void *p2)
{
- int i;
-
- if (options.all_callee_saves) return 1;
- 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);
}
/*-----------------------------------------------------------------*/
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 */
}
}
+/*
for (muldivmod = 0; muldivmod < 3; muldivmod++)
{
for (bwd = 0; bwd < 3; bwd++)
{
for (su = 0; su < 2; su++)
{
- SNPRINTF (buffer, sizeof(buffer),
+ SNPRINTF (buffer, sizeof(buffer),
"_%s%s%s",
smuldivmod[muldivmod],
ssu[su],
}
}
+ 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),
+ SNPRINTF (buffer, sizeof(buffer),
"_%s%s%s",
srlrr[rlrr],
ssu[su],