| author | |
| committer | |
| log | 476faef97ab0f292159bb3eef42078f9b1e43dde |
| tree | fdbe0ebed92520fa7920409cc65c9b51ca9dd288 |
| parent | 4eb778fc3eeec62c5c45ccc0a21631ff757d8a23 |
* rename files to adhere to conventions
* remove unnecessary function / optionality
* fix merge conflict
* better panic message
* remove unnecessary TODO comment
* proper namespacing of declarations
* clean up documentation comments
* no copyright header needed for a brand new zig file that is not
copied from anywhere7 files changed, 148 insertions(+), 167 deletions(-)
CMakeLists.txt+1-1| ... | ... | @@ -574,7 +574,7 @@ set(ZIG_STAGE2_SOURCES |
| 574 | 574 | "${CMAKE_SOURCE_DIR}/src/link/Coff.zig" |
| 575 | 575 | "${CMAKE_SOURCE_DIR}/src/link/Elf.zig" |
| 576 | 576 | "${CMAKE_SOURCE_DIR}/src/link/Plan9.zig" |
| 577 | "${CMAKE_SOURCE_DIR}/src/link/plan9/a.out.zig" | |
| 577 | "${CMAKE_SOURCE_DIR}/src/link/Plan9/aout.zig" | |
| 578 | 578 | "${CMAKE_SOURCE_DIR}/src/link/MachO.zig" |
| 579 | 579 | "${CMAKE_SOURCE_DIR}/src/link/MachO/Archive.zig" |
| 580 | 580 | "${CMAKE_SOURCE_DIR}/src/link/MachO/CodeSignature.zig" |
lib/std/zig.zig+24-24| ... | ... | @@ -181,32 +181,32 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro |
| 181 | 181 | .spirv => return std.fmt.allocPrint(allocator, "{s}.spv", .{root_name}), |
| 182 | 182 | .hex => return std.fmt.allocPrint(allocator, "{s}.ihex", .{root_name}), |
| 183 | 183 | .raw => return std.fmt.allocPrint(allocator, "{s}.bin", .{root_name}), |
| 184 | .plan9 => return std.fmt.allocPrint(allocator, "{s}.{c}", .{ root_name, archToPlan9Char(target.cpu.arch) }), | |
| 184 | .plan9 => { | |
| 185 | // copied from 2c(1) | |
| 186 | // 0c spim little-endian MIPS 3000 family | |
| 187 | // 1c 68000 Motorola MC68000 | |
| 188 | // 2c 68020 Motorola MC68020 | |
| 189 | // 5c arm little-endian ARM | |
| 190 | // 6c amd64 AMD64 and compatibles (e.g., Intel EM64T) | |
| 191 | // 7c arm64 ARM64 (ARMv8) | |
| 192 | // 8c 386 Intel i386, i486, Pentium, etc. | |
| 193 | // kc sparc Sun SPARC | |
| 194 | // qc power Power PC | |
| 195 | // vc mips big-endian MIPS 3000 family | |
| 196 | const char: u8 = switch (target.cpu.arch) { | |
| 197 | .arm => '5', | |
| 198 | .x86_64 => '6', | |
| 199 | .aarch64 => '7', | |
| 200 | .i386 => '8', | |
| 201 | .sparc => 'k', | |
| 202 | .powerpc, .powerpcle => 'q', | |
| 203 | .mips, .mipsel => 'v', | |
| 204 | else => 'X', // this arch does not have a char or maybe was not ported to plan9 so we just use X | |
| 205 | }; | |
| 206 | return std.fmt.allocPrint(allocator, "{s}.{c}", .{ root_name, char }); | |
| 207 | }, | |
| 185 | 208 | } |
| 186 | 209 | } |
| 187 | fn archToPlan9Char(arch: std.Target.Cpu.Arch) ?u8 { | |
| 188 | // copied from 2c(1) | |
| 189 | // 0c spim little-endian MIPS 3000 family | |
| 190 | // 1c 68000 Motorola MC68000 | |
| 191 | // 2c 68020 Motorola MC68020 | |
| 192 | // 5c arm little-endian ARM | |
| 193 | // 6c amd64 AMD64 and compatibles (e.g., Intel EM64T) | |
| 194 | // 7c arm64 ARM64 (ARMv8) | |
| 195 | // 8c 386 Intel i386, i486, Pentium, etc. | |
| 196 | // kc sparc Sun SPARC | |
| 197 | // qc power Power PC | |
| 198 | // vc mips big-endian MIPS 3000 family | |
| 199 | return switch (arch) { | |
| 200 | .arm => '5', | |
| 201 | .x86_64 => '6', | |
| 202 | .aarch64 => '7', | |
| 203 | .i386 => '8', | |
| 204 | .sparc => 'k', | |
| 205 | .powerpc, .powerpcle => 'q', | |
| 206 | .mips, .mipsel => 'v', | |
| 207 | else => 'X', // this arch does not have a char or maybe was not ported to plan9 so we just use X | |
| 208 | }; | |
| 209 | } | |
| 210 | 210 | |
| 211 | 211 | pub const ParsedCharLiteral = union(enum) { |
| 212 | 212 | success: u32, |
src/codegen.zig+1-1| ... | ... | @@ -2556,7 +2556,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2556 | 2556 | } else { |
| 2557 | 2557 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); |
| 2558 | 2558 | } |
| 2559 | } else if (self.bin_file.cast(link.File.Plan9)) |_| { | |
| 2559 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | |
| 2560 | 2560 | switch (arch) { |
| 2561 | 2561 | .x86_64 => { |
| 2562 | 2562 | for (info.args) |mc_arg, arg_i| { |
src/link.zig+1-1| ... | ... | @@ -333,7 +333,7 @@ pub const File = struct { |
| 333 | 333 | .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl), |
| 334 | 334 | .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl), |
| 335 | 335 | .c => return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl), |
| 336 | .plan9 => @panic("PLAN 9 DEBUG INFO"), | |
| 336 | .plan9 => @panic("TODO: implement updateDeclLineNumber for plan9"), | |
| 337 | 337 | .wasm, .spirv => {}, |
| 338 | 338 | } |
| 339 | 339 | } |
src/link/Plan9.zig+7-6| ... | ... | @@ -1,10 +1,13 @@ |
| 1 | //! This implementation does all the linking work in flush(). A future improvement | |
| 2 | //! would be to add incremental linking in a similar way as ELF does. | |
| 3 | ||
| 1 | 4 | const Plan9 = @This(); |
| 2 | 5 | |
| 3 | 6 | const std = @import("std"); |
| 4 | 7 | const link = @import("../link.zig"); |
| 5 | 8 | const Module = @import("../Module.zig"); |
| 6 | 9 | const Compilation = @import("../Compilation.zig"); |
| 7 | const aout = @import("plan9/a.out.zig"); | |
| 10 | const aout = @import("Plan9/aout.zig"); | |
| 8 | 11 | const codegen = @import("../codegen.zig"); |
| 9 | 12 | const trace = @import("../tracy.zig").trace; |
| 10 | 13 | const mem = std.mem; |
| ... | ... | @@ -14,8 +17,6 @@ const Allocator = std.mem.Allocator; |
| 14 | 17 | const log = std.log.scoped(.link); |
| 15 | 18 | const assert = std.debug.assert; |
| 16 | 19 | |
| 17 | // TODO use incremental compilation | |
| 18 | ||
| 19 | 20 | base: link.File, |
| 20 | 21 | sixtyfour_bit: bool, |
| 21 | 22 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| ... | ... | @@ -38,7 +39,7 @@ const Bases = struct { |
| 38 | 39 | data: u64, |
| 39 | 40 | }; |
| 40 | 41 | |
| 41 | fn getAddr(self: Plan9, addr: u64, t: aout.SymType) u64 { | |
| 42 | fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { | |
| 42 | 43 | return addr + switch (t) { |
| 43 | 44 | .T, .t, .l, .L => self.bases.text, |
| 44 | 45 | .D, .d, .B, .b => self.bases.data, |
| ... | ... | @@ -46,7 +47,7 @@ fn getAddr(self: Plan9, addr: u64, t: aout.SymType) u64 { |
| 46 | 47 | }; |
| 47 | 48 | } |
| 48 | 49 | /// opposite of getAddr |
| 49 | fn takeAddr(self: Plan9, addr: u64, t: aout.SymType) u64 { | |
| 50 | fn takeAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { | |
| 50 | 51 | return addr - switch (t) { |
| 51 | 52 | .T, .t, .l, .L => self.bases.text, |
| 52 | 53 | .D, .d, .B, .b => self.bases.data, |
| ... | ... | @@ -59,7 +60,7 @@ fn getSymAddr(self: Plan9, s: aout.Sym) u64 { |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | 62 | pub const DeclBlock = struct { |
| 62 | type: aout.SymType, | |
| 63 | type: aout.Sym.Type, | |
| 63 | 64 | /// offset in the text or data sects |
| 64 | 65 | offset: ?u64, |
| 65 | 66 | /// offset into syms |
src/link/Plan9/aout.zig created+114| ... | ... | @@ -0,0 +1,114 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | /// All integers are in big-endian format (needs a byteswap). | |
| 5 | pub const ExecHdr = extern struct { | |
| 6 | magic: u32, | |
| 7 | text: u32, | |
| 8 | data: u32, | |
| 9 | bss: u32, | |
| 10 | syms: u32, | |
| 11 | /// You should truncate this to 32 bits on 64 bit systems, then but the actual 8 bytes | |
| 12 | /// in the fat header. | |
| 13 | entry: u32, | |
| 14 | spsz: u32, | |
| 15 | pcsz: u32, | |
| 16 | comptime { | |
| 17 | assert(@sizeOf(@This()) == 32); | |
| 18 | } | |
| 19 | /// It is up to the caller to disgard the last 8 bytes if the header is not fat. | |
| 20 | pub fn toU8s(self: *@This()) [40]u8 { | |
| 21 | var buf: [40]u8 = undefined; | |
| 22 | var i: u8 = 0; | |
| 23 | inline for (std.meta.fields(@This())) |f| { | |
| 24 | std.mem.writeIntSliceBig(u32, buf[i .. i + 4], @field(self, f.name)); | |
| 25 | i += 4; | |
| 26 | } | |
| 27 | return buf; | |
| 28 | } | |
| 29 | }; | |
| 30 | ||
| 31 | pub const Sym = struct { | |
| 32 | /// Big endian in the file | |
| 33 | value: u64, | |
| 34 | type: Type, | |
| 35 | name: []const u8, | |
| 36 | ||
| 37 | /// The type field is one of the following characters with the | |
| 38 | /// high bit set: | |
| 39 | /// T text segment symbol | |
| 40 | /// t static text segment symbol | |
| 41 | /// L leaf function text segment symbol | |
| 42 | /// l static leaf function text segment symbol | |
| 43 | /// D data segment symbol | |
| 44 | /// d static data segment symbol | |
| 45 | /// B bss segment symbol | |
| 46 | /// b static bss segment symbol | |
| 47 | /// a automatic (local) variable symbol | |
| 48 | /// p function parameter symbol | |
| 49 | /// f source file name components | |
| 50 | /// z source file name | |
| 51 | /// Z source file line offset | |
| 52 | /// m for '.frame' | |
| 53 | pub const Type = enum(u8) { | |
| 54 | T = 0x80 | 'T', | |
| 55 | t = 0x80 | 't', | |
| 56 | L = 0x80 | 'L', | |
| 57 | l = 0x80 | 'l', | |
| 58 | D = 0x80 | 'D', | |
| 59 | d = 0x80 | 'd', | |
| 60 | B = 0x80 | 'B', | |
| 61 | b = 0x80 | 'b', | |
| 62 | a = 0x80 | 'a', | |
| 63 | p = 0x80 | 'p', | |
| 64 | f = 0x80 | 'f', | |
| 65 | z = 0x80 | 'z', | |
| 66 | Z = 0x80 | 'Z', | |
| 67 | m = 0x80 | 'm', | |
| 68 | ||
| 69 | pub fn toGlobal(self: Type) Type { | |
| 70 | return switch (self) { | |
| 71 | .t => .T, | |
| 72 | .b => .B, | |
| 73 | .d => .D, | |
| 74 | else => unreachable, | |
| 75 | }; | |
| 76 | } | |
| 77 | }; | |
| 78 | }; | |
| 79 | ||
| 80 | pub const HDR_MAGIC = 0x00008000; | |
| 81 | pub inline fn _MAGIC(f: anytype, b: anytype) @TypeOf(f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7))) { | |
| 82 | return f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7)); | |
| 83 | } | |
| 84 | pub const A_MAGIC = _MAGIC(0, 8); // 68020 | |
| 85 | pub const I_MAGIC = _MAGIC(0, 11); // intel 386 | |
| 86 | pub const J_MAGIC = _MAGIC(0, 12); // intel 960 (retired) | |
| 87 | pub const K_MAGIC = _MAGIC(0, 13); // sparc | |
| 88 | pub const V_MAGIC = _MAGIC(0, 16); // mips 3000 BE | |
| 89 | pub const X_MAGIC = _MAGIC(0, 17); // att dsp 3210 (retired) | |
| 90 | pub const M_MAGIC = _MAGIC(0, 18); // mips 4000 BE | |
| 91 | pub const D_MAGIC = _MAGIC(0, 19); // amd 29000 (retired) | |
| 92 | pub const E_MAGIC = _MAGIC(0, 20); // arm | |
| 93 | pub const Q_MAGIC = _MAGIC(0, 21); // powerpc | |
| 94 | pub const N_MAGIC = _MAGIC(0, 22); // mips 4000 LE | |
| 95 | pub const L_MAGIC = _MAGIC(0, 23); // dec alpha (retired) | |
| 96 | pub const P_MAGIC = _MAGIC(0, 24); // mips 3000 LE | |
| 97 | pub const U_MAGIC = _MAGIC(0, 25); // sparc64 | |
| 98 | pub const S_MAGIC = _MAGIC(HDR_MAGIC, 26); // amd64 | |
| 99 | pub const T_MAGIC = _MAGIC(HDR_MAGIC, 27); // powerpc64 | |
| 100 | pub const R_MAGIC = _MAGIC(HDR_MAGIC, 28); // arm64 | |
| 101 | ||
| 102 | pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 { | |
| 103 | return switch (arch) { | |
| 104 | .i386 => I_MAGIC, | |
| 105 | .sparc => K_MAGIC, // TODO should sparcv9 and sparcel go here? | |
| 106 | .mips => V_MAGIC, | |
| 107 | .arm => E_MAGIC, | |
| 108 | .aarch64 => R_MAGIC, | |
| 109 | .powerpc => Q_MAGIC, | |
| 110 | .powerpc64 => T_MAGIC, | |
| 111 | .x86_64 => S_MAGIC, | |
| 112 | else => error.ArchNotSupportedByPlan9, | |
| 113 | }; | |
| 114 | } |
src/link/plan9/a.out.zig deleted-134| ... | ... | @@ -1,134 +0,0 @@ |
| 1 | // Copyright © 2021 Plan 9 Foundation | |
| 2 | // Copyright © 20XX 9front authors | |
| 3 | ||
| 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | // of this software and associated documentation files (the "Software"), to deal | |
| 6 | // in the Software without restriction, including without limitation the rights | |
| 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | // copies of the Software, and to permit persons to whom the Software is | |
| 9 | // furnished to do so, subject to the following conditions: | |
| 10 | ||
| 11 | // The above copyright notice and this permission notice shall be included in all | |
| 12 | // copies or substantial portions of the Software. | |
| 13 | ||
| 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 20 | // SOFTWARE. | |
| 21 | ||
| 22 | // Idomatic translation of 9front a.out.h | |
| 23 | const std = @import("std"); | |
| 24 | // all integers are in big-endian format (needs a byteswap) | |
| 25 | pub const ExecHdr = extern struct { | |
| 26 | magic: u32, | |
| 27 | text: u32, | |
| 28 | data: u32, | |
| 29 | bss: u32, | |
| 30 | syms: u32, | |
| 31 | /// You should truncate this to 32 bits on 64 bit systems, then but the actual 8 bytes | |
| 32 | /// in the fat header. | |
| 33 | entry: u32, | |
| 34 | spsz: u32, | |
| 35 | pcsz: u32, | |
| 36 | comptime { | |
| 37 | std.debug.assert(@sizeOf(@This()) == 32); | |
| 38 | } | |
| 39 | /// it is up to the caller to disgard the last 8 bytes if the header is not fat | |
| 40 | pub fn toU8s(self: *@This()) [40]u8 { | |
| 41 | var buf: [40]u8 = undefined; | |
| 42 | var i: u8 = 0; | |
| 43 | inline for (std.meta.fields(@This())) |f| { | |
| 44 | std.mem.writeIntSliceBig(u32, buf[i .. i + 4], @field(self, f.name)); | |
| 45 | i += 4; | |
| 46 | } | |
| 47 | return buf; | |
| 48 | } | |
| 49 | }; | |
| 50 | ||
| 51 | // uchar value[8]; | |
| 52 | // char type; | |
| 53 | // char name[n]; /* NUL-terminated */ | |
| 54 | pub const Sym = struct { | |
| 55 | value: u64, // big endian in the file | |
| 56 | type: SymType, | |
| 57 | name: []const u8, | |
| 58 | }; | |
| 59 | // The type field is one of the following characters with the | |
| 60 | // high bit set: | |
| 61 | // T text segment symbol | |
| 62 | // t static text segment symbol | |
| 63 | // L leaf function text segment symbol | |
| 64 | // l static leaf function text segment symbol | |
| 65 | // D data segment symbol | |
| 66 | // d static data segment symbol | |
| 67 | // B bss segment symbol | |
| 68 | // b static bss segment symbol | |
| 69 | // a automatic (local) variable symbol | |
| 70 | // p function parameter symbol | |
| 71 | // f source file name components | |
| 72 | // z source file name | |
| 73 | // Z source file line offset | |
| 74 | // m for '.frame' | |
| 75 | pub const SymType = enum(u8) { | |
| 76 | T = 0x80 | 'T', | |
| 77 | t = 0x80 | 't', | |
| 78 | L = 0x80 | 'L', | |
| 79 | l = 0x80 | 'l', | |
| 80 | D = 0x80 | 'D', | |
| 81 | d = 0x80 | 'd', | |
| 82 | B = 0x80 | 'B', | |
| 83 | b = 0x80 | 'b', | |
| 84 | a = 0x80 | 'a', | |
| 85 | p = 0x80 | 'p', | |
| 86 | f = 0x80 | 'f', | |
| 87 | z = 0x80 | 'z', | |
| 88 | Z = 0x80 | 'Z', | |
| 89 | m = 0x80 | 'm', | |
| 90 | pub fn toGlobal(self: SymType) SymType { | |
| 91 | return switch (self) { | |
| 92 | .t => .T, | |
| 93 | .b => .B, | |
| 94 | .d => .D, | |
| 95 | else => unreachable, | |
| 96 | }; | |
| 97 | } | |
| 98 | }; | |
| 99 | ||
| 100 | pub const HDR_MAGIC = 0x00008000; | |
| 101 | pub inline fn _MAGIC(f: anytype, b: anytype) @TypeOf(f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7))) { | |
| 102 | return f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7)); | |
| 103 | } | |
| 104 | pub const A_MAGIC = _MAGIC(0, 8); // 68020 | |
| 105 | pub const I_MAGIC = _MAGIC(0, 11); // intel 386 | |
| 106 | pub const J_MAGIC = _MAGIC(0, 12); // intel 960 (retired) | |
| 107 | pub const K_MAGIC = _MAGIC(0, 13); // sparc | |
| 108 | pub const V_MAGIC = _MAGIC(0, 16); // mips 3000 BE | |
| 109 | pub const X_MAGIC = _MAGIC(0, 17); // att dsp 3210 (retired) | |
| 110 | pub const M_MAGIC = _MAGIC(0, 18); // mips 4000 BE | |
| 111 | pub const D_MAGIC = _MAGIC(0, 19); // amd 29000 (retired) | |
| 112 | pub const E_MAGIC = _MAGIC(0, 20); // arm | |
| 113 | pub const Q_MAGIC = _MAGIC(0, 21); // powerpc | |
| 114 | pub const N_MAGIC = _MAGIC(0, 22); // mips 4000 LE | |
| 115 | pub const L_MAGIC = _MAGIC(0, 23); // dec alpha (retired) | |
| 116 | pub const P_MAGIC = _MAGIC(0, 24); // mips 3000 LE | |
| 117 | pub const U_MAGIC = _MAGIC(0, 25); // sparc64 | |
| 118 | pub const S_MAGIC = _MAGIC(HDR_MAGIC, 26); // amd64 | |
| 119 | pub const T_MAGIC = _MAGIC(HDR_MAGIC, 27); // powerpc64 | |
| 120 | pub const R_MAGIC = _MAGIC(HDR_MAGIC, 28); // arm64 | |
| 121 | ||
| 122 | pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 { | |
| 123 | return switch (arch) { | |
| 124 | .i386 => I_MAGIC, | |
| 125 | .sparc => K_MAGIC, // TODO should sparcv9 and sparcel go here? | |
| 126 | .mips => V_MAGIC, | |
| 127 | .arm => E_MAGIC, | |
| 128 | .aarch64 => R_MAGIC, | |
| 129 | .powerpc => Q_MAGIC, | |
| 130 | .powerpc64 => T_MAGIC, | |
| 131 | .x86_64 => S_MAGIC, | |
| 132 | else => error.ArchNotSupportedByPlan9, | |
| 133 | }; | |
| 134 | } |