linker: delete plan9 support

This experimental target was never fully completed. The operating system
is not that interesting or popular anyway, and the maintainer is no
longer around.

Not worth the maintenance burden. This code can be resurrected later if
it is worth it. In such case it will be subject to greater scrutiny.
This commit is contained in:
Andrew Kelley 2025-08-10 23:55:40 -07:00
parent d1917b5c3a
commit 0b3c3c02e3
11 changed files with 19 additions and 1626 deletions

View File

@ -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

View File

@ -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 => {},
}
}

View File

@ -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 => {},
}
}

View File

@ -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 => {},
}
}

View File

@ -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,

View File

@ -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 };

View File

@ -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");

View File

@ -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,
},
}

View File

@ -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,
},
}

File diff suppressed because it is too large Load Diff

View File

@ -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,
};
}