diff --git a/src/Sema.zig b/src/Sema.zig index fd5a25968c..32c87e7a47 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9700,6 +9700,18 @@ fn funcCommon( { return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); } + + if (cc_resolved == .Interrupt) switch (target.cpu.arch) { + .x86, .x86_64 => { + const err_code_size = target.ptrBitWidth(); + switch (i) { + 0 => if (param_ty.zigTypeTag(mod) != .Pointer) return sema.fail(block, param_src, "parameter must be a pointer type", .{}), + 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}), + else => return sema.fail(block, param_src, "Interrupt calling convention supports up to 2 parameters, found {d}", .{i + 1}), + } + }, + else => return sema.fail(block, param_src, "parameters are not allowed with Interrupt calling convention", .{}), + }; } var ret_ty_requires_comptime = false; @@ -10048,6 +10060,15 @@ fn finishFunc( }); } + if (cc_resolved == .Interrupt and return_type.zigTypeTag(mod) != .Void) { + return sema.fail( + block, + cc_src, + "non-void return type '{}' not allowed in function with calling convention 'Interrupt'", + .{return_type.fmt(mod)}, + ); + } + if (cc_resolved == .Inline and is_noinline) { return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{}); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a3c7fb0b86..c9ec89f3b4 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4434,6 +4434,10 @@ pub const Object = struct { if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) { try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); } + if (fn_info.cc == .Interrupt) { + const child_type = try lowerType(o, Type.fromInterned(ptr_info.child)); + try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder); + } if (ptr_info.flags.is_const) { try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); }