Skip to content

Commit

Permalink
Fix referencing passed-by-ref structs in win abi
Browse files Browse the repository at this point in the history
The double-dereference necessary to go from the function argument to the
actual location (in the case of a large structure pass) was incorrectly
happening in the field codegen. This worked if the structure was only
ever referenced as `obj.xyz`, but if `obj` is directly used (for
example, but assignment) then the address wasn't correctly calculated.
  • Loading branch information
sgraham committed Jan 25, 2024
1 parent d3fcb0d commit a296cc7
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
12 changes: 6 additions & 6 deletions src/codegen.in.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ static void gen_addr(Node* node) {
// Local variable
if (node->var->is_local) {
///| lea rax, [rbp+node->var->offset]
#if X64WIN
if (node->var->is_param_passed_by_reference) {
///| mov rax, [rax]
}
#endif
return;
}

Expand Down Expand Up @@ -272,11 +277,6 @@ static void gen_addr(Node* node) {
return;
case ND_MEMBER:
gen_addr(node->lhs);
#if X64WIN
if (node->lhs->kind == ND_VAR && node->lhs->var->is_param_passed_by_reference) {
///| mov rax, [rax]
}
#endif
///| add rax, node->member->offset
return;
case ND_FUNCALL:
Expand Down Expand Up @@ -2090,7 +2090,7 @@ static void assign_lvar_offsets(Obj* prog) {
// such and then either assign a register or stack slot for the
// reference.
// outaf("by ref %s\n", var->name);
// var->passed_by_reference = true;
assert(var->is_param_passed_by_reference);
}

// If the pointer to a referenced value or the value itself can be
Expand Down
27 changes: 27 additions & 0 deletions test/struct_copy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <stdio.h>
static void printint(int x) {
printf("%d\n", x);
}

struct B {
int b;
int c;
int x;
};

struct A {
struct B b;
};

void A(struct B b) {
struct A a;
a.b = b;
printint(a.b.b);
printint(a.b.c);
printint(a.b.x);
}

int main(void) {
struct B b = (struct B){3, 2, 1};
A(b);
}

0 comments on commit a296cc7

Please sign in to comment.