| ... | ... | @@ -164,13 +164,21 @@ pub const PtrWidth = enum { p32, p64 }; |
| 164 | 164 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Elf { |
| 165 | 165 | assert(options.target.ofmt == .elf); |
| 166 | 166 | |
| 167 | | if (options.use_llvm) { |
| 168 | | return createEmpty(allocator, options); |
| 169 | | } |
| 170 | | |
| 171 | 167 | const self = try createEmpty(allocator, options); |
| 172 | 168 | errdefer self.base.destroy(); |
| 173 | 169 | |
| 170 | if (options.use_llvm) { |
| 171 | const use_lld = build_options.have_llvm and self.base.options.use_lld; |
| 172 | if (use_lld) return self; |
| 173 | |
| 174 | if (options.module != null) { |
| 175 | self.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{ |
| 176 | sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), |
| 177 | }); |
| 178 | } |
| 179 | } |
| 180 | errdefer if (self.base.intermediary_basename) |path| allocator.free(path); |
| 181 | |
| 174 | 182 | self.base.file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 175 | 183 | .truncate = false, |
| 176 | 184 | .read = true, |
| ... | ... | @@ -389,8 +397,6 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u32) u64 { |
| 389 | 397 | } |
| 390 | 398 | |
| 391 | 399 | pub fn populateMissingMetadata(self: *Elf) !void { |
| 392 | | assert(self.llvm_object == null); |
| 393 | | |
| 394 | 400 | const gpa = self.base.allocator; |
| 395 | 401 | const small_ptr = switch (self.ptr_width) { |
| 396 | 402 | .p32 => true, |
| ... | ... | @@ -962,7 +968,7 @@ pub fn markDirty(self: *Elf, shdr_index: u16, phdr_index: ?u16) void { |
| 962 | 968 | pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| 963 | 969 | if (self.base.options.emit == null) { |
| 964 | 970 | if (self.llvm_object) |llvm_object| { |
| 965 | | return try llvm_object.flushModule(comp, prog_node); |
| 971 | try llvm_object.flushModule(comp, prog_node); |
| 966 | 972 | } |
| 967 | 973 | return; |
| 968 | 974 | } |
| ... | ... | @@ -981,7 +987,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 981 | 987 | defer tracy.end(); |
| 982 | 988 | |
| 983 | 989 | if (self.llvm_object) |llvm_object| { |
| 984 | | return try llvm_object.flushModule(comp, prog_node); |
| 990 | try llvm_object.flushModule(comp, prog_node); |
| 991 | |
| 992 | const use_lld = build_options.have_llvm and self.base.options.use_lld; |
| 993 | if (use_lld) return; |
| 985 | 994 | } |
| 986 | 995 | |
| 987 | 996 | const gpa = self.base.allocator; |
| ... | ... | @@ -989,9 +998,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 989 | 998 | sub_prog_node.activate(); |
| 990 | 999 | defer sub_prog_node.end(); |
| 991 | 1000 | |
| 992 | | // TODO This linker code currently assumes there is only 1 compilation unit and it |
| 993 | | // corresponds to the Zig source code. |
| 994 | | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 1001 | var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); |
| 1002 | defer arena_allocator.deinit(); |
| 1003 | const arena = arena_allocator.allocator(); |
| 1004 | |
| 1005 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 1006 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); |
| 995 | 1007 | |
| 996 | 1008 | const compiler_rt_path: ?[]const u8 = blk: { |
| 997 | 1009 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| ... | ... | @@ -1002,8 +1014,19 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1002 | 1014 | |
| 1003 | 1015 | // Here we will parse input positional and library files (if referenced). |
| 1004 | 1016 | // This will roughly match in any linker backend we support. |
| 1005 | | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); |
| 1006 | | defer positionals.deinit(); |
| 1017 | var positionals = std.ArrayList(Compilation.LinkObject).init(arena); |
| 1018 | |
| 1019 | if (self.base.intermediary_basename) |path| { |
| 1020 | const full_path = blk: { |
| 1021 | if (fs.path.dirname(full_out_path)) |dirname| { |
| 1022 | break :blk try fs.path.join(arena, &.{ dirname, path }); |
| 1023 | } else { |
| 1024 | break :blk path; |
| 1025 | } |
| 1026 | }; |
| 1027 | try positionals.append(.{ .path = full_path }); |
| 1028 | } |
| 1029 | |
| 1007 | 1030 | try positionals.ensureUnusedCapacity(self.base.options.objects.len); |
| 1008 | 1031 | positionals.appendSliceAssumeCapacity(self.base.options.objects); |
| 1009 | 1032 | |
| ... | ... | @@ -1025,6 +1048,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1025 | 1048 | |
| 1026 | 1049 | // Handle any lazy symbols that were emitted by incremental compilation. |
| 1027 | 1050 | if (self.lazy_syms.getPtr(.none)) |metadata| { |
| 1051 | const module = self.base.options.module.?; |
| 1052 | |
| 1028 | 1053 | // Most lazy symbols can be updated on first use, but |
| 1029 | 1054 | // anyerror needs to wait for everything to be flushed. |
| 1030 | 1055 | if (metadata.text_state != .unused) self.updateLazySymbol( |
| ... | ... | @@ -1051,7 +1076,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1051 | 1076 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 1052 | 1077 | |
| 1053 | 1078 | if (self.dwarf) |*dw| { |
| 1054 | | try dw.flushModule(module); |
| 1079 | try dw.flushModule(self.base.options.module.?); |
| 1055 | 1080 | } |
| 1056 | 1081 | |
| 1057 | 1082 | // If we haven't already, create a linker-generated input file comprising of |
| ... | ... | @@ -1125,7 +1150,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1125 | 1150 | const text_phdr = &self.phdrs.items[self.phdr_load_re_index.?]; |
| 1126 | 1151 | const low_pc = text_phdr.p_vaddr; |
| 1127 | 1152 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; |
| 1128 | | try dw.writeDbgInfoHeader(module, low_pc, high_pc); |
| 1153 | try dw.writeDbgInfoHeader(self.base.options.module.?, low_pc, high_pc); |
| 1129 | 1154 | self.debug_info_header_dirty = false; |
| 1130 | 1155 | } |
| 1131 | 1156 | |