diff options
| -rw-r--r-- | BRANCH_TODO | 28 | ||||
| -rw-r--r-- | src-self-hosted/Compilation.zig | 290 | ||||
| -rw-r--r-- | src-self-hosted/Package.zig | 34 | ||||
| -rw-r--r-- | src-self-hosted/glibc.zig | 36 | ||||
| -rw-r--r-- | src-self-hosted/libunwind.zig | 28 | ||||
| -rw-r--r-- | src-self-hosted/link.zig | 12 | ||||
| -rw-r--r-- | src-self-hosted/link/Elf.zig | 22 | ||||
| -rw-r--r-- | src-self-hosted/main.zig | 10 |
8 files changed, 295 insertions, 165 deletions
diff --git a/BRANCH_TODO b/BRANCH_TODO index bee98d6d2b..35972cb3e2 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,6 +1,8 @@ + * Cache integration for stage1 zig code compilation * build & link against compiler-rt * build & link against freestanding libc - * Cache integration for stage1 zig code compilation + * resolve builtin.zig not working on windows & macos; try os_path_real + * build & link against libcxx and libcxxabi * `zig test` * `zig build` * `-ftime-report` @@ -16,32 +18,33 @@ * make sure zig cc works - using it as a preprocessor (-E) - try building some software + * implement proper parsing of LLD stderr/stdout and exposing compile errors + * implement proper parsing of clang stderr/stdout and exposing compile errors * support rpaths in ELF linker code * repair @cImport * add CLI support for a way to pass extra flags to c source files - * capture lld stdout/stderr better * musl * mingw-w64 * use global zig-cache dir for crt files * MachO LLD linking * COFF LLD linking * WASM LLD linking - * implement proper parsing of LLD stderr/stdout and exposing compile errors - * implement proper parsing of clang stderr/stdout and exposing compile errors - * implement proper compile errors for failing to build glibc crt files and shared libs - * improve the stage2 tests to support testing with LLVM extensions enabled - * multi-thread building C objects * support cross compiling stage2 with `zig build` - * implement emit-h in stage2 - * implement -fno-emit-bin - * audit the base cache hash * --main-pkg-path * audit the CLI options for stage2 * `zig init-lib` * `zig init-exe` * `zig run` * restore error messages for stage2_add_link_lib + * audit the base cache hash + * implement proper compile errors for failing to build glibc crt files and shared libs + * implement -fno-emit-bin + * improve the stage2 tests to support testing with LLVM extensions enabled + * rename src/ to src/stage1/ + * rename src-self-hosted/ to src/ + * implement emit-h in stage2 + * multi-thread building C objects * implement serialization/deserialization of incremental compilation metadata * incremental compilation - implement detection of which source files changed * improve the cache hash logic for c objects with respect to extra flags and file parameters @@ -59,16 +62,13 @@ * integrate target features into building assembly code * libc_installation.zig: make it look for msvc only if msvc abi is chosen * switch the default C ABI for windows to be mingw-w64 - * port windows_sdk.cpp to zig * change glibc log errors to normal exposed compile errors * update Package to use Compilation.Directory in create() - skip LLD caching when bin directory is not in the cache (so we don't put `id.txt` into the cwd) (maybe make it an explicit option and have main.zig disable it) - make it possible for Package to not openDir and reference already existing resources. - * rename src/ to src/stage1/ - * rename src-self-hosted/ to src/ * improve Directory.join to only use 1 allocation in a clean way. * tracy builds with lc++ * some kind of "zig identifier escape" function rather than unconditionally using @"" syntax in builtin.zig - * rename Mode to OptimizeMode + * rename std.builtin.Mode to std.builtin.OptimizeMode diff --git a/src-self-hosted/Compilation.zig b/src-self-hosted/Compilation.zig index f08c5ef82f..32edc92718 100644 --- a/src-self-hosted/Compilation.zig +++ b/src-self-hosted/Compilation.zig @@ -46,6 +46,12 @@ sanitize_c: bool, clang_passthrough_mode: bool, /// Whether to print clang argvs to stdout. verbose_cc: bool, +verbose_tokenize: bool, +verbose_ast: bool, +verbose_ir: bool, +verbose_llvm_ir: bool, +verbose_cimport: bool, +verbose_llvm_cpu_features: bool, disable_c_depfile: bool, is_test: bool, @@ -59,18 +65,21 @@ zig_cache_directory: Directory, libc_include_dir_list: []const []const u8, rand: *std.rand.Random, -/// Populated when we build libc++.a. A Job to build this is placed in the queue +/// Populated when we build the libc++ static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). libcxx_static_lib: ?[]const u8 = null, -/// Populated when we build libc++abi.a. A Job to build this is placed in the queue +/// Populated when we build the libc++abi static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). libcxxabi_static_lib: ?[]const u8 = null, -/// Populated when we build libunwind.a. A Job to build this is placed in the queue +/// Populated when we build the libunwind static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). libunwind_static_lib: ?CRTFile = null, -/// Populated when we build c.a. A Job to build this is placed in the queue +/// Populated when we build the libc static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). -libc_static_lib: ?[]const u8 = null, +libc_static_lib: ?CRTFile = null, +/// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue +/// and resolved before calling linker.flush(). +compiler_rt_static_lib: ?CRTFile = null, glibc_so_files: ?glibc.BuiltSharedObjects = null, @@ -121,6 +130,11 @@ const Job = union(enum) { glibc_shared_objects, /// libunwind.a, usually needed when linking libc libunwind: void, + /// needed when producing a dynamic library or executable + libcompiler_rt: void, + /// needed when not linking libc and using LLVM for code generation because it generates + /// calls to, for example, memcpy and memset. + zig_libc: void, /// Generate builtin.zig source code and write it into the correct place. generate_builtin_zig: void, @@ -310,6 +324,15 @@ pub const InitOptions = struct { }; pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { + const is_dyn_lib = switch (options.output_mode) { + .Obj, .Exe => false, + .Lib => (options.link_mode orelse .Static) == .Dynamic, + }; + const is_exe_or_dyn_lib = switch (options.output_mode) { + .Obj => false, + .Lib => is_dyn_lib, + .Exe => true, + }; const comp: *Compilation = comp: { // For allocations that have the same lifetime as Compilation. This arena is used only during this // initialization and then is freed in deinit(). @@ -375,15 +398,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { return error.MachineCodeModelNotSupported; } - const is_dyn_lib = switch (options.output_mode) { - .Obj, .Exe => false, - .Lib => (options.link_mode orelse .Static) == .Dynamic, - }; - const is_exe_or_dyn_lib = switch (options.output_mode) { - .Obj => false, - .Lib => is_dyn_lib, - .Exe => true, - }; const must_dynamic_link = dl: { if (target_util.cannotDynamicLink(options.target)) break :dl false; @@ -461,6 +475,27 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { }; const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); + const function_sections = options.function_sections orelse false; + + const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { + var buf = std.ArrayList(u8).init(arena); + for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| { + const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); + const is_enabled = options.target.cpu.features.isEnabled(index); + + if (feature.llvm_name) |llvm_name| { + const plus_or_minus = "-+"[@boolToInt(is_enabled)]; + try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len); + buf.appendAssumeCapacity(plus_or_minus); + buf.appendSliceAssumeCapacity(llvm_name); + buf.appendSliceAssumeCapacity(","); + } + } + assert(mem.endsWith(u8, buf.items, ",")); + buf.items[buf.items.len - 1] = 0; + buf.shrink(buf.items.len); + break :blk buf.items[0 .. buf.items.len - 1 :0].ptr; + } else null; // We put everything into the cache hash that *cannot be modified during an incremental update*. // For example, one cannot change the target between updates, but one can change source files, @@ -489,8 +524,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { cache.hash.add(pic); cache.hash.add(stack_check); cache.hash.add(link_mode); + cache.hash.add(function_sections); cache.hash.add(options.strip); cache.hash.add(options.link_libc); + cache.hash.add(options.link_libcpp); cache.hash.add(options.output_mode); cache.hash.add(options.machine_code_model); // TODO audit this and make sure everything is in it @@ -596,10 +633,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { owned_link_dir = artifact_dir; const link_artifact_directory: Directory = .{ .handle = artifact_dir, - .path = if (options.zig_cache_directory.path) |p| - try std.fs.path.join(arena, &[_][]const u8{ p, artifact_sub_dir }) - else - artifact_sub_dir, + .path = try options.zig_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), }; break :blk link_artifact_directory; }; @@ -609,26 +643,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .ReleaseFast, .ReleaseSmall => false, }; - const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { - var buf = std.ArrayList(u8).init(arena); - for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| { - const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); - const is_enabled = options.target.cpu.features.isEnabled(index); - - if (feature.llvm_name) |llvm_name| { - const plus_or_minus = "-+"[@boolToInt(is_enabled)]; - try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len); - buf.appendAssumeCapacity(plus_or_minus); - buf.appendSliceAssumeCapacity(llvm_name); - buf.appendSliceAssumeCapacity(","); - } - } - assert(mem.endsWith(u8, buf.items, ",")); - buf.items[buf.items.len - 1] = 0; - buf.shrink(buf.items.len); - break :blk buf.items[0 .. buf.items.len - 1 :0].ptr; - } else null; - const stage1_module: ?*stage1.Module = if (build_options.is_stage1 and use_llvm) blk: { // Here we use the legacy stage1 C++ compiler to compile Zig code. const stage2_target = try arena.create(stage1.Stage2Target); @@ -646,7 +660,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { if (options.color == .Off) progress.terminal = null; const mod = module.?; - const main_zig_file = mod.root_pkg.root_src_path; + const main_zig_file = try mod.root_pkg.root_src_directory.join(arena, &[_][]const u8{ + mod.root_pkg.root_src_path, + }); const zig_lib_dir = options.zig_lib_directory.path.?; const builtin_sub = &[_][]const u8{"builtin.zig"}; const builtin_zig_path = try mod.zig_cache_artifact_directory.join(arena, builtin_sub); @@ -700,7 +716,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .dll_export_fns = dll_export_fns, .link_mode_dynamic = link_mode == .Dynamic, .valgrind_enabled = valgrind, - .function_sections = options.function_sections orelse false, + .function_sections = function_sections, .enable_stack_probing = stack_check, .enable_time_report = options.time_report, .enable_stack_report = false, @@ -790,6 +806,12 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .rand = options.rand, .clang_passthrough_mode = options.clang_passthrough_mode, .verbose_cc = options.verbose_cc, + .verbose_tokenize = options.verbose_tokenize, + .verbose_ast = options.verbose_ast, + .verbose_ir = options.verbose_ir, + .verbose_llvm_ir = options.verbose_llvm_ir, + .verbose_cimport = options.verbose_cimport, + .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, .disable_c_depfile = options.disable_c_depfile, .owned_link_dir = owned_link_dir, .is_test = options.is_test, @@ -823,10 +845,15 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { if (comp.wantBuildLibUnwindFromSource()) { try comp.work_queue.writeItem(.{ .libunwind = {} }); } - if (comp.stage1_module) |module| { try comp.work_queue.writeItem(.{ .stage1_module = {} }); } + if (is_exe_or_dyn_lib) { + try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); + if (!comp.bin_file.options.link_libc) { + try comp.work_queue.writeItem(.{ .zig_libc = {} }); + } + } return comp; } @@ -852,8 +879,14 @@ pub fn destroy(self: *Compilation) void { self.crt_files.deinit(gpa); } - if (self.libunwind_static_lib) |*unwind_crt_file| { - unwind_crt_file.deinit(gpa); + if (self.libunwind_static_lib) |*crt_file| { + crt_file.deinit(gpa); + } + if (self.compiler_rt_static_lib) |*crt_file| { + crt_file.deinit(gpa); + } + if (self.libc_static_lib) |*crt_file| { + crt_file.deinit(gpa); } for (self.c_object_table.items()) |entry| { @@ -889,41 +922,46 @@ pub fn update(self: *Compilation) !void { self.work_queue.writeItemAssumeCapacity(.{ .c_object = entry.key }); } - if (self.bin_file.options.module) |module| { - module.generation += 1; - - // TODO Detect which source files changed. - // Until then we simulate a full cache miss. Source files could have been loaded for any reason; - // to force a refresh we unload now. - if (module.root_scope.cast(Module.Scope.File)) |zig_file| { - zig_file.unload(module.gpa); - module.analyzeContainer(&zig_file.root_container) catch |err| switch (err) { - error.AnalysisFail => { - assert(self.totalErrorCount() != 0); - }, - else => |e| return e, - }; - } else if (module.root_scope.cast(Module.Scope.ZIRModule)) |zir_module| { - zir_module.unload(module.gpa); - module.analyzeRootZIRModule(zir_module) catch |err| switch (err) { - error.AnalysisFail => { - assert(self.totalErrorCount() != 0); - }, - else => |e| return e, - }; + const use_stage1 = build_options.is_stage1 and self.bin_file.options.use_llvm; + if (!use_stage1) { + if (self.bin_file.options.module) |module| { + module.generation += 1; + + // TODO Detect which source files changed. + // Until then we simulate a full cache miss. Source files could have been loaded for any reason; + // to force a refresh we unload now. + if (module.root_scope.cast(Module.Scope.File)) |zig_file| { + zig_file.unload(module.gpa); + module.analyzeContainer(&zig_file.root_container) catch |err| switch (err) { + error.AnalysisFail => { + assert(self.totalErrorCount() != 0); + }, + else => |e| return e, + }; + } else if (module.root_scope.cast(Module.Scope.ZIRModule)) |zir_module| { + zir_module.unload(module.gpa); + module.analyzeRootZIRModule(zir_module) catch |err| switch (err) { + error.AnalysisFail => { + assert(self.totalErrorCount() != 0); + }, + else => |e| return e, + }; + } } } try self.performAllTheWork(); - if (self.bin_file.options.module) |module| { - // Process the deletion set. - while (module.deletion_set.popOrNull()) |decl| { - if (decl.dependants.items().len != 0) { - decl.deletion_flag = false; - continue; + if (!use_stage1) { + if (self.bin_file.options.module) |module| { + // Process the deletion set. + while (module.deletion_set.popOrNull()) |decl| { + if (decl.dependants.items().len != 0) { + decl.deletion_flag = false; + continue; + } + try module.deleteDecl(decl); } - try module.deleteDecl(decl); } } @@ -1142,6 +1180,18 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { fatal("unable to build libunwind: {}", .{@errorName(err)}); }; }, + .libcompiler_rt => { + self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| { + // TODO Expose this as a normal compile error rather than crashing here. + fatal("unable to build compiler_rt: {}", .{@errorName(err)}); + }; + }, + .zig_libc => { + self.buildStaticLibFromZig("c.zig", &self.libc_static_lib) catch |err| { + // TODO Expose this as a normal compile error rather than crashing here. + fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)}); + }; + }, .generate_builtin_zig => { // This Job is only queued up if there is a zig module. self.updateBuiltinZigFile(self.bin_file.options.module.?) catch |err| { @@ -1691,7 +1741,7 @@ pub fn classifyFileExt(filename: []const u8) FileExt { } else if (mem.endsWith(u8, filename, ".zig")) { return .zig; } else if (mem.endsWith(u8, filename, ".zir")) { - return .zig; + return .zir; } else if (hasSharedLibraryExt(filename)) { return .shared_library; } else if (hasStaticLibraryExt(filename)) { @@ -2030,3 +2080,97 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 }); return buffer.toOwnedSlice(); } + +pub fn updateSubCompilation(sub_compilation: *Compilation) !void { + try sub_compilation.update(); + + // Look for compilation errors in this sub_compilation + var errors = try sub_compilation.getAllErrorsAlloc(); + defer errors.deinit(sub_compilation.gpa); + + if (errors.list.len != 0) { + for (errors.list) |full_err_msg| { + std.log.err("{}:{}:{}: {}\n", .{ + full_err_msg.src_path, + full_err_msg.line + 1, + full_err_msg.column + 1, + full_err_msg.msg, + }); + } + return error.BuildingLibCObjectFailed; + } +} + +fn buildStaticLibFromZig(comp: *Compilation, basename: []const u8, out: *?CRTFile) !void { + const tracy = trace(@src()); + defer tracy.end(); + + const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; + const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); + defer comp.gpa.free(special_path); + + var special_dir = try comp.zig_lib_directory.handle.openDir(special_sub, .{}); + defer special_dir.close(); + + var root_pkg: Package = .{ + .root_src_directory = .{ + .path = special_path, + .handle = special_dir, + }, + .root_src_path = basename, + }; + + const emit_bin = Compilation.EmitLoc{ + .directory = null, // Put it in the cache directory. + .basename = basename, + }; + const optimize_mode: std.builtin.Mode = blk: { + if (comp.is_test) + break :blk comp.bin_file.options.optimize_mode; + switch (comp.bin_file.options.optimize_mode) { + .Debug, .ReleaseFast, .ReleaseSafe => break :blk .ReleaseFast, + .ReleaseSmall => break :blk .ReleaseSmall, + } + }; + const sub_compilation = try Compilation.create(comp.gpa, .{ + // TODO use the global cache directory here + .zig_cache_directory = comp.zig_cache_directory, + .zig_lib_directory = comp.zig_lib_directory, + .target = comp.getTarget(), + .root_name = mem.split(basename, ".").next().?, + .root_pkg = &root_pkg, + .output_mode = .Lib, + .rand = comp.rand, + .libc_installation = comp.bin_file.options.libc_installation, + .emit_bin = emit_bin, + .optimize_mode = optimize_mode, + .link_mode = .Static, + .function_sections = true, + .want_sanitize_c = false, + .want_stack_check = false, + .want_valgrind = false, + .want_pic = comp.bin_file.options.pic, + .emit_h = null, + .strip = comp.bin_file.options.strip, + .is_native_os = comp.bin_file.options.is_native_os, + .self_exe_path = comp.self_exe_path, + .verbose_cc = comp.verbose_cc, + .verbose_link = comp.bin_file.options.verbose_link, + .verbose_tokenize = comp.verbose_tokenize, + .verbose_ast = comp.verbose_ast, + .verbose_ir = comp.verbose_ir, + .verbose_llvm_ir = comp.verbose_llvm_ir, + .verbose_cimport = comp.verbose_cimport, + .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, + .clang_passthrough_mode = comp.clang_passthrough_mode, + }); + defer sub_compilation.destroy(); + + try sub_compilation.updateSubCompilation(); + + assert(out.* == null); + out.* = Compilation.CRTFile{ + .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}), + .lock = sub_compilation.bin_file.toOwnedLock(), + }; +} diff --git a/src-self-hosted/Package.zig b/src-self-hosted/Package.zig index 027aaafe7d..14be8b64d6 100644 --- a/src-self-hosted/Package.zig +++ b/src-self-hosted/Package.zig @@ -1,32 +1,41 @@ pub const Table = std.StringHashMapUnmanaged(*Package); root_src_directory: Compilation.Directory, -/// Relative to `root_src_directory`. -root_src_path: []u8, -table: Table, +/// Relative to `root_src_directory`. May contain path separators. +root_src_path: []const u8, +table: Table = .{}, + +const std = @import("std"); +const mem = std.mem; +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; +const Package = @This(); +const Compilation = @import("Compilation.zig"); /// No references to `root_src_dir` and `root_src_path` are kept. pub fn create( gpa: *Allocator, - base_dir: std.fs.Dir, - /// Relative to `base_dir`. + base_directory: Compilation.Directory, + /// Relative to `base_directory`. root_src_dir: []const u8, /// Relative to `root_src_dir`. root_src_path: []const u8, ) !*Package { const ptr = try gpa.create(Package); errdefer gpa.destroy(ptr); + + const root_src_dir_path = try base_directory.join(gpa, &[_][]const u8{root_src_dir}); + errdefer gpa.free(root_src_dir_path); + const root_src_path_dupe = try mem.dupe(gpa, u8, root_src_path); errdefer gpa.free(root_src_path_dupe); - const root_src_dir_path = try mem.dupe(gpa, u8, root_src_dir); - errdefer gpa.free(root_src_dir_path); + ptr.* = .{ .root_src_directory = .{ .path = root_src_dir_path, - .handle = try base_dir.openDir(root_src_dir, .{}), + .handle = try base_directory.handle.openDir(root_src_dir, .{}), }, .root_src_path = root_src_path_dupe, - .table = .{}, }; return ptr; } @@ -50,10 +59,3 @@ pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) const name_dupe = try mem.dupe(gpa, u8, name); pkg.table.putAssumeCapacityNoClobber(name_dupe, package); } - -const std = @import("std"); -const mem = std.mem; -const Allocator = std.mem.Allocator; -const assert = std.debug.assert; -const Package = @This(); -const Compilation = @import("Compilation.zig"); diff --git a/src-self-hosted/glibc.zig b/src-self-hosted/glibc.zig index 5e34302c06..9ede436f63 100644 --- a/src-self-hosted/glibc.zig +++ b/src-self-hosted/glibc.zig @@ -713,11 +713,17 @@ fn build_crt_file( .c_source_files = c_source_files, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, + .verbose_tokenize = comp.verbose_tokenize, + .verbose_ast = comp.verbose_ast, + .verbose_ir = comp.verbose_ir, + .verbose_llvm_ir = comp.verbose_llvm_ir, + .verbose_cimport = comp.verbose_cimport, + .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, }); defer sub_compilation.destroy(); - try updateSubCompilation(sub_compilation); + try sub_compilation.updateSubCompilation(); try comp.crt_files.ensureCapacity(comp.gpa, comp.crt_files.count() + 1); const artifact_path = if (sub_compilation.bin_file.options.directory.path) |p| @@ -989,6 +995,12 @@ fn buildSharedLib( .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, + .verbose_tokenize = comp.verbose_tokenize, + .verbose_ast = comp.verbose_ast, + .verbose_ir = comp.verbose_ir, + .verbose_llvm_ir = comp.verbose_llvm_ir, + .verbose_cimport = comp.verbose_cimport, + .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .version = version, .version_script = map_file_path, @@ -997,25 +1009,5 @@ fn buildSharedLib( }); defer sub_compilation.destroy(); - try updateSubCompilation(sub_compilation); -} - -fn updateSubCompilation(sub_compilation: *Compilation) !void { - try sub_compilation.update(); - - // Look for compilation errors in this sub_compilation - var errors = try sub_compilation.getAllErrorsAlloc(); - defer errors.deinit(sub_compilation.gpa); - - if (errors.list.len != 0) { - for (errors.list) |full_err_msg| { - std.log.err("{}:{}:{}: {}\n", .{ - full_err_msg.src_path, - full_err_msg.line + 1, - full_err_msg.column + 1, - full_err_msg.msg, - }); - } - return error.BuildingLibCObjectFailed; - } + try sub_compilation.updateSubCompilation(); } diff --git a/src-self-hosted/libunwind.zig b/src-self-hosted/libunwind.zig index 3ba52573ce..0bb44808ff 100644 --- a/src-self-hosted/libunwind.zig +++ b/src-self-hosted/libunwind.zig @@ -109,12 +109,18 @@ pub fn buildStaticLib(comp: *Compilation) !void { .c_source_files = &c_source_files, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, + .verbose_tokenize = comp.verbose_tokenize, + .verbose_ast = comp.verbose_ast, + .verbose_ir = comp.verbose_ir, + .verbose_llvm_ir = comp.verbose_llvm_ir, + .verbose_cimport = comp.verbose_cimport, + .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .link_libc = true, }); defer sub_compilation.destroy(); - try updateSubCompilation(sub_compilation); + try sub_compilation.updateSubCompilation(); assert(comp.libunwind_static_lib == null); comp.libunwind_static_lib = Compilation.CRTFile{ @@ -122,23 +128,3 @@ pub fn buildStaticLib(comp: *Compilation) !void { .lock = sub_compilation.bin_file.toOwnedLock(), }; } - -fn updateSubCompilation(sub_compilation: *Compilation) !void { - try sub_compilation.update(); - - // Look for compilation errors in this sub_compilation - var errors = try sub_compilation.getAllErrorsAlloc(); - defer errors.deinit(sub_compilation.gpa); - - if (errors.list.len != 0) { - for (errors.list) |full_err_msg| { - std.log.err("{}:{}:{}: {}\n", .{ - full_err_msg.src_path, - full_err_msg.line + 1, - full_err_msg.column + 1, - full_err_msg.msg, - }); - } - return error.BuildingLibCObjectFailed; - } -} diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 88a964f2ff..3ec81715e4 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -387,13 +387,15 @@ 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.is_stage1 and base.options.use_llvm; + if (use_stage1) { + const obj_basename = try std.fmt.allocPrint(arena, "{}.o", .{base.options.root_name}); + const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename}); + break :blk full_obj_path; + } try base.flushModule(comp); - const obj_basename = base.intermediary_basename.?; - const full_obj_path = if (directory.path) |dir_path| - try std.fs.path.join(arena, &[_][]const u8{ dir_path, obj_basename }) - else - obj_basename; + const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename}); break :blk full_obj_path; } else null; diff --git a/src-self-hosted/link/Elf.zig b/src-self-hosted/link/Elf.zig index 5257b46279..0a44665176 100644 --- a/src-self-hosted/link/Elf.zig +++ b/src-self-hosted/link/Elf.zig @@ -1253,8 +1253,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { const is_lib = self.base.options.output_mode == .Lib; const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; + const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; const have_dynamic_linker = self.base.options.link_libc and - self.base.options.link_mode == .Dynamic and (is_dyn_lib or self.base.options.output_mode == .Exe); + self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib; try ch.addOptionalFile(self.base.options.linker_script); try ch.addOptionalFile(self.base.options.version_script); @@ -1489,16 +1490,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { try argv.append(p); } - // TODO compiler-rt and libc - //if (!g->is_dummy_so && (g->out_type == OutTypeExe || is_dyn_lib)) { - // if (g->libc_link_lib == nullptr) { - // Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node); - // try argv.append(buf_ptr(libc_a_path)); - // } - - // Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node); - // try argv.append(buf_ptr(compiler_rt_o_path)); - //} + // compiler-rt and libc + if (is_exe_or_dyn_lib) { + if (!self.base.options.link_libc) { + try argv.append(comp.libc_static_lib.?.full_object_path); + } + try argv.append(comp.compiler_rt_static_lib.?.full_object_path); + } // Shared libraries. try argv.ensureCapacity(argv.items.len + self.base.options.system_libs.len); @@ -1545,7 +1543,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); } else if (target.isMusl()) { try argv.append(comp.libunwind_static_lib.?.full_object_path); - try argv.append(comp.libc_static_lib.?); + try argv.append(comp.libc_static_lib.?.full_object_path); } else if (self.base.options.link_libcpp) { try argv.append(comp.libunwind_static_lib.?.full_object_path); } else { diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 6aa4be7c41..430a85b93e 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -1108,8 +1108,14 @@ pub fn buildOutputType( .yes => |p| p, }; - const root_pkg = if (root_src_file) |src_path| try Package.create(gpa, fs.cwd(), ".", src_path) else null; - defer if (root_pkg) |pkg| pkg.destroy(gpa); + var root_pkg_memory: Package = undefined; + const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { + root_pkg_memory = .{ + .root_src_directory = .{ .path = null, .handle = fs.cwd() }, + .root_src_path = src_path, + }; + break :blk &root_pkg_memory; + } else null; const self_exe_path = try fs.selfExePathAlloc(arena); var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { |
