| author | |
| committer | |
| log | 2627778b251deff3426b5dc21a5a591e0c823b3b |
| tree | a82d2822d58e01f277174a275b7063f113b5a63d |
| parent | 046dce9cefa221e46f59d3f2f3132556dec6432c |
7 files changed, 104 insertions(+), 151 deletions(-)
src-self-hosted/Compilation.zig+5-4| ... | @@ -1072,13 +1072,14 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void { | ... | @@ -1072,13 +1072,14 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void { |
| 1072 | break :blk digest; | 1072 | break :blk digest; |
| 1073 | }; | 1073 | }; |
| 1074 | 1074 | ||
| 1075 | const full_object_path = if (comp.zig_cache_directory.path) |p| | 1075 | const components = if (comp.zig_cache_directory.path) |p| |
| 1076 | try std.fs.path.join(comp.gpa, &[_][]const u8{ p, "o", &digest, o_basename }) | 1076 | &[_][]const u8{ p, "o", &digest, o_basename } |
| 1077 | else | 1077 | else |
| 1078 | try std.fs.path.join(comp.gpa, &[_][]const u8{ "o", &digest, o_basename }); | 1078 | &[_][]const u8{ "o", &digest, o_basename }; |
| 1079 | |||
| 1079 | c_object.status = .{ | 1080 | c_object.status = .{ |
| 1080 | .success = .{ | 1081 | .success = .{ |
| 1081 | .object_path = full_object_path, | 1082 | .object_path = try std.fs.path.join(comp.gpa, components), |
| 1082 | .lock = ch.toOwnedLock(), | 1083 | .lock = ch.toOwnedLock(), |
| 1083 | }, | 1084 | }, |
| 1084 | }; | 1085 | }; |
src-self-hosted/link.zig+18-16| ... | @@ -126,17 +126,29 @@ pub const File = struct { | ... | @@ -126,17 +126,29 @@ pub const File = struct { |
| 126 | pub fn openPath(allocator: *Allocator, options: Options) !*File { | 126 | pub fn openPath(allocator: *Allocator, options: Options) !*File { |
| 127 | const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm | 127 | const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm |
| 128 | const sub_path = if (use_lld) blk: { | 128 | const sub_path = if (use_lld) blk: { |
| 129 | if (options.module == null) { | ||
| 130 | // No point in opening a file, we would not write anything to it. Initialize with empty. | ||
| 131 | return switch (options.object_format) { | ||
| 132 | .coff, .pe => &(try Coff.createEmpty(allocator, options)).base, | ||
| 133 | .elf => &(try Elf.createEmpty(allocator, options)).base, | ||
| 134 | .macho => &(try MachO.createEmpty(allocator, options)).base, | ||
| 135 | .wasm => &(try Wasm.createEmpty(allocator, options)).base, | ||
| 136 | .c => unreachable, // Reported error earlier. | ||
| 137 | .hex => return error.HexObjectFormatUnimplemented, | ||
| 138 | .raw => return error.RawObjectFormatUnimplemented, | ||
| 139 | }; | ||
| 140 | } | ||
| 129 | // Open a temporary object file, not the final output file because we want to link with LLD. | 141 | // Open a temporary object file, not the final output file because we want to link with LLD. |
| 130 | break :blk try std.fmt.allocPrint(allocator, "{}{}", .{ options.sub_path, options.target.oFileExt() }); | 142 | break :blk try std.fmt.allocPrint(allocator, "{}{}", .{ options.sub_path, options.target.oFileExt() }); |
| 131 | } else options.sub_path; | 143 | } else options.sub_path; |
| 132 | errdefer if (use_lld) allocator.free(sub_path); | 144 | errdefer if (use_lld) allocator.free(sub_path); |
| 133 | 145 | ||
| 134 | const file: *File = switch (options.object_format) { | 146 | const file: *File = switch (options.object_format) { |
| 135 | .coff, .pe => try Coff.openPath(allocator, sub_path, options), | 147 | .coff, .pe => &(try Coff.openPath(allocator, sub_path, options)).base, |
| 136 | .elf => try Elf.openPath(allocator, sub_path, options), | 148 | .elf => &(try Elf.openPath(allocator, sub_path, options)).base, |
| 137 | .macho => try MachO.openPath(allocator, sub_path, options), | 149 | .macho => &(try MachO.openPath(allocator, sub_path, options)).base, |
| 138 | .wasm => try Wasm.openPath(allocator, sub_path, options), | 150 | .wasm => &(try Wasm.openPath(allocator, sub_path, options)).base, |
| 139 | .c => try C.openPath(allocator, sub_path, options), | 151 | .c => &(try C.openPath(allocator, sub_path, options)).base, |
| 140 | .hex => return error.HexObjectFormatUnimplemented, | 152 | .hex => return error.HexObjectFormatUnimplemented, |
| 141 | .raw => return error.RawObjectFormatUnimplemented, | 153 | .raw => return error.RawObjectFormatUnimplemented, |
| 142 | }; | 154 | }; |
| ... | @@ -216,19 +228,9 @@ pub const File = struct { | ... | @@ -216,19 +228,9 @@ pub const File = struct { |
| 216 | } | 228 | } |
| 217 | } | 229 | } |
| 218 | 230 | ||
| 219 | pub fn deinit(base: *File) void { | 231 | pub fn destroy(base: *File) void { |
| 220 | switch (base.tag) { | ||
| 221 | .coff => @fieldParentPtr(Coff, "base", base).deinit(), | ||
| 222 | .elf => @fieldParentPtr(Elf, "base", base).deinit(), | ||
| 223 | .macho => @fieldParentPtr(MachO, "base", base).deinit(), | ||
| 224 | .c => @fieldParentPtr(C, "base", base).deinit(), | ||
| 225 | .wasm => @fieldParentPtr(Wasm, "base", base).deinit(), | ||
| 226 | } | ||
| 227 | if (base.file) |f| f.close(); | 232 | if (base.file) |f| f.close(); |
| 228 | if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path); | 233 | if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path); |
| 229 | } | ||
| 230 | |||
| 231 | pub fn destroy(base: *File) void { | ||
| 232 | switch (base.tag) { | 234 | switch (base.tag) { |
| 233 | .coff => { | 235 | .coff => { |
| 234 | const parent = @fieldParentPtr(Coff, "base", base); | 236 | const parent = @fieldParentPtr(Coff, "base", base); |
src-self-hosted/link/C.zig+2-2| ... | @@ -23,7 +23,7 @@ need_stddef: bool = false, | ... | @@ -23,7 +23,7 @@ need_stddef: bool = false, |
| 23 | need_stdint: bool = false, | 23 | need_stdint: bool = false, |
| 24 | error_msg: *Compilation.ErrorMsg = undefined, | 24 | error_msg: *Compilation.ErrorMsg = undefined, |
| 25 | 25 | ||
| 26 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*File { | 26 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*C { |
| 27 | assert(options.object_format == .c); | 27 | assert(options.object_format == .c); |
| 28 | 28 | ||
| 29 | if (options.use_llvm) return error.LLVMHasNoCBackend; | 29 | if (options.use_llvm) return error.LLVMHasNoCBackend; |
| ... | @@ -48,7 +48,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -48,7 +48,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 48 | .called = std.StringHashMap(void).init(allocator), | 48 | .called = std.StringHashMap(void).init(allocator), |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | return &c_file.base; | 51 | return c_file; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | 54 | pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
src-self-hosted/link/Coff.zig+26-54| ... | @@ -28,7 +28,7 @@ pub const base_tag: link.File.Tag = .coff; | ... | @@ -28,7 +28,7 @@ pub const base_tag: link.File.Tag = .coff; |
| 28 | const msdos_stub = @embedFile("msdos-stub.bin"); | 28 | const msdos_stub = @embedFile("msdos-stub.bin"); |
| 29 | 29 | ||
| 30 | base: link.File, | 30 | base: link.File, |
| 31 | ptr_width: enum { p32, p64 }, | 31 | ptr_width: PtrWidth, |
| 32 | error_flags: link.File.ErrorFlags = .{}, | 32 | error_flags: link.File.ErrorFlags = .{}, |
| 33 | 33 | ||
| 34 | text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, | 34 | text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, |
| ... | @@ -64,6 +64,8 @@ text_section_size_dirty: bool = false, | ... | @@ -64,6 +64,8 @@ text_section_size_dirty: bool = false, |
| 64 | /// and needs to be updated in the optional header. | 64 | /// and needs to be updated in the optional header. |
| 65 | size_of_image_dirty: bool = false, | 65 | size_of_image_dirty: bool = false, |
| 66 | 66 | ||
| 67 | pub const PtrWidth = enum { p32, p64 }; | ||
| 68 | |||
| 67 | pub const TextBlock = struct { | 69 | pub const TextBlock = struct { |
| 68 | /// Offset of the code relative to the start of the text section | 70 | /// Offset of the code relative to the start of the text section |
| 69 | text_offset: u32, | 71 | text_offset: u32, |
| ... | @@ -111,7 +113,7 @@ pub const TextBlock = struct { | ... | @@ -111,7 +113,7 @@ pub const TextBlock = struct { |
| 111 | 113 | ||
| 112 | pub const SrcFn = void; | 114 | pub const SrcFn = void; |
| 113 | 115 | ||
| 114 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*link.File { | 116 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff { |
| 115 | assert(options.object_format == .coff); | 117 | assert(options.object_format == .coff); |
| 116 | 118 | ||
| 117 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO | 119 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO |
| ... | @@ -124,66 +126,17 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -124,66 +126,17 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 124 | }); | 126 | }); |
| 125 | errdefer file.close(); | 127 | errdefer file.close(); |
| 126 | 128 | ||
| 127 | var coff_file = try allocator.create(Coff); | 129 | const self = try createEmpty(allocator, options); |
| 128 | errdefer allocator.destroy(coff_file); | 130 | errdefer self.base.destroy(); |
| 129 | |||
| 130 | coff_file.* = openFile(allocator, file, options) catch |err| switch (err) { | ||
| 131 | error.IncrFailed => try createFile(allocator, file, options), | ||
| 132 | else => |e| return e, | ||
| 133 | }; | ||
| 134 | |||
| 135 | return &coff_file.base; | ||
| 136 | } | ||
| 137 | |||
| 138 | /// Returns error.IncrFailed if incremental update could not be performed. | ||
| 139 | fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !Coff { | ||
| 140 | switch (options.output_mode) { | ||
| 141 | .Exe => {}, | ||
| 142 | .Obj => return error.IncrFailed, | ||
| 143 | .Lib => return error.IncrFailed, | ||
| 144 | } | ||
| 145 | var self: Coff = .{ | ||
| 146 | .base = .{ | ||
| 147 | .file = file, | ||
| 148 | .tag = .coff, | ||
| 149 | .options = options, | ||
| 150 | .allocator = allocator, | ||
| 151 | }, | ||
| 152 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 153 | 32 => .p32, | ||
| 154 | 64 => .p64, | ||
| 155 | else => return error.UnsupportedELFArchitecture, | ||
| 156 | }, | ||
| 157 | }; | ||
| 158 | errdefer self.deinit(); | ||
| 159 | 131 | ||
| 160 | // TODO implement reading the PE/COFF file | 132 | self.base.file = file; |
| 161 | return error.IncrFailed; | ||
| 162 | } | ||
| 163 | 133 | ||
| 164 | /// Truncates the existing file contents and overwrites the contents. | ||
| 165 | /// Returns an error if `file` is not already open with +read +write +seek abilities. | ||
| 166 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Coff { | ||
| 167 | // TODO Write object specific relocations, COFF symbol table, then enable object file output. | 134 | // TODO Write object specific relocations, COFF symbol table, then enable object file output. |
| 168 | switch (options.output_mode) { | 135 | switch (options.output_mode) { |
| 169 | .Exe => {}, | 136 | .Exe => {}, |
| 170 | .Obj => return error.TODOImplementWritingObjFiles, | 137 | .Obj => return error.TODOImplementWritingObjFiles, |
| 171 | .Lib => return error.TODOImplementWritingLibFiles, | 138 | .Lib => return error.TODOImplementWritingLibFiles, |
| 172 | } | 139 | } |
| 173 | var self: Coff = .{ | ||
| 174 | .base = .{ | ||
| 175 | .tag = .coff, | ||
| 176 | .options = options, | ||
| 177 | .allocator = allocator, | ||
| 178 | .file = file, | ||
| 179 | }, | ||
| 180 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 181 | 32 => .p32, | ||
| 182 | 64 => .p64, | ||
| 183 | else => return error.UnsupportedCOFFArchitecture, | ||
| 184 | }, | ||
| 185 | }; | ||
| 186 | errdefer self.deinit(); | ||
| 187 | 140 | ||
| 188 | var coff_file_header_offset: u32 = 0; | 141 | var coff_file_header_offset: u32 = 0; |
| 189 | if (options.output_mode == .Exe) { | 142 | if (options.output_mode == .Exe) { |
| ... | @@ -426,6 +379,25 @@ fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Coff | ... | @@ -426,6 +379,25 @@ fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Coff |
| 426 | return self; | 379 | return self; |
| 427 | } | 380 | } |
| 428 | 381 | ||
| 382 | pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Coff { | ||
| 383 | const ptr_width: PtrWidth = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 384 | 0...32 => .p32, | ||
| 385 | 33...64 => .p64, | ||
| 386 | else => return error.UnsupportedCOFFArchitecture, | ||
| 387 | }; | ||
| 388 | const self = try gpa.create(Coff); | ||
| 389 | self.* = .{ | ||
| 390 | .base = .{ | ||
| 391 | .tag = .coff, | ||
| 392 | .options = options, | ||
| 393 | .allocator = gpa, | ||
| 394 | .file = null, | ||
| 395 | }, | ||
| 396 | .ptr_width = ptr_width, | ||
| 397 | }; | ||
| 398 | return self; | ||
| 399 | } | ||
| 400 | |||
| 429 | pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void { | 401 | pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void { |
| 430 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); | 402 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); |
| 431 | 403 |
src-self-hosted/link/Elf.zig+27-26| ... | @@ -31,7 +31,7 @@ pub const base_tag: File.Tag = .elf; | ... | @@ -31,7 +31,7 @@ pub const base_tag: File.Tag = .elf; |
| 31 | 31 | ||
| 32 | base: File, | 32 | base: File, |
| 33 | 33 | ||
| 34 | ptr_width: enum { p32, p64 }, | 34 | ptr_width: PtrWidth, |
| 35 | 35 | ||
| 36 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 36 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 37 | /// Same order as in the file. | 37 | /// Same order as in the file. |
| ... | @@ -136,6 +136,8 @@ const alloc_den = 3; | ... | @@ -136,6 +136,8 @@ const alloc_den = 3; |
| 136 | const minimum_text_block_size = 64; | 136 | const minimum_text_block_size = 64; |
| 137 | const min_text_capacity = minimum_text_block_size * alloc_num / alloc_den; | 137 | const min_text_capacity = minimum_text_block_size * alloc_num / alloc_den; |
| 138 | 138 | ||
| 139 | pub const PtrWidth = enum { p32, p64 }; | ||
| 140 | |||
| 139 | pub const TextBlock = struct { | 141 | pub const TextBlock = struct { |
| 140 | /// Each decl always gets a local symbol with the fully qualified name. | 142 | /// Each decl always gets a local symbol with the fully qualified name. |
| 141 | /// The vaddr and size are found here directly. | 143 | /// The vaddr and size are found here directly. |
| ... | @@ -222,7 +224,7 @@ pub const SrcFn = struct { | ... | @@ -222,7 +224,7 @@ pub const SrcFn = struct { |
| 222 | }; | 224 | }; |
| 223 | }; | 225 | }; |
| 224 | 226 | ||
| 225 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*File { | 227 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Elf { |
| 226 | assert(options.object_format == .elf); | 228 | assert(options.object_format == .elf); |
| 227 | 229 | ||
| 228 | if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO | 230 | if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO |
| ... | @@ -234,31 +236,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -234,31 +236,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 234 | }); | 236 | }); |
| 235 | errdefer file.close(); | 237 | errdefer file.close(); |
| 236 | 238 | ||
| 237 | var elf_file = try allocator.create(Elf); | 239 | const self = try createEmpty(allocator, options); |
| 238 | errdefer allocator.destroy(elf_file); | 240 | errdefer self.base.destroy(); |
| 239 | |||
| 240 | elf_file.* = try createFile(allocator, file, options); | ||
| 241 | return &elf_file.base; | ||
| 242 | } | ||
| 243 | 241 | ||
| 244 | /// Truncates the existing file contents and overwrites the contents. | 242 | self.base.file = file; |
| 245 | /// Returns an error if `file` is not already open with +read +write +seek abilities. | 243 | self.shdr_table_dirty = true; |
| 246 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf { | ||
| 247 | var self: Elf = .{ | ||
| 248 | .base = .{ | ||
| 249 | .tag = .elf, | ||
| 250 | .options = options, | ||
| 251 | .allocator = allocator, | ||
| 252 | .file = file, | ||
| 253 | }, | ||
| 254 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 255 | 0 ... 32 => .p32, | ||
| 256 | 33 ... 64 => .p64, | ||
| 257 | else => return error.UnsupportedELFArchitecture, | ||
| 258 | }, | ||
| 259 | .shdr_table_dirty = true, | ||
| 260 | }; | ||
| 261 | errdefer self.deinit(); | ||
| 262 | 244 | ||
| 263 | // Index 0 is always a null symbol. | 245 | // Index 0 is always a null symbol. |
| 264 | try self.local_symbols.append(allocator, .{ | 246 | try self.local_symbols.append(allocator, .{ |
| ... | @@ -289,6 +271,25 @@ fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf | ... | @@ -289,6 +271,25 @@ fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf |
| 289 | return self; | 271 | return self; |
| 290 | } | 272 | } |
| 291 | 273 | ||
| 274 | pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf { | ||
| 275 | const ptr_width: PtrWidth = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 276 | 0 ... 32 => .p32, | ||
| 277 | 33 ... 64 => .p64, | ||
| 278 | else => return error.UnsupportedELFArchitecture, | ||
| 279 | }; | ||
| 280 | const self = try gpa.create(Elf); | ||
| 281 | self.* = .{ | ||
| 282 | .base = .{ | ||
| 283 | .tag = .elf, | ||
| 284 | .options = options, | ||
| 285 | .allocator = gpa, | ||
| 286 | .file = null, | ||
| 287 | }, | ||
| 288 | .ptr_width = ptr_width, | ||
| 289 | }; | ||
| 290 | return self; | ||
| 291 | } | ||
| 292 | |||
| 292 | pub fn releaseLock(self: *Elf) void { | 293 | pub fn releaseLock(self: *Elf) void { |
| 293 | if (self.lock) |*lock| { | 294 | if (self.lock) |*lock| { |
| 294 | lock.release(); | 295 | lock.release(); |
src-self-hosted/link/MachO.zig+13-42| ... | @@ -135,7 +135,7 @@ pub const SrcFn = struct { | ... | @@ -135,7 +135,7 @@ pub const SrcFn = struct { |
| 135 | pub const empty = SrcFn{}; | 135 | pub const empty = SrcFn{}; |
| 136 | }; | 136 | }; |
| 137 | 137 | ||
| 138 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*File { | 138 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*MachO { |
| 139 | assert(options.object_format == .macho); | 139 | assert(options.object_format == .macho); |
| 140 | 140 | ||
| 141 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForMachO; // TODO | 141 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForMachO; // TODO |
| ... | @@ -148,61 +148,32 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -148,61 +148,32 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 148 | }); | 148 | }); |
| 149 | errdefer file.close(); | 149 | errdefer file.close(); |
| 150 | 150 | ||
| 151 | var macho_file = try allocator.create(MachO); | 151 | const self = try createEmpty(allocator, options); |
| 152 | errdefer allocator.destroy(macho_file); | 152 | errdefer self.base.destroy(); |
| 153 | 153 | ||
| 154 | macho_file.* = openFile(allocator, file, options) catch |err| switch (err) { | 154 | self.base.file = file; |
| 155 | error.IncrFailed => try createFile(allocator, file, options), | ||
| 156 | else => |e| return e, | ||
| 157 | }; | ||
| 158 | |||
| 159 | return &macho_file.base; | ||
| 160 | } | ||
| 161 | 155 | ||
| 162 | /// Returns error.IncrFailed if incremental update could not be performed. | ||
| 163 | fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO { | ||
| 164 | switch (options.output_mode) { | 156 | switch (options.output_mode) { |
| 165 | .Exe => {}, | 157 | .Exe => {}, |
| 166 | .Obj => {}, | 158 | .Obj => {}, |
| 167 | .Lib => return error.IncrFailed, | 159 | .Lib => return error.TODOImplementWritingLibFiles, |
| 168 | } | 160 | } |
| 169 | var self: MachO = .{ | ||
| 170 | .base = .{ | ||
| 171 | .file = file, | ||
| 172 | .tag = .macho, | ||
| 173 | .options = options, | ||
| 174 | .allocator = allocator, | ||
| 175 | }, | ||
| 176 | }; | ||
| 177 | errdefer self.deinit(); | ||
| 178 | 161 | ||
| 179 | // TODO implement reading the macho file | 162 | try self.populateMissingMetadata(); |
| 180 | return error.IncrFailed; | ||
| 181 | //try self.populateMissingMetadata(); | ||
| 182 | //return self; | ||
| 183 | } | ||
| 184 | 163 | ||
| 185 | /// Truncates the existing file contents and overwrites the contents. | 164 | return self; |
| 186 | /// Returns an error if `file` is not already open with +read +write +seek abilities. | 165 | } |
| 187 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO { | ||
| 188 | switch (options.output_mode) { | ||
| 189 | .Exe => {}, | ||
| 190 | .Obj => {}, | ||
| 191 | .Lib => return error.TODOImplementWritingLibFiles, | ||
| 192 | } | ||
| 193 | 166 | ||
| 194 | var self: MachO = .{ | 167 | pub fn createEmpty(gpa: *Allocator, options: link.Options) !*MachO { |
| 168 | const self = try gpa.create(MachO); | ||
| 169 | self.* = .{ | ||
| 195 | .base = .{ | 170 | .base = .{ |
| 196 | .file = file, | ||
| 197 | .tag = .macho, | 171 | .tag = .macho, |
| 198 | .options = options, | 172 | .options = options, |
| 199 | .allocator = allocator, | 173 | .allocator = gpa, |
| 174 | .file = null, | ||
| 200 | }, | 175 | }, |
| 201 | }; | 176 | }; |
| 202 | errdefer self.deinit(); | ||
| 203 | |||
| 204 | try self.populateMissingMetadata(); | ||
| 205 | |||
| 206 | return self; | 177 | return self; |
| 207 | } | 178 | } |
| 208 | 179 |
src-self-hosted/link/Wasm.zig+13-7| ... | @@ -50,7 +50,7 @@ base: link.File, | ... | @@ -50,7 +50,7 @@ base: link.File, |
| 50 | /// TODO: can/should we access some data structure in Module directly? | 50 | /// TODO: can/should we access some data structure in Module directly? |
| 51 | funcs: std.ArrayListUnmanaged(*Module.Decl) = .{}, | 51 | funcs: std.ArrayListUnmanaged(*Module.Decl) = .{}, |
| 52 | 52 | ||
| 53 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*link.File { | 53 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Wasm { |
| 54 | assert(options.object_format == .wasm); | 54 | assert(options.object_format == .wasm); |
| 55 | 55 | ||
| 56 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForWasm; // TODO | 56 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForWasm; // TODO |
| ... | @@ -60,21 +60,27 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -60,21 +60,27 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 60 | const file = try options.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true }); | 60 | const file = try options.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true }); |
| 61 | errdefer file.close(); | 61 | errdefer file.close(); |
| 62 | 62 | ||
| 63 | const wasm = try allocator.create(Wasm); | 63 | const wasm = try createEmpty(allocator, options); |
| 64 | errdefer allocator.destroy(wasm); | 64 | errdefer wasm.base.destroy(); |
| 65 | |||
| 66 | wasm.base.file = file; | ||
| 65 | 67 | ||
| 66 | try file.writeAll(&(spec.magic ++ spec.version)); | 68 | try file.writeAll(&(spec.magic ++ spec.version)); |
| 67 | 69 | ||
| 70 | return wasm; | ||
| 71 | } | ||
| 72 | |||
| 73 | pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Wasm { | ||
| 74 | const wasm = try gpa.create(Wasm); | ||
| 68 | wasm.* = .{ | 75 | wasm.* = .{ |
| 69 | .base = .{ | 76 | .base = .{ |
| 70 | .tag = .wasm, | 77 | .tag = .wasm, |
| 71 | .options = options, | 78 | .options = options, |
| 72 | .file = file, | 79 | .file = null, |
| 73 | .allocator = allocator, | 80 | .allocator = gpa, |
| 74 | }, | 81 | }, |
| 75 | }; | 82 | }; |
| 76 | 83 | return wasm; | |
| 77 | return &wasm.base; | ||
| 78 | } | 84 | } |
| 79 | 85 | ||
| 80 | pub fn deinit(self: *Wasm) void { | 86 | pub fn deinit(self: *Wasm) void { |