Sema: fix ret_ptr when inlining

Previously, it would emit a ret_ptr AIR instruction but that is not
correct because such an instruction would reference the result pointer
of the caller function rather than the callee function.

Instead, we emit an alloc instruction in this case. `ret_load` already
handles inlining correctly.
This commit is contained in:
Andrew Kelley
2021-10-26 15:43:57 -07:00
parent c6b3d06535
commit 79702c144d
2 changed files with 39 additions and 0 deletions

View File

@@ -1958,6 +1958,14 @@ fn zirRetPtr(
.pointee_type = sema.fn_ret_ty,
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
});
if (block.inlining != null) {
// We are inlining a function call; this should be emitted as an alloc, not a ret_ptr.
// TODO when functions gain result location support, the inlining struct in
// Block should contain the return pointer, and we would pass that through here.
return block.addTy(.alloc, ptr_type);
}
return block.addTy(.ret_ptr, ptr_type);
}

View File

@@ -90,3 +90,34 @@ test "discard the result of a function that returns a struct" {
S.entry();
comptime S.entry();
}
test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" {
const S = struct {
field: u32,
fn doTheTest() !void {
bar2 = actualFn;
const result = try foo();
try expect(result.field == 1234);
}
const Foo = struct { field: u32 };
fn foo() !Foo {
var res: Foo = undefined;
res.field = bar();
return res;
}
inline fn bar() u32 {
return bar2.?();
}
var bar2: ?fn () u32 = null;
fn actualFn() u32 {
return 1234;
}
};
try S.doTheTest();
}