| author | |
| committer | |
| log | b37955f2739dc20f65cc8d352cab98dc07f44b5f |
| tree | 715317e4651dd899020dc3880abebad9aa679c2a |
| parent | 193ad413f03322b047bbfe17c4b2b368ba6bc097 |
For when linking with LLD, we always create an object rather than going
straight to the executable. Next step is putting this object on the LLD
linker line.8 files changed, 78 insertions(+), 76 deletions(-)
src-self-hosted/Module.zig+6-7| ... | @@ -35,8 +35,6 @@ root_pkg: ?*Package, | ... | @@ -35,8 +35,6 @@ root_pkg: ?*Package, |
| 35 | /// The `Scope` is either a `Scope.ZIRModule` or `Scope.File`. | 35 | /// The `Scope` is either a `Scope.ZIRModule` or `Scope.File`. |
| 36 | root_scope: *Scope, | 36 | root_scope: *Scope, |
| 37 | bin_file: *link.File, | 37 | bin_file: *link.File, |
| 38 | bin_file_dir: std.fs.Dir, | ||
| 39 | bin_file_path: []const u8, | ||
| 40 | /// It's rare for a decl to be exported, so we save memory by having a sparse map of | 38 | /// It's rare for a decl to be exported, so we save memory by having a sparse map of |
| 41 | /// Decl pointers to details about them being exported. | 39 | /// Decl pointers to details about them being exported. |
| 42 | /// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table. | 40 | /// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table. |
| ... | @@ -934,6 +932,7 @@ pub const InitOptions = struct { | ... | @@ -934,6 +932,7 @@ pub const InitOptions = struct { |
| 934 | root_pkg: ?*Package, | 932 | root_pkg: ?*Package, |
| 935 | output_mode: std.builtin.OutputMode, | 933 | output_mode: std.builtin.OutputMode, |
| 936 | rand: *std.rand.Random, | 934 | rand: *std.rand.Random, |
| 935 | bin_file_dir_path: ?[]const u8 = null, | ||
| 937 | bin_file_dir: ?std.fs.Dir = null, | 936 | bin_file_dir: ?std.fs.Dir = null, |
| 938 | bin_file_path: []const u8, | 937 | bin_file_path: []const u8, |
| 939 | emit_h: ?[]const u8 = null, | 938 | emit_h: ?[]const u8 = null, |
| ... | @@ -1018,8 +1017,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Module { | ... | @@ -1018,8 +1017,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Module { |
| 1018 | break :blk false; | 1017 | break :blk false; |
| 1019 | }; | 1018 | }; |
| 1020 | 1019 | ||
| 1021 | const bin_file_dir = options.bin_file_dir orelse std.fs.cwd(); | 1020 | const bin_file = try link.File.openPath(gpa, .{ |
| 1022 | const bin_file = try link.File.openPath(gpa, bin_file_dir, options.bin_file_path, .{ | 1021 | .dir = options.bin_file_dir orelse std.fs.cwd(), |
| 1022 | .dir_path = options.bin_file_dir_path, | ||
| 1023 | .sub_path = options.bin_file_path, | ||
| 1023 | .root_name = root_name, | 1024 | .root_name = root_name, |
| 1024 | .root_pkg = options.root_pkg, | 1025 | .root_pkg = options.root_pkg, |
| 1025 | .target = options.target, | 1026 | .target = options.target, |
| ... | @@ -1165,8 +1166,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Module { | ... | @@ -1165,8 +1166,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Module { |
| 1165 | .root_name = root_name, | 1166 | .root_name = root_name, |
| 1166 | .root_pkg = options.root_pkg, | 1167 | .root_pkg = options.root_pkg, |
| 1167 | .root_scope = root_scope, | 1168 | .root_scope = root_scope, |
| 1168 | .bin_file_dir = bin_file_dir, | ||
| 1169 | .bin_file_path = options.bin_file_path, | ||
| 1170 | .bin_file = bin_file, | 1169 | .bin_file = bin_file, |
| 1171 | .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa), | 1170 | .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa), |
| 1172 | .keep_source_files_loaded = options.keep_source_files_loaded, | 1171 | .keep_source_files_loaded = options.keep_source_files_loaded, |
| ... | @@ -1350,7 +1349,7 @@ pub fn makeBinFileExecutable(self: *Module) !void { | ... | @@ -1350,7 +1349,7 @@ pub fn makeBinFileExecutable(self: *Module) !void { |
| 1350 | } | 1349 | } |
| 1351 | 1350 | ||
| 1352 | pub fn makeBinFileWritable(self: *Module) !void { | 1351 | pub fn makeBinFileWritable(self: *Module) !void { |
| 1353 | return self.bin_file.makeWritable(self.bin_file_dir, self.bin_file_path); | 1352 | return self.bin_file.makeWritable(); |
| 1354 | } | 1353 | } |
| 1355 | 1354 | ||
| 1356 | pub fn totalErrorCount(self: *Module) usize { | 1355 | pub fn totalErrorCount(self: *Module) usize { |
src-self-hosted/link.zig+41-14| ... | @@ -10,6 +10,12 @@ const build_options = @import("build_options"); | ... | @@ -10,6 +10,12 @@ const build_options = @import("build_options"); |
| 10 | pub const producer_string = if (std.builtin.is_test) "zig test" else "zig " ++ build_options.version; | 10 | pub const producer_string = if (std.builtin.is_test) "zig test" else "zig " ++ build_options.version; |
| 11 | 11 | ||
| 12 | pub const Options = struct { | 12 | pub const Options = struct { |
| 13 | dir: fs.Dir, | ||
| 14 | /// Redundant with dir. Needed when linking with LLD because we have to pass paths rather | ||
| 15 | /// than file descriptors. `null` means cwd. OK to pass `null` when `use_lld` is `false`. | ||
| 16 | dir_path: ?[]const u8, | ||
| 17 | /// Path to the output file, relative to dir. | ||
| 18 | sub_path: []const u8, | ||
| 13 | target: std.Target, | 19 | target: std.Target, |
| 14 | output_mode: std.builtin.OutputMode, | 20 | output_mode: std.builtin.OutputMode, |
| 15 | link_mode: std.builtin.LinkMode, | 21 | link_mode: std.builtin.LinkMode, |
| ... | @@ -56,6 +62,9 @@ pub const File = struct { | ... | @@ -56,6 +62,9 @@ pub const File = struct { |
| 56 | options: Options, | 62 | options: Options, |
| 57 | file: ?fs.File, | 63 | file: ?fs.File, |
| 58 | allocator: *Allocator, | 64 | allocator: *Allocator, |
| 65 | /// When linking with LLD, this linker code will output an object file only at | ||
| 66 | /// this location, and then this path can be placed on the LLD linker line. | ||
| 67 | intermediary_basename: ?[]const u8 = null, | ||
| 59 | 68 | ||
| 60 | pub const LinkBlock = union { | 69 | pub const LinkBlock = union { |
| 61 | elf: Elf.TextBlock, | 70 | elf: Elf.TextBlock, |
| ... | @@ -90,16 +99,29 @@ pub const File = struct { | ... | @@ -90,16 +99,29 @@ pub const File = struct { |
| 90 | /// incremental linking fails, falls back to truncating the file and | 99 | /// incremental linking fails, falls back to truncating the file and |
| 91 | /// rewriting it. A malicious file is detected as incremental link failure | 100 | /// rewriting it. A malicious file is detected as incremental link failure |
| 92 | /// and does not cause Illegal Behavior. This operation is not atomic. | 101 | /// and does not cause Illegal Behavior. This operation is not atomic. |
| 93 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File { | 102 | pub fn openPath(allocator: *Allocator, options: Options) !*File { |
| 94 | switch (options.object_format) { | 103 | const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm |
| 95 | .coff, .pe => return Coff.openPath(allocator, dir, sub_path, options), | 104 | const sub_path = if (use_lld) blk: { |
| 96 | .elf => return Elf.openPath(allocator, dir, sub_path, options), | 105 | // Open a temporary object file, not the final output file because we want to link with LLD. |
| 97 | .macho => return MachO.openPath(allocator, dir, sub_path, options), | 106 | break :blk try std.fmt.allocPrint(allocator, "{}{}", .{ options.sub_path, options.target.oFileExt() }); |
| 98 | .wasm => return Wasm.openPath(allocator, dir, sub_path, options), | 107 | } else options.sub_path; |
| 99 | .c => return C.openPath(allocator, dir, sub_path, options), | 108 | errdefer if (use_lld) allocator.free(sub_path); |
| 109 | |||
| 110 | const file: *File = switch (options.object_format) { | ||
| 111 | .coff, .pe => try Coff.openPath(allocator, sub_path, options), | ||
| 112 | .elf => try Elf.openPath(allocator, sub_path, options), | ||
| 113 | .macho => try MachO.openPath(allocator, sub_path, options), | ||
| 114 | .wasm => try Wasm.openPath(allocator, sub_path, options), | ||
| 115 | .c => try C.openPath(allocator, sub_path, options), | ||
| 100 | .hex => return error.HexObjectFormatUnimplemented, | 116 | .hex => return error.HexObjectFormatUnimplemented, |
| 101 | .raw => return error.RawObjectFormatUnimplemented, | 117 | .raw => return error.RawObjectFormatUnimplemented, |
| 118 | }; | ||
| 119 | |||
| 120 | if (use_lld) { | ||
| 121 | file.intermediary_basename = sub_path; | ||
| 102 | } | 122 | } |
| 123 | |||
| 124 | return file; | ||
| 103 | } | 125 | } |
| 104 | 126 | ||
| 105 | pub fn cast(base: *File, comptime T: type) ?*T { | 127 | pub fn cast(base: *File, comptime T: type) ?*T { |
| ... | @@ -109,11 +131,11 @@ pub const File = struct { | ... | @@ -109,11 +131,11 @@ pub const File = struct { |
| 109 | return @fieldParentPtr(T, "base", base); | 131 | return @fieldParentPtr(T, "base", base); |
| 110 | } | 132 | } |
| 111 | 133 | ||
| 112 | pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void { | 134 | pub fn makeWritable(base: *File) !void { |
| 113 | switch (base.tag) { | 135 | switch (base.tag) { |
| 114 | .coff, .elf, .macho => { | 136 | .coff, .elf, .macho => { |
| 115 | if (base.file != null) return; | 137 | if (base.file != null) return; |
| 116 | base.file = try dir.createFile(sub_path, .{ | 138 | base.file = try base.options.dir.createFile(base.options.sub_path, .{ |
| 117 | .truncate = false, | 139 | .truncate = false, |
| 118 | .read = true, | 140 | .read = true, |
| 119 | .mode = determineMode(base.options), | 141 | .mode = determineMode(base.options), |
| ... | @@ -125,12 +147,16 @@ pub const File = struct { | ... | @@ -125,12 +147,16 @@ pub const File = struct { |
| 125 | 147 | ||
| 126 | pub fn makeExecutable(base: *File) !void { | 148 | pub fn makeExecutable(base: *File) !void { |
| 127 | switch (base.tag) { | 149 | switch (base.tag) { |
| 128 | .c => unreachable, | 150 | .coff, .elf, .macho => if (base.file) |f| { |
| 129 | .wasm => {}, | 151 | if (base.intermediary_basename != null) { |
| 130 | else => if (base.file) |f| { | 152 | // The file we have open is not the final file that we want to |
| 153 | // make executable, so we don't have to close it. | ||
| 154 | return; | ||
| 155 | } | ||
| 131 | f.close(); | 156 | f.close(); |
| 132 | base.file = null; | 157 | base.file = null; |
| 133 | }, | 158 | }, |
| 159 | .c, .wasm => {}, | ||
| 134 | } | 160 | } |
| 135 | } | 161 | } |
| 136 | 162 | ||
| ... | @@ -167,7 +193,6 @@ pub const File = struct { | ... | @@ -167,7 +193,6 @@ pub const File = struct { |
| 167 | } | 193 | } |
| 168 | 194 | ||
| 169 | pub fn deinit(base: *File) void { | 195 | pub fn deinit(base: *File) void { |
| 170 | if (base.file) |f| f.close(); | ||
| 171 | switch (base.tag) { | 196 | switch (base.tag) { |
| 172 | .coff => @fieldParentPtr(Coff, "base", base).deinit(), | 197 | .coff => @fieldParentPtr(Coff, "base", base).deinit(), |
| 173 | .elf => @fieldParentPtr(Elf, "base", base).deinit(), | 198 | .elf => @fieldParentPtr(Elf, "base", base).deinit(), |
| ... | @@ -175,6 +200,8 @@ pub const File = struct { | ... | @@ -175,6 +200,8 @@ pub const File = struct { |
| 175 | .c => @fieldParentPtr(C, "base", base).deinit(), | 200 | .c => @fieldParentPtr(C, "base", base).deinit(), |
| 176 | .wasm => @fieldParentPtr(Wasm, "base", base).deinit(), | 201 | .wasm => @fieldParentPtr(Wasm, "base", base).deinit(), |
| 177 | } | 202 | } |
| 203 | if (base.file) |f| f.close(); | ||
| 204 | if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path); | ||
| 178 | } | 205 | } |
| 179 | 206 | ||
| 180 | pub fn destroy(base: *File) void { | 207 | pub fn destroy(base: *File) void { |
| ... | @@ -292,7 +319,7 @@ pub fn determineMode(options: Options) fs.File.Mode { | ... | @@ -292,7 +319,7 @@ pub fn determineMode(options: Options) fs.File.Mode { |
| 292 | // more leniently. As another data point, C's fopen seems to open files with the | 319 | // more leniently. As another data point, C's fopen seems to open files with the |
| 293 | // 666 mode. | 320 | // 666 mode. |
| 294 | const executable_mode = if (std.Target.current.os.tag == .windows) 0 else 0o777; | 321 | const executable_mode = if (std.Target.current.os.tag == .windows) 0 else 0o777; |
| 295 | switch (options.output_mode) { | 322 | switch (options.effectiveOutputMode()) { |
| 296 | .Lib => return switch (options.link_mode) { | 323 | .Lib => return switch (options.link_mode) { |
| 297 | .Dynamic => executable_mode, | 324 | .Dynamic => executable_mode, |
| 298 | .Static => fs.File.default_mode, | 325 | .Static => fs.File.default_mode, |
src-self-hosted/link/C.zig+4-4| ... | @@ -22,13 +22,13 @@ need_stddef: bool = false, | ... | @@ -22,13 +22,13 @@ need_stddef: bool = false, |
| 22 | need_stdint: bool = false, | 22 | need_stdint: bool = false, |
| 23 | error_msg: *Module.ErrorMsg = undefined, | 23 | error_msg: *Module.ErrorMsg = undefined, |
| 24 | 24 | ||
| 25 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File { | 25 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*File { |
| 26 | assert(options.object_format == .c); | 26 | assert(options.object_format == .c); |
| 27 | 27 | ||
| 28 | if (options.use_llvm) return error.LLVM_HasNoCBackend; | 28 | if (options.use_llvm) return error.LLVMHasNoCBackend; |
| 29 | if (options.use_lld) return error.LLD_HasNoCBackend; | 29 | if (options.use_lld) return error.LLDHasNoCBackend; |
| 30 | 30 | ||
| 31 | const file = try dir.createFile(sub_path, .{ .truncate = true, .read = true, .mode = link.determineMode(options) }); | 31 | const file = try options.dir.createFile(sub_path, .{ .truncate = true, .read = true, .mode = link.determineMode(options) }); |
| 32 | errdefer file.close(); | 32 | errdefer file.close(); |
| 33 | 33 | ||
| 34 | var c_file = try allocator.create(C); | 34 | var c_file = try allocator.create(C); |
src-self-hosted/link/Coff.zig+7-3| ... | @@ -19,7 +19,7 @@ const file_alignment = 512; | ... | @@ -19,7 +19,7 @@ const file_alignment = 512; |
| 19 | const image_base = 0x400_000; | 19 | const image_base = 0x400_000; |
| 20 | const section_table_size = 2 * 40; | 20 | const section_table_size = 2 * 40; |
| 21 | comptime { | 21 | comptime { |
| 22 | std.debug.assert(std.mem.isAligned(image_base, section_alignment)); | 22 | assert(std.mem.isAligned(image_base, section_alignment)); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | pub const base_tag: link.File.Tag = .coff; | 25 | pub const base_tag: link.File.Tag = .coff; |
| ... | @@ -110,13 +110,17 @@ pub const TextBlock = struct { | ... | @@ -110,13 +110,17 @@ pub const TextBlock = struct { |
| 110 | 110 | ||
| 111 | pub const SrcFn = void; | 111 | pub const SrcFn = void; |
| 112 | 112 | ||
| 113 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*link.File { | 113 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*link.File { |
| 114 | assert(options.object_format == .coff); | 114 | assert(options.object_format == .coff); |
| 115 | 115 | ||
| 116 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO | 116 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO |
| 117 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO | 117 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO |
| 118 | 118 | ||
| 119 | const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) }); | 119 | const file = try options.dir.createFile(sub_path, .{ |
| 120 | .truncate = false, | ||
| 121 | .read = true, | ||
| 122 | .mode = link.determineMode(options), | ||
| 123 | }); | ||
| 120 | errdefer file.close(); | 124 | errdefer file.close(); |
| 121 | 125 | ||
| 122 | var coff_file = try allocator.create(Coff); | 126 | var coff_file = try allocator.create(Coff); |
src-self-hosted/link/Elf.zig+11-44| ... | @@ -216,65 +216,28 @@ pub const SrcFn = struct { | ... | @@ -216,65 +216,28 @@ pub const SrcFn = struct { |
| 216 | }; | 216 | }; |
| 217 | }; | 217 | }; |
| 218 | 218 | ||
| 219 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File { | 219 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*File { |
| 220 | assert(options.object_format == .elf); | 220 | assert(options.object_format == .elf); |
| 221 | 221 | ||
| 222 | if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO | 222 | if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO |
| 223 | 223 | ||
| 224 | if (build_options.have_llvm and options.use_lld) { | 224 | const file = try options.dir.createFile(sub_path, .{ |
| 225 | std.debug.print("TODO open a temporary object file, not the final output file because we want to link with LLD\n", .{}); | 225 | .truncate = false, |
| 226 | } | 226 | .read = true, |
| 227 | 227 | .mode = link.determineMode(options), | |
| 228 | const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) }); | 228 | }); |
| 229 | errdefer file.close(); | 229 | errdefer file.close(); |
| 230 | 230 | ||
| 231 | var elf_file = try allocator.create(Elf); | 231 | var elf_file = try allocator.create(Elf); |
| 232 | errdefer allocator.destroy(elf_file); | 232 | errdefer allocator.destroy(elf_file); |
| 233 | 233 | ||
| 234 | elf_file.* = openFile(allocator, file, options) catch |err| switch (err) { | 234 | elf_file.* = try createFile(allocator, file, options); |
| 235 | error.IncrFailed => try createFile(allocator, file, options), | ||
| 236 | else => |e| return e, | ||
| 237 | }; | ||
| 238 | |||
| 239 | return &elf_file.base; | 235 | return &elf_file.base; |
| 240 | } | 236 | } |
| 241 | 237 | ||
| 242 | /// Returns error.IncrFailed if incremental update could not be performed. | ||
| 243 | fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf { | ||
| 244 | switch (options.effectiveOutputMode()) { | ||
| 245 | .Exe => {}, | ||
| 246 | .Obj => {}, | ||
| 247 | .Lib => return error.IncrFailed, | ||
| 248 | } | ||
| 249 | var self: Elf = .{ | ||
| 250 | .base = .{ | ||
| 251 | .file = file, | ||
| 252 | .tag = .elf, | ||
| 253 | .options = options, | ||
| 254 | .allocator = allocator, | ||
| 255 | }, | ||
| 256 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 257 | 0 ... 32 => .p32, | ||
| 258 | 33 ... 64 => .p64, | ||
| 259 | else => return error.UnsupportedELFArchitecture, | ||
| 260 | }, | ||
| 261 | }; | ||
| 262 | errdefer self.deinit(); | ||
| 263 | |||
| 264 | // TODO implement reading the elf file | ||
| 265 | return error.IncrFailed; | ||
| 266 | //try self.populateMissingMetadata(); | ||
| 267 | //return self; | ||
| 268 | } | ||
| 269 | |||
| 270 | /// Truncates the existing file contents and overwrites the contents. | 238 | /// Truncates the existing file contents and overwrites the contents. |
| 271 | /// Returns an error if `file` is not already open with +read +write +seek abilities. | 239 | /// Returns an error if `file` is not already open with +read +write +seek abilities. |
| 272 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf { | 240 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf { |
| 273 | switch (options.effectiveOutputMode()) { | ||
| 274 | .Exe => {}, | ||
| 275 | .Obj => {}, | ||
| 276 | .Lib => return error.TODOImplementWritingLibFiles, | ||
| 277 | } | ||
| 278 | var self: Elf = .{ | 241 | var self: Elf = .{ |
| 279 | .base = .{ | 242 | .base = .{ |
| 280 | .tag = .elf, | 243 | .tag = .elf, |
| ... | @@ -753,6 +716,10 @@ pub fn flush(self: *Elf, module: *Module) !void { | ... | @@ -753,6 +716,10 @@ pub fn flush(self: *Elf, module: *Module) !void { |
| 753 | } | 716 | } |
| 754 | std.debug.print("TODO create an LLD command line and invoke it\n", .{}); | 717 | std.debug.print("TODO create an LLD command line and invoke it\n", .{}); |
| 755 | } else { | 718 | } else { |
| 719 | switch (self.base.options.effectiveOutputMode()) { | ||
| 720 | .Exe, .Obj => {}, | ||
| 721 | .Lib => return error.TODOImplementWritingLibFiles, | ||
| 722 | } | ||
| 756 | return self.flushInner(module); | 723 | return self.flushInner(module); |
| 757 | } | 724 | } |
| 758 | } | 725 | } |
src-self-hosted/link/MachO.zig+6-2| ... | @@ -134,13 +134,17 @@ pub const SrcFn = struct { | ... | @@ -134,13 +134,17 @@ pub const SrcFn = struct { |
| 134 | pub const empty = SrcFn{}; | 134 | pub const empty = SrcFn{}; |
| 135 | }; | 135 | }; |
| 136 | 136 | ||
| 137 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File { | 137 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*File { |
| 138 | assert(options.object_format == .macho); | 138 | assert(options.object_format == .macho); |
| 139 | 139 | ||
| 140 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForMachO; // TODO | 140 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForMachO; // TODO |
| 141 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForMachO; // TODO | 141 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForMachO; // TODO |
| 142 | 142 | ||
| 143 | const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) }); | 143 | const file = try options.dir.createFile(sub_path, .{ |
| 144 | .truncate = false, | ||
| 145 | .read = true, | ||
| 146 | .mode = link.determineMode(options), | ||
| 147 | }); | ||
| 144 | errdefer file.close(); | 148 | errdefer file.close(); |
| 145 | 149 | ||
| 146 | var macho_file = try allocator.create(MachO); | 150 | var macho_file = try allocator.create(MachO); |
src-self-hosted/link/Wasm.zig+2-2| ... | @@ -49,14 +49,14 @@ base: link.File, | ... | @@ -49,14 +49,14 @@ base: link.File, |
| 49 | /// TODO: can/should we access some data structure in Module directly? | 49 | /// TODO: can/should we access some data structure in Module directly? |
| 50 | funcs: std.ArrayListUnmanaged(*Module.Decl) = .{}, | 50 | funcs: std.ArrayListUnmanaged(*Module.Decl) = .{}, |
| 51 | 51 | ||
| 52 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*link.File { | 52 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*link.File { |
| 53 | assert(options.object_format == .wasm); | 53 | assert(options.object_format == .wasm); |
| 54 | 54 | ||
| 55 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForWasm; // TODO | 55 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForWasm; // TODO |
| 56 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForWasm; // TODO | 56 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForWasm; // TODO |
| 57 | 57 | ||
| 58 | // TODO: read the file and keep vaild parts instead of truncating | 58 | // TODO: read the file and keep vaild parts instead of truncating |
| 59 | const file = try dir.createFile(sub_path, .{ .truncate = true, .read = true }); | 59 | const file = try options.dir.createFile(sub_path, .{ .truncate = true, .read = true }); |
| 60 | errdefer file.close(); | 60 | errdefer file.close(); |
| 61 | 61 | ||
| 62 | const wasm = try allocator.create(Wasm); | 62 | const wasm = try allocator.create(Wasm); |
src-self-hosted/main.zig+1| ... | @@ -1000,6 +1000,7 @@ pub fn buildOutputType( | ... | @@ -1000,6 +1000,7 @@ pub fn buildOutputType( |
| 1000 | .target = target_info.target, | 1000 | .target = target_info.target, |
| 1001 | .output_mode = output_mode, | 1001 | .output_mode = output_mode, |
| 1002 | .root_pkg = root_pkg, | 1002 | .root_pkg = root_pkg, |
| 1003 | .bin_file_dir_path = null, | ||
| 1003 | .bin_file_dir = fs.cwd(), | 1004 | .bin_file_dir = fs.cwd(), |
| 1004 | .bin_file_path = bin_path, | 1005 | .bin_file_path = bin_path, |
| 1005 | .link_mode = link_mode, | 1006 | .link_mode = link_mode, |