authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-07 23:10:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-19 16:45:15-07:00
log507aae4a1a3db498ece2a3a89d74e9e24d952923
treedb52f3b00d0def30488e7ce81adc8685c4945874
parent73bbd1069a993a0e663033ea3b8cd4ed1a123566

make self-hosted the default compiler

stage1 is available behind the -fstage1 flag. closes #89

25 files changed, 176 insertions(+), 213 deletions(-)

CMakeLists.txt+1-1
...@@ -12,7 +12,7 @@ if(NOT CMAKE_BUILD_TYPE)...@@ -12,7 +12,7 @@ if(NOT CMAKE_BUILD_TYPE)
12endif()12endif()
1313
14if(NOT CMAKE_INSTALL_PREFIX)14if(NOT CMAKE_INSTALL_PREFIX)
15 set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/stage1" CACHE STRING15 set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/stage2" CACHE STRING
16 "Directory to install zig to" FORCE)16 "Directory to install zig to" FORCE)
17endif()17endif()
1818
build.zig+6-10
...@@ -64,9 +64,9 @@ pub fn build(b: *Builder) !void {...@@ -64,9 +64,9 @@ pub fn build(b: *Builder) !void {
6464
65 const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;65 const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;
6666
67 const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false;67 const have_stage1 = b.option(bool, "enable-stage1", "Include the stage1 compiler behind a feature flag") orelse false;
68 const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;68 const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;
69 const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm);69 const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (have_stage1 or static_llvm);
70 const llvm_has_m68k = b.option(70 const llvm_has_m68k = b.option(
71 bool,71 bool,
72 "llvm-has-m68k",72 "llvm-has-m68k",
...@@ -136,7 +136,7 @@ pub fn build(b: *Builder) !void {...@@ -136,7 +136,7 @@ pub fn build(b: *Builder) !void {
136 };136 };
137137
138 const main_file: ?[]const u8 = mf: {138 const main_file: ?[]const u8 = mf: {
139 if (!is_stage1) break :mf "src/main.zig";139 if (!have_stage1) break :mf "src/main.zig";
140 if (use_zig0) break :mf null;140 if (use_zig0) break :mf null;
141 break :mf "src/stage1.zig";141 break :mf "src/stage1.zig";
142 };142 };
...@@ -247,7 +247,7 @@ pub fn build(b: *Builder) !void {...@@ -247,7 +247,7 @@ pub fn build(b: *Builder) !void {
247 }247 }
248 };248 };
249249
250 if (is_stage1) {250 if (have_stage1) {
251 const softfloat = b.addStaticLibrary("softfloat", null);251 const softfloat = b.addStaticLibrary("softfloat", null);
252 softfloat.setBuildMode(.ReleaseFast);252 softfloat.setBuildMode(.ReleaseFast);
253 softfloat.setTarget(target);253 softfloat.setTarget(target);
...@@ -359,7 +359,7 @@ pub fn build(b: *Builder) !void {...@@ -359,7 +359,7 @@ pub fn build(b: *Builder) !void {
359 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);359 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
360 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);360 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
361 exe_options.addOption(bool, "value_tracing", value_tracing);361 exe_options.addOption(bool, "value_tracing", value_tracing);
362 exe_options.addOption(bool, "is_stage1", is_stage1);362 exe_options.addOption(bool, "have_stage1", have_stage1);
363 if (tracy) |tracy_path| {363 if (tracy) |tracy_path| {
364 const client_cpp = fs.path.join(364 const client_cpp = fs.path.join(
365 b.allocator,365 b.allocator,
...@@ -394,7 +394,7 @@ pub fn build(b: *Builder) !void {...@@ -394,7 +394,7 @@ pub fn build(b: *Builder) !void {
394 test_cases_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);394 test_cases_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
395 test_cases_options.addOption(bool, "skip_non_native", skip_non_native);395 test_cases_options.addOption(bool, "skip_non_native", skip_non_native);
396 test_cases_options.addOption(bool, "skip_stage1", skip_stage1);396 test_cases_options.addOption(bool, "skip_stage1", skip_stage1);
397 test_cases_options.addOption(bool, "is_stage1", is_stage1);397 test_cases_options.addOption(bool, "have_stage1", have_stage1);
398 test_cases_options.addOption(bool, "have_llvm", enable_llvm);398 test_cases_options.addOption(bool, "have_llvm", enable_llvm);
399 test_cases_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k);399 test_cases_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k);
400 test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky);400 test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
...@@ -455,7 +455,6 @@ pub fn build(b: *Builder) !void {...@@ -455,7 +455,6 @@ pub fn build(b: *Builder) !void {
455 skip_libc,455 skip_libc,
456 skip_stage1,456 skip_stage1,
457 false,457 false,
458 is_stage1,
459 ));458 ));
460459
461 toolchain_step.dependOn(tests.addPkgTests(460 toolchain_step.dependOn(tests.addPkgTests(
...@@ -470,7 +469,6 @@ pub fn build(b: *Builder) !void {...@@ -470,7 +469,6 @@ pub fn build(b: *Builder) !void {
470 true, // skip_libc469 true, // skip_libc
471 skip_stage1,470 skip_stage1,
472 true, // TODO get these all passing471 true, // TODO get these all passing
473 is_stage1,
474 ));472 ));
475473
476 toolchain_step.dependOn(tests.addPkgTests(474 toolchain_step.dependOn(tests.addPkgTests(
...@@ -485,7 +483,6 @@ pub fn build(b: *Builder) !void {...@@ -485,7 +483,6 @@ pub fn build(b: *Builder) !void {
485 true, // skip_libc483 true, // skip_libc
486 skip_stage1,484 skip_stage1,
487 true, // TODO get these all passing485 true, // TODO get these all passing
488 is_stage1,
489 ));486 ));
490487
491 toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));488 toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
...@@ -525,7 +522,6 @@ pub fn build(b: *Builder) !void {...@@ -525,7 +522,6 @@ pub fn build(b: *Builder) !void {
525 skip_libc,522 skip_libc,
526 skip_stage1,523 skip_stage1,
527 true, // TODO get these all passing524 true, // TODO get these all passing
528 is_stage1,
529 );525 );
530526
531 const test_step = b.step("test", "Run all the tests");527 const test_step = b.step("test", "Run all the tests");
ci/azure/build.zig+5-5
...@@ -37,9 +37,9 @@ pub fn build(b: *Builder) !void {...@@ -37,9 +37,9 @@ pub fn build(b: *Builder) !void {
37 const docs_step = b.step("docs", "Build documentation");37 const docs_step = b.step("docs", "Build documentation");
38 docs_step.dependOn(&docgen_cmd.step);38 docs_step.dependOn(&docgen_cmd.step);
3939
40 const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false;40 const have_stage1 = b.option(bool, "enable-stage1", "Include the stage1 compiler behind a feature flag") orelse false;
41 const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;41 const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;
42 const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm);42 const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (have_stage1 or static_llvm);
43 const llvm_has_m68k = b.option(43 const llvm_has_m68k = b.option(
44 bool,44 bool,
45 "llvm-has-m68k",45 "llvm-has-m68k",
...@@ -101,7 +101,7 @@ pub fn build(b: *Builder) !void {...@@ -101,7 +101,7 @@ pub fn build(b: *Builder) !void {
101 break :blk 4;101 break :blk 4;
102 };102 };
103103
104 const main_file: ?[]const u8 = if (is_stage1) null else "src/main.zig";104 const main_file: ?[]const u8 = if (have_stage1) null else "src/main.zig";
105105
106 const exe = b.addExecutable("zig", main_file);106 const exe = b.addExecutable("zig", main_file);
107 exe.strip = strip;107 exe.strip = strip;
...@@ -190,7 +190,7 @@ pub fn build(b: *Builder) !void {...@@ -190,7 +190,7 @@ pub fn build(b: *Builder) !void {
190 if (enable_llvm) {190 if (enable_llvm) {
191 const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option);191 const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option);
192192
193 if (is_stage1) {193 if (have_stage1) {
194 const softfloat = b.addStaticLibrary("softfloat", null);194 const softfloat = b.addStaticLibrary("softfloat", null);
195 softfloat.setBuildMode(.ReleaseFast);195 softfloat.setBuildMode(.ReleaseFast);
196 softfloat.setTarget(target);196 softfloat.setTarget(target);
...@@ -298,7 +298,7 @@ pub fn build(b: *Builder) !void {...@@ -298,7 +298,7 @@ pub fn build(b: *Builder) !void {
298 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);298 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
299 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);299 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
300 exe_options.addOption(bool, "value_tracing", value_tracing);300 exe_options.addOption(bool, "value_tracing", value_tracing);
301 exe_options.addOption(bool, "is_stage1", is_stage1);301 exe_options.addOption(bool, "have_stage1", have_stage1);
302 if (tracy) |tracy_path| {302 if (tracy) |tracy_path| {
303 const client_cpp = fs.path.join(303 const client_cpp = fs.path.join(
304 b.allocator,304 b.allocator,
ci/azure/macos_script+6-11
...@@ -34,7 +34,7 @@ git fetch --tags...@@ -34,7 +34,7 @@ git fetch --tags
34mkdir build34mkdir build
35cd build35cd build
36cmake .. \36cmake .. \
37 -DCMAKE_INSTALL_PREFIX="$(pwd)/release" \37 -DCMAKE_INSTALL_PREFIX="$(pwd)/stage2" \
38 -DCMAKE_PREFIX_PATH="$PREFIX" \38 -DCMAKE_PREFIX_PATH="$PREFIX" \
39 -DCMAKE_BUILD_TYPE=Release \39 -DCMAKE_BUILD_TYPE=Release \
40 -DZIG_TARGET_TRIPLE="$TARGET" \40 -DZIG_TARGET_TRIPLE="$TARGET" \
...@@ -52,23 +52,18 @@ make $JOBS install...@@ -52,23 +52,18 @@ make $JOBS install
52# Here we rebuild zig but this time using the Zig binary we just now produced to52# Here we rebuild zig but this time using the Zig binary we just now produced to
53# build zig1.o rather than relying on the one built with stage0. See53# build zig1.o rather than relying on the one built with stage0. See
54# https://github.com/ziglang/zig/issues/6830 for more details.54# https://github.com/ziglang/zig/issues/6830 for more details.
55cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig"55cmake .. -DZIG_EXECUTABLE="$(pwd)/stage2/bin/zig"
56make $JOBS install56make $JOBS install
5757
58# Build stage2 standalone so that we can test stage2 against stage2 compiler-rt.58stage2/bin/zig build -p release -Denable-llvm -Denable-stage1
59release/bin/zig build -p stage2 -Denable-llvm
6059
61stage2/bin/zig build test-behavior
62
63# TODO: upgrade these to test stage2 instead of stage1
64# TODO: upgrade these to test stage3 instead of stage2
65release/bin/zig build test-behavior -Denable-macos-sdk -Domit-stage2
66release/bin/zig build test-compiler-rt -Denable-macos-sdk60release/bin/zig build test-compiler-rt -Denable-macos-sdk
61release/bin/zig build test-behavior -Denable-macos-sdk
67release/bin/zig build test-std -Denable-macos-sdk62release/bin/zig build test-std -Denable-macos-sdk
68release/bin/zig build test-universal-libc -Denable-macos-sdk63release/bin/zig build test-universal-libc -Denable-macos-sdk
69release/bin/zig build test-compare-output -Denable-macos-sdk64release/bin/zig build test-compare-output -Denable-macos-sdk
70release/bin/zig build test-standalone -Denable-macos-sdk65release/bin/zig build test-standalone -Denable-macos-sdk
71release/bin/zig build test-stack-traces -Denable-macos-sdk66release/bin/zig build test-stack-traces -Denable-macos-sdk -fstage1
72release/bin/zig build test-cli -Denable-macos-sdk67release/bin/zig build test-cli -Denable-macos-sdk
73release/bin/zig build test-asm-link -Denable-macos-sdk68release/bin/zig build test-asm-link -Denable-macos-sdk
74release/bin/zig build test-translate-c -Denable-macos-sdk69release/bin/zig build test-translate-c -Denable-macos-sdk
...@@ -76,7 +71,7 @@ release/bin/zig build test-run-translated-c -Denable-macos-sdk...@@ -76,7 +71,7 @@ release/bin/zig build test-run-translated-c -Denable-macos-sdk
76release/bin/zig build docs -Denable-macos-sdk71release/bin/zig build docs -Denable-macos-sdk
77release/bin/zig build test-fmt -Denable-macos-sdk72release/bin/zig build test-fmt -Denable-macos-sdk
78release/bin/zig build test-cases -Denable-macos-sdk -Dsingle-threaded73release/bin/zig build test-cases -Denable-macos-sdk -Dsingle-threaded
79release/bin/zig build test-link -Denable-macos-sdk -Domit-stage274release/bin/zig build test-link -Denable-macos-sdk
8075
81if [ "${BUILD_REASON}" != "PullRequest" ]; then76if [ "${BUILD_REASON}" != "PullRequest" ]; then
82 mv ../LICENSE release/77 mv ../LICENSE release/
ci/azure/pipelines.yml+1-3
...@@ -68,9 +68,7 @@ jobs:...@@ -68,9 +68,7 @@ jobs:
68 & "${ZIGPREFIXPATH}/bin/zig.exe" build `68 & "${ZIGPREFIXPATH}/bin/zig.exe" build `
69 --prefix "$ZIGINSTALLDIR" `69 --prefix "$ZIGINSTALLDIR" `
70 --search-prefix "$ZIGPREFIXPATH" `70 --search-prefix "$ZIGPREFIXPATH" `
71 -Dstage1 `71 -Denable-stage1 `
72 <# stage2 is omitted until we resolve https://github.com/ziglang/zig/issues/6485 #> `
73 -Domit-stage2 `
74 -Dstatic-llvm `72 -Dstatic-llvm `
75 -Drelease `73 -Drelease `
76 -Dstrip `74 -Dstrip `
ci/srht/freebsd_script+5-4
...@@ -38,10 +38,11 @@ cmake .. \...@@ -38,10 +38,11 @@ cmake .. \
38 -GNinja38 -GNinja
39samu install39samu install
4040
41# TODO ld.lld: error: undefined symbol: main41# Here we rebuild zig but this time using the Zig binary we just now produced to
42# >>> referenced by crt1_c.c:75 (/usr/src/lib/csu/amd64/crt1_c.c:75)42# build zig1.o rather than relying on the one built with stage0. This makes it
43# >>> /usr/lib/crt1.o:(_start)43# a stage3 build rather than a stage2 build.
44#release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test44cmake .. -DZIG_EXECUTABLE="$PREFIX/bin/zig"
45samu install
4546
46# Here we skip some tests to save time.47# Here we skip some tests to save time.
47release/bin/zig build test -Dskip-stage1 -Dskip-non-native48release/bin/zig build test -Dskip-stage1 -Dskip-non-native
ci/zinc/linux_test.sh+23-25
...@@ -33,41 +33,39 @@ unset CXX...@@ -33,41 +33,39 @@ unset CXX
3333
34ninja install34ninja install
3535
36STAGE1_ZIG="$DEBUG_STAGING/bin/zig"
37
38# Here we rebuild zig but this time using the Zig binary we just now produced to36# Here we rebuild zig but this time using the Zig binary we just now produced to
39# build zig1.o rather than relying on the one built with stage0. See37# build zig1.o rather than relying on the one built with stage0. See
40# https://github.com/ziglang/zig/issues/6830 for more details.38# https://github.com/ziglang/zig/issues/6830 for more details.
41cmake .. -DZIG_EXECUTABLE="$STAGE1_ZIG"39cmake .. -DZIG_EXECUTABLE="$DEBUG_STAGING/bin/zig"
42ninja install40ninja install
4341
44cd $WORKSPACE42cd $WORKSPACE
4543
44"$DEBUG_STAGING/bin/zig" build -p stage3 -Denable-stage1 -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
45
46# simultaneously test building self-hosted without LLVM and with 32-bit arm
47stage3/bin/zig build -Dtarget=arm-linux-musleabihf
48
46echo "Looking for non-conforming code formatting..."49echo "Looking for non-conforming code formatting..."
47echo "Formatting errors can be fixed by running 'zig fmt' on the files printed here."50echo "Formatting errors can be fixed by running 'zig fmt' on the files printed here."
48$STAGE1_ZIG fmt --check . --exclude test/cases/51stage3/bin/zig fmt --check . --exclude test/cases/
4952
50$STAGE1_ZIG build -p stage2 -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"53stage3/bin/zig build test-compiler-rt -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
51stage2/bin/zig build -p stage3 -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"54stage3/bin/zig build test-behavior -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
52stage3/bin/zig build # test building self-hosted without LLVM55stage3/bin/zig build test-std -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
53stage3/bin/zig build -Dtarget=arm-linux-musleabihf # test building self-hosted for 32-bit arm56stage3/bin/zig build test-universal-libc -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
5457stage3/bin/zig build test-compare-output -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
55stage3/bin/zig build test-compiler-rt -fqemu -fwasmtime -Denable-llvm58stage3/bin/zig build test-asm-link -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
56stage3/bin/zig build test-behavior -fqemu -fwasmtime -Denable-llvm59stage3/bin/zig build test-fmt -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
57stage3/bin/zig build test-std -fqemu -fwasmtime -Denable-llvm60stage3/bin/zig build test-translate-c -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
58stage3/bin/zig build test-universal-libc -fqemu -fwasmtime -Denable-llvm61stage3/bin/zig build test-run-translated-c -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
59stage3/bin/zig build test-compare-output -fqemu -fwasmtime -Denable-llvm62stage3/bin/zig build test-standalone -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
60stage3/bin/zig build test-asm-link -fqemu -fwasmtime -Denable-llvm63stage3/bin/zig build test-cli -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
61stage3/bin/zig build test-fmt -fqemu -fwasmtime -Denable-llvm
62stage3/bin/zig build test-translate-c -fqemu -fwasmtime -Denable-llvm
63stage3/bin/zig build test-run-translated-c -fqemu -fwasmtime -Denable-llvm
64stage3/bin/zig build test-standalone -fqemu -fwasmtime -Denable-llvm
65stage3/bin/zig build test-cli -fqemu -fwasmtime -Denable-llvm
66stage3/bin/zig build test-cases -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"64stage3/bin/zig build test-cases -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
67stage3/bin/zig build test-link -fqemu -fwasmtime -Denable-llvm65stage3/bin/zig build test-link -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
66stage3/bin/zig build docs -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
6867
69$STAGE1_ZIG build test-stack-traces -fqemu -fwasmtime68stage3/bin/zig build test-stack-traces -fqemu -fwasmtime -fstage1
70$STAGE1_ZIG build docs -fqemu -fwasmtime
7169
72# Produce the experimental std lib documentation.70# Produce the experimental std lib documentation.
73mkdir -p "$RELEASE_STAGING/docs/std"71mkdir -p "$RELEASE_STAGING/docs/std"
...@@ -87,7 +85,7 @@ stage3/bin/zig build \...@@ -87,7 +85,7 @@ stage3/bin/zig build \
87 -Drelease \85 -Drelease \
88 -Dstrip \86 -Dstrip \
89 -Dtarget="$TARGET" \87 -Dtarget="$TARGET" \
90 -Dstage188 -Denable-stage1
9189
92# Explicit exit helps show last command duration.90# Explicit exit helps show last command duration.
93exit91exit
doc/docgen.zig+31
...@@ -285,6 +285,7 @@ const Code = struct {...@@ -285,6 +285,7 @@ const Code = struct {
285 link_objects: []const []const u8,285 link_objects: []const []const u8,
286 target_str: ?[]const u8,286 target_str: ?[]const u8,
287 link_libc: bool,287 link_libc: bool,
288 backend_stage1: bool,
288 link_mode: ?std.builtin.LinkMode,289 link_mode: ?std.builtin.LinkMode,
289 disable_cache: bool,290 disable_cache: bool,
290 verbose_cimport: bool,291 verbose_cimport: bool,
...@@ -554,6 +555,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -554,6 +555,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
554 var link_mode: ?std.builtin.LinkMode = null;555 var link_mode: ?std.builtin.LinkMode = null;
555 var disable_cache = false;556 var disable_cache = false;
556 var verbose_cimport = false;557 var verbose_cimport = false;
558 var backend_stage1 = false;
557559
558 const source_token = while (true) {560 const source_token = while (true) {
559 const content_tok = try eatToken(tokenizer, Token.Id.Content);561 const content_tok = try eatToken(tokenizer, Token.Id.Content);
...@@ -586,6 +588,8 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -586,6 +588,8 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
586 link_libc = true;588 link_libc = true;
587 } else if (mem.eql(u8, end_tag_name, "link_mode_dynamic")) {589 } else if (mem.eql(u8, end_tag_name, "link_mode_dynamic")) {
588 link_mode = .Dynamic;590 link_mode = .Dynamic;
591 } else if (mem.eql(u8, end_tag_name, "backend_stage1")) {
592 backend_stage1 = true;
589 } else if (mem.eql(u8, end_tag_name, "code_end")) {593 } else if (mem.eql(u8, end_tag_name, "code_end")) {
590 _ = try eatToken(tokenizer, Token.Id.BracketClose);594 _ = try eatToken(tokenizer, Token.Id.BracketClose);
591 break content_tok;595 break content_tok;
...@@ -609,6 +613,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -609,6 +613,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
609 .link_objects = link_objects.toOwnedSlice(),613 .link_objects = link_objects.toOwnedSlice(),
610 .target_str = target_str,614 .target_str = target_str,
611 .link_libc = link_libc,615 .link_libc = link_libc,
616 .backend_stage1 = backend_stage1,
612 .link_mode = link_mode,617 .link_mode = link_mode,
613 .disable_cache = disable_cache,618 .disable_cache = disable_cache,
614 .verbose_cimport = verbose_cimport,619 .verbose_cimport = verbose_cimport,
...@@ -1187,6 +1192,9 @@ fn printShell(out: anytype, shell_content: []const u8) !void {...@@ -1187,6 +1192,9 @@ fn printShell(out: anytype, shell_content: []const u8) !void {
1187 try out.writeAll("</samp></pre></figure>");1192 try out.writeAll("</samp></pre></figure>");
1188}1193}
11891194
1195// Override this to skip to later tests
1196const debug_start_line = 0;
1197
1190fn genHtml(1198fn genHtml(
1191 allocator: Allocator,1199 allocator: Allocator,
1192 tokenizer: *Tokenizer,1200 tokenizer: *Tokenizer,
...@@ -1266,6 +1274,13 @@ fn genHtml(...@@ -1266,6 +1274,13 @@ fn genHtml(
1266 continue;1274 continue;
1267 }1275 }
12681276
1277 if (debug_start_line > 0) {
1278 const loc = tokenizer.getTokenLocation(code.source_token);
1279 if (debug_start_line > loc.line) {
1280 continue;
1281 }
1282 }
1283
1269 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];1284 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];
1270 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");1285 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");
1271 const tmp_source_file_name = try fs.path.join(1286 const tmp_source_file_name = try fs.path.join(
...@@ -1311,6 +1326,10 @@ fn genHtml(...@@ -1311,6 +1326,10 @@ fn genHtml(
1311 try build_args.append("-lc");1326 try build_args.append("-lc");
1312 try shell_out.print("-lc ", .{});1327 try shell_out.print("-lc ", .{});
1313 }1328 }
1329 if (code.backend_stage1) {
1330 try build_args.append("-fstage1");
1331 try shell_out.print("-fstage1", .{});
1332 }
1314 const target = try std.zig.CrossTarget.parse(.{1333 const target = try std.zig.CrossTarget.parse(.{
1315 .arch_os_abi = code.target_str orelse "native",1334 .arch_os_abi = code.target_str orelse "native",
1316 });1335 });
...@@ -1443,6 +1462,10 @@ fn genHtml(...@@ -1443,6 +1462,10 @@ fn genHtml(
1443 try test_args.append("-lc");1462 try test_args.append("-lc");
1444 try shell_out.print("-lc ", .{});1463 try shell_out.print("-lc ", .{});
1445 }1464 }
1465 if (code.backend_stage1) {
1466 try test_args.append("-fstage1");
1467 try shell_out.print("-fstage1", .{});
1468 }
1446 if (code.target_str) |triple| {1469 if (code.target_str) |triple| {
1447 try test_args.appendSlice(&[_][]const u8{ "-target", triple });1470 try test_args.appendSlice(&[_][]const u8{ "-target", triple });
1448 try shell_out.print("-target {s} ", .{triple});1471 try shell_out.print("-target {s} ", .{triple});
...@@ -1490,6 +1513,14 @@ fn genHtml(...@@ -1490,6 +1513,14 @@ fn genHtml(
1490 try shell_out.print("-O {s} ", .{@tagName(code.mode)});1513 try shell_out.print("-O {s} ", .{@tagName(code.mode)});
1491 },1514 },
1492 }1515 }
1516 if (code.link_libc) {
1517 try test_args.append("-lc");
1518 try shell_out.print("-lc ", .{});
1519 }
1520 if (code.backend_stage1) {
1521 try test_args.append("-fstage1");
1522 try shell_out.print("-fstage1", .{});
1523 }
1493 const result = try ChildProcess.exec(.{1524 const result = try ChildProcess.exec(.{
1494 .allocator = allocator,1525 .allocator = allocator,
1495 .argv = test_args.items,1526 .argv = test_args.items,
doc/langref.html.in+69-109
...@@ -1188,6 +1188,7 @@ test "this will be skipped" {...@@ -1188,6 +1188,7 @@ test "this will be skipped" {
1188 (The evented IO mode is enabled using the <kbd>--test-evented-io</kbd> command line parameter.)1188 (The evented IO mode is enabled using the <kbd>--test-evented-io</kbd> command line parameter.)
1189 </p>1189 </p>
1190 {#code_begin|test|async_skip#}1190 {#code_begin|test|async_skip#}
1191 {#backend_stage1#}
1191const std = @import("std");1192const std = @import("std");
11921193
1193test "async skip test" {1194test "async skip test" {
...@@ -2768,7 +2769,7 @@ test "comptime @intToPtr" {...@@ -2768,7 +2769,7 @@ test "comptime @intToPtr" {
2768 }2769 }
2769}2770}
2770 {#code_end#}2771 {#code_end#}
2771 {#see_also|Optional Pointers|@intToPtr|@ptrToInt|C Pointers|Pointers to Zero Bit Types#}2772 {#see_also|Optional Pointers|@intToPtr|@ptrToInt|C Pointers#}
2772 {#header_open|volatile#}2773 {#header_open|volatile#}
2773 <p>Loads and stores are assumed to not have side effects. If a given load or store2774 <p>Loads and stores are assumed to not have side effects. If a given load or store
2774 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.2775 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
...@@ -2862,19 +2863,22 @@ var foo: u8 align(4) = 100;...@@ -2862,19 +2863,22 @@ var foo: u8 align(4) = 100;
2862test "global variable alignment" {2863test "global variable alignment" {
2863 try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);2864 try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
2864 try expect(@TypeOf(&foo) == *align(4) u8);2865 try expect(@TypeOf(&foo) == *align(4) u8);
2865 const as_pointer_to_array: *[1]u8 = &foo;2866 const as_pointer_to_array: *align(4) [1]u8 = &foo;
2866 const as_slice: []u8 = as_pointer_to_array;2867 const as_slice: []align(4) u8 = as_pointer_to_array;
2867 try expect(@TypeOf(as_slice) == []align(4) u8);2868 const as_unaligned_slice: []u8 = as_slice;
2869 try expect(as_unaligned_slice[0] == 100);
2868}2870}
28692871
2870fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }2872fn derp() align(@sizeOf(usize) * 2) i32 {
2873 return 1234;
2874}
2871fn noop1() align(1) void {}2875fn noop1() align(1) void {}
2872fn noop4() align(4) void {}2876fn noop4() align(4) void {}
28732877
2874test "function alignment" {2878test "function alignment" {
2875 try expect(derp() == 1234);2879 try expect(derp() == 1234);
2876 try expect(@TypeOf(noop1) == fn() align(1) void);2880 try expect(@TypeOf(noop1) == fn () align(1) void);
2877 try expect(@TypeOf(noop4) == fn() align(4) void);2881 try expect(@TypeOf(noop4) == fn () align(4) void);
2878 noop1();2882 noop1();
2879 noop4();2883 noop4();
2880}2884}
...@@ -3336,6 +3340,7 @@ fn doTheTest() !void {...@@ -3336,6 +3340,7 @@ fn doTheTest() !void {
3336 Zig allows the address to be taken of a non-byte-aligned field:3340 Zig allows the address to be taken of a non-byte-aligned field:
3337 </p>3341 </p>
3338 {#code_begin|test|pointer_to_non-byte_aligned_field#}3342 {#code_begin|test|pointer_to_non-byte_aligned_field#}
3343 {#backend_stage1#}
3339const std = @import("std");3344const std = @import("std");
3340const expect = std.testing.expect;3345const expect = std.testing.expect;
33413346
...@@ -3391,7 +3396,8 @@ fn bar(x: *const u3) u3 {...@@ -3391,7 +3396,8 @@ fn bar(x: *const u3) u3 {
3391 <p>3396 <p>
3392 Pointers to non-ABI-aligned fields share the same address as the other fields within their host integer:3397 Pointers to non-ABI-aligned fields share the same address as the other fields within their host integer:
3393 </p>3398 </p>
3394 {#code_begin|test|pointer_to_non-bit_aligned_field#}3399 {#code_begin|test|packed_struct_field_addrs#}
3400 {#backend_stage1#}
3395const std = @import("std");3401const std = @import("std");
3396const expect = std.testing.expect;3402const expect = std.testing.expect;
33973403
...@@ -3407,7 +3413,7 @@ var bit_field = BitField{...@@ -3407,7 +3413,7 @@ var bit_field = BitField{
3407 .c = 3,3413 .c = 3,
3408};3414};
34093415
3410test "pointer to non-bit-aligned field" {3416test "pointers of sub-byte-aligned fields share addresses" {
3411 try expect(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.b));3417 try expect(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.b));
3412 try expect(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.c));3418 try expect(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.c));
3413}3419}
...@@ -3438,20 +3444,22 @@ test "pointer to non-bit-aligned field" {...@@ -3438,20 +3444,22 @@ test "pointer to non-bit-aligned field" {
3438}3444}
3439 {#code_end#}3445 {#code_end#}
3440 <p>3446 <p>
3441 Packed structs have 1-byte alignment. However if you have an overaligned pointer to a packed struct,3447 Packed structs have the same alignment as their backing integer, however, overaligned
3442 Zig should correctly understand the alignment of fields. However there is3448 pointers to packed structs can override this:
3443 <a href="https://github.com/ziglang/zig/issues/1994">a bug</a>:
3444 </p>3449 </p>
3445 {#code_begin|test_err|expected type '*u32', found '*align(1) u32'#}3450 {#code_begin|test|overaligned_packed_struct#}
3451const std = @import("std");
3452const expect = std.testing.expect;
3453
3446const S = packed struct {3454const S = packed struct {
3447 a: u32,3455 a: u32,
3448 b: u32,3456 b: u32,
3449};3457};
3450test "overaligned pointer to packed struct" {3458test "overaligned pointer to packed struct" {
3451 var foo: S align(4) = undefined;3459 var foo: S align(4) = .{ .a = 1, .b = 2 };
3452 const ptr: *align(4) S = &foo;3460 const ptr: *align(4) S = &foo;
3453 const ptr_to_b: *u32 = &ptr.b;3461 const ptr_to_b: *u32 = &ptr.b;
3454 _ = ptr_to_b;3462 try expect(ptr_to_b.* == 2);
3455}3463}
3456 {#code_end#}3464 {#code_end#}
3457 <p>When this bug is fixed, the above test in the documentation will unexpectedly pass, which will3465 <p>When this bug is fixed, the above test in the documentation will unexpectedly pass, which will
...@@ -3698,7 +3706,7 @@ test "@tagName" {...@@ -3698,7 +3706,7 @@ test "@tagName" {
3698 <p>3706 <p>
3699 By default, enums are not guaranteed to be compatible with the C ABI:3707 By default, enums are not guaranteed to be compatible with the C ABI:
3700 </p>3708 </p>
3701 {#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'C'#}3709 {#code_begin|obj_err|parameter of type 'test.Foo' not allowed in function with calling convention 'C'#}
3702const Foo = enum { a, b, c };3710const Foo = enum { a, b, c };
3703export fn entry(foo: Foo) void { _ = foo; }3711export fn entry(foo: Foo) void { _ = foo; }
3704 {#code_end#}3712 {#code_end#}
...@@ -4004,7 +4012,7 @@ fn makeNumber() Number {...@@ -4004,7 +4012,7 @@ fn makeNumber() Number {
4004 This is typically used for type safety when interacting with C code that does not expose struct details.4012 This is typically used for type safety when interacting with C code that does not expose struct details.
4005 Example:4013 Example:
4006 </p>4014 </p>
4007 {#code_begin|test_err|expected type '*Derp', found '*Wat'#}4015 {#code_begin|test_err|expected type '*test.Derp', found '*test.Wat'#}
4008const Derp = opaque {};4016const Derp = opaque {};
4009const Wat = opaque {};4017const Wat = opaque {};
40104018
...@@ -4203,7 +4211,7 @@ test "switch on tagged union" {...@@ -4203,7 +4211,7 @@ test "switch on tagged union" {
4203 When a {#syntax#}switch{#endsyntax#} expression does not have an {#syntax#}else{#endsyntax#} clause,4211 When a {#syntax#}switch{#endsyntax#} expression does not have an {#syntax#}else{#endsyntax#} clause,
4204 it must exhaustively list all the possible values. Failure to do so is a compile error:4212 it must exhaustively list all the possible values. Failure to do so is a compile error:
4205 </p>4213 </p>
4206 {#code_begin|test_err|not handled in switch#}4214 {#code_begin|test_err|unhandled enumeration value#}
4207const Color = enum {4215const Color = enum {
4208 auto,4216 auto,
4209 off,4217 off,
...@@ -5026,17 +5034,9 @@ test "function" {...@@ -5026,17 +5034,9 @@ test "function" {
5026 try expect(do_op(sub2, 5, 6) == -1);5034 try expect(do_op(sub2, 5, 6) == -1);
5027}5035}
5028 {#code_end#}5036 {#code_end#}
5029 <p>Function values are like pointers:</p>5037 <p>There is a difference between a function <em>body</em> and a function <em>pointer</em>.
5030 {#code_begin|obj#}5038 Function bodies are {#link|comptime#}-only types while function {#link|Pointers#} may be
5031const assert = @import("std").debug.assert;5039 runtime-known.</p>
5032
5033comptime {
5034 assert(@TypeOf(foo) == fn()void);
5035 assert(@sizeOf(fn()void) == @sizeOf(?fn()void));
5036}
5037
5038fn foo() void { }
5039 {#code_end#}
5040 {#header_open|Pass-by-value Parameters#}5040 {#header_open|Pass-by-value Parameters#}
5041 <p>5041 <p>
5042 Primitive types such as {#link|Integers#} and {#link|Floats#} passed as parameters5042 Primitive types such as {#link|Integers#} and {#link|Floats#} passed as parameters
...@@ -6123,10 +6123,11 @@ test "float widening" {...@@ -6123,10 +6123,11 @@ test "float widening" {
6123 two choices about the coercion.6123 two choices about the coercion.
6124 </p>6124 </p>
6125 <ul>6125 <ul>
6126 <li> Cast {#syntax#}54.0{#endsyntax#} to {#syntax#}comptime_int{#endsyntax#} resulting in {#syntax#}@as(comptime_int, 10){#endsyntax#}, which is casted to {#syntax#}@as(f32, 10){#endsyntax#}</li>6126 <li>Cast {#syntax#}54.0{#endsyntax#} to {#syntax#}comptime_int{#endsyntax#} resulting in {#syntax#}@as(comptime_int, 10){#endsyntax#}, which is casted to {#syntax#}@as(f32, 10){#endsyntax#}</li>
6127 <li> Cast {#syntax#}5{#endsyntax#} to {#syntax#}comptime_float{#endsyntax#} resulting in {#syntax#}@as(comptime_float, 10.8){#endsyntax#}, which is casted to {#syntax#}@as(f32, 10.8){#endsyntax#}</li>6127 <li>Cast {#syntax#}5{#endsyntax#} to {#syntax#}comptime_float{#endsyntax#} resulting in {#syntax#}@as(comptime_float, 10.8){#endsyntax#}, which is casted to {#syntax#}@as(f32, 10.8){#endsyntax#}</li>
6128 </ul>6128 </ul>
6129 {#code_begin|test_err#}6129 {#code_begin|test_err#}
6130 {#backend_stage1#}
6130// Compile time coercion of float to int6131// Compile time coercion of float to int
6131test "implicit cast to comptime_int" {6132test "implicit cast to comptime_int" {
6132 var f: f32 = 54.0 / 5;6133 var f: f32 = 54.0 / 5;
...@@ -6302,19 +6303,6 @@ test "coercion between unions and enums" {...@@ -6302,19 +6303,6 @@ test "coercion between unions and enums" {
6302 {#code_end#}6303 {#code_end#}
6303 {#see_also|union|enum#}6304 {#see_also|union|enum#}
6304 {#header_close#}6305 {#header_close#}
6305 {#header_open|Type Coercion: Zero Bit Types#}
6306 <p>{#link|Zero Bit Types#} may be coerced to single-item {#link|Pointers#},
6307 regardless of const.</p>
6308 <p>TODO document the reasoning for this</p>
6309 <p>TODO document whether vice versa should work and why</p>
6310 {#code_begin|test|coerce_zero_bit_types#}
6311test "coercion of zero bit types" {
6312 var x: void = {};
6313 var y: *void = x;
6314 _ = y;
6315}
6316 {#code_end#}
6317 {#header_close#}
6318 {#header_open|Type Coercion: undefined#}6306 {#header_open|Type Coercion: undefined#}
6319 <p>{#link|undefined#} can be cast to any type.</p>6307 <p>{#link|undefined#} can be cast to any type.</p>
6320 {#header_close#}6308 {#header_close#}
...@@ -6467,7 +6455,6 @@ test "peer type resolution: *const T and ?*T" {...@@ -6467,7 +6455,6 @@ test "peer type resolution: *const T and ?*T" {
6467 <li>An {#link|enum#} with only 1 tag.</li>6455 <li>An {#link|enum#} with only 1 tag.</li>
6468 <li>A {#link|struct#} with all fields being zero bit types.</li>6456 <li>A {#link|struct#} with all fields being zero bit types.</li>
6469 <li>A {#link|union#} with only 1 field which is a zero bit type.</li>6457 <li>A {#link|union#} with only 1 field which is a zero bit type.</li>
6470 <li>{#link|Pointers to Zero Bit Types#} are themselves zero bit types.</li>
6471 </ul>6458 </ul>
6472 <p>6459 <p>
6473 These types can only ever have one possible value, and thus6460 These types can only ever have one possible value, and thus
...@@ -6527,7 +6514,7 @@ test "turn HashMap into a set with void" {...@@ -6527,7 +6514,7 @@ test "turn HashMap into a set with void" {
6527 <p>6514 <p>
6528 Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example:6515 Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example:
6529 </p>6516 </p>
6530 {#code_begin|test_err|expression value is ignored#}6517 {#code_begin|test_err|ignored#}
6531test "ignoring expression value" {6518test "ignoring expression value" {
6532 foo();6519 foo();
6533}6520}
...@@ -6553,37 +6540,6 @@ fn foo() i32 {...@@ -6553,37 +6540,6 @@ fn foo() i32 {
6553}6540}
6554 {#code_end#}6541 {#code_end#}
6555 {#header_close#}6542 {#header_close#}
6556
6557 {#header_open|Pointers to Zero Bit Types#}
6558 <p>Pointers to zero bit types also have zero bits. They always compare equal to each other:</p>
6559 {#code_begin|test|pointers_to_zero_bits#}
6560const std = @import("std");
6561const expect = std.testing.expect;
6562
6563test "pointer to empty struct" {
6564 const Empty = struct {};
6565 var a = Empty{};
6566 var b = Empty{};
6567 var ptr_a = &a;
6568 var ptr_b = &b;
6569 comptime try expect(ptr_a == ptr_b);
6570}
6571 {#code_end#}
6572 <p>The type being pointed to can only ever be one value; therefore loads and stores are
6573 never generated. {#link|ptrToInt#} and {#link|intToPtr#} are not allowed:</p>
6574 {#code_begin|test_err#}
6575const Empty = struct {};
6576
6577test "@ptrToInt for pointer to zero bit type" {
6578 var a = Empty{};
6579 _ = @ptrToInt(&a);
6580}
6581
6582test "@intToPtr for pointer to zero bit type" {
6583 _ = @intToPtr(*Empty, 0x1);
6584}
6585 {#code_end#}
6586 {#header_close#}
6587 {#header_close#}6543 {#header_close#}
65886544
6589 {#header_open|Result Location Semantics#}6545 {#header_open|Result Location Semantics#}
...@@ -6666,7 +6622,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {...@@ -6666,7 +6622,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
6666 <p>6622 <p>
6667 For example, if we were to introduce another function to the above snippet:6623 For example, if we were to introduce another function to the above snippet:
6668 </p>6624 </p>
6669 {#code_begin|test_err|values of type 'type' must be comptime known#}6625 {#code_begin|test_err|value with comptime only type 'type' depends on runtime control flow#}
6670fn max(comptime T: type, a: T, b: T) T {6626fn max(comptime T: type, a: T, b: T) T {
6671 return if (a > b) a else b;6627 return if (a > b) a else b;
6672}6628}
...@@ -6692,7 +6648,7 @@ fn foo(condition: bool) void {...@@ -6692,7 +6648,7 @@ fn foo(condition: bool) void {
6692 <p>6648 <p>
6693 For example:6649 For example:
6694 </p>6650 </p>
6695 {#code_begin|test_err|operator not allowed for type 'bool'#}6651 {#code_begin|test_err|operator > not allowed for type 'bool'#}
6696fn max(comptime T: type, a: T, b: T) T {6652fn max(comptime T: type, a: T, b: T) T {
6697 return if (a > b) a else b;6653 return if (a > b) a else b;
6698}6654}
...@@ -6837,7 +6793,7 @@ fn performFn(start_value: i32) i32 {...@@ -6837,7 +6793,7 @@ fn performFn(start_value: i32) i32 {
6837 use a {#syntax#}comptime{#endsyntax#} expression to guarantee that the expression will be evaluated at compile-time.6793 use a {#syntax#}comptime{#endsyntax#} expression to guarantee that the expression will be evaluated at compile-time.
6838 If this cannot be accomplished, the compiler will emit an error. For example:6794 If this cannot be accomplished, the compiler will emit an error. For example:
6839 </p>6795 </p>
6840 {#code_begin|test_err|unable to evaluate constant expression#}6796 {#code_begin|test_err|comptime call of extern function#}
6841extern fn exit() noreturn;6797extern fn exit() noreturn;
68426798
6843test "foo" {6799test "foo" {
...@@ -6889,7 +6845,7 @@ test "fibonacci" {...@@ -6889,7 +6845,7 @@ test "fibonacci" {
6889 <p>6845 <p>
6890 Imagine if we had forgotten the base case of the recursive function and tried to run the tests:6846 Imagine if we had forgotten the base case of the recursive function and tried to run the tests:
6891 </p>6847 </p>
6892 {#code_begin|test_err|operation caused overflow#}6848 {#code_begin|test_err|overflow of integer type#}
6893const expect = @import("std").testing.expect;6849const expect = @import("std").testing.expect;
68946850
6895fn fibonacci(index: u32) u32 {6851fn fibonacci(index: u32) u32 {
...@@ -6913,7 +6869,8 @@ test "fibonacci" {...@@ -6913,7 +6869,8 @@ test "fibonacci" {
6913 But what would have happened if we used a signed integer?6869 But what would have happened if we used a signed integer?
6914 </p>6870 </p>
6915 {#code_begin|test_err|evaluation exceeded 1000 backwards branches#}6871 {#code_begin|test_err|evaluation exceeded 1000 backwards branches#}
6916const expect = @import("std").testing.expect;6872 {#backend_stage1#}
6873const assert = @import("std").debug.assert;
69176874
6918fn fibonacci(index: i32) i32 {6875fn fibonacci(index: i32) i32 {
6919 //if (index < 2) return index;6876 //if (index < 2) return index;
...@@ -6922,7 +6879,7 @@ fn fibonacci(index: i32) i32 {...@@ -6922,7 +6879,7 @@ fn fibonacci(index: i32) i32 {
69226879
6923test "fibonacci" {6880test "fibonacci" {
6924 comptime {6881 comptime {
6925 try expect(fibonacci(7) == 13);6882 try assert(fibonacci(7) == 13);
6926 }6883 }
6927}6884}
6928 {#code_end#}6885 {#code_end#}
...@@ -6935,8 +6892,8 @@ test "fibonacci" {...@@ -6935,8 +6892,8 @@ test "fibonacci" {
6935 <p>6892 <p>
6936 What if we fix the base case, but put the wrong value in the {#syntax#}expect{#endsyntax#} line?6893 What if we fix the base case, but put the wrong value in the {#syntax#}expect{#endsyntax#} line?
6937 </p>6894 </p>
6938 {#code_begin|test_err|test "fibonacci"... FAIL (TestUnexpectedResult)#}6895 {#code_begin|test_err|reached unreachable#}
6939const expect = @import("std").testing.expect;6896const assert = @import("std").debug.assert;
69406897
6941fn fibonacci(index: i32) i32 {6898fn fibonacci(index: i32) i32 {
6942 if (index < 2) return index;6899 if (index < 2) return index;
...@@ -6945,16 +6902,10 @@ fn fibonacci(index: i32) i32 {...@@ -6945,16 +6902,10 @@ fn fibonacci(index: i32) i32 {
69456902
6946test "fibonacci" {6903test "fibonacci" {
6947 comptime {6904 comptime {
6948 try expect(fibonacci(7) == 99999);6905 try assert(fibonacci(7) == 99999);
6949 }6906 }
6950}6907}
6951 {#code_end#}6908 {#code_end#}
6952 <p>
6953 What happened is Zig started interpreting the {#syntax#}expect{#endsyntax#} function with the
6954 parameter {#syntax#}ok{#endsyntax#} set to {#syntax#}false{#endsyntax#}. When the interpreter hit
6955 {#syntax#}@panic{#endsyntax#} it emitted a compile error because a panic during compile
6956 causes a compile error if it is detected at compile-time.
6957 </p>
69586909
6959 <p>6910 <p>
6960 At container level (outside of any function), all expressions are implicitly6911 At container level (outside of any function), all expressions are implicitly
...@@ -7280,6 +7231,7 @@ pub fn main() void {...@@ -7280,6 +7231,7 @@ pub fn main() void {
7280 </p>7231 </p>
7281 {#code_begin|exe#}7232 {#code_begin|exe#}
7282 {#target_linux_x86_64#}7233 {#target_linux_x86_64#}
7234 {#backend_stage1#}
7283pub fn main() noreturn {7235pub fn main() noreturn {
7284 const msg = "hello world\n";7236 const msg = "hello world\n";
7285 _ = syscall3(SYS_write, STDOUT_FILENO, @ptrToInt(msg), msg.len);7237 _ = syscall3(SYS_write, STDOUT_FILENO, @ptrToInt(msg), msg.len);
...@@ -7497,6 +7449,7 @@ test "global assembly" {...@@ -7497,6 +7449,7 @@ test "global assembly" {
7497 or resumer (in the case of subsequent suspensions).7449 or resumer (in the case of subsequent suspensions).
7498 </p>7450 </p>
7499 {#code_begin|test|suspend_no_resume#}7451 {#code_begin|test|suspend_no_resume#}
7452 {#backend_stage1#}
7500const std = @import("std");7453const std = @import("std");
7501const expect = std.testing.expect;7454const expect = std.testing.expect;
75027455
...@@ -7524,6 +7477,7 @@ fn func() void {...@@ -7524,6 +7477,7 @@ fn func() void {
7524 {#link|@frame#} provides access to the async function frame pointer.7477 {#link|@frame#} provides access to the async function frame pointer.
7525 </p>7478 </p>
7526 {#code_begin|test|async_suspend_block#}7479 {#code_begin|test|async_suspend_block#}
7480 {#backend_stage1#}
7527const std = @import("std");7481const std = @import("std");
7528const expect = std.testing.expect;7482const expect = std.testing.expect;
75297483
...@@ -7562,6 +7516,7 @@ fn testSuspendBlock() void {...@@ -7562,6 +7516,7 @@ fn testSuspendBlock() void {
7562 never returns to its resumer and continues executing.7516 never returns to its resumer and continues executing.
7563 </p>7517 </p>
7564 {#code_begin|test|resume_from_suspend#}7518 {#code_begin|test|resume_from_suspend#}
7519 {#backend_stage1#}
7565const std = @import("std");7520const std = @import("std");
7566const expect = std.testing.expect;7521const expect = std.testing.expect;
75677522
...@@ -7598,6 +7553,7 @@ fn testResumeFromSuspend(my_result: *i32) void {...@@ -7598,6 +7553,7 @@ fn testResumeFromSuspend(my_result: *i32) void {
7598 and the return value of the async function would be lost.7553 and the return value of the async function would be lost.
7599 </p>7554 </p>
7600 {#code_begin|test|async_await#}7555 {#code_begin|test|async_await#}
7556 {#backend_stage1#}
7601const std = @import("std");7557const std = @import("std");
7602const expect = std.testing.expect;7558const expect = std.testing.expect;
76037559
...@@ -7642,6 +7598,7 @@ fn func() void {...@@ -7642,6 +7598,7 @@ fn func() void {
7642 return value directly from the target function's frame.7598 return value directly from the target function's frame.
7643 </p>7599 </p>
7644 {#code_begin|test|async_await_sequence#}7600 {#code_begin|test|async_await_sequence#}
7601 {#backend_stage1#}
7645const std = @import("std");7602const std = @import("std");
7646const expect = std.testing.expect;7603const expect = std.testing.expect;
76477604
...@@ -7695,6 +7652,7 @@ fn seq(c: u8) void {...@@ -7695,6 +7652,7 @@ fn seq(c: u8) void {
7695 {#syntax#}async{#endsyntax#}/{#syntax#}await{#endsyntax#} usage:7652 {#syntax#}async{#endsyntax#}/{#syntax#}await{#endsyntax#} usage:
7696 </p>7653 </p>
7697 {#code_begin|exe|async#}7654 {#code_begin|exe|async#}
7655 {#backend_stage1#}
7698const std = @import("std");7656const std = @import("std");
7699const Allocator = std.mem.Allocator;7657const Allocator = std.mem.Allocator;
77007658
...@@ -7773,6 +7731,7 @@ fn readFile(allocator: Allocator, filename: []const u8) ![]u8 {...@@ -7773,6 +7731,7 @@ fn readFile(allocator: Allocator, filename: []const u8) ![]u8 {
7773 observe the same behavior, with one tiny difference:7731 observe the same behavior, with one tiny difference:
7774 </p>7732 </p>
7775 {#code_begin|exe|blocking#}7733 {#code_begin|exe|blocking#}
7734 {#backend_stage1#}
7776const std = @import("std");7735const std = @import("std");
7777const Allocator = std.mem.Allocator;7736const Allocator = std.mem.Allocator;
77787737
...@@ -7910,6 +7869,7 @@ comptime {...@@ -7910,6 +7869,7 @@ comptime {
7910 {#syntax#}await{#endsyntax#} will copy the result from {#syntax#}result_ptr{#endsyntax#}.7869 {#syntax#}await{#endsyntax#} will copy the result from {#syntax#}result_ptr{#endsyntax#}.
7911 </p>7870 </p>
7912 {#code_begin|test|async_struct_field_fn_pointer#}7871 {#code_begin|test|async_struct_field_fn_pointer#}
7872 {#backend_stage1#}
7913const std = @import("std");7873const std = @import("std");
7914const expect = std.testing.expect;7874const expect = std.testing.expect;
79157875
...@@ -8677,6 +8637,7 @@ test "decl access by string" {...@@ -8677,6 +8637,7 @@ test "decl access by string" {
8677 allows one to, for example, heap-allocate an async function frame:8637 allows one to, for example, heap-allocate an async function frame:
8678 </p>8638 </p>
8679 {#code_begin|test|heap_allocated_frame#}8639 {#code_begin|test|heap_allocated_frame#}
8640 {#backend_stage1#}
8680const std = @import("std");8641const std = @import("std");
86818642
8682test "heap allocated frame" {8643test "heap allocated frame" {
...@@ -9423,12 +9384,6 @@ const std = @import("std");...@@ -9423,12 +9384,6 @@ const std = @import("std");
9423const expect = std.testing.expect;9384const expect = std.testing.expect;
94249385
9425test "vector @reduce" {9386test "vector @reduce" {
9426 // This test regressed with LLVM 14:
9427 // https://github.com/llvm/llvm-project/issues/55522
9428 // We'll skip this test unless the self-hosted compiler is being used.
9429 // After LLVM 15 is released we can delete this line.
9430 if (@import("builtin").zig_backend == .stage1) return;
9431
9432 const value = @Vector(4, i32){ 1, -1, 1, -1 };9387 const value = @Vector(4, i32){ 1, -1, 1, -1 };
9433 const result = value > @splat(4, @as(i32, 0));9388 const result = value > @splat(4, @as(i32, 0));
9434 // result is { true, false, true, false };9389 // result is { true, false, true, false };
...@@ -9938,7 +9893,7 @@ pub fn main() void {...@@ -9938,7 +9893,7 @@ pub fn main() void {
9938 {#header_close#}9893 {#header_close#}
9939 {#header_open|Index out of Bounds#}9894 {#header_open|Index out of Bounds#}
9940 <p>At compile-time:</p>9895 <p>At compile-time:</p>
9941 {#code_begin|test_err|index 5 outside array of size 5#}9896 {#code_begin|test_err|index 5 outside array of length 5#}
9942comptime {9897comptime {
9943 const array: [5]u8 = "hello".*;9898 const array: [5]u8 = "hello".*;
9944 const garbage = array[5];9899 const garbage = array[5];
...@@ -9959,9 +9914,9 @@ fn foo(x: []const u8) u8 {...@@ -9959,9 +9914,9 @@ fn foo(x: []const u8) u8 {
9959 {#header_close#}9914 {#header_close#}
9960 {#header_open|Cast Negative Number to Unsigned Integer#}9915 {#header_open|Cast Negative Number to Unsigned Integer#}
9961 <p>At compile-time:</p>9916 <p>At compile-time:</p>
9962 {#code_begin|test_err|attempt to cast negative value to unsigned integer#}9917 {#code_begin|test_err|type 'u32' cannot represent integer value '-1'#}
9963comptime {9918comptime {
9964 const value: i32 = -1;9919 var value: i32 = -1;
9965 const unsigned = @intCast(u32, value);9920 const unsigned = @intCast(u32, value);
9966 _ = unsigned;9921 _ = unsigned;
9967}9922}
...@@ -9982,7 +9937,7 @@ pub fn main() void {...@@ -9982,7 +9937,7 @@ pub fn main() void {
9982 {#header_close#}9937 {#header_close#}
9983 {#header_open|Cast Truncates Data#}9938 {#header_open|Cast Truncates Data#}
9984 <p>At compile-time:</p>9939 <p>At compile-time:</p>
9985 {#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#}9940 {#code_begin|test_err|type 'u8' cannot represent integer value '300'#}
9986comptime {9941comptime {
9987 const spartan_count: u16 = 300;9942 const spartan_count: u16 = 300;
9988 const byte = @intCast(u8, spartan_count);9943 const byte = @intCast(u8, spartan_count);
...@@ -10017,7 +9972,7 @@ pub fn main() void {...@@ -10017,7 +9972,7 @@ pub fn main() void {
10017 <li>{#link|@divExact#} (division)</li>9972 <li>{#link|@divExact#} (division)</li>
10018 </ul>9973 </ul>
10019 <p>Example with addition at compile-time:</p>9974 <p>Example with addition at compile-time:</p>
10020 {#code_begin|test_err|operation caused overflow#}9975 {#code_begin|test_err|overflow of integer type 'u8' with value '256'#}
10021comptime {9976comptime {
10022 var byte: u8 = 255;9977 var byte: u8 = 255;
10023 byte += 1;9978 byte += 1;
...@@ -10118,6 +10073,7 @@ test "wraparound addition and subtraction" {...@@ -10118,6 +10073,7 @@ test "wraparound addition and subtraction" {
10118 {#header_open|Exact Left Shift Overflow#}10073 {#header_open|Exact Left Shift Overflow#}
10119 <p>At compile-time:</p>10074 <p>At compile-time:</p>
10120 {#code_begin|test_err|operation caused overflow#}10075 {#code_begin|test_err|operation caused overflow#}
10076 {#backend_stage1#}
10121comptime {10077comptime {
10122 const x = @shlExact(@as(u8, 0b01010101), 2);10078 const x = @shlExact(@as(u8, 0b01010101), 2);
10123 _ = x;10079 _ = x;
...@@ -10137,6 +10093,7 @@ pub fn main() void {...@@ -10137,6 +10093,7 @@ pub fn main() void {
10137 {#header_open|Exact Right Shift Overflow#}10093 {#header_open|Exact Right Shift Overflow#}
10138 <p>At compile-time:</p>10094 <p>At compile-time:</p>
10139 {#code_begin|test_err|exact shift shifted out 1 bits#}10095 {#code_begin|test_err|exact shift shifted out 1 bits#}
10096 {#backend_stage1#}
10140comptime {10097comptime {
10141 const x = @shrExact(@as(u8, 0b10101010), 2);10098 const x = @shrExact(@as(u8, 0b10101010), 2);
10142 _ = x;10099 _ = x;
...@@ -10200,6 +10157,7 @@ pub fn main() void {...@@ -10200,6 +10157,7 @@ pub fn main() void {
10200 {#header_open|Exact Division Remainder#}10157 {#header_open|Exact Division Remainder#}
10201 <p>At compile-time:</p>10158 <p>At compile-time:</p>
10202 {#code_begin|test_err|exact division had a remainder#}10159 {#code_begin|test_err|exact division had a remainder#}
10160 {#backend_stage1#}
10203comptime {10161comptime {
10204 const a: u32 = 10;10162 const a: u32 = 10;
10205 const b: u32 = 3;10163 const b: u32 = 3;
...@@ -10302,7 +10260,7 @@ fn getNumberOrFail() !i32 {...@@ -10302,7 +10260,7 @@ fn getNumberOrFail() !i32 {
10302 {#header_close#}10260 {#header_close#}
10303 {#header_open|Invalid Error Code#}10261 {#header_open|Invalid Error Code#}
10304 <p>At compile-time:</p>10262 <p>At compile-time:</p>
10305 {#code_begin|test_err|integer value 11 represents no error#}10263 {#code_begin|test_err|integer value '11' represents no error#}
10306comptime {10264comptime {
10307 const err = error.AnError;10265 const err = error.AnError;
10308 const number = @errorToInt(err) + 10;10266 const number = @errorToInt(err) + 10;
...@@ -10324,7 +10282,7 @@ pub fn main() void {...@@ -10324,7 +10282,7 @@ pub fn main() void {
10324 {#header_close#}10282 {#header_close#}
10325 {#header_open|Invalid Enum Cast#}10283 {#header_open|Invalid Enum Cast#}
10326 <p>At compile-time:</p>10284 <p>At compile-time:</p>
10327 {#code_begin|test_err|has no tag matching integer value 3#}10285 {#code_begin|test_err|enum 'test.Foo' has no tag with value '3'#}
10328const Foo = enum {10286const Foo = enum {
10329 a,10287 a,
10330 b,10288 b,
...@@ -10356,7 +10314,7 @@ pub fn main() void {...@@ -10356,7 +10314,7 @@ pub fn main() void {
1035610314
10357 {#header_open|Invalid Error Set Cast#}10315 {#header_open|Invalid Error Set Cast#}
10358 <p>At compile-time:</p>10316 <p>At compile-time:</p>
10359 {#code_begin|test_err|error.B not a member of error set 'Set2'#}10317 {#code_begin|test_err|'error.B' not a member of error set 'error{A,C}'#}
10360const Set1 = error{10318const Set1 = error{
10361 A,10319 A,
10362 B,10320 B,
...@@ -10417,7 +10375,7 @@ fn foo(bytes: []u8) u32 {...@@ -10417,7 +10375,7 @@ fn foo(bytes: []u8) u32 {
10417 {#header_close#}10375 {#header_close#}
10418 {#header_open|Wrong Union Field Access#}10376 {#header_open|Wrong Union Field Access#}
10419 <p>At compile-time:</p>10377 <p>At compile-time:</p>
10420 {#code_begin|test_err|accessing union field 'float' while field 'int' is set#}10378 {#code_begin|test_err|access of union field 'float' while field 'int' is active#}
10421comptime {10379comptime {
10422 var f = Foo{ .int = 42 };10380 var f = Foo{ .int = 42 };
10423 f.float = 12.34;10381 f.float = 12.34;
...@@ -10509,6 +10467,7 @@ fn bar(f: *Foo) void {...@@ -10509,6 +10467,7 @@ fn bar(f: *Foo) void {
10509 </p>10467 </p>
10510 <p>At compile-time:</p>10468 <p>At compile-time:</p>
10511 {#code_begin|test_err|null pointer casted to type#}10469 {#code_begin|test_err|null pointer casted to type#}
10470 {#backend_stage1#}
10512comptime {10471comptime {
10513 const opt_ptr: ?*i32 = null;10472 const opt_ptr: ?*i32 = null;
10514 const ptr = @ptrCast(*i32, opt_ptr);10473 const ptr = @ptrCast(*i32, opt_ptr);
...@@ -10551,7 +10510,8 @@ const expect = std.testing.expect;...@@ -10551,7 +10510,8 @@ const expect = std.testing.expect;
1055110510
10552test "using an allocator" {10511test "using an allocator" {
10553 var buffer: [100]u8 = undefined;10512 var buffer: [100]u8 = undefined;
10554 const allocator = std.heap.FixedBufferAllocator.init(&buffer).allocator();10513 var fba = std.heap.FixedBufferAllocator.init(&buffer);
10514 const allocator = fba.allocator();
10555 const result = try concat(allocator, "foo", "bar");10515 const result = try concat(allocator, "foo", "bar");
10556 try expect(std.mem.eql(u8, "foobar", result));10516 try expect(std.mem.eql(u8, "foobar", result));
10557}10517}
...@@ -10647,7 +10607,7 @@ pub fn main() !void {...@@ -10647,7 +10607,7 @@ pub fn main() !void {
10647 <p>String literals such as {#syntax#}"foo"{#endsyntax#} are in the global constant data section.10607 <p>String literals such as {#syntax#}"foo"{#endsyntax#} are in the global constant data section.
10648 This is why it is an error to pass a string literal to a mutable slice, like this:10608 This is why it is an error to pass a string literal to a mutable slice, like this:
10649 </p>10609 </p>
10650 {#code_begin|test_err|cannot cast pointer to array literal to slice type '[]u8'#}10610 {#code_begin|test_err|expected type '[]u8', found '*const [5:0]u8'#}
10651fn foo(s: []u8) void {10611fn foo(s: []u8) void {
10652 _ = s;10612 _ = s;
10653}10613}
lib/std/builtin.zig+1-1
...@@ -866,7 +866,7 @@ pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn {...@@ -866,7 +866,7 @@ pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn {
866866
867pub fn panicOutOfBounds(index: usize, len: usize) noreturn {867pub fn panicOutOfBounds(index: usize, len: usize) noreturn {
868 @setCold(true);868 @setCold(true);
869 std.debug.panic("attempt to index out of bound: index {d}, len {d}", .{ index, len });869 std.debug.panic("index out of bounds: index {d}, len {d}", .{ index, len });
870}870}
871871
872pub noinline fn returnError(st: *StackTrace) void {872pub noinline fn returnError(st: *StackTrace) void {
src/Compilation.zig+7-22
...@@ -1040,22 +1040,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1040,22 +1040,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1040 const comp = try arena.create(Compilation);1040 const comp = try arena.create(Compilation);
1041 const root_name = try arena.dupeZ(u8, options.root_name);1041 const root_name = try arena.dupeZ(u8, options.root_name);
10421042
1043 const use_stage1 = options.use_stage1 orelse blk: {1043 const use_stage1 = options.use_stage1 orelse false;
1044 // Even though we may have no Zig code to compile (depending on `options.main_pkg`),
1045 // we may need to use stage1 for building compiler-rt and other dependencies.
1046
1047 if (options.use_llvm) |use_llvm| {
1048 if (!use_llvm) {
1049 break :blk false;
1050 }
1051 }
1052
1053 // If LLVM does not support the target, then we can't use it.
1054 if (!target_util.hasLlvmSupport(options.target, options.target.ofmt))
1055 break :blk false;
1056
1057 break :blk build_options.is_stage1;
1058 };
10591044
1060 const cache_mode = if (use_stage1 and !options.disable_lld_caching)1045 const cache_mode = if (use_stage1 and !options.disable_lld_caching)
1061 CacheMode.whole1046 CacheMode.whole
...@@ -2211,7 +2196,7 @@ pub fn update(comp: *Compilation) !void {...@@ -2211,7 +2196,7 @@ pub fn update(comp: *Compilation) !void {
2211 comp.c_object_work_queue.writeItemAssumeCapacity(key);2196 comp.c_object_work_queue.writeItemAssumeCapacity(key);
2212 }2197 }
22132198
2214 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;2199 const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
2215 if (comp.bin_file.options.module) |module| {2200 if (comp.bin_file.options.module) |module| {
2216 module.compile_log_text.shrinkAndFree(module.gpa, 0);2201 module.compile_log_text.shrinkAndFree(module.gpa, 0);
2217 module.generation += 1;2202 module.generation += 1;
...@@ -2387,7 +2372,7 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {...@@ -2387,7 +2372,7 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
2387 };2372 };
2388 comp.link_error_flags = comp.bin_file.errorFlags();2373 comp.link_error_flags = comp.bin_file.errorFlags();
23892374
2390 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;2375 const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
2391 if (!use_stage1) {2376 if (!use_stage1) {
2392 if (comp.bin_file.options.module) |module| {2377 if (comp.bin_file.options.module) |module| {
2393 try link.File.C.flushEmitH(module);2378 try link.File.C.flushEmitH(module);
...@@ -2845,7 +2830,7 @@ pub fn performAllTheWork(...@@ -2845,7 +2830,7 @@ pub fn performAllTheWork(
2845 comp.work_queue_wait_group.reset();2830 comp.work_queue_wait_group.reset();
2846 defer comp.work_queue_wait_group.wait();2831 defer comp.work_queue_wait_group.wait();
28472832
2848 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;2833 const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
28492834
2850 {2835 {
2851 const astgen_frame = tracy.namedFrame("astgen");2836 const astgen_frame = tracy.namedFrame("astgen");
...@@ -3430,7 +3415,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {...@@ -3430,7 +3415,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
3430 var man = comp.obtainCObjectCacheManifest();3415 var man = comp.obtainCObjectCacheManifest();
3431 defer man.deinit();3416 defer man.deinit();
34323417
3433 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;3418 const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
34343419
3435 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects3420 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
3436 man.hash.add(use_stage1);3421 man.hash.add(use_stage1);
...@@ -4745,7 +4730,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca...@@ -4745,7 +4730,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
47454730
4746 const target = comp.getTarget();4731 const target = comp.getTarget();
4747 const generic_arch_name = target.cpu.arch.genericName();4732 const generic_arch_name = target.cpu.arch.genericName();
4748 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;4733 const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
47494734
4750 const zig_backend: std.builtin.CompilerBackend = blk: {4735 const zig_backend: std.builtin.CompilerBackend = blk: {
4751 if (use_stage1) break :blk .stage1;4736 if (use_stage1) break :blk .stage1;
...@@ -5032,7 +5017,7 @@ fn buildOutputFromZig(...@@ -5032,7 +5017,7 @@ fn buildOutputFromZig(
5032 .link_mode = .Static,5017 .link_mode = .Static,
5033 .function_sections = true,5018 .function_sections = true,
5034 .no_builtin = true,5019 .no_builtin = true,
5035 .use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1,5020 .use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1,
5036 .want_sanitize_c = false,5021 .want_sanitize_c = false,
5037 .want_stack_check = false,5022 .want_stack_check = false,
5038 .want_stack_protector = 0,5023 .want_stack_protector = 0,
src/config.zig.in+1-1
...@@ -8,5 +8,5 @@ pub const enable_logging: bool = @ZIG_ENABLE_LOGGING_BOOL@;...@@ -8,5 +8,5 @@ pub const enable_logging: bool = @ZIG_ENABLE_LOGGING_BOOL@;
8pub const enable_link_snapshots: bool = false;8pub const enable_link_snapshots: bool = false;
9pub const enable_tracy = false;9pub const enable_tracy = false;
10pub const value_tracing = false;10pub const value_tracing = false;
11pub const is_stage1 = true;11pub const have_stage1 = true;
12pub const skip_non_native = false;12pub const skip_non_native = false;
src/link.zig+2-2
...@@ -279,7 +279,7 @@ pub const File = struct {...@@ -279,7 +279,7 @@ pub const File = struct {
279 return &(try MachO.openPath(allocator, options)).base;279 return &(try MachO.openPath(allocator, options)).base;
280 }280 }
281281
282 const use_stage1 = build_options.is_stage1 and options.use_stage1;282 const use_stage1 = build_options.have_stage1 and options.use_stage1;
283 if (use_stage1 or options.emit == null) {283 if (use_stage1 or options.emit == null) {
284 return switch (options.target.ofmt) {284 return switch (options.target.ofmt) {
285 .coff => &(try Coff.createEmpty(allocator, options)).base,285 .coff => &(try Coff.createEmpty(allocator, options)).base,
...@@ -817,7 +817,7 @@ pub const File = struct {...@@ -817,7 +817,7 @@ pub const File = struct {
817 // If there is no Zig code to compile, then we should skip flushing the output file817 // If there is no Zig code to compile, then we should skip flushing the output file
818 // because it will not be part of the linker line anyway.818 // because it will not be part of the linker line anyway.
819 const module_obj_path: ?[]const u8 = if (base.options.module) |module| blk: {819 const module_obj_path: ?[]const u8 = if (base.options.module) |module| blk: {
820 const use_stage1 = build_options.is_stage1 and base.options.use_stage1;820 const use_stage1 = build_options.have_stage1 and base.options.use_stage1;
821 if (use_stage1) {821 if (use_stage1) {
822 const obj_basename = try std.zig.binNameAlloc(arena, .{822 const obj_basename = try std.zig.binNameAlloc(arena, .{
823 .root_name = base.options.root_name,823 .root_name = base.options.root_name,
src/link/Coff.zig+2-2
...@@ -411,7 +411,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff {...@@ -411,7 +411,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff {
411 };411 };
412412
413 const use_llvm = build_options.have_llvm and options.use_llvm;413 const use_llvm = build_options.have_llvm and options.use_llvm;
414 const use_stage1 = build_options.is_stage1 and options.use_stage1;414 const use_stage1 = build_options.have_stage1 and options.use_stage1;
415 if (use_llvm and !use_stage1) {415 if (use_llvm and !use_stage1) {
416 self.llvm_object = try LlvmObject.create(gpa, options);416 self.llvm_object = try LlvmObject.create(gpa, options);
417 }417 }
...@@ -949,7 +949,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -949,7 +949,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
949 // If there is no Zig code to compile, then we should skip flushing the output file because it949 // If there is no Zig code to compile, then we should skip flushing the output file because it
950 // will not be part of the linker line anyway.950 // will not be part of the linker line anyway.
951 const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {951 const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
952 const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;952 const use_stage1 = build_options.have_stage1 and self.base.options.use_stage1;
953 if (use_stage1) {953 if (use_stage1) {
954 const obj_basename = try std.zig.binNameAlloc(arena, .{954 const obj_basename = try std.zig.binNameAlloc(arena, .{
955 .root_name = self.base.options.root_name,955 .root_name = self.base.options.root_name,
src/link/Elf.zig+1-1
...@@ -328,7 +328,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {...@@ -328,7 +328,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
328 .page_size = page_size,328 .page_size = page_size,
329 };329 };
330 const use_llvm = build_options.have_llvm and options.use_llvm;330 const use_llvm = build_options.have_llvm and options.use_llvm;
331 const use_stage1 = build_options.is_stage1 and options.use_stage1;331 const use_stage1 = build_options.have_stage1 and options.use_stage1;
332 if (use_llvm and !use_stage1) {332 if (use_llvm and !use_stage1) {
333 self.llvm_object = try LlvmObject.create(gpa, options);333 self.llvm_object = try LlvmObject.create(gpa, options);
334 }334 }
src/link/MachO.zig+2-2
...@@ -272,7 +272,7 @@ pub const Export = struct {...@@ -272,7 +272,7 @@ pub const Export = struct {
272pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {272pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
273 assert(options.target.ofmt == .macho);273 assert(options.target.ofmt == .macho);
274274
275 const use_stage1 = build_options.is_stage1 and options.use_stage1;275 const use_stage1 = build_options.have_stage1 and options.use_stage1;
276 if (use_stage1 or options.emit == null) {276 if (use_stage1 or options.emit == null) {
277 return createEmpty(allocator, options);277 return createEmpty(allocator, options);
278 }278 }
...@@ -363,7 +363,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {...@@ -363,7 +363,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
363 const cpu_arch = options.target.cpu.arch;363 const cpu_arch = options.target.cpu.arch;
364 const page_size: u16 = if (cpu_arch == .aarch64) 0x4000 else 0x1000;364 const page_size: u16 = if (cpu_arch == .aarch64) 0x4000 else 0x1000;
365 const use_llvm = build_options.have_llvm and options.use_llvm;365 const use_llvm = build_options.have_llvm and options.use_llvm;
366 const use_stage1 = build_options.is_stage1 and options.use_stage1;366 const use_stage1 = build_options.have_stage1 and options.use_stage1;
367367
368 const self = try gpa.create(MachO);368 const self = try gpa.create(MachO);
369 errdefer gpa.destroy(self);369 errdefer gpa.destroy(self);
src/link/Wasm.zig+3-3
...@@ -356,7 +356,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {...@@ -356,7 +356,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
356 }356 }
357357
358 const use_llvm = build_options.have_llvm and options.use_llvm;358 const use_llvm = build_options.have_llvm and options.use_llvm;
359 const use_stage1 = build_options.is_stage1 and options.use_stage1;359 const use_stage1 = build_options.have_stage1 and options.use_stage1;
360 if (use_llvm and !use_stage1) {360 if (use_llvm and !use_stage1) {
361 self.llvm_object = try LlvmObject.create(gpa, options);361 self.llvm_object = try LlvmObject.create(gpa, options);
362 }362 }
...@@ -2593,7 +2593,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2593,7 +2593,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2593 // If there is no Zig code to compile, then we should skip flushing the output file because it2593 // If there is no Zig code to compile, then we should skip flushing the output file because it
2594 // will not be part of the linker line anyway.2594 // will not be part of the linker line anyway.
2595 const module_obj_path: ?[]const u8 = if (self.base.options.module) |mod| blk: {2595 const module_obj_path: ?[]const u8 = if (self.base.options.module) |mod| blk: {
2596 const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;2596 const use_stage1 = build_options.have_stage1 and self.base.options.use_stage1;
2597 if (use_stage1) {2597 if (use_stage1) {
2598 const obj_basename = try std.zig.binNameAlloc(arena, .{2598 const obj_basename = try std.zig.binNameAlloc(arena, .{
2599 .root_name = self.base.options.root_name,2599 .root_name = self.base.options.root_name,
...@@ -2803,7 +2803,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2803,7 +2803,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2803 if (self.base.options.module) |mod| {2803 if (self.base.options.module) |mod| {
2804 // when we use stage1, we use the exports that stage1 provided us.2804 // when we use stage1, we use the exports that stage1 provided us.
2805 // For stage2, we can directly retrieve them from the module.2805 // For stage2, we can directly retrieve them from the module.
2806 const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;2806 const use_stage1 = build_options.have_stage1 and self.base.options.use_stage1;
2807 if (use_stage1) {2807 if (use_stage1) {
2808 for (comp.export_symbol_names.items) |symbol_name| {2808 for (comp.export_symbol_names.items) |symbol_name| {
2809 try argv.append(try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}));2809 try argv.append(try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}));
src/main.zig+1-1
...@@ -2989,7 +2989,7 @@ fn buildOutputType(...@@ -2989,7 +2989,7 @@ fn buildOutputType(
2989 return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));2989 return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
2990 }2990 }
2991 if (arg_mode == .translate_c) {2991 if (arg_mode == .translate_c) {
2992 const stage1_mode = use_stage1 orelse build_options.is_stage1;2992 const stage1_mode = use_stage1 orelse false;
2993 return cmdTranslateC(comp, arena, have_enable_cache, stage1_mode);2993 return cmdTranslateC(comp, arena, have_enable_cache, stage1_mode);
2994 }2994 }
29952995
src/stage1.zig+1-1
...@@ -18,7 +18,7 @@ const target_util = @import("target.zig");...@@ -18,7 +18,7 @@ const target_util = @import("target.zig");
1818
19comptime {19comptime {
20 assert(builtin.link_libc);20 assert(builtin.link_libc);
21 assert(build_options.is_stage1);21 assert(build_options.have_stage1);
22 assert(build_options.have_llvm);22 assert(build_options.have_llvm);
23 if (!builtin.is_test) {23 if (!builtin.is_test) {
24 @export(main, .{ .name = "main" });24 @export(main, .{ .name = "main" });
src/test.zig+1-1
...@@ -25,7 +25,7 @@ const skip_stage1 = builtin.zig_backend != .stage1 or build_options.skip_stage1;...@@ -25,7 +25,7 @@ const skip_stage1 = builtin.zig_backend != .stage1 or build_options.skip_stage1;
25const hr = "=" ** 80;25const hr = "=" ** 80;
2626
27test {27test {
28 if (build_options.is_stage1) {28 if (build_options.have_stage1) {
29 @import("stage1.zig").os_init();29 @import("stage1.zig").os_init();
30 }30 }
3131
test/cases/safety/empty slice with sentinel out of bounds.zig +1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
4 _ = stack_trace;4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to index out of bound: index 1, len 0")) {5 if (std.mem.eql(u8, message, "index out of bounds: index 1, len 0")) {
6 std.process.exit(0);6 std.process.exit(0);
7 }7 }
8 std.process.exit(1);8 std.process.exit(1);
test/cases/safety/out of bounds slice access.zig +3-3
...@@ -2,20 +2,20 @@ const std = @import("std");...@@ -2,20 +2,20 @@ const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
4 _ = stack_trace;4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to index out of bound: index 4, len 4")) {5 if (std.mem.eql(u8, message, "index out of bounds: index 4, len 4")) {
6 std.process.exit(0);6 std.process.exit(0);
7 }7 }
8 std.process.exit(1);8 std.process.exit(1);
9}9}
10pub fn main() !void {10pub fn main() !void {
11 const a = [_]i32{1, 2, 3, 4};11 const a = [_]i32{ 1, 2, 3, 4 };
12 baz(bar(&a));12 baz(bar(&a));
13 return error.TestFailed;13 return error.TestFailed;
14}14}
15fn bar(a: []const i32) i32 {15fn bar(a: []const i32) i32 {
16 return a[4];16 return a[4];
17}17}
18fn baz(_: i32) void { }18fn baz(_: i32) void {}
19// run19// run
20// backend=llvm20// backend=llvm
21// target=native21// target=native
test/cases/safety/slice with sentinel out of bounds - runtime len.zig +1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
4 _ = stack_trace;4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to index out of bound: index 5, len 4")) {5 if (std.mem.eql(u8, message, "index out of bounds: index 5, len 4")) {
6 std.process.exit(0);6 std.process.exit(0);
7 }7 }
8 std.process.exit(1);8 std.process.exit(1);
test/cases/safety/slice with sentinel out of bounds.zig +1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
4 _ = stack_trace;4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "attempt to index out of bound: index 5, len 4")) {5 if (std.mem.eql(u8, message, "index out of bounds: index 5, len 4")) {
6 std.process.exit(0);6 std.process.exit(0);
7 }7 }
8 std.process.exit(1);8 std.process.exit(1);
test/tests.zig+1-2
...@@ -601,7 +601,6 @@ pub fn addPkgTests(...@@ -601,7 +601,6 @@ pub fn addPkgTests(
601 skip_libc: bool,601 skip_libc: bool,
602 skip_stage1: bool,602 skip_stage1: bool,
603 skip_stage2: bool,603 skip_stage2: bool,
604 is_stage1: bool,
605) *build.Step {604) *build.Step {
606 const step = b.step(b.fmt("test-{s}", .{name}), desc);605 const step = b.step(b.fmt("test-{s}", .{name}), desc);
607606
...@@ -630,7 +629,7 @@ pub fn addPkgTests(...@@ -630,7 +629,7 @@ pub fn addPkgTests(
630 if (test_target.backend) |backend| switch (backend) {629 if (test_target.backend) |backend| switch (backend) {
631 .stage1 => if (skip_stage1) continue,630 .stage1 => if (skip_stage1) continue,
632 else => if (skip_stage2) continue,631 else => if (skip_stage2) continue,
633 } else if (is_stage1 and skip_stage1) continue;632 } else if (skip_stage2) continue;
634633
635 const want_this_mode = for (modes) |m| {634 const want_this_mode = for (modes) |m| {
636 if (m == test_target.mode) break true;635 if (m == test_target.mode) break true;