zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 0f21d3d4d1a5cbb5254dbf55304347f4d5c3e9c5 (tree)
parent c3364b372f4fa67a681d599f1a7ddcd4c0154fd1
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Wed, 26 Jul 2023 19:49:16 -0700

LLVM: always add argument attributes to calls

These are needed for correctness. There's no reason to only add them for
function pointers.

closes #16290

Diffstat:
Msrc/codegen/llvm.zig | 4++--
Mtest/c_abi/cfuncs.c | 17+++++++++++++++++
Mtest/c_abi/main.zig | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig @@ -5324,8 +5324,8 @@ pub const FuncGen = struct { }, }; - if (callee_ty.zigTypeTag(mod) == .Pointer) { - // Add argument attributes for function pointer calls. + { + // Add argument attributes. it = iterateParamTypes(o, fn_info); it.llvm_index += @intFromBool(sret); it.llvm_index += @intFromBool(err_return_tracing); diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c @@ -1034,3 +1034,20 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) { return in; } #endif + + +struct byval_tail_callsite_attr_Point { + double x; + double y; +} Point; +struct byval_tail_callsite_attr_Size { + double width; + double height; +} Size; +struct byval_tail_callsite_attr_Rect { + struct byval_tail_callsite_attr_Point origin; + struct byval_tail_callsite_attr_Size size; +}; +double c_byval_tail_callsite_attr(struct byval_tail_callsite_attr_Rect in) { + return in.size.width; +} diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig @@ -1216,3 +1216,58 @@ test "explicit Win64 calling convention" { const res = c_explict_sys_v(.{ .val = 1, .arr = undefined }); try expect(res.val == 42); } + +const byval_tail_callsite_attr = struct { + const struct_Point = extern struct { + x: f64, + y: f64, + }; + const struct_Size = extern struct { + width: f64, + height: f64, + }; + const struct_Rect = extern struct { + origin: struct_Point, + size: struct_Size, + }; + + const Point = extern struct { + x: f64, + y: f64, + }; + + const Size = extern struct { + width: f64, + height: f64, + }; + + const MyRect = extern struct { + origin: Point, + size: Size, + + fn run(self: MyRect) f64 { + return c_byval_tail_callsite_attr(cast(self)); + } + + fn cast(self: MyRect) struct_Rect { + return @bitCast(self); + } + + extern fn c_byval_tail_callsite_attr(struct_Rect) f64; + }; +}; + +test "byval tail callsite attribute" { + if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest; + + // Originally reported at https://github.com/ziglang/zig/issues/16290 + // the bug was that the extern function had the byval attribute, but + // zig did not put the byval attribute at the callsite. Some LLVM optimization + // passes would then pass undefined for that parameter. + var v: byval_tail_callsite_attr.MyRect = .{ + .origin = .{ .x = 1, .y = 2 }, + .size = .{ .width = 3, .height = 4 }, + }; + try expect(v.run() == 3.0); +}