1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

Fixed passing by value structs/unions <= 4 bytes in size to functions. Larger ones are forbidden for now.

This commit is contained in:
acqn 2020-07-18 23:30:09 +08:00 committed by Oliver Schmidt
parent 9f67b45ea0
commit b45d373fd6
2 changed files with 34 additions and 8 deletions

View File

@ -395,12 +395,18 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
}
/* Handle struct/union specially */
if (IsTypeStruct (Expr.Type) || IsTypeUnion (Expr.Type)) {
/* Use the replacement type */
Flags |= TypeOf (GetReplacementType (Expr.Type));
} else {
/* Use the type of the argument for the push */
Flags |= TypeOf (Expr.Type);
}
/* Load the value into the primary if it is not already there */
LoadExpr (Flags, &Expr);
/* Use the type of the argument for the push */
Flags |= TypeOf (Expr.Type);
/* If this is a fastcall function, don't push the last argument */
if ((CurTok.Tok == TOK_COMMA && NextTok.Tok != TOK_RPAREN) || !IsFastcall) {
unsigned ArgSize = sizeofarg (Flags);
@ -651,8 +657,8 @@ static void FunctionCall (ExprDesc* Expr)
ED_FinalizeRValLoad (Expr);
ReturnType = GetFuncReturn (Expr->Type);
/* Handle struct specially */
if (IsTypeStruct (ReturnType)) {
/* Handle struct/union specially */
if (IsTypeStruct (ReturnType) || IsTypeUnion (ReturnType)) {
/* If there is no replacement type, then it is just the address */
if (ReturnType == GetReplacementType (ReturnType)) {
/* Dereference it */

View File

@ -380,6 +380,7 @@ void NewFunc (SymEntry* Func)
{
int C99MainFunc = 0;/* Flag for C99 main function returning int */
SymEntry* Param;
const Type* RType; /* Real type used for struct parameters */
/* Get the function descriptor from the function entry */
FuncDesc* D = Func->V.F.Func;
@ -475,7 +476,12 @@ void NewFunc (SymEntry* Func)
/* Pointer to function */
Flags = CF_PTR;
} else {
Flags = TypeOf (D->LastParam->Type) | CF_FORCECHAR;
/* Handle struct/union specially */
if (IsTypeStruct (D->LastParam->Type) || IsTypeUnion (D->LastParam->Type)) {
Flags = TypeOf (GetReplacementType (D->LastParam->Type)) | CF_FORCECHAR;
} else {
Flags = TypeOf (D->LastParam->Type) | CF_FORCECHAR;
}
}
g_push (Flags, 0);
}
@ -498,11 +504,25 @@ void NewFunc (SymEntry* Func)
Param = D->SymTab->SymHead;
while (Param && (Param->Flags & SC_PARAM) != 0) {
/* Check if we need copy for struct/union type */
RType = Param->Type;
if (IsTypeStruct (RType) || IsTypeUnion (RType)) {
RType = GetReplacementType (RType);
/* If there is no replacement type, then it is just the address.
** We don't currently support this case.
*/
if (RType == Param->Type) {
Error ("Passing %s of this size by value is not supported", GetBasicTypeName (Param->Type));
}
}
/* Check for a register variable */
if (SymIsRegVar (Param)) {
/* Allocate space */
int Reg = F_AllocRegVar (CurrentFunc, Param->Type);
int Reg = F_AllocRegVar (CurrentFunc, RType);
/* Could we allocate a register? */
if (Reg < 0) {
@ -513,7 +533,7 @@ void NewFunc (SymEntry* Func)
Param->V.R.RegOffs = Reg;
/* Generate swap code */
g_swap_regvars (Param->V.R.SaveOffs, Reg, CheckedSizeOf (Param->Type));
g_swap_regvars (Param->V.R.SaveOffs, Reg, CheckedSizeOf (RType));
}
}