authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-08-16 18:11:10+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-08-17 18:16:29+02:00
loge23fc3905f65d65a743cb60783830b85199ed83b
tree530254eca34f09e81bfc6d3f7f94563c8ef69dab
parent6b141620a623ae36ad0e40533457a5a24aa404e1

Add skeleton for MachO support in stage2

This commit adds an empty skeleton for MachO format support in stage2.

2 files changed, 117 insertions(+), 2 deletions(-)

src-self-hosted/Module.zig+5
...@@ -1568,6 +1568,9 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {...@@ -1568,6 +1568,9 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
1568 // in `Decl` to notice that the line number did not change.1568 // in `Decl` to notice that the line number did not change.
1569 self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });1569 self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
1570 },1570 },
1571 .macho => {
1572 // TODO Implement for MachO
1573 },
1571 .c => {},1574 .c => {},
1572 }1575 }
1573 }1576 }
...@@ -1776,10 +1779,12 @@ fn allocateNewDecl(...@@ -1776,10 +1779,12 @@ fn allocateNewDecl(
1776 .contents_hash = contents_hash,1779 .contents_hash = contents_hash,
1777 .link = switch (self.bin_file.tag) {1780 .link = switch (self.bin_file.tag) {
1778 .elf => .{ .elf = link.File.Elf.TextBlock.empty },1781 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
1782 .macho => .{ .macho = link.File.MachO.TextBlock.empty },
1779 .c => .{ .c = {} },1783 .c => .{ .c = {} },
1780 },1784 },
1781 .fn_link = switch (self.bin_file.tag) {1785 .fn_link = switch (self.bin_file.tag) {
1782 .elf => .{ .elf = link.File.Elf.SrcFn.empty },1786 .elf => .{ .elf = link.File.Elf.SrcFn.empty },
1787 .macho => .{ .macho = link.File.MachO.SrcFn.empty },
1783 .c => .{ .c = {} },1788 .c => .{ .c = {} },
1784 },1789 },
1785 .generation = 0,1790 .generation = 0,
src-self-hosted/link.zig+112-2
...@@ -44,11 +44,13 @@ pub const Options = struct {...@@ -44,11 +44,13 @@ pub const Options = struct {
44pub const File = struct {44pub const File = struct {
45 pub const LinkBlock = union {45 pub const LinkBlock = union {
46 elf: Elf.TextBlock,46 elf: Elf.TextBlock,
47 macho: MachO.TextBlock,
47 c: void,48 c: void,
48 };49 };
4950
50 pub const LinkFn = union {51 pub const LinkFn = union {
51 elf: Elf.SrcFn,52 elf: Elf.SrcFn,
53 macho: MachO.SrcFn,
52 c: void,54 c: void,
53 };55 };
5456
...@@ -66,7 +68,7 @@ pub const File = struct {...@@ -66,7 +68,7 @@ pub const File = struct {
66 .unknown => unreachable,68 .unknown => unreachable,
67 .coff => return error.TODOImplementCoff,69 .coff => return error.TODOImplementCoff,
68 .elf => return Elf.openPath(allocator, dir, sub_path, options),70 .elf => return Elf.openPath(allocator, dir, sub_path, options),
69 .macho => return error.TODOImplementMacho,71 .macho => return MachO.openPath(allocator, dir, sub_path, options),
70 .wasm => return error.TODOImplementWasm,72 .wasm => return error.TODOImplementWasm,
71 .c => return C.openPath(allocator, dir, sub_path, options),73 .c => return C.openPath(allocator, dir, sub_path, options),
72 .hex => return error.TODOImplementHex,74 .hex => return error.TODOImplementHex,
...@@ -83,7 +85,7 @@ pub const File = struct {...@@ -83,7 +85,7 @@ pub const File = struct {
8385
84 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {86 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
85 switch (base.tag) {87 switch (base.tag) {
86 .elf => {88 .elf, .macho => {
87 if (base.file != null) return;89 if (base.file != null) return;
88 base.file = try dir.createFile(sub_path, .{90 base.file = try dir.createFile(sub_path, .{
89 .truncate = false,91 .truncate = false,
...@@ -106,6 +108,7 @@ pub const File = struct {...@@ -106,6 +108,7 @@ pub const File = struct {
106 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {108 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
107 switch (base.tag) {109 switch (base.tag) {
108 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),110 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
111 .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),
109 .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),112 .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),
110 }113 }
111 }114 }
...@@ -113,6 +116,7 @@ pub const File = struct {...@@ -113,6 +116,7 @@ pub const File = struct {
113 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {116 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {
114 switch (base.tag) {117 switch (base.tag) {
115 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),118 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
119 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),
116 .c => {},120 .c => {},
117 }121 }
118 }122 }
...@@ -120,6 +124,7 @@ pub const File = struct {...@@ -120,6 +124,7 @@ pub const File = struct {
120 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {124 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
121 switch (base.tag) {125 switch (base.tag) {
122 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),126 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
127 .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl),
123 .c => {},128 .c => {},
124 }129 }
125 }130 }
...@@ -128,6 +133,7 @@ pub const File = struct {...@@ -128,6 +133,7 @@ pub const File = struct {
128 if (base.file) |f| f.close();133 if (base.file) |f| f.close();
129 switch (base.tag) {134 switch (base.tag) {
130 .elf => @fieldParentPtr(Elf, "base", base).deinit(),135 .elf => @fieldParentPtr(Elf, "base", base).deinit(),
136 .macho => @fieldParentPtr(MachO, "base", base).deinit(),
131 .c => @fieldParentPtr(C, "base", base).deinit(),137 .c => @fieldParentPtr(C, "base", base).deinit(),
132 }138 }
133 }139 }
...@@ -139,6 +145,11 @@ pub const File = struct {...@@ -139,6 +145,11 @@ pub const File = struct {
139 parent.deinit();145 parent.deinit();
140 base.allocator.destroy(parent);146 base.allocator.destroy(parent);
141 },147 },
148 .macho => {
149 const parent = @fieldParentPtr(MachO, "base", base);
150 parent.deinit();
151 base.allocator.destroy(parent);
152 },
142 .c => {153 .c => {
143 const parent = @fieldParentPtr(C, "base", base);154 const parent = @fieldParentPtr(C, "base", base);
144 parent.deinit();155 parent.deinit();
...@@ -153,6 +164,7 @@ pub const File = struct {...@@ -153,6 +164,7 @@ pub const File = struct {
153164
154 try switch (base.tag) {165 try switch (base.tag) {
155 .elf => @fieldParentPtr(Elf, "base", base).flush(),166 .elf => @fieldParentPtr(Elf, "base", base).flush(),
167 .macho => @fieldParentPtr(MachO, "base", base).flush(),
156 .c => @fieldParentPtr(C, "base", base).flush(),168 .c => @fieldParentPtr(C, "base", base).flush(),
157 };169 };
158 }170 }
...@@ -160,6 +172,7 @@ pub const File = struct {...@@ -160,6 +172,7 @@ pub const File = struct {
160 pub fn freeDecl(base: *File, decl: *Module.Decl) void {172 pub fn freeDecl(base: *File, decl: *Module.Decl) void {
161 switch (base.tag) {173 switch (base.tag) {
162 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),174 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),
175 .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),
163 .c => unreachable,176 .c => unreachable,
164 }177 }
165 }178 }
...@@ -167,6 +180,7 @@ pub const File = struct {...@@ -167,6 +180,7 @@ pub const File = struct {
167 pub fn errorFlags(base: *File) ErrorFlags {180 pub fn errorFlags(base: *File) ErrorFlags {
168 return switch (base.tag) {181 return switch (base.tag) {
169 .elf => @fieldParentPtr(Elf, "base", base).error_flags,182 .elf => @fieldParentPtr(Elf, "base", base).error_flags,
183 .macho => @fieldParentPtr(MachO, "base", base).error_flags,
170 .c => return .{ .no_entry_point_found = false },184 .c => return .{ .no_entry_point_found = false },
171 };185 };
172 }186 }
...@@ -180,12 +194,14 @@ pub const File = struct {...@@ -180,12 +194,14 @@ pub const File = struct {
180 ) !void {194 ) !void {
181 switch (base.tag) {195 switch (base.tag) {
182 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),196 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),
197 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl, exports),
183 .c => return {},198 .c => return {},
184 }199 }
185 }200 }
186201
187 pub const Tag = enum {202 pub const Tag = enum {
188 elf,203 elf,
204 macho,
189 c,205 c,
190 };206 };
191207
...@@ -2815,6 +2831,100 @@ pub const File = struct {...@@ -2815,6 +2831,100 @@ pub const File = struct {
2815 }2831 }
28162832
2817 };2833 };
2834
2835 pub const MachO = struct {
2836 pub const base_tag: Tag = .macho;
2837
2838 base: File,
2839
2840 ptr_width: enum { p32, p64 },
2841
2842 error_flags: ErrorFlags = ErrorFlags{},
2843
2844 pub const TextBlock = struct {
2845 pub const empty = TextBlock{};
2846 };
2847
2848 pub const SrcFn = struct {
2849 pub const empty = SrcFn{};
2850 };
2851
2852 pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File {
2853 assert(options.object_format == .macho);
2854
2855 const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = determineMode(options) });
2856 errdefer file.close();
2857
2858 var macho_file = try allocator.create(MachO);
2859 errdefer allocator.destroy(macho_file);
2860
2861 macho_file.* = openFile(allocator, file, options) catch |err| switch (err) {
2862 error.IncrFailed => try createFile(allocator, file, options),
2863 else => |e| return e,
2864 };
2865
2866 return &macho_file.base;
2867 }
2868
2869 /// Returns error.IncrFailed if incremental update could not be performed.
2870 fn openFile(allocator: *Allocator, file: fs.File, options: Options) !MachO {
2871 switch (options.output_mode) {
2872 .Exe => {},
2873 .Obj => {},
2874 .Lib => return error.IncrFailed,
2875 }
2876 var self: MachO = .{
2877 .base = .{
2878 .file = file,
2879 .tag = .macho,
2880 .options = options,
2881 .allocator = allocator,
2882 },
2883 .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) {
2884 32 => .p32,
2885 64 => .p64,
2886 else => return error.UnsupportedELFArchitecture,
2887 },
2888 };
2889 errdefer self.deinit();
2890
2891 // TODO implement reading the macho file
2892 return error.IncrFailed;
2893 //try self.populateMissingMetadata();
2894 //return self;
2895 }
2896
2897 /// Truncates the existing file contents and overwrites the contents.
2898 /// Returns an error if `file` is not already open with +read +write +seek abilities.
2899 fn createFile(allocator: *Allocator, file: fs.File, options: Options) !MachO {
2900 switch (options.output_mode) {
2901 .Exe => return error.TODOImplementWritingMachOExeFiles,
2902 .Obj => return error.TODOImplementWritingMachOObjFiles,
2903 .Lib => return error.TODOImplementWritingLibFiles,
2904 }
2905 }
2906
2907 /// Commit pending changes and write headers.
2908 pub fn flush(self: *MachO) !void {}
2909
2910 pub fn deinit(self: *MachO) void {}
2911
2912 pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {}
2913
2914 pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {}
2915
2916 pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {}
2917
2918 /// Must be called only after a successful call to `updateDecl`.
2919 pub fn updateDeclExports(
2920 self: *MachO,
2921 module: *Module,
2922 decl: *const Module.Decl,
2923 exports: []const *Module.Export,
2924 ) !void {}
2925
2926 pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}
2927 };
2818};2928};
28192929
2820/// Saturating multiplication2930/// Saturating multiplication