authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-12-12 20:30:50+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-01-06 21:15:02+01:00
log7daf0b6f4660245ac518c663f8971aad7e540da8
tree44e6d449219d848aa6c8da136512c96c8e76cc6f
parenta996a75e06193d377c3071042ece1c3af5cfdc6c
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

build: use -ffunction-sections -fdata-sections for the Zig compiler on PowerPC

It has been observed in practice on powerpc64(le)-linux that zig.o (in various stages and build modes) is large enough that the +/- 32MB branch range of PowerPC is insufficient to reach from one end of the code section to the other. With LLVM 21, this leads to silent miscompiles that then crash at runtime. With LLVM 22, it will at least lead to branch range errors that fail the compilation, but that gets us no closer to a working compiler. By using these options, we give the linker much greater flexibility to move code and data around to satisfy these range constraints; without them, the linker is not allowed to split up the huge code and data sections of zig.o to do so. Similar issues have also been observed on powerpc-linux (32-bit), hexagon-linux, and some variations of mips(64)(el)-linux. But let's be conservative for now; those other targets can be added to the condition later. As a data point to support this change, it's worth noting that LLD started enabling these options for LTO precisely because the resulting large compilation units ran into these range issues. In some abstract sense, Zig can be seen as doing a limited form of "LTO" in the frontend, so it's not surprising that we would hit the same issues.

2 files changed, 11 insertions(+), 0 deletions(-)

CMakeLists.txt+5
......@@ -787,6 +787,11 @@ else()
787787 set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2")
788788 set(ZIG1_COMPILE_FLAGS "-std=c99 -Os")
789789 set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector")
790 # Must match the condition in build.zig.
791 if(ZIG_HOST_TARGET_ARCH MATCHES "^powerpc(64)?(le)?$")
792 set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections")
793 set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -ffunction-sections -fdata-sections")
794 endif()
790795 if(APPLE)
791796 set(ZIG2_LINK_FLAGS "-Wl,-stack_size,0x10000000")
792797 elseif(MINGW)
build.zig+6
......@@ -838,6 +838,12 @@ fn addCompilerStep(b: *std.Build, options: AddCompilerModOptions) *std.Build.Ste
838838 });
839839 exe.stack_size = stack_size;
840840
841 // Must match the condition in CMakeLists.txt.
842 const function_data_sections = options.target.result.cpu.arch.isPowerPC();
843
844 exe.link_function_sections = function_data_sections;
845 exe.link_data_sections = function_data_sections;
846
841847 return exe;
842848}
843849