mirror of
https://github.com/cc65/cc65.git
synced 2025-02-07 04:31:38 +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:
parent
9f67b45ea0
commit
b45d373fd6
@ -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 */
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user