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 {
15681568 // in `Decl` to notice that the line number did not change.
15691569 self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
15701570 },
1571 .macho => {
1572 // TODO Implement for MachO
1573 },
15711574 .c => {},
15721575 }
15731576 }
......@@ -1776,10 +1779,12 @@ fn allocateNewDecl(
17761779 .contents_hash = contents_hash,
17771780 .link = switch (self.bin_file.tag) {
17781781 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
1782 .macho => .{ .macho = link.File.MachO.TextBlock.empty },
17791783 .c => .{ .c = {} },
17801784 },
17811785 .fn_link = switch (self.bin_file.tag) {
17821786 .elf => .{ .elf = link.File.Elf.SrcFn.empty },
1787 .macho => .{ .macho = link.File.MachO.SrcFn.empty },
17831788 .c => .{ .c = {} },
17841789 },
17851790 .generation = 0,
src-self-hosted/link.zig+112-2
......@@ -44,11 +44,13 @@ pub const Options = struct {
4444pub const File = struct {
4545 pub const LinkBlock = union {
4646 elf: Elf.TextBlock,
47 macho: MachO.TextBlock,
4748 c: void,
4849 };
4950
5051 pub const LinkFn = union {
5152 elf: Elf.SrcFn,
53 macho: MachO.SrcFn,
5254 c: void,
5355 };
5456
......@@ -66,7 +68,7 @@ pub const File = struct {
6668 .unknown => unreachable,
6769 .coff => return error.TODOImplementCoff,
6870 .elf => return Elf.openPath(allocator, dir, sub_path, options),
69 .macho => return error.TODOImplementMacho,
71 .macho => return MachO.openPath(allocator, dir, sub_path, options),
7072 .wasm => return error.TODOImplementWasm,
7173 .c => return C.openPath(allocator, dir, sub_path, options),
7274 .hex => return error.TODOImplementHex,
......@@ -83,7 +85,7 @@ pub const File = struct {
8385
8486 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
8587 switch (base.tag) {
86 .elf => {
88 .elf, .macho => {
8789 if (base.file != null) return;
8890 base.file = try dir.createFile(sub_path, .{
8991 .truncate = false,
......@@ -106,6 +108,7 @@ pub const File = struct {
106108 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
107109 switch (base.tag) {
108110 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
111 .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),
109112 .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),
110113 }
111114 }
......@@ -113,6 +116,7 @@ pub const File = struct {
113116 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {
114117 switch (base.tag) {
115118 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
119 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),
116120 .c => {},
117121 }
118122 }
......@@ -120,6 +124,7 @@ pub const File = struct {
120124 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
121125 switch (base.tag) {
122126 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
127 .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl),
123128 .c => {},
124129 }
125130 }
......@@ -128,6 +133,7 @@ pub const File = struct {
128133 if (base.file) |f| f.close();
129134 switch (base.tag) {
130135 .elf => @fieldParentPtr(Elf, "base", base).deinit(),
136 .macho => @fieldParentPtr(MachO, "base", base).deinit(),
131137 .c => @fieldParentPtr(C, "base", base).deinit(),
132138 }
133139 }
......@@ -139,6 +145,11 @@ pub const File = struct {
139145 parent.deinit();
140146 base.allocator.destroy(parent);
141147 },
148 .macho => {
149 const parent = @fieldParentPtr(MachO, "base", base);
150 parent.deinit();
151 base.allocator.destroy(parent);
152 },
142153 .c => {
143154 const parent = @fieldParentPtr(C, "base", base);
144155 parent.deinit();
......@@ -153,6 +164,7 @@ pub const File = struct {
153164
154165 try switch (base.tag) {
155166 .elf => @fieldParentPtr(Elf, "base", base).flush(),
167 .macho => @fieldParentPtr(MachO, "base", base).flush(),
156168 .c => @fieldParentPtr(C, "base", base).flush(),
157169 };
158170 }
......@@ -160,6 +172,7 @@ pub const File = struct {
160172 pub fn freeDecl(base: *File, decl: *Module.Decl) void {
161173 switch (base.tag) {
162174 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),
175 .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),
163176 .c => unreachable,
164177 }
165178 }
......@@ -167,6 +180,7 @@ pub const File = struct {
167180 pub fn errorFlags(base: *File) ErrorFlags {
168181 return switch (base.tag) {
169182 .elf => @fieldParentPtr(Elf, "base", base).error_flags,
183 .macho => @fieldParentPtr(MachO, "base", base).error_flags,
170184 .c => return .{ .no_entry_point_found = false },
171185 };
172186 }
......@@ -180,12 +194,14 @@ pub const File = struct {
180194 ) !void {
181195 switch (base.tag) {
182196 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),
197 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl, exports),
183198 .c => return {},
184199 }
185200 }
186201
187202 pub const Tag = enum {
188203 elf,
204 macho,
189205 c,
190206 };
191207
......@@ -2815,6 +2831,100 @@ pub const File = struct {
28152831 }
28162832
28172833 };
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 };
28182928};
28192929
28202930/// Saturating multiplication