From f027286b6a92c94781b4d36fc911a3ea2acaba7c Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Thu, 8 Dec 2022 19:27:37 -0600 Subject: [PATCH] Do not generate varargs stack repair code if no variable args are passed. This affects calls to a varargs function that do not actually supply any arguments beyond the fixed portion of the argument list, e.g. printf("foo"). Since these calls do not supply any variable arguments, they clearly do not include any extra variable arguments beyond those used by the function, so the standards-conformance issue that requires varargs stack repair code does not apply. It is possible that the call may include too few variable arguments, but that is illegal behavior, and it will trash the stack even when varargs stack repair code is present (although in some cases programs may "get away" with it). If stack repair code around these calls is still desired, then general stack repair code can be enabled for all function calls. --- Expression.pas | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Expression.pas b/Expression.pas index 646b171..7f6ea0b 100644 --- a/Expression.pas +++ b/Expression.pas @@ -3251,6 +3251,7 @@ var fntype: typePtr; {temp function type} ftree: tokenPtr; {function address tree} ftype: typePtr; {function type} + hasVarargs: boolean; {varargs call with 1+ varargs passed?} i: integer; {loop variable} indirect: boolean; {is this an indirect call?} ldoDispose: boolean; {local copy of doDispose} @@ -3332,8 +3333,11 @@ var tp := tp^.right; end; {while} tp := parms; - if (pCount > 0) or ((pCount <> 0) and not ftype^.varargs) then - Error(85); + if pCount <> 0 then + if ftype^.varargs and (pcount < 0) then + hasVarargs := true + else + Error(85); end; {if} tp := parms; @@ -3402,6 +3406,7 @@ var begin {FunctionCall} {find the type of the function} indirect := true; {assume an indirect call} + hasVarargs := false; {assume no variable arguments} ftree := tree^.left; {get the function tree} if ftree^.token.kind = ident then {check for direct calls} if ftree^.id^.itype^.kind = functionType then begin @@ -3438,7 +3443,7 @@ var fntype := expressionType; GenerateCode(ftree); expressionType := fntype; - Gen1t(pc_cui, ord(fType^.varargs and strictVararg), + Gen1t(pc_cui, ord(hasVarargs and strictVararg), UsualUnaryConversions); end {if} else begin @@ -3450,10 +3455,10 @@ var if fName^[i] in ['a'..'z'] then fName^[i] := chr(ord(fName^[i]) & $5F); end; {if} - Gen1tName(pc_cup, ord(fType^.varargs and strictVararg), + Gen1tName(pc_cup, ord(hasVarargs and strictVararg), UsualUnaryConversions, fname); end; {else} - if fType^.varargs then + if hasVarargs then hasVarargsCall := true; end {if} else