remove -fstage1 option

After this commit, the self-hosted compiler does not offer the option to
use stage1 as a backend anymore.
This commit is contained in:
Andrew Kelley 2022-10-31 20:29:55 -07:00
parent bf316e5506
commit 28514476ef
25 changed files with 97 additions and 463 deletions

View File

@ -1084,7 +1084,6 @@ set(ZIG_BUILD_ARGS
--zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"
"-Dconfig_h=${ZIG_CONFIG_H_OUT}"
"-Denable-llvm"
"-Denable-stage1"
${ZIG_RELEASE_ARG}
${ZIG_STATIC_ARG}
${ZIG_NO_LIB_ARG}

123
build.zig
View File

@ -69,9 +69,8 @@ pub fn build(b: *Builder) !void {
const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;
const have_stage1 = b.option(bool, "enable-stage1", "Include the stage1 compiler behind a feature flag") orelse false;
const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;
const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (have_stage1 or static_llvm);
const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse static_llvm;
const llvm_has_m68k = b.option(
bool,
"llvm-has-m68k",
@ -133,7 +132,6 @@ pub fn build(b: *Builder) !void {
const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse (enable_llvm or only_c);
const sanitize_thread = b.option(bool, "sanitize-thread", "Enable thread-sanitization") orelse false;
const strip = b.option(bool, "strip", "Omit debug information") orelse false;
const use_zig0 = b.option(bool, "zig0", "Bootstrap using zig0") orelse false;
const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false;
const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
@ -146,11 +144,7 @@ pub fn build(b: *Builder) !void {
target.ofmt = .c;
}
const main_file: ?[]const u8 = mf: {
if (!have_stage1) break :mf "src/main.zig";
if (use_zig0) break :mf null;
break :mf "src/stage1.zig";
};
const main_file: ?[]const u8 = "src/main.zig";
const exe = b.addExecutable("zig", main_file);
@ -264,92 +258,6 @@ pub fn build(b: *Builder) !void {
}
};
if (have_stage1) {
const softfloat = b.addStaticLibrary("softfloat", null);
softfloat.setBuildMode(.ReleaseFast);
softfloat.setTarget(target);
softfloat.addIncludePath("deps/SoftFloat-3e-prebuilt");
softfloat.addIncludePath("deps/SoftFloat-3e/source/8086");
softfloat.addIncludePath("deps/SoftFloat-3e/source/include");
softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" });
softfloat.single_threaded = single_threaded;
const zig0 = b.addExecutable("zig0", null);
zig0.addCSourceFiles(&.{"src/stage1/zig0.cpp"}, &exe_cflags);
zig0.addIncludePath("zig-cache/tmp"); // for config.h
zig0.defineCMacro("ZIG_VERSION_MAJOR", b.fmt("{d}", .{zig_version.major}));
zig0.defineCMacro("ZIG_VERSION_MINOR", b.fmt("{d}", .{zig_version.minor}));
zig0.defineCMacro("ZIG_VERSION_PATCH", b.fmt("{d}", .{zig_version.patch}));
zig0.defineCMacro("ZIG_VERSION_STRING", b.fmt("\"{s}\"", .{version}));
for ([_]*std.build.LibExeObjStep{ zig0, exe, test_cases }) |artifact| {
artifact.addIncludePath("src");
artifact.addIncludePath("deps/SoftFloat-3e/source/include");
artifact.addIncludePath("deps/SoftFloat-3e-prebuilt");
artifact.defineCMacro("ZIG_LINK_MODE", "Static");
artifact.addCSourceFiles(&stage1_sources, &exe_cflags);
artifact.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" });
artifact.linkLibrary(softfloat);
artifact.linkLibCpp();
}
try addStaticLlvmOptionsToExe(zig0);
const zig1_obj_ext = target.getObjectFormat().fileExt(target.getCpuArch());
const zig1_obj_path = b.pathJoin(&.{ "zig-cache", "tmp", b.fmt("zig1{s}", .{zig1_obj_ext}) });
const zig1_compiler_rt_path = b.pathJoin(&.{ b.pathFromRoot("lib"), "std", "special", "compiler_rt.zig" });
const zig1_obj = zig0.run();
zig1_obj.addArgs(&.{
"src/stage1.zig",
"-target",
try target.zigTriple(b.allocator),
"-mcpu=baseline",
"--name",
"zig1",
"--zig-lib-dir",
b.pathFromRoot("lib"),
b.fmt("-femit-bin={s}", .{b.pathFromRoot(zig1_obj_path)}),
"-fcompiler-rt",
"-lc",
});
{
zig1_obj.addArgs(&.{ "--pkg-begin", "build_options" });
zig1_obj.addFileSourceArg(exe_options.getSource());
zig1_obj.addArgs(&.{ "--pkg-end", "--pkg-begin", "compiler_rt", zig1_compiler_rt_path, "--pkg-end" });
}
switch (mode) {
.Debug => {},
.ReleaseFast => {
zig1_obj.addArg("-OReleaseFast");
zig1_obj.addArg("-fstrip");
},
.ReleaseSafe => {
zig1_obj.addArg("-OReleaseSafe");
zig1_obj.addArg("-fstrip");
},
.ReleaseSmall => {
zig1_obj.addArg("-OReleaseSmall");
zig1_obj.addArg("-fstrip");
},
}
if (single_threaded orelse false) {
zig1_obj.addArg("-fsingle-threaded");
}
if (use_zig0) {
exe.step.dependOn(&zig1_obj.step);
exe.addObjectFile(zig1_obj_path);
}
// This is intentionally a dummy path. stage1.zig tries to @import("compiler_rt") in case
// of being built by cmake. But when built by zig it's gonna get a compiler_rt so that
// is pointless.
exe.addPackagePath("compiler_rt", "src/empty.zig");
}
if (cmake_cfg) |cfg| {
// Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD.
// That means we also have to rely on stage1 compiled c++ files. We parse config.h to find
@ -379,7 +287,6 @@ pub fn build(b: *Builder) !void {
exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
exe_options.addOption(bool, "value_tracing", value_tracing);
exe_options.addOption(bool, "have_stage1", have_stage1);
if (tracy) |tracy_path| {
const client_cpp = fs.path.join(
b.allocator,
@ -414,7 +321,6 @@ pub fn build(b: *Builder) !void {
test_cases_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
test_cases_options.addOption(bool, "skip_non_native", skip_non_native);
test_cases_options.addOption(bool, "skip_stage1", skip_stage1);
test_cases_options.addOption(bool, "have_stage1", have_stage1);
test_cases_options.addOption(bool, "have_llvm", enable_llvm);
test_cases_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k);
test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
@ -1010,31 +916,6 @@ const softfloat_sources = [_][]const u8{
"deps/SoftFloat-3e/source/ui64_to_extF80M.c",
};
const stage1_sources = [_][]const u8{
"src/stage1/analyze.cpp",
"src/stage1/astgen.cpp",
"src/stage1/bigfloat.cpp",
"src/stage1/bigint.cpp",
"src/stage1/buffer.cpp",
"src/stage1/codegen.cpp",
"src/stage1/errmsg.cpp",
"src/stage1/error.cpp",
"src/stage1/heap.cpp",
"src/stage1/ir.cpp",
"src/stage1/ir_print.cpp",
"src/stage1/mem.cpp",
"src/stage1/os.cpp",
"src/stage1/parser.cpp",
"src/stage1/range_set.cpp",
"src/stage1/stage1.cpp",
"src/stage1/target.cpp",
"src/stage1/tokenizer.cpp",
"src/stage1/util.cpp",
"src/stage1/softfloat_ext.cpp",
};
const optimized_c_sources = [_][]const u8{
"src/stage1/parse_f128.c",
};
const zig_cpp_sources = [_][]const u8{
// These are planned to stay even when we are self-hosted.
"src/zig_llvm.cpp",

View File

@ -183,10 +183,6 @@ pub fn main() !void {
builder.enable_darling = true;
} else if (mem.eql(u8, arg, "-fno-darling")) {
builder.enable_darling = false;
} else if (mem.eql(u8, arg, "-fstage1")) {
builder.use_stage1 = true;
} else if (mem.eql(u8, arg, "-fno-stage1")) {
builder.use_stage1 = false;
} else if (mem.eql(u8, arg, "-freference-trace")) {
builder.reference_trace = 256;
} else if (mem.startsWith(u8, arg, "-freference-trace=")) {
@ -318,8 +314,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
try out_stream.writeAll(
\\
\\Advanced Options:
\\ -fstage1 Force using bootstrap compiler as the codegen backend
\\ -fno-stage1 Prevent using bootstrap compiler as the codegen backend
\\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
\\ -fno-reference-trace Disable reference trace
\\ --build-file [file] Override path to build.zig

View File

@ -46,7 +46,6 @@ pub const Builder = struct {
prominent_compile_errors: bool,
color: enum { auto, on, off } = .auto,
reference_trace: ?u32 = null,
use_stage1: ?bool = null,
invalid_user_input: bool,
zig_exe: []const u8,
default_step: *Step,
@ -1621,7 +1620,6 @@ pub const LibExeObjStep = struct {
stack_size: ?u64 = null,
want_lto: ?bool = null,
use_stage1: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
@ -2467,20 +2465,6 @@ pub const LibExeObjStep = struct {
try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-freference-trace={d}", .{some}));
}
if (self.use_stage1) |stage1| {
if (stage1) {
try zig_args.append("-fstage1");
} else {
try zig_args.append("-fno-stage1");
}
} else if (builder.use_stage1) |stage1| {
if (stage1) {
try zig_args.append("-fstage1");
} else {
try zig_args.append("-fno-stage1");
}
}
if (self.use_llvm) |use_llvm| {
if (use_llvm) {
try zig_args.append("-fLLVM");

View File

@ -21,7 +21,6 @@ output_dir: ?[]const u8,
out_basename: []const u8,
target: CrossTarget = CrossTarget{},
output_file: build.GeneratedFile,
use_stage1: ?bool = null,
pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep {
const self = builder.allocator.create(TranslateCStep) catch unreachable;
@ -92,19 +91,6 @@ fn make(step: *Step) !void {
try argv_list.append("-D");
try argv_list.append(c_macro);
}
if (self.use_stage1) |stage1| {
if (stage1) {
try argv_list.append("-fstage1");
} else {
try argv_list.append("-fno-stage1");
}
} else if (self.builder.use_stage1) |stage1| {
if (stage1) {
try argv_list.append("-fstage1");
} else {
try argv_list.append("-fno-stage1");
}
}
try argv_list.append(self.source.getPath(self.builder));

View File

@ -935,7 +935,6 @@ pub const InitOptions = struct {
use_llvm: ?bool = null,
use_lld: ?bool = null,
use_clang: ?bool = null,
use_stage1: ?bool = null,
single_threaded: ?bool = null,
strip: ?bool = null,
formatted_panics: ?bool = null,
@ -1133,9 +1132,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
const comp = try arena.create(Compilation);
const root_name = try arena.dupeZ(u8, options.root_name);
const use_stage1 = options.use_stage1 orelse false;
if (use_stage1 and !build_options.have_stage1) return error.ZigCompilerBuiltWithoutStage1;
// Make a decision on whether to use LLVM or our own backend.
const use_llvm = build_options.have_llvm and blk: {
if (options.use_llvm) |explicit|
@ -1149,11 +1145,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
if (options.main_pkg == null)
break :blk false;
// The stage1 compiler depends on the stage1 C++ LLVM backend
// to compile zig code.
if (use_stage1)
break :blk true;
// If LLVM does not support the target, then we can't use it.
if (!target_util.hasLlvmSupport(options.target, options.target.ofmt))
break :blk false;
@ -1181,8 +1172,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
// compiler state, the second clause here can be removed so that incremental
// cache mode is used for LLVM backend too. We need some fuzz testing before
// that can be enabled.
const cache_mode = if ((use_stage1 and !options.disable_lld_caching) or
(use_llvm and !options.disable_lld_caching)) CacheMode.whole else options.cache_mode;
const cache_mode = if (use_llvm and !options.disable_lld_caching)
CacheMode.whole
else
options.cache_mode;
const tsan = options.want_tsan orelse false;
// TSAN is implemented in C++ so it requires linking libc++.
@ -1545,7 +1538,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
// Synchronize with other matching comments: ZigOnlyHashStuff
hash.add(valgrind);
hash.add(single_threaded);
hash.add(use_stage1);
hash.add(use_llvm);
hash.add(dll_export_fns);
hash.add(options.is_test);
@ -1587,9 +1579,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.handle = artifact_dir,
.path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),
};
log.debug("zig_cache_artifact_directory='{?s}' use_stage1={}", .{
zig_cache_artifact_directory.path, use_stage1,
});
const builtin_pkg = try Package.createWithDir(
gpa,
@ -1907,7 +1896,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.subsystem = options.subsystem,
.is_test = options.is_test,
.wasi_exec_model = wasi_exec_model,
.use_stage1 = use_stage1,
.hash_style = options.hash_style,
.enable_link_snapshots = options.enable_link_snapshots,
.native_darwin_sdk = options.native_darwin_sdk,
@ -2344,7 +2332,6 @@ pub fn update(comp: *Compilation) !void {
comp.c_object_work_queue.writeItemAssumeCapacity(key);
}
const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
if (comp.bin_file.options.module) |module| {
module.compile_log_text.shrinkAndFree(module.gpa, 0);
module.generation += 1;
@ -2360,7 +2347,7 @@ pub fn update(comp: *Compilation) !void {
// import_table here.
// Likewise, in the case of `zig test`, the test runner is the root source file,
// and so there is nothing to import the main file.
if (use_stage1 or comp.bin_file.options.is_test) {
if (comp.bin_file.options.is_test) {
_ = try module.importPkg(module.main_pkg);
}
@ -2374,21 +2361,19 @@ pub fn update(comp: *Compilation) !void {
comp.astgen_work_queue.writeItemAssumeCapacity(value);
}
if (!use_stage1) {
// Put a work item in for checking if any files used with `@embedFile` changed.
{
try comp.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count());
var it = module.embed_table.iterator();
while (it.next()) |entry| {
const embed_file = entry.value_ptr.*;
comp.embed_file_work_queue.writeItemAssumeCapacity(embed_file);
}
// Put a work item in for checking if any files used with `@embedFile` changed.
{
try comp.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count());
var it = module.embed_table.iterator();
while (it.next()) |entry| {
const embed_file = entry.value_ptr.*;
comp.embed_file_work_queue.writeItemAssumeCapacity(embed_file);
}
}
try comp.work_queue.writeItem(.{ .analyze_pkg = std_pkg });
if (comp.bin_file.options.is_test) {
try comp.work_queue.writeItem(.{ .analyze_pkg = module.main_pkg });
}
try comp.work_queue.writeItem(.{ .analyze_pkg = std_pkg });
if (comp.bin_file.options.is_test) {
try comp.work_queue.writeItem(.{ .analyze_pkg = module.main_pkg });
}
}
@ -2400,36 +2385,34 @@ pub fn update(comp: *Compilation) !void {
try comp.performAllTheWork(main_progress_node);
if (!use_stage1) {
if (comp.bin_file.options.module) |module| {
if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
// The `test_functions` decl has been intentionally postponed until now,
// at which point we must populate it with the list of test functions that
// have been discovered and not filtered out.
try module.populateTestFunctions(main_progress_node);
}
// Process the deletion set. We use a while loop here because the
// deletion set may grow as we call `clearDecl` within this loop,
// and more unreferenced Decls are revealed.
while (module.deletion_set.count() != 0) {
const decl_index = module.deletion_set.keys()[0];
const decl = module.declPtr(decl_index);
assert(decl.deletion_flag);
assert(decl.dependants.count() == 0);
const is_anon = if (decl.zir_decl_index == 0) blk: {
break :blk decl.src_namespace.anon_decls.swapRemove(decl_index);
} else false;
try module.clearDecl(decl_index, null);
if (is_anon) {
module.destroyDecl(decl_index);
}
}
try module.processExports();
if (comp.bin_file.options.module) |module| {
if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
// The `test_functions` decl has been intentionally postponed until now,
// at which point we must populate it with the list of test functions that
// have been discovered and not filtered out.
try module.populateTestFunctions(main_progress_node);
}
// Process the deletion set. We use a while loop here because the
// deletion set may grow as we call `clearDecl` within this loop,
// and more unreferenced Decls are revealed.
while (module.deletion_set.count() != 0) {
const decl_index = module.deletion_set.keys()[0];
const decl = module.declPtr(decl_index);
assert(decl.deletion_flag);
assert(decl.dependants.count() == 0);
const is_anon = if (decl.zir_decl_index == 0) blk: {
break :blk decl.src_namespace.anon_decls.swapRemove(decl_index);
} else false;
try module.clearDecl(decl_index, null);
if (is_anon) {
module.destroyDecl(decl_index);
}
}
try module.processExports();
}
if (comp.totalErrorCount() != 0) {
@ -2536,11 +2519,8 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
};
comp.link_error_flags = comp.bin_file.errorFlags();
const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
if (!use_stage1) {
if (comp.bin_file.options.module) |module| {
try link.File.C.flushEmitH(module);
}
if (comp.bin_file.options.module) |module| {
try link.File.C.flushEmitH(module);
}
}
@ -2610,7 +2590,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
// Synchronize with other matching comments: ZigOnlyHashStuff
man.hash.add(comp.bin_file.options.valgrind);
man.hash.add(comp.bin_file.options.single_threaded);
man.hash.add(comp.bin_file.options.use_stage1);
man.hash.add(comp.bin_file.options.use_llvm);
man.hash.add(comp.bin_file.options.dll_export_fns);
man.hash.add(comp.bin_file.options.is_test);
@ -3010,8 +2989,6 @@ pub fn performAllTheWork(
comp.work_queue_wait_group.reset();
defer comp.work_queue_wait_group.wait();
const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
{
const astgen_frame = tracy.namedFrame("astgen");
defer astgen_frame.end();
@ -3056,7 +3033,7 @@ pub fn performAllTheWork(
}
}
if (!use_stage1) {
{
const outdated_and_deleted_decls_frame = tracy.namedFrame("outdated_and_deleted_decls");
defer outdated_and_deleted_decls_frame.end();
@ -3064,15 +3041,6 @@ pub fn performAllTheWork(
if (comp.bin_file.options.module) |mod| {
try mod.processOutdatedAndDeletedDecls();
}
} else if (comp.bin_file.options.module) |mod| {
// If there are any AstGen compile errors, report them now to avoid
// hitting stage1 bugs.
if (mod.failed_files.count() != 0) {
return;
}
comp.updateStage1Module(main_progress_node) catch |err| {
fatal("unable to build stage1 zig object: {s}", .{@errorName(err)});
};
}
if (comp.bin_file.options.module) |mod| {
@ -3598,10 +3566,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
var man = comp.obtainCObjectCacheManifest();
defer man.deinit();
const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
man.hash.add(use_stage1);
man.hash.addBytes(c_src);
// If the previous invocation resulted in clang errors, we will see a hit
@ -3665,7 +3630,6 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
new_argv.ptr + new_argv.len,
&clang_errors,
c_headers_dir_path_z,
use_stage1,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.ASTUnitFailure => {
@ -5097,8 +5061,6 @@ pub fn dump_argv(argv: []const []const u8) void {
}
pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {
const use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1;
if (use_stage1) return .stage1;
if (build_options.have_llvm and comp.bin_file.options.use_llvm) return .stage2_llvm;
const target = comp.bin_file.options.target;
if (target.ofmt == .c) return .stage2_c;
@ -5394,7 +5356,6 @@ fn buildOutputFromZig(
.link_mode = .Static,
.function_sections = true,
.no_builtin = true,
.use_stage1 = build_options.have_stage1 and comp.bin_file.options.use_stage1,
.want_sanitize_c = false,
.want_stack_check = false,
.want_stack_protector = 0,

View File

@ -2121,8 +2121,6 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError
const msg = msg: {
const msg = try sema.errMsg(block, src, "async has not been implemented in the self-hosted compiler yet", .{});
errdefer msg.destroy(sema.gpa);
try sema.errNote(block, src, msg, "to use async enable the stage1 compiler with either '-fstage1' or by setting '.use_stage1 = true` in your 'build.zig' script", .{});
break :msg msg;
};
return sema.failWithOwnedErrorMsg(msg);

View File

@ -155,7 +155,6 @@ pub const Options = struct {
build_id: bool,
disable_lld_caching: bool,
is_test: bool,
use_stage1: bool,
hash_style: HashStyle,
major_subsystem_version: ?u32,
minor_subsystem_version: ?u32,
@ -293,8 +292,7 @@ pub const File = struct {
return &(try MachO.openPath(allocator, options)).base;
}
const use_stage1 = build_options.have_stage1 and options.use_stage1;
if (use_stage1 or options.emit == null) {
if (options.emit == null) {
return switch (options.target.ofmt) {
.coff => &(try Coff.createEmpty(allocator, options)).base,
.elf => &(try Elf.createEmpty(allocator, options)).base,
@ -983,24 +981,7 @@ pub const File = struct {
// If there is no Zig code to compile, then we should skip flushing the output file
// because it will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (base.options.module) |module| blk: {
const use_stage1 = build_options.have_stage1 and base.options.use_stage1;
if (use_stage1) {
const obj_basename = try std.zig.binNameAlloc(arena, .{
.root_name = base.options.root_name,
.target = base.options.target,
.output_mode = .Obj,
});
switch (base.options.cache_mode) {
.incremental => break :blk try module.zig_cache_artifact_directory.join(
arena,
&[_][]const u8{obj_basename},
),
.whole => break :blk try fs.path.join(arena, &.{
fs.path.dirname(full_out_path_z).?, obj_basename,
}),
}
}
const module_obj_path: ?[]const u8 = if (base.options.module != null) blk: {
try base.flushModule(comp, prog_node);
const dirname = fs.path.dirname(full_out_path_z) orelse ".";

View File

@ -248,8 +248,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff {
};
const use_llvm = build_options.have_llvm and options.use_llvm;
const use_stage1 = build_options.have_stage1 and options.use_stage1;
if (use_llvm and !use_stage1) {
if (use_llvm) {
self.llvm_object = try LlvmObject.create(gpa, options);
}
return self;

View File

@ -30,25 +30,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
const use_stage1 = build_options.have_stage1 and self.base.options.use_stage1;
if (use_stage1) {
const obj_basename = try std.zig.binNameAlloc(arena, .{
.root_name = self.base.options.root_name,
.target = self.base.options.target,
.output_mode = .Obj,
});
switch (self.base.options.cache_mode) {
.incremental => break :blk try module.zig_cache_artifact_directory.join(
arena,
&[_][]const u8{obj_basename},
),
.whole => break :blk try fs.path.join(arena, &.{
fs.path.dirname(full_out_path).?, obj_basename,
}),
}
}
const module_obj_path: ?[]const u8 = if (self.base.options.module != null) blk: {
try self.flushModule(comp, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {

View File

@ -328,8 +328,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
.page_size = page_size,
};
const use_llvm = build_options.have_llvm and options.use_llvm;
const use_stage1 = build_options.have_stage1 and options.use_stage1;
if (use_llvm and !use_stage1) {
if (use_llvm) {
self.llvm_object = try LlvmObject.create(gpa, options);
}
return self;
@ -1228,25 +1227,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
// stage1 puts the object file in the cache directory.
if (self.base.options.use_stage1) {
const obj_basename = try std.zig.binNameAlloc(arena, .{
.root_name = self.base.options.root_name,
.target = self.base.options.target,
.output_mode = .Obj,
});
switch (self.base.options.cache_mode) {
.incremental => break :blk try module.zig_cache_artifact_directory.join(
arena,
&[_][]const u8{obj_basename},
),
.whole => break :blk try fs.path.join(arena, &.{
fs.path.dirname(full_out_path).?, obj_basename,
}),
}
}
const module_obj_path: ?[]const u8 = if (self.base.options.module != null) blk: {
try self.flushModule(comp, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {

View File

@ -290,8 +290,7 @@ pub const Export = struct {
pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
assert(options.target.ofmt == .macho);
const use_stage1 = build_options.have_stage1 and options.use_stage1;
if (use_stage1 or options.emit == null or options.module == null) {
if (options.emit == null or options.module == null) {
return createEmpty(allocator, options);
}
@ -377,7 +376,6 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
const cpu_arch = options.target.cpu.arch;
const page_size: u16 = if (cpu_arch == .aarch64) 0x4000 else 0x1000;
const use_llvm = build_options.have_llvm and options.use_llvm;
const use_stage1 = build_options.have_stage1 and options.use_stage1;
const self = try gpa.create(MachO);
errdefer gpa.destroy(self);
@ -390,13 +388,13 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
.file = null,
},
.page_size = page_size,
.mode = if (use_stage1 or use_llvm or options.module == null or options.cache_mode == .whole)
.mode = if (use_llvm or options.module == null or options.cache_mode == .whole)
.one_shot
else
.incremental,
};
if (use_llvm and !use_stage1) {
if (use_llvm) {
self.llvm_object = try LlvmObject.create(gpa, options);
}

View File

@ -3746,24 +3746,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (options.module) |module| blk: {
if (options.use_stage1) {
const obj_basename = try std.zig.binNameAlloc(arena, .{
.root_name = options.root_name,
.target = target,
.output_mode = .Obj,
});
switch (options.cache_mode) {
.incremental => break :blk try module.zig_cache_artifact_directory.join(
arena,
&[_][]const u8{obj_basename},
),
.whole => break :blk try fs.path.join(arena, &.{
fs.path.dirname(full_out_path).?, obj_basename,
}),
}
}
const module_obj_path: ?[]const u8 = if (options.module != null) blk: {
try macho_file.flushModule(comp, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {

View File

@ -382,8 +382,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
};
const use_llvm = build_options.have_llvm and options.use_llvm;
const use_stage1 = build_options.have_stage1 and options.use_stage1;
if (use_llvm and !use_stage1) {
if (use_llvm) {
wasm.llvm_object = try LlvmObject.create(gpa, options);
}
return wasm;
@ -2986,25 +2985,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (wasm.base.options.module) |mod| blk: {
const use_stage1 = build_options.have_stage1 and wasm.base.options.use_stage1;
if (use_stage1) {
const obj_basename = try std.zig.binNameAlloc(arena, .{
.root_name = wasm.base.options.root_name,
.target = wasm.base.options.target,
.output_mode = .Obj,
});
switch (wasm.base.options.cache_mode) {
.incremental => break :blk try mod.zig_cache_artifact_directory.join(
arena,
&[_][]const u8{obj_basename},
),
.whole => break :blk try fs.path.join(arena, &.{
fs.path.dirname(full_out_path).?, obj_basename,
}),
}
}
const module_obj_path: ?[]const u8 = if (wasm.base.options.module != null) blk: {
try wasm.flushModule(comp, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {
@ -3198,26 +3179,19 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
if (wasm.base.options.module) |mod| {
// when we use stage1, we use the exports that stage1 provided us.
// For stage2, we can directly retrieve them from the module.
const use_stage1 = build_options.have_stage1 and wasm.base.options.use_stage1;
if (use_stage1) {
for (comp.export_symbol_names.items) |symbol_name| {
try argv.append(try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}));
}
} else {
const skip_export_non_fn = target.os.tag == .wasi and
wasm.base.options.wasi_exec_model == .command;
for (mod.decl_exports.values()) |exports| {
for (exports.items) |exprt| {
const exported_decl = mod.declPtr(exprt.exported_decl);
if (skip_export_non_fn and exported_decl.ty.zigTypeTag() != .Fn) {
// skip exporting symbols when we're building a WASI command
// and the symbol is not a function
continue;
}
const symbol_name = exported_decl.name;
const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
try argv.append(arg);
const skip_export_non_fn = target.os.tag == .wasi and
wasm.base.options.wasi_exec_model == .command;
for (mod.decl_exports.values()) |exports| {
for (exports.items) |exprt| {
const exported_decl = mod.declPtr(exprt.exported_decl);
if (skip_export_non_fn and exported_decl.ty.zigTypeTag() != .Fn) {
// skip exporting symbols when we're building a WASI command
// and the symbol is not a function
continue;
}
const symbol_name = exported_decl.name;
const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
try argv.append(arg);
}
}
}

View File

@ -394,8 +394,6 @@ const usage_build_generic =
\\ -fno-LLVM Prevent using LLVM as the codegen backend
\\ -fClang Force using Clang as the C/C++ compilation backend
\\ -fno-Clang Prevent using Clang as the C/C++ compilation backend
\\ -fstage1 Force using bootstrap compiler as the codegen backend
\\ -fno-stage1 Prevent using bootstrap compiler as the codegen backend
\\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
\\ -fno-reference-trace Disable reference trace
\\ -fsingle-threaded Code assumes there is only one thread
@ -719,7 +717,6 @@ fn buildOutputType(
var use_llvm: ?bool = null;
var use_lld: ?bool = null;
var use_clang: ?bool = null;
var use_stage1: ?bool = null;
var link_eh_frame_hdr = false;
var link_emit_relocs = false;
var each_lib_rpath: ?bool = null;
@ -1158,10 +1155,6 @@ fn buildOutputType(
use_clang = true;
} else if (mem.eql(u8, arg, "-fno-Clang")) {
use_clang = false;
} else if (mem.eql(u8, arg, "-fstage1")) {
use_stage1 = true;
} else if (mem.eql(u8, arg, "-fno-stage1")) {
use_stage1 = false;
} else if (mem.eql(u8, arg, "-freference-trace")) {
reference_trace = 256;
} else if (mem.startsWith(u8, arg, "-freference-trace=")) {
@ -2909,7 +2902,6 @@ fn buildOutputType(
.use_llvm = use_llvm,
.use_lld = use_lld,
.use_clang = use_clang,
.use_stage1 = use_stage1,
.hash_style = hash_style,
.rdynamic = rdynamic,
.linker_script = linker_script,
@ -3024,8 +3016,7 @@ fn buildOutputType(
return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
}
if (arg_mode == .translate_c) {
const stage1_mode = use_stage1 orelse false;
return cmdTranslateC(comp, arena, have_enable_cache, stage1_mode);
return cmdTranslateC(comp, arena, have_enable_cache);
}
const hook: AfterUpdateHook = blk: {
@ -3444,7 +3435,7 @@ fn freePkgTree(gpa: Allocator, pkg: *Package, free_parent: bool) void {
}
}
fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool, stage1_mode: bool) !void {
fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool) !void {
if (!build_options.have_llvm)
fatal("cannot translate-c: compiler built without LLVM extensions", .{});
@ -3457,7 +3448,6 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool, stage
defer if (enable_cache) man.deinit();
man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
man.hash.add(stage1_mode);
man.hashCSource(c_source_file) catch |err| {
fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
};
@ -3509,7 +3499,6 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool, stage
new_argv.ptr + new_argv.len,
&clang_errors,
c_headers_dir_path_z,
stage1_mode,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.ASTUnitFailure => fatal("clang API returned errors but due to a clang bug, it is not exposing the errors for zig to see. For more details: https://github.com/ziglang/zig/issues/4455", .{}),
@ -3755,8 +3744,6 @@ pub const usage_build =
\\ Build a project from build.zig.
\\
\\Options:
\\ -fstage1 Force using bootstrap compiler as the codegen backend
\\ -fno-stage1 Prevent using bootstrap compiler as the codegen backend
\\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
\\ -fno-reference-trace Disable reference trace
\\ --build-file [file] Override path to build.zig
@ -3770,7 +3757,6 @@ pub const usage_build =
pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
var prominent_compile_errors: bool = false;
var use_stage1: ?bool = null;
// We want to release all the locks before executing the child process, so we make a nice
// big block here to ensure the cleanup gets run when we extract out our argv.
@ -3827,12 +3813,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
continue;
} else if (mem.eql(u8, arg, "--prominent-compile-errors")) {
prominent_compile_errors = true;
} else if (mem.eql(u8, arg, "-fstage1")) {
use_stage1 = true;
try child_argv.append(arg);
} else if (mem.eql(u8, arg, "-fno-stage1")) {
use_stage1 = false;
try child_argv.append(arg);
} else if (mem.eql(u8, arg, "-freference-trace")) {
try child_argv.append(arg);
reference_trace = 256;
@ -3979,7 +3959,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
.optimize_mode = .Debug,
.self_exe_path = self_exe_path,
.thread_pool = &thread_pool,
.use_stage1 = use_stage1,
.cache_mode = .whole,
.reference_trace = reference_trace,
.debug_compile_errors = debug_compile_errors,

View File

@ -1548,7 +1548,6 @@ pub const TestContext = struct {
.dynamic_linker = target_info.dynamic_linker.get(),
.link_libc = case.link_libc,
.use_llvm = use_llvm,
.use_stage1 = null, // We already handled stage1 tests
.self_exe_path = zig_exe_path,
// TODO instead of turning off color, pass in a std.Progress.Node
.color = .off,

View File

@ -327,16 +327,6 @@ pub const Context = struct {
pattern_list: PatternList,
/// This is used to emit different code depending on whether
/// the output zig source code is intended to be compiled with stage1 or stage2.
/// Ideally we will have stage1 and stage2 support the exact same Zig language,
/// but for now they diverge because I would rather focus on finishing and shipping
/// stage2 than implementing the features in stage1.
/// The list of differences are currently:
/// * function pointers in stage1 are e.g. `fn()void`
/// but in stage2 they are `*const fn()void`.
zig_is_stage1: bool,
fn getMangle(c: *Context) u32 {
c.mangle_count += 1;
return c.mangle_count;
@ -365,7 +355,6 @@ pub fn translate(
args_end: [*]?[*]const u8,
errors: *[]ClangErrMsg,
resources_path: [*:0]const u8,
zig_is_stage1: bool,
) !std.zig.Ast {
// TODO stage2 bug
var tmp = errors;
@ -395,7 +384,6 @@ pub fn translate(
.global_scope = try arena.create(Scope.Root),
.clang_context = ast_unit.getASTContext(),
.pattern_list = try PatternList.init(gpa),
.zig_is_stage1 = zig_is_stage1,
};
context.global_scope.* = Scope.Root.init(&context);
defer {
@ -435,7 +423,7 @@ pub fn translate(
}
}
return ast.render(gpa, zig_is_stage1, context.global_scope.nodes.items);
return ast.render(gpa, context.global_scope.nodes.items);
}
/// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens)
@ -4747,9 +4735,6 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan
.Pointer => {
const child_qt = ty.getPointeeType();
const is_fn_proto = qualTypeChildIsFnProto(child_qt);
if (c.zig_is_stage1 and is_fn_proto) {
return Tag.optional_type.create(c.arena, try transQualType(c, scope, child_qt, source_loc));
}
const is_const = is_fn_proto or child_qt.isConstQualified();
const is_volatile = child_qt.isVolatileQualified();
const elem_type = try transQualType(c, scope, child_qt, source_loc);
@ -6681,16 +6666,10 @@ fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {
return null;
if (getContainerTypeOf(c, init)) |ty_node| {
if (ty_node.castTag(.optional_type)) |prefix| {
if (c.zig_is_stage1) {
if (prefix.data.castTag(.func)) |fn_proto| {
if (prefix.data.castTag(.single_pointer)) |sp| {
if (sp.data.elem_type.castTag(.func)) |fn_proto| {
return fn_proto;
}
} else {
if (prefix.data.castTag(.single_pointer)) |sp| {
if (sp.data.elem_type.castTag(.func)) |fn_proto| {
return fn_proto;
}
}
}
}
}

View File

@ -732,11 +732,10 @@ pub const Payload = struct {
/// Converts the nodes into a Zig Ast.
/// Caller must free the source slice.
pub fn render(gpa: Allocator, zig_is_stage1: bool, nodes: []const Node) !std.zig.Ast {
pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
var ctx = Context{
.gpa = gpa,
.buf = std.ArrayList(u8).init(gpa),
.zig_is_stage1 = zig_is_stage1,
};
defer ctx.buf.deinit();
defer ctx.nodes.deinit(gpa);
@ -805,11 +804,6 @@ const Context = struct {
extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{},
tokens: std.zig.Ast.TokenList = .{},
/// This is used to emit different code depending on whether
/// the output zig source code is intended to be compiled with stage1 or stage2.
/// Refer to the Context in translate_c.zig.
zig_is_stage1: bool,
fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
const start_index = c.buf.items.len;
try c.buf.writer().print(format ++ " ", args);
@ -932,7 +926,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.call => {
const payload = node.castTag(.call).?.data;
// Cosmetic: avoids an unnecesary address_of on most function calls.
const lhs = if (!c.zig_is_stage1 and payload.lhs.tag() == .fn_identifier)
const lhs = if (payload.lhs.tag() == .fn_identifier)
try c.addNode(.{
.tag = .identifier,
.main_token = try c.addIdentifier(payload.lhs.castTag(.fn_identifier).?.data),
@ -1097,28 +1091,20 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
// value (implicit in stage1, explicit in stage2), except in
// the context of an address_of, which is handled there.
const payload = node.castTag(.fn_identifier).?.data;
if (c.zig_is_stage1) {
return try c.addNode(.{
.tag = .identifier,
.main_token = try c.addIdentifier(payload),
.data = undefined,
});
} else {
const tok = try c.addToken(.ampersand, "&");
const arg = try c.addNode(.{
.tag = .identifier,
.main_token = try c.addIdentifier(payload),
.data = undefined,
});
return c.addNode(.{
.tag = .address_of,
.main_token = tok,
.data = .{
.lhs = arg,
.rhs = undefined,
},
});
}
const tok = try c.addToken(.ampersand, "&");
const arg = try c.addNode(.{
.tag = .identifier,
.main_token = try c.addIdentifier(payload),
.data = undefined,
});
return c.addNode(.{
.tag = .address_of,
.main_token = tok,
.data = .{
.lhs = arg,
.rhs = undefined,
},
});
},
.float_literal => {
const payload = node.castTag(.float_literal).?.data;
@ -1448,7 +1434,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.optional_type => return renderPrefixOp(c, node, .optional_type, .question_mark, "?"),
.address_of => {
const payload = node.castTag(.address_of).?.data;
if (c.zig_is_stage1 and payload.tag() == .fn_identifier)
if (payload.tag() == .fn_identifier)
return try c.addNode(.{
.tag = .identifier,
.main_token = try c.addIdentifier(payload.castTag(.fn_identifier).?.data),

View File

@ -13,7 +13,6 @@ pub fn build(b: *Builder) void {
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
lib.use_llvm = false;
lib.use_stage1 = false;
lib.use_lld = false;
lib.strip = false;

View File

@ -11,7 +11,6 @@ pub fn build(b: *Builder) void {
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
lib.use_llvm = false;
lib.use_stage1 = false;
lib.use_lld = false;
lib.strip = false;
// to make sure the bss segment is emitted, we must import memory

View File

@ -12,7 +12,6 @@ pub fn build(b: *Builder) void {
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
lib.use_llvm = false;
lib.use_stage1 = false;
lib.use_lld = false;
lib.strip = false;
lib.install();

View File

@ -11,7 +11,6 @@ pub fn build(b: *Builder) void {
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
lib.use_llvm = false;
lib.use_stage1 = false;
lib.use_lld = false;
lib.strip = false;
lib.install();

View File

@ -11,7 +11,6 @@ pub fn build(b: *Builder) void {
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
lib.use_llvm = false;
lib.use_stage1 = false;
lib.use_lld = false;
lib.strip = false;
lib.stack_size = std.wasm.page_size * 2; // set an explicit stack size

View File

@ -11,7 +11,6 @@ pub fn build(b: *Builder) void {
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
lib.use_llvm = false;
lib.use_stage1 = false;
lib.use_lld = false;
lib.strip = false;
lib.install();

View File

@ -720,20 +720,18 @@ pub fn addPkgTests(
these_tests.addIncludePath("test");
if (test_target.backend) |backend| switch (backend) {
.stage1 => {
these_tests.use_stage1 = true;
@panic("stage1 testing requested");
},
.stage2_llvm => {
these_tests.use_stage1 = false;
these_tests.use_llvm = true;
},
.stage2_c => {
these_tests.use_stage1 = false;
these_tests.use_llvm = false;
},
else => {
these_tests.use_stage1 = false;
these_tests.use_llvm = false;
// TODO: force self-hosted linkers to avoid LLD creeping in until the auto-select mechanism deems them worthy
// TODO: force self-hosted linkers to avoid LLD creeping in
// until the auto-select mechanism deems them worthy
these_tests.use_lld = false;
},
};
@ -1355,8 +1353,6 @@ pub fn addCAbiTests(b: *build.Builder, skip_non_native: bool) *build.Step {
triple_prefix,
}));
test_step.use_stage1 = false;
step.dependOn(&test_step.step);
}
return step;