From e8d060e5f5b7a51cec101c4f36edc48f28510d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:31:08 +0200 Subject: [PATCH 01/43] std.Target: update lists of omitted LLVM tags --- lib/std/Target.zig | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 3982794c7632..9638b1ddb0e7 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -72,6 +72,7 @@ pub const Os = struct { // LLVM tags deliberately omitted: // - bridgeos + // - cheriotrtos // - darwin // - kfreebsd // - nacl @@ -800,14 +801,22 @@ pub const Abi = enum { // - coreclr // - domain // - geometry + // - gnueabit64 + // - gnueabihft64 // - gnuf64 + // - gnut64 // - hull // - intersection // - library + // - llvm // - mesh // - miss + // - mlibc + // - mtia + // - pauthtest // - pixel // - raygeneration + // - rootsignature // - vertex pub fn default(arch: Cpu.Arch, os_tag: Os.Tag) Abi { @@ -1353,8 +1362,6 @@ pub const Cpu = struct { // - amdil // - amdil64 // - dxil - // - le32 - // - le64 // - r600 // - hsail // - hsail64 From 362a44a122d51096d301a9aeba86c8c7dbf40ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:31:57 +0200 Subject: [PATCH 02/43] std.Target: better Abi.default() behavior for arc and xtensa --- lib/std/Target.zig | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 9638b1ddb0e7..7ad66e7590e2 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -825,13 +825,13 @@ pub const Abi = enum { // Soft float is usually a sane default for freestanding. .arm, .armeb, - .thumb, - .thumbeb, .csky, .mips, .mipsel, .powerpc, .powerpcle, + .thumb, + .thumbeb, => .eabi, else => .none, }, @@ -846,20 +846,28 @@ pub const Abi = enum { .linux => switch (arch) { .arm, .armeb, - .thumb, - .thumbeb, .powerpc, .powerpcle, + .thumb, + .thumbeb, => .musleabihf, - // Soft float tends to be more common for CSKY and MIPS. - .csky, - => .gnueabi, // No musl support. .mips, .mipsel, => .musleabi, .mips64, .mips64el, => .muslabi64, + + // No musl support. + .arc, + => .gnu, + .csky, + => .gnueabi, + + // No glibc or musl support. + .xtensa, + => .none, + else => .musl, }, .rtems => switch (arch) { From 0e15b2ac108e82c005eb792b7f485f69165c1cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:33:21 +0200 Subject: [PATCH 03/43] std.Target: handle some more cases in toCoffMachine() --- lib/std/Target.zig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 7ad66e7590e2..dd99394053ef 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1106,36 +1106,36 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .aarch64 => .ARM64, .loongarch32 => .LOONGARCH32, .loongarch64 => .LOONGARCH64, + .mips => .R3000BE, + .mipsel => .R3000, + .mips64el => .R4000, + .powerpcle => .POWERPC, .riscv32 => .RISCV32, .riscv64 => .RISCV64, .x86 => .I386, .x86_64 => .AMD64, + .aarch64_be, .amdgcn, .arc, .armeb, - .thumbeb, - .aarch64_be, .avr, - .bpfel, .bpfeb, + .bpfel, .csky, .hexagon, .kalimba, .lanai, .m68k, - .mips, - .mipsel, .mips64, - .mips64el, .msp430, - .or1k, .nvptx, .nvptx64, + .or1k, .powerpc, - .powerpcle, .powerpc64, .powerpc64le, + .propeller, .riscv32be, .riscv64be, .s390x, @@ -1143,12 +1143,12 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .sparc64, .spirv32, .spirv64, + .thumbeb, .ve, .wasm32, .wasm64, .xcore, .xtensa, - .propeller, => .UNKNOWN, }; } From a7f085f0d7cfe4a395b39fb37b7cc89f87b061c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:41:37 +0200 Subject: [PATCH 04/43] std.Target: fix cCallingConvention() to pick mips64_n32 for muslabin32 --- lib/std/Target.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index dd99394053ef..efd2921c567f 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3467,7 +3467,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .hard => .{ .arm_aapcs_vfp = .{} }, }, .mips64, .mips64el => switch (target.abi) { - .gnuabin32 => .{ .mips64_n32 = .{} }, + .gnuabin32, .muslabin32 => .{ .mips64_n32 = .{} }, else => .{ .mips64_n64 = .{} }, }, .mips, .mipsel => .{ .mips_o32 = .{} }, From 022dcbc37a2cda002357792c2227c24d43c769ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:44:36 +0200 Subject: [PATCH 05/43] std.Target.DynamicLinker: recognize standard hexagon-linux-musl path --- lib/std/Target.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index efd2921c567f..b2cbe4b56df2 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -2358,6 +2358,7 @@ pub const DynamicLinker = struct { .aarch64, .aarch64_be, + .hexagon, .m68k, .powerpc64, .powerpc64le, From ae789fa50a60327f01041a06f95436a8fc083e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:45:31 +0200 Subject: [PATCH 06/43] test: enable dynamic hexagon-linux-musl with -Dtest-extra-targets --- test/tests.zig | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/test/tests.zig b/test/tests.zig index 3625b560cdf6..5ae056f0e4f9 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -40,7 +40,7 @@ const test_targets = blk: { // getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm // (where N is roughly 160, which technically makes it O(1), but it adds up to a // lot of branches) - @setEvalBranchQuota(50000); + @setEvalBranchQuota(60000); break :blk [_]TestTarget{ // Native Targets @@ -397,16 +397,15 @@ const test_targets = blk: { }) catch unreachable, .link_libc = true, }, - // Currently crashes in qemu-hexagon. - // .{ - // .target = std.Target.Query.parse(.{ - // .arch_os_abi = "hexagon-linux-musl", - // .cpu_features = "baseline+long_calls", - // }) catch unreachable, - // .linkage = .dynamic, - // .link_libc = true, - // .extra_target = true, - // }, + .{ + .target = std.Target.Query.parse(.{ + .arch_os_abi = "hexagon-linux-musl", + .cpu_features = "baseline+long_calls", + }) catch unreachable, + .linkage = .dynamic, + .link_libc = true, + .extra_target = true, + }, .{ .target = .{ From cd56b06352f816dc82d492071701c26c6fd430c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:46:36 +0200 Subject: [PATCH 07/43] Zcu: simplify atomicPtrAlignment() The value being computed here is almost always equal to the pointer bit width. --- src/Zcu.zig | 58 +++++++---------------------------------------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/src/Zcu.zig b/src/Zcu.zig index ea030905ebbf..6fa200561c42 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3836,61 +3836,17 @@ pub fn atomicPtrAlignment( ) AtomicPtrAlignmentError!Alignment { const target = zcu.getTarget(); const max_atomic_bits: u16 = switch (target.cpu.arch) { - .avr, - .msp430, - => 16, - - .arc, - .arm, - .armeb, - .hexagon, - .m68k, - .mips, - .mipsel, - .nvptx, - .or1k, - .powerpc, - .powerpcle, - .riscv32, - .riscv32be, - .sparc, - .thumb, - .thumbeb, - .x86, - .xcore, - .kalimba, - .lanai, - .wasm32, - .csky, - .spirv32, - .loongarch32, - .xtensa, - .propeller, - => 32, - - .amdgcn, - .bpfel, - .bpfeb, - .mips64, - .mips64el, - .nvptx64, - .powerpc64, - .powerpc64le, - .riscv64, - .riscv64be, - .sparc64, - .s390x, - .wasm64, - .ve, - .spirv64, - .loongarch64, - => 64, - .aarch64, .aarch64_be, => 128, - .x86_64 => if (target.cpu.has(.x86, .cx16)) 128 else 64, + .mips64, + .mips64el, + => 64, // N32 should be 64, not 32. + + .x86_64 => if (target.cpu.has(.x86, .cx16)) 128 else 64, // x32 should be 64 or 128, not 32. + + else => target.ptrBitWidth(), }; if (ty.toIntern() == .bool_type) return .none; From 862e674758743d722a2d654b394abb1afe34e253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 23:08:27 +0200 Subject: [PATCH 08/43] std.Target: remove bogus hosted avr/msp430 prongs in cTypeBitSize() These are microcontroller architectures; none of the OSs in the outer switch run on them. --- lib/std/Target.zig | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index b2cbe4b56df2..ddbef65369f8 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -2962,18 +2962,6 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { .wasi, .emscripten, => switch (target.cpu.arch) { - .msp430 => switch (c_type) { - .char => return 8, - .short, .ushort, .int, .uint => return 16, - .long, .ulong, .float => return 32, - .longlong, .ulonglong, .double, .longdouble => return 64, - }, - .avr => switch (c_type) { - .char => return 8, - .short, .ushort, .int, .uint => return 16, - .long, .ulong, .float, .double, .longdouble => return 32, - .longlong, .ulonglong => return 64, - }, .mips64, .mips64el => switch (c_type) { .char => return 8, .short, .ushort => return 16, From 45b80f2e41adfef82cfbdfec4d63a35de66b2f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 23:12:22 +0200 Subject: [PATCH 09/43] std.Target: fix cTypePreferredAlignment() for arc --- lib/std/Target.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index ddbef65369f8..5cc887fcaa01 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3314,6 +3314,7 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { @as(u16, switch (target.cpu.arch) { .msp430 => 2, + .arc, .csky, .xcore, .or1k, @@ -3322,7 +3323,6 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { .propeller, => 4, - .arc, .arm, .armeb, .thumb, From dda05b29c06731895970e75c7444f0d30c7d334f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 23:14:49 +0200 Subject: [PATCH 10/43] std.Target: fix cMaxIntAlignment() for a few architectures --- lib/std/Target.zig | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 5cc887fcaa01..9ffad45de3bb 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3377,32 +3377,40 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .msp430 => 2, - .xcore, + .arc, + .csky, + .kalimba, + .or1k, .propeller, + .xcore, => 4, - .amdgcn, .arm, .armeb, - .thumb, - .thumbeb, - .lanai, .hexagon, + .lanai, + .loongarch32, + .m68k, .mips, .mipsel, - .or1k, .powerpc, .powerpcle, .riscv32, .riscv32be, .s390x, + .sparc, + .thumb, + .thumbeb, + .x86, + .xtensa, => 8, - // Even LLVMABIAlignmentOfType(i128) agrees on these targets. .aarch64, .aarch64_be, + .amdgcn, .bpfel, .bpfeb, + .loongarch64, .mips64, .mips64el, .nvptx, @@ -3411,26 +3419,13 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .powerpc64le, .riscv64, .riscv64be, - .sparc, .sparc64, - .wasm32, - .wasm64, - .x86, - .x86_64, - => 16, - - // Below this comment are unverified but based on the fact that C requires - // int128_t to be 16 bytes aligned, it's a safe default. - .arc, - .csky, - .kalimba, - .loongarch32, - .loongarch64, - .m68k, .spirv32, .spirv64, .ve, - .xtensa, + .wasm32, + .wasm64, + .x86_64, => 16, }; } From 3e2daa509a897a4e10d5e6f28731b33ac2cc3dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 23:32:47 +0200 Subject: [PATCH 11/43] std.Target: add arceb and xtensaeb Cpu.Arch tags --- lib/std/Target.zig | 215 +++++++++++++++++++-------------- lib/std/atomic.zig | 1 + lib/std/builtin.zig | 7 +- lib/std/builtin/assembly.zig | 4 +- lib/std/debug/Dwarf.zig | 6 +- lib/std/debug/SelfInfo/Elf.zig | 2 +- lib/std/debug/cpu_context.zig | 10 +- lib/std/heap.zig | 8 +- lib/std/os/linux.zig | 11 +- lib/std/os/linux/tls.zig | 3 +- lib/std/pie.zig | 4 +- lib/std/start.zig | 4 +- lib/std/zig/system.zig | 1 + src/codegen/llvm.zig | 6 + src/target.zig | 4 + test/tests.zig | 2 +- 16 files changed, 173 insertions(+), 115 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 9ffad45de3bb..eda1bb2cefdc 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -860,12 +860,14 @@ pub const Abi = enum { // No musl support. .arc, + .arceb, => .gnu, .csky, => .gnueabi, // No glibc or musl support. .xtensa, + .xtensaeb, => .none, else => .musl, @@ -1061,12 +1063,12 @@ pub const ObjectFormat = enum { pub fn toElfMachine(target: *const Target) std.elf.EM { return switch (target.cpu.arch) { + .aarch64, .aarch64_be => .AARCH64, .amdgcn => .AMDGPU, - .arc => .ARC_COMPACT, + .arc, .arceb => .ARC_COMPACT, .arm, .armeb, .thumb, .thumbeb => .ARM, - .aarch64, .aarch64_be => .AARCH64, .avr => .AVR, - .bpfel, .bpfeb => .BPF, + .bpfeb, .bpfel => .BPF, .csky => .CSKY, .hexagon => .QDSP6, .kalimba => .CSR_KALIMBA, @@ -1087,7 +1089,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM { .x86 => .@"386", .x86_64 => .X86_64, .xcore => .XCORE, - .xtensa => .XTENSA, + .xtensa, .xtensaeb => .XTENSA, .nvptx, .nvptx64, @@ -1118,6 +1120,7 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .aarch64_be, .amdgcn, .arc, + .arceb, .armeb, .avr, .bpfeb, @@ -1149,6 +1152,7 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .wasm64, .xcore, .xtensa, + .xtensaeb, => .UNKNOWN, }; } @@ -1317,17 +1321,16 @@ pub const Cpu = struct { }; pub const Arch = enum { + aarch64, + aarch64_be, amdgcn, arc, + arceb, arm, armeb, - thumb, - thumbeb, - aarch64, - aarch64_be, avr, - bpfel, bpfeb, + bpfel, csky, hexagon, kalimba, @@ -1340,9 +1343,9 @@ pub const Cpu = struct { mips64, mips64el, msp430, - or1k, nvptx, nvptx64, + or1k, powerpc, powerpcle, powerpc64, @@ -1357,6 +1360,8 @@ pub const Cpu = struct { sparc64, spirv32, spirv64, + thumb, + thumbeb, ve, wasm32, wasm64, @@ -1364,6 +1369,7 @@ pub const Cpu = struct { x86_64, xcore, xtensa, + xtensaeb, // LLVM tags deliberately omitted: // - aarch64_32 @@ -1418,12 +1424,12 @@ pub const Cpu = struct { pub inline fn family(arch: Arch) Family { return switch (arch) { + .aarch64, .aarch64_be => .aarch64, .amdgcn => .amdgcn, - .arc => .arc, + .arc, .arceb => .arc, .arm, .armeb, .thumb, .thumbeb => .arm, - .aarch64, .aarch64_be => .aarch64, .avr => .avr, - .bpfel, .bpfeb => .bpf, + .bpfeb, .bpfel => .bpf, .csky => .csky, .hexagon => .hexagon, .kalimba => .kalimba, @@ -1444,7 +1450,7 @@ pub const Cpu = struct { .wasm32, .wasm64 => .wasm, .x86, .x86_64 => .x86, .xcore => .xcore, - .xtensa => .xtensa, + .xtensa, .xtensaeb => .xtensa, }; } @@ -1477,6 +1483,13 @@ pub const Cpu = struct { }; } + pub inline fn isArc(arch: Arch) bool { + return switch (arch) { + .arc, .arceb => true, + else => false, + }; + } + pub inline fn isWasm(arch: Arch) bool { return switch (arch) { .wasm32, .wasm64 => true, @@ -1573,6 +1586,13 @@ pub const Cpu = struct { }; } + pub inline fn isXtensa(arch: Arch) bool { + return switch (arch) { + .xtensa, .xtensaeb => true, + else => false, + }; + } + pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { for (arch.allCpuModels()) |cpu| { if (std.mem.eql(u8, cpu_name, cpu.name)) { @@ -1584,43 +1604,39 @@ pub const Cpu = struct { pub fn endian(arch: Arch) std.builtin.Endian { return switch (arch) { - .avr, - .arm, .aarch64, - .amdgcn, + .arm, + .arc, + .avr, .bpfel, .csky, - .xtensa, .hexagon, .kalimba, + .loongarch32, + .loongarch64, .mipsel, .mips64el, .msp430, - .nvptx, - .nvptx64, .powerpcle, .powerpc64le, + .propeller, .riscv32, .riscv64, - .x86, - .x86_64, + .thumb, + .ve, .wasm32, .wasm64, + .x86, + .x86_64, .xcore, - .thumb, - .ve, - // GPU bitness is opaque. For now, assume little endian. - .spirv32, - .spirv64, - .loongarch32, - .loongarch64, - .arc, - .propeller, + .xtensa, => .little, - .armeb, .aarch64_be, + .arceb, + .armeb, .bpfeb, + .lanai, .m68k, .mips, .mips64, @@ -1629,12 +1645,20 @@ pub const Cpu = struct { .powerpc64, .riscv32be, .riscv64be, + .s390x, .thumbeb, .sparc, .sparc64, - .lanai, - .s390x, + .xtensaeb, => .big, + + // GPU endianness is opaque. For now, assume little endian. + .amdgcn, + .nvptx, + .nvptx64, + .spirv32, + .spirv64, + => .little, }; } @@ -1770,7 +1794,7 @@ pub const Cpu = struct { .arc_sysv, .arc_interrupt, - => &.{.arc}, + => &.{ .arc, .arceb }, .avr_gnu, .avr_builtin, @@ -1826,7 +1850,7 @@ pub const Cpu = struct { .xtensa_call0, .xtensa_windowed, - => &.{.xtensa}, + => &.{ .xtensa, .xtensaeb }, .amdgcn_device, .amdgcn_kernel, @@ -2418,9 +2442,10 @@ pub const DynamicLinker = struct { } else if (abi.isGnu()) switch (cpu.arch) { - // TODO: `eb` architecture support. // TODO: `700` ABI support. - .arc => if (abi == .gnu) init("/lib/ld-linux-arc.so.2") else none, + .arc, + .arceb, + => |arch| if (abi == .gnu) initFmt("/lib/ld-linux-{t}.so.2", .{arch}) else none, .arm, .armeb, @@ -2450,7 +2475,10 @@ pub const DynamicLinker = struct { else => return none, }}), - .m68k => if (abi == .gnu) init("/lib/ld.so.1") else none, + .m68k, + .xtensa, + .xtensaeb, + => if (abi == .gnu) init("/lib/ld.so.1") else none, .mips, .mipsel, @@ -2480,6 +2508,7 @@ pub const DynamicLinker = struct { => init("/lib/ld.so.1"), else => none, }, + .powerpc64, .powerpc64le, => if (abi == .gnu) init("/lib64/ld64.so.2") else none, @@ -2512,8 +2541,6 @@ pub const DynamicLinker = struct { else => none, }, - .xtensa => if (abi == .gnu) init("/lib/ld.so.1") else none, - else => none, } else @@ -2680,52 +2707,54 @@ pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 { => 16, .arc, + .arceb, .arm, .armeb, .csky, .hexagon, + .kalimba, + .lanai, + .loongarch32, .m68k, .mips, .mipsel, + .nvptx, .or1k, .powerpc, .powerpcle, + .propeller, .riscv32, .riscv32be, + .sparc, + .spirv32, .thumb, .thumbeb, + .wasm32, .x86, .xcore, - .nvptx, - .kalimba, - .lanai, - .wasm32, - .sparc, - .spirv32, - .loongarch32, .xtensa, - .propeller, + .xtensaeb, => 32, .aarch64, .aarch64_be, + .amdgcn, + .bpfeb, + .bpfel, + .loongarch64, .mips64, .mips64el, + .nvptx64, .powerpc64, .powerpc64le, .riscv64, .riscv64be, - .x86_64, - .nvptx64, - .wasm64, - .amdgcn, - .bpfel, - .bpfeb, - .sparc64, .s390x, - .ve, + .sparc64, .spirv64, - .loongarch64, + .ve, + .wasm64, + .x86_64, => 64, }; } @@ -2788,13 +2817,12 @@ pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed; return switch (target.cpu.arch) { - .arm, - .armeb, - .thumb, - .thumbeb, .aarch64, .aarch64_be, + .arm, + .armeb, .arc, + .arceb, .csky, .hexagon, .msp430, @@ -2807,8 +2835,11 @@ pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { .riscv32be, .riscv64, .riscv64be, + .thumb, + .thumbeb, .xcore, .xtensa, + .xtensaeb, => .unsigned, else => .signed, }; @@ -3217,31 +3248,33 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { => 2, .arc, + .arceb, .csky, + .kalimba, + .or1k, + .propeller, .x86, .xcore, - .or1k, - .kalimba, .xtensa, - .propeller, + .xtensaeb, => 4, + .amdgcn, .arm, .armeb, - .thumb, - .thumbeb, - .amdgcn, - .bpfel, .bpfeb, + .bpfel, .hexagon, + .lanai, .m68k, .mips, .mipsel, - .sparc, - .lanai, .nvptx, .nvptx64, .s390x, + .sparc, + .thumb, + .thumbeb, => 8, .aarch64, @@ -3261,10 +3294,10 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { .sparc64, .spirv32, .spirv64, - .x86_64, .ve, .wasm32, .wasm64, + .x86_64, => 16, .avr, @@ -3276,7 +3309,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { // Overrides for unusual alignments switch (target.cpu.arch) { - .arc => switch (c_type) { + .arc, .arceb => switch (c_type) { .longdouble => return 4, else => {}, }, @@ -3315,31 +3348,33 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { .msp430 => 2, .arc, + .arceb, .csky, - .xcore, - .or1k, .kalimba, - .xtensa, + .or1k, .propeller, + .xcore, + .xtensa, + .xtensaeb, => 4, + .amdgcn, .arm, .armeb, - .thumb, - .thumbeb, - .amdgcn, - .bpfel, .bpfeb, + .bpfel, .hexagon, - .x86, + .lanai, .m68k, .mips, .mipsel, - .sparc, - .lanai, .nvptx, .nvptx64, .s390x, + .sparc, + .thumb, + .thumbeb, + .x86, => 8, .aarch64, @@ -3359,10 +3394,10 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { .sparc64, .spirv32, .spirv64, - .x86_64, .ve, .wasm32, .wasm64, + .x86_64, => 16, .avr, @@ -3378,6 +3413,7 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .msp430 => 2, .arc, + .arceb, .csky, .kalimba, .or1k, @@ -3403,6 +3439,7 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .thumbeb, .x86, .xtensa, + .xtensaeb, => 8, .aarch64, @@ -3440,9 +3477,9 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .windows, .uefi => .{ .x86_win = .{} }, else => .{ .x86_sysv = .{} }, }, - .aarch64, .aarch64_be => if (target.os.tag.isDarwin()) cc: { - break :cc .{ .aarch64_aapcs_darwin = .{} }; - } else switch (target.os.tag) { + .aarch64, .aarch64_be => if (target.os.tag.isDarwin()) + .{ .aarch64_aapcs_darwin = .{} } + else switch (target.os.tag) { .windows => .{ .aarch64_aapcs_win = .{} }, else => .{ .aarch64_aapcs = .{} }, }, @@ -3469,7 +3506,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention else => .{ .powerpc_sysv = .{} }, }, .wasm32, .wasm64 => .{ .wasm_mvp = .{} }, - .arc => .{ .arc_sysv = .{} }, + .arc, .arceb => .{ .arc_sysv = .{} }, .avr => .avr_gnu, .bpfel, .bpfeb => .{ .bpf_std = .{} }, .csky => .{ .csky_sysv = .{} }, @@ -3488,7 +3525,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .s390x => .{ .s390x_sysv = .{} }, .ve => .{ .ve_sysv = .{} }, .xcore => .{ .xcore_xs1 = .{} }, - .xtensa => .{ .xtensa_call0 = .{} }, + .xtensa, .xtensaeb => .{ .xtensa_call0 = .{} }, .amdgcn => .{ .amdgcn_device = .{} }, .nvptx, .nvptx64 => .nvptx_device, .spirv32, .spirv64 => .spirv_device, diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig index 7853d042143a..507040c582c1 100644 --- a/lib/std/atomic.zig +++ b/lib/std/atomic.zig @@ -419,6 +419,7 @@ pub fn cacheLineForCpu(cpu: std.Target.Cpu) u16 { .aarch64, .aarch64_be, .arc, + .arceb, .powerpc64, .powerpc64le, => 128, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index fbd65c557429..d889e168a2b6 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -275,7 +275,7 @@ pub const CallingConvention = union(enum(u8)) { /// The standard `wasm32` and `wasm64` calling convention, as specified in the WebAssembly Tool Conventions. wasm_mvp: CommonOptions, - /// The standard `arc` calling convention. + /// The standard `arc`/`arceb` calling convention. arc_sysv: CommonOptions, arc_interrupt: ArcInterruptOptions, @@ -331,7 +331,7 @@ pub const CallingConvention = union(enum(u8)) { xcore_xs1: CommonOptions, xcore_xs2: CommonOptions, - // Calling conventions for the `xtensa` architecture. + // Calling conventions for the `xtensa`/`xtensaeb` architecture. xtensa_call0: CommonOptions, xtensa_windowed: CommonOptions, @@ -920,6 +920,7 @@ pub const VaList = switch (builtin.cpu.arch) { .x86, => *u8, .arc, + .arceb, .avr, .bpfel, .bpfeb, @@ -966,7 +967,7 @@ pub const VaList = switch (builtin.cpu.arch) { }, else => VaListX86_64, }, - .xtensa => VaListXtensa, + .xtensa, .xtensaeb => VaListXtensa, else => @compileError("VaList not supported for this target yet"), }; diff --git a/lib/std/builtin/assembly.zig b/lib/std/builtin/assembly.zig index ba0f7ceb4e37..773b8e587ad0 100644 --- a/lib/std/builtin/assembly.zig +++ b/lib/std/builtin/assembly.zig @@ -779,7 +779,7 @@ pub const Clobbers = switch (@import("builtin").cpu.arch) { lr: bool = false, sr: bool = false, }, - .xtensa => packed struct { + .xtensa, .xtensaeb => packed struct { /// Whether the inline assembly code may perform stores to memory /// addresses other than those derived from input pointer provenance. memory: bool = false, @@ -1591,7 +1591,7 @@ pub const Clobbers = switch (@import("builtin").cpu.arch) { vr30: bool = false, vr31: bool = false, }, - .arc => packed struct { + .arc, .arceb => packed struct { /// Whether the inline assembly code may perform stores to memory /// addresses other than those derived from input pointer provenance. memory: bool = false, diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 7229dcdf4cc9..11dc6e5429b9 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1430,7 +1430,7 @@ pub fn compactUnwindToDwarfRegNumber(unwind_reg_number: u3) !u16 { pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { return switch (arch) { .aarch64, .aarch64_be => 32, - .arc => 160, + .arc, .arceb => 160, .arm, .armeb, .thumb, .thumbeb => 15, .csky => 64, .hexagon => 76, @@ -1453,7 +1453,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { return switch (arch) { .aarch64, .aarch64_be => 29, - .arc => 27, + .arc, .arceb => 27, .arm, .armeb, .thumb, .thumbeb => 11, .csky => 14, .hexagon => 30, @@ -1476,7 +1476,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 { return switch (arch) { .aarch64, .aarch64_be => 31, - .arc => 28, + .arc, .arceb => 28, .arm, .armeb, .thumb, .thumbeb => 13, .csky => 14, .hexagon => 29, diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 57135425105e..d9f48281dee9 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -102,7 +102,7 @@ pub const can_unwind: bool = s: { .x86, .x86_64, }, - // Not supported yet: arm/armeb/thumb/thumbeb, xtensa + // Not supported yet: arm/armeb/thumb/thumbeb, xtensa/xtensaeb .linux => &.{ .aarch64, .aarch64_be, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index caed9e328929..0b1a4e34b736 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -5,7 +5,7 @@ pub const Native = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "CpuCont root.debug.CpuContext else switch (native_arch) { .aarch64, .aarch64_be => Aarch64, - .arc => Arc, + .arc, .arceb => Arc, .arm, .armeb, .thumb, .thumbeb => Arm, .csky => Csky, .hexagon => Hexagon, @@ -36,7 +36,7 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { const uc: *const signal_ucontext_t = @ptrCast(@alignCast(ctx_ptr)); // Deal with some special cases first. - if (native_arch == .arc and native_os == .linux) { + if (native_arch.isArc() and native_os == .linux) { var native: Native = .{ .r = [_]u32{ uc.mcontext.r31, uc.mcontext.r30, 0, uc.mcontext.r28 } ++ uc.mcontext.r27_26 ++ @@ -1553,6 +1553,7 @@ const signal_ucontext_t = switch (native_os) { }, // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/include/uapi/asm-generic/ucontext.h .arc, + .arceb, .csky, .hexagon, .m68k, @@ -1565,13 +1566,14 @@ const signal_ucontext_t = switch (native_os) { .x86, .x86_64, .xtensa, + .xtensaeb, => extern struct { _flags: usize, _link: ?*signal_ucontext_t, _stack: std.os.linux.stack_t, mcontext: switch (native_arch) { // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arc/include/uapi/asm/sigcontext.h - .arc => extern struct { + .arc, .arceb => extern struct { _pad1: u32, _bta: u32, _lp: extern struct { @@ -1691,7 +1693,7 @@ const signal_ucontext_t = switch (native_os) { rip: u64, }, // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/xtensa/include/uapi/asm/sigcontext.h - .xtensa => extern struct { + .xtensa, .xtensaeb => extern struct { pc: u32, _ps: u32, _l: extern struct { diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 382e763ef2fd..3996d91203a8 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -824,7 +824,7 @@ const page_size_min_default: ?usize = switch (builtin.os.tag) { .emscripten => 64 << 10, .linux => switch (builtin.cpu.arch) { // Linux/arch/*/Kconfig - .arc => 4 << 10, + .arc, .arceb => 4 << 10, .thumb, .thumbeb, .arm, .armeb => 4 << 10, .aarch64, .aarch64_be => 4 << 10, .csky => 4 << 10, @@ -839,7 +839,7 @@ const page_size_min_default: ?usize = switch (builtin.os.tag) { .sparc => 4 << 10, .sparc64 => 8 << 10, .x86, .x86_64 => 4 << 10, - .xtensa => 4 << 10, + .xtensa, .xtensaeb => 4 << 10, else => null, }, .freestanding, .other => switch (builtin.cpu.arch) { @@ -972,7 +972,7 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) { .emscripten => 64 << 10, .linux => switch (builtin.cpu.arch) { // Linux/arch/*/Kconfig - .arc => 16 << 10, + .arc, .arceb => 16 << 10, .thumb, .thumbeb, .arm, .armeb => 4 << 10, .aarch64, .aarch64_be => 64 << 10, .csky => 4 << 10, @@ -987,7 +987,7 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) { .sparc => 4 << 10, .sparc64 => 8 << 10, .x86, .x86_64 => 4 << 10, - .xtensa => 4 << 10, + .xtensa, .xtensaeb => 4 << 10, else => null, }, .freestanding => switch (builtin.cpu.arch) { diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 10feead2ae94..11add50a057b 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -116,7 +116,7 @@ pub const SECCOMP = @import("linux/seccomp.zig"); pub const syscalls = @import("linux/syscalls.zig"); pub const SYS = switch (native_arch) { - .arc => syscalls.Arc, + .arc, .arceb => syscalls.Arc, .aarch64, .aarch64_be => syscalls.Arm64, .arm, .armeb, .thumb, .thumbeb => syscalls.Arm, .csky => syscalls.CSky, @@ -141,7 +141,7 @@ pub const SYS = switch (native_arch) { .gnux32, .muslx32 => syscalls.X32, else => syscalls.X64, }, - .xtensa => syscalls.Xtensa, + .xtensa, .xtensaeb => syscalls.Xtensa, else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"), }; @@ -3686,7 +3686,7 @@ pub const PROT = struct { pub const EXEC = 0x4; /// page may be used for atomic ops pub const SEM = switch (native_arch) { - .mips, .mipsel, .mips64, .mips64el, .xtensa => 0x10, + .mips, .mipsel, .mips64, .mips64el, .xtensa, .xtensaeb => 0x10, else => 0x8, }; /// mprotect flag: extend change to start of growsdown vma @@ -6161,6 +6161,7 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t { pub const MINSIGSTKSZ = switch (native_arch) { .arc, + .arceb, .arm, .armeb, .csky, @@ -6181,6 +6182,7 @@ pub const MINSIGSTKSZ = switch (native_arch) { .x86, .x86_64, .xtensa, + .xtensaeb, => 2048, .loongarch64, .sparc, @@ -6196,6 +6198,7 @@ pub const MINSIGSTKSZ = switch (native_arch) { }; pub const SIGSTKSZ = switch (native_arch) { .arc, + .arceb, .arm, .armeb, .csky, @@ -6216,6 +6219,7 @@ pub const SIGSTKSZ = switch (native_arch) { .x86, .x86_64, .xtensa, + .xtensaeb, => 8192, .aarch64, .aarch64_be, @@ -9740,6 +9744,7 @@ pub const AUDIT = struct { .armeb, .thumbeb => .ARMEB, .aarch64 => .AARCH64, .arc => .ARCV2, + .arceb => .ARCV2BE, .csky => .CSKY, .hexagon => .HEXAGON, .loongarch32 => .LOONGARCH32, diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index abac4318e446..62df828916a9 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -64,6 +64,7 @@ const Variant = enum { const current_variant: Variant = switch (native_arch) { .arc, + .arceb, .arm, .armeb, .aarch64, @@ -243,7 +244,7 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr), ); }, - .arc => { + .arc, .arceb => { // We apparently need to both set r25 (TP) *and* inform the kernel... asm volatile ( \\ mov r25, %[addr] diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 1b028930c75b..395f03e449b6 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -22,7 +22,7 @@ const R_SPARC_RELATIVE = 22; const R_RELATIVE = switch (builtin.cpu.arch) { .x86 => R_386_RELATIVE, .x86_64 => R_AMD64_RELATIVE, - .arc => R_ARC_RELATIVE, + .arc, .arceb => R_ARC_RELATIVE, .arm, .armeb, .thumb, .thumbeb => R_ARM_RELATIVE, .aarch64, .aarch64_be => R_AARCH64_RELATIVE, .csky => R_CSKY_RELATIVE, @@ -58,7 +58,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ lea _DYNAMIC(%%rip), %[ret] : [ret] "=r" (-> [*]const elf.Dyn), ), - .arc => asm volatile ( + .arc, .arceb => asm volatile ( \\ .weak _DYNAMIC \\ .hidden _DYNAMIC \\ add %[ret], pcl, _DYNAMIC@pcl diff --git a/lib/std/start.zig b/lib/std/start.zig index c6f65aae25d4..1f1aee060493 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -195,7 +195,7 @@ fn _start() callconv(.naked) noreturn { // This is the first userspace frame. Prevent DWARF-based unwinders from unwinding further. We // prevent FP-based unwinders from unwinding further by zeroing the register below. if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (switch (native_arch) { - .arc => ".cfi_undefined blink", + .arc, .arceb => ".cfi_undefined blink", .arm, .armeb, .thumb, .thumbeb => "", // https://github.com/llvm/llvm-project/issues/115891 .aarch64, .aarch64_be => ".cfi_undefined lr", .csky => ".cfi_undefined lr", @@ -253,7 +253,7 @@ fn _start() callconv(.naked) noreturn { \\ and sp, x0, #-16 \\ b %[posixCallMainAndExit] , - .arc => + .arc, .arceb => // ARC v1 and v2 had a very low stack alignment requirement of 4; v3 increased it to 16. \\ mov fp, 0 \\ mov blink, 0 diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index e237cecd5904..54ba15ea832d 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -119,6 +119,7 @@ pub fn getExternalExecutor( .thumb, .thumbeb, .xtensa, + .xtensaeb, => |t| switch (candidate.os.tag) { .linux, => .{ .qemu = switch (t) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 8fae998492aa..b922ae070474 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -106,9 +106,11 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 .wasm64 => "wasm64", .ve => "ve", + .arceb, .kalimba, .or1k, .propeller, + .xtensaeb, => unreachable, // Gated by hasLlvmSupport(). }; @@ -473,9 +475,11 @@ pub fn dataLayout(target: *const std.Target) []const u8 { .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32", + .arceb, .kalimba, .or1k, .propeller, + .xtensaeb, => unreachable, // Gated by hasLlvmSupport(). }; } @@ -13107,9 +13111,11 @@ pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { }, // LLVM does does not have a backend for these. + .arceb, .kalimba, .or1k, .propeller, + .xtensaeb, => unreachable, } } diff --git a/src/target.zig b/src/target.zig index 3a1b9f93afc7..a5de66a68dcc 100644 --- a/src/target.zig +++ b/src/target.zig @@ -216,9 +216,11 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat) => false, // No LLVM backend exists. + .arceb, .kalimba, .or1k, .propeller, + .xtensaeb, => false, }; } @@ -711,6 +713,7 @@ pub fn minFunctionAlignment(target: *const std.Target) Alignment { .xcore, => .@"2", .arc, + .arceb, .arm, .armeb, .aarch64, @@ -728,6 +731,7 @@ pub fn minFunctionAlignment(target: *const std.Target) Alignment { .sparc, .sparc64, .xtensa, + .xtensaeb, => .@"4", .bpfel, .bpfeb, diff --git a/test/tests.zig b/test/tests.zig index 5ae056f0e4f9..c7fe8a7e7885 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1550,7 +1550,7 @@ const CAbiTarget = struct { }; const c_abi_targets = blk: { - @setEvalBranchQuota(20000); + @setEvalBranchQuota(30000); break :blk [_]CAbiTarget{ // Native Targets From c55e83eab1369373fe6db5072802c2fc1c4d7ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 16:30:29 +0200 Subject: [PATCH 12/43] std.Target: xtensa defaults to windowed ABI --- lib/std/Target.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index eda1bb2cefdc..004d5ef51b4b 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3525,7 +3525,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .s390x => .{ .s390x_sysv = .{} }, .ve => .{ .ve_sysv = .{} }, .xcore => .{ .xcore_xs1 = .{} }, - .xtensa, .xtensaeb => .{ .xtensa_call0 = .{} }, + .xtensa, .xtensaeb => .{ .xtensa_windowed = .{} }, .amdgcn => .{ .amdgcn_device = .{} }, .nvptx, .nvptx64 => .nvptx_device, .spirv32, .spirv64 => .spirv_device, From ee72f06f47055ecf3fa650eae9ef49446745f509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:43:03 +0200 Subject: [PATCH 13/43] std.Target: add tags and info for alpha, hppa, microblaze, sh --- lib/std/Target.zig | 158 +++++++++++++++++- lib/std/builtin.zig | 39 +++++ lib/std/builtin/assembly.zig | 315 +++++++++++++++++++++++++++++++++++ src/Sema.zig | 6 + src/codegen/c.zig | 2 + src/codegen/llvm.zig | 27 +++ src/link/Dwarf.zig | 2 + src/target.zig | 20 ++- 8 files changed, 561 insertions(+), 8 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 004d5ef51b4b..d5caf8665968 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -733,6 +733,7 @@ pub const Os = struct { }; pub const aarch64 = @import("Target/aarch64.zig"); +pub const alpha = @import("Target/generic.zig"); pub const amdgcn = @import("Target/amdgcn.zig"); pub const arc = @import("Target/arc.zig"); pub const arm = @import("Target/arm.zig"); @@ -740,10 +741,12 @@ pub const avr = @import("Target/avr.zig"); pub const bpf = @import("Target/bpf.zig"); pub const csky = @import("Target/csky.zig"); pub const hexagon = @import("Target/hexagon.zig"); +pub const hppa = @import("Target/generic.zig"); pub const kalimba = @import("Target/generic.zig"); pub const lanai = @import("Target/lanai.zig"); pub const loongarch = @import("Target/loongarch.zig"); pub const m68k = @import("Target/m68k.zig"); +pub const microblaze = @import("Target/generic.zig"); pub const mips = @import("Target/mips.zig"); pub const msp430 = @import("Target/msp430.zig"); pub const nvptx = @import("Target/nvptx.zig"); @@ -752,6 +755,7 @@ pub const powerpc = @import("Target/powerpc.zig"); pub const propeller = @import("Target/propeller.zig"); pub const riscv = @import("Target/riscv.zig"); pub const s390x = @import("Target/s390x.zig"); +pub const sh = @import("Target/generic.zig"); pub const sparc = @import("Target/sparc.zig"); pub const spirv = @import("Target/spirv.zig"); pub const ve = @import("Target/ve.zig"); @@ -826,10 +830,13 @@ pub const Abi = enum { .arm, .armeb, .csky, + .hppa, .mips, .mipsel, .powerpc, .powerpcle, + .sh, + .sheb, .thumb, .thumbeb, => .eabi, @@ -864,6 +871,10 @@ pub const Abi = enum { => .gnu, .csky, => .gnueabi, + .hppa, + .sh, + .sheb, + => .gnueabihf, // No glibc or musl support. .xtensa, @@ -1064,6 +1075,7 @@ pub const ObjectFormat = enum { pub fn toElfMachine(target: *const Target) std.elf.EM { return switch (target.cpu.arch) { .aarch64, .aarch64_be => .AARCH64, + .alpha => .ALPHA, .amdgcn => .AMDGPU, .arc, .arceb => .ARC_COMPACT, .arm, .armeb, .thumb, .thumbeb => .ARM, @@ -1071,10 +1083,12 @@ pub fn toElfMachine(target: *const Target) std.elf.EM { .bpfeb, .bpfel => .BPF, .csky => .CSKY, .hexagon => .QDSP6, + .hppa, .hppa64 => .PARISC, .kalimba => .CSR_KALIMBA, .lanai => .LANAI, .loongarch32, .loongarch64 => .LOONGARCH, .m68k => .@"68K", + .microblaze, .microblazeel => .MICROBLAZE, .mips, .mips64, .mipsel, .mips64el => .MIPS, .msp430 => .MSP430, .or1k => .OR1K, @@ -1083,6 +1097,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM { .propeller => .PROPELLER, .riscv32, .riscv32be, .riscv64, .riscv64be => .RISCV, .s390x => .S390, + .sh, .sheb => .SH, .sparc => if (target.cpu.has(.sparc, .v9)) .SPARC32PLUS else .SPARC, .sparc64 => .SPARCV9, .ve => .VE, @@ -1103,6 +1118,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM { pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { return switch (target.cpu.arch) { + .alpha => .ALPHA64, .arm => .ARM, .thumb => .ARMNT, .aarch64 => .ARM64, @@ -1114,6 +1130,7 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .powerpcle => .POWERPC, .riscv32 => .RISCV32, .riscv64 => .RISCV64, + .sh => .SH3, .x86 => .I386, .x86_64 => .AMD64, @@ -1127,9 +1144,13 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .bpfel, .csky, .hexagon, + .hppa, + .hppa64, .kalimba, .lanai, .m68k, + .microblaze, + .microblazeel, .mips64, .msp430, .nvptx, @@ -1142,6 +1163,7 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .riscv32be, .riscv64be, .s390x, + .sheb, .sparc, .sparc64, .spirv32, @@ -1323,6 +1345,7 @@ pub const Cpu = struct { pub const Arch = enum { aarch64, aarch64_be, + alpha, amdgcn, arc, arceb, @@ -1333,11 +1356,15 @@ pub const Cpu = struct { bpfel, csky, hexagon, + hppa, + hppa64, kalimba, lanai, loongarch32, loongarch64, m68k, + microblaze, + microblazeel, mips, mipsel, mips64, @@ -1356,6 +1383,8 @@ pub const Cpu = struct { riscv64, riscv64be, s390x, + sh, + sheb, sparc, sparc64, spirv32, @@ -1393,18 +1422,21 @@ pub const Cpu = struct { /// For a given family tag, it is guaranteed that an `std.Target.` namespace exists /// containing CPU model and feature data. pub const Family = enum { + aarch64, + alpha, amdgcn, arc, arm, - aarch64, avr, bpf, csky, hexagon, + hppa, kalimba, lanai, loongarch, m68k, + microblaze, mips, msp430, nvptx, @@ -1413,6 +1445,7 @@ pub const Cpu = struct { propeller, riscv, s390x, + sh, sparc, spirv, ve, @@ -1425,6 +1458,7 @@ pub const Cpu = struct { pub inline fn family(arch: Arch) Family { return switch (arch) { .aarch64, .aarch64_be => .aarch64, + .alpha => .alpha, .amdgcn => .amdgcn, .arc, .arceb => .arc, .arm, .armeb, .thumb, .thumbeb => .arm, @@ -1432,10 +1466,12 @@ pub const Cpu = struct { .bpfeb, .bpfel => .bpf, .csky => .csky, .hexagon => .hexagon, + .hppa, .hppa64 => .hppa, .kalimba => .kalimba, .lanai => .lanai, .loongarch32, .loongarch64 => .loongarch, .m68k => .m68k, + .microblaze, .microblazeel => .microblaze, .mips, .mipsel, .mips64, .mips64el => .mips, .msp430 => .msp430, .or1k => .or1k, @@ -1444,6 +1480,7 @@ pub const Cpu = struct { .propeller => .propeller, .riscv32, .riscv32be, .riscv64, .riscv64be => .riscv, .s390x => .s390x, + .sh, .sheb => .sh, .sparc, .sparc64 => .sparc, .spirv32, .spirv64 => .spirv, .ve => .ve, @@ -1490,6 +1527,13 @@ pub const Cpu = struct { }; } + pub inline fn isHppa(arch: Arch) bool { + return switch (arch) { + .hppa, .hppa64 => true, + else => false, + }; + } + pub inline fn isWasm(arch: Arch) bool { return switch (arch) { .wasm32, .wasm64 => true, @@ -1522,6 +1566,13 @@ pub const Cpu = struct { }; } + pub inline fn isMicroblaze(arch: Arch) bool { + return switch (arch) { + .microblaze, .microblazeel => true, + else => false, + }; + } + pub inline fn isMIPS(arch: Arch) bool { return arch.isMIPS32() or arch.isMIPS64(); } @@ -1572,6 +1623,13 @@ pub const Cpu = struct { }; } + pub inline fn isSh(arch: Arch) bool { + return switch (arch) { + .sh, .sheb => true, + else => false, + }; + } + pub inline fn isBpf(arch: Arch) bool { return switch (arch) { .bpfel, .bpfeb => true, @@ -1605,6 +1663,7 @@ pub const Cpu = struct { pub fn endian(arch: Arch) std.builtin.Endian { return switch (arch) { .aarch64, + .alpha, .arm, .arc, .avr, @@ -1614,6 +1673,7 @@ pub const Cpu = struct { .kalimba, .loongarch32, .loongarch64, + .microblazeel, .mipsel, .mips64el, .msp430, @@ -1622,6 +1682,7 @@ pub const Cpu = struct { .propeller, .riscv32, .riscv64, + .sh, .thumb, .ve, .wasm32, @@ -1636,8 +1697,11 @@ pub const Cpu = struct { .arceb, .armeb, .bpfeb, + .hppa, + .hppa64, .lanai, .m68k, + .microblaze, .mips, .mips64, .or1k, @@ -1646,6 +1710,7 @@ pub const Cpu = struct { .riscv32be, .riscv64be, .s390x, + .sheb, .thumbeb, .sparc, .sparc64, @@ -1748,6 +1813,9 @@ pub const Cpu = struct { .aarch64_vfabi_sve, => &.{ .aarch64, .aarch64_be }, + .alpha_osf, + => &.{.alpha}, + .arm_aapcs, .arm_aapcs_vfp, .arm_interrupt, @@ -1813,6 +1881,12 @@ pub const Cpu = struct { .hexagon_sysv_hvx, => &.{.hexagon}, + .hppa_elf, + => &.{.hppa}, + + .hppa64_elf, + => &.{.hppa64}, + .lanai_sysv, => &.{.lanai}, @@ -1828,6 +1902,9 @@ pub const Cpu = struct { .m68k_interrupt, => &.{.m68k}, + .microblaze_std, + => &.{ .microblaze, .microblazeel }, + .msp430_eabi, => &.{.msp430}, @@ -1841,6 +1918,10 @@ pub const Cpu = struct { .s390x_sysv_vx, => &.{.s390x}, + .sh_gnu, + .sh_renesas, + => &.{ .sh, .sheb }, + .ve_sysv, => &.{.ve}, @@ -2384,6 +2465,8 @@ pub const DynamicLinker = struct { .aarch64_be, .hexagon, .m68k, + .microblaze, + .microblazeel, .powerpc64, .powerpc64le, .s390x, @@ -2419,6 +2502,17 @@ pub const DynamicLinker = struct { else => return none, }}), + .sh, + .sheb, + => |arch| initFmt("/lib/ld-musl-{t}{s}.so.1", .{ + arch, + switch (abi) { + .musleabi => "-nofpu", + .musleabihf => "", + else => return none, + }, + }), + .riscv32, .riscv64, => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}{s}.so.1", .{ @@ -2432,6 +2526,7 @@ pub const DynamicLinker = struct { }) else none, .x86 => if (abi == .musl) init("/lib/ld-musl-i386.so.1") else none, + .x86_64 => initFmt("/lib/ld-musl-{s}.so.1", .{switch (abi) { .musl => "x86_64", .muslx32 => "x32", @@ -2475,7 +2570,10 @@ pub const DynamicLinker = struct { else => return none, }}), + .hppa, .m68k, + .microblaze, + .microblazeel, .xtensa, .xtensaeb, => if (abi == .gnu) init("/lib/ld.so.1") else none, @@ -2531,10 +2629,22 @@ pub const DynamicLinker = struct { .s390x => if (abi == .gnu) init("/lib/ld64.so.1") else none, - .sparc => if (abi == .gnu) init("/lib/ld-linux.so.2") else none, + .sh, + .sheb, + => switch (abi) { + .gnueabi, + .gnueabihf, + => init("/lib/ld-linux.so.2"), + else => none, + }, + + .alpha, + .sparc, + .x86, + => if (abi == .gnu) init("/lib/ld-linux.so.2") else none, + .sparc64 => if (abi == .gnu) init("/lib64/ld-linux.so.2") else none, - .x86 => if (abi == .gnu) init("/lib/ld-linux.so.2") else none, .x86_64 => switch (abi) { .gnu => init("/lib64/ld-linux-x86-64.so.2"), .gnux32 => init("/libx32/ld-linux-x32.so.2"), @@ -2712,10 +2822,13 @@ pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 { .armeb, .csky, .hexagon, + .hppa, .kalimba, .lanai, .loongarch32, .m68k, + .microblaze, + .microblazeel, .mips, .mipsel, .nvptx, @@ -2725,6 +2838,8 @@ pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 { .propeller, .riscv32, .riscv32be, + .sh, + .sheb, .sparc, .spirv32, .thumb, @@ -2738,9 +2853,11 @@ pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 { .aarch64, .aarch64_be, + .alpha, .amdgcn, .bpfeb, .bpfel, + .hppa64, .loongarch64, .mips64, .mips64el, @@ -2772,17 +2889,20 @@ pub fn stackAlignment(target: *const Target) u16 { => return 4, .arm, .armeb, - .thumb, - .thumbeb, + .hppa, .lanai, .mips, .mipsel, .sparc, + .thumb, + .thumbeb, => return 8, .aarch64, .aarch64_be, + .alpha, .bpfeb, .bpfel, + .hppa64, .loongarch32, .loongarch64, .mips64, @@ -2950,6 +3070,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { else => return 128, }, + .alpha, .riscv32, .riscv32be, .riscv64, @@ -3059,6 +3180,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { }, }, + .alpha, .riscv32, .riscv32be, .riscv64, @@ -3251,8 +3373,12 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { .arceb, .csky, .kalimba, + .microblaze, + .microblazeel, .or1k, .propeller, + .sh, + .sheb, .x86, .xcore, .xtensa, @@ -3265,6 +3391,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { .bpfeb, .bpfel, .hexagon, + .hppa, .lanai, .m68k, .mips, @@ -3279,6 +3406,8 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { .aarch64, .aarch64_be, + .alpha, + .hppa64, .loongarch32, .loongarch64, .mips64, @@ -3351,8 +3480,12 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { .arceb, .csky, .kalimba, + .microblaze, + .microblazeel, .or1k, .propeller, + .sh, + .sheb, .xcore, .xtensa, .xtensaeb, @@ -3364,6 +3497,7 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { .bpfeb, .bpfel, .hexagon, + .hppa, .lanai, .m68k, .mips, @@ -3379,6 +3513,8 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { .aarch64, .aarch64_be, + .alpha, + .hppa64, .loongarch32, .loongarch64, .mips64, @@ -3416,14 +3552,19 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .arceb, .csky, .kalimba, + .microblaze, + .microblazeel, .or1k, .propeller, + .sh, + .sheb, .xcore, => 4, .arm, .armeb, .hexagon, + .hppa, .lanai, .loongarch32, .m68k, @@ -3444,9 +3585,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .aarch64, .aarch64_be, + .alpha, .amdgcn, .bpfel, .bpfeb, + .hppa64, .loongarch64, .mips64, .mips64el, @@ -3483,6 +3626,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .windows => .{ .aarch64_aapcs_win = .{} }, else => .{ .aarch64_aapcs = .{} }, }, + .alpha => .{ .alpha_osf = .{} }, .arm, .armeb, .thumb, .thumbeb => switch (target.abi.float()) { .soft => .{ .arm_aapcs = .{} }, .hard => .{ .arm_aapcs_vfp = .{} }, @@ -3511,6 +3655,8 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .bpfel, .bpfeb => .{ .bpf_std = .{} }, .csky => .{ .csky_sysv = .{} }, .hexagon => .{ .hexagon_sysv = .{} }, + .hppa => .{ .hppa_elf = .{} }, + .hppa64 => .{ .hppa64_elf = .{} }, .kalimba => null, .lanai => .{ .lanai_sysv = .{} }, .loongarch64 => .{ .loongarch64_lp64 = .{} }, @@ -3519,10 +3665,12 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .{ .m68k_gnu = .{} } else .{ .m68k_sysv = .{} }, + .microblaze, .microblazeel => .{ .microblaze_std = .{} }, .msp430 => .{ .msp430_eabi = .{} }, .or1k => .{ .or1k_sysv = .{} }, .propeller => .{ .propeller_sysv = .{} }, .s390x => .{ .s390x_sysv = .{} }, + .sh, .sheb => .{ .sh_gnu = .{} }, .ve => .{ .ve_sysv = .{} }, .xcore => .{ .xcore_xs1 = .{} }, .xtensa, .xtensaeb => .{ .xtensa_windowed = .{} }, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index d889e168a2b6..ed4a39b8bb59 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -229,6 +229,9 @@ pub const CallingConvention = union(enum(u8)) { aarch64_vfabi: CommonOptions, aarch64_vfabi_sve: CommonOptions, + /// The standard `alpha` calling convention. + alpha_osf: CommonOptions, + // Calling convetions for the `arm`, `armeb`, `thumb`, and `thumbeb` architectures. /// ARM Architecture Procedure Call Standard arm_aapcs: CommonOptions, @@ -296,6 +299,12 @@ pub const CallingConvention = union(enum(u8)) { hexagon_sysv: CommonOptions, hexagon_sysv_hvx: CommonOptions, + /// The standard `hppa` calling convention. + hppa_elf: CommonOptions, + + /// The standard `hppa64` calling convention. + hppa64_elf: CommonOptions, + /// The standard `lanai` calling convention. lanai_sysv: CommonOptions, @@ -311,6 +320,9 @@ pub const CallingConvention = union(enum(u8)) { m68k_rtd: CommonOptions, m68k_interrupt: CommonOptions, + /// The standard `microblaze`/`microblazeel` calling convention. + microblaze_std: CommonOptions, + /// The standard `msp430` calling convention. msp430_eabi: CommonOptions, @@ -324,6 +336,10 @@ pub const CallingConvention = union(enum(u8)) { s390x_sysv: CommonOptions, s390x_sysv_vx: CommonOptions, + // Calling conventions for the `sh`/`sheb` architecture. + sh_gnu: CommonOptions, + sh_renesas: CommonOptions, + /// The standard `ve` calling convention. ve_sysv: CommonOptions, @@ -858,6 +874,13 @@ pub const VaListAarch64 = extern struct { __vr_offs: c_int, }; +/// This data structure is used by the Zig language code generation and +/// therefore must be kept in sync with the compiler implementation. +pub const VaListAlpha = extern struct { + __base: *anyopaque, + __offset: c_int, +}; + /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const VaListArm = extern struct { @@ -891,6 +914,16 @@ pub const VaListS390x = extern struct { __overflow_area_pointer: *anyopaque, }; +/// This data structure is used by the Zig language code generation and +/// therefore must be kept in sync with the compiler implementation. +pub const VaListSh = extern struct { + __va_next_o: *anyopaque, + __va_next_o_limit: *anyopaque, + __va_next_fp: *anyopaque, + __va_next_fp_limit: *anyopaque, + __va_next_stack: *anyopaque, +}; + /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const VaListX86_64 = extern struct { @@ -925,10 +958,14 @@ pub const VaList = switch (builtin.cpu.arch) { .bpfel, .bpfeb, .csky, + .hppa, + .hppa64, .lanai, .loongarch32, .loongarch64, .m68k, + .microblaze, + .microblazeel, .mips, .mipsel, .mips64, @@ -953,6 +990,7 @@ pub const VaList = switch (builtin.cpu.arch) { .stage2_llvm => @compileError("disabled due to miscompilations"), }, }, + .alpha => VaListAlpha, .arm, .armeb, .thumb, .thumbeb => VaListArm, .hexagon => if (builtin.target.abi.isMusl()) VaListHexagon else *u8, .powerpc, .powerpcle => switch (builtin.os.tag) { @@ -960,6 +998,7 @@ pub const VaList = switch (builtin.cpu.arch) { else => VaListPowerPc, }, .s390x => VaListS390x, + .sh, .sheb => VaListSh, // This is wrong for `sh_renesas`: https://github.com/ziglang/zig/issues/24692#issuecomment-3150779829 .x86_64 => switch (builtin.os.tag) { .uefi, .windows => switch (builtin.zig_backend) { else => *u8, diff --git a/lib/std/builtin/assembly.zig b/lib/std/builtin/assembly.zig index 773b8e587ad0..12a0757ebfa8 100644 --- a/lib/std/builtin/assembly.zig +++ b/lib/std/builtin/assembly.zig @@ -2197,6 +2197,321 @@ pub const Clobbers = switch (@import("builtin").cpu.arch) { msa_map: bool = false, msa_unmap: bool = false, }, + .alpha => packed struct { + /// Whether the inline assembly code may perform stores to memory + /// addresses other than those derived from input pointer provenance. + memory: bool = false, + + r0: bool = false, + r1: bool = false, + r2: bool = false, + r3: bool = false, + r4: bool = false, + r5: bool = false, + r6: bool = false, + r7: bool = false, + r8: bool = false, + r9: bool = false, + r10: bool = false, + r11: bool = false, + r12: bool = false, + r13: bool = false, + r14: bool = false, + r15: bool = false, + r16: bool = false, + r17: bool = false, + r18: bool = false, + r19: bool = false, + r20: bool = false, + r21: bool = false, + r22: bool = false, + r23: bool = false, + r24: bool = false, + r25: bool = false, + r26: bool = false, + r27: bool = false, + r28: bool = false, + r29: bool = false, + r30: bool = false, + + f0: bool = false, + f1: bool = false, + f2: bool = false, + f3: bool = false, + f4: bool = false, + f5: bool = false, + f6: bool = false, + f7: bool = false, + f8: bool = false, + f9: bool = false, + f10: bool = false, + f11: bool = false, + f12: bool = false, + f13: bool = false, + f14: bool = false, + f15: bool = false, + f16: bool = false, + f17: bool = false, + f18: bool = false, + f19: bool = false, + f20: bool = false, + f21: bool = false, + f22: bool = false, + f23: bool = false, + f24: bool = false, + f25: bool = false, + f26: bool = false, + f27: bool = false, + f28: bool = false, + f29: bool = false, + f30: bool = false, + }, + .hppa, .hppa64 => packed struct { + /// Whether the inline assembly code may perform stores to memory + /// addresses other than those derived from input pointer provenance. + memory: bool = false, + + sar: bool = false, + + r1: bool = false, + r2: bool = false, + r3: bool = false, + r4: bool = false, + r5: bool = false, + r6: bool = false, + r7: bool = false, + r8: bool = false, + r9: bool = false, + r10: bool = false, + r11: bool = false, + r12: bool = false, + r13: bool = false, + r14: bool = false, + r15: bool = false, + r16: bool = false, + r17: bool = false, + r18: bool = false, + r19: bool = false, + r20: bool = false, + r21: bool = false, + r22: bool = false, + r23: bool = false, + r24: bool = false, + r25: bool = false, + r26: bool = false, + r27: bool = false, + r28: bool = false, + r29: bool = false, + r30: bool = false, + r31: bool = false, + + fr4: bool = false, + fr5: bool = false, + fr6: bool = false, + fr7: bool = false, + fr8: bool = false, + fr9: bool = false, + fr10: bool = false, + fr11: bool = false, + fr12: bool = false, + fr13: bool = false, + fr14: bool = false, + fr15: bool = false, + fr16: bool = false, + fr17: bool = false, + fr18: bool = false, + fr19: bool = false, + fr20: bool = false, + fr21: bool = false, + fr22: bool = false, + fr23: bool = false, + fr24: bool = false, + fr25: bool = false, + fr26: bool = false, + fr27: bool = false, + fr28: bool = false, + fr29: bool = false, + fr30: bool = false, + fr31: bool = false, + + fr4r: bool = false, + fr5r: bool = false, + fr6r: bool = false, + fr7r: bool = false, + fr8r: bool = false, + fr9r: bool = false, + fr10r: bool = false, + fr11r: bool = false, + fr12r: bool = false, + fr13r: bool = false, + fr14r: bool = false, + fr15r: bool = false, + fr16r: bool = false, + fr17r: bool = false, + fr18r: bool = false, + fr19r: bool = false, + fr20r: bool = false, + fr21r: bool = false, + fr22r: bool = false, + fr23r: bool = false, + fr24r: bool = false, + fr25r: bool = false, + fr26r: bool = false, + fr27r: bool = false, + fr28r: bool = false, + fr29r: bool = false, + fr30r: bool = false, + fr31r: bool = false, + }, + .microblaze, .microblazeel => packed struct { + /// Whether the inline assembly code may perform stores to memory + /// addresses other than those derived from input pointer provenance. + memory: bool = false, + + rmsr: bool = false, + + r1: bool = false, + r2: bool = false, + r3: bool = false, + r4: bool = false, + r5: bool = false, + r6: bool = false, + r7: bool = false, + r8: bool = false, + r9: bool = false, + r10: bool = false, + r11: bool = false, + r12: bool = false, + r13: bool = false, + r14: bool = false, + r15: bool = false, + r16: bool = false, + r17: bool = false, + r18: bool = false, + r19: bool = false, + r20: bool = false, + r21: bool = false, + r22: bool = false, + r23: bool = false, + r24: bool = false, + r25: bool = false, + r26: bool = false, + r27: bool = false, + r28: bool = false, + r29: bool = false, + r30: bool = false, + r31: bool = false, + }, + .sh, .sheb => packed struct { + /// Whether the inline assembly code may perform stores to memory + /// addresses other than those derived from input pointer provenance. + memory: bool = false, + + sr: bool = false, + gbr: bool = false, + pr: bool = false, + + r0: bool = false, + r1: bool = false, + r2: bool = false, + r3: bool = false, + r4: bool = false, + r5: bool = false, + r6: bool = false, + r7: bool = false, + r8: bool = false, + r9: bool = false, + r10: bool = false, + r11: bool = false, + r12: bool = false, + r13: bool = false, + r14: bool = false, + r15: bool = false, + + mach: bool = false, + macl: bool = false, + + fr0: bool = false, + fr1: bool = false, + fr2: bool = false, + fr3: bool = false, + fr4: bool = false, + fr5: bool = false, + fr6: bool = false, + fr7: bool = false, + fr8: bool = false, + fr9: bool = false, + fr10: bool = false, + fr11: bool = false, + fr12: bool = false, + fr13: bool = false, + fr14: bool = false, + fr15: bool = false, + + dr0: bool = false, + dr2: bool = false, + dr4: bool = false, + dr6: bool = false, + dr8: bool = false, + dr10: bool = false, + dr12: bool = false, + dr14: bool = false, + + fv0: bool = false, + fv4: bool = false, + fv8: bool = false, + fv12: bool = false, + + xf0: bool = false, + xf1: bool = false, + xf2: bool = false, + xf3: bool = false, + xf4: bool = false, + xf5: bool = false, + xf6: bool = false, + xf7: bool = false, + xf8: bool = false, + xf9: bool = false, + xf10: bool = false, + xf11: bool = false, + xf12: bool = false, + xf13: bool = false, + xf14: bool = false, + xf15: bool = false, + + xd0: bool = false, + xd2: bool = false, + xd4: bool = false, + xd6: bool = false, + xd8: bool = false, + xd10: bool = false, + xd12: bool = false, + xd14: bool = false, + + xmtrx: bool = false, + + fpul: bool = false, + fpscr: bool = false, + + ms: bool = false, + me: bool = false, + + rs: bool = false, + re: bool = false, + + a0: bool = false, + a0g: bool = false, + a1: bool = false, + a1g: bool = false, + m0: bool = false, + m1: bool = false, + x0: bool = false, + x1: bool = false, + y0: bool = false, + y1: bool = false, + + dsr: bool = false, + }, else => packed struct { /// Whether the inline assembly code may perform stores to memory /// addresses other than those derived from input pointer provenance. diff --git a/src/Sema.zig b/src/Sema.zig index 3361d1a59cea..be4b777eebeb 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9043,8 +9043,10 @@ const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention .aarch64_aapcs_win, .aarch64_vfabi, .aarch64_vfabi_sve, + .alpha_osf, .arm_aapcs, .arm_aapcs_vfp, + .microblaze_std, .mips64_n64, .mips64_n32, .mips_o32, @@ -9068,6 +9070,8 @@ const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention .csky_sysv, .hexagon_sysv, .hexagon_sysv_hvx, + .hppa_elf, + .hppa64_elf, .lanai_sysv, .loongarch64_lp64, .loongarch32_ilp32, @@ -9078,6 +9082,8 @@ const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention .or1k_sysv, .s390x_sysv, .s390x_sysv_vx, + .sh_gnu, + .sh_renesas, .ve_sysv, .xcore_xs1, .xcore_xs2, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index bf9be70529f1..cf0519e1f108 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -8106,6 +8106,8 @@ fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")", }, + .sh_renesas => "renesas", + .m68k_rtd => "m68k_rtd", .avr_interrupt, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b922ae070474..8c6f5f973f8f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -106,10 +106,17 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 .wasm64 => "wasm64", .ve => "ve", + .alpha, .arceb, + .hppa, + .hppa64, .kalimba, + .microblaze, + .microblazeel, .or1k, .propeller, + .sh, + .sheb, .xtensaeb, => unreachable, // Gated by hasLlvmSupport(). }; @@ -475,10 +482,17 @@ pub fn dataLayout(target: *const std.Target) []const u8 { .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32", + .alpha, .arceb, + .hppa, + .hppa64, .kalimba, + .microblaze, + .microblazeel, .or1k, .propeller, + .sh, + .sheb, .xtensaeb, => unreachable, // Gated by hasLlvmSupport(). }; @@ -11908,6 +11922,8 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win, + .alpha_osf, + .microblaze_std, .mips64_n64, .mips64_n32, .mips_o32, @@ -11930,6 +11946,8 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s .csky_sysv, .hexagon_sysv, .hexagon_sysv_hvx, + .hppa_elf, + .hppa64_elf, .lanai_sysv, .loongarch64_lp64, .loongarch32_ilp32, @@ -11940,6 +11958,8 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s .propeller_sysv, .s390x_sysv, .s390x_sysv_vx, + .sh_gnu, + .sh_renesas, .ve_sysv, .xcore_xs1, .xcore_xs2, @@ -13111,10 +13131,17 @@ pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { }, // LLVM does does not have a backend for these. + .alpha, .arceb, + .hppa, + .hppa64, .kalimba, + .microblaze, + .microblazeel, .or1k, .propeller, + .sh, + .sheb, .xtensaeb, => unreachable, } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index a9cfefa2c4ac..2ecac73c1c80 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3905,6 +3905,8 @@ fn updateLazyType( .m68k_rtd => .LLVM_M68kRTD, + .sh_renesas => .GNU_renesas_sh, + .amdgcn_kernel => .LLVM_OpenCLKernel, .nvptx_kernel, .spirv_kernel, diff --git a/src/target.zig b/src/target.zig index a5de66a68dcc..bd0708b3d8fa 100644 --- a/src/target.zig +++ b/src/target.zig @@ -216,10 +216,17 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat) => false, // No LLVM backend exists. + .alpha, .arceb, + .hppa, + .hppa64, .kalimba, + .microblaze, + .microblazeel, .or1k, .propeller, + .sh, + .sheb, .xtensaeb, => false, }; @@ -709,19 +716,26 @@ pub fn minFunctionAlignment(target: *const std.Target) Alignment { .csky, .m68k, .msp430, + .sh, + .sheb, .s390x, .xcore, => .@"2", + .aarch64, + .aarch64_be, + .alpha, .arc, .arceb, .arm, .armeb, - .aarch64, - .aarch64_be, .hexagon, + .hppa, + .hppa64, .lanai, .loongarch32, .loongarch64, + .microblaze, + .microblazeel, .mips, .mipsel, .powerpc, @@ -733,8 +747,8 @@ pub fn minFunctionAlignment(target: *const std.Target) Alignment { .xtensa, .xtensaeb, => .@"4", - .bpfel, .bpfeb, + .bpfel, .mips64, .mips64el, => .@"8", From a1441943e41014cfbce3105c4cdd9d3e0d137e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:44:36 +0200 Subject: [PATCH 14/43] std.Target: add stackGrowth() function --- lib/std/Target.zig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index d5caf8665968..20d37b893943 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -2930,6 +2930,24 @@ pub fn stackAlignment(target: *const Target) u16 { return @divExact(target.ptrBitWidth(), 8); } +pub const StackGrowth = enum { + down, + up, +}; + +pub fn stackGrowth(target: *const Target) StackGrowth { + // Strictly speaking, most architectures don't inherently define the stack growth direction; you + // could quite easily argue that it is in fact a property of the ABI. However, that's just not + // really how it plays out in the real world. And besides, we have no mechanism for indicating + // a different stack growth ABI, nor a compelling use case for creating such a mechanism. + return switch (target.cpu.arch) { + .hppa, + .hppa64, + => .up, + else => .down, + }; +} + /// Default signedness of `char` for the native C compiler for this target /// Note that char signedness is implementation-defined and many compilers provide /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char From beb507a1edadb2829478d066b80ea62ed537157a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 19 Oct 2025 22:40:15 +0200 Subject: [PATCH 15/43] std.builtin: add CallingConvention.x86_64_x32 This was forgotten during the refactoring of std.builtin.CallingConvention. It mirrors mips64_n32 for MIPS. --- lib/std/Target.zig | 6 +++++- lib/std/builtin.zig | 1 + src/Sema.zig | 1 + src/codegen/llvm.zig | 1 + test/cases/compile_errors/invalid_variadic_function.zig | 4 ++-- ...ify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig | 2 +- 6 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 20d37b893943..b99e2b366ed7 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1787,6 +1787,7 @@ pub const Cpu = struct { => unreachable, .x86_64_sysv, + .x86_64_x32, .x86_64_win, .x86_64_regcall_v3_sysv, .x86_64_regcall_v4_win, @@ -3632,7 +3633,10 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention return switch (target.cpu.arch) { .x86_64 => switch (target.os.tag) { .windows, .uefi => .{ .x86_64_win = .{} }, - else => .{ .x86_64_sysv = .{} }, + else => switch (target.abi) { + .gnuabin32, .muslabin32 => .{ .x86_64_x32 = .{} }, + else => .{ .x86_64_sysv = .{} }, + }, }, .x86 => switch (target.os.tag) { .windows, .uefi => .{ .x86_win = .{} }, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index ed4a39b8bb59..6feacbc8c89f 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -204,6 +204,7 @@ pub const CallingConvention = union(enum(u8)) { // Calling conventions for the `x86_64` architecture. x86_64_sysv: CommonOptions, + x86_64_x32: CommonOptions, x86_64_win: CommonOptions, x86_64_regcall_v3_sysv: CommonOptions, x86_64_regcall_v4_win: CommonOptions, diff --git a/src/Sema.zig b/src/Sema.zig index be4b777eebeb..47b533922288 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9035,6 +9035,7 @@ pub fn handleExternLibName( /// functions or there are no more other calling conventions that support variadic functions. const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention.Tag{ .x86_64_sysv, + .x86_64_x32, .x86_64_win, .x86_sysv, .x86_win, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 8c6f5f973f8f..3b3febf27e8f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -11919,6 +11919,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s .x86_sysv, .x86_win, .x86_thiscall_mingw, + .x86_64_x32, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win, diff --git a/test/cases/compile_errors/invalid_variadic_function.zig b/test/cases/compile_errors/invalid_variadic_function.zig index 08e1eb0148ea..a5f2c2f89324 100644 --- a/test/cases/compile_errors/invalid_variadic_function.zig +++ b/test/cases/compile_errors/invalid_variadic_function.zig @@ -12,6 +12,6 @@ comptime { // target=x86_64-linux // // :1:8: error: variadic function does not support 'auto' calling convention -// :1:8: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win' +// :1:8: note: supported calling conventions: 'x86_64_sysv', 'x86_64_x32', 'x86_64_win' // :2:16: error: variadic function does not support 'inline' calling convention -// :2:16: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win' +// :2:16: note: supported calling conventions: 'x86_64_sysv', 'x86_64_x32', 'x86_64_win' diff --git a/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig b/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig index e72dc41b6ea8..f74b89ae8719 100644 --- a/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig +++ b/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig @@ -15,4 +15,4 @@ comptime { // target=x86_64-linux // // :1:13: error: variadic function does not support 'auto' calling convention -// :1:13: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win' +// :1:13: note: supported calling conventions: 'x86_64_sysv', 'x86_64_x32', 'x86_64_win' From abf40caeb7d85d8fc842fe82215b19902b749481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 18:37:13 +0200 Subject: [PATCH 16/43] std.builtin: add CallingConvention.msp430_interrupt Supported by LLVM and CBE. --- lib/std/Target.zig | 1 + lib/std/builtin.zig | 1 + src/Sema.zig | 3 +++ src/Zcu.zig | 1 + src/codegen/c.zig | 1 + src/codegen/llvm.zig | 1 + src/link/Dwarf.zig | 1 + 7 files changed, 9 insertions(+) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index b99e2b366ed7..257113f477c9 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1907,6 +1907,7 @@ pub const Cpu = struct { => &.{ .microblaze, .microblazeel }, .msp430_eabi, + .msp430_interrupt, => &.{.msp430}, .or1k_sysv, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 6feacbc8c89f..84b228d68511 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -326,6 +326,7 @@ pub const CallingConvention = union(enum(u8)) { /// The standard `msp430` calling convention. msp430_eabi: CommonOptions, + msp430_interrupt: CommonOptions, /// The standard `or1k` calling convention. or1k_sysv: CommonOptions, diff --git a/src/Sema.zig b/src/Sema.zig index 47b533922288..62e6942a5b2f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9137,6 +9137,7 @@ fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool { .m68k_interrupt, .mips_interrupt, .mips64_interrupt, + .msp430_interrupt, .riscv32_interrupt, .riscv64_interrupt, .x86_interrupt, @@ -9301,6 +9302,7 @@ fn funcCommon( .avr_interrupt, .csky_interrupt, .m68k_interrupt, + .msp430_interrupt, .avr_signal, => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}), else => {}, @@ -9528,6 +9530,7 @@ fn finishFunc( .avr_interrupt, .csky_interrupt, .m68k_interrupt, + .msp430_interrupt, .avr_signal, => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) { return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)}); diff --git a/src/Zcu.zig b/src/Zcu.zig index 6fa200561c42..9839db66591a 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4426,6 +4426,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu .riscv32_ilp32_v, .m68k_rtd, .m68k_interrupt, + .msp430_interrupt, => |opts| opts.incoming_stack_alignment == null, .arm_aapcs_vfp, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index cf0519e1f108..a47d03152085 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -8113,6 +8113,7 @@ fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 .avr_interrupt, .csky_interrupt, .m68k_interrupt, + .msp430_interrupt, .x86_interrupt, .x86_64_interrupt, => "interrupt", diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 3b3febf27e8f..9d2317888776 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -11900,6 +11900,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s .avr_interrupt => .avr_intrcc, .m68k_rtd => .m68k_rtdcc, .m68k_interrupt => .m68k_intrcc, + .msp430_interrupt => .msp430_intrcc, .amdgcn_kernel => .amdgpu_kernel, .amdgcn_cs => .amdgpu_cs, .nvptx_device => .ptx_device, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 2ecac73c1c80..cc440905f0e0 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3925,6 +3925,7 @@ fn updateLazyType( .avr_interrupt, .csky_interrupt, .m68k_interrupt, + .msp430_interrupt, => .normal, else => .nocall, From 4fa453ce20ceaee254a7d127a4a99be2260ec605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 19:47:51 +0200 Subject: [PATCH 17/43] std.builtin: add CallingConvention.microblaze_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 | 7 +++++++ src/codegen/llvm.zig | 2 ++ src/link/Dwarf.zig | 1 + 8 files changed, 49 insertions(+) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 257113f477c9..ebc3762bbcf0 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1904,6 +1904,7 @@ pub const Cpu = struct { => &.{.m68k}, .microblaze_std, + .microblaze_interrupt, => &.{ .microblaze, .microblazeel }, .msp430_eabi, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 84b228d68511..983358ceebca 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -323,6 +323,7 @@ pub const CallingConvention = union(enum(u8)) { /// The standard `microblaze`/`microblazeel` calling convention. microblaze_std: CommonOptions, + microblaze_interrupt: MicroblazeInterruptOptions, /// The standard `msp430` calling convention. msp430_eabi: CommonOptions, @@ -421,6 +422,25 @@ pub const CallingConvention = union(enum(u8)) { }; }; + /// Options for the `microblaze_interrupt` calling convention. + pub const MicroblazeInterruptOptions = 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, + type: InterruptType = .regular, + + pub const InterruptType = enum(u2) { + /// User exception; return with `rtsd`. + user, + /// Regular interrupt; return with `rtid`. + regular, + /// Fast interrupt; return with `rtid`. + fast, + /// Software breakpoint; return with `rtbd`. + breakpoint, + }; + }; + /// Options for the `mips_interrupt` and `mips64_interrupt` calling conventions. pub const MipsInterruptOptions = struct { /// The boundary the stack is aligned to when the function is called. diff --git a/src/InternPool.zig b/src/InternPool.zig index 445245fbe912..05ca2ae2c757 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -12960,6 +12960,11 @@ const PackedCallingConvention = packed struct(u18) { .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), .extra = @intFromEnum(pl.type), }, + std.builtin.CallingConvention.MicroblazeInterruptOptions => .{ + .tag = tag, + .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), + .extra = @intFromEnum(pl.type), + }, std.builtin.CallingConvention.MipsInterruptOptions => .{ .tag = tag, .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), @@ -12997,6 +13002,10 @@ const PackedCallingConvention = packed struct(u18) { .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), .type = @enumFromInt(cc.extra), }, + std.builtin.CallingConvention.MicroblazeInterruptOptions => .{ + .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), + .type = @enumFromInt(cc.extra), + }, std.builtin.CallingConvention.MipsInterruptOptions => .{ .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), .mode = @enumFromInt(cc.extra), diff --git a/src/Sema.zig b/src/Sema.zig index 62e6942a5b2f..398fb7e5bb91 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9135,6 +9135,7 @@ fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool { .avr_signal, .csky_interrupt, .m68k_interrupt, + .microblaze_interrupt, .mips_interrupt, .mips64_interrupt, .msp430_interrupt, @@ -9295,6 +9296,7 @@ fn funcCommon( }, .arc_interrupt, .arm_interrupt, + .microblaze_interrupt, .mips64_interrupt, .mips_interrupt, .riscv64_interrupt, @@ -9530,6 +9532,7 @@ fn finishFunc( .avr_interrupt, .csky_interrupt, .m68k_interrupt, + .microblaze_interrupt, .msp430_interrupt, .avr_signal, => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) { @@ -30057,6 +30060,9 @@ fn callconvCoerceAllowed( std.builtin.CallingConvention.ArmInterruptOptions => { if (src_data.type != dest_data.type) return false; }, + std.builtin.CallingConvention.MicroblazeInterruptOptions => { + if (src_data.type != dest_data.type) return false; + }, std.builtin.CallingConvention.MipsInterruptOptions => { if (src_data.mode != dest_data.mode) return false; }, diff --git a/src/Zcu.zig b/src/Zcu.zig index 9839db66591a..539a45d72239 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4438,6 +4438,9 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu .arm_interrupt, => |opts| opts.incoming_stack_alignment == null, + .microblaze_interrupt, + => |opts| opts.incoming_stack_alignment == null, + .mips_interrupt, .mips64_interrupt, => |opts| opts.incoming_stack_alignment == null, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index a47d03152085..e531125a40ea 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -8092,6 +8092,13 @@ fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 .avr_signal => "signal", + .microblaze_interrupt => |opts| switch (opts.type) { + .user => "save_volatiles", + .regular => "interrupt_handler", + .fast => "fast_interrupt", + .breakpoint => "break_handler", + }, + .mips_interrupt, .mips64_interrupt, => |opts| switch (opts.mode) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 9d2317888776..0bda369deb8b 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.MicroblazeInterruptOptions, std.builtin.CallingConvention.MipsInterruptOptions, std.builtin.CallingConvention.CommonOptions, => .{ pl.incoming_stack_alignment, 0 }, @@ -11926,6 +11927,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s .aarch64_aapcs_win, .alpha_osf, .microblaze_std, + .microblaze_interrupt, .mips64_n64, .mips64_n32, .mips_o32, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index cc440905f0e0..da39a2fa4e98 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3925,6 +3925,7 @@ fn updateLazyType( .avr_interrupt, .csky_interrupt, .m68k_interrupt, + .microblaze_interrupt, .msp430_interrupt, => .normal, 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 18/43] 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 ebc3762bbcf0..2ed6b12c71b9 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 983358ceebca..46d367829723 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 05ca2ae2c757..a595fa502c0b 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 398fb7e5bb91..4872f47ac7c9 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 539a45d72239..0eb37668cf37 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 e531125a40ea..86669aea931d 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 0bda369deb8b..50fed0c2d457 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 da39a2fa4e98..e03517f97a2c 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, From 340d6ce1bf30556089bdefa60abf50f81617ceb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 21:33:24 +0200 Subject: [PATCH 19/43] std.builtin: move AddressSpace.Context to std.Target.AddressSpaceContext This type has nothing to do with the language. --- lib/std/Target.zig | 17 ++++++++++++++++- lib/std/builtin.zig | 15 --------------- src/Sema.zig | 6 +++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 2ed6b12c71b9..849a013f6982 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -2228,6 +2228,21 @@ pub fn requiresLibC(target: *const Target) bool { }; } +/// The places where a user can specify an address space attribute +pub const AddressSpaceContext = enum { + /// A function is specified to be placed in a certain address space. + function, + /// A (global) variable is specified to be placed in a certain address space. In contrast to + /// `.constant`, these values (and thus the address space they will be placed in) are required + /// to be mutable. + variable, + /// A (global) constant value is specified to be placed in a certain address space. In contrast + /// to `.variable`, values placed in this address space are not required to be mutable. + constant, + /// A pointer is ascripted to point into a certain address space. + pointer, +}; + /// Returns whether this target supports `address_space`. If `context` is `null`, this /// function simply answers the general question of whether the target has any concept /// of `address_space`; if non-`null`, the function additionally checks whether @@ -2235,7 +2250,7 @@ pub fn requiresLibC(target: *const Target) bool { pub fn supportsAddressSpace( target: Target, address_space: std.builtin.AddressSpace, - context: ?std.builtin.AddressSpace.Context, + context: ?AddressSpaceContext, ) bool { const arch = target.cpu.arch; diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 46d367829723..3e1413cd99e1 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -517,21 +517,6 @@ pub const CallingConvention = union(enum(u8)) { /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const AddressSpace = enum(u5) { - /// The places where a user can specify an address space attribute - pub const Context = enum { - /// A function is specified to be placed in a certain address space. - function, - /// A (global) variable is specified to be placed in a certain address space. - /// In contrast to .constant, these values (and thus the address space they will be - /// placed in) are required to be mutable. - variable, - /// A (global) constant value is specified to be placed in a certain address space. - /// In contrast to .variable, values placed in this address space are not required to be mutable. - constant, - /// A pointer is ascripted to point into a certain address space. - pointer, - }; - // CPU address spaces. generic, gs, diff --git a/src/Sema.zig b/src/Sema.zig index 4872f47ac7c9..9b086e201e69 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -36517,7 +36517,7 @@ fn resolveAddressSpace( block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, - ctx: std.builtin.AddressSpace.Context, + ctx: std.Target.AddressSpaceContext, ) !std.builtin.AddressSpace { const air_ref = try sema.resolveInst(zir_ref); return sema.analyzeAsAddressSpace(block, src, air_ref, ctx); @@ -36528,7 +36528,7 @@ pub fn analyzeAsAddressSpace( block: *Block, src: LazySrcLoc, air_ref: Air.Inst.Ref, - ctx: std.builtin.AddressSpace.Context, + ctx: std.Target.AddressSpaceContext, ) !std.builtin.AddressSpace { const pt = sema.pt; const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); @@ -37653,7 +37653,7 @@ pub fn resolveNavPtrModifiers( }; const @"addrspace": std.builtin.AddressSpace = as: { - const addrspace_ctx: std.builtin.AddressSpace.Context = switch (zir_decl.kind) { + const addrspace_ctx: std.Target.AddressSpaceContext = switch (zir_decl.kind) { .@"var" => .variable, else => switch (nav_ty.zigTypeTag(zcu)) { .@"fn" => .function, From 252e1fd7ecc037b129490af5eb5ca8fdfa6a20bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 23 Oct 2025 04:53:14 +0200 Subject: [PATCH 20/43] std.start: add alpha support --- lib/std/start.zig | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index 1f1aee060493..ab362a31954b 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -195,9 +195,10 @@ fn _start() callconv(.naked) noreturn { // This is the first userspace frame. Prevent DWARF-based unwinders from unwinding further. We // prevent FP-based unwinders from unwinding further by zeroing the register below. if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (switch (native_arch) { + .aarch64, .aarch64_be => ".cfi_undefined lr", + .alpha => ".cfi_undefined $26", .arc, .arceb => ".cfi_undefined blink", .arm, .armeb, .thumb, .thumbeb => "", // https://github.com/llvm/llvm-project/issues/115891 - .aarch64, .aarch64_be => ".cfi_undefined lr", .csky => ".cfi_undefined lr", .hexagon => ".cfi_undefined r31", .loongarch32, .loongarch64 => ".cfi_undefined 1", @@ -253,6 +254,18 @@ fn _start() callconv(.naked) noreturn { \\ and sp, x0, #-16 \\ b %[posixCallMainAndExit] , + .alpha => + // $15 = FP, $26 = LR, $29 = GP, $30 = SP + \\ br $29, 1f + \\1: + \\ ldgp $29, 0($29) + \\ mov 0, $15 + \\ mov 0, $26 + \\ mov $30, $16 + \\ ldi $1, -16 + \\ and $30, $30, $1 + \\ jsr $26, %[posixCallMainAndExit] + , .arc, .arceb => // ARC v1 and v2 had a very low stack alignment requirement of 4; v3 increased it to 16. \\ mov fp, 0 From c792ebfee2fab3ee9c633e7abc344d0e7535c983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 23 Oct 2025 07:24:24 +0200 Subject: [PATCH 21/43] std.start: add microblaze support --- lib/std/start.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/std/start.zig b/lib/std/start.zig index ab362a31954b..7e45bc42ea0d 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -203,6 +203,7 @@ fn _start() callconv(.naked) noreturn { .hexagon => ".cfi_undefined r31", .loongarch32, .loongarch64 => ".cfi_undefined 1", .m68k => ".cfi_undefined %%pc", + .microblaze, .microblazeel => ".cfi_undefined r15", .mips, .mipsel, .mips64, .mips64el => ".cfi_undefined $ra", .or1k => ".cfi_undefined r9", .powerpc, .powerpcle, .powerpc64, .powerpc64le => ".cfi_undefined lr", @@ -346,6 +347,16 @@ fn _start() callconv(.naked) noreturn { \\ lea %[posixCallMainAndExit] - . - 8, %%a0 \\ jsr (%%pc, %%a0) , + .microblaze, .microblazeel => + // r1 = SP, r15 = LR, r19 = FP, r20 = GP + \\ ori r15, r0, r0 + \\ ori r19, r0, r0 + \\ mfs r20, rpc + \\ addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8 + \\ ori r5, r1, r0 + \\ andi r1, r1, -4 + \\ brlid r15, %[posixCallMainAndExit] + , .mips, .mipsel => \\ move $fp, $zero \\ bal 1f From 4193ea8239264c7ee6891e9ef5ee756e13833fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 23 Oct 2025 06:18:22 +0200 Subject: [PATCH 22/43] std.start: add sh support --- lib/std/start.zig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/std/start.zig b/lib/std/start.zig index 7e45bc42ea0d..4cf2a0956b97 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -212,6 +212,7 @@ fn _start() callconv(.naked) noreturn { else ".cfi_undefined ra", .s390x => ".cfi_undefined %%r14", + .sh, .sheb => ".cfi_undefined pr", .sparc, .sparc64 => ".cfi_undefined %%i7", .x86 => ".cfi_undefined %%eip", .x86_64 => ".cfi_undefined %%rip", @@ -455,6 +456,21 @@ fn _start() callconv(.naked) noreturn { \\ stg %%r0, 0(%%r15) \\ jg %[posixCallMainAndExit] , + .sh, .sheb => + // r14 = FP, r15 = SP, pr = LR + \\ mov #0, r0 + \\ lds r0, pr + \\ mov r0, r14 + \\ mov r15, r4 + \\ mov #-4, r0 + \\ and r0, r15 + \\ mov.l 2f, r1 + \\1: + \\ bsrf r1 + \\2: + \\ .balign 4 + \\ .long %[posixCallMainAndExit]@PCREL - (1b + 4 - .) + , .sparc => // argc is stored after a register window (16 registers * 4 bytes). // i7 = LR From fc48f8aa553e3d0c03393d976e36f217099cab25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 05:07:14 +0200 Subject: [PATCH 23/43] std.pie: add alpha support --- lib/std/pie.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 395f03e449b6..365f9f498288 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -3,6 +3,7 @@ const builtin = @import("builtin"); const elf = std.elf; const assert = std.debug.assert; +const R_ALPHA_RELATIVE = 27; const R_AMD64_RELATIVE = 8; const R_386_RELATIVE = 8; const R_ARC_RELATIVE = 56; @@ -25,6 +26,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) { .arc, .arceb => R_ARC_RELATIVE, .arm, .armeb, .thumb, .thumbeb => R_ARM_RELATIVE, .aarch64, .aarch64_be => R_AARCH64_RELATIVE, + .alpha => R_ALPHA_RELATIVE, .csky => R_CSKY_RELATIVE, .hexagon => R_HEXAGON_RELATIVE, .loongarch32, .loongarch64 => R_LARCH_RELATIVE, @@ -83,6 +85,15 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ add %[ret], %[ret], #:lo12:_DYNAMIC : [ret] "=r" (-> [*]const elf.Dyn), ), + // The compiler is not required to load the GP register, so do it ourselves. + .alpha => asm volatile ( + \\ br $29, 1f + \\1: + \\ ldgp $29, 0($29) + \\ ldq %[ret], -0x8000($29) + : [ret] "=r" (-> [*]const elf.Dyn), + : + : .{ .r26 = true }), // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first // entry in the GOT is defined to hold the address of _DYNAMIC. .csky => asm volatile ( From fb2c02929e9325d2912d7d0bab1eb501b747c496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 23 Oct 2025 03:39:58 +0200 Subject: [PATCH 24/43] std.pie: add microblaze support --- lib/std/pie.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 365f9f498288..0fa2781f289f 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -13,6 +13,7 @@ const R_CSKY_RELATIVE = 9; const R_HEXAGON_RELATIVE = 35; const R_LARCH_RELATIVE = 3; const R_68K_RELATIVE = 22; +const R_MICROBLAZE_REL = 16; const R_MIPS_RELATIVE = 128; const R_OR1K_RELATIVE = 21; const R_PPC_RELATIVE = 22; @@ -31,6 +32,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) { .hexagon => R_HEXAGON_RELATIVE, .loongarch32, .loongarch64 => R_LARCH_RELATIVE, .m68k => R_68K_RELATIVE, + .microblaze, .microblazeel => R_MICROBLAZE_REL, .mips, .mipsel, .mips64, .mips64el => R_MIPS_RELATIVE, .or1k => R_OR1K_RELATIVE, .powerpc, .powerpcle, .powerpc64, .powerpc64le => R_PPC_RELATIVE, @@ -129,6 +131,10 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ lea (%[ret], %%pc), %[ret] : [ret] "=r" (-> [*]const elf.Dyn), ), + .microblaze, .microblazeel => asm volatile ( + \\ lwi %[ret], r20, 0 + : [ret] "=r" (-> [*]const elf.Dyn), + ), .mips, .mipsel => asm volatile ( \\ .weak _DYNAMIC \\ .hidden _DYNAMIC From 2b54437f243ef62a2e490350943bb313d5827639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 05:14:04 +0200 Subject: [PATCH 25/43] std.pie: add sh support --- lib/std/pie.zig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 0fa2781f289f..a37c03fbf260 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -19,6 +19,7 @@ const R_OR1K_RELATIVE = 21; const R_PPC_RELATIVE = 22; const R_RISCV_RELATIVE = 3; const R_390_RELATIVE = 12; +const R_SH_RELATIVE = 165; const R_SPARC_RELATIVE = 22; const R_RELATIVE = switch (builtin.cpu.arch) { @@ -38,6 +39,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) { .powerpc, .powerpcle, .powerpc64, .powerpc64le => R_PPC_RELATIVE, .riscv32, .riscv32be, .riscv64, .riscv64be => R_RISCV_RELATIVE, .s390x => R_390_RELATIVE, + .sh, .sheb => R_SH_RELATIVE, .sparc, .sparc64 => R_SPARC_RELATIVE, else => @compileError("Missing R_RELATIVE definition for this target"), }; @@ -223,6 +225,20 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ 2: : [ret] "=a" (-> [*]const elf.Dyn), ), + .sh, .sheb => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ mova 1f, r0 + \\ mov.l 1f, %[ret] + \\ add r0, %[ret] + \\ bra 2f + \\1: + \\ .balign 4 + \\ .long DYNAMIC - . + \\2: + : [ret] "=r" (-> [*]const elf.Dyn), + : + : .{ .r0 = true }), // The compiler does not necessarily have any obligation to load the `l7` register (pointing // to the GOT), so do it ourselves just in case. .sparc, .sparc64 => asm volatile ( From 9fde44229c30d6dbdc943af2a2c2cb82adf703f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 04:07:19 +0200 Subject: [PATCH 26/43] std.os.linux.tls: add alpha support --- lib/std/os/linux/tls.zig | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 62df828916a9..ba77e25788ee 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -63,12 +63,13 @@ const Variant = enum { }; const current_variant: Variant = switch (native_arch) { + .aarch64, + .aarch64_be, + .alpha, .arc, .arceb, .arm, .armeb, - .aarch64, - .aarch64_be, .csky, .thumb, .thumbeb, @@ -138,6 +139,7 @@ const AbiTcb = switch (current_variant) { // usual, while the second one is unspecified. .aarch64, .aarch64_be, + .alpha, .arm, .armeb, .thumb, @@ -244,6 +246,14 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr), ); }, + .alpha => { + asm volatile ( + \\ lda a0, %[addr] + \\ wruniq + : + : [addr] "r" (addr), + ); + }, .arc, .arceb => { // We apparently need to both set r25 (TP) *and* inform the kernel... asm volatile ( From 5e921261a08a9b27f95ce982e8a10b461520b922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 02:19:03 +0200 Subject: [PATCH 27/43] std.os.linux.tls: add microblaze support Implemented according to glibc because I'm pretty sure musl gets it wrong. --- lib/std/os/linux/tls.zig | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index ba77e25788ee..4d22824aa9b3 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -46,7 +46,7 @@ const Variant = enum { /// -------------------------------------^------------- /// `-- The TP register points here. /// - /// The offset (which can be zero) is applied to the TP only; there is never physical gap + /// The offset (which can be zero) is applied to the TP only; there is never a physical gap /// between the ABI TCB and the TLS blocks. This implies that we only need to align the TP. /// /// The first (and only) word in the ABI TCB points to the DTV. @@ -71,6 +71,8 @@ const current_variant: Variant = switch (native_arch) { .arm, .armeb, .csky, + .microblaze, + .microblazeel, .thumb, .thumbeb, => .I_original, @@ -135,19 +137,19 @@ const current_dtv_offset = switch (native_arch) { /// Per-thread storage for the ELF TLS ABI. const AbiTcb = switch (current_variant) { .I_original, .I_modified => switch (native_arch) { - // ARM EABI mandates enough space for two pointers: the first one points to the DTV as - // usual, while the second one is unspecified. .aarch64, .aarch64_be, .alpha, .arm, .armeb, + .microblaze, + .microblazeel, .thumb, .thumbeb, => extern struct { /// This is offset by `current_dtv_offset`. dtv: usize, - reserved: ?*anyopaque, + _reserved: ?*anyopaque, }, else => extern struct { /// This is offset by `current_dtv_offset`. @@ -297,6 +299,13 @@ pub fn setThreadPointer(addr: usize) void { const rc = @call(.always_inline, linux.syscall1, .{ .set_thread_area, addr }); assert(rc == 0); }, + .microblaze, .microblazeel => { + asm volatile ( + \\ ori r21, %[addr], 0 + : + : [addr] "r" (addr), + ); + }, .or1k => { asm volatile ( \\ l.ori r10, %[addr], 0 From aff557e4e81f88028e34fad8aa86f7361ef1632e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 03:50:09 +0200 Subject: [PATCH 28/43] std.os.linux.tls: add sh support --- lib/std/os/linux/tls.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 4d22824aa9b3..57ea18764ffb 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -73,6 +73,8 @@ const current_variant: Variant = switch (native_arch) { .csky, .microblaze, .microblazeel, + .sh, + .sheb, .thumb, .thumbeb, => .I_original, @@ -144,6 +146,8 @@ const AbiTcb = switch (current_variant) { .armeb, .microblaze, .microblazeel, + .sh, + .sheb, .thumb, .thumbeb, => extern struct { @@ -337,6 +341,13 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr), : .{ .r0 = true }); }, + .sh, .sheb => { + asm volatile ( + \\ ldc gbr, %[addr] + : + : [addr] "r" (addr), + ); + }, .sparc, .sparc64 => { asm volatile ( \\ mov %[addr], %%g7 From f723d69a5825221a87221d946d23d6b1093d70ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 04:26:27 +0200 Subject: [PATCH 29/43] std.os.linux.tls: add hppa support Turns out Linux on PA-RISC does system calls in a pretty fascinating way; see arch/parisc/kernel/syscall.S for details. --- lib/std/os/linux/tls.zig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 57ea18764ffb..3f3e6f987de5 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -71,6 +71,7 @@ const current_variant: Variant = switch (native_arch) { .arm, .armeb, .csky, + .hppa, .microblaze, .microblazeel, .sh, @@ -144,6 +145,7 @@ const AbiTcb = switch (current_variant) { .alpha, .arm, .armeb, + .hppa, .microblaze, .microblazeel, .sh, @@ -285,6 +287,13 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr), ); }, + .hppa => { + asm volatile ( + \\ ble 0xe0(%%sr2, %%r0) + : + : [addr] "={r26}" (addr), + : .{ .r29 = true }); + }, .loongarch32, .loongarch64 => { asm volatile ( \\ move $tp, %[addr] From 3d1b7811d4a09a5f7377c2d4122aab9217ded4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 17:59:00 +0200 Subject: [PATCH 30/43] std.Thread: implement freeAndExit() for m68k-linux --- lib/std/Thread.zig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index ce4abada7dec..049ea9e8b76e 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1247,6 +1247,18 @@ const LinuxThreadImpl = struct { : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), : .{ .memory = true }), + .m68k => asm volatile ( + \\ move.l #91, %%d0 // SYS_munmap + \\ move.l %[ptr], %%d1 + \\ move.l %[len], %%d2 + \\ trap #0 + \\ move.l #1, %%d0 // SYS_exit + \\ move.l #0, %%d1 + \\ trap #0 + : + : [ptr] "r" (@intFromPtr(self.mapped.ptr)), + [len] "r" (self.mapped.len), + : .{ .memory = true }), // We set `sp` to the address of the current function as a workaround for a Linux // kernel bug that caused syscalls to return EFAULT if the stack pointer is invalid. // The bug was introduced in 46e12c07b3b9603c60fc1d421ff18618241cb081 and fixed in From de87c856e78fa8c9a92a7d9638c287fd70d7f235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 05:56:46 +0200 Subject: [PATCH 31/43] std.Thread: implement freeAndExit() for alpha-linux --- lib/std/Thread.zig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 049ea9e8b76e..02d7dc9eee32 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1235,6 +1235,18 @@ const LinuxThreadImpl = struct { : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), : .{ .memory = true }), + .alpha => asm volatile ( + \\ ldi $0, 73 # SYS_munmap + \\ mov %[ptr], $16 + \\ mov %[len], $17 + \\ callsys + \\ ldi $0, 1 # SYS_exit + \\ ldi $16, 0 + \\ callsys + : + : [ptr] "r" (@intFromPtr(self.mapped.ptr)), + [len] "r" (self.mapped.len), + : .{ .memory = true }), .hexagon => asm volatile ( \\ r6 = #215 // SYS_munmap \\ r0 = %[ptr] From f6c06d7069bd347528f388d39dfbd4b451560ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 06:10:04 +0200 Subject: [PATCH 32/43] std.Thread: implement freeAndExit() for hppa-linux --- lib/std/Thread.zig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 02d7dc9eee32..3c7536ea21c8 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1259,6 +1259,18 @@ const LinuxThreadImpl = struct { : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), : .{ .memory = true }), + .hppa => asm volatile ( + \\ ldi 91, %%r20 /* SYS_munmap */ + \\ copy %[ptr], %%r26 + \\ copy %[len], %%r25 + \\ ble 0x100(%%sr2, %%r0) + \\ ldi 1, %%r20 /* SYS_exit */ + \\ ldi 0, %%r26 + \\ ble 0x100(%%sr2, %%r0) + : + : [ptr] "r" (@intFromPtr(self.mapped.ptr)), + [len] "r" (self.mapped.len), + : .{ .memory = true }), .m68k => asm volatile ( \\ move.l #91, %%d0 // SYS_munmap \\ move.l %[ptr], %%d1 From 3777d3c25bb597998eea9cbc977519622e27eeab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 05:28:16 +0200 Subject: [PATCH 33/43] std.Thread: implement freeAndExit() for microblaze-linux --- lib/std/Thread.zig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 3c7536ea21c8..fdf1a6f4d80e 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1283,6 +1283,18 @@ const LinuxThreadImpl = struct { : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), : .{ .memory = true }), + .microblaze, .microblazeel => asm volatile ( + \\ ori r12, r0, 91 # SYS_munmap + \\ ori r5, %[ptr], 0 + \\ ori r6, %[len], 0 + \\ brki r14, 0x8 + \\ ori r12, r0, 1 # SYS_exit + \\ or r5, r0, r0 + \\ brki r14, 0x8 + : + : [ptr] "r" (@intFromPtr(self.mapped.ptr)), + [len] "r" (self.mapped.len), + : .{ .memory = true }), // We set `sp` to the address of the current function as a workaround for a Linux // kernel bug that caused syscalls to return EFAULT if the stack pointer is invalid. // The bug was introduced in 46e12c07b3b9603c60fc1d421ff18618241cb081 and fixed in From 493889d5ebd961dabcb53d90c0814f6c71700cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 21 Oct 2025 05:33:48 +0200 Subject: [PATCH 34/43] std.Thread: implement freeAndExit() for sh-linux --- lib/std/Thread.zig | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index fdf1a6f4d80e..dfefeceea02a 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1383,6 +1383,28 @@ const LinuxThreadImpl = struct { : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), : .{ .memory = true }), + .sh, .sheb => asm volatile ( + \\ mov #91, r3 ! SYS_munmap + \\ mov %[ptr], r4 + \\ mov %[len], r5 + \\ trapa #31 + \\ or r0, r0 + \\ or r0, r0 + \\ or r0, r0 + \\ or r0, r0 + \\ or r0, r0 + \\ mov #1, r3 ! SYS_exit + \\ mov #0, r4 + \\ trapa #31 + \\ or r0, r0 + \\ or r0, r0 + \\ or r0, r0 + \\ or r0, r0 + \\ or r0, r0 + : + : [ptr] "r" (@intFromPtr(self.mapped.ptr)), + [len] "r" (self.mapped.len), + : .{ .memory = true }), .sparc => asm volatile ( \\ # See sparc64 comments below. \\ 1: From 3c5502ed8def9f604bd4338c6276c1f858daecfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:43:48 +0200 Subject: [PATCH 35/43] std.atomic: define cache line size for alpha, hppa, microblaze, sh --- lib/std/atomic.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig index 507040c582c1..0b35b61e9bab 100644 --- a/lib/std/atomic.zig +++ b/lib/std/atomic.zig @@ -433,20 +433,29 @@ pub fn cacheLineForCpu(cpu: std.Target.Cpu) u16 { // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sparc/include/asm/cache.h#L14 + // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/microblaze/include/asm/cache.h#L15 + // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sh/include/cpu-sh4/cpu/cache.h#L10 .arm, .armeb, .thumb, .thumbeb, + .microblaze, + .microblazeel, .mips, .mipsel, .mips64, .mips64el, + .sh, + .sheb, .sparc, .sparc64, => 32, // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/m68k/include/asm/cache.h#L10 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/openrisc/include/asm/cache.h#L24 + // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/parisc/include/asm/cache.h#L16 + .hppa, + .hppa64, .m68k, .or1k, => 16, @@ -469,6 +478,7 @@ pub fn cacheLineForCpu(cpu: std.Target.Cpu) u16 { // - https://github.com/golang/go/blob/19e923182e590ae6568c2c714f20f32512aeb3e3/src/internal/cpu/cpu_riscv64.go#L7 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/xtensa/variants/csp/include/variant/core.h#L209 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/csky/Kconfig#L183 + // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/alpha/include/asm/cache.h#L11 // - https://www.xmos.com/download/The-XMOS-XS3-Architecture.pdf else => 64, }; From 7eda0b572489ccd3867d0d98bf85ffa7b9d4f882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:45:38 +0200 Subject: [PATCH 36/43] std.heap: define page size for alpha, hppa, microblaze, sh on Linux --- lib/std/heap.zig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 3996d91203a8..2bf5553bba23 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -824,18 +824,22 @@ const page_size_min_default: ?usize = switch (builtin.os.tag) { .emscripten => 64 << 10, .linux => switch (builtin.cpu.arch) { // Linux/arch/*/Kconfig + .alpha => 8 << 10, .arc, .arceb => 4 << 10, .thumb, .thumbeb, .arm, .armeb => 4 << 10, .aarch64, .aarch64_be => 4 << 10, .csky => 4 << 10, .hexagon => 4 << 10, + .hppa => 4 << 10, .loongarch32, .loongarch64 => 4 << 10, .m68k => 4 << 10, + .microblaze, .microblazeel => 4 << 10, .mips, .mipsel, .mips64, .mips64el => 4 << 10, .or1k => 8 << 10, .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, .riscv32, .riscv64 => 4 << 10, .s390x => 4 << 10, + .sh, .sheb => 4 << 10, .sparc => 4 << 10, .sparc64 => 8 << 10, .x86, .x86_64 => 4 << 10, @@ -972,18 +976,22 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) { .emscripten => 64 << 10, .linux => switch (builtin.cpu.arch) { // Linux/arch/*/Kconfig + .alpha => 8 << 10, .arc, .arceb => 16 << 10, .thumb, .thumbeb, .arm, .armeb => 4 << 10, .aarch64, .aarch64_be => 64 << 10, .csky => 4 << 10, .hexagon => 256 << 10, + .hppa => 64 << 10, .loongarch32, .loongarch64 => 64 << 10, .m68k => 8 << 10, + .microblaze, .microblazeel => 4 << 10, .mips, .mipsel, .mips64, .mips64el => 64 << 10, .or1k => 8 << 10, .powerpc, .powerpc64, .powerpc64le, .powerpcle => 256 << 10, .riscv32, .riscv64 => 4 << 10, .s390x => 4 << 10, + .sh, .sheb => 64 << 10, .sparc => 4 << 10, .sparc64 => 8 << 10, .x86, .x86_64 => 4 << 10, From a03b924e742f61be53731a09ec01db2ca0f8cd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 23 Oct 2025 19:32:02 +0200 Subject: [PATCH 37/43] std.heap: define page size for alpha, hppa, sh on OpenBSD --- lib/std/heap.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 2bf5553bba23..9d3c6b89a33b 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -754,11 +754,14 @@ const page_size_min_default: ?usize = switch (builtin.os.tag) { }, .openbsd => switch (builtin.cpu.arch) { // OpenBSD/sys/arch/* + .alpha => 8 << 10, + .hppa => 4 << 10, .x86, .x86_64 => 4 << 10, .thumb, .thumbeb, .arm, .armeb, .aarch64, .aarch64_be => 4 << 10, .mips64, .mips64el => 4 << 10, .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, .riscv64 => 4 << 10, + .sh, .sheb => 4 << 10, .sparc64 => 8 << 10, else => null, }, @@ -906,11 +909,14 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) { }, .openbsd => switch (builtin.cpu.arch) { // OpenBSD/sys/arch/* + .alpha => 8 << 10, + .hppa => 4 << 10, .x86, .x86_64 => 4 << 10, .thumb, .thumbeb, .arm, .armeb, .aarch64, .aarch64_be => 4 << 10, .mips64, .mips64el => 16 << 10, .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, .riscv64 => 4 << 10, + .sh, .sheb => 4 << 10, .sparc64 => 8 << 10, else => null, }, From 23b299056dd6d5ed5f8f0dc4306add697e2154c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 23 Oct 2025 19:33:34 +0200 Subject: [PATCH 38/43] std.heap: define page size for hppa, sh on NetBSD --- lib/std/heap.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 9d3c6b89a33b..c99395c38953 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -739,8 +739,10 @@ const page_size_min_default: ?usize = switch (builtin.os.tag) { .x86, .x86_64 => 4 << 10, .thumb, .thumbeb, .arm, .armeb => 4 << 10, .aarch64, .aarch64_be => 4 << 10, + .hppa => 4 << 10, .mips, .mipsel, .mips64, .mips64el => 4 << 10, .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10, + .sh, .sheb => 4 << 10, .sparc => 4 << 10, .sparc64 => 8 << 10, .riscv32, .riscv64 => 4 << 10, @@ -895,8 +897,10 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) { .x86, .x86_64 => 4 << 10, .thumb, .thumbeb, .arm, .armeb => 4 << 10, .aarch64, .aarch64_be => 64 << 10, + .hppa => 4 << 10, .mips, .mipsel, .mips64, .mips64el => 16 << 10, .powerpc, .powerpc64, .powerpc64le, .powerpcle => 16 << 10, + .sh, .sheb => 4 << 10, .sparc => 8 << 10, .sparc64 => 8 << 10, .riscv32, .riscv64 => 4 << 10, From d99cf5061c205a57a721a5c6e751158803ed04b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 23 Oct 2025 03:14:55 +0200 Subject: [PATCH 39/43] std.debug.cpu_context: add signal_ucontext_t for alpha, hppa, microblaze, sh --- lib/std/debug/cpu_context.zig | 98 +++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 0b1a4e34b736..1ff61ee2a25e 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1492,6 +1492,21 @@ const X86_64 = struct { /// as unsigned everywhere even if that's not how they're declared in the C headers. const signal_ucontext_t = switch (native_os) { .linux => switch (native_arch) { + // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/alpha/include/asm/ucontext.h + .alpha => extern struct { + _flags: u64, + _link: ?*signal_ucontext_t, + _osf_sigmask: u64, + _stack: std.os.linux.stack_t, + // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/alpha/include/uapi/asm/sigcontext.h + mcontext: extern struct { + _onstack: i64, + _mask: i64, + pc: u64, + _ps: i64, + r: [32]u64, + }, + }, // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm64/include/uapi/asm/ucontext.h .aarch64, .aarch64_be, @@ -1618,6 +1633,21 @@ const signal_ucontext_t = switch (native_os) { _ugp: u32, pc: u32, }, + // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/parisc/include/uapi/asm/sigcontext.h + .hppa => extern struct { + _flags: u32, + _psw: u32, + r1_19: [19]u32, + r20: u32, + r21: u32, + r22: u32, + r23_29: [7]u32, + r30: u32, + r31: u32, + _fr: [32]f64, + _iasq: [2]u32, + iaoq: [2]u32, + }, // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/m68k/include/asm/ucontext.h .m68k => extern struct { _version: i32, @@ -1625,6 +1655,11 @@ const signal_ucontext_t = switch (native_os) { a: [8]u32, pc: u32, }, + // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/microblaze/include/uapi/asm/sigcontext.h + .microblaze, .microblazeel => extern struct { + r: [32]u32, + pc: u32, + }, // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/mips/include/uapi/asm/sigcontext.h .mips, .mipsel => extern struct { _regmask: u32, @@ -1654,6 +1689,13 @@ const signal_ucontext_t = switch (native_os) { }, r: [16]u64, }, + // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/sh/include/uapi/asm/sigcontext.h + .sh, .sheb => extern struct { + _oldmask: u32, + r: [16]u32, + pc: u32, + pr: u32, + }, // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/x86/include/uapi/asm/sigcontext.h .x86 => extern struct { _gs: u32, @@ -1950,6 +1992,7 @@ const signal_ucontext_t = switch (native_os) { _err: i32, eip: u32, }, + // https://github.com/illumos/illumos-gate/blob/d4ce137bba3bd16823db6374d9e9a643264ce245/usr/src/uts/intel/sys/mcontext.h .x86_64 => extern struct { r15: u64, r14: u64, @@ -1986,6 +2029,14 @@ const signal_ucontext_t = switch (native_os) { x: [30]u64, }, }, + // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/alpha/include/signal.h + .alpha => extern struct { + _cookie: i64, + _mask: i64, + pc: u64, + _ps: i64, + r: [32]u64, + }, // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/arm/include/signal.h .arm => extern struct { _cookie: i32, @@ -1997,6 +2048,22 @@ const signal_ucontext_t = switch (native_os) { pc: u32, }, }, + // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/hppa/include/signal.h + .hppa => extern struct { + _unused: u32, + _mask: i32, + _fp: u32, + iaoq: [2]u32, + _resv: [2]u32, + r22: u32, + r21: u32, + r30: u32, + r20: u32, + _sar: u32, + r1_19: [19]u32, + r23_29: [7]u32, + r31: u32, + }, // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/mips64/include/signal.h .mips64, .mips64el => extern struct { _cookie: i64, @@ -2036,6 +2103,18 @@ const signal_ucontext_t = switch (native_os) { }, // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/sparc64/include/signal.h .sparc64 => @compileError("sparc64-openbsd ucontext_t missing"), + // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/sh/include/signal.h + .sh, .sheb => extern struct { + pc: u32, + _sr: i32, + _gbr: i32, + _macl: i32, + _mach: i32, + pr: u32, + r13_0: [14]u32, + r15: u32, + r14: u32, + }, // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/i386/include/signal.h .x86 => extern struct { mcontext: extern struct { @@ -2102,6 +2181,12 @@ const signal_ucontext_t = switch (native_os) { sp: u64, pc: u64, }, + // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/alpha/include/mcontext.h + .alpha => extern struct { + r: [32]u64, + pc: u64, + }, + // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/arm/include/mcontext.h .arm, .armeb => extern struct { r: [15]u32 align(8), pc: u32, @@ -2120,6 +2205,7 @@ const signal_ucontext_t = switch (native_os) { _cause: i32, pc: u32, }, + // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/mips/include/mcontext.h .mips64, .mips64el => @compileError("https://github.com/ziglang/zig/issues/23765#issuecomment-2880386178"), // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/powerpc/include/mcontext.h .powerpc => extern struct { @@ -2131,6 +2217,18 @@ const signal_ucontext_t = switch (native_os) { // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/sparc/include/mcontext.h .sparc => @compileError("sparc-netbsd mcontext_t missing"), .sparc64 => @compileError("sparc64-netbsd mcontext_t missing"), + // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/sh3/include/mcontext.h + .sh, .sheb => extern struct { + _gbr: i32, + pc: u32, + _sr: i32, + _macl: i32, + _mach: i32, + pr: u32, + r14: u32, + r13_0: [14]u32, + r15: u32, + }, // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/i386/include/mcontext.h .x86 => extern struct { _gs: i32, From a689c3819777c7ebbf00f752951a9a69c7a44c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:44:10 +0200 Subject: [PATCH 40/43] std.debug: FP unwinding is impossible on alpha, microblaze, sh --- lib/std/debug.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index ec082443836b..9a0a1f27d9ed 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -872,13 +872,18 @@ const StackIterator = union(enum) { }; const fp_usability: FpUsability = switch (builtin.target.cpu.arch) { + .alpha, .avr, .csky, + .microblaze, + .microblazeel, .mips, .mipsel, .mips64, .mips64el, .msp430, + .sh, + .sheb, .xcore, => .useless, .hexagon, From c13355abda21e90443ae9ea59706e491111a8bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:44:51 +0200 Subject: [PATCH 41/43] std.debug: fix FP unwind progress check for stackGrowth() == .up targets --- lib/std/debug.zig | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 9a0a1f27d9ed..677630fbcf32 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -974,11 +974,15 @@ const StackIterator = union(enum) { const ra_ptr: *const usize = @ptrFromInt(ra_addr); const bp = applyOffset(bp_ptr.*, stack_bias) orelse return .end; - // The stack grows downards, so `bp > fp` should always hold. If it doesn't, this - // frame is invalid, so we'll treat it as though it we reached end of stack. The + // If the stack grows downwards, `bp > fp` should always hold; conversely, if it + // grows upwards, `bp < fp` should always hold. If that is not the case, this + // frame is invalid, so we'll treat it as though we reached end of stack. The // exception is address 0, which is a graceful end-of-stack signal, in which case // *this* return address is valid and the *next* iteration will be the last. - if (bp != 0 and bp <= fp) return .end; + if (bp != 0 and switch (comptime builtin.target.stackGrowth()) { + .down => bp <= fp, + .up => bp >= fp, + }) return .end; it.fp = bp; const ra = stripInstructionPtrAuthCode(ra_ptr.*); From d8cb8b7baec1ed3e3457486b35d64bdae9904ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:45:20 +0200 Subject: [PATCH 42/43] std.debug: fix FP unwinding for hppa/hppa64 --- lib/std/debug.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 677630fbcf32..57d6f45111ee 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -994,6 +994,11 @@ const StackIterator = union(enum) { /// Offset of the saved base pointer (previous frame pointer) wrt the frame pointer. const fp_to_bp_offset = off: { + // On 32-bit PA-RISC, the base pointer is the final word of the frame marker. + if (native_arch == .hppa) break :off -1 * @sizeOf(usize); + // On 64-bit PA-RISC, the frame marker was shrunk significantly; now there's just the return + // address followed by the base pointer. + if (native_arch == .hppa64) break :off -1 * @sizeOf(usize); // On LoongArch and RISC-V, the frame pointer points to the top of the saved register area, // in which the base pointer is the first word. if (native_arch.isLoongArch() or native_arch.isRISCV()) break :off -2 * @sizeOf(usize); @@ -1008,6 +1013,11 @@ const StackIterator = union(enum) { /// Offset of the saved return address wrt the frame pointer. const fp_to_ra_offset = off: { + // On 32-bit PA-RISC, the return address sits in the middle-ish of the frame marker. + if (native_arch == .hppa) break :off -5 * @sizeOf(usize); + // On 64-bit PA-RISC, the frame marker was shrunk significantly; now there's just the return + // address followed by the base pointer. + if (native_arch == .hppa64) break :off -2 * @sizeOf(usize); // On LoongArch and RISC-V, the frame pointer points to the top of the saved register area, // in which the return address is the second word. if (native_arch.isLoongArch() or native_arch.isRISCV()) break :off -1 * @sizeOf(usize); From 07d764dc301d4547a6dab131cd6b687fef3278c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 20 Oct 2025 03:46:11 +0200 Subject: [PATCH 43/43] std.zig.system: handle alpha, hppa, microblaze, sh in getExternalExecutor() --- lib/std/zig/system.zig | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 54ba15ea832d..f5fae5581a70 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -100,10 +100,14 @@ pub fn getExternalExecutor( else => bad_result, }, inline .aarch64_be, + .alpha, .armeb, .hexagon, + .hppa, .loongarch64, .m68k, + .microblaze, + .microblazeel, .mips, .mipsel, .mips64, @@ -114,6 +118,8 @@ pub fn getExternalExecutor( .powerpc64le, .riscv32, .s390x, + .sh, + .sheb, .sparc, .sparc64, .thumb, @@ -122,19 +128,24 @@ pub fn getExternalExecutor( .xtensaeb, => |t| switch (candidate.os.tag) { .linux, - => .{ .qemu = switch (t) { - .powerpc => "qemu-ppc", - .powerpc64 => "qemu-ppc64", - .powerpc64le => "qemu-ppc64le", - .mips64, .mips64el => switch (candidate.abi) { - .gnuabin32, .muslabin32 => if (t == .mips64el) "qemu-mipsn32el" else "qemu-mipsn32", + => .{ + .qemu = switch (t) { + .powerpc => "qemu-ppc", + .powerpc64 => "qemu-ppc64", + .powerpc64le => "qemu-ppc64le", + .mips64, .mips64el => switch (candidate.abi) { + .gnuabin32, .muslabin32 => if (t == .mips64el) "qemu-mipsn32el" else "qemu-mipsn32", + else => "qemu-" ++ @tagName(t), + }, + // TODO: Actually check the SuperH version. + .sh => "qemu-sh4", + .sheb => "qemu-sh4eb", + .sparc => if (candidate.cpu.has(.sparc, .v8plus)) "qemu-sparc32plus" else "qemu-sparc", + .thumb => "qemu-arm", + .thumbeb => "qemu-armeb", else => "qemu-" ++ @tagName(t), }, - .sparc => if (candidate.cpu.has(.sparc, .v8plus)) "qemu-sparc32plus" else "qemu-sparc", - .thumb => "qemu-arm", - .thumbeb => "qemu-armeb", - else => "qemu-" ++ @tagName(t), - } }, + }, else => bad_result, }, else => bad_result,