implicit address-taking for array slices
This commit is contained in:
@@ -1017,6 +1017,78 @@ immutable_pointer_and_slice_bindings_preserve_mutable_pointees :: proc(t: ^testi
|
||||
testing.expect_value(t, len(diagnostics.items), 0)
|
||||
}
|
||||
|
||||
@(test)
|
||||
slicing_an_array_variable_takes_its_address_implicitly :: proc(t: ^testing.T) {
|
||||
// Milestone 10: `arr[a..b]` on an array variable slices without an explicit
|
||||
// `&`. The slice operand must be a pointer to the array (getelementptr off a
|
||||
// `ptr`), not the array value.
|
||||
text := `sink :: func(s []i32) i32 {
|
||||
return s[0]
|
||||
}
|
||||
main :: func() i32 {
|
||||
arr [4]i32 = [10, 20, 30, 40]
|
||||
full :: sink(arr[..])
|
||||
part :: sink(arr[1..3])
|
||||
return full + part
|
||||
}
|
||||
`
|
||||
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)
|
||||
testing.expect(t, strings.contains(llvm_text, "getelementptr [4 x i32], ptr"))
|
||||
}
|
||||
|
||||
@(test)
|
||||
slicing_an_array_rvalue_materializes_a_temporary :: proc(t: ^testing.T) {
|
||||
// The checker accepts slicing a non-location array (here, a by-value array
|
||||
// return). Lowering must store it into a temporary and slice that address;
|
||||
// otherwise the slice operand is an array value, which is an invalid pointer.
|
||||
text := `make_arr :: func() [4]i32 {
|
||||
return [1, 2, 3, 4]
|
||||
}
|
||||
sink :: func(s []i32) i32 {
|
||||
return s[0]
|
||||
}
|
||||
main :: func() i32 {
|
||||
return sink(make_arr()[0..])
|
||||
}
|
||||
`
|
||||
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 materialization store of the array rvalue into its temporary.
|
||||
testing.expect(t, strings.contains(llvm_text, "store [4 x i32]"))
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user