From 999777e73aa1bd06b05cbe53f8c2488877e18874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 20 May 2025 02:44:52 +0200 Subject: [PATCH] compiler: Scaffold stage2_powerpc backend. Nothing interesting here; literally just the bare minimum so I can work on this on and off in a branch without worrying about merge conflicts in the non-backend code. --- CMakeLists.txt | 1 + lib/compiler/test_runner.zig | 4 +- lib/std/builtin.zig | 13 +++-- lib/std/debug.zig | 23 ++++---- lib/std/mem.zig | 6 ++- lib/std/os/linux.zig | 7 ++- lib/std/start.zig | 27 ++++++---- lib/std/testing.zig | 8 ++- lib/ubsan_rt.zig | 4 +- src/Zcu.zig | 20 +++++++ src/arch/powerpc/CodeGen.zig | 52 +++++++++++++++++++ src/codegen.zig | 7 ++- src/dev.zig | 15 ++++++ src/target.zig | 10 ++-- .../compile_errors/@import_zon_bad_type.zig | 6 +-- .../anytype_param_requires_comptime.zig | 2 +- .../bogus_method_call_on_slice.zig | 2 +- .../compile_errors/coerce_anon_struct.zig | 2 +- test/cases/compile_errors/redundant_try.zig | 4 +- 19 files changed, 172 insertions(+), 41 deletions(-) create mode 100644 src/arch/powerpc/CodeGen.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index fdf4b8988a..cfba9f2579 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -543,6 +543,7 @@ set(ZIG_STAGE2_SOURCES src/arch/arm/Mir.zig src/arch/arm/abi.zig src/arch/arm/bits.zig + src/arch/powerpc/CodeGen.zig src/arch/riscv64/abi.zig src/arch/riscv64/bits.zig src/arch/riscv64/CodeGen.zig diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index ab1dae9a70..adbee7d07d 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -15,7 +15,9 @@ var fba_buffer: [8192]u8 = undefined; var fba = std.heap.FixedBufferAllocator.init(&fba_buffer); const crippled = switch (builtin.zig_backend) { - .stage2_riscv64 => true, + .stage2_powerpc, + .stage2_riscv64, + => true, else => false, }; diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index de2d8b2156..852b94c324 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -1110,6 +1110,9 @@ pub const CompilerBackend = enum(u64) { /// The reference implementation self-hosted compiler of Zig, using the /// spirv backend. stage2_spirv64 = 11, + /// The reference implementation self-hosted compiler of Zig, using the + /// powerpc backend. + stage2_powerpc = 12, _, }; @@ -1143,10 +1146,12 @@ pub const panic: type = p: { if (@hasDecl(root, "Panic")) { break :p root.Panic; // Deprecated; use `panic` instead. } - if (builtin.zig_backend == .stage2_riscv64) { - break :p std.debug.simple_panic; - } - break :p std.debug.FullPanic(std.debug.defaultPanic); + break :p switch (builtin.zig_backend) { + .stage2_powerpc, + .stage2_riscv64, + => std.debug.simple_panic, + else => std.debug.FullPanic(std.debug.defaultPanic), + }; }; pub noinline fn returnError() void { diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 81c627b633..91ff367c2d 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -608,15 +608,20 @@ pub fn defaultPanic( // For backends that cannot handle the language features depended on by the // default panic handler, we have a simpler panic handler: - if (builtin.zig_backend == .stage2_wasm or - builtin.zig_backend == .stage2_arm or - builtin.zig_backend == .stage2_aarch64 or - builtin.zig_backend == .stage2_x86 or - (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or - builtin.zig_backend == .stage2_sparc64 or - builtin.zig_backend == .stage2_spirv64) - { - @trap(); + switch (builtin.zig_backend) { + .stage2_aarch64, + .stage2_arm, + .stage2_powerpc, + .stage2_riscv64, + .stage2_spirv64, + .stage2_wasm, + .stage2_x86, + => @trap(), + .stage2_x86_64 => switch (builtin.target.ofmt) { + .elf, .macho => {}, + else => @trap(), + }, + else => {}, } switch (builtin.os.tag) { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 311b5701a0..79291871b9 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -675,10 +675,12 @@ test lessThan { } const eqlBytes_allowed = switch (builtin.zig_backend) { + // These backends don't support vectors yet. + .stage2_powerpc, + .stage2_riscv64, + => false, // The SPIR-V backend does not support the optimized path yet. .stage2_spirv64 => false, - // The RISC-V does not support vectors. - .stage2_riscv64 => false, // The naive memory comparison implementation is more useful for fuzzers to // find interesting inputs. else => !builtin.fuzz, diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index e5b2696f80..32eb8d186d 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -505,7 +505,12 @@ pub var elf_aux_maybe: ?[*]std.elf.Auxv = null; /// Whether an external or internal getauxval implementation is used. const extern_getauxval = switch (builtin.zig_backend) { // Calling extern functions is not yet supported with these backends - .stage2_aarch64, .stage2_arm, .stage2_riscv64, .stage2_sparc64 => false, + .stage2_aarch64, + .stage2_arm, + .stage2_powerpc, + .stage2_riscv64, + .stage2_sparc64, + => false, else => !builtin.link_libc, }; diff --git a/lib/std/start.zig b/lib/std/start.zig index 477e24bb55..2280bea9e7 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -14,12 +14,16 @@ const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start"; // The self-hosted compiler is not fully capable of handling all of this start.zig file. // Until then, we have simplified logic here for self-hosted. TODO remove this once // self-hosted is capable enough to handle all of the real start.zig logic. -pub const simplified_logic = - builtin.zig_backend == .stage2_x86 or - builtin.zig_backend == .stage2_aarch64 or - builtin.zig_backend == .stage2_arm or - builtin.zig_backend == .stage2_sparc64 or - builtin.zig_backend == .stage2_spirv64; +pub const simplified_logic = switch (builtin.zig_backend) { + .stage2_aarch64, + .stage2_arm, + .stage2_powerpc, + .stage2_sparc64, + .stage2_spirv64, + .stage2_x86, + => true, + else => false, +}; comptime { // No matter what, we import the root file, so that any export, test, comptime @@ -669,9 +673,14 @@ pub inline fn callMain() u8 { if (@typeInfo(ReturnType) != .error_union) @compileError(bad_main_ret); const result = root.main() catch |err| { - if (builtin.zig_backend == .stage2_riscv64) { - std.debug.print("error: failed with error\n", .{}); - return 1; + switch (builtin.zig_backend) { + .stage2_powerpc, + .stage2_riscv64, + => { + std.debug.print("error: failed with error\n", .{}); + return 1; + }, + else => {}, } std.log.err("{s}", .{@errorName(err)}); if (@errorReturnTrace()) |trace| { diff --git a/lib/std/testing.zig b/lib/std/testing.zig index a3b14d18bd..9bad5826a2 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -32,7 +32,13 @@ pub var allocator_instance: std.heap.GeneralPurposeAllocator(.{ pub var log_level = std.log.Level.warn; // Disable printing in tests for simple backends. -pub const backend_can_print = !(builtin.zig_backend == .stage2_spirv64 or builtin.zig_backend == .stage2_riscv64); +pub const backend_can_print = switch (builtin.zig_backend) { + .stage2_powerpc, + .stage2_riscv64, + .stage2_spirv64, + => false, + else => true, +}; fn print(comptime fmt: []const u8, args: anytype) void { if (@inComptime()) { diff --git a/lib/ubsan_rt.zig b/lib/ubsan_rt.zig index 20b0cc2942..a2e0a6c1aa 100644 --- a/lib/ubsan_rt.zig +++ b/lib/ubsan_rt.zig @@ -671,7 +671,9 @@ fn exportHandlerWithAbort( } const can_build_ubsan = switch (builtin.zig_backend) { - .stage2_riscv64 => false, + .stage2_powerpc, + .stage2_riscv64, + => false, else => true, }; diff --git a/src/Zcu.zig b/src/Zcu.zig index 037c90ac19..bee7fadb95 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4500,6 +4500,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu .naked => true, else => false, }, + .stage2_powerpc => switch (target.cpu.arch) { + .powerpc, .powerpcle => switch (cc) { + .powerpc_sysv, + .powerpc_sysv_altivec, + .powerpc_aix, + .powerpc_aix_altivec, + .naked, + => true, + else => false, + }, + .powerpc64, .powerpc64le => switch (cc) { + .powerpc64_elf, + .powerpc64_elf_altivec, + .powerpc64_elf_v2, + .naked, + => true, + else => false, + }, + else => unreachable, + }, .stage2_riscv64 => switch (cc) { .riscv64_lp64 => |opts| opts.incoming_stack_alignment == null, .naked => true, diff --git a/src/arch/powerpc/CodeGen.zig b/src/arch/powerpc/CodeGen.zig new file mode 100644 index 0000000000..c8553f5d67 --- /dev/null +++ b/src/arch/powerpc/CodeGen.zig @@ -0,0 +1,52 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const Air = @import("../../Air.zig"); +const codegen = @import("../../codegen.zig"); +const InternPool = @import("../../InternPool.zig"); +const link = @import("../../link.zig"); +const Liveness = @import("../../Liveness.zig"); +const Zcu = @import("../../Zcu.zig"); + +const assert = std.debug.assert; +const log = std.log.scoped(.codegen); + +pub fn generate( + bin_file: *link.File, + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + func_index: InternPool.Index, + air: Air, + liveness: Liveness, + code: *std.ArrayListUnmanaged(u8), + debug_output: link.File.DebugInfoOutput, +) codegen.CodeGenError!void { + _ = bin_file; + _ = pt; + _ = src_loc; + _ = func_index; + _ = air; + _ = liveness; + _ = code; + _ = debug_output; + + unreachable; +} + +pub fn generateLazy( + bin_file: *link.File, + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + lazy_sym: link.File.LazySymbol, + code: *std.ArrayListUnmanaged(u8), + debug_output: link.File.DebugInfoOutput, +) codegen.CodeGenError!void { + _ = bin_file; + _ = pt; + _ = src_loc; + _ = lazy_sym; + _ = code; + _ = debug_output; + + unreachable; +} diff --git a/src/codegen.zig b/src/codegen.zig index fb06d7a240..c3be335acc 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -37,6 +37,7 @@ fn importBackend(comptime backend: std.builtin.CompilerBackend) type { return switch (backend) { .stage2_aarch64 => @import("arch/aarch64/CodeGen.zig"), .stage2_arm => @import("arch/arm/CodeGen.zig"), + .stage2_powerpc => @import("arch/powerpc/CodeGen.zig"), .stage2_riscv64 => @import("arch/riscv64/CodeGen.zig"), .stage2_sparc64 => @import("arch/sparc64/CodeGen.zig"), .stage2_x86_64 => @import("arch/x86_64/CodeGen.zig"), @@ -61,6 +62,7 @@ pub fn generateFunction( else => unreachable, inline .stage2_aarch64, .stage2_arm, + .stage2_powerpc, .stage2_riscv64, .stage2_sparc64, .stage2_x86_64, @@ -86,7 +88,10 @@ pub fn generateLazyFunction( zcu.getTarget(); switch (target_util.zigBackend(target, false)) { else => unreachable, - inline .stage2_x86_64, .stage2_riscv64 => |backend| { + inline .stage2_powerpc, + .stage2_riscv64, + .stage2_x86_64, + => |backend| { dev.check(devFeatureForBackend(backend)); return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output); }, diff --git a/src/dev.zig b/src/dev.zig index 11b8be785c..473cb4a8d0 100644 --- a/src/dev.zig +++ b/src/dev.zig @@ -26,6 +26,10 @@ pub const Env = enum { /// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-` @"x86_64-linux", + /// - sema + /// - `zig build-* -fincremental -fno-llvm -fno-lld -target powerpc(64)(le)-linux --listen=-` + @"powerpc-linux", + /// - sema /// - `zig build-* -fno-llvm -fno-lld -target riscv64-linux` @"riscv64-linux", @@ -70,6 +74,7 @@ pub const Env = enum { .x86_64_backend, .aarch64_backend, .x86_backend, + .powerpc_backend, .riscv64_backend, .sparc64_backend, .spirv64_backend, @@ -144,6 +149,15 @@ pub const Env = enum { => true, else => Env.sema.supports(feature), }, + .@"powerpc-linux" => switch (feature) { + .build_command, + .stdio_listen, + .incremental, + .x86_64_backend, + .elf_linker, + => true, + else => Env.sema.supports(feature), + }, .@"riscv64-linux" => switch (feature) { .riscv64_backend, .elf_linker, @@ -216,6 +230,7 @@ pub const Feature = enum { x86_64_backend, aarch64_backend, x86_backend, + powerpc_backend, riscv64_backend, sparc64_backend, spirv64_backend, diff --git a/src/target.zig b/src/target.zig index 03686d7687..4931b11eba 100644 --- a/src/target.zig +++ b/src/target.zig @@ -736,6 +736,7 @@ pub fn supportsTailCall(target: std.Target, backend: std.builtin.CompilerBackend pub fn supportsThreads(target: std.Target, backend: std.builtin.CompilerBackend) bool { return switch (backend) { + .stage2_powerpc => true, .stage2_x86_64 => target.ofmt == .macho or target.ofmt == .elf, else => true, }; @@ -796,14 +797,15 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken if (use_llvm) return .stage2_llvm; if (target.ofmt == .c) return .stage2_c; return switch (target.cpu.arch) { - .wasm32, .wasm64 => .stage2_wasm, - .arm, .armeb, .thumb, .thumbeb => .stage2_arm, - .x86_64 => .stage2_x86_64, - .x86 => .stage2_x86, .aarch64, .aarch64_be => .stage2_aarch64, + .arm, .armeb, .thumb, .thumbeb => .stage2_arm, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => .stage2_powerpc, .riscv64 => .stage2_riscv64, .sparc64 => .stage2_sparc64, .spirv64 => .stage2_spirv64, + .wasm32, .wasm64 => .stage2_wasm, + .x86 => .stage2_x86, + .x86_64 => .stage2_x86_64, else => .other, }; } diff --git a/test/cases/compile_errors/@import_zon_bad_type.zig b/test/cases/compile_errors/@import_zon_bad_type.zig index 51586af6f2..3265c6d92c 100644 --- a/test/cases/compile_errors/@import_zon_bad_type.zig +++ b/test/cases/compile_errors/@import_zon_bad_type.zig @@ -117,9 +117,9 @@ export fn testMutablePointer() void { // tmp.zig:37:38: note: imported here // neg_inf.zon:1:1: error: expected type '?u8' // tmp.zig:57:28: note: imported here -// neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_496' +// neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_499' // tmp.zig:62:39: note: imported here -// neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_498' +// neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_501' // tmp.zig:67:44: note: imported here -// neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_501' +// neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_504' // tmp.zig:72:50: note: imported here diff --git a/test/cases/compile_errors/anytype_param_requires_comptime.zig b/test/cases/compile_errors/anytype_param_requires_comptime.zig index e5558d90c2..3546955e23 100644 --- a/test/cases/compile_errors/anytype_param_requires_comptime.zig +++ b/test/cases/compile_errors/anytype_param_requires_comptime.zig @@ -15,6 +15,6 @@ pub export fn entry() void { // error // // :7:25: error: unable to resolve comptime value -// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_470.C' must be comptime-known +// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_473.C' must be comptime-known // :4:16: note: struct requires comptime because of this field // :4:16: note: types are not available at runtime diff --git a/test/cases/compile_errors/bogus_method_call_on_slice.zig b/test/cases/compile_errors/bogus_method_call_on_slice.zig index 466a78a917..fe30379476 100644 --- a/test/cases/compile_errors/bogus_method_call_on_slice.zig +++ b/test/cases/compile_errors/bogus_method_call_on_slice.zig @@ -16,5 +16,5 @@ pub export fn entry2() void { // // :3:6: error: no field or member function named 'copy' in '[]const u8' // :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})' -// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_474' +// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_477' // :12:6: note: struct declared here diff --git a/test/cases/compile_errors/coerce_anon_struct.zig b/test/cases/compile_errors/coerce_anon_struct.zig index 9053a32cf7..75e27ddbed 100644 --- a/test/cases/compile_errors/coerce_anon_struct.zig +++ b/test/cases/compile_errors/coerce_anon_struct.zig @@ -6,6 +6,6 @@ export fn foo() void { // error // -// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_463' +// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_466' // :3:16: note: struct declared here // :1:11: note: struct declared here diff --git a/test/cases/compile_errors/redundant_try.zig b/test/cases/compile_errors/redundant_try.zig index a9fc4aed2f..2a3488c413 100644 --- a/test/cases/compile_errors/redundant_try.zig +++ b/test/cases/compile_errors/redundant_try.zig @@ -44,9 +44,9 @@ comptime { // // :5:23: error: expected error union type, found 'comptime_int' // :10:23: error: expected error union type, found '@TypeOf(.{})' -// :15:23: error: expected error union type, found 'tmp.test2__struct_500' +// :15:23: error: expected error union type, found 'tmp.test2__struct_503' // :15:23: note: struct declared here -// :20:27: error: expected error union type, found 'tmp.test3__struct_502' +// :20:27: error: expected error union type, found 'tmp.test3__struct_505' // :20:27: note: struct declared here // :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }' // :31:13: error: expected error union type, found 'u32'