diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2024-07-19 01:04:59 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-07-19 22:35:33 -0700 |
| commit | 4f742c4cfc3c3134a0d6ebfdfc354286ae97b2c1 (patch) | |
| tree | c20b44dbe98cb8cb7484b19aca727ad2957e42a2 /src/link.zig | |
| parent | b7e48c6bcd99457f84f0043a3f4590a6ac1f4933 (diff) | |
| download | zig-4f742c4cfc3c3134a0d6ebfdfc354286ae97b2c1.tar.gz zig-4f742c4cfc3c3134a0d6ebfdfc354286ae97b2c1.zip | |
dev: introduce dev environments that enable compiler feature sets
Diffstat (limited to 'src/link.zig')
| -rw-r--r-- | src/link.zig | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/src/link.zig b/src/link.zig index 03ee3185ab..cf780c76fa 100644 --- a/src/link.zig +++ b/src/link.zig @@ -21,6 +21,7 @@ const Value = @import("Value.zig"); const LlvmObject = @import("codegen/llvm.zig").Object; const lldMain = @import("main.zig").lldMain; const Package = @import("Package.zig"); +const dev = @import("dev.zig"); /// When adding a new field, remember to update `hashAddSystemLibs`. /// These are *always* dynamically linked. Static libraries will be @@ -192,7 +193,7 @@ pub const File = struct { ) !*File { switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); const ptr = try tag.Type().open(arena, comp, emit, options); return &ptr.base; }, @@ -207,7 +208,7 @@ pub const File = struct { ) !*File { switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); const ptr = try tag.Type().createEmpty(arena, comp, emit, options); return &ptr.base; }, @@ -219,12 +220,13 @@ pub const File = struct { } pub fn makeWritable(base: *File) !void { + dev.check(.make_writable); const comp = base.comp; const gpa = comp.gpa; switch (base.tag) { .coff, .elf, .macho, .plan9, .wasm => { - if (build_options.only_c) unreachable; if (base.file != null) return; + dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker }); const emit = base.emit; if (base.child_pid) |pid| { if (builtin.os.tag == .windows) { @@ -263,11 +265,12 @@ pub const File = struct { .mode = determineMode(use_lld, output_mode, link_mode), }); }, - .c, .spirv, .nvptx => {}, + .c, .spirv, .nvptx => dev.checkAny(&.{ .c_linker, .spirv_linker, .nvptx_linker }), } } pub fn makeExecutable(base: *File) !void { + dev.check(.make_executable); const comp = base.comp; const output_mode = comp.config.output_mode; const link_mode = comp.config.link_mode; @@ -283,7 +286,7 @@ pub const File = struct { } switch (base.tag) { .elf => if (base.file) |f| { - if (build_options.only_c) unreachable; + dev.check(.elf_linker); if (base.zcu_object_sub_path != null and use_lld) { // The file we have open is not the final file that we want to // make executable, so we don't have to close it. @@ -302,7 +305,7 @@ pub const File = struct { } }, .coff, .macho, .plan9, .wasm => if (base.file) |f| { - if (build_options.only_c) unreachable; + dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker }); if (base.zcu_object_sub_path != null) { // The file we have open is not the final file that we want to // make executable, so we don't have to close it. @@ -321,7 +324,7 @@ pub const File = struct { } } }, - .c, .spirv, .nvptx => {}, + .c, .spirv, .nvptx => dev.checkAny(&.{ .c_linker, .spirv_linker, .nvptx_linker }), } } @@ -366,13 +369,13 @@ pub const File = struct { /// constant. Returns the symbol index of the lowered constant in the read-only section /// of the final binary. pub fn lowerUnnamedConst(base: *File, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 { - if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { .spirv => unreachable, .c => unreachable, .nvptx => unreachable, - inline else => |t| { - return @as(*t.Type(), @fieldParentPtr("base", base)).lowerUnnamedConst(pt, val, decl_index); + inline else => |tag| { + dev.check(tag.devFeature()); + return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUnnamedConst(pt, val, decl_index); }, } } @@ -383,15 +386,15 @@ pub const File = struct { /// Optionally, it is possible to specify where to expect the symbol defined if it /// is an import. pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateDeclError!u32 { - if (build_options.only_c) @compileError("unreachable"); log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name }); switch (base.tag) { .plan9 => unreachable, .spirv => unreachable, .c => unreachable, .nvptx => unreachable, - inline else => |t| { - return @as(*t.Type(), @fieldParentPtr("base", base)).getGlobalSymbol(name, lib_name); + inline else => |tag| { + dev.check(tag.devFeature()); + return @as(*tag.Type(), @fieldParentPtr("base", base)).getGlobalSymbol(name, lib_name); }, } } @@ -402,7 +405,7 @@ pub const File = struct { assert(decl.has_tv); switch (base.tag) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDecl(pt, decl_index); }, } @@ -418,7 +421,7 @@ pub const File = struct { ) UpdateDeclError!void { switch (base.tag) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, air, liveness); }, } @@ -430,7 +433,7 @@ pub const File = struct { switch (base.tag) { .spirv, .nvptx => {}, inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(pt, decl_index); }, } @@ -454,7 +457,7 @@ pub const File = struct { if (base.file) |f| f.close(); switch (base.tag) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); @as(*tag.Type(), @fieldParentPtr("base", base)).deinit(); }, } @@ -536,12 +539,9 @@ pub const File = struct { /// and `use_lld`, not only `effectiveOutputMode`. /// `arena` has the lifetime of the call to `Compilation.update`. pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void { - if (build_options.only_c) { - assert(base.tag == .c); - return @as(*C, @fieldParentPtr("base", base)).flush(arena, tid, prog_node); - } const comp = base.comp; if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) { + dev.check(.clang_command); const gpa = comp.gpa; const emit = base.emit; // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) @@ -565,6 +565,7 @@ pub const File = struct { } switch (base.tag) { inline else => |tag| { + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).flush(arena, tid, prog_node); }, } @@ -575,7 +576,7 @@ pub const File = struct { pub fn flushModule(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void { switch (base.tag) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, tid, prog_node); }, } @@ -585,7 +586,7 @@ pub const File = struct { pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void { switch (base.tag) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); @as(*tag.Type(), @fieldParentPtr("base", base)).freeDecl(decl_index); }, } @@ -608,7 +609,7 @@ pub const File = struct { ) UpdateExportsError!void { switch (base.tag) { inline else => |tag| { - if (tag != .c and build_options.only_c) unreachable; + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(pt, exported, export_indices); }, } @@ -627,12 +628,12 @@ pub const File = struct { /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate /// the block/atom. pub fn getDeclVAddr(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 { - if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { .c => unreachable, .spirv => unreachable, .nvptx => unreachable, inline else => |tag| { + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).getDeclVAddr(pt, decl_index, reloc_info); }, } @@ -647,24 +648,24 @@ pub const File = struct { decl_align: InternPool.Alignment, src_loc: Zcu.LazySrcLoc, ) !LowerResult { - if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { .c => unreachable, .spirv => unreachable, .nvptx => unreachable, inline else => |tag| { + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerAnonDecl(pt, decl_val, decl_align, src_loc); }, } } pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 { - if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { .c => unreachable, .spirv => unreachable, .nvptx => unreachable, inline else => |tag| { + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).getAnonDeclVAddr(decl_val, reloc_info); }, } @@ -675,7 +676,6 @@ pub const File = struct { exported: Zcu.Exported, name: InternPool.NullTerminatedString, ) void { - if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { .plan9, .spirv, @@ -683,12 +683,15 @@ pub const File = struct { => {}, inline else => |tag| { + dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteExport(exported, name); }, } } pub fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void { + dev.check(.lld_linker); + const tracy = trace(@src()); defer tracy.end(); @@ -743,10 +746,8 @@ pub const File = struct { for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); } - if (!build_options.only_core_functionality) { - for (comp.win32_resource_table.keys()) |key| { - _ = try man.addFile(key.status.success.res_path, null); - } + for (comp.win32_resource_table.keys()) |key| { + _ = try man.addFile(key.status.success.res_path, null); } try man.addOptionalFile(zcu_obj_path); try man.addOptionalFile(compiler_rt_path); @@ -777,7 +778,7 @@ pub const File = struct { }; } - const win32_resource_table_len = if (build_options.only_core_functionality) 0 else comp.win32_resource_table.count(); + const win32_resource_table_len = comp.win32_resource_table.count(); const num_object_files = objects.len + comp.c_object_table.count() + win32_resource_table_len + 2; var object_files = try std.ArrayList([*:0]const u8).initCapacity(gpa, num_object_files); defer object_files.deinit(); @@ -788,10 +789,8 @@ pub const File = struct { for (comp.c_object_table.keys()) |key| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path)); } - if (!build_options.only_core_functionality) { - for (comp.win32_resource_table.keys()) |key| { - object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path)); - } + for (comp.win32_resource_table.keys()) |key| { + object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path)); } if (zcu_obj_path) |p| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); @@ -869,6 +868,10 @@ pub const File = struct { .dxcontainer => @panic("TODO implement dxcontainer object format"), }; } + + pub fn devFeature(tag: Tag) dev.Feature { + return @field(dev.Feature, @tagName(tag) ++ "_linker"); + } }; pub const ErrorFlags = struct { |
