From af1d777b27641e2dedb70d19e3e4f5b04fa62a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 21:26:14 +0200 Subject: [PATCH] std.builtin: add CallingConvention.sh_interrupt Only supported in CBE. --- lib/std/Target.zig | 1 + lib/std/builtin.zig | 20 ++++++++++++++++++++ src/InternPool.zig | 9 +++++++++ src/Sema.zig | 6 ++++++ src/Zcu.zig | 3 +++ src/codegen/c.zig | 6 ++++++ src/codegen/llvm.zig | 2 ++ src/link/Dwarf.zig | 1 + 8 files changed, 48 insertions(+) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index ebc3762bbc..2ed6b12c71 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1923,6 +1923,7 @@ pub const Cpu = struct { .sh_gnu, .sh_renesas, + .sh_interrupt, => &.{ .sh, .sheb }, .ve_sysv, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 983358ceeb..46d3678297 100644 --- a/lib/std/builtin.zig +++ b/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 { diff --git a/src/InternPool.zig b/src/InternPool.zig index 05ca2ae2c7..a595fa502c 100644 --- a/src/InternPool.zig +++ b/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, }, ), diff --git a/src/Sema.zig b/src/Sema.zig index 398fb7e5bb..4872f47ac7 100644 --- a/src/Sema.zig +++ b/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, } }, diff --git a/src/Zcu.zig b/src/Zcu.zig index 539a45d722..0eb37668cf 100644 --- a/src/Zcu.zig +++ b/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, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index e531125a40..86669aea93 100644 --- a/src/codegen/c.zig +++ b/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", diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 0bda369deb..50fed0c2d4 100644 --- a/src/codegen/llvm.zig +++ b/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, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index da39a2fa4e..e03517f97a 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3919,6 +3919,7 @@ fn updateLazyType( .mips_interrupt, .riscv64_interrupt, .riscv32_interrupt, + .sh_interrupt, .arc_interrupt, .avr_builtin, .avr_signal,