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 */
|
/* Load the value into the primary if it is not already there */
|
||||||
LoadExpr (Flags, &Expr);
|
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 this is a fastcall function, don't push the last argument */
|
||||||
if ((CurTok.Tok == TOK_COMMA && NextTok.Tok != TOK_RPAREN) || !IsFastcall) {
|
if ((CurTok.Tok == TOK_COMMA && NextTok.Tok != TOK_RPAREN) || !IsFastcall) {
|
||||||
unsigned ArgSize = sizeofarg (Flags);
|
unsigned ArgSize = sizeofarg (Flags);
|
||||||
@ -651,8 +657,8 @@ static void FunctionCall (ExprDesc* Expr)
|
|||||||
ED_FinalizeRValLoad (Expr);
|
ED_FinalizeRValLoad (Expr);
|
||||||
ReturnType = GetFuncReturn (Expr->Type);
|
ReturnType = GetFuncReturn (Expr->Type);
|
||||||
|
|
||||||
/* Handle struct specially */
|
/* Handle struct/union specially */
|
||||||
if (IsTypeStruct (ReturnType)) {
|
if (IsTypeStruct (ReturnType) || IsTypeUnion (ReturnType)) {
|
||||||
/* If there is no replacement type, then it is just the address */
|
/* If there is no replacement type, then it is just the address */
|
||||||
if (ReturnType == GetReplacementType (ReturnType)) {
|
if (ReturnType == GetReplacementType (ReturnType)) {
|
||||||
/* Dereference it */
|
/* Dereference it */
|
||||||
|
@ -380,6 +380,7 @@ void NewFunc (SymEntry* Func)
|
|||||||
{
|
{
|
||||||
int C99MainFunc = 0;/* Flag for C99 main function returning int */
|
int C99MainFunc = 0;/* Flag for C99 main function returning int */
|
||||||
SymEntry* Param;
|
SymEntry* Param;
|
||||||
|
const Type* RType; /* Real type used for struct parameters */
|
||||||
|
|
||||||
/* Get the function descriptor from the function entry */
|
/* Get the function descriptor from the function entry */
|
||||||
FuncDesc* D = Func->V.F.Func;
|
FuncDesc* D = Func->V.F.Func;
|
||||||
@ -475,7 +476,12 @@ void NewFunc (SymEntry* Func)
|
|||||||
/* Pointer to function */
|
/* Pointer to function */
|
||||||
Flags = CF_PTR;
|
Flags = CF_PTR;
|
||||||
} else {
|
} 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);
|
g_push (Flags, 0);
|
||||||
}
|
}
|
||||||
@ -498,11 +504,25 @@ void NewFunc (SymEntry* Func)
|
|||||||
Param = D->SymTab->SymHead;
|
Param = D->SymTab->SymHead;
|
||||||
while (Param && (Param->Flags & SC_PARAM) != 0) {
|
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 */
|
/* Check for a register variable */
|
||||||
if (SymIsRegVar (Param)) {
|
if (SymIsRegVar (Param)) {
|
||||||
|
|
||||||
/* Allocate space */
|
/* Allocate space */
|
||||||
int Reg = F_AllocRegVar (CurrentFunc, Param->Type);
|
int Reg = F_AllocRegVar (CurrentFunc, RType);
|
||||||
|
|
||||||
/* Could we allocate a register? */
|
/* Could we allocate a register? */
|
||||||
if (Reg < 0) {
|
if (Reg < 0) {
|
||||||
@ -513,7 +533,7 @@ void NewFunc (SymEntry* Func)
|
|||||||
Param->V.R.RegOffs = Reg;
|
Param->V.R.RegOffs = Reg;
|
||||||
|
|
||||||
/* Generate swap code */
|
/* 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