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.
This commit is contained in:
Stephen Heumann 2022-12-08 19:27:37 -06:00
parent 6ba6ad549f
commit f027286b6a
1 changed files with 10 additions and 5 deletions

View File

@ -3251,6 +3251,7 @@ var
fntype: typePtr; {temp function type} fntype: typePtr; {temp function type}
ftree: tokenPtr; {function address tree} ftree: tokenPtr; {function address tree}
ftype: typePtr; {function type} ftype: typePtr; {function type}
hasVarargs: boolean; {varargs call with 1+ varargs passed?}
i: integer; {loop variable} i: integer; {loop variable}
indirect: boolean; {is this an indirect call?} indirect: boolean; {is this an indirect call?}
ldoDispose: boolean; {local copy of doDispose} ldoDispose: boolean; {local copy of doDispose}
@ -3332,8 +3333,11 @@ var
tp := tp^.right; tp := tp^.right;
end; {while} end; {while}
tp := parms; tp := parms;
if (pCount > 0) or ((pCount <> 0) and not ftype^.varargs) then if pCount <> 0 then
Error(85); if ftype^.varargs and (pcount < 0) then
hasVarargs := true
else
Error(85);
end; {if} end; {if}
tp := parms; tp := parms;
@ -3402,6 +3406,7 @@ var
begin {FunctionCall} begin {FunctionCall}
{find the type of the function} {find the type of the function}
indirect := true; {assume an indirect call} indirect := true; {assume an indirect call}
hasVarargs := false; {assume no variable arguments}
ftree := tree^.left; {get the function tree} ftree := tree^.left; {get the function tree}
if ftree^.token.kind = ident then {check for direct calls} if ftree^.token.kind = ident then {check for direct calls}
if ftree^.id^.itype^.kind = functionType then begin if ftree^.id^.itype^.kind = functionType then begin
@ -3438,7 +3443,7 @@ var
fntype := expressionType; fntype := expressionType;
GenerateCode(ftree); GenerateCode(ftree);
expressionType := fntype; expressionType := fntype;
Gen1t(pc_cui, ord(fType^.varargs and strictVararg), Gen1t(pc_cui, ord(hasVarargs and strictVararg),
UsualUnaryConversions); UsualUnaryConversions);
end {if} end {if}
else begin else begin
@ -3450,10 +3455,10 @@ var
if fName^[i] in ['a'..'z'] then if fName^[i] in ['a'..'z'] then
fName^[i] := chr(ord(fName^[i]) & $5F); fName^[i] := chr(ord(fName^[i]) & $5F);
end; {if} end; {if}
Gen1tName(pc_cup, ord(fType^.varargs and strictVararg), Gen1tName(pc_cup, ord(hasVarargs and strictVararg),
UsualUnaryConversions, fname); UsualUnaryConversions, fname);
end; {else} end; {else}
if fType^.varargs then if hasVarargs then
hasVarargsCall := true; hasVarargsCall := true;
end {if} end {if}
else else