Commit dbf9c7b548

Alex Rønne Petersen <alex@alexrp.com>
2025-10-18 16:59:05
compiler: add support for arc_interrupt calling convention
Only for use with the C backend at the moment.
1 parent 49eea79
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.
lib/std/Target.zig
@@ -1754,6 +1754,7 @@ pub const Cpu = struct {
                 => &.{ .wasm64, .wasm32 },
 
                 .arc_sysv,
+                .arc_interrupt,
                 => &.{.arc},
 
                 .avr_gnu,
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\")",
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,
src/link/Dwarf.zig
@@ -3917,6 +3917,7 @@ fn updateLazyType(
                     .mips_interrupt,
                     .riscv64_interrupt,
                     .riscv32_interrupt,
+                    .arc_interrupt,
                     .avr_builtin,
                     .avr_signal,
                     .avr_interrupt,
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),
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;
                 },
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,