Commit af1d777b27

Alex Rønne Petersen <alex@alexrp.com>
2025-10-20 21:26:14
std.builtin: add CallingConvention.sh_interrupt
Only supported in CBE.
1 parent 4fa453c
lib/std/builtin.zig
@@ -342,6 +342,7 @@ pub const CallingConvention = union(enum(u8)) {
     // Calling conventions for the `sh`/`sheb` architecture.
     sh_gnu: CommonOptions,
     sh_renesas: CommonOptions,
+    sh_interrupt: ShInterruptOptions,
 
     /// The standard `ve` calling convention.
     ve_sysv: CommonOptions,
@@ -476,6 +477,25 @@ pub const CallingConvention = union(enum(u8)) {
         };
     };
 
+    /// Options for the `sh_interrupt` calling convention.
+    pub const ShInterruptOptions = 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,
+        save: SaveBehavior = .full,
+
+        pub const SaveBehavior = enum(u3) {
+            /// Save only fpscr (if applicable).
+            fpscr,
+            /// Save only high-numbered registers, i.e. r0 through r7 are *not* saved.
+            high,
+            /// Save all registers normally.
+            full,
+            /// Save all registers using the CPU's fast register bank.
+            bank,
+        };
+    };
+
     /// Returns the array of `std.Target.Cpu.Arch` to which this `CallingConvention` applies.
     /// Asserts that `cc` is not `.auto`, `.@"async"`, `.naked`, or `.@"inline"`.
     pub fn archs(cc: CallingConvention) []const std.Target.Cpu.Arch {
lib/std/Target.zig
@@ -1923,6 +1923,7 @@ pub const Cpu = struct {
 
                 .sh_gnu,
                 .sh_renesas,
+                .sh_interrupt,
                 => &.{ .sh, .sheb },
 
                 .ve_sysv,
src/codegen/c.zig
@@ -8114,6 +8114,12 @@ fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8
         },
 
         .sh_renesas => "renesas",
+        .sh_interrupt => |opts| switch (opts.save) {
+            .fpscr => "trapa_handler", // Implies `interrupt_handler`.
+            .high => "interrupt_handler, nosave_low_regs",
+            .full => "interrupt_handler",
+            .bank => "interrupt_handler, resbank",
+        },
 
         .m68k_rtd => "m68k_rtd",
 
src/codegen/llvm.zig
@@ -11837,6 +11837,7 @@ pub fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: *const std.Targ
             std.builtin.CallingConvention.ArcInterruptOptions,
             std.builtin.CallingConvention.ArmInterruptOptions,
             std.builtin.CallingConvention.RiscvInterruptOptions,
+            std.builtin.CallingConvention.ShInterruptOptions,
             std.builtin.CallingConvention.MicroblazeInterruptOptions,
             std.builtin.CallingConvention.MipsInterruptOptions,
             std.builtin.CallingConvention.CommonOptions,
@@ -11964,6 +11965,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s
         .s390x_sysv_vx,
         .sh_gnu,
         .sh_renesas,
+        .sh_interrupt,
         .ve_sysv,
         .xcore_xs1,
         .xcore_xs2,
src/link/Dwarf.zig
@@ -3919,6 +3919,7 @@ fn updateLazyType(
                     .mips_interrupt,
                     .riscv64_interrupt,
                     .riscv32_interrupt,
+                    .sh_interrupt,
                     .arc_interrupt,
                     .avr_builtin,
                     .avr_signal,
src/InternPool.zig
@@ -12975,6 +12975,11 @@ const PackedCallingConvention = packed struct(u18) {
                     .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
                     .extra = @intFromEnum(pl.mode),
                 },
+                std.builtin.CallingConvention.ShInterruptOptions => .{
+                    .tag = tag,
+                    .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
+                    .extra = @intFromEnum(pl.save),
+                },
                 else => comptime unreachable,
             },
         };
@@ -13014,6 +13019,10 @@ const PackedCallingConvention = packed struct(u18) {
                         .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
                         .mode = @enumFromInt(cc.extra),
                     },
+                    std.builtin.CallingConvention.ShInterruptOptions => .{
+                        .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
+                        .save = @enumFromInt(cc.extra),
+                    },
                     else => comptime unreachable,
                 },
             ),
src/Sema.zig
@@ -9141,6 +9141,7 @@ fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool {
         .msp430_interrupt,
         .riscv32_interrupt,
         .riscv64_interrupt,
+        .sh_interrupt,
         .x86_interrupt,
         .x86_64_interrupt,
 
@@ -9301,6 +9302,7 @@ fn funcCommon(
             .mips_interrupt,
             .riscv64_interrupt,
             .riscv32_interrupt,
+            .sh_interrupt,
             .avr_interrupt,
             .csky_interrupt,
             .m68k_interrupt,
@@ -9528,6 +9530,7 @@ fn finishFunc(
         .mips_interrupt,
         .riscv64_interrupt,
         .riscv32_interrupt,
+        .sh_interrupt,
         .arc_interrupt,
         .avr_interrupt,
         .csky_interrupt,
@@ -30069,6 +30072,9 @@ fn callconvCoerceAllowed(
                 std.builtin.CallingConvention.RiscvInterruptOptions => {
                     if (src_data.mode != dest_data.mode) return false;
                 },
+                std.builtin.CallingConvention.ShInterruptOptions => {
+                    if (src_data.save != dest_data.save) return false;
+                },
                 else => comptime unreachable,
             }
         },
src/Zcu.zig
@@ -4449,6 +4449,9 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu
                 .riscv64_interrupt,
                 => |opts| opts.incoming_stack_alignment == null,
 
+                .sh_interrupt,
+                => |opts| opts.incoming_stack_alignment == null,
+
                 .x86_sysv,
                 .x86_win,
                 .x86_stdcall,