| author | |
| committer | |
| log | a5219cd288c322f5f5bda89d608af5b243e9fd6f |
| tree | ccb3c205da6f25dde27b12f679c98d98ea480edb |
| parent | c73db56b4543776ce157626361f1cb66df1dac69 |
| signature |
GCC bug 119085, which affects versions 13.0--15.1, is being triggered by
the C backend, resulting in a (small but critical) miscompilation in
zig2. Unfortunately, we can't really work around that bug without a
command-line flag, because the bug is sensitive to things like the order
in which `struct` types are defined.
Therefore, I have added an option to `bootstrap.c` which causes it to
pass the appropriate flag to `gcc` to disable the optimization pass in
question. This flag can likely be removed in future, once the affected
GCC versions become less common.
At least one of our x86_64-linux CI machines is using an affected GCC
version, so I also updated the relevant CI script to pass this flag when
testing no-LLVM bootstrap.
CMakeLists also has a workaround, but no user intervention is required
there: the GCC version range is automatically detected by CMakeLists.3 files changed, 33 insertions(+), 3 deletions(-)
CMakeLists.txt+10-2| ... | ... | @@ -330,7 +330,6 @@ set(ZIG_STAGE2_SOURCES |
| 330 | 330 | src/Air/Liveness.zig |
| 331 | 331 | src/Air/Liveness/Verify.zig |
| 332 | 332 | src/Air/print.zig |
| 333 | src/Air/types_resolved.zig | |
| 334 | 333 | src/Builtin.zig |
| 335 | 334 | src/Compilation.zig |
| 336 | 335 | src/Compilation/Config.zig |
| ... | ... | @@ -344,6 +343,7 @@ set(ZIG_STAGE2_SOURCES |
| 344 | 343 | src/Sema.zig |
| 345 | 344 | src/Sema/bitcast.zig |
| 346 | 345 | src/Sema/comptime_ptr_access.zig |
| 346 | src/Sema/type_resolution.zig | |
| 347 | 347 | src/Type.zig |
| 348 | 348 | src/Value.zig |
| 349 | 349 | src/Zcu.zig |
| ... | ... | @@ -360,7 +360,8 @@ set(ZIG_STAGE2_SOURCES |
| 360 | 360 | src/codegen/aarch64/Mir.zig |
| 361 | 361 | src/codegen/aarch64/Select.zig |
| 362 | 362 | src/codegen/c.zig |
| 363 | src/codegen/c/Type.zig | |
| 363 | src/codegen/c/type.zig | |
| 364 | src/codegen/c/type/render_defs.zig | |
| 364 | 365 | src/codegen/llvm.zig |
| 365 | 366 | src/codegen/llvm/bindings.zig |
| 366 | 367 | src/crash_report.zig |
| ... | ... | @@ -375,6 +376,7 @@ set(ZIG_STAGE2_SOURCES |
| 375 | 376 | src/libs/libunwind.zig |
| 376 | 377 | src/link.zig |
| 377 | 378 | src/link/C.zig |
| 379 | src/link/ConstPool.zig | |
| 378 | 380 | src/link/Coff.zig |
| 379 | 381 | src/link/Dwarf.zig |
| 380 | 382 | src/link/Elf.zig |
| ... | ... | @@ -623,6 +625,12 @@ else() |
| 623 | 625 | else() |
| 624 | 626 | set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000") |
| 625 | 627 | endif() |
| 628 | # Prevent GCC from miscompiling 'zig2.c'. See also 'workaround_gcc_sra_miscomp' in 'bootstrap.c'. | |
| 629 | if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND | |
| 630 | CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "13.0" AND | |
| 631 | CMAKE_C_COMPILER_VERSION VERSION_LESS_EQUAL "15.2") | |
| 632 | set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -fno-tree-sra") | |
| 633 | endif() | |
| 626 | 634 | endif() |
| 627 | 635 | |
| 628 | 636 | set(ZIG1_WASM_MODULE "${PROJECT_SOURCE_DIR}/stage1/zig1.wasm") |
bootstrap.c+21| ... | ... | @@ -102,6 +102,26 @@ int main(int argc, char **argv) { |
| 102 | 102 | const char *cc = get_c_compiler(); |
| 103 | 103 | const char *host_triple = get_host_triple(); |
| 104 | 104 | |
| 105 | // GCC versions 13.0--14.1 have a miscompilation where some bytes of a union may get clobbered | |
| 106 | // depending on the union layout and the order in which types are defined. This miscompilation | |
| 107 | // affects the output of the C backend, and thus can affect the bootstrap process. Specifically, | |
| 108 | // we observe that using the self-hosted x86_64 backend in 'zig2' will cause all function calls | |
| 109 | // to be relocated incorrectly, causing immediate crashes on any binary produced by it. | |
| 110 | // | |
| 111 | // The only reliable workaround for this bug is to disable the optimization pass containing it, | |
| 112 | // so here we check for a CLI flag requesting that workaround. | |
| 113 | // | |
| 114 | // The upstream bug is fixed in GCC version 15.2 onwards (and was also backported to the 13 and | |
| 115 | // 14 branches). Once this bug is no longer widespread, we can remove this CLI flag. | |
| 116 | // | |
| 117 | // Upstream bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119085 | |
| 118 | bool workaround_gcc_sra_miscomp = false; | |
| 119 | for (int i = 1; i < argc; ++i) { | |
| 120 | if (!strcmp(argv[i], "--workaround-gcc-sra-miscomp")) { | |
| 121 | workaround_gcc_sra_miscomp = true; | |
| 122 | } | |
| 123 | } | |
| 124 | ||
| 105 | 125 | { |
| 106 | 126 | const char *child_argv[] = { |
| 107 | 127 | cc, "-o", "zig-wasm2c", "stage1/wasm2c.c", "-O2", "-std=c99", NULL, |
| ... | ... | @@ -193,6 +213,7 @@ int main(int argc, char **argv) { |
| 193 | 213 | #if defined(__GNUC__) |
| 194 | 214 | "-pthread", |
| 195 | 215 | #endif |
| 216 | workaround_gcc_sra_miscomp ? "-fno-tree-sra" : NULL, | |
| 196 | 217 | NULL, |
| 197 | 218 | }; |
| 198 | 219 | print_and_run(child_argv); |
ci/x86_64-linux-release.sh+2-1| ... | ... | @@ -21,7 +21,8 @@ export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache" |
| 21 | 21 | |
| 22 | 22 | # Test building from source without LLVM. |
| 23 | 23 | cc -o bootstrap bootstrap.c |
| 24 | ./bootstrap | |
| 24 | # See comments in bootstrap.c for an explanation of the flag given here. | |
| 25 | ./bootstrap --workaround-gcc-sra-miscomp | |
| 25 | 26 | ./zig2 build -Dno-lib |
| 26 | 27 | ./zig-out/bin/zig test test/behavior.zig |
| 27 | 28 |