From 79702c144d713de126d37637630c7b25ee9ecc82 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Oct 2021 15:43:57 -0700 Subject: [PATCH] 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. --- src/Sema.zig | 8 ++++++++ test/behavior/fn.zig | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index d61aa52be4..87216348f2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -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); } diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index b00c2f7a59..80f1f4d919 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -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(); +}