authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-26 19:49:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-27 00:49:25-07:00
log0f21d3d4d1a5cbb5254dbf55304347f4d5c3e9c5
tree4e0933b1300b0fe9fc8f005ab96b074901ad44d5
parentc3364b372f4fa67a681d599f1a7ddcd4c0154fd1

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

3 files changed, 74 insertions(+), 2 deletions(-)

src/codegen/llvm.zig+2-2
......@@ -5324,8 +5324,8 @@ pub const FuncGen = struct {
53245324 },
53255325 };
53265326
5327 if (callee_ty.zigTypeTag(mod) == .Pointer) {
5328 // Add argument attributes for function pointer calls.
5327 {
5328 // Add argument attributes.
53295329 it = iterateParamTypes(o, fn_info);
53305330 it.llvm_index += @intFromBool(sret);
53315331 it.llvm_index += @intFromBool(err_return_tracing);
test/c_abi/cfuncs.c+17
......@@ -1034,3 +1034,20 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {
10341034 return in;
10351035}
10361036#endif
1037
1038
1039struct byval_tail_callsite_attr_Point {
1040 double x;
1041 double y;
1042} Point;
1043struct byval_tail_callsite_attr_Size {
1044 double width;
1045 double height;
1046} Size;
1047struct byval_tail_callsite_attr_Rect {
1048 struct byval_tail_callsite_attr_Point origin;
1049 struct byval_tail_callsite_attr_Size size;
1050};
1051double c_byval_tail_callsite_attr(struct byval_tail_callsite_attr_Rect in) {
1052 return in.size.width;
1053}
test/c_abi/main.zig+55
......@@ -1216,3 +1216,58 @@ test "explicit Win64 calling convention" {
12161216 const res = c_explict_sys_v(.{ .val = 1, .arr = undefined });
12171217 try expect(res.val == 42);
12181218}
1219
1220const byval_tail_callsite_attr = struct {
1221 const struct_Point = extern struct {
1222 x: f64,
1223 y: f64,
1224 };
1225 const struct_Size = extern struct {
1226 width: f64,
1227 height: f64,
1228 };
1229 const struct_Rect = extern struct {
1230 origin: struct_Point,
1231 size: struct_Size,
1232 };
1233
1234 const Point = extern struct {
1235 x: f64,
1236 y: f64,
1237 };
1238
1239 const Size = extern struct {
1240 width: f64,
1241 height: f64,
1242 };
1243
1244 const MyRect = extern struct {
1245 origin: Point,
1246 size: Size,
1247
1248 fn run(self: MyRect) f64 {
1249 return c_byval_tail_callsite_attr(cast(self));
1250 }
1251
1252 fn cast(self: MyRect) struct_Rect {
1253 return @bitCast(self);
1254 }
1255
1256 extern fn c_byval_tail_callsite_attr(struct_Rect) f64;
1257 };
1258};
1259
1260test "byval tail callsite attribute" {
1261 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1262 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
1263
1264 // Originally reported at https://github.com/ziglang/zig/issues/16290
1265 // the bug was that the extern function had the byval attribute, but
1266 // zig did not put the byval attribute at the callsite. Some LLVM optimization
1267 // passes would then pass undefined for that parameter.
1268 var v: byval_tail_callsite_attr.MyRect = .{
1269 .origin = .{ .x = 1, .y = 2 },
1270 .size = .{ .width = 3, .height = 4 },
1271 };
1272 try expect(v.run() == 3.0);
1273}