Merge pull request #1439 from acqn/CConvFix

[cc65] Issue #1438 fix
This commit is contained in:
Oliver Schmidt
2021-03-27 01:33:07 +01:00
committed by GitHub
5 changed files with 36 additions and 25 deletions

View File

@@ -493,17 +493,14 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
** registers. ** registers.
*/ */
*Use = REG_EAXY; *Use = REG_EAXY;
} else if ((D->ParamCount > 0 || } else if ((D->ParamCount > 0 || (D->Flags & FD_EMPTY) != 0) &&
(D->Flags & FD_EMPTY) != 0) && IsFastcallFunc (E->Type)) {
(AutoCDecl ?
IsQualFastcall (E->Type) :
!IsQualCDecl (E->Type))) {
/* Will use registers depending on the last param. If the last /* Will use registers depending on the last param. If the last
** param has incomplete type, or if the function has not been ** param has incomplete type, or if the function has not been
** prototyped yet, just assume __EAX__. ** prototyped yet, just assume __EAX__.
*/ */
if (D->LastParam != 0) { if (D->LastParam != 0) {
switch (SizeOf(D->LastParam->Type)) { switch (SizeOf (D->LastParam->Type)) {
case 1u: case 1u:
*Use = REG_A; *Use = REG_A;
break; break;

View File

@@ -1085,11 +1085,26 @@ int HasUnknownSize (const Type* T)
int IsVariadicFunc (const Type* T) int IsVariadicFunc (const Type* T)
/* Return true if this is a function type or pointer to function type with /* Return true if this is a function type or pointer to function type with
** variable parameter list ** variable parameter list.
** Check fails if the type is not a function or a pointer to function.
*/ */
{ {
FuncDesc* F = GetFuncDesc (T); return (GetFuncDesc (T)->Flags & FD_VARIADIC) != 0;
return (F->Flags & FD_VARIADIC) != 0; }
int IsFastcallFunc (const Type* T)
/* Return true if this is a function type or pointer to function type by
** __fastcall__ calling convention.
** Check fails if the type is not a function or a pointer to function.
*/
{
if (UnqualifiedType (T->C) == T_PTR) {
/* Pointer to function */
++T;
}
return !IsVariadicFunc (T) && (AutoCDecl ? IsQualFastcall (T) : !IsQualCDecl (T));
} }

View File

@@ -825,7 +825,14 @@ INLINE int IsQualCConv (const Type* T)
int IsVariadicFunc (const Type* T) attribute ((const)); int IsVariadicFunc (const Type* T) attribute ((const));
/* Return true if this is a function type or pointer to function type with /* Return true if this is a function type or pointer to function type with
** variable parameter list ** variable parameter list.
** Check fails if the type is not a function or a pointer to function.
*/
int IsFastcallFunc (const Type* T) attribute ((const));
/* Return true if this is a function type or pointer to function type by
** __fastcall__ calling convention.
** Check fails if the type is not a function or a pointer to function.
*/ */
FuncDesc* GetFuncDesc (const Type* T) attribute ((const)); FuncDesc* GetFuncDesc (const Type* T) attribute ((const));

View File

@@ -835,7 +835,7 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall, ExprDesc* ED)
/* Append last deferred inc/dec before the function is called. /* Append last deferred inc/dec before the function is called.
** The last parameter needs to be preserved if it is passed in AX/EAX Regs. ** The last parameter needs to be preserved if it is passed in AX/EAX Regs.
*/ */
DoDeferred (IsFastcall ? SQP_KEEP_EAX : SQP_KEEP_NONE, &Expr); DoDeferred (IsFastcall && PushedCount > 0 ? SQP_KEEP_EAX : SQP_KEEP_NONE, &Expr);
/* Check if we had enough arguments */ /* Check if we had enough arguments */
if (PushedCount < Func->ParamCount) { if (PushedCount < Func->ParamCount) {
@@ -863,7 +863,7 @@ static void FunctionCall (ExprDesc* Expr)
unsigned ParamSize; /* Number of parameter bytes */ unsigned ParamSize; /* Number of parameter bytes */
CodeMark Mark; CodeMark Mark;
int PtrOffs = 0; /* Offset of function pointer on stack */ int PtrOffs = 0; /* Offset of function pointer on stack */
int IsFastcall = 0; /* True if it's a fast-call function */ int IsFastcall = 0; /* True if we are fast-calling the function */
int PtrOnStack = 0; /* True if a pointer copy is on stack */ int PtrOnStack = 0; /* True if a pointer copy is on stack */
Type* ReturnType; Type* ReturnType;
@@ -882,11 +882,8 @@ static void FunctionCall (ExprDesc* Expr)
** parameter count is zero. Handle K & R functions as though there are ** parameter count is zero. Handle K & R functions as though there are
** parameters. ** parameters.
*/ */
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && IsFastcall = (Func->ParamCount > 0 || (Func->Flags & FD_EMPTY) != 0) &&
(Func->ParamCount > 0 || (Func->Flags & FD_EMPTY)) && IsFastcallFunc (Expr->Type + 1);
(AutoCDecl ?
IsQualFastcall (Expr->Type + 1) :
!IsQualCDecl (Expr->Type + 1));
/* Things may be difficult, depending on where the function pointer /* Things may be difficult, depending on where the function pointer
** resides. If the function pointer is an expression of some sort ** resides. If the function pointer is an expression of some sort
@@ -931,10 +928,8 @@ static void FunctionCall (ExprDesc* Expr)
} }
/* If we didn't inline the function, get fastcall info */ /* If we didn't inline the function, get fastcall info */
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && IsFastcall = (Func->ParamCount > 0 || (Func->Flags & FD_EMPTY) != 0) &&
(AutoCDecl ? IsFastcallFunc (Expr->Type);
IsQualFastcall (Expr->Type) :
!IsQualCDecl (Expr->Type));
} }
/* Parse the parameter list */ /* Parse the parameter list */

View File

@@ -558,10 +558,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
PushLiteralPool (Func); PushLiteralPool (Func);
/* If this is a fastcall function, push the last parameter onto the stack */ /* If this is a fastcall function, push the last parameter onto the stack */
if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 && if (D->ParamCount > 0 && IsFastcallFunc (Func->Type)) {
(AutoCDecl ?
IsQualFastcall (Func->Type) :
!IsQualCDecl (Func->Type))) {
unsigned Flags; unsigned Flags;
/* Generate the push */ /* Generate the push */