╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ bootstrap.c ──────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
4 #include <stdbool.h> 5 6 static const char *get_c_compiler(void) { 7 const char *cc = getenv("CC"); 8 return (cc == NULL) ? "cc" : cc; 9 } 10 11 static void panic(const char *reason) { 12 fprintf(stderr, "%s\n", reason); 13 abort(); 14 } 15 16 #if defined(__GNUC__) && !defined(__clang__) 17 #define GCC_VERSION (__GNUC__ * 10000 \ 18 + __GNUC_MINOR__ * 100 \ 19 + __GNUC_PATCHLEVEL__) 20 // GCC versions 10.0--15.1 have a miscompilation where some bytes of a union may get clobbered 21 // depending on the union layout and the order in which types are defined. This miscompilation 22 // affects the output of the C backend, and thus can affect the bootstrap process. Specifically, 23 // we observe that using the self-hosted x86_64 backend in 'zig2' will cause all function calls 24 // to be relocated incorrectly, causing immediate crashes on any binary produced by it. 25 // 26 // The only reliable workaround for this bug is to disable the optimization pass containing it, 27 // so here we detect whether the compiler being used requires that workaround. 28 // 29 // The upstream bug is fixed in GCC version 15.2 onwards (and was also backported to the 13 and 30 // 14 branches, however there are no 13.x and 14.x releases that contains the fix as of now). 31 // Once this bug is no longer widespread, we can remove this workaround. 32 // 33 // Upstream bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119085 34 #if (GCC_VERSION >= 160000) || \ 35 (GCC_VERSION >= 150200 && GCC_VERSION < 160000) || \ 36 (GCC_VERSION > 140300 && GCC_VERSION < 150000) || \ 37 (GCC_VERSION > 130400 && GCC_VERSION < 140000) || \ 38 (GCC_VERSION <= 100000) 39 #define GCC_BUG_119085_PRESENT 0 40 #else 41 #define GCC_BUG_119085_PRESENT 1 42 #endif 43 44 45 // GCC doesn't take into account alignment annotations when --Waddress-of-packed-member is 46 // evaluated, which causes false positive warnings when the C backend generates code that takes 47 // the address of a field in a packed struct. 48 // 49 // There is no fix for this as now, so the only way to get rid of the false positive warnings 50 // is to disable the flag altogether. 51 // 52 // Upstream bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94081 53 #define GCC_BUG_94081_PRESENT 1 54 #else 55 #define GCC_BUG_94081_PRESENT 0 56 #define GCC_BUG_119085_PRESENT 0 57 #endif 58 59 #if defined(_WIN32) 60 #error TODO write the functionality for executing child process into this build script 61 #else 62 63 #include <unistd.h> 64 #include <errno.h> 65 #include <sys/wait.h> 66 67 static void run(char **argv) { 68 pid_t pid = fork(); 69 if (pid == -1) 70 panic("fork failed"); 71 if (pid == 0) { 72 // child 73 execvp(argv[0], argv); 74 exit(1); 75 } 76 77 // parent 78 79 int status; 80 waitpid(pid, &status, 0); 81 82 if (!WIFEXITED(status)) 83 panic("child process crashed"); 84 85 if (WEXITSTATUS(status) != 0) 86 panic("child process failed"); 87 } 88 #endif 89 90 static void print_and_run(const char **argv) { 91 fprintf(stderr, "%s", argv[0]); 92 for (const char **arg = argv + 1; *arg; arg += 1) { 93 fprintf(stderr, " %s", *arg); 94 } 95 fprintf(stderr, "\n"); 96 run((char **)argv); 97 } 98 99 static const char *get_host_os(void) { 100 const char *host_os = getenv("ZIG_HOST_TARGET_OS"); 101 if (host_os != NULL) return host_os; 102 #if defined(_WIN32) 103 return "windows"; 104 #elif defined(__APPLE__) 105 return "macos"; 106 #elif defined(__linux__) 107 return "linux"; 108 #elif defined(__FreeBSD__) 109 return "freebsd"; 110 #elif defined(__DragonFly__) 111 return "dragonfly"; 112 #elif defined(__HAIKU__) 113 return "haiku"; 114 #else 115 panic("unknown host os, specify with ZIG_HOST_TARGET_OS"); 116 #endif 117 } 118 119 static const char *get_host_arch(void) { 120 const char *host_arch = getenv("ZIG_HOST_TARGET_ARCH"); 121 if (host_arch != NULL) return host_arch; 122 #if defined(__x86_64__ ) 123 return "x86_64"; 124 #elif defined(__aarch64__) 125 return "aarch64"; 126 #else 127 panic("unknown host arch, specify with ZIG_HOST_TARGET_ARCH"); 128 #endif 129 } 130 131 static const char *get_host_abi(void) { 132 const char *host_abi = getenv("ZIG_HOST_TARGET_ABI"); 133 return (host_abi == NULL) ? "" : host_abi; 134 } 135 136 static const char *get_host_triple(void) { 137 const char *host_triple = getenv("ZIG_HOST_TARGET_TRIPLE"); 138 if (host_triple != NULL) return host_triple; 139 static char global_buffer[100]; 140 sprintf(global_buffer, "%s-%s%s", get_host_arch(), get_host_os(), get_host_abi()); 141 return global_buffer; 142 } 143 144 int main(int argc, char **argv) { 145 const char *cc = get_c_compiler(); 146 const char *host_triple = get_host_triple(); 147 148 { 149 const char *child_argv[] = { 150 cc, "-o", "zig-wasm2c", "stage1/wasm2c.c", "-O2", "-std=c99", NULL, 151 }; 152 print_and_run(child_argv); 153 } 154 { 155 const char *child_argv[] = { 156 "./zig-wasm2c", "stage1/zig1.wasm", "zig1.c", NULL, 157 }; 158 print_and_run(child_argv); 159 } 160 { 161 const char *child_argv[] = { 162 cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-fno-strict-aliasing", "-lm", NULL, 163 }; 164 print_and_run(child_argv); 165 } 166 { 167 FILE *f = fopen("config.zig", "wb"); 168 if (f == NULL) 169 panic("unable to open config.zig for writing"); 170 171 const char *zig_version = "0.17.0-dev.bootstrap"; 172 173 int written = fprintf(f, 174 "pub const have_llvm = false;\n" 175 "pub const llvm_has_m68k = false;\n" 176 "pub const llvm_has_csky = false;\n" 177 "pub const llvm_has_arc = false;\n" 178 "pub const llvm_has_xtensa = false;\n" 179 "pub const version: [:0]const u8 = \"%s\";\n" 180 "pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n" 181 "pub const enable_debug_extensions = false;\n" 182 "pub const enable_logging = false;\n" 183 "pub const enable_link_snapshots = false;\n" 184 "pub const enable_tracy = false;\n" 185 "pub const value_tracing = false;\n" 186 "pub const skip_non_native = false;\n" 187 "pub const debug_gpa = false;\n" 188 "pub const dev = .core;\n" 189 "pub const io_mode: enum { threaded, evented } = .threaded;\n" 190 "pub const value_interpret_mode = .direct;\n" 191 , zig_version); 192 if (written < 100) 193 panic("unable to write to config.zig file"); 194 if (fclose(f) != 0) 195 panic("unable to finish writing to config.zig file"); 196 } 197 198 { 199 const char *child_argv[] = { 200 "./zig1", "lib", "build-exe", 201 "-ofmt=c", "-lc", "-OReleaseSmall", 202 "--name", "zig2", "-femit-bin=zig2.c", 203 "-target", host_triple, 204 "--dep", "build_options", 205 "-Mroot=src/main.zig", 206 "-Mbuild_options=config.zig", 207 NULL, 208 }; 209 print_and_run(child_argv); 210 } 211 212 { 213 const char *child_argv[] = { 214 "./zig1", "lib", "build-obj", 215 "-ofmt=c", "-OReleaseSmall", 216 "--name", "compiler_rt", "-femit-bin=compiler_rt.c", 217 "-target", host_triple, 218 "-Mroot=lib/compiler_rt.zig", 219 NULL, 220 }; 221 print_and_run(child_argv); 222 } 223 224 { 225 const char *child_argv[] = { 226 cc, "-o", "zig2", "zig2.c", "compiler_rt.c", 227 "-std=c99", "-O2", "-fno-stack-protector", 228 "-Istage1", 229 #if defined(__APPLE__) 230 "-Wl,-stack_size,0x10000000", 231 #else 232 "-Wl,-z,stack-size=0x10000000", 233 #endif 234 #if defined(__GNUC__) 235 "-pthread", 236 #endif 237 "-fno-strict-aliasing", 238 #if GCC_BUG_119085_PRESENT 239 "-fno-tree-sra", 240 #endif 241 #if GCC_BUG_94081_PRESENT 242 "-Wno-address-of-packed-member", 243 #endif 244 NULL, 245 }; 246 print_and_run(child_argv); 247 } 248 } 249