| ... | @@ -38,13 +38,10 @@ input_archive_symbol_indices: std.AutoArrayHashMapUnmanaged(String, struct { | ... | @@ -38,13 +38,10 @@ input_archive_symbol_indices: std.AutoArrayHashMapUnmanaged(String, struct { |
| 38 | first: InputArchive.Member.Symbol.Index, | 38 | first: InputArchive.Member.Symbol.Index, |
| 39 | last: InputArchive.Member.Symbol.Index, | 39 | last: InputArchive.Member.Symbol.Index, |
| 40 | }), | 40 | }), |
| | 41 | pending_input: ?InputArchive.Member.Index, |
| 41 | inputs: std.ArrayList(Input), | 42 | inputs: std.ArrayList(Input), |
| 42 | input_resolved: std.ArrayList(Symbol.Index), | 43 | input_resolved: std.ArrayList(Symbol.Index), |
| 43 | input_sections: std.ArrayList(struct { | 44 | input_sections: std.ArrayList(Node.InputSection), |
| 44 | ii: Node.InputIndex, | | |
| 45 | si: Symbol.Index, | | |
| 46 | file_location: MappedFile.Node.FileLocation, | | |
| 47 | }), | | |
| 48 | input_section_pending_index: u32, | 45 | input_section_pending_index: u32, |
| 49 | strings: std.HashMapUnmanaged( | 46 | strings: std.HashMapUnmanaged( |
| 50 | u32, | 47 | u32, |
| ... | @@ -203,7 +200,7 @@ pub const Node = union(enum) { | ... | @@ -203,7 +200,7 @@ pub const Node = union(enum) { |
| 203 | | 200 | |
| 204 | pseudo_section: PseudoSectionMapIndex, | 201 | pseudo_section: PseudoSectionMapIndex, |
| 205 | object_section: ObjectSectionMapIndex, | 202 | object_section: ObjectSectionMapIndex, |
| 206 | input_section: InputSectionIndex, | 203 | input_section: InputSection.Index, |
| 207 | global: GlobalMapIndex, | 204 | global: GlobalMapIndex, |
| 208 | nav: NavMapIndex, | 205 | nav: NavMapIndex, |
| 209 | uav: UavMapIndex, | 206 | uav: UavMapIndex, |
| ... | @@ -292,16 +289,16 @@ pub const Node = union(enum) { | ... | @@ -292,16 +289,16 @@ pub const Node = union(enum) { |
| 292 | return coff.inputs.items[@intFromEnum(ii)].path; | 289 | return coff.inputs.items[@intFromEnum(ii)].path; |
| 293 | } | 290 | } |
| 294 | | 291 | |
| 295 | pub fn archiveName(ii: InputIndex, coff: *const Coff) ?[]const u8 { | 292 | pub fn memberName(ii: InputIndex, coff: *const Coff) ?[]const u8 { |
| 296 | return coff.inputs.items[@intFromEnum(ii)].archive_name; | 293 | return coff.inputs.items[@intFromEnum(ii)].member_name; |
| 297 | } | 294 | } |
| 298 | | 295 | |
| 299 | pub fn firstSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index { | 296 | pub fn firstSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index { |
| 300 | return coff.inputs.items[@intFromEnum(ii)].first_si; | 297 | return coff.inputs.items[@intFromEnum(ii)].first_si; |
| 301 | } | 298 | } |
| 302 | | 299 | |
| 303 | pub fn lastSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index { | 300 | pub fn endSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index { |
| 304 | return coff.inputs.items[@intFromEnum(ii)].last_si; | 301 | return coff.inputs.items[@intFromEnum(ii)].end_si; |
| 305 | } | 302 | } |
| 306 | | 303 | |
| 307 | pub fn firstResolvedGlobal(ii: InputIndex, coff: *const Coff) Input.ResolvedIndex { | 304 | pub fn firstResolvedGlobal(ii: InputIndex, coff: *const Coff) Input.ResolvedIndex { |
| ... | @@ -309,24 +306,39 @@ pub const Node = union(enum) { | ... | @@ -309,24 +306,39 @@ pub const Node = union(enum) { |
| 309 | } | 306 | } |
| 310 | }; | 307 | }; |
| 311 | | 308 | |
| 312 | pub const InputSectionIndex = enum(u32) { | 309 | const InputSection = struct { |
| 313 | _, | 310 | ii: Node.InputIndex, |
| | 311 | si: Symbol.Index, |
| | 312 | file_location: MappedFile.Node.FileLocation, |
| | 313 | first_iri: Node.InputSection.ResolvedIndex, |
| 314 | | 314 | |
| 315 | pub fn input(isi: InputSectionIndex, coff: *const Coff) InputIndex { | 315 | pub const Index = enum(u32) { |
| 316 | return coff.input_sections.items[@intFromEnum(isi)].ii; | 316 | _, |
| 317 | } | | |
| 318 | | 317 | |
| 319 | pub fn fileLocation(isi: InputSectionIndex, coff: *const Coff) MappedFile.Node.FileLocation { | 318 | pub fn inputSection(isi: Index, coff: *const Coff) *InputSection { |
| 320 | return coff.input_sections.items[@intFromEnum(isi)].file_location; | 319 | return &coff.input_sections.items[@intFromEnum(isi)]; |
| 321 | } | 320 | } |
| 322 | | 321 | |
| 323 | pub fn symbol(isi: InputSectionIndex, coff: *const Coff) Symbol.Index { | 322 | pub fn input(isi: Index, coff: *const Coff) InputIndex { |
| 324 | return coff.input_sections.items[@intFromEnum(isi)].si; | 323 | return coff.input_sections.items[@intFromEnum(isi)].ii; |
| 325 | } | 324 | } |
| 326 | | 325 | |
| 327 | pub fn lastSymbol(isi: InputSectionIndex, coff: *const Coff) Symbol.Index { | 326 | pub fn fileLocation(isi: Index, coff: *const Coff) MappedFile.Node.FileLocation { |
| 328 | return coff.input_sections.items[@intFromEnum(isi)].last_si; | 327 | return coff.input_sections.items[@intFromEnum(isi)].file_location; |
| 329 | } | 328 | } |
| | 329 | |
| | 330 | pub fn symbol(isi: Index, coff: *const Coff) Symbol.Index { |
| | 331 | return coff.input_sections.items[@intFromEnum(isi)].si; |
| | 332 | } |
| | 333 | |
| | 334 | pub fn firstResolvedSymbol(isi: Index, coff: *const Coff) ResolvedIndex { |
| | 335 | return coff.input_sections.items[@intFromEnum(isi)].first_iri; |
| | 336 | } |
| | 337 | }; |
| | 338 | |
| | 339 | const ResolvedIndex = enum(u32) { |
| | 340 | _, |
| | 341 | }; |
| 330 | }; | 342 | }; |
| 331 | | 343 | |
| 332 | pub const LazyMapRef = struct { | 344 | pub const LazyMapRef = struct { |
| ... | @@ -398,6 +410,10 @@ pub const InputArchive = struct { | ... | @@ -398,6 +410,10 @@ pub const InputArchive = struct { |
| 398 | | 410 | |
| 399 | const Index = enum(u32) { | 411 | const Index = enum(u32) { |
| 400 | _, | 412 | _, |
| | 413 | |
| | 414 | pub fn path(iai: InputArchive.Index, coff: *Coff) std.Build.Cache.Path { |
| | 415 | return coff.input_archives.items[@intFromEnum(iai)].path; |
| | 416 | } |
| 401 | }; | 417 | }; |
| 402 | | 418 | |
| 403 | pub const Member = struct { | 419 | pub const Member = struct { |
| ... | @@ -405,10 +421,17 @@ pub const InputArchive = struct { | ... | @@ -405,10 +421,17 @@ pub const InputArchive = struct { |
| 405 | name: String, | 421 | name: String, |
| 406 | // This range includes the member header | 422 | // This range includes the member header |
| 407 | file_location: MappedFile.Node.FileLocation, | 423 | file_location: MappedFile.Node.FileLocation, |
| 408 | is_import: bool, | 424 | flags: packed struct { |
| 409 | // TODO: Field indicating we loaded it already (ii) | 425 | is_import: bool, |
| | 426 | is_loaded: bool, |
| | 427 | }, |
| | 428 | |
| 410 | const Index = enum(u32) { | 429 | const Index = enum(u32) { |
| 411 | _, | 430 | _, |
| | 431 | |
| | 432 | pub fn member(iami: InputArchive.Member.Index, coff: *Coff) *InputArchive.Member { |
| | 433 | return &coff.input_archive_members.items[@intFromEnum(iami)]; |
| | 434 | } |
| 412 | }; | 435 | }; |
| 413 | | 436 | |
| 414 | pub const Symbol = struct { | 437 | pub const Symbol = struct { |
| ... | @@ -425,14 +448,9 @@ pub const InputArchive = struct { | ... | @@ -425,14 +448,9 @@ pub const InputArchive = struct { |
| 425 | | 448 | |
| 426 | pub const Input = struct { | 449 | pub const Input = struct { |
| 427 | path: std.Build.Cache.Path, | 450 | path: std.Build.Cache.Path, |
| 428 | archive_name: ?[]const u8, | 451 | member_name: ?[]const u8, |
| 429 | first_si: Symbol.Index, | 452 | first_si: Symbol.Index, |
| 430 | last_si: Symbol.Index, | 453 | end_si: Symbol.Index, |
| 431 | first_iri: ResolvedIndex, | | |
| 432 | | | |
| 433 | const ResolvedIndex = enum(u32) { | | |
| 434 | _, | | |
| 435 | }; | | |
| 436 | }; | 454 | }; |
| 437 | | 455 | |
| 438 | pub const Member = struct { | 456 | pub const Member = struct { |
| ... | @@ -1336,6 +1354,7 @@ fn create( | ... | @@ -1336,6 +1354,7 @@ fn create( |
| 1336 | .input_archive_members = .empty, | 1354 | .input_archive_members = .empty, |
| 1337 | .input_archive_symbols = .empty, | 1355 | .input_archive_symbols = .empty, |
| 1338 | .input_archive_symbol_indices = .empty, | 1356 | .input_archive_symbol_indices = .empty, |
| | 1357 | .pending_input = null, |
| 1339 | .inputs = .empty, | 1358 | .inputs = .empty, |
| 1340 | .input_resolved = .empty, | 1359 | .input_resolved = .empty, |
| 1341 | .input_sections = .empty, | 1360 | .input_sections = .empty, |
| ... | @@ -2315,6 +2334,8 @@ fn getOrPutGlobalSymbol( | ... | @@ -2315,6 +2334,8 @@ fn getOrPutGlobalSymbol( |
| 2315 | si.get(coff).gmi = .wrap(@intCast(sym_gop.index)); | 2334 | si.get(coff).gmi = .wrap(@intCast(sym_gop.index)); |
| 2316 | sym_gop.value_ptr.* = si; | 2335 | sym_gop.value_ptr.* = si; |
| 2317 | coff.synth_prog_node.increaseEstimatedTotalItems(1); | 2336 | coff.synth_prog_node.increaseEstimatedTotalItems(1); |
| | 2337 | |
| | 2338 | log.debug("globalSymbol({s}, {?s}) = {d}", .{ opts.name, opts.lib_name, si }); |
| 2318 | } | 2339 | } |
| 2319 | | 2340 | |
| 2320 | return sym_gop; | 2341 | return sym_gop; |
| ... | @@ -2724,7 +2745,28 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void | ... | @@ -2724,7 +2745,28 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void |
| 2724 | log.debug("updateSymbolTableEntry({d}) = {d}", .{ si, sym.sti }); | 2745 | log.debug("updateSymbolTableEntry({d}) = {d}", .{ si, sym.sti }); |
| 2725 | } | 2746 | } |
| 2726 | | 2747 | |
| 2727 | fn flushInputSection(coff: *Coff, isi: Node.InputSectionIndex) !void { | 2748 | fn flushInputMember(coff: *Coff, iami: InputArchive.Member.Index) !void { |
| | 2749 | const member = iami.member(coff); |
| | 2750 | if (member.file_location.size == 0) return; |
| | 2751 | assert(!member.flags.is_loaded); |
| | 2752 | defer member.flags.is_loaded = true; |
| | 2753 | const comp = coff.base.comp; |
| | 2754 | const io = comp.io; |
| | 2755 | const path = member.iai.path(coff); |
| | 2756 | const file = try path.root_dir.handle.openFile(io, path.sub_path, .{}); |
| | 2757 | defer file.close(io); |
| | 2758 | var buffer: [4096]u8 = undefined; |
| | 2759 | var fr = file.reader(io, &buffer); |
| | 2760 | const offset = member.file_location.offset + @sizeOf(std.coff.ArchiveMemberHeader); |
| | 2761 | try fr.seekTo(offset); |
| | 2762 | log.debug("flushInputMember({f}({s}))", .{ path, member.name.toSlice(coff) }); |
| | 2763 | try coff.loadObject(path, member.name.toSlice(coff), &fr, .{ |
| | 2764 | .offset = offset, |
| | 2765 | .size = member.file_location.size, |
| | 2766 | }); |
| | 2767 | } |
| | 2768 | |
| | 2769 | fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void { |
| 2728 | const file_loc = isi.fileLocation(coff); | 2770 | const file_loc = isi.fileLocation(coff); |
| 2729 | if (file_loc.size == 0) return; | 2771 | if (file_loc.size == 0) return; |
| 2730 | const comp = coff.base.comp; | 2772 | const comp = coff.base.comp; |
| ... | @@ -2740,6 +2782,11 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSectionIndex) !void { | ... | @@ -2740,6 +2782,11 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSectionIndex) !void { |
| 2740 | const si = isi.symbol(coff); | 2782 | const si = isi.symbol(coff); |
| 2741 | si.node(coff).writer(&coff.mf, gpa, &nw); | 2783 | si.node(coff).writer(&coff.mf, gpa, &nw); |
| 2742 | defer nw.deinit(); | 2784 | defer nw.deinit(); |
| | 2785 | log.debug("flushInputSection({f}{f}, {s})", .{ |
| | 2786 | path, |
| | 2787 | fmtMemberNameString(ii.memberName(coff)), |
| | 2788 | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), |
| | 2789 | }); |
| 2743 | if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size) | 2790 | if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size) |
| 2744 | return error.EndOfStream; | 2791 | return error.EndOfStream; |
| 2745 | si.applyLocationRelocs(coff); | 2792 | si.applyLocationRelocs(coff); |
| ... | @@ -3180,12 +3227,12 @@ pub fn loadInput(coff: *Coff, input: link.Input) (Io.File.Reader.SizeError || | ... | @@ -3180,12 +3227,12 @@ pub fn loadInput(coff: *Coff, input: link.Input) (Io.File.Reader.SizeError || |
| 3180 | } | 3227 | } |
| 3181 | } | 3228 | } |
| 3182 | | 3229 | |
| 3183 | fn fmtArchiveNameString(archiveName: ?[]const u8) std.fmt.Alt(?[]const u8, archiveNameStringEscape) { | 3230 | fn fmtMemberNameString(memberName: ?[]const u8) std.fmt.Alt(?[]const u8, memberNameStringEscape) { |
| 3184 | return .{ .data = archiveName }; | 3231 | return .{ .data = memberName }; |
| 3185 | } | 3232 | } |
| 3186 | | 3233 | |
| 3187 | fn archiveNameStringEscape(archiveName: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void { | 3234 | fn memberNameStringEscape(memberName: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void { |
| 3188 | try w.print("({f})", .{std.zig.fmtString(archiveName orelse return)}); | 3235 | try w.print("({f})", .{std.zig.fmtString(memberName orelse return)}); |
| 3189 | } | 3236 | } |
| 3190 | | 3237 | |
| 3191 | fn inputSectionHeaderNameSlice( | 3238 | fn inputSectionHeaderNameSlice( |
| ... | @@ -3214,7 +3261,7 @@ fn inputSectionHeaderNameSlice( | ... | @@ -3214,7 +3261,7 @@ fn inputSectionHeaderNameSlice( |
| 3214 | fn loadObject( | 3261 | fn loadObject( |
| 3215 | coff: *Coff, | 3262 | coff: *Coff, |
| 3216 | path: std.Build.Cache.Path, | 3263 | path: std.Build.Cache.Path, |
| 3217 | archive_name: ?[]const u8, | 3264 | member_name: ?[]const u8, |
| 3218 | fr: *Io.File.Reader, | 3265 | fr: *Io.File.Reader, |
| 3219 | fl: MappedFile.Node.FileLocation, | 3266 | fl: MappedFile.Node.FileLocation, |
| 3220 | ) !void { | 3267 | ) !void { |
| ... | @@ -3227,7 +3274,7 @@ fn loadObject( | ... | @@ -3227,7 +3274,7 @@ fn loadObject( |
| 3227 | const is_archive = coff.isArchive(); | 3274 | const is_archive = coff.isArchive(); |
| 3228 | assert(!coff.isObj()); | 3275 | assert(!coff.isObj()); |
| 3229 | | 3276 | |
| 3230 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtArchiveNameString(archive_name) }); | 3277 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberNameString(member_name) }); |
| 3231 | | 3278 | |
| 3232 | const header = try r.peekStruct(std.coff.Header, coff.targetEndian()); | 3279 | const header = try r.peekStruct(std.coff.Header, coff.targetEndian()); |
| 3233 | if (header.machine != target.toCoffMachine()) | 3280 | if (header.machine != target.toCoffMachine()) |
| ... | @@ -3271,10 +3318,9 @@ fn loadObject( | ... | @@ -3271,10 +3318,9 @@ fn loadObject( |
| 3271 | const input = coff.inputs.addOneAssumeCapacity(); | 3318 | const input = coff.inputs.addOneAssumeCapacity(); |
| 3272 | input.* = .{ | 3319 | input.* = .{ |
| 3273 | .path = path, | 3320 | .path = path, |
| 3274 | .archive_name = if (archive_name) |m| try gpa.dupe(u8, m) else null, | 3321 | .member_name = if (member_name) |m| try gpa.dupe(u8, m) else null, |
| 3275 | .first_si = .null, | 3322 | .first_si = @enumFromInt(coff.symbols.items.len), |
| 3276 | .last_si = .null, | 3323 | .end_si = @enumFromInt(coff.symbols.items.len), |
| 3277 | .first_iri = @enumFromInt(coff.input_resolved.items.len), | | |
| 3278 | }; | 3324 | }; |
| 3279 | | 3325 | |
| 3280 | const string_table = string_table: { | 3326 | const string_table = string_table: { |
| ... | @@ -3455,6 +3501,7 @@ fn loadObject( | ... | @@ -3455,6 +3501,7 @@ fn loadObject( |
| 3455 | .offset = fl.offset + section.header.pointer_to_raw_data, | 3501 | .offset = fl.offset + section.header.pointer_to_raw_data, |
| 3456 | .size = section.header.size_of_raw_data, | 3502 | .size = section.header.size_of_raw_data, |
| 3457 | }, | 3503 | }, |
| | 3504 | .first_iri = @enumFromInt(coff.input_resolved.items.len), |
| 3458 | }; | 3505 | }; |
| 3459 | | 3506 | |
| 3460 | log.debug("loadInputSection({s}) = {d}@{d}", .{ section.name.toSlice(coff), section.si, sym.section_number }); | 3507 | log.debug("loadInputSection({s}) = {d}@{d}", .{ section.name.toSlice(coff), section.si, sym.section_number }); |
| ... | @@ -3497,8 +3544,11 @@ fn loadObject( | ... | @@ -3497,8 +3544,11 @@ fn loadObject( |
| 3497 | | 3544 | |
| 3498 | var symbols: std.ArrayList(Symbol.Index) = .empty; | 3545 | var symbols: std.ArrayList(Symbol.Index) = .empty; |
| 3499 | try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols); | 3546 | try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols); |
| | 3547 | var num_resolved: u32 = 0; |
| | 3548 | |
| | 3549 | input.first_si = @enumFromInt(coff.symbols.items.len); |
| | 3550 | defer input.end_si = @enumFromInt(coff.symbols.items.len); |
| 3500 | | 3551 | |
| 3501 | const first_si = coff.symbols.items.len; | | |
| 3502 | var symbol_i: u32 = 0; | 3552 | var symbol_i: u32 = 0; |
| 3503 | while (symbol_i < header.number_of_symbols) { | 3553 | while (symbol_i < header.number_of_symbols) { |
| 3504 | var symbol: std.coff.Symbol = undefined; | 3554 | var symbol: std.coff.Symbol = undefined; |
| ... | @@ -3619,6 +3669,7 @@ fn loadObject( | ... | @@ -3619,6 +3669,7 @@ fn loadObject( |
| 3619 | .{name}, | 3669 | .{name}, |
| 3620 | ), | 3670 | ), |
| 3621 | else => |sn| { | 3671 | else => |sn| { |
| | 3672 | // TODO: Should this use archive name as lib_name as well? |
| 3622 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = name }); | 3673 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = name }); |
| 3623 | si_slice[0] = global_gop.value_ptr.*; | 3674 | si_slice[0] = global_gop.value_ptr.*; |
| 3624 | const sym = si_slice[0].get(coff); | 3675 | const sym = si_slice[0].get(coff); |
| ... | @@ -3631,7 +3682,7 @@ fn loadObject( | ... | @@ -3631,7 +3682,7 @@ fn loadObject( |
| 3631 | const other_ii = isi.input(coff); | 3682 | const other_ii = isi.input(coff); |
| 3632 | err.addNote("first seen in input '{f}{f}'", .{ | 3683 | err.addNote("first seen in input '{f}{f}'", .{ |
| 3633 | other_ii.path(coff).fmtEscapeString(), | 3684 | other_ii.path(coff).fmtEscapeString(), |
| 3634 | fmtArchiveNameString(other_ii.archiveName(coff)), | 3685 | fmtMemberNameString(other_ii.memberName(coff)), |
| 3635 | }); | 3686 | }); |
| 3636 | }, | 3687 | }, |
| 3637 | .nav, .uav => err.addNote("first seen in module '{s}'", .{ | 3688 | .nav, .uav => err.addNote("first seen in module '{s}'", .{ |
| ... | @@ -3643,12 +3694,8 @@ fn loadObject( | ... | @@ -3643,12 +3694,8 @@ fn loadObject( |
| 3643 | return error.LinkFailure; | 3694 | return error.LinkFailure; |
| 3644 | } | 3695 | } |
| 3645 | | 3696 | |
| 3646 | if (global_gop.found_existing) { | 3697 | if (global_gop.found_existing) |
| 3647 | // `input_resolved` allows visting this symbol in this input section's flushMoved, | 3698 | num_resolved += 1; |
| 3648 | // as the previously undefined global created earlier will not be in our | | |
| 3649 | // contiguous first / last range. | | |
| 3650 | (try coff.input_resolved.addOne(gpa)).* = si_slice[0]; | | |
| 3651 | } | | |
| 3652 | | 3699 | |
| 3653 | coff.initInputSectionSymbol(sym, sections[@intCast(@intFromEnum(sn) - 1)].si, symbol.value); | 3700 | coff.initInputSectionSymbol(sym, sections[@intCast(@intFromEnum(sn) - 1)].si, symbol.value); |
| 3654 | }, | 3701 | }, |
| ... | @@ -3657,11 +3704,6 @@ fn loadObject( | ... | @@ -3657,11 +3704,6 @@ fn loadObject( |
| 3657 | } | 3704 | } |
| 3658 | } | 3705 | } |
| 3659 | | 3706 | |
| 3660 | if (coff.symbols.items.len > first_si) { | | |
| 3661 | input.first_si = @enumFromInt(first_si); | | |
| 3662 | input.last_si = @enumFromInt(coff.symbols.items.len - 1); | | |
| 3663 | } | | |
| 3664 | | | |
| 3665 | const relocation_size = std.coff.Relocation.sizeOf(); | 3707 | const relocation_size = std.coff.Relocation.sizeOf(); |
| 3666 | for (sections) |section| { | 3708 | for (sections) |section| { |
| 3667 | if (section.si == .null) continue; | 3709 | if (section.si == .null) continue; |
| ... | @@ -3697,6 +3739,38 @@ fn loadObject( | ... | @@ -3697,6 +3739,38 @@ fn loadObject( |
| 3697 | ); | 3739 | ); |
| 3698 | } | 3740 | } |
| 3699 | } | 3741 | } |
| | 3742 | |
| | 3743 | const symbolLessThan = struct { |
| | 3744 | fn lessThan(ctx: *Coff, lhs: Symbol.Index, rhs: Symbol.Index) bool { |
| | 3745 | const lhs_sn = @intFromEnum(if (lhs == .null) .UNDEFINED else lhs.get(ctx).section_number); |
| | 3746 | const rhs_sn = @intFromEnum(if (rhs == .null) .UNDEFINED else rhs.get(ctx).section_number); |
| | 3747 | if (lhs_sn == rhs_sn) return @intFromEnum(lhs) < @intFromEnum(rhs); |
| | 3748 | return lhs_sn < rhs_sn; |
| | 3749 | } |
| | 3750 | }.lessThan; |
| | 3751 | |
| | 3752 | std.mem.sortUnstable(Symbol.Index, symbols.items, coff, symbolLessThan); |
| | 3753 | |
| | 3754 | // Any symbols that we resolved (used to be undefined but are now defined) in this pass need to be |
| | 3755 | // added to contigous ranges in `input_resolved` so they can be visited in `flushMoved`, as they |
| | 3756 | // are not part of the contiguous ii.first_si / ii.last_si range. |
| | 3757 | // |
| | 3758 | // TODO: Should we just use this array for all symbols in this input? More memory but less get().ni misses in flushMoved |
| | 3759 | try coff.input_resolved.ensureUnusedCapacity(gpa, num_resolved); |
| | 3760 | var prev_isi: ?Node.InputSection.Index = null; |
| | 3761 | for (symbols.items) |si| { |
| | 3762 | if (si == .null or @intFromEnum(si) >= @intFromEnum(input.end_si)) continue; |
| | 3763 | const ni = si.get(coff).ni; |
| | 3764 | if (ni == .none) continue; |
| | 3765 | |
| | 3766 | const isi = coff.getNode(ni).input_section; |
| | 3767 | if (prev_isi != isi) { |
| | 3768 | isi.inputSection(coff).first_iri = @enumFromInt(coff.input_resolved.items.len); |
| | 3769 | prev_isi = isi; |
| | 3770 | } |
| | 3771 | |
| | 3772 | coff.input_resolved.addOneAssumeCapacity().* = si; |
| | 3773 | } |
| 3700 | } | 3774 | } |
| 3701 | | 3775 | |
| 3702 | const ArchiveMemberHeader = struct { | 3776 | const ArchiveMemberHeader = struct { |
| ... | @@ -3813,6 +3887,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo | ... | @@ -3813,6 +3887,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo |
| 3813 | var pos = fr.logicalPos(); | 3887 | var pos = fr.logicalPos(); |
| 3814 | const size = try fr.getSize(); | 3888 | const size = try fr.getSize(); |
| 3815 | while (pos < size) : (pos = fr.logicalPos()) { | 3889 | while (pos < size) : (pos = fr.logicalPos()) { |
| | 3890 | if ((pos & 1) != 0) r.toss(1); |
| 3816 | const header = try r.takeStruct(std.coff.ArchiveMemberHeader, target_endian); | 3891 | const header = try r.takeStruct(std.coff.ArchiveMemberHeader, target_endian); |
| 3817 | const res = try parseArchiveMemberHeader(diags, path, &header, opt_longnames); | 3892 | const res = try parseArchiveMemberHeader(diags, path, &header, opt_longnames); |
| 3818 | | 3893 | |
| ... | @@ -3891,7 +3966,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo | ... | @@ -3891,7 +3966,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo |
| 3891 | coff.input_archive_members.addOneAssumeCapacity().* = .{ | 3966 | coff.input_archive_members.addOneAssumeCapacity().* = .{ |
| 3892 | .iai = iai, | 3967 | .iai = iai, |
| 3893 | .name = undefined, | 3968 | .name = undefined, |
| 3894 | .is_import = undefined, | 3969 | .flags = undefined, |
| 3895 | .file_location = .{ | 3970 | .file_location = .{ |
| 3896 | .offset = member_offset, | 3971 | .offset = member_offset, |
| 3897 | .size = undefined, | 3972 | .size = undefined, |
| ... | @@ -3952,7 +4027,10 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo | ... | @@ -3952,7 +4027,10 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo |
| 3952 | const member_sig = try r.peek(4); | 4027 | const member_sig = try r.peek(4); |
| 3953 | const machine = std.mem.readInt(u16, member_sig[0..2], target_endian); | 4028 | const machine = std.mem.readInt(u16, member_sig[0..2], target_endian); |
| 3954 | const sig = std.mem.readInt(u16, member_sig[2..4], target_endian); | 4029 | const sig = std.mem.readInt(u16, member_sig[2..4], target_endian); |
| 3955 | member.is_import = machine == @intFromEnum(std.coff.IMAGE.FILE.MACHINE.UNKNOWN) and sig == 0xffff; | 4030 | member.flags = .{ |
| | 4031 | .is_import = machine == @intFromEnum(std.coff.IMAGE.FILE.MACHINE.UNKNOWN) and sig == 0xffff, |
| | 4032 | .is_loaded = false, |
| | 4033 | }; |
| 3956 | member.file_location.size = res.size; | 4034 | member.file_location.size = res.size; |
| 3957 | | 4035 | |
| 3958 | log.debug("verifyArchiveMember({s}) = 0x{x}+{x}", .{ | 4036 | log.debug("verifyArchiveMember({s}) = 0x{x}+{x}", .{ |
| ... | @@ -3961,7 +4039,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo | ... | @@ -3961,7 +4039,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo |
| 3961 | member.file_location.size, | 4039 | member.file_location.size, |
| 3962 | }); | 4040 | }); |
| 3963 | | 4041 | |
| 3964 | if (member.is_import) { | 4042 | if (member.flags.is_import) { |
| 3965 | const import_header = try r.peekStruct(std.coff.ImportHeader, target_endian); | 4043 | const import_header = try r.peekStruct(std.coff.ImportHeader, target_endian); |
| 3966 | // TODO: Validate import table header fields | 4044 | // TODO: Validate import table header fields |
| 3967 | // TODO: Use this result in flushGlobal | 4045 | // TODO: Use this result in flushGlobal |
| ... | @@ -4356,13 +4434,13 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { | ... | @@ -4356,13 +4434,13 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| 4356 | // TODO: We could report the name here if we interned it in loadObject | 4434 | // TODO: We could report the name here if we interned it in loadObject |
| 4357 | err.addNote("referenced internally by input '{f}{f}'", .{ | 4435 | err.addNote("referenced internally by input '{f}{f}'", .{ |
| 4358 | other_ii.path(coff).fmtEscapeString(), | 4436 | other_ii.path(coff).fmtEscapeString(), |
| 4359 | fmtArchiveNameString(other_ii.archiveName(coff)), | 4437 | fmtMemberNameString(other_ii.memberName(coff)), |
| 4360 | }); | 4438 | }); |
| 4361 | } else { | 4439 | } else { |
| 4362 | err.addNote("referenced by input symbol '{s}' from '{f}{f}'", .{ | 4440 | err.addNote("referenced by input symbol '{s}' from '{f}{f}'", .{ |
| 4363 | loc_sym.gmi.globalName(coff).name.toSlice(coff), | 4441 | loc_sym.gmi.globalName(coff).name.toSlice(coff), |
| 4364 | other_ii.path(coff).fmtEscapeString(), | 4442 | other_ii.path(coff).fmtEscapeString(), |
| 4365 | fmtArchiveNameString(other_ii.archiveName(coff)), | 4443 | fmtMemberNameString(other_ii.memberName(coff)), |
| 4366 | }); | 4444 | }); |
| 4367 | } | 4445 | } |
| 4368 | }, | 4446 | }, |
| ... | @@ -4478,21 +4556,32 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -4478,21 +4556,32 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 4478 | }; | 4556 | }; |
| 4479 | break :task; | 4557 | break :task; |
| 4480 | } | 4558 | } |
| | 4559 | if (coff.pending_input) |pending_iami| { |
| | 4560 | // TODO: Prog node? |
| | 4561 | coff.flushInputMember(pending_iami) catch |err| switch (err) { |
| | 4562 | error.OutOfMemory => return error.OutOfMemory, |
| | 4563 | else => |e| return comp.link_diags.fail( |
| | 4564 | "linker failed to archive member: {t}", |
| | 4565 | .{e}, |
| | 4566 | ), |
| | 4567 | }; |
| | 4568 | coff.pending_input = null; |
| | 4569 | break :task; |
| | 4570 | } |
| 4481 | if (coff.global_pending_index < coff.globals.count()) { | 4571 | if (coff.global_pending_index < coff.globals.count()) { |
| 4482 | const gmi: Node.GlobalMapIndex = .wrap(coff.global_pending_index); | 4572 | const gmi: Node.GlobalMapIndex = .wrap(coff.global_pending_index); |
| 4483 | coff.global_pending_index += 1; | | |
| 4484 | const sub_prog_node = coff.synth_prog_node.start( | 4573 | const sub_prog_node = coff.synth_prog_node.start( |
| 4485 | gmi.globalName(coff).name.toSlice(coff), | 4574 | gmi.globalName(coff).name.toSlice(coff), |
| 4486 | 0, | 4575 | 0, |
| 4487 | ); | 4576 | ); |
| 4488 | defer sub_prog_node.end(); | 4577 | defer sub_prog_node.end(); |
| 4489 | coff.flushGlobal(gmi) catch |err| switch (err) { | 4578 | if (coff.flushGlobal(gmi) catch |err| switch (err) { |
| 4490 | else => |e| return e, | 4579 | else => |e| return e, |
| 4491 | error.MappedFileIo => return comp.link_diags.fail( | 4580 | error.MappedFileIo => return comp.link_diags.fail( |
| 4492 | "linker failed to lower constant: {t}", | 4581 | "linker failed to lower constant: {t}", |
| 4493 | .{coff.mf.io_err.?}, | 4582 | .{coff.mf.io_err.?}, |
| 4494 | ), | 4583 | ), |
| 4495 | }; | 4584 | }) coff.global_pending_index += 1; |
| 4496 | break :task; | 4585 | break :task; |
| 4497 | } | 4586 | } |
| 4498 | var lazy_it = coff.lazy.iterator(); | 4587 | var lazy_it = coff.lazy.iterator(); |
| ... | @@ -4547,7 +4636,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -4547,7 +4636,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 4547 | } | 4636 | } |
| 4548 | // TODO: Idle task for flushing obj into lib? | 4637 | // TODO: Idle task for flushing obj into lib? |
| 4549 | if (coff.input_section_pending_index < coff.input_sections.items.len) { | 4638 | if (coff.input_section_pending_index < coff.input_sections.items.len) { |
| 4550 | const isi: Node.InputSectionIndex = @enumFromInt(coff.input_section_pending_index); | 4639 | const isi: Node.InputSection.Index = @enumFromInt(coff.input_section_pending_index); |
| 4551 | coff.input_section_pending_index += 1; | 4640 | coff.input_section_pending_index += 1; |
| 4552 | const sub_prog_node = coff.idleProgNode(tid, coff.input_prog_node, coff.getNode(isi.symbol(coff).node(coff))); | 4641 | const sub_prog_node = coff.idleProgNode(tid, coff.input_prog_node, coff.getNode(isi.symbol(coff).node(coff))); |
| 4553 | defer sub_prog_node.end(); | 4642 | defer sub_prog_node.end(); |
| ... | @@ -4559,7 +4648,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -4559,7 +4648,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 4559 | .{ | 4648 | .{ |
| 4560 | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), | 4649 | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), |
| 4561 | ii.path(coff).fmtEscapeString(), | 4650 | ii.path(coff).fmtEscapeString(), |
| 4562 | fmtArchiveNameString(ii.archiveName(coff)), | 4651 | fmtMemberNameString(ii.memberName(coff)), |
| 4563 | e, | 4652 | e, |
| 4564 | }, | 4653 | }, |
| 4565 | ); | 4654 | ); |
| ... | @@ -4629,9 +4718,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -4629,9 +4718,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 4629 | } | 4718 | } |
| 4630 | } | 4719 | } |
| 4631 | if (coff.pending_uavs.count() > 0) return true; | 4720 | if (coff.pending_uavs.count() > 0) return true; |
| | 4721 | if (coff.pending_input != null) return true; |
| 4632 | if (coff.globals.count() > coff.global_pending_index) return true; | 4722 | if (coff.globals.count() > coff.global_pending_index) return true; |
| 4633 | if (coff.symbol_table.pending.count() > 0) return true; | | |
| 4634 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; | 4723 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; |
| | 4724 | if (coff.symbol_table.pending.count() > 0) return true; |
| 4635 | if (coff.input_sections.items.len > coff.input_section_pending_index) return true; | 4725 | if (coff.input_sections.items.len > coff.input_section_pending_index) return true; |
| 4636 | if (coff.mf.updates.items.len > 0) return true; | 4726 | if (coff.mf.updates.items.len > 0) return true; |
| 4637 | if (coff.pending_members.count() > 0) return true; | 4727 | if (coff.pending_members.count() > 0) return true; |
| ... | @@ -4655,7 +4745,7 @@ fn idleProgNode( | ... | @@ -4655,7 +4745,7 @@ fn idleProgNode( |
| 4655 | const ii = isi.input(coff); | 4745 | const ii = isi.input(coff); |
| 4656 | break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{ | 4746 | break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{ |
| 4657 | ii.path(coff).fmtEscapeString(), | 4747 | ii.path(coff).fmtEscapeString(), |
| 4658 | fmtArchiveNameString(ii.archiveName(coff)), | 4748 | fmtMemberNameString(ii.memberName(coff)), |
| 4659 | coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff), | 4749 | coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff), |
| 4660 | }) catch &name; | 4750 | }) catch &name; |
| 4661 | }, | 4751 | }, |
| ... | @@ -4736,7 +4826,7 @@ fn flushUav( | ... | @@ -4736,7 +4826,7 @@ fn flushUav( |
| 4736 | si.applyLocationRelocs(coff); | 4826 | si.applyLocationRelocs(coff); |
| 4737 | } | 4827 | } |
| 4738 | | 4828 | |
| 4739 | fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void { | 4829 | fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 4740 | const comp = coff.base.comp; | 4830 | const comp = coff.base.comp; |
| 4741 | const gpa = comp.gpa; | 4831 | const gpa = comp.gpa; |
| 4742 | const gn = gmi.globalName(coff); | 4832 | const gn = gmi.globalName(coff); |
| ... | @@ -4751,7 +4841,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void { | ... | @@ -4751,7 +4841,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void { |
| 4751 | gn.name, | 4841 | gn.name, |
| 4752 | ); | 4842 | ); |
| 4753 | | 4843 | |
| 4754 | return; | 4844 | return true; |
| 4755 | } | 4845 | } |
| 4756 | | 4846 | |
| 4757 | if (gn.lib_name.toSlice(coff)) |lib_name| { | 4847 | if (gn.lib_name.toSlice(coff)) |lib_name| { |
| ... | @@ -4911,15 +5001,26 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void { | ... | @@ -4911,15 +5001,26 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void { |
| 4911 | sym.rva = coff.computeNodeRva(sym.ni); | 5001 | sym.rva = coff.computeNodeRva(sym.ni); |
| 4912 | si.applyLocationRelocs(coff); | 5002 | si.applyLocationRelocs(coff); |
| 4913 | } else { | 5003 | } else { |
| | 5004 | if (coff.input_archive_symbol_indices.get(gn.name)) |index| { |
| | 5005 | var iter: InputArchive.Member.Symbol.Index = index.first; |
| | 5006 | while (true) { |
| | 5007 | const archive_sym = &coff.input_archive_symbols.items[@intFromEnum(iter)]; |
| | 5008 | |
| | 5009 | // TODO: This implies that loading an input failing is not fatal |
| | 5010 | if (!coff.input_archive_members.items[@intFromEnum(archive_sym.iami)].flags.is_loaded) { |
| | 5011 | coff.pending_input = archive_sym.iami; |
| | 5012 | return false; |
| | 5013 | } |
| 4914 | | 5014 | |
| 4915 | // TODO: Check if not defined, and if in an input member | 5015 | if (archive_sym.next == iter) break; |
| 4916 | // TODO: If so, queue a loadObject for that member | 5016 | iter = archive_sym.next; |
| 4917 | // TODO: Return a value indicating to retry this flushGlobal | 5017 | } |
| 4918 | // TODO: The loadObject idle task should be before the flushGlobal idle task | 5018 | } |
| 4919 | // | | |
| 4920 | // TODO: Check if we can get flushGlobal before prelink, that would cause a problem | | |
| 4921 | | 5019 | |
| | 5020 | // TODO: Check if we can get flushGlobal before prelink, that would cause a problem |
| 4922 | } | 5021 | } |
| | 5022 | |
| | 5023 | return true; |
| 4923 | } | 5024 | } |
| 4924 | | 5025 | |
| 4925 | fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { | 5026 | fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| ... | @@ -5040,14 +5141,14 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { | ... | @@ -5040,14 +5141,14 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 5040 | | 5141 | |
| 5041 | { | 5142 | { |
| 5042 | var si = ii.firstSymbol(coff); | 5143 | var si = ii.firstSymbol(coff); |
| 5043 | const last_si = ii.lastSymbol(coff); | 5144 | const end_si = ii.endSymbol(coff); |
| 5044 | while (@intFromEnum(si) <= @intFromEnum(last_si)) : (si = si.next()) { | 5145 | while (@intFromEnum(si) < @intFromEnum(end_si)) : (si = si.next()) { |
| 5045 | if (si.get(coff).ni != ni) continue; | 5146 | if (si.get(coff).ni != ni) continue; |
| 5046 | si.flushMoved(coff); | 5147 | si.flushMoved(coff); |
| 5047 | } | 5148 | } |
| 5048 | } | 5149 | } |
| 5049 | | 5150 | |
| 5050 | for (coff.input_resolved.items[@intFromEnum(ii.firstResolvedGlobal(coff))..]) |si| { | 5151 | for (coff.input_resolved.items[@intFromEnum(isi.firstResolvedSymbol(coff))..]) |si| { |
| 5051 | if (si.get(coff).ni != ni) break; | 5152 | if (si.get(coff).ni != ni) break; |
| 5052 | si.flushMoved(coff); | 5153 | si.flushMoved(coff); |
| 5053 | } | 5154 | } |
| ... | @@ -5606,7 +5707,7 @@ pub fn printNode( | ... | @@ -5606,7 +5707,7 @@ pub fn printNode( |
| 5606 | const ii = isi.input(coff); | 5707 | const ii = isi.input(coff); |
| 5607 | try w.print("({f}{f}, {s})", .{ | 5708 | try w.print("({f}{f}, {s})", .{ |
| 5608 | ii.path(coff).fmtEscapeString(), | 5709 | ii.path(coff).fmtEscapeString(), |
| 5609 | fmtArchiveNameString(ii.archiveName(coff)), | 5710 | fmtMemberNameString(ii.memberName(coff)), |
| 5610 | coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff), | 5711 | coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff), |
| 5611 | }); | 5712 | }); |
| 5612 | }, | 5713 | }, |