+2004-02-06 Erik Petrich <epetrich AT ivorytower.norman.ok.us>
+
+ * src/SDCCast.c (decorateType),
+ * src/SDCCicode.c (geniCodeParms, geniCodeCall): fixed bugs in my ANSI
+ function pointer implementation
+ * support/regression/tests/funptrs.c: added tests to verify both forms
+ of function pointers work correctly. Added tests to verify parameters
+ are passed in the correct order.
+
2004-02-06 Vangelis Rokas <vrokas AT otenet.gr>
* device.c (regCompare): registers are sorted by ascending
werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
goto errorTreeReturn;
}
-
- parmNumber = 1;
-
- if (processParms (tree->left,
- IS_CODEPTR(LTYPE(tree)) ?
- FUNC_ARGS(tree->left->ftype->next)
- : FUNC_ARGS(tree->left->ftype),
- tree->right, &parmNumber, TRUE)) {
- goto errorTreeReturn;
- }
- if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) &&
- !IFFUNC_ISBUILTIN(LTYPE(tree)))
- {
- reverseParms (tree->right);
- }
+ {
+ sym_link *functype;
+ parmNumber = 1;
- if (IS_CODEPTR(LTYPE(tree))) {
- TTYPE(tree) = LTYPE(tree)->next->next;
- } else {
- TTYPE(tree) = LTYPE(tree)->next;
+ if (IS_CODEPTR(LTYPE(tree)))
+ functype = LTYPE (tree)->next;
+ else
+ functype = LTYPE (tree);
+
+ if (processParms (tree->left, FUNC_ARGS(functype),
+ tree->right, &parmNumber, TRUE)) {
+ goto errorTreeReturn;
+ }
+
+ if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
+ !IFFUNC_ISBUILTIN(functype))
+ {
+ reverseParms (tree->right);
+ }
+
+ TTYPE (tree) = functype->next;
+ TETYPE (tree) = getSpec (TTYPE (tree));
}
- TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
/*------------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
value *
geniCodeParms (ast * parms, value *argVals, int *stack,
- sym_link * fetype, symbol * func,int lvl)
+ sym_link * ftype, int lvl)
{
iCode *ic;
operand *pval;
if (argVals==NULL) {
// first argument
- if (IS_CODEPTR(func->type))
- argVals = FUNC_ARGS (func->type->next);
- else
- argVals = FUNC_ARGS (func->type);
+ argVals = FUNC_ARGS (ftype);
}
/* if this is a param node then do the left & right */
if (parms->type == EX_OP && parms->opval.op == PARAM)
{
- argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
- argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
+ argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
+ argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
return argVals;
}
}
/* if register parm then make it a send */
- if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
- IFFUNC_ISBUILTIN(func->type))
+ if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
+ IFFUNC_ISBUILTIN(ftype))
{
ic = newiCode (SEND, pval, NULL);
ic->argreg = SPEC_ARGREG(parms->etype);
- ic->builtinSEND = FUNC_ISBUILTIN(func->type);
+ ic->builtinSEND = FUNC_ISBUILTIN(ftype);
ADDTOCHAIN (ic);
}
else
{
/* now decide whether to push or assign */
- if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
+ if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
{
/* assign */
iCode *ic;
operand *result;
sym_link *type, *etype;
+ sym_link *ftype;
int stack = 0;
if (!IS_FUNC(OP_SYMBOL(left)->type) &&
of overlaying function parameters */
geniCodeSEParms (parms,lvl);
+ ftype = operandType (left);
+ if (IS_CODEPTR (ftype))
+ ftype = ftype->next;
+
/* first the parameters */
- geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
+ geniCodeParms (parms, NULL, &stack, ftype, lvl);
/* now call : if symbol then pcall */
if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
ic = newiCode (CALL, left, NULL);
}
- type = copyLinkChain (operandType (left)->next);
+ type = copyLinkChain (ftype->next);
etype = getSpec (type);
SPEC_EXTR (etype) = 0;
IC_RESULT (ic) = result = newiTempOperand (type, 1);
*/
typedef void (*NOARGFUNPTR)(void);
typedef void (*ONEARGFUNPTR)({type}) REENTRANT;
+typedef long int (*FOURARGFUNPTR)(char, char, long int, long int) REENTRANT;
int count;
+FOURARGFUNPTR fafp;
void
incCount(void)
count += a;
}
+long int f6(char a, char b, long int c, long int d) REENTRANT
+{
+ switch (a)
+ {
+ case 0: return a;
+ case 1: return b;
+ case 2: return c;
+ case 3: return d;
+ }
+ return 0;
+}
+
+
void
callViaPtr(NOARGFUNPTR fptr)
{
(*fptr)();
}
+void
+callViaPtrAnsi(NOARGFUNPTR fptr)
+{
+ fptr();
+}
+
+void
+callViaPtr2Ansi(ONEARGFUNPTR fptr, {type} arg)
+{
+ fptr(arg);
+}
+
+void
+callViaPtr3Ansi(void (*fptr)(void))
+{
+ fptr();
+}
+
+
+
void
testFunPtr(void)
{
+ fafp = f6;
+
ASSERT(count == 0);
callViaPtr(incCount);
ASSERT(count == 1);
callViaPtr2(incBy, 7);
ASSERT(count == 8);
+
+ ASSERT((*fafp)(0, 0x55, 0x12345678, 0x9abcdef0) == 0);
+ ASSERT((*fafp)(1, 0x55, 0x12345678, 0x9abcdef0) == 0x55);
+ ASSERT((*fafp)(2, 0x55, 0x12345678, 0x9abcdef0) == 0x12345678);
+ ASSERT((*fafp)(3, 0x55, 0x12345678, 0x9abcdef0) == 0x9abcdef0);
+}
+
+void
+testFunPtrAnsi(void)
+{
+ fafp = f6;
+
+ count = 0;
+ callViaPtrAnsi(incCount);
+ ASSERT(count == 1);
+ callViaPtr2Ansi(incBy, 7);
+ ASSERT(count == 8);
+
+ ASSERT(fafp(0, 0x55, 0x12345678, 0x9abcdef0) == 0);
+ ASSERT(fafp(1, 0x55, 0x12345678, 0x9abcdef0) == 0x55);
+ ASSERT(fafp(2, 0x55, 0x12345678, 0x9abcdef0) == 0x12345678);
+ ASSERT(fafp(3, 0x55, 0x12345678, 0x9abcdef0) == 0x9abcdef0);
}
+