Skip to content

Commit

Permalink
Fix win abi bug causing stack dealignment for when passing struct by …
Browse files Browse the repository at this point in the history
…value
  • Loading branch information
sgraham committed Jan 25, 2024
1 parent 068590a commit d0467b1
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/codegen.in.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,9 @@ static int push_args_win(Node* node, int* by_ref_copies_size) {
assert((*by_ref_copies_size == 0 && !has_by_ref_args) ||
(*by_ref_copies_size && has_by_ref_args));

if ((C(depth) + stack + (*by_ref_copies_size / 8)) % 2 == 1) {
// Realign the stack to 16 bytes if rsp fiddling mucked it up.
size_t r11_push_size = has_by_ref_args ? 1 : 0;
if ((C(depth) + stack + (*by_ref_copies_size / 8) + r11_push_size) % 2 == 1) {
///| sub rsp, 8
C(depth)++;
stack++;
Expand Down
19 changes: 19 additions & 0 deletions test/substructs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "test.h"

struct B {
int x;
int y;
int z;
};

void f(struct B b) {
ASSERT(10, b.x);
ASSERT(20, b.y);
ASSERT(30, b.z);
}

int main(void) {
struct B b = {10, 20, 30};
f(b);
return 0;
}
52 changes: 52 additions & 0 deletions test/update_structabi2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from test_helpers_for_update import *

HOST = '''\
#include <stdio.h>
struct B {
int x;
int y;
int z;
};
void test_f(struct B b) {
printf("%d %d %d\\n", b.x, b.y, b.z);
}
'''

SRC = '''\
#include <stdio.h>
struct B {
int x;
int y;
int z;
};
extern void test_f(struct B b);
// This was causing stack un-alignment due to how struct copying was
// implemented in codegen.
int main(void) {
struct B b = {10, 20, 30};
test_f(b);
printf("OK\\n");
return 0;
}
'''

# This is not really an "update" test, but because the update tests happen to
# build a separate host binary rather than using the standard dyibicc.exe, it
# gives us a way to have C code to call that's test-specific and compiled by
# the host compiler, rather than by ours.

add_to_host(HOST);
add_host_helper_func("test_f")
include_path("../../test")

initial({'main.c': SRC})
update_ok()
expect(0)

done()

0 comments on commit d0467b1

Please sign in to comment.