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
This commit is contained in:
Andrew Kelley 2023-07-26 19:49:16 -07:00
parent c3364b372f
commit 0f21d3d4d1
3 changed files with 74 additions and 2 deletions

View File

@ -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 = iterateParamTypes(o, fn_info);
it.llvm_index += @intFromBool(sret); it.llvm_index += @intFromBool(sret);
it.llvm_index += @intFromBool(err_return_tracing); it.llvm_index += @intFromBool(err_return_tracing);

View File

@ -1034,3 +1034,20 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {
return in; return in;
} }
#endif #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;
}

View File

@ -1216,3 +1216,58 @@ test "explicit Win64 calling convention" {
const res = c_explict_sys_v(.{ .val = 1, .arr = undefined }); const res = c_explict_sys_v(.{ .val = 1, .arr = undefined });
try expect(res.val == 42); 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);
}