From dbf9c7b548a56653c9267dbb615d7119974ecca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 18 Oct 2025 16:59:05 +0200 Subject: [PATCH] compiler: add support for arc_interrupt calling convention Only for use with the C backend at the moment. --- lib/std/Target.zig | 1 + lib/std/builtin.zig | 17 +++++++++++++++++ src/InternPool.zig | 9 +++++++++ src/Sema.zig | 6 ++++++ src/Zcu.zig | 3 +++ src/codegen/c.zig | 4 ++++ src/codegen/llvm.zig | 2 ++ src/link/Dwarf.zig | 1 + 8 files changed, 43 insertions(+) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index eeb755aa20..3982794c76 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1754,6 +1754,7 @@ pub const Cpu = struct { => &.{ .wasm64, .wasm32 }, .arc_sysv, + .arc_interrupt, => &.{.arc}, .avr_gnu, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index a3f3e791e6..fbd65c5574 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -277,6 +277,7 @@ pub const CallingConvention = union(enum(u8)) { /// The standard `arc` calling convention. arc_sysv: CommonOptions, + arc_interrupt: ArcInterruptOptions, // Calling conventions for the `avr` architecture. avr_gnu, @@ -368,6 +369,22 @@ pub const CallingConvention = union(enum(u8)) { register_params: u2 = 0, }; + /// Options for the `arc_interrupt` calling convention. + pub const ArcInterruptOptions = struct { + /// The boundary the stack is aligned to when the function is called. + /// `null` means the default for this calling convention. + incoming_stack_alignment: ?u64 = null, + /// The kind of interrupt being received. + type: InterruptType, + + pub const InterruptType = enum(u2) { + ilink1, + ilink2, + ilink, + firq, + }; + }; + /// Options for the `arm_interrupt` calling convention. pub const ArmInterruptOptions = struct { /// The boundary the stack is aligned to when the function is called. diff --git a/src/InternPool.zig b/src/InternPool.zig index 17fafe320e..445245fbe9 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -12950,6 +12950,11 @@ const PackedCallingConvention = packed struct(u18) { .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), .extra = pl.register_params, }, + std.builtin.CallingConvention.ArcInterruptOptions => .{ + .tag = tag, + .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), + .extra = @intFromEnum(pl.type), + }, std.builtin.CallingConvention.ArmInterruptOptions => .{ .tag = tag, .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), @@ -12984,6 +12989,10 @@ const PackedCallingConvention = packed struct(u18) { .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), .register_params = @intCast(cc.extra), }, + std.builtin.CallingConvention.ArcInterruptOptions => .{ + .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), + .type = @enumFromInt(cc.extra), + }, std.builtin.CallingConvention.ArmInterruptOptions => .{ .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), .type = @enumFromInt(cc.extra), diff --git a/src/Sema.zig b/src/Sema.zig index aef98a4dcd..3361d1a59c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9122,6 +9122,7 @@ fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool { return switch (cc) { .naked, + .arc_interrupt, .arm_interrupt, .avr_interrupt, .avr_signal, @@ -9284,6 +9285,7 @@ fn funcCommon( else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), i + 1 }), } }, + .arc_interrupt, .arm_interrupt, .mips64_interrupt, .mips_interrupt, @@ -9515,6 +9517,7 @@ fn finishFunc( .mips_interrupt, .riscv64_interrupt, .riscv32_interrupt, + .arc_interrupt, .avr_interrupt, .csky_interrupt, .m68k_interrupt, @@ -30038,6 +30041,9 @@ fn callconvCoerceAllowed( std.builtin.CallingConvention.X86RegparmOptions => { if (src_data.register_params != dest_data.register_params) return false; }, + std.builtin.CallingConvention.ArcInterruptOptions => { + if (src_data.type != dest_data.type) return false; + }, std.builtin.CallingConvention.ArmInterruptOptions => { if (src_data.type != dest_data.type) return false; }, diff --git a/src/Zcu.zig b/src/Zcu.zig index 8579eb3906..ea030905eb 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4475,6 +4475,9 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu .arm_aapcs_vfp, => |opts| opts.incoming_stack_alignment == null, + .arc_interrupt, + => |opts| opts.incoming_stack_alignment == null, + .arm_interrupt, => |opts| opts.incoming_stack_alignment == null, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d47c7657e6..bf9be70529 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -8077,6 +8077,10 @@ fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 .arm_aapcs => "pcs(\"aapcs\")", .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")", + .arc_interrupt => |opts| switch (opts.type) { + inline else => |t| "interrupt(\"" ++ @tagName(t) ++ "\")", + }, + .arm_interrupt => |opts| switch (opts.type) { .generic => "interrupt", .irq => "interrupt(\"IRQ\")", diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 5d0b87baee..8fae998492 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -11816,6 +11816,7 @@ pub fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: *const std.Targ const incoming_stack_alignment: ?u64, const register_params: u2 = switch (cc) { inline else => |pl| switch (@TypeOf(pl)) { void => .{ null, 0 }, + std.builtin.CallingConvention.ArcInterruptOptions, std.builtin.CallingConvention.ArmInterruptOptions, std.builtin.CallingConvention.RiscvInterruptOptions, std.builtin.CallingConvention.MipsInterruptOptions, @@ -11919,6 +11920,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s .powerpc_aix_altivec, .wasm_mvp, .arc_sysv, + .arc_interrupt, .avr_gnu, .bpf_std, .csky_sysv, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 3aeffb0365..a9cfefa2c4 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3917,6 +3917,7 @@ fn updateLazyType( .mips_interrupt, .riscv64_interrupt, .riscv32_interrupt, + .arc_interrupt, .avr_builtin, .avr_signal, .avr_interrupt,