/* 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 &&
- !IS_STATIC(sym->etype))
+ if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED
+ && !IS_STATIC(sym->etype)
+ )
{
if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type)))
{
else
{
/* hack-o-matic! I see no reason why the useXstack option should ever
- * control this allcoation, but the code was originally that way, and
+ * control this allocation, but the code was originally that way, and
* changing it for non-390 ports breaks the compiler badly.
*/
bool useXdata = (TARGET_IS_DS390 || TARGET_IS_DS400) ?
return 0;
}
-/*-------------------------------------------------------------------*/
-/* copyStruct - makes a copy of the struct chain & rets ptr 2 struct */
-/*-------------------------------------------------------------------*/
-structdef *
-copyStruct (structdef * src)
-{
- structdef *dst = (void *) NULL;
-
- if (src)
- {
- dst = newStruct(src->tag);
- memcpy(dst, src, sizeof(structdef)); /* copy it */
- dst->fields = copySymbolChain(src->fields);
- }
- return dst;
-}
-
/*------------------------------------------------------------------*/
/* copyLinkChain - makes a copy of the link chain & rets ptr 2 head */
/*------------------------------------------------------------------*/
while (curr)
{
memcpy (loop, curr, sizeof (sym_link)); /* copy it */
- if ((curr == p) && IS_STRUCT(curr) && SPEC_STRUCT(curr)->type == STRUCT)
- {
- /* if this is a struct specifier which ends */
- /* with an array of unspecified length then */
- /* copy the struct and it's fields */
- struct symbol *field = SPEC_STRUCT(curr)->fields;
- while (field && field->next)
- field = field->next; /* find last one */
- if (field && IS_ARRAY(field->type) && !DCL_ELEM(field->type))
- SPEC_STRUCT(loop) = copyStruct(SPEC_STRUCT(curr));
- }
loop->next = (curr->next ? newLink (curr->next->class) : (void *) NULL);
loop = loop->next;
curr = curr->next;
if (IS_PTR (dest) && IS_GENPTR (src) && IS_VOID(src->next)) {
return -1;
}
- if (IS_PTR (src) && IS_GENPTR (dest))
+ if (IS_PTR (src) &&
+ (IS_GENPTR (dest) ||
+ ((DCL_TYPE(src) == POINTER) && (DCL_TYPE(dest) == IPOINTER))
+ ))
return -1;
if (IS_PTR (dest) && IS_ARRAY (src)) {
value *val=aggregateToPointer (valFromType(src));
}
}
+ if (IFFUNC_ISSHADOWREGS(sym->type) && !FUNC_ISISR (sym->type))
+ {
+ werror (E_SHADOWREGS_NO_ISR, sym->name);
+ }
+
+
for (argCnt=1, acargs = FUNC_ARGS(sym->type);
acargs;
acargs=acargs->next, argCnt++) {
werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt");
}
- if (FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type))
+ /* I don't think this is necessary for interrupts. An isr is a */
+ /* root in the calling tree. */
+ if ((FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type)) &&
+ (!FUNC_ISISR (sym->type)))
{
werror (E_PREV_DEF_CONFLICT, csym->name, "using");
}
{
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 */
werror (E_PREV_DEF_CONFLICT, csym->name, "reentrant");
}
+ if (IFFUNC_ISWPARAM (csym->type) != IFFUNC_ISWPARAM (sym->type))
+ {
+ werror (E_PREV_DEF_CONFLICT, csym->name, "wparam");
+ }
+
+ if (IFFUNC_ISSHADOWREGS (csym->type) != IFFUNC_ISSHADOWREGS (sym->type))
+ {
+ werror (E_PREV_DEF_CONFLICT, csym->name, "shadowregs");
+ }
+
+
/* compare expected args with actual args */
exargs = FUNC_ARGS(csym->type);
acargs = FUNC_ARGS(sym->type);
/* reset regparm for the port */
(*port->reset_regparms) ();
+
/* if any of the arguments is an aggregate */
/* change it to pointer to the same type */
while (val)
{
- int argreg = 0;
+ int argreg = 0;
+ char buffer[SDCC_NAME_MAX+1];
+
+ SNPRINTF (buffer, sizeof(buffer), "%s parameter %d", func->name, pNum);
+ checkTypeSanity (val->etype, buffer);
+
/* mark it as a register parameter if
the function does not have VA_ARG
and as port dictates */
SNPRINTF (val->name, sizeof(val->name),
"_%s_PARM_%d", func->name, pNum++);
val->sym = newSymbol (val->name, 1);
- SPEC_OCLS (val->etype) = port->mem.default_local_map;
+ if (SPEC_SCLS(val->etype) == S_BIT)
+ SPEC_OCLS (val->etype) = bit;
+ else
+ SPEC_OCLS (val->etype) = port->mem.default_local_map;
val->sym->type = copyLinkChain (val->type);
val->sym->etype = getSpec (val->sym->type);
val->sym->_isparm = 1;
SNPRINTF (val->name, sizeof(val->name), "_%s_PARM_%d", func->name, pNum++);
strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname));
val->sym->_isparm = 1;
- SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
- (options.model != MODEL_SMALL ? xdata : data);
+ if (SPEC_SCLS(val->etype) == S_BIT)
+ SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = bit;
+ else
+ SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
+ (options.model != MODEL_SMALL ? xdata : data);
#if 0
/* ?? static functions shouldn't imply static parameters - EEP */