Skip to content

Commit d6b5a31

Browse files
committed
Fix allocation of anonymous globals
1 parent b4d193b commit d6b5a31

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

src/llvm_backend.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,7 @@ gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedur
20902090
name = gb_string_append_length(name, ename.text, ename.len);
20912091

20922092
lbProcedure *dummy = lb_create_dummy_procedure(m, make_string_c(name), dummy_type);
2093+
dummy->is_startup = true;
20932094
LLVMSetVisibility(dummy->value, LLVMHiddenVisibility);
20942095
LLVMSetLinkage(dummy->value, LLVMWeakAnyLinkage);
20952096

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package test_internal
2+
3+
import "core:testing"
4+
5+
6+
7+
@(test)
8+
test_address_of_anonymous_global :: proc(t: ^testing.T) {
9+
// This loop exists so that we do more computation with stack memory
10+
// This increases the likelihood of catching a bug where anonymous globals are incorrectly allocated on the stack
11+
// instead of the data segment
12+
for _ in 0..<10 {
13+
testing.expect(t, global_variable.inner.field == 0xDEADBEEF)
14+
}
15+
}
16+
17+
global_variable := Outer_Struct{
18+
inner = &Inner_Struct{
19+
field = 0xDEADBEEF,
20+
},
21+
}
22+
Outer_Struct :: struct{
23+
inner: ^Inner_Struct,
24+
25+
// Must have a second field to prevent the compiler from simplifying the `Outer_Struct` type to `^Inner_Struct`
26+
// ...I think? In any case, don't remove this field
27+
_: int,
28+
}
29+
Inner_Struct :: struct{
30+
field: int,
31+
}
32+
33+
34+
35+
// Regression test for commit f1e3977cf94dfc0457f05d499cc280d8e1329086 where a larger anonymous global is needed to trigger
36+
// the bug
37+
@(test)
38+
test_address_of_large_anonymous_global :: proc(t: ^testing.T) {
39+
// This loop exists so that we do more computation with stack memory
40+
// This increases the likelihood of catching a bug where anonymous globals are incorrectly allocated on the stack
41+
// instead of the data segment
42+
for _ in 0..<10 {
43+
for i in 0..<8 {
44+
testing.expect(t, global_variable_64.inner.field[i] == i)
45+
}
46+
}
47+
}
48+
49+
#assert(size_of(Inner_Struct_64) == 64)
50+
global_variable_64 := Outer_Struct_64{
51+
inner = &Inner_Struct_64{
52+
field = [8]int{0, 1, 2, 3, 4, 5, 6, 7},
53+
},
54+
}
55+
Outer_Struct_64 :: struct{
56+
inner: ^Inner_Struct_64,
57+
58+
// Must have a second field to prevent the compiler from simplifying the `Outer_Struct` type to `^Inner_Struct`
59+
// ...I think? In any case, don't remove this field
60+
_: int,
61+
}
62+
Inner_Struct_64 :: struct{
63+
field: [8]int,
64+
}

0 commit comments

Comments
 (0)