authorgravatar for 29632054+Parzival-3141@users.noreply.github.comJulian <29632054+Parzival-3141@users.noreply.github.com> 2024-04-28 18:43:00-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-01 12:04:44-07:00
logad63be7eb92d17f2d8d8cc8ec606293813c05deb
tree56f373a36c76bbde05af8b9286ba61102be2381d
parent704f8f4013dee59c899f8900ee2289983bb9d5da

Sema+llvm: properly implement `Interrupt` callconv

Co-authored-by: Veikka Tuominen <git@vexu.eu>

2 files changed, 25 insertions(+), 0 deletions(-)

src/Sema.zig+21
...@@ -9700,6 +9700,18 @@ fn funcCommon(...@@ -9700,6 +9700,18 @@ fn funcCommon(
9700 {9700 {
9701 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});9701 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9702 }9702 }
9703
9704 if (cc_resolved == .Interrupt) switch (target.cpu.arch) {
9705 .x86, .x86_64 => {
9706 const err_code_size = target.ptrBitWidth();
9707 switch (i) {
9708 0 => if (param_ty.zigTypeTag(mod) != .Pointer) return sema.fail(block, param_src, "parameter must be a pointer type", .{}),
9709 1 => if (param_ty.bitSize(mod) != err_code_size) return sema.fail(block, param_src, "parameter must be a {d}-bit integer", .{err_code_size}),
9710 else => return sema.fail(block, param_src, "Interrupt calling convention supports up to 2 parameters, found {d}", .{i + 1}),
9711 }
9712 },
9713 else => return sema.fail(block, param_src, "parameters are not allowed with Interrupt calling convention", .{}),
9714 };
9703 }9715 }
97049716
9705 var ret_ty_requires_comptime = false;9717 var ret_ty_requires_comptime = false;
...@@ -10048,6 +10060,15 @@ fn finishFunc(...@@ -10048,6 +10060,15 @@ fn finishFunc(
10048 });10060 });
10049 }10061 }
1005010062
10063 if (cc_resolved == .Interrupt and return_type.zigTypeTag(mod) != .Void) {
10064 return sema.fail(
10065 block,
10066 cc_src,
10067 "non-void return type '{}' not allowed in function with calling convention 'Interrupt'",
10068 .{return_type.fmt(mod)},
10069 );
10070 }
10071
10051 if (cc_resolved == .Inline and is_noinline) {10072 if (cc_resolved == .Inline and is_noinline) {
10052 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});10073 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
10053 }10074 }
src/codegen/llvm.zig+4
...@@ -4434,6 +4434,10 @@ pub const Object = struct {...@@ -4434,6 +4434,10 @@ pub const Object = struct {
4434 if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) {4434 if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) {
4435 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);4435 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4436 }4436 }
4437 if (fn_info.cc == .Interrupt) {
4438 const child_type = try lowerType(o, Type.fromInterned(ptr_info.child));
4439 try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder);
4440 }
4437 if (ptr_info.flags.is_const) {4441 if (ptr_info.flags.is_const) {
4438 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);4442 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4439 }4443 }