| ... | ... | @@ -44,11 +44,13 @@ pub const Options = struct { |
| 44 | 44 | pub const File = struct { |
| 45 | 45 | pub const LinkBlock = union { |
| 46 | 46 | elf: Elf.TextBlock, |
| 47 | macho: MachO.TextBlock, |
| 47 | 48 | c: void, |
| 48 | 49 | }; |
| 49 | 50 | |
| 50 | 51 | pub const LinkFn = union { |
| 51 | 52 | elf: Elf.SrcFn, |
| 53 | macho: MachO.SrcFn, |
| 52 | 54 | c: void, |
| 53 | 55 | }; |
| 54 | 56 | |
| ... | ... | @@ -66,7 +68,7 @@ pub const File = struct { |
| 66 | 68 | .unknown => unreachable, |
| 67 | 69 | .coff => return error.TODOImplementCoff, |
| 68 | 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 | 72 | .wasm => return error.TODOImplementWasm, |
| 71 | 73 | .c => return C.openPath(allocator, dir, sub_path, options), |
| 72 | 74 | .hex => return error.TODOImplementHex, |
| ... | ... | @@ -83,7 +85,7 @@ pub const File = struct { |
| 83 | 85 | |
| 84 | 86 | pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void { |
| 85 | 87 | switch (base.tag) { |
| 86 | | .elf => { |
| 88 | .elf, .macho => { |
| 87 | 89 | if (base.file != null) return; |
| 88 | 90 | base.file = try dir.createFile(sub_path, .{ |
| 89 | 91 | .truncate = false, |
| ... | ... | @@ -106,6 +108,7 @@ pub const File = struct { |
| 106 | 108 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void { |
| 107 | 109 | switch (base.tag) { |
| 108 | 110 | .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), |
| 111 | .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl), |
| 109 | 112 | .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl), |
| 110 | 113 | } |
| 111 | 114 | } |
| ... | ... | @@ -113,6 +116,7 @@ pub const File = struct { |
| 113 | 116 | pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void { |
| 114 | 117 | switch (base.tag) { |
| 115 | 118 | .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl), |
| 119 | .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl), |
| 116 | 120 | .c => {}, |
| 117 | 121 | } |
| 118 | 122 | } |
| ... | ... | @@ -120,6 +124,7 @@ pub const File = struct { |
| 120 | 124 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void { |
| 121 | 125 | switch (base.tag) { |
| 122 | 126 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), |
| 127 | .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl), |
| 123 | 128 | .c => {}, |
| 124 | 129 | } |
| 125 | 130 | } |
| ... | ... | @@ -128,6 +133,7 @@ pub const File = struct { |
| 128 | 133 | if (base.file) |f| f.close(); |
| 129 | 134 | switch (base.tag) { |
| 130 | 135 | .elf => @fieldParentPtr(Elf, "base", base).deinit(), |
| 136 | .macho => @fieldParentPtr(MachO, "base", base).deinit(), |
| 131 | 137 | .c => @fieldParentPtr(C, "base", base).deinit(), |
| 132 | 138 | } |
| 133 | 139 | } |
| ... | ... | @@ -139,6 +145,11 @@ pub const File = struct { |
| 139 | 145 | parent.deinit(); |
| 140 | 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 | 153 | .c => { |
| 143 | 154 | const parent = @fieldParentPtr(C, "base", base); |
| 144 | 155 | parent.deinit(); |
| ... | ... | @@ -153,6 +164,7 @@ pub const File = struct { |
| 153 | 164 | |
| 154 | 165 | try switch (base.tag) { |
| 155 | 166 | .elf => @fieldParentPtr(Elf, "base", base).flush(), |
| 167 | .macho => @fieldParentPtr(MachO, "base", base).flush(), |
| 156 | 168 | .c => @fieldParentPtr(C, "base", base).flush(), |
| 157 | 169 | }; |
| 158 | 170 | } |
| ... | ... | @@ -160,6 +172,7 @@ pub const File = struct { |
| 160 | 172 | pub fn freeDecl(base: *File, decl: *Module.Decl) void { |
| 161 | 173 | switch (base.tag) { |
| 162 | 174 | .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl), |
| 175 | .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl), |
| 163 | 176 | .c => unreachable, |
| 164 | 177 | } |
| 165 | 178 | } |
| ... | ... | @@ -167,6 +180,7 @@ pub const File = struct { |
| 167 | 180 | pub fn errorFlags(base: *File) ErrorFlags { |
| 168 | 181 | return switch (base.tag) { |
| 169 | 182 | .elf => @fieldParentPtr(Elf, "base", base).error_flags, |
| 183 | .macho => @fieldParentPtr(MachO, "base", base).error_flags, |
| 170 | 184 | .c => return .{ .no_entry_point_found = false }, |
| 171 | 185 | }; |
| 172 | 186 | } |
| ... | ... | @@ -180,12 +194,14 @@ pub const File = struct { |
| 180 | 194 | ) !void { |
| 181 | 195 | switch (base.tag) { |
| 182 | 196 | .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports), |
| 197 | .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl, exports), |
| 183 | 198 | .c => return {}, |
| 184 | 199 | } |
| 185 | 200 | } |
| 186 | 201 | |
| 187 | 202 | pub const Tag = enum { |
| 188 | 203 | elf, |
| 204 | macho, |
| 189 | 205 | c, |
| 190 | 206 | }; |
| 191 | 207 | |
| ... | ... | @@ -2815,6 +2831,100 @@ pub const File = struct { |
| 2815 | 2831 | } |
| 2816 | 2832 | |
| 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 | }; |
| 2819 | 2929 | |
| 2820 | 2930 | /// Saturating multiplication |