mirror of
https://github.com/cc65/cc65.git
synced 2024-12-28 22:30:12 +00:00
Inline parameter frame building
git-svn-id: svn://svn.cc65.org/cc65/trunk@661 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
59bcc726b6
commit
c18453ebcb
@ -652,63 +652,63 @@ void g_getimmed (unsigned flags, unsigned long val, unsigned offs)
|
||||
{
|
||||
if ((flags & CF_CONST) != 0) {
|
||||
|
||||
/* Numeric constant */
|
||||
switch (flags & CF_TYPE) {
|
||||
/* Numeric constant */
|
||||
switch (flags & CF_TYPE) {
|
||||
|
||||
case CF_CHAR:
|
||||
if ((flags & CF_FORCECHAR) != 0) {
|
||||
ldaconst (val);
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case CF_INT:
|
||||
ldxconst ((val >> 8) & 0xFF);
|
||||
ldaconst (val & 0xFF);
|
||||
break;
|
||||
case CF_CHAR:
|
||||
if ((flags & CF_FORCECHAR) != 0) {
|
||||
ldaconst (val);
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case CF_INT:
|
||||
ldxconst ((val >> 8) & 0xFF);
|
||||
ldaconst (val & 0xFF);
|
||||
break;
|
||||
|
||||
case CF_LONG:
|
||||
if (val < 0x100) {
|
||||
AddCodeLine ("\tldx\t#$00");
|
||||
AddCodeLine ("\tstx\tsreg+1");
|
||||
AddCodeLine ("\tstx\tsreg");
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
|
||||
} else if ((val & 0xFFFF00FF) == 0) {
|
||||
AddCodeLine ("\tlda\t#$00");
|
||||
AddCodeLine ("\tsta\tsreg+1");
|
||||
AddCodeLine ("\tsta\tsreg");
|
||||
AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
|
||||
} else if ((val & 0xFFFF0000) == 0 && FavourSize == 0) {
|
||||
AddCodeLine ("\tlda\t#$00");
|
||||
AddCodeLine ("\tsta\tsreg+1");
|
||||
AddCodeLine ("\tsta\tsreg");
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
|
||||
AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
|
||||
} else if ((val & 0xFFFFFF00) == 0xFFFFFF00) {
|
||||
AddCodeLine ("\tldx\t#$FF");
|
||||
AddCodeLine ("\tstx\tsreg+1");
|
||||
AddCodeLine ("\tstx\tsreg");
|
||||
if ((val & 0xFF) == 0xFF) {
|
||||
AddCodeLine ("\ttxa");
|
||||
} else {
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
|
||||
}
|
||||
} else if ((val & 0xFFFF00FF) == 0xFFFF00FF) {
|
||||
AddCodeLine ("\tlda\t#$FF");
|
||||
AddCodeLine ("\tsta\tsreg+1");
|
||||
AddCodeLine ("\tsta\tsreg");
|
||||
AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
|
||||
} else {
|
||||
/* Call a subroutine that will load following value */
|
||||
AddCodeLine ("\tjsr\tldeax");
|
||||
AddCodeLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF);
|
||||
}
|
||||
break;
|
||||
case CF_LONG:
|
||||
if (val < 0x100) {
|
||||
AddCodeLine ("\tldx\t#$00");
|
||||
AddCodeLine ("\tstx\tsreg+1");
|
||||
AddCodeLine ("\tstx\tsreg");
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
|
||||
} else if ((val & 0xFFFF00FF) == 0) {
|
||||
AddCodeLine ("\tlda\t#$00");
|
||||
AddCodeLine ("\tsta\tsreg+1");
|
||||
AddCodeLine ("\tsta\tsreg");
|
||||
AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
|
||||
} else if ((val & 0xFFFF0000) == 0 && FavourSize == 0) {
|
||||
AddCodeLine ("\tlda\t#$00");
|
||||
AddCodeLine ("\tsta\tsreg+1");
|
||||
AddCodeLine ("\tsta\tsreg");
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
|
||||
AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
|
||||
} else if ((val & 0xFFFFFF00) == 0xFFFFFF00) {
|
||||
AddCodeLine ("\tldx\t#$FF");
|
||||
AddCodeLine ("\tstx\tsreg+1");
|
||||
AddCodeLine ("\tstx\tsreg");
|
||||
if ((val & 0xFF) == 0xFF) {
|
||||
AddCodeLine ("\ttxa");
|
||||
} else {
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
|
||||
}
|
||||
} else if ((val & 0xFFFF00FF) == 0xFFFF00FF) {
|
||||
AddCodeLine ("\tlda\t#$FF");
|
||||
AddCodeLine ("\tsta\tsreg+1");
|
||||
AddCodeLine ("\tsta\tsreg");
|
||||
AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
|
||||
} else {
|
||||
/* Call a subroutine that will load following value */
|
||||
AddCodeLine ("\tjsr\tldeax");
|
||||
AddCodeLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
typeerror (flags);
|
||||
break;
|
||||
default:
|
||||
typeerror (flags);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@ -1084,34 +1084,79 @@ void g_putstatic (unsigned flags, unsigned long label, unsigned offs)
|
||||
|
||||
|
||||
|
||||
void g_putlocal (unsigned flags, int offs)
|
||||
void g_putlocal (unsigned Flags, int Offs, long Val)
|
||||
/* Put data into local object. */
|
||||
{
|
||||
offs -= oursp;
|
||||
CheckLocalOffs (offs);
|
||||
switch (flags & CF_TYPE) {
|
||||
Offs -= oursp;
|
||||
CheckLocalOffs (Offs);
|
||||
switch (Flags & CF_TYPE) {
|
||||
|
||||
case CF_CHAR:
|
||||
if (CPU == CPU_65C02 && offs == 0) {
|
||||
AddCodeLine ("\tsta\t(sp)");
|
||||
} else {
|
||||
ldyconst (offs);
|
||||
AddCodeLine ("\tsta\t(sp),y");
|
||||
if (Flags & CF_CONST) {
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) Val);
|
||||
}
|
||||
break;
|
||||
|
||||
case CF_INT:
|
||||
if (offs) {
|
||||
ldyconst (offs);
|
||||
AddCodeLine ("\tjsr\tstaxysp");
|
||||
if (CPU == CPU_65C02 && Offs == 0) {
|
||||
AddCodeLine ("\tsta\t(sp)");
|
||||
} else {
|
||||
AddCodeLine ("\tjsr\tstax0sp");
|
||||
ldyconst (Offs);
|
||||
AddCodeLine ("\tsta\t(sp),y");
|
||||
}
|
||||
break;
|
||||
|
||||
case CF_INT:
|
||||
if (Flags & CF_CONST) {
|
||||
ldyconst (Offs+1);
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) (Val >> 8));
|
||||
AddCodeLine ("\tsta\t(sp),y");
|
||||
if ((Flags & CF_NOKEEP) == 0) {
|
||||
/* Place high byte into X */
|
||||
AddCodeLine ("\ttax");
|
||||
}
|
||||
if (CPU == CPU_65C02 && Offs == 0) {
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) Val);
|
||||
AddCodeLine ("\tsta\t(sp)");
|
||||
} else {
|
||||
if ((Val & 0xFF) == Offs+1) {
|
||||
/* The value we need is already in Y */
|
||||
AddCodeLine ("\ttya");
|
||||
AddCodeLine ("\tdey");
|
||||
} else {
|
||||
AddCodeLine ("\tdey");
|
||||
AddCodeLine ("\tlda\t#$%02X", (unsigned char) Val);
|
||||
}
|
||||
AddCodeLine ("\tsta\t(sp),y");
|
||||
}
|
||||
} else {
|
||||
if ((Flags & CF_NOKEEP) == 0 || FavourSize) {
|
||||
if (Offs) {
|
||||
ldyconst (Offs);
|
||||
AddCodeLine ("\tjsr\tstaxysp");
|
||||
} else {
|
||||
AddCodeLine ("\tjsr\tstax0sp");
|
||||
}
|
||||
} else {
|
||||
if (CPU == CPU_65C02 && Offs == 0) {
|
||||
AddCodeLine ("\tsta\t(sp)");
|
||||
ldyconst (1);
|
||||
AddCodeLine ("\ttxa");
|
||||
AddCodeLine ("\tsta\t(sp),y");
|
||||
} else {
|
||||
ldyconst (Offs);
|
||||
AddCodeLine ("\tsta\t(sp),y");
|
||||
AddCodeLine ("\tiny");
|
||||
AddCodeLine ("\ttxa");
|
||||
AddCodeLine ("\tsta\t(sp),y");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CF_LONG:
|
||||
if (offs) {
|
||||
ldyconst (offs);
|
||||
if (Flags & CF_CONST) {
|
||||
g_getimmed (Flags, Val, 0);
|
||||
}
|
||||
if (Offs) {
|
||||
ldyconst (Offs);
|
||||
AddCodeLine ("\tjsr\tsteaxysp");
|
||||
} else {
|
||||
AddCodeLine ("\tjsr\tsteax0sp");
|
||||
@ -1119,7 +1164,7 @@ void g_putlocal (unsigned flags, int offs)
|
||||
break;
|
||||
|
||||
default:
|
||||
typeerror (flags);
|
||||
typeerror (Flags);
|
||||
|
||||
}
|
||||
}
|
||||
@ -2461,44 +2506,44 @@ void g_swap (unsigned flags)
|
||||
|
||||
|
||||
|
||||
void g_call (unsigned flags, char* lbl, unsigned argsize)
|
||||
void g_call (unsigned Flags, const char* Label, unsigned ArgSize)
|
||||
/* Call the specified subroutine name */
|
||||
{
|
||||
if ((flags & CF_FIXARGC) == 0) {
|
||||
/* Pass arg count */
|
||||
ldyconst (argsize);
|
||||
if ((Flags & CF_FIXARGC) == 0) {
|
||||
/* Pass the argument count */
|
||||
ldyconst (ArgSize);
|
||||
}
|
||||
AddCodeLine ("\tjsr\t_%s", lbl);
|
||||
oursp += argsize; /* callee pops args */
|
||||
AddCodeLine ("\tjsr\t_%s", Label);
|
||||
oursp += ArgSize; /* callee pops args */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void g_callind (unsigned flags, unsigned argsize)
|
||||
void g_callind (unsigned Flags, unsigned ArgSize)
|
||||
/* Call subroutine with address in AX */
|
||||
{
|
||||
if ((flags & CF_FIXARGC) == 0) {
|
||||
if ((Flags & CF_FIXARGC) == 0) {
|
||||
/* Pass arg count */
|
||||
ldyconst (argsize);
|
||||
ldyconst (ArgSize);
|
||||
}
|
||||
AddCodeLine ("\tjsr\tcallax"); /* do the call */
|
||||
oursp += argsize; /* callee pops args */
|
||||
oursp += ArgSize; /* callee pops args */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void g_jump (unsigned label)
|
||||
void g_jump (unsigned Label)
|
||||
/* Jump to specified internal label number */
|
||||
{
|
||||
AddCodeLine ("\tjmp\tL%04X", label);
|
||||
AddCodeLine ("\tjmp\tL%04X", Label);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void g_switch (unsigned flags)
|
||||
/* Output switch statement preample */
|
||||
void g_switch (unsigned Flags)
|
||||
/* Output switch statement preamble */
|
||||
{
|
||||
switch (flags & CF_TYPE) {
|
||||
switch (Flags & CF_TYPE) {
|
||||
|
||||
case CF_CHAR:
|
||||
case CF_INT:
|
||||
@ -2510,7 +2555,7 @@ void g_switch (unsigned flags)
|
||||
break;
|
||||
|
||||
default:
|
||||
typeerror (flags);
|
||||
typeerror (Flags);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -50,12 +50,14 @@
|
||||
*/
|
||||
#define CF_NONE 0x0000 /* No special flags */
|
||||
|
||||
#define CF_TYPE 0x000F /* Mask for operand type */
|
||||
#define CF_TYPE 0x0007 /* Mask for operand type */
|
||||
#define CF_CHAR 0x0003 /* Operation on characters */
|
||||
#define CF_INT 0x0001 /* Operation on ints */
|
||||
#define CF_PTR CF_INT /* Alias for readability */
|
||||
#define CF_LONG 0x0000 /* Operation on longs */
|
||||
|
||||
#define CF_NOKEEP 0x0008 /* Value may get destroyed when storing */
|
||||
|
||||
#define CF_UNSIGNED 0x0010 /* Value is unsigned */
|
||||
#define CF_CONST 0x0020 /* Constant value available */
|
||||
#define CF_CONSTADDR 0x0040 /* Constant address value available */
|
||||
@ -273,7 +275,7 @@ void g_leavariadic (int Offs);
|
||||
void g_putstatic (unsigned flags, unsigned long label, unsigned offs);
|
||||
/* Store the primary register into the specified static memory cell */
|
||||
|
||||
void g_putlocal (unsigned flags, int offs);
|
||||
void g_putlocal (unsigned Flags, int Offs, long Val);
|
||||
/* Put data into local object. */
|
||||
|
||||
void g_putind (unsigned flags, unsigned offs);
|
||||
@ -370,10 +372,18 @@ void g_cmp (unsigned flags, unsigned long val);
|
||||
void g_test (unsigned flags);
|
||||
void g_push (unsigned flags, unsigned long val);
|
||||
void g_swap (unsigned flags);
|
||||
void g_call (unsigned flags, char *lbl, unsigned argsize);
|
||||
void g_callind (unsigned flags, unsigned argsize);
|
||||
void g_jump (unsigned label);
|
||||
void g_switch (unsigned flags);
|
||||
|
||||
void g_call (unsigned Flags, const char* Label, unsigned ArgSize);
|
||||
/* Call the specified subroutine name */
|
||||
|
||||
void g_callind (unsigned Flags, unsigned ArgSize);
|
||||
/* Call subroutine with address in AX */
|
||||
|
||||
void g_jump (unsigned Label);
|
||||
/* Jump to specified internal label number */
|
||||
|
||||
void g_switch (unsigned Flags);
|
||||
/* Output switch statement preamble */
|
||||
|
||||
void g_case (unsigned flags, unsigned label, unsigned long val);
|
||||
/* Create table code for one case selector */
|
||||
|
@ -173,7 +173,7 @@ type* GetImplicitFuncType (void)
|
||||
type* T = TypeAlloc (1 + DECODE_SIZE + 2);
|
||||
|
||||
/* Prepare the function descriptor */
|
||||
F->Flags = FD_IMPLICIT | FD_EMPTY | FD_ELLIPSIS;
|
||||
F->Flags = FD_IMPLICIT | FD_EMPTY | FD_VARIADIC;
|
||||
F->SymTab = &EmptySymTab;
|
||||
F->TagTab = &EmptySymTab;
|
||||
|
||||
@ -476,7 +476,7 @@ unsigned TypeOf (const type* T)
|
||||
|
||||
case T_FUNC:
|
||||
F = (FuncDesc*) DecodePtr (T+1);
|
||||
return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC;
|
||||
return (F->Flags & FD_VARIADIC)? 0 : CF_FIXARGC;
|
||||
|
||||
case T_STRUCT:
|
||||
case T_UNION:
|
||||
@ -654,7 +654,7 @@ int IsVariadicFunc (const type* T)
|
||||
FuncDesc* F;
|
||||
CHECK (IsTypeFunc (T));
|
||||
F = (FuncDesc*) DecodePtr (T+1);
|
||||
return (F->Flags & FD_ELLIPSIS) != 0;
|
||||
return (F->Flags & FD_VARIADIC) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -626,7 +626,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||
/* Allow an ellipsis as last parameter */
|
||||
if (curtok == TOK_ELLIPSIS) {
|
||||
NextToken ();
|
||||
F->Flags |= FD_ELLIPSIS;
|
||||
F->Flags |= FD_VARIADIC;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -708,14 +708,14 @@ static FuncDesc* ParseFuncDecl (void)
|
||||
/* Check for several special parameter lists */
|
||||
if (curtok == TOK_RPAREN) {
|
||||
/* Parameter list is empty */
|
||||
F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
|
||||
F->Flags |= (FD_EMPTY | FD_VARIADIC);
|
||||
} else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
|
||||
/* Parameter list declared as void */
|
||||
NextToken ();
|
||||
F->Flags |= FD_VOID_PARAM;
|
||||
} else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
|
||||
/* Old style (K&R) function. Assume variable param list. */
|
||||
F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
|
||||
F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
|
||||
}
|
||||
|
||||
/* Parse params */
|
||||
@ -730,7 +730,7 @@ static FuncDesc* ParseFuncDecl (void)
|
||||
/* Assign offsets. If the function has a variable parameter list,
|
||||
* there's one additional byte (the arg size).
|
||||
*/
|
||||
Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
|
||||
Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
|
||||
Sym = GetSymTab()->SymTail;
|
||||
while (Sym) {
|
||||
unsigned Size = SizeOf (Sym->Type);
|
||||
|
166
src/cc65/expr.c
166
src/cc65/expr.c
@ -510,54 +510,70 @@ void exprhs (unsigned flags, int k, struct expent *lval)
|
||||
}
|
||||
|
||||
|
||||
static void callfunction (struct expent* lval)
|
||||
/* Perform a function call. Called from hie11, this routine will
|
||||
* either call the named function, or if the supplied ptr is zero,
|
||||
* will call the contents of P.
|
||||
|
||||
static unsigned FunctionParamList (FuncDesc* Func)
|
||||
/* Parse a function parameter list and pass the parameters to the called
|
||||
* function. Depending on several criteria this may be done by just pushing
|
||||
* each parameter separately, or creating the parameter frame once and then
|
||||
* storing into this frame.
|
||||
* The function returns the size of the parameters pushed.
|
||||
*/
|
||||
{
|
||||
struct expent lval2;
|
||||
FuncDesc* Func; /* Function descriptor */
|
||||
int Ellipsis; /* True if we have an open param list */
|
||||
SymEntry* Param; /* Current formal parameter */
|
||||
unsigned ParamCount; /* Actual parameter count */
|
||||
unsigned ParamSize; /* Number of parameter bytes */
|
||||
unsigned Flags;
|
||||
unsigned CFlags;
|
||||
CodeMark Mark;
|
||||
struct expent lval;
|
||||
|
||||
/* Initialize variables */
|
||||
SymEntry* Param = 0; /* Keep gcc silent */
|
||||
unsigned ParamSize = 0; /* Size of parameters pushed */
|
||||
unsigned ParamCount = 0; /* Number of parameters pushed */
|
||||
unsigned FrameSize = 0; /* Size of parameter frame */
|
||||
unsigned FrameParams = 0; /* Number of params in frame */
|
||||
int FrameOffs = 0; /* Offset into parameter frame */
|
||||
int Ellipsis = 0; /* Function is variadic */
|
||||
|
||||
/* Get a pointer to the function descriptor from the type string */
|
||||
Func = GetFuncDesc (lval->e_tptr);
|
||||
|
||||
/* Initialize vars to keep gcc silent */
|
||||
Param = 0;
|
||||
Mark = 0;
|
||||
|
||||
/* Check if this is a function pointer. If so, save it. If not, check for
|
||||
* special known library functions that may be inlined.
|
||||
/* As an optimization, we may allocate the complete parameter frame at
|
||||
* once instead of pushing each parameter as it comes. We may do that,
|
||||
* if...
|
||||
*
|
||||
* - optimizations that increase code size are enabled (allocating the
|
||||
* stack frame at once gives usually larger code).
|
||||
* - we have more than one parameter to push (don't count the last param
|
||||
* for __fastcall__ functions).
|
||||
*/
|
||||
if (lval->e_flags & E_MEXPR) {
|
||||
/* Function pointer is in primary register, save it */
|
||||
Mark = GetCodePos ();
|
||||
g_save (CF_PTR);
|
||||
} else if (InlineStdFuncs && IsStdFunc ((const char*) lval->e_name)) {
|
||||
/* Inline this function */
|
||||
HandleStdFunc (lval);
|
||||
return;
|
||||
if (Optimize && !FavourSize) {
|
||||
|
||||
/* Calculate the number and size of the parameters */
|
||||
FrameParams = Func->ParamCount;
|
||||
FrameSize = Func->ParamSize;
|
||||
if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) {
|
||||
/* Last parameter is not pushed */
|
||||
const SymEntry* LastParam = Func->SymTab->SymTail;
|
||||
FrameSize -= SizeOf (LastParam->Type);
|
||||
--FrameParams;
|
||||
}
|
||||
|
||||
/* Do we have more than one parameter in the frame? */
|
||||
if (FrameParams > 1) {
|
||||
/* Okeydokey, setup the frame */
|
||||
FrameOffs = oursp;
|
||||
g_space (FrameSize);
|
||||
oursp -= FrameSize;
|
||||
} else {
|
||||
/* Don't use a preallocated frame */
|
||||
FrameSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the actual parameter list */
|
||||
ParamSize = 0;
|
||||
ParamCount = 0;
|
||||
Ellipsis = 0;
|
||||
while (curtok != TOK_RPAREN) {
|
||||
|
||||
unsigned CFlags;
|
||||
unsigned Flags;
|
||||
|
||||
/* Add a hint for the optimizer */
|
||||
AddCodeHint ("param:start");
|
||||
|
||||
/* Count arguments */
|
||||
++ParamCount;
|
||||
/* Count arguments */
|
||||
++ParamCount;
|
||||
|
||||
/* Fetch the pointer to the next argument, check for too many args */
|
||||
if (ParamCount <= Func->ParamCount) {
|
||||
@ -579,7 +595,7 @@ static void callfunction (struct expent* lval)
|
||||
}
|
||||
} else if (!Ellipsis) {
|
||||
/* Too many arguments. Do we have an open param list? */
|
||||
if ((Func->Flags & FD_ELLIPSIS) == 0) {
|
||||
if ((Func->Flags & FD_VARIADIC) == 0) {
|
||||
/* End of param list reached, no ellipsis */
|
||||
Error ("Too many arguments in function call");
|
||||
}
|
||||
@ -596,8 +612,8 @@ static void callfunction (struct expent* lval)
|
||||
if (!Ellipsis && SizeOf (Param->Type) == 1) {
|
||||
CFlags = CF_FORCECHAR;
|
||||
}
|
||||
Flags = 0;
|
||||
if (evalexpr (CFlags, hie1, &lval2) == 0) {
|
||||
Flags = CF_NONE;
|
||||
if (evalexpr (CFlags, hie1, &lval) == 0) {
|
||||
/* A constant value */
|
||||
Flags |= CF_CONST;
|
||||
}
|
||||
@ -607,14 +623,14 @@ static void callfunction (struct expent* lval)
|
||||
*/
|
||||
if (!Ellipsis) {
|
||||
/* Promote the argument if needed */
|
||||
assignadjust (Param->Type, &lval2);
|
||||
assignadjust (Param->Type, &lval);
|
||||
|
||||
/* If we have a prototype, chars may be pushed as chars */
|
||||
Flags |= CF_FORCECHAR;
|
||||
}
|
||||
|
||||
/* Use the type of the argument for the push */
|
||||
Flags |= TypeOf (lval2.e_tptr);
|
||||
Flags |= TypeOf (lval.e_tptr);
|
||||
|
||||
/* If this is a fastcall function, don't push the last argument */
|
||||
if (ParamCount == Func->ParamCount && (Func->Flags & FD_FASTCALL) != 0) {
|
||||
@ -623,12 +639,24 @@ static void callfunction (struct expent* lval)
|
||||
* the primary.
|
||||
*/
|
||||
if (Flags & CF_CONST) {
|
||||
exprhs (CF_FORCECHAR, 0, &lval2);
|
||||
exprhs (CF_FORCECHAR, 0, &lval);
|
||||
}
|
||||
} else {
|
||||
/* Push the argument, count the argument size */
|
||||
g_push (Flags, lval2.e_const);
|
||||
ParamSize += sizeofarg (Flags);
|
||||
unsigned ArgSize = sizeofarg (Flags);
|
||||
if (FrameSize > 0) {
|
||||
/* We have the space already allocated, store in the frame */
|
||||
CHECK (FrameSize >= ArgSize);
|
||||
FrameSize -= ArgSize;
|
||||
FrameOffs -= ArgSize;
|
||||
/* Store */
|
||||
g_putlocal (Flags | CF_NOKEEP, FrameOffs, lval.e_const);
|
||||
} else {
|
||||
/* Push the argument */
|
||||
g_push (Flags, lval.e_const);
|
||||
}
|
||||
|
||||
/* Calculate total parameter size */
|
||||
ParamSize += ArgSize;
|
||||
}
|
||||
|
||||
/* Add an optimizer hint */
|
||||
@ -641,14 +669,52 @@ static void callfunction (struct expent* lval)
|
||||
NextToken ();
|
||||
}
|
||||
|
||||
/* We need the closing bracket here */
|
||||
ConsumeRParen ();
|
||||
|
||||
/* Check if we had enough parameters */
|
||||
if (ParamCount < Func->ParamCount) {
|
||||
Error ("Too few arguments in function call");
|
||||
}
|
||||
|
||||
/* Return the size of all parameters pushed onto the stack */
|
||||
return ParamSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CallFunction (struct expent* lval)
|
||||
/* Perform a function call. Called from hie11, this routine will
|
||||
* either call the named function, or the function pointer in a/x.
|
||||
*/
|
||||
{
|
||||
FuncDesc* Func; /* Function descriptor */
|
||||
unsigned ParamSize; /* Number of parameter bytes */
|
||||
CodeMark Mark;
|
||||
|
||||
|
||||
/* Get a pointer to the function descriptor from the type string */
|
||||
Func = GetFuncDesc (lval->e_tptr);
|
||||
|
||||
/* Initialize vars to keep gcc silent */
|
||||
Mark = 0;
|
||||
|
||||
/* Check if this is a function pointer. If so, save it. If not, check for
|
||||
* special known library functions that may be inlined.
|
||||
*/
|
||||
if (lval->e_flags & E_MEXPR) {
|
||||
/* Function pointer is in primary register, save it */
|
||||
Mark = GetCodePos ();
|
||||
g_save (CF_PTR);
|
||||
} else if (InlineStdFuncs && IsStdFunc ((const char*) lval->e_name)) {
|
||||
/* Inline this function */
|
||||
HandleStdFunc (lval);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse the parameter list */
|
||||
ParamSize = FunctionParamList (Func);
|
||||
|
||||
/* We need the closing bracket here */
|
||||
ConsumeRParen ();
|
||||
|
||||
/* */
|
||||
if (lval->e_flags & E_MEXPR) {
|
||||
/* Function called via pointer: Restore it and call function */
|
||||
@ -660,7 +726,7 @@ static void callfunction (struct expent* lval)
|
||||
}
|
||||
g_callind (TypeOf (lval->e_tptr), ParamSize);
|
||||
} else {
|
||||
g_call (TypeOf (lval->e_tptr), (char*) lval->e_name, ParamSize);
|
||||
g_call (TypeOf (lval->e_tptr), (const char*) lval->e_name, ParamSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,7 +1271,7 @@ static int hie11 (struct expent *lval)
|
||||
++lval->e_tptr; /* Skip T_PTR */
|
||||
lval->e_flags |= E_MEXPR;
|
||||
}
|
||||
callfunction (lval);
|
||||
CallFunction (lval);
|
||||
lval->e_flags = E_MEXPR;
|
||||
lval->e_tptr += DECODE_SIZE + 1; /* Set to result */
|
||||
} else {
|
||||
@ -1255,7 +1321,7 @@ static void store (struct expent* lval)
|
||||
g_putstatic (flags, lval->e_name, lval->e_const);
|
||||
|
||||
} else if (f & E_MLOCAL) {
|
||||
g_putlocal (flags, lval->e_const);
|
||||
g_putlocal (flags, lval->e_const, 0);
|
||||
} else if (f == E_MEOFFS) {
|
||||
g_putind (flags, lval->e_const);
|
||||
} else if (f != E_MREG) {
|
||||
|
@ -48,7 +48,7 @@
|
||||
#define FD_IMPLICIT 0x0001U /* Implicitly declared function */
|
||||
#define FD_EMPTY 0x0002U /* Function with empty param list */
|
||||
#define FD_VOID_PARAM 0x0004U /* Function with a void param list */
|
||||
#define FD_ELLIPSIS 0x0008U /* Function with variable param list */
|
||||
#define FD_VARIADIC 0x0008U /* Function with variable param list */
|
||||
#define FD_FASTCALL 0x0010U /* __fastcall__ function */
|
||||
#define FD_OLDSTYLE 0x0020U /* Old style (K&R) function */
|
||||
#define FD_UNNAMED_PARAMS 0x0040U /* Function has unnamed params */
|
||||
|
@ -151,7 +151,7 @@ int HasVoidReturn (const Function* F)
|
||||
int IsVariadic (const Function* F)
|
||||
/* Return true if this is a variadic function */
|
||||
{
|
||||
return (F->Desc->Flags & FD_ELLIPSIS) != 0;
|
||||
return (F->Desc->Flags & FD_VARIADIC) != 0;
|
||||
}
|
||||
|
||||
|
||||
@ -231,8 +231,8 @@ void NewFunc (SymEntry* Func)
|
||||
* The latter is different depending on the type of the function (variadic
|
||||
* or not).
|
||||
*/
|
||||
AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize);
|
||||
if (D->Flags & FD_ELLIPSIS) {
|
||||
AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize);
|
||||
if (D->Flags & FD_VARIADIC) {
|
||||
/* Variadic function. The variable must be const. */
|
||||
static const type T [] = { T_UCHAR | T_QUAL_CONST, T_END };
|
||||
AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0);
|
||||
@ -263,8 +263,8 @@ void NewFunc (SymEntry* Func)
|
||||
unsigned Flags;
|
||||
|
||||
/* Fastcall functions may never have an ellipsis or the compiler is buggy */
|
||||
CHECK ((D->Flags & FD_ELLIPSIS) == 0);
|
||||
|
||||
CHECK ((D->Flags & FD_VARIADIC) == 0);
|
||||
|
||||
/* Get a pointer to the last parameter entry */
|
||||
LastParam = D->SymTab->SymTail;
|
||||
|
||||
|
@ -589,7 +589,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
|
||||
}
|
||||
} else if (!Ellipsis) {
|
||||
/* Too many arguments. Do we have an open param list? */
|
||||
if ((Func->Flags & FD_ELLIPSIS) == 0) {
|
||||
if ((Func->Flags & FD_VARIADIC) == 0) {
|
||||
/* End of param list reached, no ellipsis */
|
||||
Error ("Too many function arguments");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user