refactor(codegen-native): extract EmitArgsToSlots (>6-slot call marshalling)
Phase 2 item 11 of the de-duplication plan — the largest single dedup. The ">6-slot store-into-stack-slots" loop (write each logical argument to its (I+1)*8(%rsp) slot, dispatching per kind: reload a hoisted akRecCall buffer from its hoist depth / store a var-param address / store a width-adjusted xmm bit pattern for a by-value float / store %rax for a plain scalar) was copy- pasted verbatim at 6 call sites — the regular, metaclass-ctor, implicit-Self, and proc-field >6-slot method paths. Collapse into EmitArgsToSlots(AArgs, AParams, AAllocSz, AHoistTotal, AHoistDepths, AHoistKinds); 7 call sites now share it. Risk gates preserved as the helper contract: all 6 sites used the same Self-at- slot-0 base offset (Dest = (I+1)*8) and the same push-phase-free akRecCall reload formula (AAllocSz + AHoistTotal - depth), so they parameterize cleanly — no phase/index divergence to thread. Behaviour-reconciling, but verified behaviour-preserving: native .s for a >6-arg program (Self+8 int args, and a 7-slot mixed int/double/var-param call) is byte-identical to pre-refactor HEAD; the native self-host fixpoint (which compiles the whole compiler, exercising every >6-slot path including metaclass and proc-field) is unchanged. All four fixpoints pass; full suite OK (3853 tests) on both QBE-built and native-built test runners.
This commit is contained in:
parent
8e52f7769f
commit
180fbb62b4
|
|
@ -726,6 +726,18 @@ type
|
|||
pattern (movsd %xmm0). }
|
||||
function EmitMethodOverflowLoad(AParams, AArgs: TObjectList;
|
||||
AAllocSz: Integer): Integer;
|
||||
{ Store every logical argument into its 8-byte slot in the >6-slot call
|
||||
frame already allocated at (%rsp): slot I goes to (I+1)*8(%rsp) (slot 0 is
|
||||
reserved for Self). Dispatches per arg kind — a hoisted akRecCall buffer
|
||||
is reloaded from its hoist depth, a var/out param stores its address, a
|
||||
by-value float stores the width-adjusted xmm bit pattern, and a plain
|
||||
scalar stores %rax. AHoistDepths/AHoistKinds are the (depth, kind) vectors
|
||||
EmitArgHoist produced; AAllocSz/AHoistTotal frame the akRecCall reload
|
||||
offset. Shared verbatim by every >6-slot method/implicit-Self/metaclass
|
||||
call path. }
|
||||
procedure EmitArgsToSlots(AArgs, AParams: TObjectList;
|
||||
AAllocSz, AHoistTotal: Integer;
|
||||
AHoistDepths, AHoistKinds: TList<Integer>);
|
||||
{ True when the parameter at AIndex is a by-value float-family param (the
|
||||
caller must store its slot as an xmm bit pattern, not via %rax). }
|
||||
function OverflowArgIsFloat(AParams: TObjectList; AIndex: Integer): Boolean;
|
||||
|
|
@ -8153,34 +8165,7 @@ begin
|
|||
OverflowSlots := TotalSlots - 6;
|
||||
AllocSz := ((TotalSlots * 8 + 15) and (-16));
|
||||
Self.Emit(Format(#9'subq $%d, %%rsp', [AllocSz]));
|
||||
for I := 0 to ACall.Args.Count - 1 do
|
||||
begin
|
||||
Arg := TASTExpr(ACall.Args.Items[I]);
|
||||
Dest := (I + 1) * 8;
|
||||
if HK.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax',
|
||||
[AllocSz + HTotal - HD.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if TMethodParam(MD.Params.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(MD.Params, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(Arg);
|
||||
Self.EmitXmm0WidthAdjust(Arg.ResolvedType,
|
||||
TMethodParam(MD.Params.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end;
|
||||
end;
|
||||
Self.EmitArgsToSlots(ACall.Args, MD.Params, AllocSz, HTotal, HD, HK);
|
||||
Self.Emit(Format(#9'movq %%rbx, 0(%%rsp)', []));
|
||||
CleanUp := Self.EmitMethodOverflowLoad(MD.Params, ACall.Args, AllocSz);
|
||||
if ACall.IsMetaclassDispatch and (MD.VTableSlot >= 0) then
|
||||
|
|
@ -8354,34 +8339,7 @@ begin
|
|||
HTotal := Self.EmitArgHoist(MD.Params, nil, True, '', ACall.Args, HD, HK);
|
||||
Self.Emit(Format(#9'subq $%d, %%rsp', [AllocSz]));
|
||||
|
||||
for I := 0 to ACall.Args.Count - 1 do
|
||||
begin
|
||||
Arg := TASTExpr(ACall.Args.Items[I]);
|
||||
Dest := (I + 1) * 8;
|
||||
if HK.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax',
|
||||
[AllocSz + HTotal - HD.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if TMethodParam(MD.Params.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(MD.Params, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(Arg);
|
||||
Self.EmitXmm0WidthAdjust(Arg.ResolvedType,
|
||||
TMethodParam(MD.Params.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end;
|
||||
end;
|
||||
Self.EmitArgsToSlots(ACall.Args, MD.Params, AllocSz, HTotal, HD, HK);
|
||||
|
||||
if ACall.ObjectName <> '' then
|
||||
begin
|
||||
|
|
@ -8450,33 +8408,7 @@ begin
|
|||
HK := TList<Integer>.Create();
|
||||
HTotal := Self.EmitArgHoist(MD.Params, nil, True, '', AArgs, HD, HK);
|
||||
Self.Emit(Format(#9'subq $%d, %%rsp', [AllocSz]));
|
||||
for I := 0 to AArgs.Count - 1 do
|
||||
begin
|
||||
Arg := TASTExpr(AArgs.Items[I]);
|
||||
Dest := (I + 1) * 8;
|
||||
if HK.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax', [AllocSz + HTotal - HD.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if TMethodParam(MD.Params.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(MD.Params, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(Arg);
|
||||
Self.EmitXmm0WidthAdjust(Arg.ResolvedType,
|
||||
TMethodParam(MD.Params.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end;
|
||||
end;
|
||||
Self.EmitArgsToSlots(AArgs, MD.Params, AllocSz, HTotal, HD, HK);
|
||||
{ Self into slot 0. }
|
||||
Self.Emit(Format(#9'movq %s, %%rax', [Self.VarOperand('Self')]));
|
||||
Self.Emit(#9'movq %rax, 0(%rsp)');
|
||||
|
|
@ -8992,6 +8924,43 @@ begin
|
|||
not P.IsOpenArray;
|
||||
end;
|
||||
|
||||
procedure TX86_64Backend.EmitArgsToSlots(AArgs, AParams: TObjectList;
|
||||
AAllocSz, AHoistTotal: Integer;
|
||||
AHoistDepths, AHoistKinds: TList<Integer>);
|
||||
var
|
||||
I, Dest: Integer;
|
||||
Arg: TASTExpr;
|
||||
begin
|
||||
for I := 0 to AArgs.Count - 1 do
|
||||
begin
|
||||
Arg := TASTExpr(AArgs.Items[I]);
|
||||
Dest := (I + 1) * 8;
|
||||
if AHoistKinds.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax',
|
||||
[AAllocSz + AHoistTotal - AHoistDepths.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if TMethodParam(AParams.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(AParams, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(Arg);
|
||||
Self.EmitXmm0WidthAdjust(Arg.ResolvedType,
|
||||
TMethodParam(AParams.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TX86_64Backend.EmitMethodOverflowLoad(AParams, AArgs: TObjectList;
|
||||
AAllocSz: Integer): Integer;
|
||||
var
|
||||
|
|
@ -9155,34 +9124,7 @@ begin
|
|||
OverflowSlots := TotalSlots - 6;
|
||||
AllocSz := ((TotalSlots * 8 + 15) and (-16));
|
||||
Self.Emit(Format(#9'subq $%d, %%rsp', [AllocSz]));
|
||||
for I := 0 to ACall.Args.Count - 1 do
|
||||
begin
|
||||
Arg := TASTExpr(ACall.Args.Items[I]);
|
||||
Dest := (I + 1) * 8;
|
||||
if HK.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax',
|
||||
[AllocSz + HTotal - HD.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if TMethodParam(MD.Params.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(MD.Params, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(Arg);
|
||||
Self.EmitXmm0WidthAdjust(Arg.ResolvedType,
|
||||
TMethodParam(MD.Params.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end;
|
||||
end;
|
||||
Self.EmitArgsToSlots(ACall.Args, MD.Params, AllocSz, HTotal, HD, HK);
|
||||
Self.Emit(Format(#9'movq %%rbx, 0(%%rsp)', []));
|
||||
CleanUp := Self.EmitMethodOverflowLoad(MD.Params, ACall.Args, AllocSz);
|
||||
if MD.VTableSlot >= 0 then
|
||||
|
|
@ -9399,34 +9341,7 @@ begin
|
|||
HTotal := Self.EmitArgHoist(MD.Params, nil, True, '', ACall.Args, HD, HK);
|
||||
Self.Emit(Format(#9'subq $%d, %%rsp', [AllocSz]));
|
||||
|
||||
for I := 0 to ACall.Args.Count - 1 do
|
||||
begin
|
||||
Arg := TASTExpr(ACall.Args.Items[I]);
|
||||
Dest := (I + 1) * 8;
|
||||
if HK.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax',
|
||||
[AllocSz + HTotal - HD.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if TMethodParam(MD.Params.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(MD.Params, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(Arg);
|
||||
Self.EmitXmm0WidthAdjust(Arg.ResolvedType,
|
||||
TMethodParam(MD.Params.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end;
|
||||
end;
|
||||
Self.EmitArgsToSlots(ACall.Args, MD.Params, AllocSz, HTotal, HD, HK);
|
||||
|
||||
if ACall.IsImplicitSelf and (ACall.ImplicitBaseInfo <> nil) then
|
||||
begin
|
||||
|
|
@ -9546,34 +9461,7 @@ begin
|
|||
HK := TList<Integer>.Create();
|
||||
HTotal := Self.EmitArgHoist(MD.Params, nil, True, '', AArgs, HD, HK);
|
||||
Self.Emit(Format(#9'subq $%d, %%rsp', [AllocSz]));
|
||||
for I := 0 to AArgs.Count - 1 do
|
||||
begin
|
||||
Arg := TASTExpr(AArgs.Items[I]);
|
||||
Dest := (I + 1) * 8;
|
||||
if HK.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax',
|
||||
[AllocSz + HTotal - HD.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if TMethodParam(MD.Params.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(MD.Params, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(Arg);
|
||||
Self.EmitXmm0WidthAdjust(Arg.ResolvedType,
|
||||
TMethodParam(MD.Params.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [Dest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(Arg);
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [Dest]));
|
||||
end;
|
||||
end;
|
||||
Self.EmitArgsToSlots(AArgs, MD.Params, AllocSz, HTotal, HD, HK);
|
||||
{ Self into slot 0 (the implicit first integer arg). }
|
||||
Self.Emit(Format(#9'movq %s, %%rax', [Self.VarOperand('Self')]));
|
||||
Self.Emit(Format(#9'movq %%rax, 0(%%rsp)', []));
|
||||
|
|
@ -11894,33 +11782,7 @@ begin
|
|||
PCHK := TList<Integer>.Create();
|
||||
PCHTotal := Self.EmitArgHoist(MD.Params, nil, True, '', PC.Args, PCHD, PCHK);
|
||||
Self.Emit(Format(#9'subq $%d, %%rsp', [PCAllocSz]));
|
||||
for I := 0 to PC.Args.Count - 1 do
|
||||
begin
|
||||
PCDest := (I + 1) * 8;
|
||||
if PCHK.Get(I) >= akRecCall then
|
||||
begin
|
||||
Self.Emit(Format(#9'movq %d(%%rsp), %%rax',
|
||||
[PCAllocSz + PCHTotal - PCHD.Get(I)]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [PCDest]));
|
||||
end
|
||||
else if TMethodParam(MD.Params.Items[I]).IsVarParam then
|
||||
begin
|
||||
Self.EmitVarArgAddrToRax(TASTExpr(PC.Args.Items[I]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [PCDest]));
|
||||
end
|
||||
else if Self.OverflowArgIsFloat(MD.Params, I) then
|
||||
begin
|
||||
Self.EmitExprToXmm0(TASTExpr(PC.Args.Items[I]));
|
||||
Self.EmitXmm0WidthAdjust(TASTExpr(PC.Args.Items[I]).ResolvedType,
|
||||
TMethodParam(MD.Params.Items[I]).ResolvedType.Kind = tySingle);
|
||||
Self.Emit(Format(#9'movsd %%xmm0, %d(%%rsp)', [PCDest]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Self.EmitExprToEax(TASTExpr(PC.Args.Items[I]));
|
||||
Self.Emit(Format(#9'movq %%rax, %d(%%rsp)', [PCDest]));
|
||||
end;
|
||||
end;
|
||||
Self.EmitArgsToSlots(PC.Args, MD.Params, PCAllocSz, PCHTotal, PCHD, PCHK);
|
||||
{ Self into slot 0 -> %rdi. }
|
||||
Self.Emit(Format(#9'movq %s, %%rax', [Self.VarOperand('Self')]));
|
||||
Self.Emit(#9'movq %rax, 0(%rsp)');
|
||||
|
|
|
|||
Loading…
Reference in a new issue