Commit 3743c3e39c
Changed files (20)
src/codegen/spirv/Section.zig
@@ -386,8 +386,6 @@ test "SPIR-V Section emit() - string" {
}
test "SPIR-V Section emit() - extended mask" {
- if (@import("builtin").zig_backend == .stage1) return error.SkipZigTest;
-
var section = Section{};
defer section.deinit(std.testing.allocator);
src/codegen/llvm.zig
@@ -1586,6 +1586,24 @@ pub const Object = struct {
const global_index = self.nav_map.get(nav_index).?;
const comp = zcu.comp;
+ // If we're on COFF and linking with LLD, the linker cares about our exports to determine the subsystem in use.
+ if (comp.bin_file != null and
+ comp.bin_file.?.tag == .coff and
+ zcu.comp.config.use_lld and
+ ip.isFunctionType(ip.getNav(nav_index).typeOf(ip)))
+ {
+ const flags = &comp.bin_file.?.cast(.coff).?.lld_export_flags;
+ for (export_indices) |export_index| {
+ const name = export_index.ptr(zcu).opts.name;
+ if (name.eqlSlice("main", ip)) flags.c_main = true;
+ if (name.eqlSlice("WinMain", ip)) flags.winmain = true;
+ if (name.eqlSlice("wWinMain", ip)) flags.wwinmain = true;
+ if (name.eqlSlice("WinMainCRTStartup", ip)) flags.winmain_crt_startup = true;
+ if (name.eqlSlice("wWinMainCRTStartup", ip)) flags.wwinmain_crt_startup = true;
+ if (name.eqlSlice("DllMainCRTStartup", ip)) flags.dllmain_crt_startup = true;
+ }
+ }
+
if (export_indices.len != 0) {
return updateExportedGlobal(self, zcu, global_index, export_indices);
} else {
src/link/Elf/ZigObject.zig
@@ -310,7 +310,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
if (self.dwarf) |*dwarf| {
const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
defer pt.deactivate();
- try dwarf.flushModule(pt);
+ try dwarf.flushZcu(pt);
const gpa = elf_file.base.comp.gpa;
const cpu_arch = elf_file.getTarget().cpu.arch;
@@ -481,7 +481,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
self.debug_str_section_dirty = false;
}
- // The point of flushModule() is to commit changes, so in theory, nothing should
+ // The point of flushZcu() is to commit changes, so in theory, nothing should
// be dirty after this. However, it is possible for some things to remain
// dirty because they fail to be written in the event of compile errors,
// such as debug_line_header_dirty and debug_info_header_dirty.
@@ -661,7 +661,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
if (shdr.sh_type == elf.SHT_NOBITS) continue;
if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
// TODO ideally we don't have to fetch the code here.
- // Perhaps it would make sense to save the code until flushModule where we
+ // Perhaps it would make sense to save the code until flushZcu where we
// would free all of generated code?
const code = try self.codeAlloc(elf_file, atom_index);
defer gpa.free(code);
@@ -1075,7 +1075,7 @@ pub fn getOrCreateMetadataForLazySymbol(
}
state_ptr.* = .pending_flush;
const symbol_index = symbol_index_ptr.*;
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flushZcu
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index);
return symbol_index;
}
src/link/MachO/DebugSymbols.zig
@@ -178,7 +178,7 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) !u64
return offset;
}
-pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
+pub fn flushZcu(self: *DebugSymbols, macho_file: *MachO) !void {
const zo = macho_file.getZigObject().?;
for (self.relocs.items) |*reloc| {
const sym = zo.symbols.items[reloc.target];
src/link/MachO/ZigObject.zig
@@ -550,7 +550,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se
return sect;
}
-pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
+pub fn flushZcu(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
const diags = &macho_file.base.comp.link_diags;
// Handle any lazy symbols that were emitted by incremental compilation.
@@ -589,7 +589,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
if (self.dwarf) |*dwarf| {
const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
defer pt.deactivate();
- dwarf.flushModule(pt) catch |err| switch (err) {
+ dwarf.flushZcu(pt) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => |e| return diags.fail("failed to flush dwarf module: {s}", .{@errorName(e)}),
};
@@ -599,7 +599,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
self.debug_strtab_dirty = false;
}
- // The point of flushModule() is to commit changes, so in theory, nothing should
+ // The point of flushZcu() is to commit changes, so in theory, nothing should
// be dirty after this. However, it is possible for some things to remain
// dirty because they fail to be written in the event of compile errors,
// such as debug_line_header_dirty and debug_info_header_dirty.
@@ -1537,7 +1537,7 @@ pub fn getOrCreateMetadataForLazySymbol(
}
state_ptr.* = .pending_flush;
const symbol_index = symbol_index_ptr.*;
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flushZcu
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index);
return symbol_index;
}
src/link/C.zig
@@ -382,7 +382,7 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn
}
pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
+ return self.flushZcu(arena, tid, prog_node);
}
fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
@@ -400,7 +400,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
return defines;
}
-pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
+pub fn flushZcu(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
_ = arena; // Has the same lifetime as the call to Compilation.update.
const tracy = trace(@src());
src/link/Coff.zig
@@ -3,9 +3,6 @@
//! LLD for traditional linking (linking relocatable object files).
//! LLD is also the default linker for LLVM.
-/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
-llvm_object: ?LlvmObject.Ptr = null,
-
base: link.File,
image_base: u64,
subsystem: ?std.Target.SubSystem,
@@ -87,6 +84,16 @@ base_relocs: BaseRelocationTable = .{},
/// Hot-code swapping state.
hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},
+/// When linking with LLD, these flags are used to determine the subsystem to pass on the LLD command line.
+lld_export_flags: struct {
+ c_main: bool = false,
+ winmain: bool = false,
+ wwinmain: bool = false,
+ winmain_crt_startup: bool = false,
+ wwinmain_crt_startup: bool = false,
+ dllmain_crt_startup: bool = false,
+} = .{},
+
const is_hot_update_compatible = switch (builtin.target.os.tag) {
.windows => true,
else => false,
@@ -302,9 +309,6 @@ pub fn createEmpty(
.pdb_out_path = options.pdb_out_path,
.repro = options.repro,
};
- if (use_llvm and comp.config.have_zcu) {
- coff.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer coff.base.destroy();
if (use_lld and (use_llvm or !comp.config.have_zcu)) {
@@ -322,7 +326,6 @@ pub fn createEmpty(
.mode = link.File.determineMode(use_lld, output_mode, link_mode),
});
- assert(coff.llvm_object == null);
const gpa = comp.gpa;
try coff.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
@@ -428,8 +431,6 @@ pub fn open(
pub fn deinit(coff: *Coff) void {
const gpa = coff.base.comp.gpa;
- if (coff.llvm_object) |llvm_object| llvm_object.deinit();
-
for (coff.sections.items(.free_list)) |*free_list| {
free_list.deinit(gpa);
}
@@ -1103,9 +1104,6 @@ pub fn updateFunc(
if (build_options.skip_non_native and builtin.object_format != .coff) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (coff.llvm_object) |llvm_object| {
- return llvm_object.updateFunc(pt, func_index, air, liveness);
- }
const tracy = trace(@src());
defer tracy.end();
@@ -1205,7 +1203,6 @@ pub fn updateNav(
if (build_options.skip_non_native and builtin.object_format != .coff) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (coff.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
const tracy = trace(@src());
defer tracy.end();
@@ -1330,7 +1327,7 @@ pub fn getOrCreateAtomForLazySymbol(
}
state_ptr.* = .pending_flush;
const atom = atom_ptr.*;
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flushZcu
if (lazy_sym.ty != .anyerror_type) try coff.updateLazySymbolAtom(pt, lazy_sym, atom, switch (lazy_sym.kind) {
.code => coff.text_section_index.?,
.const_data => coff.rdata_section_index.?,
@@ -1463,8 +1460,6 @@ fn updateNavCode(
}
pub fn freeNav(coff: *Coff, nav_index: InternPool.NavIndex) void {
- if (coff.llvm_object) |llvm_object| return llvm_object.freeNav(nav_index);
-
const gpa = coff.base.comp.gpa;
if (coff.decls.fetchOrderedRemove(nav_index)) |const_kv| {
@@ -1485,50 +1480,7 @@ pub fn updateExports(
}
const zcu = pt.zcu;
- const ip = &zcu.intern_pool;
- const comp = coff.base.comp;
- const target = comp.root_mod.resolved_target.result;
-
- if (comp.config.use_llvm) {
- // Even in the case of LLVM, we need to notice certain exported symbols in order to
- // detect the default subsystem.
- for (export_indices) |export_idx| {
- const exp = export_idx.ptr(zcu);
- const exported_nav_index = switch (exp.exported) {
- .nav => |nav| nav,
- .uav => continue,
- };
- const exported_nav = ip.getNav(exported_nav_index);
- const exported_ty = exported_nav.typeOf(ip);
- if (!ip.isFunctionType(exported_ty)) continue;
- const c_cc = target.cCallingConvention().?;
- const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) {
- .x86 => .{ .x86_stdcall = .{} },
- else => c_cc,
- };
- const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu);
- const CcTag = std.builtin.CallingConvention.Tag;
- if (@as(CcTag, exported_cc) == @as(CcTag, c_cc) and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) {
- zcu.stage1_flags.have_c_main = true;
- } else if (@as(CcTag, exported_cc) == @as(CcTag, winapi_cc) and target.os.tag == .windows) {
- if (exp.opts.name.eqlSlice("WinMain", ip)) {
- zcu.stage1_flags.have_winmain = true;
- } else if (exp.opts.name.eqlSlice("wWinMain", ip)) {
- zcu.stage1_flags.have_wwinmain = true;
- } else if (exp.opts.name.eqlSlice("WinMainCRTStartup", ip)) {
- zcu.stage1_flags.have_winmain_crt_startup = true;
- } else if (exp.opts.name.eqlSlice("wWinMainCRTStartup", ip)) {
- zcu.stage1_flags.have_wwinmain_crt_startup = true;
- } else if (exp.opts.name.eqlSlice("DllMainCRTStartup", ip)) {
- zcu.stage1_flags.have_dllmain_crt_startup = true;
- }
- }
- }
- }
-
- if (coff.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
-
- const gpa = comp.gpa;
+ const gpa = zcu.gpa;
const metadata = switch (exported) {
.nav => |nav| blk: {
@@ -1621,7 +1573,6 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (coff.llvm_object) |_| return;
const metadata = switch (exported) {
.nav => |nav| coff.navs.getPtr(nav),
.uav => |uav| coff.uavs.getPtr(uav),
@@ -1692,7 +1643,7 @@ pub fn flush(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: st
};
}
switch (comp.config.output_mode) {
- .Exe, .Obj => return coff.flushModule(arena, tid, prog_node),
+ .Exe, .Obj => return coff.flushZcu(arena, tid, prog_node),
.Lib => return diags.fail("writing lib files not yet implemented for COFF", .{}),
}
}
@@ -1711,8 +1662,12 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_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 (comp.zcu != null) blk: {
- try coff.flushModule(arena, tid, prog_node);
+ const module_obj_path: ?[]const u8 = if (comp.zcu) |zcu| blk: {
+ if (zcu.llvm_object == null) {
+ try coff.flushZcu(arena, tid, prog_node);
+ } else {
+ // `Compilation.flush` has already made LLVM emit this object file for us.
+ }
if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, coff.base.zcu_object_sub_path.? });
@@ -1998,16 +1953,16 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
if (coff.subsystem) |explicit| break :blk explicit;
switch (target.os.tag) {
.windows => {
- if (comp.zcu) |module| {
- if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)
+ if (comp.zcu != null) {
+ if (coff.lld_export_flags.dllmain_crt_startup or is_dyn_lib)
break :blk null;
- if (module.stage1_flags.have_c_main or comp.config.is_test or
- module.stage1_flags.have_winmain_crt_startup or
- module.stage1_flags.have_wwinmain_crt_startup)
+ if (coff.lld_export_flags.c_main or comp.config.is_test or
+ coff.lld_export_flags.winmain_crt_startup or
+ coff.lld_export_flags.wwinmain_crt_startup)
{
break :blk .Console;
}
- if (module.stage1_flags.have_winmain or module.stage1_flags.have_wwinmain)
+ if (coff.lld_export_flags.winmain or coff.lld_export_flags.wwinmain)
break :blk .Windows;
}
},
@@ -2136,8 +2091,8 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
} else {
try argv.append("-NODEFAULTLIB");
if (!is_lib and entry_name == null) {
- if (comp.zcu) |module| {
- if (module.stage1_flags.have_winmain_crt_startup) {
+ if (comp.zcu != null) {
+ if (coff.lld_export_flags.winmain_crt_startup) {
try argv.append("-ENTRY:WinMainCRTStartup");
} else {
try argv.append("-ENTRY:wWinMainCRTStartup");
@@ -2244,7 +2199,7 @@ fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Director
return null;
}
-pub fn flushModule(
+pub fn flushZcu(
coff: *Coff,
arena: Allocator,
tid: Zcu.PerThread.Id,
@@ -2256,22 +2211,17 @@ pub fn flushModule(
const comp = coff.base.comp;
const diags = &comp.link_diags;
- if (coff.llvm_object) |llvm_object| {
- try coff.base.emitLlvmObject(arena, llvm_object, prog_node);
- return;
- }
-
const sub_prog_node = prog_node.start("COFF Flush", 0);
defer sub_prog_node.end();
- return flushModuleInner(coff, arena, tid) catch |err| switch (err) {
+ return flushZcuInner(coff, arena, tid) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.LinkFailure => return error.LinkFailure,
else => |e| return diags.fail("COFF flush failed: {s}", .{@errorName(e)}),
};
}
-fn flushModuleInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
+fn flushZcuInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
_ = arena;
const comp = coff.base.comp;
@@ -2397,7 +2347,6 @@ pub fn getNavVAddr(
nav_index: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
- assert(coff.llvm_object == null);
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
@@ -2483,8 +2432,6 @@ pub fn getUavVAddr(
uav: InternPool.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
- assert(coff.llvm_object == null);
-
const this_atom_index = coff.uavs.get(uav).?.atom;
const sym_index = coff.getAtom(this_atom_index).getSymbolIndex().?;
const atom_index = coff.getAtomIndexForSymbol(.{
@@ -3798,7 +3745,6 @@ const trace = @import("../tracy.zig").trace;
const Air = @import("../Air.zig");
const Compilation = @import("../Compilation.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Zcu = @import("../Zcu.zig");
const InternPool = @import("../InternPool.zig");
const TableSection = @import("table_section.zig").TableSection;
src/link/Dwarf.zig
@@ -4391,7 +4391,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
return @intFromEnum(abbrev_code);
}
-pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
+pub fn flushZcu(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
src/link/Elf.zig
@@ -32,9 +32,6 @@ entry_name: ?[]const u8,
ptr_width: PtrWidth,
-/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
-llvm_object: ?LlvmObject.Ptr = null,
-
/// A list of all input files.
/// First index is a special "null file". Order is otherwise not observed.
files: std.MultiArrayList(File.Entry) = .{},
@@ -344,9 +341,6 @@ pub fn createEmpty(
.print_map = options.print_map,
.dump_argv_list = .empty,
};
- if (use_llvm and comp.config.have_zcu) {
- self.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer self.base.destroy();
if (use_lld and (use_llvm or !comp.config.have_zcu)) {
@@ -457,8 +451,6 @@ pub fn open(
pub fn deinit(self: *Elf) void {
const gpa = self.base.comp.gpa;
- if (self.llvm_object) |llvm_object| llvm_object.deinit();
-
for (self.file_handles.items) |fh| {
fh.close();
}
@@ -515,7 +507,6 @@ pub fn deinit(self: *Elf) void {
}
pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);
}
@@ -530,7 +521,6 @@ pub fn lowerUav(
}
pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);
}
@@ -805,35 +795,29 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std
else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
};
}
- try self.flushModule(arena, tid, prog_node);
+ try self.flushZcu(arena, tid, prog_node);
}
-pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
+pub fn flushZcu(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
const comp = self.base.comp;
const diags = &comp.link_diags;
- if (self.llvm_object) |llvm_object| {
- try self.base.emitLlvmObject(arena, llvm_object, prog_node);
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- if (use_lld) return;
- }
-
if (comp.verbose_link) Compilation.dump_argv(self.dump_argv_list.items);
const sub_prog_node = prog_node.start("ELF Flush", 0);
defer sub_prog_node.end();
- return flushModuleInner(self, arena, tid) catch |err| switch (err) {
+ return flushZcuInner(self, arena, tid) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.LinkFailure => return error.LinkFailure,
else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),
};
}
-fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
+fn flushZcuInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
const comp = self.base.comp;
const gpa = comp.gpa;
const diags = &comp.link_diags;
@@ -1523,8 +1507,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
// 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 (comp.zcu != null) blk: {
- try self.flushModule(arena, tid, prog_node);
+ const module_obj_path: ?[]const u8 = if (comp.zcu) |zcu| blk: {
+ if (zcu.llvm_object == null) {
+ try self.flushZcu(arena, tid, prog_node);
+ } else {
+ // `Compilation.flush` has already made LLVM emit this object file for us.
+ }
if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });
@@ -2385,7 +2373,6 @@ pub fn writeElfHeader(self: *Elf) !void {
}
pub fn freeNav(self: *Elf, nav: InternPool.Nav.Index) void {
- if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
return self.zigObjectPtr().?.freeNav(self, nav);
}
@@ -2399,7 +2386,6 @@ pub fn updateFunc(
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
return self.zigObjectPtr().?.updateFunc(self, pt, func_index, air, liveness);
}
@@ -2411,7 +2397,6 @@ pub fn updateNav(
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
return self.zigObjectPtr().?.updateNav(self, pt, nav);
}
@@ -2423,7 +2408,6 @@ pub fn updateContainerType(
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |_| return;
const zcu = pt.zcu;
const gpa = zcu.gpa;
return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) {
@@ -2449,12 +2433,10 @@ pub fn updateExports(
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
}
pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
- if (self.llvm_object) |_| return;
return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);
}
@@ -2463,7 +2445,6 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (self.llvm_object) |_| return;
return self.zigObjectPtr().?.deleteExport(self, exported, name);
}
@@ -5332,7 +5313,6 @@ const GotSection = synthetic_sections.GotSection;
const GotPltSection = synthetic_sections.GotPltSection;
const HashSection = synthetic_sections.HashSection;
const LinkerDefined = @import("Elf/LinkerDefined.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Zcu = @import("../Zcu.zig");
const Object = @import("Elf/Object.zig");
const InternPool = @import("../InternPool.zig");
src/link/Goff.zig
@@ -17,10 +17,8 @@ const link = @import("../link.zig");
const trace = @import("../tracy.zig").trace;
const build_options = @import("build_options");
const Air = @import("../Air.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
base: link.File,
-llvm_object: LlvmObject.Ptr,
pub fn createEmpty(
arena: Allocator,
@@ -36,7 +34,6 @@ pub fn createEmpty(
assert(!use_lld); // Caught by Compilation.Config.resolve.
assert(target.os.tag == .zos); // Caught by Compilation.Config.resolve.
- const llvm_object = try LlvmObject.create(arena, comp);
const goff = try arena.create(Goff);
goff.* = .{
.base = .{
@@ -52,7 +49,6 @@ pub fn createEmpty(
.disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
- .llvm_object = llvm_object,
};
return goff;
@@ -70,7 +66,7 @@ pub fn open(
}
pub fn deinit(self: *Goff) void {
- self.llvm_object.deinit();
+ _ = self;
}
pub fn updateFunc(
@@ -80,17 +76,19 @@ pub fn updateFunc(
air: Air,
liveness: Air.Liveness,
) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .goff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- try self.llvm_object.updateFunc(pt, func_index, air, liveness);
+ _ = self;
+ _ = pt;
+ _ = func_index;
+ _ = air;
+ _ = liveness;
+ unreachable; // we always use llvm
}
pub fn updateNav(self: *Goff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .goff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateNav(pt, nav);
+ _ = self;
+ _ = pt;
+ _ = nav;
+ unreachable; // we always use llvm
}
pub fn updateExports(
@@ -99,21 +97,21 @@ pub fn updateExports(
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
) !void {
- if (build_options.skip_non_native and builtin.object_format != .goff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateExports(pt, exported, export_indices);
+ _ = self;
+ _ = pt;
+ _ = exported;
+ _ = export_indices;
+ unreachable; // we always use llvm
}
pub fn flush(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
+ return self.flushZcu(arena, tid, prog_node);
}
-pub fn flushModule(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- if (build_options.skip_non_native and builtin.object_format != .goff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
+pub fn flushZcu(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
+ _ = self;
+ _ = arena;
_ = tid;
-
- try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
+ _ = prog_node;
+ unreachable; // we always use llvm
}
src/link/MachO.zig
@@ -6,9 +6,6 @@ base: link.File,
rpath_list: []const []const u8,
-/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
-llvm_object: ?LlvmObject.Ptr = null,
-
/// Debug symbols bundle (or dSym).
d_sym: ?DebugSymbols = null,
@@ -225,9 +222,6 @@ pub fn createEmpty(
.force_load_objc = options.force_load_objc,
.discard_local_symbols = options.discard_local_symbols,
};
- if (use_llvm and comp.config.have_zcu) {
- self.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer self.base.destroy();
self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
@@ -280,8 +274,6 @@ pub fn open(
pub fn deinit(self: *MachO) void {
const gpa = self.base.comp.gpa;
- if (self.llvm_object) |llvm_object| llvm_object.deinit();
-
if (self.d_sym) |*d_sym| {
d_sym.deinit();
}
@@ -350,10 +342,10 @@ pub fn flush(
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) link.File.FlushError!void {
- try self.flushModule(arena, tid, prog_node);
+ try self.flushZcu(arena, tid, prog_node);
}
-pub fn flushModule(
+pub fn flushZcu(
self: *MachO,
arena: Allocator,
tid: Zcu.PerThread.Id,
@@ -366,10 +358,6 @@ pub fn flushModule(
const gpa = comp.gpa;
const diags = &self.base.comp.link_diags;
- if (self.llvm_object) |llvm_object| {
- try self.base.emitLlvmObject(arena, llvm_object, prog_node);
- }
-
const sub_prog_node = prog_node.start("MachO Flush", 0);
defer sub_prog_node.end();
@@ -385,7 +373,7 @@ pub fn flushModule(
// --verbose-link
if (comp.verbose_link) try self.dumpArgv(comp);
- if (self.getZigObject()) |zo| try zo.flushModule(self, tid);
+ if (self.getZigObject()) |zo| try zo.flushZcu(self, tid);
if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
@@ -629,7 +617,7 @@ pub fn flushModule(
error.LinkFailure => return error.LinkFailure,
else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),
};
- if (self.getDebugSymbols()) |dsym| dsym.flushModule(self) catch |err| switch (err) {
+ if (self.getDebugSymbols()) |dsym| dsym.flushZcu(self) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => |e| return diags.fail("failed to get debug symbols: {s}", .{@errorName(e)}),
};
@@ -3079,7 +3067,6 @@ pub fn updateFunc(
if (build_options.skip_non_native and builtin.object_format != .macho) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
return self.getZigObject().?.updateFunc(self, pt, func_index, air, liveness);
}
@@ -3087,12 +3074,10 @@ pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin
if (build_options.skip_non_native and builtin.object_format != .macho) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
return self.getZigObject().?.updateNav(self, pt, nav);
}
pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
- if (self.llvm_object) |_| return;
return self.getZigObject().?.updateLineNumber(pt, ti_id);
}
@@ -3105,7 +3090,6 @@ pub fn updateExports(
if (build_options.skip_non_native and builtin.object_format != .macho) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
return self.getZigObject().?.updateExports(self, pt, exported, export_indices);
}
@@ -3114,17 +3098,14 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (self.llvm_object) |_| return;
return self.getZigObject().?.deleteExport(self, exported, name);
}
pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {
- if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
return self.getZigObject().?.freeNav(nav);
}
pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);
}
@@ -3139,7 +3120,6 @@ pub fn lowerUav(
}
pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);
}
@@ -5496,7 +5476,6 @@ const ObjcStubsSection = synthetic.ObjcStubsSection;
const Object = @import("MachO/Object.zig");
const LazyBind = bind.LazyBind;
const LaSymbolPtrSection = synthetic.LaSymbolPtrSection;
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Md5 = std.crypto.hash.Md5;
const Zcu = @import("../Zcu.zig");
const InternPool = @import("../InternPool.zig");
src/link/Plan9.zig
@@ -494,7 +494,7 @@ fn updateFinish(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
// write the symbol
// we already have the got index
const sym: aout.Sym = .{
- .value = undefined, // the value of stuff gets filled in in flushModule
+ .value = undefined, // the value of stuff gets filled in in flushZcu
.type = atom.type,
.name = try gpa.dupe(u8, nav.name.toSlice(ip)),
};
@@ -543,7 +543,7 @@ pub fn flush(
.Obj => return diags.fail("writing plan9 object files unimplemented", .{}),
.Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),
}
- return self.flushModule(arena, tid, prog_node);
+ return self.flushZcu(arena, tid, prog_node);
}
pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
@@ -586,7 +586,7 @@ fn atomCount(self: *Plan9) usize {
return data_nav_count + fn_nav_count + lazy_atom_count + extern_atom_count + uav_atom_count;
}
-pub fn flushModule(
+pub fn flushZcu(
self: *Plan9,
arena: Allocator,
/// TODO: stop using this
@@ -610,7 +610,7 @@ pub fn flushModule(
const sub_prog_node = prog_node.start("Flush Module", 0);
defer sub_prog_node.end();
- log.debug("flushModule", .{});
+ log.debug("flushZcu", .{});
defer assert(self.hdr.entry != 0x0);
@@ -1039,7 +1039,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, lazy_sym: F
const atom = atom_ptr.*;
_ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self);
_ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self);
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flushZcu
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom);
return atom;
}
src/link/SpirV.zig
@@ -17,7 +17,7 @@
//! All regular functions.
// Because SPIR-V requires re-compilation anyway, and so hot swapping will not work
-// anyway, we simply generate all the code in flushModule. This keeps
+// anyway, we simply generate all the code in flushZcu. This keeps
// things considerably simpler.
const SpirV = @This();
@@ -194,17 +194,17 @@ pub fn updateExports(
}
pub fn flush(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
+ return self.flushZcu(arena, tid, prog_node);
}
-pub fn flushModule(
+pub fn flushZcu(
self: *SpirV,
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) link.File.FlushError!void {
// The goal is to never use this because it's only needed if we need to
- // write to InternPool, but flushModule is too late to be writing to the
+ // write to InternPool, but flushZcu is too late to be writing to the
// InternPool.
_ = tid;
src/link/Wasm.zig
@@ -36,7 +36,6 @@ const abi = @import("../arch/wasm/abi.zig");
const Compilation = @import("../Compilation.zig");
const Dwarf = @import("Dwarf.zig");
const InternPool = @import("../InternPool.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Zcu = @import("../Zcu.zig");
const codegen = @import("../codegen.zig");
const dev = @import("../dev.zig");
@@ -81,8 +80,6 @@ import_table: bool,
export_table: bool,
/// Output name of the file
name: []const u8,
-/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
-llvm_object: ?LlvmObject.Ptr = null,
/// List of relocatable files to be linked into the final binary.
objects: std.ArrayListUnmanaged(Object) = .{},
@@ -2992,9 +2989,6 @@ pub fn createEmpty(
.object_host_name = .none,
.preloaded_strings = undefined,
};
- if (use_llvm and comp.config.have_zcu) {
- wasm.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer wasm.base.destroy();
if (options.object_host_name) |name| wasm.object_host_name = (try wasm.internString(name)).toOptional();
@@ -3116,7 +3110,6 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
pub fn deinit(wasm: *Wasm) void {
const gpa = wasm.base.comp.gpa;
- if (wasm.llvm_object) |llvm_object| llvm_object.deinit();
wasm.navs_exe.deinit(gpa);
wasm.navs_obj.deinit(gpa);
@@ -3196,7 +3189,6 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
if (build_options.skip_non_native and builtin.object_format != .wasm) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
dev.check(.wasm_backend);
@@ -3228,7 +3220,6 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
if (build_options.skip_non_native and builtin.object_format != .wasm) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (wasm.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
@@ -3308,8 +3299,6 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (wasm.llvm_object != null) return;
-
const zcu = wasm.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const name_slice = name.toSlice(ip);
@@ -3332,7 +3321,6 @@ pub fn updateExports(
if (build_options.skip_non_native and builtin.object_format != .wasm) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -3391,7 +3379,7 @@ pub fn flush(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: st
else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
};
}
- return wasm.flushModule(arena, tid, prog_node);
+ return wasm.flushZcu(arena, tid, prog_node);
}
pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {
@@ -3785,26 +3773,20 @@ fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {
try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});
}
-pub fn flushModule(
+pub fn flushZcu(
wasm: *Wasm,
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) link.File.FlushError!void {
// The goal is to never use this because it's only needed if we need to
- // write to InternPool, but flushModule is too late to be writing to the
+ // write to InternPool, but flushZcu is too late to be writing to the
// InternPool.
_ = tid;
const comp = wasm.base.comp;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
const diags = &comp.link_diags;
const gpa = comp.gpa;
- if (wasm.llvm_object) |llvm_object| {
- try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
- if (use_lld) return;
- }
-
if (comp.verbose_link) Compilation.dump_argv(wasm.dump_argv_list.items);
if (wasm.base.zcu_object_sub_path) |path| {
@@ -3870,8 +3852,12 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_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 (comp.zcu != null) blk: {
- try wasm.flushModule(arena, tid, prog_node);
+ const module_obj_path: ?[]const u8 = if (comp.zcu) |zcu| blk: {
+ if (zcu.llvm_object == null) {
+ try wasm.flushZcu(arena, tid, prog_node);
+ } else {
+ // `Compilation.flush` has already made LLVM emit this object file for us.
+ }
if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });
src/link/Xcoff.zig
@@ -17,10 +17,8 @@ const link = @import("../link.zig");
const trace = @import("../tracy.zig").trace;
const build_options = @import("build_options");
const Air = @import("../Air.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
base: link.File,
-llvm_object: LlvmObject.Ptr,
pub fn createEmpty(
arena: Allocator,
@@ -36,7 +34,6 @@ pub fn createEmpty(
assert(!use_lld); // Caught by Compilation.Config.resolve.
assert(target.os.tag == .aix); // Caught by Compilation.Config.resolve.
- const llvm_object = try LlvmObject.create(arena, comp);
const xcoff = try arena.create(Xcoff);
xcoff.* = .{
.base = .{
@@ -52,7 +49,6 @@ pub fn createEmpty(
.disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
- .llvm_object = llvm_object,
};
return xcoff;
@@ -70,7 +66,7 @@ pub fn open(
}
pub fn deinit(self: *Xcoff) void {
- self.llvm_object.deinit();
+ _ = self;
}
pub fn updateFunc(
@@ -80,17 +76,19 @@ pub fn updateFunc(
air: Air,
liveness: Air.Liveness,
) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .xcoff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- try self.llvm_object.updateFunc(pt, func_index, air, liveness);
+ _ = self;
+ _ = pt;
+ _ = func_index;
+ _ = air;
+ _ = liveness;
+ unreachable; // we always use llvm
}
pub fn updateNav(self: *Xcoff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .xcoff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateNav(pt, nav);
+ _ = self;
+ _ = pt;
+ _ = nav;
+ unreachable; // we always use llvm
}
pub fn updateExports(
@@ -99,21 +97,21 @@ pub fn updateExports(
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
) !void {
- if (build_options.skip_non_native and builtin.object_format != .xcoff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateExports(pt, exported, export_indices);
+ _ = self;
+ _ = pt;
+ _ = exported;
+ _ = export_indices;
+ unreachable; // we always use llvm
}
pub fn flush(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
+ return self.flushZcu(arena, tid, prog_node);
}
-pub fn flushModule(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- if (build_options.skip_non_native and builtin.object_format != .xcoff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
+pub fn flushZcu(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
+ _ = self;
+ _ = arena;
_ = tid;
-
- try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
+ _ = prog_node;
+ unreachable; // we always use llvm
}
src/Zcu/PerThread.zig
@@ -1784,8 +1784,12 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A
};
}
- if (comp.bin_file) |lf| {
- lf.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
+ if (zcu.llvm_object) |llvm_object| {
+ llvm_object.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+ } else if (comp.bin_file) |lf| {
+ lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
error.Overflow, error.RelocationNotByteAligned => {
@@ -1798,10 +1802,6 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A
// Not a retryable failure.
},
};
- } else if (zcu.llvm_object) |llvm_object| {
- llvm_object.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- };
}
}
@@ -1877,7 +1877,6 @@ fn createFileRootStruct(
try pt.scanNamespace(namespace_index, decls);
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
- if (zcu.comp.config.use_llvm) break :codegen_type;
if (file.mod.?.strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
@@ -3309,10 +3308,10 @@ fn processExportsInner(
.uav => {},
}
- if (zcu.comp.bin_file) |lf| {
- try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
- } else if (zcu.llvm_object) |llvm_object| {
+ if (zcu.llvm_object) |llvm_object| {
try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
+ } else if (zcu.comp.bin_file) |lf| {
+ try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
}
}
@@ -4064,7 +4063,6 @@ fn recreateStructType(
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
- if (zcu.comp.config.use_llvm) break :codegen_type;
if (file.mod.?.strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
@@ -4157,7 +4155,6 @@ fn recreateUnionType(
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
- if (zcu.comp.config.use_llvm) break :codegen_type;
if (file.mod.?.strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
src/Compilation.zig
@@ -2188,14 +2188,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
},
}
- // Handle the case of e.g. -fno-emit-bin -femit-llvm-ir.
- if (options.emit_bin == null and (comp.verbose_llvm_ir != null or
- comp.verbose_llvm_bc != null or
- (use_llvm and comp.emit_asm != null) or
- comp.emit_llvm_ir != null or
- comp.emit_llvm_bc != null))
- {
- if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);
+ if (use_llvm) {
+ if (opt_zcu) |zcu| {
+ zcu.llvm_object = try LlvmObject.create(arena, comp);
+ }
}
break :comp comp;
@@ -2945,6 +2941,33 @@ fn flush(
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) !void {
+ if (comp.zcu) |zcu| {
+ if (zcu.llvm_object) |llvm_object| {
+ // Emit the ZCU object from LLVM now; it's required to flush the output file.
+ // If there's an output file, it wants to decide where the LLVM object goes!
+ const zcu_obj_emit_loc: ?EmitLoc = if (comp.bin_file) |lf| .{
+ .directory = null,
+ .basename = lf.zcu_object_sub_path.?,
+ } else null;
+ const sub_prog_node = prog_node.start("LLVM Emit Object", 0);
+ defer sub_prog_node.end();
+ try llvm_object.emit(.{
+ .pre_ir_path = comp.verbose_llvm_ir,
+ .pre_bc_path = comp.verbose_llvm_bc,
+ .bin_path = try resolveEmitLoc(arena, default_artifact_directory, zcu_obj_emit_loc),
+ .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm),
+ .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir),
+ .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc),
+
+ .is_debug = comp.root_mod.optimize_mode == .Debug,
+ .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
+ .time_report = comp.time_report,
+ .sanitize_thread = comp.config.any_sanitize_thread,
+ .fuzz = comp.config.any_fuzz,
+ .lto = comp.config.lto,
+ });
+ }
+ }
if (comp.bin_file) |lf| {
// This is needed before reading the error flags.
lf.flush(arena, tid, prog_node) catch |err| switch (err) {
@@ -2952,13 +2975,8 @@ fn flush(
error.OutOfMemory => return error.OutOfMemory,
};
}
-
if (comp.zcu) |zcu| {
try link.File.C.flushEmitH(zcu);
-
- if (zcu.llvm_object) |llvm_object| {
- try emitLlvmObject(comp, arena, default_artifact_directory, null, llvm_object, prog_node);
- }
}
}
@@ -3233,34 +3251,6 @@ fn emitOthers(comp: *Compilation) void {
}
}
-pub fn emitLlvmObject(
- comp: *Compilation,
- arena: Allocator,
- default_artifact_directory: Cache.Path,
- bin_emit_loc: ?EmitLoc,
- llvm_object: LlvmObject.Ptr,
- prog_node: std.Progress.Node,
-) !void {
- const sub_prog_node = prog_node.start("LLVM Emit Object", 0);
- defer sub_prog_node.end();
-
- try llvm_object.emit(.{
- .pre_ir_path = comp.verbose_llvm_ir,
- .pre_bc_path = comp.verbose_llvm_bc,
- .bin_path = try resolveEmitLoc(arena, default_artifact_directory, bin_emit_loc),
- .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm),
- .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir),
- .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc),
-
- .is_debug = comp.root_mod.optimize_mode == .Debug,
- .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
- .time_report = comp.time_report,
- .sanitize_thread = comp.config.any_sanitize_thread,
- .fuzz = comp.config.any_fuzz,
- .lto = comp.config.lto,
- });
-}
-
fn resolveEmitLoc(
arena: Allocator,
default_artifact_directory: Cache.Path,
src/link.zig
@@ -19,7 +19,6 @@ const Zcu = @import("Zcu.zig");
const InternPool = @import("InternPool.zig");
const Type = @import("Type.zig");
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");
@@ -704,7 +703,9 @@ pub const File = struct {
}
/// May be called before or after updateExports for any given Nav.
+ /// Asserts that the ZCU is not using the LLVM backend.
fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
const nav = pt.zcu.intern_pool.getNav(nav_index);
assert(nav.status == .fully_resolved);
switch (base.tag) {
@@ -721,7 +722,9 @@ pub const File = struct {
TypeFailureReported,
};
+ /// Never called when LLVM is codegenning the ZCU.
fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
else => {},
inline .elf => |tag| {
@@ -733,6 +736,7 @@ pub const File = struct {
/// May be called before or after updateExports for any given Decl.
/// TODO: currently `pub` because `Zcu.PerThread` is calling this.
+ /// Never called when LLVM is codegenning the ZCU.
pub fn updateFunc(
base: *File,
pt: Zcu.PerThread,
@@ -740,6 +744,7 @@ pub const File = struct {
air: Air,
liveness: Air.Liveness,
) UpdateNavError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
inline else => |tag| {
dev.check(tag.devFeature());
@@ -756,7 +761,9 @@ pub const File = struct {
/// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
/// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
+ /// Never called when LLVM is codegenning the ZCU.
fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
{
const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
const file = pt.zcu.fileByIndex(ti.file);
@@ -846,11 +853,13 @@ pub const File = struct {
/// Commit pending changes and write headers. Works based on `effectiveOutputMode`
/// rather than final output mode.
- pub fn flushModule(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
+ /// Never called when LLVM is codegenning the ZCU.
+ fn flushZcu(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
inline else => |tag| {
dev.check(tag.devFeature());
- return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, tid, prog_node);
+ return @as(*tag.Type(), @fieldParentPtr("base", base)).flushZcu(arena, tid, prog_node);
},
}
}
@@ -864,12 +873,14 @@ pub const File = struct {
/// a list of size 1, meaning that `exported` is exported once. However, it is possible
/// to export the same thing with multiple different symbol names (aliases).
/// May be called before or after updateDecl for any given Decl.
+ /// Never called when LLVM is codegenning the ZCU.
pub fn updateExports(
base: *File,
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
) UpdateExportsError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
inline else => |tag| {
dev.check(tag.devFeature());
@@ -896,7 +907,9 @@ pub const File = struct {
/// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
/// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
/// the block/atom.
+ /// Never called when LLVM is codegenning the ZCU.
pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.c => unreachable,
.spirv => unreachable,
@@ -909,6 +922,7 @@ pub const File = struct {
}
}
+ /// Never called when LLVM is codegenning the ZCU.
pub fn lowerUav(
base: *File,
pt: Zcu.PerThread,
@@ -916,6 +930,7 @@ pub const File = struct {
decl_align: InternPool.Alignment,
src_loc: Zcu.LazySrcLoc,
) !codegen.GenResult {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.c => unreachable,
.spirv => unreachable,
@@ -928,7 +943,9 @@ pub const File = struct {
}
}
+ /// Never called when LLVM is codegenning the ZCU.
pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.c => unreachable,
.spirv => unreachable,
@@ -941,11 +958,13 @@ pub const File = struct {
}
}
+ /// Never called when LLVM is codegenning the ZCU.
pub fn deleteExport(
base: *File,
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.plan9,
.spirv,
@@ -1077,7 +1096,7 @@ pub const File = struct {
}
}
- pub fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
+ 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());
@@ -1103,9 +1122,12 @@ 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 zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
- try base.flushModule(arena, tid, prog_node);
-
+ const zcu_obj_path: ?[]const u8 = if (opt_zcu) |zcu| blk: {
+ if (zcu.llvm_object == null) {
+ try base.flushZcu(arena, tid, prog_node);
+ } else {
+ // `Compilation.flush` has already made LLVM emit this object file for us.
+ }
const dirname = fs.path.dirname(full_out_path_z) orelse ".";
break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? });
} else null;
@@ -1346,21 +1368,6 @@ pub const File = struct {
return output_mode == .Lib and !self.isStatic();
}
- pub fn emitLlvmObject(
- base: File,
- arena: Allocator,
- llvm_object: LlvmObject.Ptr,
- prog_node: std.Progress.Node,
- ) !void {
- return base.comp.emitLlvmObject(arena, .{
- .root_dir = base.emit.root_dir,
- .sub_path = std.fs.path.dirname(base.emit.sub_path) orelse "",
- }, .{
- .directory = null,
- .basename = base.zcu_object_sub_path.?,
- }, llvm_object, prog_node);
- }
-
pub fn cgFail(
base: *File,
nav_index: InternPool.Nav.Index,
@@ -1600,7 +1607,11 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
// on the failed type, so when it is changed the `Nav` will be updated.
return;
}
- if (comp.bin_file) |lf| {
+ if (zcu.llvm_object) |llvm_object| {
+ llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
+ error.OutOfMemory => diags.setAllocFailure(),
+ };
+ } else if (comp.bin_file) |lf| {
lf.updateNav(pt, nav_index) catch |err| switch (err) {
error.OutOfMemory => diags.setAllocFailure(),
error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
@@ -1616,10 +1627,6 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
// Not a retryable failure.
},
};
- } else if (zcu.llvm_object) |llvm_object| {
- llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
- error.OutOfMemory => diags.setAllocFailure(),
- };
}
},
.link_func => |func| {
@@ -1650,11 +1657,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
// on the failed type, so when that is changed, this type will be updated.
return;
}
- if (comp.bin_file) |lf| {
- lf.updateContainerType(pt, ty) catch |err| switch (err) {
- error.OutOfMemory => diags.setAllocFailure(),
- error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
- };
+ if (zcu.llvm_object == null) {
+ if (comp.bin_file) |lf| {
+ lf.updateContainerType(pt, ty) catch |err| switch (err) {
+ error.OutOfMemory => diags.setAllocFailure(),
+ error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
+ };
+ }
}
},
.update_line_number => |ti| {
@@ -1664,11 +1673,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
}
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
defer pt.deactivate();
- if (comp.bin_file) |lf| {
- lf.updateLineNumber(pt, ti) catch |err| switch (err) {
- error.OutOfMemory => diags.setAllocFailure(),
- else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
- };
+ if (pt.zcu.llvm_object == null) {
+ if (comp.bin_file) |lf| {
+ lf.updateLineNumber(pt, ti) catch |err| switch (err) {
+ error.OutOfMemory => diags.setAllocFailure(),
+ else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
+ };
+ }
}
},
}
src/target.zig
@@ -739,7 +739,7 @@ pub fn functionPointerMask(target: std.Target) ?u64 {
pub fn supportsTailCall(target: std.Target, backend: std.builtin.CompilerBackend) bool {
switch (backend) {
- .stage1, .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),
+ .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),
.stage2_c => return true,
else => return false,
}
src/Zcu.zig
@@ -56,9 +56,8 @@ comptime {
/// General-purpose allocator. Used for both temporary and long-term storage.
gpa: Allocator,
comp: *Compilation,
-/// Usually, the LlvmObject is managed by linker code, however, in the case
-/// that -fno-emit-bin is specified, the linker code never executes, so we
-/// store the LlvmObject here.
+/// If the ZCU is emitting an LLVM object (i.e. we are using the LLVM backend), then this is the
+/// `LlvmObject` we are emitting to.
llvm_object: ?LlvmObject.Ptr,
/// Pointer to externally managed resource.
@@ -267,16 +266,6 @@ resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = n
/// Reset to `false` at the start of each update in `Compilation.update`.
skip_analysis_this_update: bool = false,
-stage1_flags: packed struct {
- have_winmain: bool = false,
- have_wwinmain: bool = false,
- have_winmain_crt_startup: bool = false,
- have_wwinmain_crt_startup: bool = false,
- have_dllmain_crt_startup: bool = false,
- have_c_main: bool = false,
- reserved: u2 = 0,
-} = .{},
-
test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,