address rvalue aggregates for field access

This commit is contained in:
2026-06-24 21:13:30 +02:00
parent c7e171c438
commit f6fc25a899
2 changed files with 71 additions and 30 deletions
+47
View File
@@ -1089,6 +1089,53 @@ main :: func() i32 {
testing.expect(t, strings.contains(llvm_text, "getelementptr [4 x i32], ptr"))
}
@(test)
field_and_index_access_on_an_rvalue_aggregate_materializes_it :: proc(t: ^testing.T) {
// A by-value struct return is a temporary with no address. Reading a field,
// slicing an array field, and taking its address must spill it into a
// temporary and address that, rather than addressing the aggregate value.
text := `Box :: struct {
score i32
data [4]i32
}
make_box :: func() Box {
return Box { score = 7, data = [1, 2, 3, 4] }
}
sink :: func(s []i32) i32 {
return s[0]
}
main :: func() i32 {
s :: make_box().score
v :: sink(make_box().data[0..])
p :: &make_box().data
return s + v + p^[1]
}
`
source_file := source.Source{path="test.bro", text=text}
diagnostics := source.init_diagnostics(&source_file)
defer source.destroy_diagnostics(&diagnostics)
symbols := symbol.init_table()
defer symbol.destroy_table(&symbols)
stream := lexer.lex(&source_file, &diagnostics, &symbols)
defer delete(stream.items)
ast_module := parser.parse(&stream, &source_file, &diagnostics)
defer ast.destroy_module(&ast_module)
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
defer hir.destroy_module(&hir_module)
ir_module := lower.lower(&hir_module)
defer ir.destroy_module(&ir_module)
llvm_text := llvm.emit(&ir_module, &diagnostics, &symbols)
defer delete(llvm_text)
testing.expect_value(t, len(diagnostics.items), 0)
// The rvalue Box is spilled into a stack temporary (structs render as
// %bro.type.N), then stored, then its fields are addressed off a `ptr`.
// A regression addresses the aggregate value directly, which llc rejects.
testing.expect(t, strings.contains(llvm_text, "alloca %bro.type."))
testing.expect(t, strings.contains(llvm_text, "store %bro.type."))
testing.expect(t, strings.contains(llvm_text, "getelementptr [4 x i32], ptr"))
}
@(test)
c_variadic_calls_promote_extras_and_emit_variadic_llvm :: proc(t: ^testing.T) {
text := `variadic :: c_func(tag c_int, ...) c_int