winabi: fix allocation of parameters to regs with hidden arg

In the presence of the hidden arg for return-by-value, the
registers used for natural arguments were incorrect.

(This should be applied on the 'winabi' branch.)
This commit is contained in:
Scott Graham 2026-01-08 12:32:59 -08:00 committed by Quentin Carbonneaux
parent d166a61141
commit d5f02dc67c
2 changed files with 22 additions and 1 deletions

View File

@ -630,6 +630,7 @@ static RegisterUsage lower_func_parameters(Fn* func) {
// when adding to it. // when adding to it.
curi = &insb[NIns]; curi = &insb[NIns];
int reg_counter = 0;
RegisterUsage reg_usage = {0}; RegisterUsage reg_usage = {0};
if (func->retty >= 0) { if (func->retty >= 0) {
bool by_copy = type_is_by_copy(&typ[func->retty]); bool by_copy = type_is_by_copy(&typ[func->retty]);
@ -639,6 +640,7 @@ static RegisterUsage lower_func_parameters(Fn* func) {
Ref ret_ref = newtmp("abi.ret", Kl, func); Ref ret_ref = newtmp("abi.ret", Kl, func);
emit(Ocopy, Kl, ret_ref, TMP(RCX), R); emit(Ocopy, Kl, ret_ref, TMP(RCX), R);
func->retr = ret_ref; func->retr = ret_ref;
++reg_counter;
} }
} }
Ref env = R; Ref env = R;
@ -650,7 +652,6 @@ static RegisterUsage lower_func_parameters(Fn* func) {
// Copy from the registers or stack slots into the named parameters. Depending // Copy from the registers or stack slots into the named parameters. Depending
// on how they're passed, they either need to be copied or loaded. // on how they're passed, they either need to be copied or loaded.
ArgClass* arg = arg_classes; ArgClass* arg = arg_classes;
int reg_counter = 0;
uint slot_offset = SHADOW_SPACE_SIZE / 4 + 4; uint slot_offset = SHADOW_SPACE_SIZE / 4 + 4;
for (Ins* instr = start_of_params; instr < end_of_params; ++instr, ++arg) { for (Ins* instr = start_of_params; instr < end_of_params; ++instr, ++arg) {
switch (arg->style) { switch (arg->style) {

20
test/abi9.ssa Normal file
View File

@ -0,0 +1,20 @@
type :obj = { l, l, l, l }
export
function :obj $f(l %self) {
@_0
%_1 =l alloc8 16
storel 77, %_1
ret %_1
}
# >>> driver
# #include <stdio.h>
# typedef struct { long long a, b, c, d; } obj;
# extern obj f();
# int main() { obj ret = f(); printf("%lld\n", ret.a); return 0; }
# <<<
# >>> output
# 77
# <<<