Commit 0b3c3c02e3
Changed files (11)
src
link
src/arch/riscv64/Emit.zig
@@ -125,7 +125,6 @@ pub fn emitMir(emit: *Emit) Error!void {
});
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
},
- .plan9 => {},
.none => {},
}
},
@@ -142,7 +141,6 @@ pub fn emitMir(emit: *Emit) Error!void {
});
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
},
- .plan9 => {},
.none => {},
}
},
@@ -200,7 +198,6 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
emit.prev_di_column = column;
emit.prev_di_pc = emit.code.items.len;
},
- .plan9 => {},
.none => {},
}
}
src/arch/sparc64/Emit.zig
@@ -179,7 +179,6 @@ fn mirDebugPrologueEnd(emit: *Emit) !void {
try dbg_out.setPrologueEnd();
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
},
- .plan9 => {},
.none => {},
}
}
@@ -190,7 +189,6 @@ fn mirDebugEpilogueBegin(emit: *Emit) !void {
try dbg_out.setEpilogueBegin();
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
},
- .plan9 => {},
.none => {},
}
}
src/arch/x86_64/Emit.zig
@@ -82,7 +82,6 @@ pub fn emitMir(emit: *Emit) Error!void {
}),
else => unreachable,
},
- .plan9 => {},
.none => {},
}
continue;
@@ -173,9 +172,6 @@ pub fn emitMir(emit: *Emit) Error!void {
coff_file.getAtom(atom).getSymbolIndex().?
else |err|
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
- else if (emit.bin_file.cast(.plan9)) |p9_file|
- p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
- return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
else
return emit.fail("lazy symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
.is_extern = false,
@@ -418,7 +414,6 @@ pub fn emitMir(emit: *Emit) Error!void {
else => unreachable,
.pseudo_dbg_prologue_end_none => switch (emit.debug_output) {
.dwarf => |dwarf| try dwarf.setPrologueEnd(),
- .plan9 => {},
.none => {},
},
.pseudo_dbg_line_stmt_line_column => try emit.dbgAdvancePCAndLine(.{
@@ -439,7 +434,6 @@ pub fn emitMir(emit: *Emit) Error!void {
});
try emit.dbgAdvancePCAndLine(emit.prev_di_loc);
},
- .plan9 => {},
.none => {},
},
.pseudo_dbg_enter_block_none => switch (emit.debug_output) {
@@ -449,7 +443,6 @@ pub fn emitMir(emit: *Emit) Error!void {
});
try dwarf.enterBlock(emit.code.items.len);
},
- .plan9 => {},
.none => {},
},
.pseudo_dbg_leave_block_none => switch (emit.debug_output) {
@@ -459,7 +452,6 @@ pub fn emitMir(emit: *Emit) Error!void {
});
try dwarf.leaveBlock(emit.code.items.len);
},
- .plan9 => {},
.none => {},
},
.pseudo_dbg_enter_inline_func => switch (emit.debug_output) {
@@ -469,7 +461,6 @@ pub fn emitMir(emit: *Emit) Error!void {
});
try dwarf.enterInlineFunc(mir_inst.data.ip_index, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column);
},
- .plan9 => {},
.none => {},
},
.pseudo_dbg_leave_inline_func => switch (emit.debug_output) {
@@ -479,7 +470,6 @@ pub fn emitMir(emit: *Emit) Error!void {
});
try dwarf.leaveInlineFunc(mir_inst.data.ip_index, emit.code.items.len);
},
- .plan9 => {},
.none => {},
},
.pseudo_dbg_arg_none,
@@ -613,7 +603,7 @@ pub fn emitMir(emit: *Emit) Error!void {
loc,
);
},
- .plan9, .none => local_index += 1,
+ .none => local_index += 1,
},
.pseudo_dbg_arg_val, .pseudo_dbg_var_val => switch (emit.debug_output) {
.dwarf => |dwarf| {
@@ -630,11 +620,10 @@ pub fn emitMir(emit: *Emit) Error!void {
.fromInterned(mir_inst.data.ip_index),
);
},
- .plan9, .none => local_index += 1,
+ .none => local_index += 1,
},
.pseudo_dbg_var_args_none => switch (emit.debug_output) {
.dwarf => |dwarf| try dwarf.genVarArgsDebugInfo(),
- .plan9 => {},
.none => {},
},
.pseudo_dead_none => {},
@@ -929,38 +918,6 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {
emit.prev_di_loc = loc;
emit.prev_di_pc = emit.code.items.len;
},
- .plan9 => |dbg_out| {
- if (delta_pc <= 0) return; // only do this when the pc changes
-
- // increasing the line number
- try link.File.Plan9.changeLine(&dbg_out.dbg_line, @intCast(delta_line));
- // increasing the pc
- const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
- if (d_pc_p9 > 0) {
- // minus one because if its the last one, we want to leave space to change the line which is one pc quanta
- var diff = @divExact(d_pc_p9, dbg_out.pc_quanta) - dbg_out.pc_quanta;
- while (diff > 0) {
- if (diff < 64) {
- try dbg_out.dbg_line.append(@intCast(diff + 128));
- diff = 0;
- } else {
- try dbg_out.dbg_line.append(@intCast(64 + 128));
- diff -= 64;
- }
- }
- if (dbg_out.pcop_change_index) |pci|
- dbg_out.dbg_line.items[pci] += 1;
- dbg_out.pcop_change_index = @intCast(dbg_out.dbg_line.items.len - 1);
- } else if (d_pc_p9 == 0) {
- // we don't need to do anything, because adding the pc quanta does it for us
- } else unreachable;
- if (dbg_out.start_line == null)
- dbg_out.start_line = emit.prev_di_loc.line;
- dbg_out.end_line = loc.line;
- // only do this if the pc changed
- emit.prev_di_loc = loc;
- emit.prev_di_pc = emit.code.items.len;
- },
.none => {},
}
}
src/arch/x86_64/Mir.zig
@@ -2004,7 +2004,6 @@ pub fn emit(
const atom = try cf.getOrCreateAtomForNav(nav);
break :sym cf.getAtom(atom).getSymbolIndex().?;
}
- if (lf.cast(.plan9)) |p9f| break :sym try p9f.seeNav(pt, nav);
unreachable;
},
.debug_output = debug_output,
@@ -2015,7 +2014,6 @@ pub fn emit(
.column = func.lbrace_column,
.is_stmt = switch (debug_output) {
.dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt,
- .plan9 => undefined,
.none => undefined,
},
},
@@ -2067,8 +2065,6 @@ pub fn emitLazy(
return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
break :sym cf.getAtom(atom).getSymbolIndex().?;
}
- if (lf.cast(.plan9)) |p9f| break :sym p9f.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
- return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
unreachable;
},
.debug_output = debug_output,
src/link/Elf/ZigObject.zig
@@ -950,7 +950,6 @@ pub fn getNavVAddr(
.target_sym = this_sym_index,
.target_off = reloc_info.addend,
}),
- .plan9 => unreachable,
.none => unreachable,
},
}
@@ -983,7 +982,6 @@ pub fn getUavVAddr(
.target_sym = sym_index,
.target_off = reloc_info.addend,
}),
- .plan9 => unreachable,
.none => unreachable,
},
}
src/link/MachO/ZigObject.zig
@@ -650,7 +650,6 @@ pub fn getNavVAddr(
.target_sym = sym_index,
.target_off = reloc_info.addend,
}),
- .plan9 => unreachable,
.none => unreachable,
},
}
@@ -690,7 +689,6 @@ pub fn getUavVAddr(
.target_sym = sym_index,
.target_off = reloc_info.addend,
}),
- .plan9 => unreachable,
.none => unreachable,
},
}
src/link/Plan9/aout.zig
@@ -1,131 +0,0 @@
-const std = @import("std");
-const assert = std.debug.assert;
-
-/// All integers are in big-endian format (needs a byteswap).
-pub const ExecHdr = extern struct {
- magic: u32,
- text: u32,
- data: u32,
- bss: u32,
- syms: u32,
- /// You should truncate this to 32 bits on 64 bit systems, then but the actual 8 bytes
- /// in the fat header.
- entry: u32,
- spsz: u32,
- pcsz: u32,
- comptime {
- assert(@sizeOf(@This()) == 32);
- }
- /// It is up to the caller to discard the last 8 bytes if the header is not fat.
- pub fn toU8s(self: *@This()) [40]u8 {
- var buf: [40]u8 = undefined;
- var i: u8 = 0;
- inline for (std.meta.fields(@This())) |f| {
- std.mem.writeInt(u32, buf[i..][0..4], @field(self, f.name), .big);
- i += 4;
- }
- return buf;
- }
-};
-
-pub const Sym = struct {
- /// Big endian in the file
- value: u64,
- type: Type,
- name: []const u8,
-
- pub const undefined_symbol: Sym = .{
- .value = undefined,
- .type = .bad,
- .name = "undefined_symbol",
- };
-
- /// The type field is one of the following characters with the
- /// high bit set:
- /// T text segment symbol
- /// t static text segment symbol
- /// L leaf function text segment symbol
- /// l static leaf function text segment symbol
- /// D data segment symbol
- /// d static data segment symbol
- /// B bss segment symbol
- /// b static bss segment symbol
- /// a automatic (local) variable symbol
- /// p function parameter symbol
- /// f source file name components
- /// z source file name
- /// Z source file line offset
- /// m for '.frame'
- pub const Type = enum(u8) {
- T = 0x80 | 'T',
- t = 0x80 | 't',
- L = 0x80 | 'L',
- l = 0x80 | 'l',
- D = 0x80 | 'D',
- d = 0x80 | 'd',
- B = 0x80 | 'B',
- b = 0x80 | 'b',
- a = 0x80 | 'a',
- p = 0x80 | 'p',
- f = 0x80 | 'f',
- z = 0x80 | 'z',
- Z = 0x80 | 'Z',
- m = 0x80 | 'm',
- /// represents an undefined symbol, to be removed in flush
- bad = 0,
-
- pub fn toGlobal(self: Type) Type {
- return switch (self) {
- .t => .T,
- .b => .B,
- .d => .D,
- else => unreachable,
- };
- }
- };
-};
-
-pub const HDR_MAGIC = 0x00008000;
-pub inline fn _MAGIC(f: anytype, b: anytype) @TypeOf(f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7))) {
- return f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7));
-}
-pub const A_MAGIC = _MAGIC(0, 8); // 68020
-pub const I_MAGIC = _MAGIC(0, 11); // intel 386
-pub const J_MAGIC = _MAGIC(0, 12); // intel 960 (retired)
-pub const K_MAGIC = _MAGIC(0, 13); // sparc
-pub const V_MAGIC = _MAGIC(0, 16); // mips 3000 BE
-pub const X_MAGIC = _MAGIC(0, 17); // att dsp 3210 (retired)
-pub const M_MAGIC = _MAGIC(0, 18); // mips 4000 BE
-pub const D_MAGIC = _MAGIC(0, 19); // amd 29000 (retired)
-pub const E_MAGIC = _MAGIC(0, 20); // arm
-pub const Q_MAGIC = _MAGIC(0, 21); // powerpc
-pub const N_MAGIC = _MAGIC(0, 22); // mips 4000 LE
-pub const L_MAGIC = _MAGIC(0, 23); // dec alpha (retired)
-pub const P_MAGIC = _MAGIC(0, 24); // mips 3000 LE
-pub const U_MAGIC = _MAGIC(0, 25); // sparc64
-pub const S_MAGIC = _MAGIC(HDR_MAGIC, 26); // amd64
-pub const T_MAGIC = _MAGIC(HDR_MAGIC, 27); // powerpc64
-pub const R_MAGIC = _MAGIC(HDR_MAGIC, 28); // arm64
-
-pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 {
- return switch (arch) {
- .x86 => I_MAGIC,
- .sparc => K_MAGIC, // TODO should sparc64 go here?
- .mips => V_MAGIC,
- .arm => E_MAGIC,
- .aarch64 => R_MAGIC,
- .powerpc => Q_MAGIC,
- .powerpc64 => T_MAGIC,
- .x86_64 => S_MAGIC,
- else => error.ArchNotSupportedByPlan9,
- };
-}
-
-/// gets the quantization of pc for the arch
-pub fn getPCQuant(arch: std.Target.Cpu.Arch) !u8 {
- return switch (arch) {
- .x86, .x86_64 => 1,
- .powerpc, .powerpc64, .mips, .sparc, .arm, .aarch64 => 4,
- else => error.ArchNotSupportedByPlan9,
- };
-}
src/link/Plan9.zig
@@ -1,1426 +0,0 @@
-//! This implementation does all the linking work in flush(). A future improvement
-//! would be to add incremental linking in a similar way as ELF does.
-
-const Plan9 = @This();
-const link = @import("../link.zig");
-const Zcu = @import("../Zcu.zig");
-const InternPool = @import("../InternPool.zig");
-const Compilation = @import("../Compilation.zig");
-const aout = @import("Plan9/aout.zig");
-const codegen = @import("../codegen.zig");
-const trace = @import("../tracy.zig").trace;
-const File = link.File;
-const build_options = @import("build_options");
-const Air = @import("../Air.zig");
-const Type = @import("../Type.zig");
-const Value = @import("../Value.zig");
-const AnalUnit = InternPool.AnalUnit;
-
-const std = @import("std");
-const builtin = @import("builtin");
-const mem = std.mem;
-const Allocator = std.mem.Allocator;
-const log = std.log.scoped(.link);
-const assert = std.debug.assert;
-const Path = std.Build.Cache.Path;
-
-base: link.File,
-sixtyfour_bit: bool,
-bases: Bases,
-
-/// A symbol's value is just casted down when compiling
-/// for a 32 bit target.
-/// Does not represent the order or amount of symbols in the file
-/// it is just useful for storing symbols. Some other symbols are in
-/// file_segments.
-syms: std.ArrayListUnmanaged(aout.Sym) = .empty,
-
-/// The plan9 a.out format requires segments of
-/// filenames to be deduplicated, so we use this map to
-/// de duplicate it. The value is the value of the path
-/// component
-file_segments: std.StringArrayHashMapUnmanaged(u16) = .empty,
-/// The value of a 'f' symbol increments by 1 every time, so that no 2 'f'
-/// symbols have the same value.
-file_segments_i: u16 = 1,
-
-path_arena: std.heap.ArenaAllocator,
-
-/// maps a file scope to a hash map of decl to codegen output
-/// this is useful for line debuginfo, since it makes sense to sort by file
-/// The debugger looks for the first file (aout.Sym.Type.z) preceeding the text symbol
-/// of the function to know what file it came from.
-/// If we group the decls by file, it makes it really easy to do this (put the symbol in the correct place)
-fn_nav_table: std.AutoArrayHashMapUnmanaged(
- Zcu.File.Index,
- struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, FnNavOutput) = .empty },
-) = .{},
-/// the code is modified when relocated, so that is why it is mutable
-data_nav_table: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []u8) = .empty,
-/// When `updateExports` is called, we store the export indices here, to be used
-/// during flush.
-nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []Zcu.Export.Index) = .empty,
-
-lazy_syms: LazySymbolTable = .{},
-
-uavs: std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index) = .empty,
-
-relocs: std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Reloc)) = .empty,
-hdr: aout.ExecHdr = undefined,
-
-// relocs: std.
-magic: u32,
-
-entry_val: ?u64 = null,
-
-got_len: usize = 0,
-// A list of all the free got indexes, so when making a new decl
-// don't make a new one, just use one from here.
-got_index_free_list: std.ArrayListUnmanaged(usize) = .empty,
-
-syms_index_free_list: std.ArrayListUnmanaged(usize) = .empty,
-
-atoms: std.ArrayListUnmanaged(Atom) = .empty,
-navs: std.AutoHashMapUnmanaged(InternPool.Nav.Index, NavMetadata) = .empty,
-
-/// Indices of the three "special" symbols into atoms
-etext_edata_end_atom_indices: [3]?Atom.Index = .{ null, null, null },
-
-const Reloc = struct {
- target: Atom.Index,
- offset: u64,
- addend: u32,
- type: enum {
- pcrel,
- nonpcrel,
- // for getting the value of the etext symbol; we ignore target
- special_etext,
- // for getting the value of the edata symbol; we ignore target
- special_edata,
- // for getting the value of the end symbol; we ignore target
- special_end,
- } = .nonpcrel,
-};
-
-const Bases = struct {
- text: u64,
- /// the Global Offset Table starts at the beginning of the data section
- data: u64,
-};
-
-const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata);
-
-const LazySymbolMetadata = struct {
- const State = enum { unused, pending_flush, flushed };
- text_atom: Atom.Index = undefined,
- rodata_atom: Atom.Index = undefined,
- text_state: State = .unused,
- rodata_state: State = .unused,
-
- fn numberOfAtoms(self: LazySymbolMetadata) u32 {
- var n: u32 = 0;
- if (self.text_state != .unused) n += 1;
- if (self.rodata_state != .unused) n += 1;
- return n;
- }
-};
-
-pub const PtrWidth = enum { p32, p64 };
-
-pub const Atom = struct {
- type: aout.Sym.Type,
- /// offset in the text or data sects
- offset: ?u64,
- /// offset into syms
- sym_index: ?usize,
- /// offset into got
- got_index: ?usize,
- /// We include the code here to be use in relocs
- /// In the case of lazy_syms, this atom owns the code.
- /// But, in the case of function and data decls, they own the code and this field
- /// is just a pointer for convience.
- code: CodePtr,
-
- const CodePtr = struct {
- code_ptr: ?[*]u8,
- other: union {
- code_len: usize,
- nav_index: InternPool.Nav.Index,
- },
- fn fromSlice(slice: []u8) CodePtr {
- return .{ .code_ptr = slice.ptr, .other = .{ .code_len = slice.len } };
- }
- fn getCode(self: CodePtr, plan9: *const Plan9) []u8 {
- const zcu = plan9.base.comp.zcu.?;
- const ip = &zcu.intern_pool;
- return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: {
- const nav_index = self.other.nav_index;
- const nav = ip.getNav(nav_index);
- if (ip.isFunctionType(nav.typeOf(ip))) {
- const table = plan9.fn_nav_table.get(zcu.navFileScopeIndex(nav_index)).?.functions;
- const output = table.get(nav_index).?;
- break :blk output.code;
- } else {
- break :blk plan9.data_nav_table.get(nav_index).?;
- }
- };
- }
- fn getOwnedCode(self: CodePtr) ?[]u8 {
- return if (self.code_ptr) |p| p[0..self.other.code_len] else null;
- }
- };
-
- pub const Index = u32;
-
- pub fn getOrCreateOffsetTableEntry(self: *Atom, plan9: *Plan9) usize {
- if (self.got_index == null) self.got_index = plan9.allocateGotIndex();
- return self.got_index.?;
- }
-
- pub fn getOrCreateSymbolTableEntry(self: *Atom, plan9: *Plan9) !usize {
- if (self.sym_index == null) self.sym_index = try plan9.allocateSymbolIndex();
- return self.sym_index.?;
- }
-
- // asserts that self.got_index != null
- pub fn getOffsetTableAddress(self: Atom, plan9: *Plan9) u64 {
- const target = &plan9.base.comp.root_mod.resolved_target.result;
- const ptr_bytes = @divExact(target.ptrBitWidth(), 8);
- const got_addr = plan9.bases.data;
- const got_index = self.got_index.?;
- return got_addr + got_index * ptr_bytes;
- }
-};
-
-/// the plan9 debuginfo output is a bytecode with 4 opcodes
-/// assume all numbers/variables are bytes
-/// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset
-/// x when x < 65 -> add x to line offset
-/// x when x < 129 -> subtract 64 from x and subtract it from the line offset
-/// x -> subtract 129 from x, multiply it by the quanta of the instruction size
-/// (1 on x86_64), and add it to the pc
-/// after every opcode, add the quanta of the instruction size to the pc
-pub const DebugInfoOutput = struct {
- /// the actual opcodes
- dbg_line: std.ArrayList(u8),
- /// what line the debuginfo starts on
- /// this helps because the linker might have to insert some opcodes to make sure that the line count starts at the right amount for the next decl
- start_line: ?u32,
- /// what the line count ends on after codegen
- /// this helps because the linker might have to insert some opcodes to make sure that the line count starts at the right amount for the next decl
- end_line: u32,
- /// the last pc change op
- /// This is very useful for adding quanta
- /// to it if its not actually the last one.
- pcop_change_index: ?u32,
- /// cached pc quanta
- pc_quanta: u8,
-};
-
-const NavMetadata = struct {
- index: Atom.Index,
- exports: std.ArrayListUnmanaged(usize) = .empty,
-
- fn getExport(m: NavMetadata, p9: *const Plan9, name: []const u8) ?usize {
- for (m.exports.items) |exp| {
- const sym = p9.syms.items[exp];
- if (mem.eql(u8, name, sym.name)) return exp;
- }
- return null;
- }
-};
-
-const FnNavOutput = struct {
- /// this code is modified when relocated so it is mutable
- code: []u8,
- /// this might have to be modified in the linker, so thats why its mutable
- lineinfo: []u8,
- start_line: u32,
- end_line: u32,
-};
-
-fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 {
- return addr + switch (t) {
- .T, .t, .l, .L => self.bases.text,
- .D, .d, .B, .b => self.bases.data,
- else => unreachable,
- };
-}
-
-fn getSymAddr(self: Plan9, s: aout.Sym) u64 {
- return self.getAddr(s.value, s.type);
-}
-
-pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
- return switch (arch) {
- .x86_64 => .{
- // header size => 40 => 0x28
- .text = 0x200028,
- .data = 0x400000,
- },
- .x86 => .{
- // header size => 32 => 0x20
- .text = 0x200020,
- .data = 0x400000,
- },
- .aarch64 => .{
- // header size => 40 => 0x28
- .text = 0x10028,
- .data = 0x20000,
- },
- else => std.debug.panic("find default base address for {}", .{arch}),
- };
-}
-
-pub fn createEmpty(
- arena: Allocator,
- comp: *Compilation,
- emit: Path,
- options: link.File.OpenOptions,
-) !*Plan9 {
- const target = &comp.root_mod.resolved_target.result;
- const gpa = comp.gpa;
- const optimize_mode = comp.root_mod.optimize_mode;
- const output_mode = comp.config.output_mode;
-
- const sixtyfour_bit: bool = switch (target.ptrBitWidth()) {
- 0...32 => false,
- 33...64 => true,
- else => return error.UnsupportedP9Architecture,
- };
-
- const self = try arena.create(Plan9);
- self.* = .{
- .path_arena = std.heap.ArenaAllocator.init(gpa),
- .base = .{
- .tag = .plan9,
- .comp = comp,
- .emit = emit,
- .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
- .print_gc_sections = options.print_gc_sections,
- .stack_size = options.stack_size orelse 16777216,
- .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
- .file = null,
- .build_id = options.build_id,
- },
- .sixtyfour_bit = sixtyfour_bit,
- .bases = undefined,
- .magic = try aout.magicFromArch(target.cpu.arch),
- };
- // a / will always be in a file path
- try self.file_segments.put(gpa, "/", 1);
- return self;
-}
-
-fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void {
- const comp = self.base.comp;
- const gpa = comp.gpa;
- const zcu = comp.zcu.?;
- const file_scope = zcu.navFileScopeIndex(nav_index);
- const fn_map_res = try self.fn_nav_table.getOrPut(gpa, file_scope);
- if (fn_map_res.found_existing) {
- if (try fn_map_res.value_ptr.functions.fetchPut(gpa, nav_index, out)) |old_entry| {
- gpa.free(old_entry.value.code);
- gpa.free(old_entry.value.lineinfo);
- }
- } else {
- const file = zcu.fileByIndex(file_scope);
- const arena = self.path_arena.allocator();
- // each file gets a symbol
- fn_map_res.value_ptr.* = .{
- .sym_index = blk: {
- try self.syms.append(gpa, undefined);
- try self.syms.append(gpa, undefined);
- break :blk @as(u32, @intCast(self.syms.items.len - 1));
- },
- };
- try fn_map_res.value_ptr.functions.put(gpa, nav_index, out);
-
- var a = std.ArrayList(u8).init(arena);
- errdefer a.deinit();
- // every 'z' starts with 0
- try a.append(0);
- // path component value of '/'
- try a.writer().writeInt(u16, 1, .big);
-
- // getting the full file path
- {
- const full_path = try file.path.toAbsolute(comp.dirs, gpa);
- defer gpa.free(full_path);
- try self.addPathComponents(full_path, &a);
- }
-
- // null terminate
- try a.append(0);
- const final = try a.toOwnedSlice();
- self.syms.items[fn_map_res.value_ptr.sym_index - 1] = .{
- .type = .z,
- .value = 1,
- .name = final,
- };
- self.syms.items[fn_map_res.value_ptr.sym_index] = .{
- .type = .z,
- // just put a giant number, no source file will have this many newlines
- .value = std.math.maxInt(u31),
- .name = &.{ 0, 0 },
- };
- }
-}
-
-fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !void {
- const gpa = self.base.comp.gpa;
- const sep = std.fs.path.sep;
- var it = std.mem.tokenizeScalar(u8, path, sep);
- while (it.next()) |component| {
- if (self.file_segments.get(component)) |num| {
- try a.writer().writeInt(u16, num, .big);
- } else {
- self.file_segments_i += 1;
- try self.file_segments.put(gpa, component, self.file_segments_i);
- try a.writer().writeInt(u16, self.file_segments_i, .big);
- }
- }
-}
-
-pub fn updateFunc(
- self: *Plan9,
- pt: Zcu.PerThread,
- func_index: InternPool.Index,
- mir: *const codegen.AnyMir,
-) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .plan9) {
- @panic("Attempted to compile for object format that was disabled by build configuration");
- }
-
- const zcu = pt.zcu;
- const gpa = zcu.gpa;
- const target = &self.base.comp.root_mod.resolved_target.result;
- const func = zcu.funcInfo(func_index);
-
- const atom_idx = try self.seeNav(pt, func.owner_nav);
-
- var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
- defer code_buffer.deinit(gpa);
- var dbg_info_output: DebugInfoOutput = .{
- .dbg_line = std.ArrayList(u8).init(gpa),
- .start_line = null,
- .end_line = undefined,
- .pcop_change_index = null,
- // we have already checked the target in the linker to make sure it is compatable
- .pc_quanta = aout.getPCQuant(target.cpu.arch) catch unreachable,
- };
- defer dbg_info_output.dbg_line.deinit();
-
- try codegen.emitFunction(
- &self.base,
- pt,
- zcu.navSrcLoc(func.owner_nav),
- func_index,
- mir,
- &code_buffer,
- .{ .plan9 = &dbg_info_output },
- );
- const code = try code_buffer.toOwnedSlice(gpa);
- self.getAtomPtr(atom_idx).code = .{
- .code_ptr = null,
- .other = .{ .nav_index = func.owner_nav },
- };
- const out: FnNavOutput = .{
- .code = code,
- .lineinfo = try dbg_info_output.dbg_line.toOwnedSlice(),
- .start_line = dbg_info_output.start_line.?,
- .end_line = dbg_info_output.end_line,
- };
- try self.putFn(func.owner_nav, out);
- return self.updateFinish(pt, func.owner_nav);
-}
-
-pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.File.UpdateNavError!void {
- const zcu = pt.zcu;
- const gpa = zcu.gpa;
- const ip = &zcu.intern_pool;
- const nav = ip.getNav(nav_index);
- const nav_val = zcu.navValue(nav_index);
- const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
- .func => return,
- .variable => |variable| Value.fromInterned(variable.init),
- .@"extern" => {
- log.debug("found extern decl: {f}", .{nav.name.fmt(ip)});
- return;
- },
- else => nav_val,
- };
-
- if (nav_init.typeOf(zcu).hasRuntimeBits(zcu)) {
- const atom_idx = try self.seeNav(pt, nav_index);
-
- var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
- defer code_buffer.deinit(gpa);
- // TODO we need the symbol index for symbol in the table of locals for the containing atom
- try codegen.generateSymbol(
- &self.base,
- pt,
- zcu.navSrcLoc(nav_index),
- nav_init,
- &code_buffer,
- .{ .atom_index = @intCast(atom_idx) },
- );
- const code = code_buffer.items;
- try self.data_nav_table.ensureUnusedCapacity(gpa, 1);
- const duped_code = try gpa.dupe(u8, code);
- self.getAtomPtr(self.navs.get(nav_index).?.index).code = .{ .code_ptr = null, .other = .{ .nav_index = nav_index } };
- if (self.data_nav_table.fetchPutAssumeCapacity(nav_index, duped_code)) |old_entry| {
- gpa.free(old_entry.value);
- }
- try self.updateFinish(pt, nav_index);
- }
-}
-
-/// called at the end of update{Decl,Func}
-fn updateFinish(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
- const zcu = pt.zcu;
- const gpa = zcu.gpa;
- const ip = &zcu.intern_pool;
- const nav = ip.getNav(nav_index);
- const is_fn = ip.isFunctionType(nav.typeOf(ip));
- const sym_t: aout.Sym.Type = if (is_fn) .t else .d;
-
- const atom = self.getAtomPtr(self.navs.get(nav_index).?.index);
- // write the internal linker metadata
- atom.type = sym_t;
- // write the symbol
- // we already have the got index
- const sym: aout.Sym = .{
- .value = undefined, // the value of stuff gets filled in in flush
- .type = atom.type,
- .name = try gpa.dupe(u8, nav.name.toSlice(ip)),
- };
-
- if (atom.sym_index) |s| {
- self.syms.items[s] = sym;
- } else {
- const s = try self.allocateSymbolIndex();
- atom.sym_index = s;
- self.syms.items[s] = sym;
- }
-}
-
-fn allocateSymbolIndex(self: *Plan9) !usize {
- const gpa = self.base.comp.gpa;
- if (self.syms_index_free_list.pop()) |i| {
- return i;
- } else {
- _ = try self.syms.addOne(gpa);
- return self.syms.items.len - 1;
- }
-}
-
-fn allocateGotIndex(self: *Plan9) usize {
- if (self.got_index_free_list.pop()) |i| {
- return i;
- } else {
- self.got_len += 1;
- return self.got_len - 1;
- }
-}
-
-pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
- if (delta_line > 0 and delta_line < 65) {
- const toappend = @as(u8, @intCast(delta_line));
- try l.append(toappend);
- } else if (delta_line < 0 and delta_line > -65) {
- const toadd: u8 = @as(u8, @intCast(-delta_line + 64));
- try l.append(toadd);
- } else if (delta_line != 0) {
- try l.append(0);
- try l.writer().writeInt(i32, delta_line, .big);
- }
-}
-
-fn externCount(self: *Plan9) usize {
- var extern_atom_count: usize = 0;
- for (self.etext_edata_end_atom_indices) |idx| {
- if (idx != null) extern_atom_count += 1;
- }
- return extern_atom_count;
-}
-// counts decls, and lazy syms
-fn atomCount(self: *Plan9) usize {
- var fn_nav_count: usize = 0;
- var itf_files = self.fn_nav_table.iterator();
- while (itf_files.next()) |ent| {
- // get the submap
- var submap = ent.value_ptr.functions;
- fn_nav_count += submap.count();
- }
- const data_nav_count = self.data_nav_table.count();
- var lazy_atom_count: usize = 0;
- var it_lazy = self.lazy_syms.iterator();
- while (it_lazy.next()) |kv| {
- lazy_atom_count += kv.value_ptr.numberOfAtoms();
- }
- const uav_atom_count = self.uavs.count();
- const extern_atom_count = self.externCount();
- return data_nav_count + fn_nav_count + lazy_atom_count + extern_atom_count + uav_atom_count;
-}
-
-pub fn flush(
- self: *Plan9,
- arena: Allocator,
- /// TODO: stop using this
- tid: Zcu.PerThread.Id,
- prog_node: std.Progress.Node,
-) link.File.FlushError!void {
- if (build_options.skip_non_native and builtin.object_format != .plan9) {
- @panic("Attempted to compile for object format that was disabled by build configuration");
- }
-
- const tracy = trace(@src());
- defer tracy.end();
-
- _ = arena; // Has the same lifetime as the call to Compilation.update.
-
- const comp = self.base.comp;
- const diags = &comp.link_diags;
- const gpa = comp.gpa;
- const target = &comp.root_mod.resolved_target.result;
-
- switch (comp.config.output_mode) {
- .Exe => {},
- .Obj => return diags.fail("writing plan9 object files unimplemented", .{}),
- .Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),
- }
-
- const sub_prog_node = prog_node.start("Flush Module", 0);
- defer sub_prog_node.end();
-
- log.debug("flush", .{});
-
- defer assert(self.hdr.entry != 0x0);
-
- const pt: Zcu.PerThread = .activate(
- self.base.comp.zcu orelse return diags.fail("linking without zig source unimplemented", .{}),
- tid,
- );
- defer pt.deactivate();
-
- // finish up the lazy syms
- if (self.lazy_syms.getPtr(.none)) |metadata| {
- // Most lazy symbols can be updated on first use, but
- // anyerror needs to wait for everything to be flushed.
- if (metadata.text_state != .unused) try self.updateLazySymbolAtom(
- pt,
- .{ .kind = .code, .ty = .anyerror_type },
- metadata.text_atom,
- );
- if (metadata.rodata_state != .unused) try self.updateLazySymbolAtom(
- pt,
- .{ .kind = .const_data, .ty = .anyerror_type },
- metadata.rodata_atom,
- );
- }
- for (self.lazy_syms.values()) |*metadata| {
- if (metadata.text_state != .unused) metadata.text_state = .flushed;
- if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed;
- }
- // make sure the got table is good
- const atom_count = self.atomCount();
- assert(self.got_len == atom_count + self.got_index_free_list.items.len);
- const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;
- var got_table = try gpa.alloc(u8, got_size);
- defer gpa.free(got_table);
-
- // + 4 for header, got, symbols, linecountinfo
- var iovecs = try gpa.alloc(std.posix.iovec_const, self.atomCount() + 4 - self.externCount());
- defer gpa.free(iovecs);
-
- const file = self.base.file.?;
-
- var hdr_buf: [40]u8 = undefined;
- // account for the fat header
- const hdr_size: usize = if (self.sixtyfour_bit) 40 else 32;
- const hdr_slice: []u8 = hdr_buf[0..hdr_size];
- var foff = hdr_size;
- iovecs[0] = .{ .base = hdr_slice.ptr, .len = hdr_slice.len };
- var iovecs_i: usize = 1;
- var text_i: u64 = 0;
-
- var linecountinfo = std.ArrayList(u8).init(gpa);
- defer linecountinfo.deinit();
- // text
- {
- var linecount: i64 = -1;
- var it_file = self.fn_nav_table.iterator();
- while (it_file.next()) |fentry| {
- var it = fentry.value_ptr.functions.iterator();
- while (it.next()) |entry| {
- const nav_index = entry.key_ptr.*;
- const nav = pt.zcu.intern_pool.getNav(nav_index);
- const atom = self.getAtomPtr(self.navs.get(nav_index).?.index);
- const out = entry.value_ptr.*;
- {
- // connect the previous decl to the next
- const delta_line = @as(i32, @intCast(out.start_line)) - @as(i32, @intCast(linecount));
-
- try changeLine(&linecountinfo, delta_line);
- // TODO change the pc too (maybe?)
-
- // write out the actual info that was generated in codegen now
- try linecountinfo.appendSlice(out.lineinfo);
- linecount = out.end_line;
- }
- foff += out.code.len;
- iovecs[iovecs_i] = .{ .base = out.code.ptr, .len = out.code.len };
- iovecs_i += 1;
- const off = self.getAddr(text_i, .t);
- text_i += out.code.len;
- atom.offset = off;
- log.debug("write text nav 0x{x} ({f}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ nav_index, nav.name.fmt(&pt.zcu.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off });
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(off), target.cpu.arch.endian());
- } else {
- mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());
- }
- self.syms.items[atom.sym_index.?].value = off;
- if (self.nav_exports.get(nav_index)) |export_indices| {
- try self.addNavExports(pt.zcu, nav_index, export_indices);
- }
- }
- }
- if (linecountinfo.items.len & 1 == 1) {
- // just a nop to make it even, the plan9 linker does this
- try linecountinfo.append(129);
- }
- }
- // the text lazy symbols
- {
- var it = self.lazy_syms.iterator();
- while (it.next()) |kv| {
- const meta = kv.value_ptr;
- const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;
- const code = text_atom.code.getOwnedCode().?;
- foff += code.len;
- iovecs[iovecs_i] = .{ .base = code.ptr, .len = code.len };
- iovecs_i += 1;
- const off = self.getAddr(text_i, .t);
- text_i += code.len;
- text_atom.offset = off;
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[text_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian());
- } else {
- mem.writeInt(u64, got_table[text_atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());
- }
- self.syms.items[text_atom.sym_index.?].value = off;
- }
- }
- // fix the sym for etext
- if (self.etext_edata_end_atom_indices[0]) |etext_atom_idx| {
- const etext_atom = self.getAtom(etext_atom_idx);
- const val = self.getAddr(text_i, .t);
- self.syms.items[etext_atom.sym_index.?].value = val;
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[etext_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), target.cpu.arch.endian());
- } else {
- mem.writeInt(u64, got_table[etext_atom.got_index.? * 8 ..][0..8], val, target.cpu.arch.endian());
- }
- }
- // global offset table is in data
- iovecs[iovecs_i] = .{ .base = got_table.ptr, .len = got_table.len };
- iovecs_i += 1;
- // data
- var data_i: u64 = got_size;
- {
- var it = self.data_nav_table.iterator();
- while (it.next()) |entry| {
- const nav_index = entry.key_ptr.*;
- const atom = self.getAtomPtr(self.navs.get(nav_index).?.index);
- const code = entry.value_ptr.*;
-
- foff += code.len;
- iovecs[iovecs_i] = .{ .base = code.ptr, .len = code.len };
- iovecs_i += 1;
- const off = self.getAddr(data_i, .d);
- data_i += code.len;
- atom.offset = off;
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian());
- } else {
- mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());
- }
- self.syms.items[atom.sym_index.?].value = off;
- if (self.nav_exports.get(nav_index)) |export_indices| {
- try self.addNavExports(pt.zcu, nav_index, export_indices);
- }
- }
- {
- var it_uav = self.uavs.iterator();
- while (it_uav.next()) |kv| {
- const atom = self.getAtomPtr(kv.value_ptr.*);
- const code = atom.code.getOwnedCode().?;
- log.debug("write anon decl: {s}", .{self.syms.items[atom.sym_index.?].name});
- foff += code.len;
- iovecs[iovecs_i] = .{ .base = code.ptr, .len = code.len };
- iovecs_i += 1;
- const off = self.getAddr(data_i, .d);
- data_i += code.len;
- atom.offset = off;
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian());
- } else {
- mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());
- }
- self.syms.items[atom.sym_index.?].value = off;
- }
- }
- // the lazy data symbols
- var it_lazy = self.lazy_syms.iterator();
- while (it_lazy.next()) |kv| {
- const meta = kv.value_ptr;
- const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;
- const code = data_atom.code.getOwnedCode().?; // lazy symbols must own their code
- foff += code.len;
- iovecs[iovecs_i] = .{ .base = code.ptr, .len = code.len };
- iovecs_i += 1;
- const off = self.getAddr(data_i, .d);
- data_i += code.len;
- data_atom.offset = off;
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[data_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian());
- } else {
- mem.writeInt(u64, got_table[data_atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());
- }
- self.syms.items[data_atom.sym_index.?].value = off;
- }
- // edata symbol
- if (self.etext_edata_end_atom_indices[1]) |edata_atom_idx| {
- const edata_atom = self.getAtom(edata_atom_idx);
- const val = self.getAddr(data_i, .b);
- self.syms.items[edata_atom.sym_index.?].value = val;
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[edata_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), target.cpu.arch.endian());
- } else {
- mem.writeInt(u64, got_table[edata_atom.got_index.? * 8 ..][0..8], val, target.cpu.arch.endian());
- }
- }
- // end symbol (same as edata because native backends don't do .bss yet)
- if (self.etext_edata_end_atom_indices[2]) |end_atom_idx| {
- const end_atom = self.getAtom(end_atom_idx);
- const val = self.getAddr(data_i, .b);
- self.syms.items[end_atom.sym_index.?].value = val;
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, got_table[end_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), target.cpu.arch.endian());
- } else {
- log.debug("write end (got_table[0x{x}] = 0x{x})", .{ end_atom.got_index.? * 8, val });
- mem.writeInt(u64, got_table[end_atom.got_index.? * 8 ..][0..8], val, target.cpu.arch.endian());
- }
- }
- }
- var sym_buf = std.ArrayList(u8).init(gpa);
- try self.writeSyms(&sym_buf);
- const syms = try sym_buf.toOwnedSlice();
- defer gpa.free(syms);
- assert(2 + self.atomCount() - self.externCount() == iovecs_i); // we didn't write all the decls
- iovecs[iovecs_i] = .{ .base = syms.ptr, .len = syms.len };
- iovecs_i += 1;
- iovecs[iovecs_i] = .{ .base = linecountinfo.items.ptr, .len = linecountinfo.items.len };
- iovecs_i += 1;
- // generate the header
- self.hdr = .{
- .magic = self.magic,
- .text = @as(u32, @intCast(text_i)),
- .data = @as(u32, @intCast(data_i)),
- .syms = @as(u32, @intCast(syms.len)),
- .bss = 0,
- .spsz = 0,
- .pcsz = @as(u32, @intCast(linecountinfo.items.len)),
- .entry = @as(u32, @intCast(self.entry_val.?)),
- };
- @memcpy(hdr_slice, self.hdr.toU8s()[0..hdr_size]);
- // write the fat header for 64 bit entry points
- if (self.sixtyfour_bit) {
- mem.writeInt(u64, hdr_buf[32..40], self.entry_val.?, .big);
- }
- // perform the relocs
- {
- var it = self.relocs.iterator();
- while (it.next()) |kv| {
- const source_atom_index = kv.key_ptr.*;
- const source_atom = self.getAtom(source_atom_index);
- const source_atom_symbol = self.syms.items[source_atom.sym_index.?];
- const code = source_atom.code.getCode(self);
- const endian = target.cpu.arch.endian();
- for (kv.value_ptr.items) |reloc| {
- const offset = reloc.offset;
- const addend = reloc.addend;
- if (reloc.type == .pcrel or reloc.type == .nonpcrel) {
- const target_atom_index = reloc.target;
- const target_atom = self.getAtomPtr(target_atom_index);
- const target_symbol = self.syms.items[target_atom.sym_index.?];
- const target_offset = target_atom.offset.?;
-
- switch (reloc.type) {
- .pcrel => {
- const disp = @as(i32, @intCast(target_offset)) - @as(i32, @intCast(source_atom.offset.?)) - 4 - @as(i32, @intCast(offset));
- mem.writeInt(i32, code[@as(usize, @intCast(offset))..][0..4], @as(i32, @intCast(disp)), endian);
- },
- .nonpcrel => {
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, code[@intCast(offset)..][0..4], @as(u32, @intCast(target_offset + addend)), endian);
- } else {
- mem.writeInt(u64, code[@intCast(offset)..][0..8], target_offset + addend, endian);
- }
- },
- else => unreachable,
- }
- log.debug("relocating the address of '{s}' + {d} into '{s}' + {d} (({s}[{d}] = 0x{x} + 0x{x})", .{ target_symbol.name, addend, source_atom_symbol.name, offset, source_atom_symbol.name, offset, target_offset, addend });
- } else {
- const addr = switch (reloc.type) {
- .special_etext => self.syms.items[self.getAtom(self.etext_edata_end_atom_indices[0].?).sym_index.?].value,
- .special_edata => self.syms.items[self.getAtom(self.etext_edata_end_atom_indices[1].?).sym_index.?].value,
- .special_end => self.syms.items[self.getAtom(self.etext_edata_end_atom_indices[2].?).sym_index.?].value,
- else => unreachable,
- };
- if (!self.sixtyfour_bit) {
- mem.writeInt(u32, code[@intCast(offset)..][0..4], @as(u32, @intCast(addr + addend)), endian);
- } else {
- mem.writeInt(u64, code[@intCast(offset)..][0..8], addr + addend, endian);
- }
- log.debug("relocating the address of '{s}' + {d} into '{s}' + {d} (({s}[{d}] = 0x{x} + 0x{x})", .{ @tagName(reloc.type), addend, source_atom_symbol.name, offset, source_atom_symbol.name, offset, addr, addend });
- }
- }
- }
- }
- file.pwritevAll(iovecs, 0) catch |err| return diags.fail("failed to write file: {s}", .{@errorName(err)});
-}
-fn addNavExports(
- self: *Plan9,
- zcu: *Zcu,
- nav_index: InternPool.Nav.Index,
- export_indices: []const Zcu.Export.Index,
-) !void {
- const gpa = self.base.comp.gpa;
- const metadata = self.navs.getPtr(nav_index).?;
- const atom = self.getAtom(metadata.index);
-
- for (export_indices) |export_idx| {
- const exp = export_idx.ptr(zcu);
- const exp_name = exp.opts.name.toSlice(&zcu.intern_pool);
- // plan9 does not support custom sections
- if (exp.opts.section.unwrap()) |section_name| {
- if (!section_name.eqlSlice(".text", &zcu.intern_pool) and
- !section_name.eqlSlice(".data", &zcu.intern_pool))
- {
- try zcu.failed_exports.put(zcu.gpa, export_idx, try Zcu.ErrorMsg.create(
- gpa,
- zcu.navSrcLoc(nav_index),
- "plan9 does not support extra sections",
- .{},
- ));
- break;
- }
- }
- const sym: aout.Sym = .{
- .value = atom.offset.?,
- .type = atom.type.toGlobal(),
- .name = try gpa.dupe(u8, exp_name),
- };
-
- if (metadata.getExport(self, exp_name)) |i| {
- self.syms.items[i] = sym;
- } else {
- try self.syms.append(gpa, sym);
- try metadata.exports.append(gpa, self.syms.items.len - 1);
- }
- }
-}
-
-fn createAtom(self: *Plan9) !Atom.Index {
- const gpa = self.base.comp.gpa;
- const index = @as(Atom.Index, @intCast(self.atoms.items.len));
- const atom = try self.atoms.addOne(gpa);
- atom.* = .{
- .type = .t,
- .offset = null,
- .sym_index = null,
- .got_index = null,
- .code = undefined,
- };
- return index;
-}
-
-pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !Atom.Index {
- const zcu = pt.zcu;
- const ip = &zcu.intern_pool;
- const gpa = zcu.gpa;
- const gop = try self.navs.getOrPut(gpa, nav_index);
- if (!gop.found_existing) {
- const index = try self.createAtom();
- self.getAtomPtr(index).got_index = self.allocateGotIndex();
- gop.value_ptr.* = .{
- .index = index,
- .exports = .{},
- };
- }
- const atom_idx = gop.value_ptr.index;
- // handle externs here because they might not get updateDecl called on them
- const nav = ip.getNav(nav_index);
- if (nav.getExtern(ip) != null) {
- // this is a "phantom atom" - it is never actually written to disk, just convenient for us to store stuff about externs
- if (nav.name.eqlSlice("etext", ip)) {
- self.etext_edata_end_atom_indices[0] = atom_idx;
- } else if (nav.name.eqlSlice("edata", ip)) {
- self.etext_edata_end_atom_indices[1] = atom_idx;
- } else if (nav.name.eqlSlice("end", ip)) {
- self.etext_edata_end_atom_indices[2] = atom_idx;
- }
- try self.updateFinish(pt, nav_index);
- log.debug("seeNav(extern) for {f} (got_addr=0x{x})", .{
- nav.name.fmt(ip),
- self.getAtom(atom_idx).getOffsetTableAddress(self),
- });
- } else log.debug("seeNav for {f}", .{nav.name.fmt(ip)});
- return atom_idx;
-}
-
-pub fn updateExports(
- self: *Plan9,
- pt: Zcu.PerThread,
- exported: Zcu.Exported,
- export_indices: []const Zcu.Export.Index,
-) !void {
- const gpa = self.base.comp.gpa;
- switch (exported) {
- .uav => @panic("TODO: plan9 updateExports handling values"),
- .nav => |nav| {
- _ = try self.seeNav(pt, nav);
- if (self.nav_exports.fetchSwapRemove(nav)) |kv| {
- gpa.free(kv.value);
- }
- try self.nav_exports.ensureUnusedCapacity(gpa, 1);
- const duped_indices = try gpa.dupe(Zcu.Export.Index, export_indices);
- self.nav_exports.putAssumeCapacityNoClobber(nav, duped_indices);
- },
- }
- // all proper work is done in flush
-}
-
-pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, lazy_sym: File.LazySymbol) !Atom.Index {
- const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty);
- errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
-
- if (!gop.found_existing) gop.value_ptr.* = .{};
-
- const atom_ptr, const state_ptr = switch (lazy_sym.kind) {
- .code => .{ &gop.value_ptr.text_atom, &gop.value_ptr.text_state },
- .const_data => .{ &gop.value_ptr.rodata_atom, &gop.value_ptr.rodata_state },
- };
- switch (state_ptr.*) {
- .unused => atom_ptr.* = try self.createAtom(),
- .pending_flush => return atom_ptr.*,
- .flushed => {},
- }
- state_ptr.* = .pending_flush;
- const atom = atom_ptr.*;
- _ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self);
- _ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self);
- // anyerror needs to be deferred until flush
- if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom);
- return atom;
-}
-
-fn updateLazySymbolAtom(
- self: *Plan9,
- pt: Zcu.PerThread,
- sym: File.LazySymbol,
- atom_index: Atom.Index,
-) error{ LinkFailure, OutOfMemory }!void {
- const gpa = pt.zcu.gpa;
- const comp = self.base.comp;
- const diags = &comp.link_diags;
-
- var required_alignment: InternPool.Alignment = .none;
- var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
- defer code_buffer.deinit(gpa);
-
- // create the symbol for the name
- const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
- @tagName(sym.kind),
- Type.fromInterned(sym.ty).fmt(pt),
- });
-
- const symbol: aout.Sym = .{
- .value = undefined,
- .type = if (sym.kind == .code) .t else .d,
- .name = name,
- };
- self.syms.items[self.getAtomPtr(atom_index).sym_index.?] = symbol;
-
- // generate the code
- const src = Type.fromInterned(sym.ty).srcLocOrNull(pt.zcu) orelse Zcu.LazySrcLoc.unneeded;
- codegen.generateLazySymbol(
- &self.base,
- pt,
- src,
- sym,
- &required_alignment,
- &code_buffer,
- .none,
- .{ .atom_index = @intCast(atom_index) },
- ) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.CodegenFail => return error.LinkFailure,
- error.Overflow,
- error.RelocationNotByteAligned,
- => return diags.fail("unable to codegen: {s}", .{@errorName(err)}),
- };
- const code = code_buffer.items;
- // duped_code is freed when the atom is freed
- const duped_code = try gpa.dupe(u8, code);
- errdefer gpa.free(duped_code);
- self.getAtomPtr(atom_index).code = .{
- .code_ptr = duped_code.ptr,
- .other = .{ .code_len = duped_code.len },
- };
-}
-
-pub fn deinit(self: *Plan9) void {
- const gpa = self.base.comp.gpa;
- {
- var it = self.relocs.valueIterator();
- while (it.next()) |relocs| {
- relocs.deinit(gpa);
- }
- self.relocs.deinit(gpa);
- }
- var it_lzc = self.lazy_syms.iterator();
- while (it_lzc.next()) |kv| {
- if (kv.value_ptr.text_state != .unused)
- gpa.free(self.syms.items[self.getAtom(kv.value_ptr.text_atom).sym_index.?].name);
- if (kv.value_ptr.rodata_state != .unused)
- gpa.free(self.syms.items[self.getAtom(kv.value_ptr.rodata_atom).sym_index.?].name);
- }
- self.lazy_syms.deinit(gpa);
- var itf_files = self.fn_nav_table.iterator();
- while (itf_files.next()) |ent| {
- // get the submap
- var submap = ent.value_ptr.functions;
- defer submap.deinit(gpa);
- var itf = submap.iterator();
- while (itf.next()) |entry| {
- gpa.free(entry.value_ptr.code);
- gpa.free(entry.value_ptr.lineinfo);
- }
- }
- self.fn_nav_table.deinit(gpa);
- var itd = self.data_nav_table.iterator();
- while (itd.next()) |entry| {
- gpa.free(entry.value_ptr.*);
- }
- var it_uav = self.uavs.iterator();
- while (it_uav.next()) |entry| {
- const sym_index = self.getAtom(entry.value_ptr.*).sym_index.?;
- gpa.free(self.syms.items[sym_index].name);
- }
- self.data_nav_table.deinit(gpa);
- for (self.nav_exports.values()) |export_indices| {
- gpa.free(export_indices);
- }
- self.nav_exports.deinit(gpa);
- self.syms.deinit(gpa);
- self.got_index_free_list.deinit(gpa);
- self.syms_index_free_list.deinit(gpa);
- self.file_segments.deinit(gpa);
- self.path_arena.deinit();
- for (self.atoms.items) |a| {
- if (a.code.getOwnedCode()) |c| {
- gpa.free(c);
- }
- }
- self.atoms.deinit(gpa);
-
- {
- var it = self.navs.iterator();
- while (it.next()) |entry| {
- entry.value_ptr.exports.deinit(gpa);
- }
- self.navs.deinit(gpa);
- }
-}
-
-pub fn open(
- arena: Allocator,
- comp: *Compilation,
- emit: Path,
- options: link.File.OpenOptions,
-) !*Plan9 {
- const target = &comp.root_mod.resolved_target.result;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- const use_llvm = comp.config.use_llvm;
-
- assert(!use_llvm); // Caught by Compilation.Config.resolve.
- assert(!use_lld); // Caught by Compilation.Config.resolve.
- assert(target.ofmt == .plan9);
-
- const self = try createEmpty(arena, comp, emit, options);
- errdefer self.base.destroy();
-
- const file = try emit.root_dir.handle.createFile(emit.sub_path, .{
- .read = true,
- .mode = link.File.determineMode(comp.config.output_mode, comp.config.link_mode),
- });
- errdefer file.close();
- self.base.file = file;
-
- self.bases = defaultBaseAddrs(target.cpu.arch);
-
- const gpa = comp.gpa;
-
- try self.syms.appendSlice(gpa, &.{
- // we include the global offset table to make it easier for debugging
- .{
- .value = self.getAddr(0, .d), // the global offset table starts at 0
- .type = .d,
- .name = "__GOT",
- },
- });
-
- return self;
-}
-
-pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {
- // log.debug("write sym{{name: {s}, value: {x}}}", .{ sym.name, sym.value });
- if (sym.type == .bad) return; // we don't want to write free'd symbols
- if (!self.sixtyfour_bit) {
- try w.writeInt(u32, @as(u32, @intCast(sym.value)), .big);
- } else {
- try w.writeInt(u64, sym.value, .big);
- }
- try w.writeByte(@intFromEnum(sym.type));
- try w.writeAll(sym.name);
- try w.writeByte(0);
-}
-
-pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
- const zcu = self.base.comp.zcu.?;
- const ip = &zcu.intern_pool;
- const writer = buf.writer();
- // write __GOT
- try self.writeSym(writer, self.syms.items[0]);
- // write the f symbols
- {
- var it = self.file_segments.iterator();
- while (it.next()) |entry| {
- try self.writeSym(writer, .{
- .type = .f,
- .value = entry.value_ptr.*,
- .name = entry.key_ptr.*,
- });
- }
- }
-
- // write the data symbols
- {
- var it = self.data_nav_table.iterator();
- while (it.next()) |entry| {
- const nav_index = entry.key_ptr.*;
- const nav_metadata = self.navs.get(nav_index).?;
- const atom = self.getAtom(nav_metadata.index);
- const sym = self.syms.items[atom.sym_index.?];
- try self.writeSym(writer, sym);
- if (self.nav_exports.get(nav_index)) |export_indices| {
- for (export_indices) |export_idx| {
- const exp = export_idx.ptr(zcu);
- if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {
- try self.writeSym(writer, self.syms.items[exp_i]);
- }
- }
- }
- }
- }
- // the data lazy symbols
- {
- var it = self.lazy_syms.iterator();
- while (it.next()) |kv| {
- const meta = kv.value_ptr;
- const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;
- const sym = self.syms.items[data_atom.sym_index.?];
- try self.writeSym(writer, sym);
- }
- }
- // text symbols are the hardest:
- // the file of a text symbol is the .z symbol before it
- // so we have to write everything in the right order
- {
- var it_file = self.fn_nav_table.iterator();
- while (it_file.next()) |fentry| {
- var symidx_and_submap = fentry.value_ptr;
- // write the z symbols
- try self.writeSym(writer, self.syms.items[symidx_and_submap.sym_index - 1]);
- try self.writeSym(writer, self.syms.items[symidx_and_submap.sym_index]);
-
- // write all the decls come from the file of the z symbol
- var submap_it = symidx_and_submap.functions.iterator();
- while (submap_it.next()) |entry| {
- const nav_index = entry.key_ptr.*;
- const nav_metadata = self.navs.get(nav_index).?;
- const atom = self.getAtom(nav_metadata.index);
- const sym = self.syms.items[atom.sym_index.?];
- try self.writeSym(writer, sym);
- if (self.nav_exports.get(nav_index)) |export_indices| {
- for (export_indices) |export_idx| {
- const exp = export_idx.ptr(zcu);
- if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {
- const s = self.syms.items[exp_i];
- if (mem.eql(u8, s.name, "_start"))
- self.entry_val = s.value;
- try self.writeSym(writer, s);
- }
- }
- }
- }
- }
- // the text lazy symbols
- {
- var it = self.lazy_syms.iterator();
- while (it.next()) |kv| {
- const meta = kv.value_ptr;
- const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;
- const sym = self.syms.items[text_atom.sym_index.?];
- try self.writeSym(writer, sym);
- }
- }
- }
- // special symbols
- for (self.etext_edata_end_atom_indices) |idx| {
- if (idx) |atom_idx| {
- const atom = self.getAtom(atom_idx);
- const sym = self.syms.items[atom.sym_index.?];
- try self.writeSym(writer, sym);
- }
- }
-}
-
-pub fn updateLineNumber(self: *Plan9, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
- _ = self;
- _ = pt;
- _ = ti_id;
-}
-
-pub fn getNavVAddr(
- self: *Plan9,
- pt: Zcu.PerThread,
- nav_index: InternPool.Nav.Index,
- reloc_info: link.File.RelocInfo,
-) !u64 {
- const ip = &pt.zcu.intern_pool;
- const nav = ip.getNav(nav_index);
- log.debug("getDeclVAddr for {f}", .{nav.name.fmt(ip)});
- if (nav.getExtern(ip) != null) {
- if (nav.name.eqlSlice("etext", ip)) {
- try self.addReloc(reloc_info.parent.atom_index, .{
- .target = undefined,
- .offset = reloc_info.offset,
- .addend = reloc_info.addend,
- .type = .special_etext,
- });
- } else if (nav.name.eqlSlice("edata", ip)) {
- try self.addReloc(reloc_info.parent.atom_index, .{
- .target = undefined,
- .offset = reloc_info.offset,
- .addend = reloc_info.addend,
- .type = .special_edata,
- });
- } else if (nav.name.eqlSlice("end", ip)) {
- try self.addReloc(reloc_info.parent.atom_index, .{
- .target = undefined,
- .offset = reloc_info.offset,
- .addend = reloc_info.addend,
- .type = .special_end,
- });
- }
- // TODO handle other extern variables and functions
- return undefined;
- }
- // otherwise, we just add a relocation
- const atom_index = try self.seeNav(pt, nav_index);
- // the parent_atom_index in this case is just the decl_index of the parent
- try self.addReloc(reloc_info.parent.atom_index, .{
- .target = atom_index,
- .offset = reloc_info.offset,
- .addend = reloc_info.addend,
- });
- return undefined;
-}
-
-pub fn lowerUav(
- self: *Plan9,
- pt: Zcu.PerThread,
- uav: InternPool.Index,
- explicit_alignment: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
- _ = explicit_alignment;
- // example:
- // const ty = mod.intern_pool.typeOf(decl_val).toType();
- // const val = decl_val.toValue();
- // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
- // It doesn't have an owner decl because it's just an unnamed constant that might
- // be used by more than one function, however, its address is being used so we need
- // to put it in some location.
- // ...
- const gpa = self.base.comp.gpa;
- const gop = try self.uavs.getOrPut(gpa, uav);
- if (gop.found_existing) return .{ .sym_index = gop.value_ptr.* };
- const val = Value.fromInterned(uav);
- const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(uav)});
-
- const index = try self.createAtom();
- const got_index = self.allocateGotIndex();
- gop.value_ptr.* = index;
- // we need to free name latex
- var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
- defer code_buffer.deinit(gpa);
- try codegen.generateSymbol(&self.base, pt, src_loc, val, &code_buffer, .{ .atom_index = index });
- const atom_ptr = self.getAtomPtr(index);
- atom_ptr.* = .{
- .type = .d,
- .offset = undefined,
- .sym_index = null,
- .got_index = got_index,
- .code = Atom.CodePtr.fromSlice(try code_buffer.toOwnedSlice(gpa)),
- };
- _ = try atom_ptr.getOrCreateSymbolTableEntry(self);
- self.syms.items[atom_ptr.sym_index.?] = .{
- .type = .d,
- .value = undefined,
- .name = name,
- };
- return .{ .sym_index = index };
-}
-
-pub fn getUavVAddr(self: *Plan9, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
- const atom_index = self.uavs.get(uav).?;
- try self.addReloc(reloc_info.parent.atom_index, .{
- .target = atom_index,
- .offset = reloc_info.offset,
- .addend = reloc_info.addend,
- });
- return undefined;
-}
-
-pub fn addReloc(self: *Plan9, parent_index: Atom.Index, reloc: Reloc) !void {
- const gpa = self.base.comp.gpa;
- const gop = try self.relocs.getOrPut(gpa, parent_index);
- if (!gop.found_existing) {
- gop.value_ptr.* = .{};
- }
- try gop.value_ptr.append(gpa, reloc);
-}
-
-pub fn getAtom(self: *const Plan9, index: Atom.Index) Atom {
- return self.atoms.items[index];
-}
-
-fn getAtomPtr(self: *Plan9, index: Atom.Index) *Atom {
- return &self.atoms.items[index];
-}
src/codegen.zig
@@ -997,8 +997,6 @@ pub fn genNavRef(
},
.link_once => unreachable,
}
- } else if (lf.cast(.plan9)) |p9| {
- return .{ .sym_index = try p9.seeNav(pt, nav_index) };
} else {
const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
return .{ .fail = msg };
src/link.zig
@@ -530,6 +530,7 @@ pub const File = struct {
return &lld.base;
}
switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
+ .plan9 => return error.UnsupportedObjectFormat,
inline else => |tag| {
dev.check(tag.devFeature());
const ptr = try tag.Type().open(arena, comp, emit, options);
@@ -552,6 +553,7 @@ pub const File = struct {
return &lld.base;
}
switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
+ .plan9 => return error.UnsupportedObjectFormat,
inline else => |tag| {
dev.check(tag.devFeature());
const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
@@ -571,7 +573,7 @@ pub const File = struct {
const gpa = comp.gpa;
switch (base.tag) {
.lld => assert(base.file == null),
- .coff, .elf, .macho, .plan9, .wasm, .goff, .xcoff => {
+ .coff, .elf, .macho, .wasm, .goff, .xcoff => {
if (base.file != null) return;
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
const emit = base.emit;
@@ -612,6 +614,7 @@ pub const File = struct {
});
},
.c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
+ .plan9 => unreachable,
}
}
@@ -659,7 +662,7 @@ pub const File = struct {
}
}
},
- .coff, .macho, .plan9, .wasm, .goff, .xcoff => if (base.file) |f| {
+ .coff, .macho, .wasm, .goff, .xcoff => if (base.file) |f| {
dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
f.close();
base.file = null;
@@ -675,12 +678,12 @@ pub const File = struct {
}
},
.c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
+ .plan9 => unreachable,
}
}
pub const DebugInfoOutput = union(enum) {
dwarf: *Dwarf.WipNav,
- plan9: *Plan9.DebugInfoOutput,
none,
};
pub const UpdateDebugInfoError = Dwarf.UpdateError;
@@ -699,7 +702,6 @@ pub const File = struct {
log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });
switch (base.tag) {
.lld => unreachable,
- .plan9 => unreachable,
.spirv => unreachable,
.c => unreachable,
inline else => |tag| {
@@ -717,6 +719,7 @@ pub const File = struct {
assert(nav.status == .fully_resolved);
switch (base.tag) {
.lld => unreachable,
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateNav(pt, nav_index);
@@ -759,6 +762,7 @@ pub const File = struct {
switch (base.tag) {
.lld => unreachable,
.spirv => unreachable, // see corresponding special case in `Zcu.PerThread.runCodegenInner`
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, mir);
@@ -788,6 +792,7 @@ pub const File = struct {
.lld => unreachable,
.spirv => {},
.goff, .xcoff => {},
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id);
@@ -812,6 +817,7 @@ pub const File = struct {
base.releaseLock();
if (base.file) |f| f.close();
switch (base.tag) {
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
@as(*tag.Type(), @fieldParentPtr("base", base)).deinit();
@@ -851,6 +857,7 @@ pub const File = struct {
}
assert(base.post_prelink);
switch (base.tag) {
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).flush(arena, tid, prog_node);
@@ -877,6 +884,7 @@ pub const File = struct {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(pt, exported, export_indices);
@@ -911,6 +919,7 @@ pub const File = struct {
.spirv => unreachable,
.wasm => unreachable,
.goff, .xcoff => unreachable,
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(pt, nav_index, reloc_info);
@@ -933,6 +942,7 @@ pub const File = struct {
.spirv => unreachable,
.wasm => unreachable,
.goff, .xcoff => unreachable,
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align, src_loc);
@@ -949,6 +959,7 @@ pub const File = struct {
.spirv => unreachable,
.wasm => unreachable,
.goff, .xcoff => unreachable,
+ .plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).getUavVAddr(decl_val, reloc_info);
@@ -965,8 +976,8 @@ pub const File = struct {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
+ .plan9 => unreachable,
- .plan9,
.spirv,
.goff,
.xcoff,
@@ -1116,10 +1127,10 @@ pub const File = struct {
.c => C,
.wasm => Wasm,
.spirv => SpirV,
- .plan9 => Plan9,
.goff => Goff,
.xcoff => Xcoff,
.lld => Lld,
+ .plan9 => comptime unreachable,
};
}
@@ -1211,7 +1222,6 @@ pub const File = struct {
pub const Lld = @import("link/Lld.zig");
pub const C = @import("link/C.zig");
pub const Coff = @import("link/Coff.zig");
- pub const Plan9 = @import("link/Plan9.zig");
pub const Elf = @import("link/Elf.zig");
pub const MachO = @import("link/MachO.zig");
pub const SpirV = @import("link/SpirV.zig");
CMakeLists.txt
@@ -612,8 +612,6 @@ set(ZIG_STAGE2_SOURCES
src/link/MachO/synthetic.zig
src/link/MachO/Thunk.zig
src/link/MachO/uuid.zig
- src/link/Plan9.zig
- src/link/Plan9/aout.zig
src/link/Queue.zig
src/link/StringTable.zig
src/link/Wasm.zig