| author | |
| committer | |
| log | 3fdcbc03d43246a39411725b1e4e23e862d32b82 |
| tree | 24dae16c0a65be5e9656d31473b37e15cf64b2e3 |
| parent | 8a3fc2fecf365927a470a25d43e0bd26a01eb9ed |
| parent | d44db8ea0c35122aefbb1d86bed820b382eec988 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36413
Reviewed-by: Andrew Kelley <andrew@ziglang.org>76 files changed, 10355 insertions(+), 2620 deletions(-)
CMakeLists.txt+1| ... | @@ -383,6 +383,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -383,6 +383,7 @@ set(ZIG_STAGE2_SOURCES |
| 383 | src/link/ConstPool.zig | 383 | src/link/ConstPool.zig |
| 384 | src/link/Coff.zig | 384 | src/link/Coff.zig |
| 385 | src/link/Dwarf.zig | 385 | src/link/Dwarf.zig |
| 386 | src/link/Dwarf2.zig | ||
| 386 | src/link/Elf.zig | 387 | src/link/Elf.zig |
| 387 | src/link/Elf/Archive.zig | 388 | src/link/Elf/Archive.zig |
| 388 | src/link/Elf/Atom.zig | 389 | src/link/Elf/Atom.zig |
README.md+13-6| ... | @@ -781,12 +781,20 @@ If you will be debugging the Zig compiler itself, or if you will be debugging | ... | @@ -781,12 +781,20 @@ If you will be debugging the Zig compiler itself, or if you will be debugging |
| 781 | any project compiled with Zig's LLVM backend (not recommended with the LLDB | 781 | any project compiled with Zig's LLVM backend (not recommended with the LLDB |
| 782 | fork, prefer vanilla LLDB with a version that matches the version of LLVM that | 782 | fork, prefer vanilla LLDB with a version that matches the version of LLVM that |
| 783 | Zig is using), you can get a better debugging experience by using | 783 | Zig is using), you can get a better debugging experience by using |
| 784 | [`lldb_pretty_printers.py`](https://codeberg.org/ziglang/zig/src/branch/master/tools/lldb_pretty_printers.py). | 784 | [`lldb/pretty_printers.py`](https://codeberg.org/ziglang/zig/src/branch/master/lib/lldb/pretty_printers.py) |
| 785 | which is included in Zig's installed lib dir. | ||
| 785 | 786 | ||
| 786 | Put this line in `~/.lldbinit`: | 787 | Put this line in `~/.lldbinit`: |
| 787 | 788 | ||
| 788 | ``` | 789 | ``` |
| 789 | command script import /path/to/zig/tools/lldb_pretty_printers.py | 790 | command script import /path/to/zig/lib/lldb/pretty_printers.py |
| 791 | ``` | ||
| 792 | |||
| 793 | If you will be debugging a Zig compiler built using Zig's self-hosted backends, | ||
| 794 | you will also want this line: | ||
| 795 | |||
| 796 | ``` | ||
| 797 | type category enable zig.compiler | ||
| 790 | ``` | 798 | ``` |
| 791 | 799 | ||
| 792 | If you will be using Zig's LLVM backend (again, not recommended with the LLDB | 800 | If you will be using Zig's LLVM backend (again, not recommended with the LLDB |
| ... | @@ -797,10 +805,9 @@ type category enable zig.lang | ... | @@ -797,10 +805,9 @@ type category enable zig.lang |
| 797 | type category enable zig.std | 805 | type category enable zig.std |
| 798 | ``` | 806 | ``` |
| 799 | 807 | ||
| 800 | If you will be debugging a Zig compiler built using Zig's LLVM backend (again, | 808 | If you will be debugging a Zig compiler built using Zig's LLVM backend without |
| 801 | not recommended with the LLDB fork), you will also want this line: | 809 | using the LLDB fork, you will also want this line: |
| 802 | 810 | ||
| 803 | ``` | 811 | ``` |
| 804 | type category enable zig.stage2 | 812 | type category enable zig |
| 805 | ``` | 813 | ``` |
| 806 |
ci/x86_64-linux-debug-llvm.sh+1-1| ... | @@ -53,7 +53,7 @@ stage3-debug/bin/zig build \ | ... | @@ -53,7 +53,7 @@ stage3-debug/bin/zig build \ |
| 53 | 53 | ||
| 54 | stage3-debug/bin/zig build test docs \ | 54 | stage3-debug/bin/zig build test docs \ |
| 55 | --maxrss ${ZSF_MAX_RSS:-0} \ | 55 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 56 | -Dlldb=$HOME/deps/lldb-zig/Debug-7c1090fd46/bin/lldb \ | 56 | -Dlldb=$HOME/deps/lldb-zig/Debug-aad646607a/bin/lldb \ |
| 57 | -Dlibc-test-path=$HOME/deps/libc-test-b95fe84 \ | 57 | -Dlibc-test-path=$HOME/deps/libc-test-b95fe84 \ |
| 58 | -fqemu \ | 58 | -fqemu \ |
| 59 | --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ | 59 | --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ |
ci/x86_64-linux-debug.sh+1-1| ... | @@ -53,7 +53,7 @@ stage3-debug/bin/zig build \ | ... | @@ -53,7 +53,7 @@ stage3-debug/bin/zig build \ |
| 53 | 53 | ||
| 54 | stage3-debug/bin/zig build test docs \ | 54 | stage3-debug/bin/zig build test docs \ |
| 55 | --maxrss ${ZSF_MAX_RSS:-0} \ | 55 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 56 | -Dlldb=$HOME/deps/lldb-zig/Debug-7c1090fd46/bin/lldb \ | 56 | -Dlldb=$HOME/deps/lldb-zig/Debug-aad646607a/bin/lldb \ |
| 57 | -fqemu \ | 57 | -fqemu \ |
| 58 | --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ | 58 | --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ |
| 59 | -fwasmtime \ | 59 | -fwasmtime \ |
ci/x86_64-linux-release.sh+1-1| ... | @@ -61,7 +61,7 @@ stage3-release/bin/zig build \ | ... | @@ -61,7 +61,7 @@ stage3-release/bin/zig build \ |
| 61 | 61 | ||
| 62 | stage3-release/bin/zig build test docs \ | 62 | stage3-release/bin/zig build test docs \ |
| 63 | --maxrss ${ZSF_MAX_RSS:-0} \ | 63 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 64 | -Dlldb=$HOME/deps/lldb-zig/Release-7c1090fd46/bin/lldb \ | 64 | -Dlldb=$HOME/deps/lldb-zig/Release-aad646607a/bin/lldb \ |
| 65 | -Dlibc-test-path=$HOME/deps/libc-test-b95fe84 \ | 65 | -Dlibc-test-path=$HOME/deps/libc-test-b95fe84 \ |
| 66 | -fqemu \ | 66 | -fqemu \ |
| 67 | --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ | 67 | --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ |
lib/std/Io/Writer.zig+4-7| ... | @@ -487,7 +487,7 @@ pub fn writableSliceGreedyPreserve(w: *Writer, preserve: usize, minimum_len: usi | ... | @@ -487,7 +487,7 @@ pub fn writableSliceGreedyPreserve(w: *Writer, preserve: usize, minimum_len: usi |
| 487 | @branchHint(.likely); | 487 | @branchHint(.likely); |
| 488 | return w.buffer[w.end..]; | 488 | return w.buffer[w.end..]; |
| 489 | } | 489 | } |
| 490 | try rebase(w, preserve, minimum_len); | 490 | try w.vtable.rebase(w, preserve, minimum_len); |
| 491 | assert(w.buffer.len >= preserve + minimum_len); | 491 | assert(w.buffer.len >= preserve + minimum_len); |
| 492 | return w.buffer[w.end..]; | 492 | return w.buffer[w.end..]; |
| 493 | } | 493 | } |
| ... | @@ -845,13 +845,10 @@ pub fn writeByte(w: *Writer, byte: u8) Error!void { | ... | @@ -845,13 +845,10 @@ pub fn writeByte(w: *Writer, byte: u8) Error!void { |
| 845 | /// | 845 | /// |
| 846 | /// Asserts buffer capacity is at least `preserve`. | 846 | /// Asserts buffer capacity is at least `preserve`. |
| 847 | pub fn writeBytePreserve(w: *Writer, preserve: usize, byte: u8) Error!void { | 847 | pub fn writeBytePreserve(w: *Writer, preserve: usize, byte: u8) Error!void { |
| 848 | if (w.buffer.len - w.end != 0) { | 848 | if (w.buffer.len - w.end == 0) { |
| 849 | @branchHint(.likely); | 849 | @branchHint(.unlikely); |
| 850 | w.buffer[w.end] = byte; | 850 | try w.vtable.rebase(w, preserve -| 1, 1); |
| 851 | w.end += 1; | ||
| 852 | return; | ||
| 853 | } | 851 | } |
| 854 | try w.vtable.rebase(w, preserve -| 1, 1); | ||
| 855 | w.buffer[w.end] = byte; | 852 | w.buffer[w.end] = byte; |
| 856 | w.end += 1; | 853 | w.end += 1; |
| 857 | } | 854 | } |
lib/std/debug/Dwarf.zig+10-8| ... | @@ -387,18 +387,19 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void { | ... | @@ -387,18 +387,19 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void { |
| 387 | const next_offset = unit_header.header_length + unit_header.unit_length; | 387 | const next_offset = unit_header.header_length + unit_header.unit_length; |
| 388 | 388 | ||
| 389 | const version = try fr.takeInt(u16, endian); | 389 | const version = try fr.takeInt(u16, endian); |
| 390 | if (version < 2 or version > 5) return bad(); | ||
| 391 | |||
| 392 | var address_size: u8 = undefined; | 390 | var address_size: u8 = undefined; |
| 393 | var debug_abbrev_offset: u64 = undefined; | 391 | var debug_abbrev_offset: u64 = undefined; |
| 394 | if (version >= 5) { | 392 | if (version == 5) { |
| 395 | const unit_type = try fr.takeByte(); | 393 | const unit_type = try fr.takeByte(); |
| 396 | if (unit_type != DW.UT.compile) return bad(); | 394 | if (unit_type != DW.UT.compile) return bad(); |
| 397 | address_size = try fr.takeByte(); | 395 | address_size = try fr.takeByte(); |
| 398 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); | 396 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); |
| 399 | } else { | 397 | } else if (version >= 2 and version < 5) { |
| 400 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); | 398 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); |
| 401 | address_size = try fr.takeByte(); | 399 | address_size = try fr.takeByte(); |
| 400 | } else { | ||
| 401 | this_unit_offset += next_offset; | ||
| 402 | continue; | ||
| 402 | } | 403 | } |
| 403 | 404 | ||
| 404 | const abbrev_table = try di.getAbbrevTable(gpa, debug_abbrev_offset); | 405 | const abbrev_table = try di.getAbbrevTable(gpa, debug_abbrev_offset); |
| ... | @@ -585,18 +586,19 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi | ... | @@ -585,18 +586,19 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi |
| 585 | const next_offset = unit_header.header_length + unit_header.unit_length; | 586 | const next_offset = unit_header.header_length + unit_header.unit_length; |
| 586 | 587 | ||
| 587 | const version = try fr.takeInt(u16, endian); | 588 | const version = try fr.takeInt(u16, endian); |
| 588 | if (version < 2 or version > 5) return bad(); | ||
| 589 | |||
| 590 | var address_size: u8 = undefined; | 589 | var address_size: u8 = undefined; |
| 591 | var debug_abbrev_offset: u64 = undefined; | 590 | var debug_abbrev_offset: u64 = undefined; |
| 592 | if (version >= 5) { | 591 | if (version == 5) { |
| 593 | const unit_type = try fr.takeByte(); | 592 | const unit_type = try fr.takeByte(); |
| 594 | if (unit_type != UT.compile) return bad(); | 593 | if (unit_type != UT.compile) return bad(); |
| 595 | address_size = try fr.takeByte(); | 594 | address_size = try fr.takeByte(); |
| 596 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); | 595 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); |
| 597 | } else { | 596 | } else if (version >= 2 and version < 5) { |
| 598 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); | 597 | debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian); |
| 599 | address_size = try fr.takeByte(); | 598 | address_size = try fr.takeByte(); |
| 599 | } else { | ||
| 600 | this_unit_offset += next_offset; | ||
| 601 | continue; | ||
| 600 | } | 602 | } |
| 601 | 603 | ||
| 602 | const abbrev_table = try di.getAbbrevTable(gpa, debug_abbrev_offset); | 604 | const abbrev_table = try di.getAbbrevTable(gpa, debug_abbrev_offset); |
lib/std/debug/Dwarf/Unwind.zig+16-7| ... | @@ -362,8 +362,7 @@ pub const CommonInformationEntry = struct { | ... | @@ -362,8 +362,7 @@ pub const CommonInformationEntry = struct { |
| 362 | if (aug_str.len == 0) break :aug .none; | 362 | if (aug_str.len == 0) break :aug .none; |
| 363 | if (aug_str[0] == 'z') break :aug .lsb_z; | 363 | if (aug_str[0] == 'z') break :aug .lsb_z; |
| 364 | if (std.mem.eql(u8, aug_str, "eh")) break :aug .gcc_eh; | 364 | if (std.mem.eql(u8, aug_str, "eh")) break :aug .gcc_eh; |
| 365 | // We can't finish parsing the CIE if we don't know what its augmentation means. | 365 | return error.UnsupportedAugmentation; |
| 366 | return bad(); | ||
| 367 | }; | 366 | }; |
| 368 | 367 | ||
| 369 | switch (aug_kind) { | 368 | switch (aug_kind) { |
| ... | @@ -396,7 +395,7 @@ pub const CommonInformationEntry = struct { | ... | @@ -396,7 +395,7 @@ pub const CommonInformationEntry = struct { |
| 396 | 'R' => fde_pointer_enc = @bitCast(try aug_data.takeByte()), | 395 | 'R' => fde_pointer_enc = @bitCast(try aug_data.takeByte()), |
| 397 | 'S' => is_signal_frame = true, | 396 | 'S' => is_signal_frame = true, |
| 398 | 'B', 'G' => {}, | 397 | 'B', 'G' => {}, |
| 399 | else => return bad(), | 398 | else => return error.UnsupportedAugmentation, |
| 400 | }; | 399 | }; |
| 401 | break :aug .{ fde_pointer_enc, is_signal_frame }; | 400 | break :aug .{ fde_pointer_enc, is_signal_frame }; |
| 402 | }; | 401 | }; |
| ... | @@ -502,7 +501,15 @@ pub fn prepare( | ... | @@ -502,7 +501,15 @@ pub fn prepare( |
| 502 | const idx = unwind.cie_list.len; | 501 | const idx = unwind.cie_list.len; |
| 503 | try unwind.cie_list.append(gpa, .{ | 502 | try unwind.cie_list.append(gpa, .{ |
| 504 | .offset = entry_offset, | 503 | .offset = entry_offset, |
| 505 | .cie = try .parse(cie_info.format, try r.take(bytes_len), section.id, addr_size_bytes), | 504 | .cie = CommonInformationEntry.parse(cie_info.format, try r.take(bytes_len), section.id, addr_size_bytes) catch |err| switch (err) { |
| 505 | error.UnsupportedDwarfVersion, | ||
| 506 | error.UnsupportedAugmentation, | ||
| 507 | => { | ||
| 508 | // These are recoverable by just skipping the CIE. | ||
| 509 | continue; | ||
| 510 | }, | ||
| 511 | else => |e| return e, | ||
| 512 | }, | ||
| 506 | }); | 513 | }); |
| 507 | errdefer _ = unwind.cie_list.pop().?; | 514 | errdefer _ = unwind.cie_list.pop().?; |
| 508 | try VirtualMachine.populateCieLastRow(gpa, &unwind.cie_list.items(.cie)[idx], addr_size_bytes, endian); | 515 | try VirtualMachine.populateCieLastRow(gpa, &unwind.cie_list.items(.cie)[idx], addr_size_bytes, endian); |
| ... | @@ -514,8 +521,10 @@ pub fn prepare( | ... | @@ -514,8 +521,10 @@ pub fn prepare( |
| 514 | try r.discardAll(bytes_len); | 521 | try r.discardAll(bytes_len); |
| 515 | continue; | 522 | continue; |
| 516 | } | 523 | } |
| 517 | const cie = unwind.findCie(fde_info.cie_offset) orelse return error.InvalidDebugInfo; | 524 | const fde_vaddr = section.vaddr + r.seek; |
| 518 | const fde: FrameDescriptionEntry = try .parse(section.vaddr + r.seek, try r.take(bytes_len), cie, endian); | 525 | const fde_bytes = try r.take(bytes_len); |
| 526 | const cie = unwind.findCie(fde_info.cie_offset) orelse continue; | ||
| 527 | const fde: FrameDescriptionEntry = try .parse(fde_vaddr, fde_bytes, cie, endian); | ||
| 519 | try fde_list.append(gpa, .{ | 528 | try fde_list.append(gpa, .{ |
| 520 | .pc_begin = fde.pc_begin, | 529 | .pc_begin = fde.pc_begin, |
| 521 | .fde_offset = entry_offset, | 530 | .fde_offset = entry_offset, |
| ... | @@ -612,7 +621,7 @@ pub fn getFde(unwind: *const Unwind, fde_offset: u64, endian: Endian) !struct { | ... | @@ -612,7 +621,7 @@ pub fn getFde(unwind: *const Unwind, fde_offset: u64, endian: Endian) !struct { |
| 612 | .cie, .terminator => return bad(), // This is meant to be an FDE | 621 | .cie, .terminator => return bad(), // This is meant to be an FDE |
| 613 | }; | 622 | }; |
| 614 | 623 | ||
| 615 | const cie = unwind.findCie(fde_info.cie_offset) orelse return error.InvalidDebugInfo; | 624 | const cie = unwind.findCie(fde_info.cie_offset) orelse return bad(); |
| 616 | const fde: FrameDescriptionEntry = try .parse( | 625 | const fde: FrameDescriptionEntry = try .parse( |
| 617 | section.vaddr + fde_offset + fde_reader.seek, | 626 | section.vaddr + fde_offset + fde_reader.seek, |
| 618 | try fde_reader.take(cast(usize, fde_info.bytes_len) orelse return error.EndOfStream), | 627 | try fde_reader.take(cast(usize, fde_info.bytes_len) orelse return error.EndOfStream), |
lib/std/debug/SelfInfo/Elf.zig-1| ... | @@ -340,7 +340,6 @@ const Module = struct { | ... | @@ -340,7 +340,6 @@ const Module = struct { |
| 340 | error.InvalidOperation, | 340 | error.InvalidOperation, |
| 341 | => return error.InvalidDebugInfo, | 341 | => return error.InvalidDebugInfo, |
| 342 | error.UnsupportedAddrSize, | 342 | error.UnsupportedAddrSize, |
| 343 | error.UnsupportedDwarfVersion, | ||
| 344 | error.UnimplementedUserOpcode, | 343 | error.UnimplementedUserOpcode, |
| 345 | => return error.UnsupportedDebugInfo, | 344 | => return error.UnsupportedDebugInfo, |
| 346 | }; | 345 | }; |
lib/std/debug/SelfInfo/MachO.zig-1| ... | @@ -578,7 +578,6 @@ const Module = struct { | ... | @@ -578,7 +578,6 @@ const Module = struct { |
| 578 | error.InvalidOperation, | 578 | error.InvalidOperation, |
| 579 | => return error.InvalidDebugInfo, | 579 | => return error.InvalidDebugInfo, |
| 580 | error.UnsupportedAddrSize, | 580 | error.UnsupportedAddrSize, |
| 581 | error.UnsupportedDwarfVersion, | ||
| 582 | error.UnimplementedUserOpcode, | 581 | error.UnimplementedUserOpcode, |
| 583 | => return error.UnsupportedDebugInfo, | 582 | => return error.UnsupportedDebugInfo, |
| 584 | }; | 583 | }; |
lib/std/dwarf/AT.zig+1| ... | @@ -225,6 +225,7 @@ pub const ZIG_padding = 0x2cce; | ... | @@ -225,6 +225,7 @@ pub const ZIG_padding = 0x2cce; |
| 225 | pub const ZIG_relative_decl = 0x2cd0; | 225 | pub const ZIG_relative_decl = 0x2cd0; |
| 226 | pub const ZIG_decl_line_relative = 0x2cd1; | 226 | pub const ZIG_decl_line_relative = 0x2cd1; |
| 227 | pub const ZIG_comptime_value = 0x2cd2; | 227 | pub const ZIG_comptime_value = 0x2cd2; |
| 228 | pub const ZIG_call_line_relative = 0x2cd3; | ||
| 228 | pub const ZIG_sentinel = 0x2ce2; | 229 | pub const ZIG_sentinel = 0x2ce2; |
| 229 | 230 | ||
| 230 | // UPC extension. | 231 | // UPC extension. |
lib/std/dwarf/TAG.zig+3-2| ... | @@ -40,8 +40,8 @@ pub const namelist = 0x2b; | ... | @@ -40,8 +40,8 @@ pub const namelist = 0x2b; |
| 40 | pub const namelist_item = 0x2c; | 40 | pub const namelist_item = 0x2c; |
| 41 | pub const packed_type = 0x2d; | 41 | pub const packed_type = 0x2d; |
| 42 | pub const subprogram = 0x2e; | 42 | pub const subprogram = 0x2e; |
| 43 | pub const template_type_param = 0x2f; | 43 | pub const template_type_parameter = 0x2f; |
| 44 | pub const template_value_param = 0x30; | 44 | pub const template_value_parameter = 0x30; |
| 45 | pub const thrown_type = 0x31; | 45 | pub const thrown_type = 0x31; |
| 46 | pub const try_block = 0x32; | 46 | pub const try_block = 0x32; |
| 47 | pub const variant_part = 0x33; | 47 | pub const variant_part = 0x33; |
| ... | @@ -120,3 +120,4 @@ pub const PGI_interface_block = 0xA020; | ... | @@ -120,3 +120,4 @@ pub const PGI_interface_block = 0xA020; |
| 120 | // ZIG extensions. | 120 | // ZIG extensions. |
| 121 | pub const ZIG_padding = 0xfdb1; | 121 | pub const ZIG_padding = 0xfdb1; |
| 122 | pub const ZIG_comptime_value = 0xfdb2; | 122 | pub const ZIG_comptime_value = 0xfdb2; |
| 123 | pub const ZIG_lost_declaration = 0xfdb3; |
lib/std/zig/AstGen.zig+42-6| ... | @@ -1884,7 +1884,8 @@ fn structInitExprAnon( | ... | @@ -1884,7 +1884,8 @@ fn structInitExprAnon( |
| 1884 | 1884 | ||
| 1885 | const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{ | 1885 | const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{ |
| 1886 | .abs_node = node, | 1886 | .abs_node = node, |
| 1887 | .abs_line = astgen.source_line, | 1887 | .src_line = astgen.source_line, |
| 1888 | .src_column = astgen.source_column, | ||
| 1888 | .fields_len = @intCast(struct_init.ast.fields.len), | 1889 | .fields_len = @intCast(struct_init.ast.fields.len), |
| 1889 | }); | 1890 | }); |
| 1890 | const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).@"struct".field_names.len; | 1891 | const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).@"struct".field_names.len; |
| ... | @@ -1917,7 +1918,8 @@ fn structInitExprTyped( | ... | @@ -1917,7 +1918,8 @@ fn structInitExprTyped( |
| 1917 | 1918 | ||
| 1918 | const payload_index = try addExtra(astgen, Zir.Inst.StructInit{ | 1919 | const payload_index = try addExtra(astgen, Zir.Inst.StructInit{ |
| 1919 | .abs_node = node, | 1920 | .abs_node = node, |
| 1920 | .abs_line = astgen.source_line, | 1921 | .src_line = astgen.source_line, |
| 1922 | .src_column = astgen.source_column, | ||
| 1921 | .fields_len = @intCast(struct_init.ast.fields.len), | 1923 | .fields_len = @intCast(struct_init.ast.fields.len), |
| 1922 | }); | 1924 | }); |
| 1923 | const field_size = @typeInfo(Zir.Inst.StructInit.Item).@"struct".field_names.len; | 1925 | const field_size = @typeInfo(Zir.Inst.StructInit.Item).@"struct".field_names.len; |
| ... | @@ -4846,9 +4848,13 @@ fn structDeclInner( | ... | @@ -4846,9 +4848,13 @@ fn structDeclInner( |
| 4846 | astgen.advanceSourceCursorToNode(node); | 4848 | astgen.advanceSourceCursorToNode(node); |
| 4847 | 4849 | ||
| 4848 | const decl_inst = try gz.reserveInstructionIndex(); | 4850 | const decl_inst = try gz.reserveInstructionIndex(); |
| 4851 | const src_line = astgen.source_line; | ||
| 4852 | const src_column = astgen.source_column; | ||
| 4849 | 4853 | ||
| 4850 | if (container_decl.ast.members.len == 0 and maybe_backing_int_node == .none) { | 4854 | if (container_decl.ast.members.len == 0 and maybe_backing_int_node == .none) { |
| 4851 | try gz.setStruct(decl_inst, .{ | 4855 | try gz.setStruct(decl_inst, .{ |
| 4856 | .src_line = src_line, | ||
| 4857 | .src_column = src_column, | ||
| 4852 | .src_node = node, | 4858 | .src_node = node, |
| 4853 | .name_strat = name_strat, | 4859 | .name_strat = name_strat, |
| 4854 | .layout = layout, | 4860 | .layout = layout, |
| ... | @@ -5003,6 +5009,8 @@ fn structDeclInner( | ... | @@ -5003,6 +5009,8 @@ fn structDeclInner( |
| 5003 | astgen.src_hasher.final(&fields_hash); | 5009 | astgen.src_hasher.final(&fields_hash); |
| 5004 | 5010 | ||
| 5005 | try gz.setStruct(decl_inst, .{ | 5011 | try gz.setStruct(decl_inst, .{ |
| 5012 | .src_line = src_line, | ||
| 5013 | .src_column = src_column, | ||
| 5006 | .src_node = node, | 5014 | .src_node = node, |
| 5007 | .name_strat = name_strat, | 5015 | .name_strat = name_strat, |
| 5008 | .layout = layout, | 5016 | .layout = layout, |
| ... | @@ -5151,6 +5159,8 @@ fn unionDeclInner( | ... | @@ -5151,6 +5159,8 @@ fn unionDeclInner( |
| 5151 | astgen.advanceSourceCursorToNode(node); | 5159 | astgen.advanceSourceCursorToNode(node); |
| 5152 | 5160 | ||
| 5153 | const decl_inst = try gz.reserveInstructionIndex(); | 5161 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5162 | const src_line = astgen.source_line; | ||
| 5163 | const src_column = astgen.source_column; | ||
| 5154 | 5164 | ||
| 5155 | var namespace: Scope.Namespace = .{ | 5165 | var namespace: Scope.Namespace = .{ |
| 5156 | .parent = scope, | 5166 | .parent = scope, |
| ... | @@ -5284,6 +5294,8 @@ fn unionDeclInner( | ... | @@ -5284,6 +5294,8 @@ fn unionDeclInner( |
| 5284 | astgen.src_hasher.final(&fields_hash); | 5294 | astgen.src_hasher.final(&fields_hash); |
| 5285 | 5295 | ||
| 5286 | try gz.setUnion(decl_inst, .{ | 5296 | try gz.setUnion(decl_inst, .{ |
| 5297 | .src_line = src_line, | ||
| 5298 | .src_column = src_column, | ||
| 5287 | .src_node = node, | 5299 | .src_node = node, |
| 5288 | .name_strat = name_strat, | 5300 | .name_strat = name_strat, |
| 5289 | .kind = switch (layout) { | 5301 | .kind = switch (layout) { |
| ... | @@ -5358,6 +5370,8 @@ fn containerDecl( | ... | @@ -5358,6 +5370,8 @@ fn containerDecl( |
| 5358 | astgen.advanceSourceCursorToNode(node); | 5370 | astgen.advanceSourceCursorToNode(node); |
| 5359 | 5371 | ||
| 5360 | const decl_inst = try gz.reserveInstructionIndex(); | 5372 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5373 | const src_line = astgen.source_line; | ||
| 5374 | const src_column = astgen.source_column; | ||
| 5361 | 5375 | ||
| 5362 | var namespace: Scope.Namespace = .{ | 5376 | var namespace: Scope.Namespace = .{ |
| 5363 | .parent = scope, | 5377 | .parent = scope, |
| ... | @@ -5482,6 +5496,8 @@ fn containerDecl( | ... | @@ -5482,6 +5496,8 @@ fn containerDecl( |
| 5482 | astgen.src_hasher.final(&fields_hash); | 5496 | astgen.src_hasher.final(&fields_hash); |
| 5483 | 5497 | ||
| 5484 | try gz.setEnum(decl_inst, .{ | 5498 | try gz.setEnum(decl_inst, .{ |
| 5499 | .src_line = src_line, | ||
| 5500 | .src_column = src_column, | ||
| 5485 | .src_node = node, | 5501 | .src_node = node, |
| 5486 | .name_strat = name_strat, | 5502 | .name_strat = name_strat, |
| 5487 | .tag_type_body_len = tag_type_body_len, | 5503 | .tag_type_body_len = tag_type_body_len, |
| ... | @@ -5504,6 +5520,8 @@ fn containerDecl( | ... | @@ -5504,6 +5520,8 @@ fn containerDecl( |
| 5504 | astgen.advanceSourceCursorToNode(node); | 5520 | astgen.advanceSourceCursorToNode(node); |
| 5505 | 5521 | ||
| 5506 | const decl_inst = try gz.reserveInstructionIndex(); | 5522 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5523 | const src_line = astgen.source_line; | ||
| 5524 | const src_column = astgen.source_column; | ||
| 5507 | 5525 | ||
| 5508 | var namespace: Scope.Namespace = .{ | 5526 | var namespace: Scope.Namespace = .{ |
| 5509 | .parent = scope, | 5527 | .parent = scope, |
| ... | @@ -5545,6 +5563,8 @@ fn containerDecl( | ... | @@ -5545,6 +5563,8 @@ fn containerDecl( |
| 5545 | wip_decls.finish(); | 5563 | wip_decls.finish(); |
| 5546 | 5564 | ||
| 5547 | try gz.setOpaque(decl_inst, .{ | 5565 | try gz.setOpaque(decl_inst, .{ |
| 5566 | .src_line = src_line, | ||
| 5567 | .src_column = src_column, | ||
| 5548 | .src_node = node, | 5568 | .src_node = node, |
| 5549 | .name_strat = name_strat, | 5569 | .name_strat = name_strat, |
| 5550 | .decls_len = scan_result.decls_len, | 5570 | .decls_len = scan_result.decls_len, |
| ... | @@ -9302,6 +9322,7 @@ fn builtinCall( | ... | @@ -9302,6 +9322,7 @@ fn builtinCall( |
| 9302 | const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .struct_field_attrs); | 9322 | const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .struct_field_attrs); |
| 9303 | const result = try gz.addExtendedPayloadSmall(.reify_struct, @backingInt(reify_name_strat), Zir.Inst.ReifyStruct{ | 9323 | const result = try gz.addExtendedPayloadSmall(.reify_struct, @backingInt(reify_name_strat), Zir.Inst.ReifyStruct{ |
| 9304 | .src_line = gz.astgen.source_line, | 9324 | .src_line = gz.astgen.source_line, |
| 9325 | .src_column = gz.astgen.source_column, | ||
| 9305 | .node = node, | 9326 | .node = node, |
| 9306 | .layout = layout, | 9327 | .layout = layout, |
| 9307 | .backing_ty = backing_ty, | 9328 | .backing_ty = backing_ty, |
| ... | @@ -9330,6 +9351,7 @@ fn builtinCall( | ... | @@ -9330,6 +9351,7 @@ fn builtinCall( |
| 9330 | const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .union_field_attrs); | 9351 | const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .union_field_attrs); |
| 9331 | const result = try gz.addExtendedPayloadSmall(.reify_union, @backingInt(reify_name_strat), Zir.Inst.ReifyUnion{ | 9352 | const result = try gz.addExtendedPayloadSmall(.reify_union, @backingInt(reify_name_strat), Zir.Inst.ReifyUnion{ |
| 9332 | .src_line = gz.astgen.source_line, | 9353 | .src_line = gz.astgen.source_line, |
| 9354 | .src_column = gz.astgen.source_column, | ||
| 9333 | .node = node, | 9355 | .node = node, |
| 9334 | .layout = layout, | 9356 | .layout = layout, |
| 9335 | .arg_ty = arg_ty, | 9357 | .arg_ty = arg_ty, |
| ... | @@ -9352,6 +9374,7 @@ fn builtinCall( | ... | @@ -9352,6 +9374,7 @@ fn builtinCall( |
| 9352 | const field_values = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_values_ty } }, params[3], .enum_field_values); | 9374 | const field_values = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_values_ty } }, params[3], .enum_field_values); |
| 9353 | const result = try gz.addExtendedPayloadSmall(.reify_enum, @backingInt(reify_name_strat), Zir.Inst.ReifyEnum{ | 9375 | const result = try gz.addExtendedPayloadSmall(.reify_enum, @backingInt(reify_name_strat), Zir.Inst.ReifyEnum{ |
| 9354 | .src_line = gz.astgen.source_line, | 9376 | .src_line = gz.astgen.source_line, |
| 9377 | .src_column = gz.astgen.source_column, | ||
| 9355 | .node = node, | 9378 | .node = node, |
| 9356 | .tag_ty = tag_ty, | 9379 | .tag_ty = tag_ty, |
| 9357 | .mode = mode, | 9380 | .mode = mode, |
| ... | @@ -9365,6 +9388,7 @@ fn builtinCall( | ... | @@ -9365,6 +9388,7 @@ fn builtinCall( |
| 9365 | const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = spirv_type_options_ty } }, params[0], .type); | 9388 | const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = spirv_type_options_ty } }, params[0], .type); |
| 9366 | const result = try gz.addExtendedPayload(.reify_spirv_type, Zir.Inst.ReifySpirvType{ | 9389 | const result = try gz.addExtendedPayload(.reify_spirv_type, Zir.Inst.ReifySpirvType{ |
| 9367 | .src_line = gz.astgen.source_line, | 9390 | .src_line = gz.astgen.source_line, |
| 9391 | .src_column = gz.astgen.source_column, | ||
| 9368 | .node = node, | 9392 | .node = node, |
| 9369 | .operand = operand, | 9393 | .operand = operand, |
| 9370 | }); | 9394 | }); |
| ... | @@ -12392,6 +12416,8 @@ const GenZir = struct { | ... | @@ -12392,6 +12416,8 @@ const GenZir = struct { |
| 12392 | } | 12416 | } |
| 12393 | 12417 | ||
| 12394 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12418 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 12419 | src_line: u32, | ||
| 12420 | src_column: u32, | ||
| 12395 | src_node: Ast.Node.Index, | 12421 | src_node: Ast.Node.Index, |
| 12396 | name_strat: Zir.Inst.NameStrategy, | 12422 | name_strat: Zir.Inst.NameStrategy, |
| 12397 | layout: std.lang.Type.ContainerLayout, | 12423 | layout: std.lang.Type.ContainerLayout, |
| ... | @@ -12428,7 +12454,8 @@ const GenZir = struct { | ... | @@ -12428,7 +12454,8 @@ const GenZir = struct { |
| 12428 | .fields_hash_1 = fields_hash_arr[1], | 12454 | .fields_hash_1 = fields_hash_arr[1], |
| 12429 | .fields_hash_2 = fields_hash_arr[2], | 12455 | .fields_hash_2 = fields_hash_arr[2], |
| 12430 | .fields_hash_3 = fields_hash_arr[3], | 12456 | .fields_hash_3 = fields_hash_arr[3], |
| 12431 | .src_line = astgen.source_line, | 12457 | .src_line = args.src_line, |
| 12458 | .src_column = args.src_column, | ||
| 12432 | .src_node = args.src_node, | 12459 | .src_node = args.src_node, |
| 12433 | }); | 12460 | }); |
| 12434 | 12461 | ||
| ... | @@ -12461,6 +12488,8 @@ const GenZir = struct { | ... | @@ -12461,6 +12488,8 @@ const GenZir = struct { |
| 12461 | } | 12488 | } |
| 12462 | 12489 | ||
| 12463 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12490 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 12491 | src_line: u32, | ||
| 12492 | src_column: u32, | ||
| 12464 | src_node: Ast.Node.Index, | 12493 | src_node: Ast.Node.Index, |
| 12465 | name_strat: Zir.Inst.NameStrategy, | 12494 | name_strat: Zir.Inst.NameStrategy, |
| 12466 | kind: Zir.Inst.UnionDecl.Kind, | 12495 | kind: Zir.Inst.UnionDecl.Kind, |
| ... | @@ -12495,7 +12524,8 @@ const GenZir = struct { | ... | @@ -12495,7 +12524,8 @@ const GenZir = struct { |
| 12495 | .fields_hash_1 = fields_hash_arr[1], | 12524 | .fields_hash_1 = fields_hash_arr[1], |
| 12496 | .fields_hash_2 = fields_hash_arr[2], | 12525 | .fields_hash_2 = fields_hash_arr[2], |
| 12497 | .fields_hash_3 = fields_hash_arr[3], | 12526 | .fields_hash_3 = fields_hash_arr[3], |
| 12498 | .src_line = astgen.source_line, | 12527 | .src_line = args.src_line, |
| 12528 | .src_column = args.src_column, | ||
| 12499 | .src_node = args.src_node, | 12529 | .src_node = args.src_node, |
| 12500 | }); | 12530 | }); |
| 12501 | 12531 | ||
| ... | @@ -12530,6 +12560,8 @@ const GenZir = struct { | ... | @@ -12530,6 +12560,8 @@ const GenZir = struct { |
| 12530 | } | 12560 | } |
| 12531 | 12561 | ||
| 12532 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12562 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 12563 | src_line: u32, | ||
| 12564 | src_column: u32, | ||
| 12533 | src_node: Ast.Node.Index, | 12565 | src_node: Ast.Node.Index, |
| 12534 | name_strat: Zir.Inst.NameStrategy, | 12566 | name_strat: Zir.Inst.NameStrategy, |
| 12535 | tag_type_body_len: ?u32, | 12567 | tag_type_body_len: ?u32, |
| ... | @@ -12563,7 +12595,8 @@ const GenZir = struct { | ... | @@ -12563,7 +12595,8 @@ const GenZir = struct { |
| 12563 | .fields_hash_1 = fields_hash_arr[1], | 12595 | .fields_hash_1 = fields_hash_arr[1], |
| 12564 | .fields_hash_2 = fields_hash_arr[2], | 12596 | .fields_hash_2 = fields_hash_arr[2], |
| 12565 | .fields_hash_3 = fields_hash_arr[3], | 12597 | .fields_hash_3 = fields_hash_arr[3], |
| 12566 | .src_line = astgen.source_line, | 12598 | .src_line = args.src_line, |
| 12599 | .src_column = args.src_column, | ||
| 12567 | .src_node = args.src_node, | 12600 | .src_node = args.src_node, |
| 12568 | }); | 12601 | }); |
| 12569 | 12602 | ||
| ... | @@ -12594,6 +12627,8 @@ const GenZir = struct { | ... | @@ -12594,6 +12627,8 @@ const GenZir = struct { |
| 12594 | } | 12627 | } |
| 12595 | 12628 | ||
| 12596 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12629 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 12630 | src_line: u32, | ||
| 12631 | src_column: u32, | ||
| 12597 | src_node: Ast.Node.Index, | 12632 | src_node: Ast.Node.Index, |
| 12598 | name_strat: Zir.Inst.NameStrategy, | 12633 | name_strat: Zir.Inst.NameStrategy, |
| 12599 | decls_len: u32, | 12634 | decls_len: u32, |
| ... | @@ -12615,7 +12650,8 @@ const GenZir = struct { | ... | @@ -12615,7 +12650,8 @@ const GenZir = struct { |
| 12615 | args.decls.len); | 12650 | args.decls.len); |
| 12616 | 12651 | ||
| 12617 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ | 12652 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| 12618 | .src_line = astgen.source_line, | 12653 | .src_line = args.src_line, |
| 12654 | .src_column = args.src_column, | ||
| 12619 | .src_node = args.src_node, | 12655 | .src_node = args.src_node, |
| 12620 | }); | 12656 | }); |
| 12621 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); | 12657 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
lib/std/zig/Zir.zig+20-4| ... | @@ -3277,6 +3277,7 @@ pub const Inst = struct { | ... | @@ -3277,6 +3277,7 @@ pub const Inst = struct { |
| 3277 | 3277 | ||
| 3278 | pub const ReifyStruct = struct { | 3278 | pub const ReifyStruct = struct { |
| 3279 | src_line: u32, | 3279 | src_line: u32, |
| 3280 | src_column: u32, | ||
| 3280 | /// This node is absolute, because `reify` instructions are tracked across updates, and | 3281 | /// This node is absolute, because `reify` instructions are tracked across updates, and |
| 3281 | /// this simplifies the logic for getting source locations for types. | 3282 | /// this simplifies the logic for getting source locations for types. |
| 3282 | node: Ast.Node.Index, | 3283 | node: Ast.Node.Index, |
| ... | @@ -3289,6 +3290,7 @@ pub const Inst = struct { | ... | @@ -3289,6 +3290,7 @@ pub const Inst = struct { |
| 3289 | 3290 | ||
| 3290 | pub const ReifyUnion = struct { | 3291 | pub const ReifyUnion = struct { |
| 3291 | src_line: u32, | 3292 | src_line: u32, |
| 3293 | src_column: u32, | ||
| 3292 | /// This node is absolute, because `reify` instructions are tracked across updates, and | 3294 | /// This node is absolute, because `reify` instructions are tracked across updates, and |
| 3293 | /// this simplifies the logic for getting source locations for types. | 3295 | /// this simplifies the logic for getting source locations for types. |
| 3294 | node: Ast.Node.Index, | 3296 | node: Ast.Node.Index, |
| ... | @@ -3301,6 +3303,7 @@ pub const Inst = struct { | ... | @@ -3301,6 +3303,7 @@ pub const Inst = struct { |
| 3301 | 3303 | ||
| 3302 | pub const ReifyEnum = struct { | 3304 | pub const ReifyEnum = struct { |
| 3303 | src_line: u32, | 3305 | src_line: u32, |
| 3306 | src_column: u32, | ||
| 3304 | /// This node is absolute, because `reify` instructions are tracked across updates, and | 3307 | /// This node is absolute, because `reify` instructions are tracked across updates, and |
| 3305 | /// this simplifies the logic for getting source locations for types. | 3308 | /// this simplifies the logic for getting source locations for types. |
| 3306 | node: Ast.Node.Index, | 3309 | node: Ast.Node.Index, |
| ... | @@ -3312,6 +3315,7 @@ pub const Inst = struct { | ... | @@ -3312,6 +3315,7 @@ pub const Inst = struct { |
| 3312 | 3315 | ||
| 3313 | pub const ReifySpirvType = struct { | 3316 | pub const ReifySpirvType = struct { |
| 3314 | src_line: u32, | 3317 | src_line: u32, |
| 3318 | src_column: u32, | ||
| 3315 | /// This node is absolute, because `reify` instructions are tracked across updates, and | 3319 | /// This node is absolute, because `reify` instructions are tracked across updates, and |
| 3316 | /// this simplifies the logic for getting source locations for types. | 3320 | /// this simplifies the logic for getting source locations for types. |
| 3317 | node: Ast.Node.Index, | 3321 | node: Ast.Node.Index, |
| ... | @@ -3509,6 +3513,7 @@ pub const Inst = struct { | ... | @@ -3509,6 +3513,7 @@ pub const Inst = struct { |
| 3509 | fields_hash_2: u32, | 3513 | fields_hash_2: u32, |
| 3510 | fields_hash_3: u32, | 3514 | fields_hash_3: u32, |
| 3511 | src_line: u32, | 3515 | src_line: u32, |
| 3516 | src_column: u32, | ||
| 3512 | /// This node provides a new absolute baseline node for all instructions within this struct. | 3517 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3513 | src_node: Ast.Node.Index, | 3518 | src_node: Ast.Node.Index, |
| 3514 | 3519 | ||
| ... | @@ -3664,6 +3669,7 @@ pub const Inst = struct { | ... | @@ -3664,6 +3669,7 @@ pub const Inst = struct { |
| 3664 | fields_hash_2: u32, | 3669 | fields_hash_2: u32, |
| 3665 | fields_hash_3: u32, | 3670 | fields_hash_3: u32, |
| 3666 | src_line: u32, | 3671 | src_line: u32, |
| 3672 | src_column: u32, | ||
| 3667 | /// This node provides a new absolute baseline node for all instructions within this struct. | 3673 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3668 | src_node: Ast.Node.Index, | 3674 | src_node: Ast.Node.Index, |
| 3669 | 3675 | ||
| ... | @@ -3701,6 +3707,7 @@ pub const Inst = struct { | ... | @@ -3701,6 +3707,7 @@ pub const Inst = struct { |
| 3701 | fields_hash_2: u32, | 3707 | fields_hash_2: u32, |
| 3702 | fields_hash_3: u32, | 3708 | fields_hash_3: u32, |
| 3703 | src_line: u32, | 3709 | src_line: u32, |
| 3710 | src_column: u32, | ||
| 3704 | /// This node provides a new absolute baseline node for all instructions within this struct. | 3711 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3705 | src_node: Ast.Node.Index, | 3712 | src_node: Ast.Node.Index, |
| 3706 | 3713 | ||
| ... | @@ -3756,6 +3763,7 @@ pub const Inst = struct { | ... | @@ -3756,6 +3763,7 @@ pub const Inst = struct { |
| 3756 | /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction | 3763 | /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3757 | pub const OpaqueDecl = struct { | 3764 | pub const OpaqueDecl = struct { |
| 3758 | src_line: u32, | 3765 | src_line: u32, |
| 3766 | src_column: u32, | ||
| 3759 | /// This node provides a new absolute baseline node for all instructions within this struct. | 3767 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3760 | src_node: Ast.Node.Index, | 3768 | src_node: Ast.Node.Index, |
| 3761 | 3769 | ||
| ... | @@ -3803,8 +3811,8 @@ pub const Inst = struct { | ... | @@ -3803,8 +3811,8 @@ pub const Inst = struct { |
| 3803 | /// If this is an anonymous initialization (the operand is poison), this instruction becomes the owner of a type. | 3811 | /// If this is an anonymous initialization (the operand is poison), this instruction becomes the owner of a type. |
| 3804 | /// To resolve source locations, we need an absolute source node. | 3812 | /// To resolve source locations, we need an absolute source node. |
| 3805 | abs_node: Ast.Node.Index, | 3813 | abs_node: Ast.Node.Index, |
| 3806 | /// Likewise, we need an absolute line number. | 3814 | src_line: u32, |
| 3807 | abs_line: u32, | 3815 | src_column: u32, |
| 3808 | fields_len: u32, | 3816 | fields_len: u32, |
| 3809 | 3817 | ||
| 3810 | pub const Item = struct { | 3818 | pub const Item = struct { |
| ... | @@ -3823,8 +3831,8 @@ pub const Inst = struct { | ... | @@ -3823,8 +3831,8 @@ pub const Inst = struct { |
| 3823 | /// This is an anonymous initialization, meaning this instruction becomes the owner of a type. | 3831 | /// This is an anonymous initialization, meaning this instruction becomes the owner of a type. |
| 3824 | /// To resolve source locations, we need an absolute source node. | 3832 | /// To resolve source locations, we need an absolute source node. |
| 3825 | abs_node: Ast.Node.Index, | 3833 | abs_node: Ast.Node.Index, |
| 3826 | /// Likewise, we need an absolute line number. | 3834 | src_line: u32, |
| 3827 | abs_line: u32, | 3835 | src_column: u32, |
| 3828 | fields_len: u32, | 3836 | fields_len: u32, |
| 3829 | 3837 | ||
| 3830 | pub const Item = struct { | 3838 | pub const Item = struct { |
| ... | @@ -5318,6 +5326,7 @@ pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDe | ... | @@ -5318,6 +5326,7 @@ pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDe |
| 5318 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); | 5326 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); |
| 5319 | return .{ | 5327 | return .{ |
| 5320 | .src_line = extra.data.src_line, | 5328 | .src_line = extra.data.src_line, |
| 5329 | .src_column = extra.data.src_column, | ||
| 5321 | .src_node = extra.data.src_node, | 5330 | .src_node = extra.data.src_node, |
| 5322 | .name_strategy = small.name_strategy, | 5331 | .name_strategy = small.name_strategy, |
| 5323 | .captures = captures, | 5332 | .captures = captures, |
| ... | @@ -5335,6 +5344,7 @@ pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDe | ... | @@ -5335,6 +5344,7 @@ pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDe |
| 5335 | } | 5344 | } |
| 5336 | pub const UnwrappedStructDecl = struct { | 5345 | pub const UnwrappedStructDecl = struct { |
| 5337 | src_line: u32, | 5346 | src_line: u32, |
| 5347 | src_column: u32, | ||
| 5338 | src_node: Ast.Node.Index, | 5348 | src_node: Ast.Node.Index, |
| 5339 | name_strategy: Inst.NameStrategy, | 5349 | name_strategy: Inst.NameStrategy, |
| 5340 | 5350 | ||
| ... | @@ -5463,6 +5473,7 @@ pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl | ... | @@ -5463,6 +5473,7 @@ pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl |
| 5463 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); | 5473 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); |
| 5464 | return .{ | 5474 | return .{ |
| 5465 | .src_line = extra.data.src_line, | 5475 | .src_line = extra.data.src_line, |
| 5476 | .src_column = extra.data.src_column, | ||
| 5466 | .src_node = extra.data.src_node, | 5477 | .src_node = extra.data.src_node, |
| 5467 | .name_strategy = small.name_strategy, | 5478 | .name_strategy = small.name_strategy, |
| 5468 | .captures = captures, | 5479 | .captures = captures, |
| ... | @@ -5479,6 +5490,7 @@ pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl | ... | @@ -5479,6 +5490,7 @@ pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl |
| 5479 | } | 5490 | } |
| 5480 | pub const UnwrappedUnionDecl = struct { | 5491 | pub const UnwrappedUnionDecl = struct { |
| 5481 | src_line: u32, | 5492 | src_line: u32, |
| 5493 | src_column: u32, | ||
| 5482 | src_node: Ast.Node.Index, | 5494 | src_node: Ast.Node.Index, |
| 5483 | name_strategy: Inst.NameStrategy, | 5495 | name_strategy: Inst.NameStrategy, |
| 5484 | 5496 | ||
| ... | @@ -5590,6 +5602,7 @@ pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { | ... | @@ -5590,6 +5602,7 @@ pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { |
| 5590 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); | 5602 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); |
| 5591 | return .{ | 5603 | return .{ |
| 5592 | .src_line = extra.data.src_line, | 5604 | .src_line = extra.data.src_line, |
| 5605 | .src_column = extra.data.src_column, | ||
| 5593 | .src_node = extra.data.src_node, | 5606 | .src_node = extra.data.src_node, |
| 5594 | .name_strategy = small.name_strategy, | 5607 | .name_strategy = small.name_strategy, |
| 5595 | .captures = captures, | 5608 | .captures = captures, |
| ... | @@ -5604,6 +5617,7 @@ pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { | ... | @@ -5604,6 +5617,7 @@ pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { |
| 5604 | } | 5617 | } |
| 5605 | pub const UnwrappedEnumDecl = struct { | 5618 | pub const UnwrappedEnumDecl = struct { |
| 5606 | src_line: u32, | 5619 | src_line: u32, |
| 5620 | src_column: u32, | ||
| 5607 | src_node: Ast.Node.Index, | 5621 | src_node: Ast.Node.Index, |
| 5608 | name_strategy: Inst.NameStrategy, | 5622 | name_strategy: Inst.NameStrategy, |
| 5609 | 5623 | ||
| ... | @@ -5682,6 +5696,7 @@ pub fn getOpaqueDecl(zir: *const Zir, opaque_decl: Inst.Index) UnwrappedOpaqueDe | ... | @@ -5682,6 +5696,7 @@ pub fn getOpaqueDecl(zir: *const Zir, opaque_decl: Inst.Index) UnwrappedOpaqueDe |
| 5682 | extra_index += decls_len; | 5696 | extra_index += decls_len; |
| 5683 | return .{ | 5697 | return .{ |
| 5684 | .src_line = extra.data.src_line, | 5698 | .src_line = extra.data.src_line, |
| 5699 | .src_column = extra.data.src_column, | ||
| 5685 | .src_node = extra.data.src_node, | 5700 | .src_node = extra.data.src_node, |
| 5686 | .name_strategy = small.name_strategy, | 5701 | .name_strategy = small.name_strategy, |
| 5687 | .captures = captures, | 5702 | .captures = captures, |
| ... | @@ -5691,6 +5706,7 @@ pub fn getOpaqueDecl(zir: *const Zir, opaque_decl: Inst.Index) UnwrappedOpaqueDe | ... | @@ -5691,6 +5706,7 @@ pub fn getOpaqueDecl(zir: *const Zir, opaque_decl: Inst.Index) UnwrappedOpaqueDe |
| 5691 | } | 5706 | } |
| 5692 | pub const UnwrappedOpaqueDecl = struct { | 5707 | pub const UnwrappedOpaqueDecl = struct { |
| 5693 | src_line: u32, | 5708 | src_line: u32, |
| 5709 | src_column: u32, | ||
| 5694 | src_node: Ast.Node.Index, | 5710 | src_node: Ast.Node.Index, |
| 5695 | name_strategy: Inst.NameStrategy, | 5711 | name_strategy: Inst.NameStrategy, |
| 5696 | captures: []const Inst.Capture, | 5712 | captures: []const Inst.Capture, |
lib/std/zig/llvm/Builder.zig+1-2| ... | @@ -3461,8 +3461,7 @@ pub const Global = struct { | ... | @@ -3461,8 +3461,7 @@ pub const Global = struct { |
| 3461 | const old_name = self.name(builder); | 3461 | const old_name = self.name(builder); |
| 3462 | if (new_name == old_name) return; | 3462 | if (new_name == old_name) return; |
| 3463 | const index = @backingInt(self.unwrap(builder)); | 3463 | const index = @backingInt(self.unwrap(builder)); |
| 3464 | _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]); | 3464 | builder.globals.setKey(index, new_name); |
| 3465 | builder.globals.swapRemoveAt(index); | ||
| 3466 | if (!old_name.isAnon()) return; | 3465 | if (!old_name.isAnon()) return; |
| 3467 | builder.next_unnamed_global = @fromBackingInt(@backingInt(builder.next_unnamed_global) - 1); | 3466 | builder.next_unnamed_global = @fromBackingInt(@backingInt(builder.next_unnamed_global) - 1); |
| 3468 | if (builder.next_unnamed_global == old_name) return; | 3467 | if (builder.next_unnamed_global == old_name) return; |
src/Compilation.zig+14-5| ... | @@ -2101,6 +2101,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, | ... | @@ -2101,6 +2101,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2101 | .analysis_roots_buffer = undefined, | 2101 | .analysis_roots_buffer = undefined, |
| 2102 | .analysis_roots_len = 0, | 2102 | .analysis_roots_len = 0, |
| 2103 | .codegen_task_pool = try .init(arena), | 2103 | .codegen_task_pool = try .init(arena), |
| 2104 | .anon_name_counter = 0, | ||
| 2104 | }; | 2105 | }; |
| 2105 | try zcu.init(gpa, io, options.thread_limit); | 2106 | try zcu.init(gpa, io, options.thread_limit); |
| 2106 | break :blk zcu; | 2107 | break :blk zcu; |
| ... | @@ -2383,6 +2384,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, | ... | @@ -2383,6 +2384,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2383 | comp.verbose_llvm_bc != null)) | 2384 | comp.verbose_llvm_bc != null)) |
| 2384 | { | 2385 | { |
| 2385 | if (opt_zcu) |zcu| { | 2386 | if (opt_zcu) |zcu| { |
| 2387 | dev.check(.llvm_backend); | ||
| 2386 | zcu.llvm_object = try LlvmObject.create(arena, zcu); | 2388 | zcu.llvm_object = try LlvmObject.create(arena, zcu); |
| 2387 | } | 2389 | } |
| 2388 | } | 2390 | } |
| ... | @@ -2829,6 +2831,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE | ... | @@ -2829,6 +2831,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2829 | } | 2831 | } |
| 2830 | 2832 | ||
| 2831 | const is_hit = man.hit(main_progress_node) catch |err| switch (err) { | 2833 | const is_hit = man.hit(main_progress_node) catch |err| switch (err) { |
| 2834 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 2832 | error.CacheCheckFailed => switch (man.diagnostic) { | 2835 | error.CacheCheckFailed => switch (man.diagnostic) { |
| 2833 | .none => unreachable, | 2836 | .none => unreachable, |
| 2834 | .manifest_create, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure( | 2837 | .manifest_create, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure( |
| ... | @@ -2844,7 +2847,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE | ... | @@ -2844,7 +2847,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2844 | }); | 2847 | }); |
| 2845 | }, | 2848 | }, |
| 2846 | }, | 2849 | }, |
| 2847 | error.OutOfMemory, error.Canceled => |e| return e, | ||
| 2848 | error.InvalidFormat => return comp.setMiscFailure( | 2850 | error.InvalidFormat => return comp.setMiscFailure( |
| 2849 | .check_whole_cache, | 2851 | .check_whole_cache, |
| 2850 | "failed to check cache: invalid manifest file format", | 2852 | "failed to check cache: invalid manifest file format", |
| ... | @@ -3283,8 +3285,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error | ... | @@ -3283,8 +3285,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3283 | .fuzz = comp.config.any_fuzz, | 3285 | .fuzz = comp.config.any_fuzz, |
| 3284 | .lto = comp.config.lto, | 3286 | .lto = comp.config.lto, |
| 3285 | }) catch |err| switch (err) { | 3287 | }) catch |err| switch (err) { |
| 3288 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 3286 | error.AlreadyReported => {}, | 3289 | error.AlreadyReported => {}, |
| 3287 | error.OutOfMemory => |e| return e, | ||
| 3288 | }; | 3290 | }; |
| 3289 | 3291 | ||
| 3290 | if (zcu_obj_path) |path| { | 3292 | if (zcu_obj_path) |path| { |
| ... | @@ -3293,8 +3295,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error | ... | @@ -3293,8 +3295,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3293 | // `link.Queue` has not called `prelink` because it knew we would want to send that | 3295 | // `link.Queue` has not called `prelink` because it knew we would want to send that |
| 3294 | // final link input. It is *our* responsibility to call `prelink` now we're done. | 3296 | // final link input. It is *our* responsibility to call `prelink` now we're done. |
| 3295 | comp.bin_file.?.prelink() catch |err| switch (err) { | 3297 | comp.bin_file.?.prelink() catch |err| switch (err) { |
| 3298 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 3296 | error.AlreadyReported => return, | 3299 | error.AlreadyReported => return, |
| 3297 | else => |e| return e, | ||
| 3298 | }; | 3300 | }; |
| 3299 | } | 3301 | } |
| 3300 | } | 3302 | } |
| ... | @@ -3308,8 +3310,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error | ... | @@ -3308,8 +3310,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3308 | }; | 3310 | }; |
| 3309 | // This is needed before reading the error flags. | 3311 | // This is needed before reading the error flags. |
| 3310 | lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) { | 3312 | lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) { |
| 3313 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 3311 | error.AlreadyReported => return, | 3314 | error.AlreadyReported => return, |
| 3312 | error.OutOfMemory, error.Canceled => |e| return e, | ||
| 3313 | }; | 3315 | }; |
| 3314 | } | 3316 | } |
| 3315 | } | 3317 | } |
| ... | @@ -3709,8 +3711,15 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -3709,8 +3711,15 @@ pub fn saveState(comp: *Compilation) !void { |
| 3709 | 3711 | ||
| 3710 | // linker state | 3712 | // linker state |
| 3711 | switch (lf.tag) { | 3713 | switch (lf.tag) { |
| 3714 | .elf => {}, | ||
| 3715 | .elf2 => { | ||
| 3716 | const elf = lf.cast(.elf2).?; | ||
| 3717 | try bufs.ensureUnusedCapacity(3); | ||
| 3718 | addBuf(&bufs, @ptrCast(elf.mf.nodes.items)); | ||
| 3719 | addBuf(&bufs, @ptrCast(&elf.mf.free_ni)); | ||
| 3720 | addBuf(&bufs, @ptrCast(elf.mf.large.items)); | ||
| 3721 | }, | ||
| 3712 | .wasm => { | 3722 | .wasm => { |
| 3713 | dev.check(link.File.Tag.wasm.devFeature()); | ||
| 3714 | const wasm = lf.cast(.wasm).?; | 3723 | const wasm = lf.cast(.wasm).?; |
| 3715 | const is_obj = comp.config.output_mode == .Obj; | 3724 | const is_obj = comp.config.output_mode == .Obj; |
| 3716 | try bufs.ensureUnusedCapacity(85); | 3725 | try bufs.ensureUnusedCapacity(85); |
src/IncrementalDebugServer.zig+3-3| ... | @@ -243,7 +243,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const | ... | @@ -243,7 +243,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const |
| 243 | var num_results: usize = 0; | 243 | var num_results: usize = 0; |
| 244 | for (zcu.incremental_debug_state.types.keys()) |type_ip_index| { | 244 | for (zcu.incremental_debug_state.types.keys()) |type_ip_index| { |
| 245 | const ty: Type = .fromInterned(type_ip_index); | 245 | const ty: Type = .fromInterned(type_ip_index); |
| 246 | const ty_name = ty.containerTypeName(ip).toSlice(ip); | 246 | const ty_name = ty.containerTypeName(ip).fqn.toSlice(ip); |
| 247 | const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) { | 247 | const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) { |
| 248 | 0b00 => std.mem.find(u8, ty_name, query) != null, | 248 | 0b00 => std.mem.find(u8, ty_name, query) != null, |
| 249 | 0b01 => std.mem.endsWith(u8, ty_name, query), | 249 | 0b01 => std.mem.endsWith(u8, ty_name, query), |
| ... | @@ -347,7 +347,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const | ... | @@ -347,7 +347,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const |
| 347 | \\created on generation: {d} | 347 | \\created on generation: {d} |
| 348 | \\ | 348 | \\ |
| 349 | , .{ | 349 | , .{ |
| 350 | Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip), | 350 | Type.fromInterned(ip_index).containerTypeName(ip).fqn.fmt(ip), |
| 351 | create_gen, | 351 | create_gen, |
| 352 | }); | 352 | }); |
| 353 | } else if (std.mem.eql(u8, cmd_str, "type_namespace")) { | 353 | } else if (std.mem.eql(u8, cmd_str, "type_namespace")) { |
| ... | @@ -451,7 +451,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: *Io.Writer) Io.Writer.Error!void { | ... | @@ -451,7 +451,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: *Io.Writer) Io.Writer.Error!void { |
| 451 | .union_type, | 451 | .union_type, |
| 452 | .enum_type, | 452 | .enum_type, |
| 453 | .opaque_type, | 453 | .opaque_type, |
| 454 | => try w.print("{f}[{d}]", .{ ty.containerTypeName(ip).fmt(ip), @backingInt(ty.toIntern()) }), | 454 | => try w.print("{f}[{d}]", .{ ty.containerTypeName(ip).fqn.fmt(ip), @backingInt(ty.toIntern()) }), |
| 455 | 455 | ||
| 456 | else => unreachable, | 456 | else => unreachable, |
| 457 | } | 457 | } |
src/InternPool.zig+54-6| ... | @@ -3207,9 +3207,10 @@ pub const LoadedStructType = struct { | ... | @@ -3207,9 +3207,10 @@ pub const LoadedStructType = struct { |
| 3207 | captures: CaptureValue.Slice, | 3207 | captures: CaptureValue.Slice, |
| 3208 | is_reified: bool, | 3208 | is_reified: bool, |
| 3209 | 3209 | ||
| 3210 | // TODO: the non-fqn will be needed by the new dwarf structure | ||
| 3211 | /// The name of this struct type. | 3210 | /// The name of this struct type. |
| 3212 | name: NullTerminatedString, | 3211 | name: NullTerminatedString, |
| 3212 | /// The fully-qualified name of this struct type. | ||
| 3213 | fqn: NullTerminatedString, | ||
| 3213 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | 3214 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. |
| 3214 | /// Otherwise, or if this is a file's root struct type, this is `.none`. | 3215 | /// Otherwise, or if this is a file's root struct type, this is `.none`. |
| 3215 | name_nav: Nav.Index.Optional, | 3216 | name_nav: Nav.Index.Optional, |
| ... | @@ -3390,9 +3391,10 @@ pub const LoadedUnionType = struct { | ... | @@ -3390,9 +3391,10 @@ pub const LoadedUnionType = struct { |
| 3390 | captures: CaptureValue.Slice, | 3391 | captures: CaptureValue.Slice, |
| 3391 | is_reified: bool, | 3392 | is_reified: bool, |
| 3392 | 3393 | ||
| 3393 | // TODO: the non-fqn will be needed by the new dwarf structure | ||
| 3394 | /// The name of this union type. | 3394 | /// The name of this union type. |
| 3395 | name: NullTerminatedString, | 3395 | name: NullTerminatedString, |
| 3396 | /// The fully-qualified name of this union type. | ||
| 3397 | fqn: NullTerminatedString, | ||
| 3396 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | 3398 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. |
| 3397 | /// Otherwise, this is `.none`. | 3399 | /// Otherwise, this is `.none`. |
| 3398 | name_nav: Nav.Index.Optional, | 3400 | name_nav: Nav.Index.Optional, |
| ... | @@ -3457,9 +3459,10 @@ pub const LoadedEnumType = struct { | ... | @@ -3457,9 +3459,10 @@ pub const LoadedEnumType = struct { |
| 3457 | owner_union: Index, | 3459 | owner_union: Index, |
| 3458 | is_reified: bool, | 3460 | is_reified: bool, |
| 3459 | 3461 | ||
| 3460 | // TODO: the non-fqn will be needed by the new dwarf structure | ||
| 3461 | /// The name of this enum type. | 3462 | /// The name of this enum type. |
| 3462 | name: NullTerminatedString, | 3463 | name: NullTerminatedString, |
| 3464 | /// The fully-qualified name of this enum type. | ||
| 3465 | fqn: NullTerminatedString, | ||
| 3463 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | 3466 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. |
| 3464 | /// Otherwise, this is `.none`. | 3467 | /// Otherwise, this is `.none`. |
| 3465 | name_nav: Nav.Index.Optional, | 3468 | name_nav: Nav.Index.Optional, |
| ... | @@ -3519,9 +3522,10 @@ pub const LoadedOpaqueType = struct { | ... | @@ -3519,9 +3522,10 @@ pub const LoadedOpaqueType = struct { |
| 3519 | zir_index: TrackedInst.Index, | 3522 | zir_index: TrackedInst.Index, |
| 3520 | captures: CaptureValue.Slice, | 3523 | captures: CaptureValue.Slice, |
| 3521 | 3524 | ||
| 3522 | // TODO: the non-fqn will be needed by the new dwarf structure | ||
| 3523 | /// The name of this opaque type. | 3525 | /// The name of this opaque type. |
| 3524 | name: NullTerminatedString, | 3526 | name: NullTerminatedString, |
| 3527 | /// The fully-qualified name of this opaque type. | ||
| 3528 | fqn: NullTerminatedString, | ||
| 3525 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | 3529 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. |
| 3526 | /// Otherwise, this is `.none`. | 3530 | /// Otherwise, this is `.none`. |
| 3527 | name_nav: Nav.Index.Optional, | 3531 | name_nav: Nav.Index.Optional, |
| ... | @@ -3607,6 +3611,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { | ... | @@ -3607,6 +3611,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3607 | .captures = captures, | 3611 | .captures = captures, |
| 3608 | .is_reified = extra.data.flags.any_captures == .reified, | 3612 | .is_reified = extra.data.flags.any_captures == .reified, |
| 3609 | .name = extra.data.name, | 3613 | .name = extra.data.name, |
| 3614 | .fqn = extra.data.fqn, | ||
| 3610 | .name_nav = extra.data.name_nav, | 3615 | .name_nav = extra.data.name_nav, |
| 3611 | .namespace = extra.data.namespace, | 3616 | .namespace = extra.data.namespace, |
| 3612 | .layout = switch (extra.data.flags.layout) { | 3617 | .layout = switch (extra.data.flags.layout) { |
| ... | @@ -3670,6 +3675,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { | ... | @@ -3670,6 +3675,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3670 | .captures = captures, | 3675 | .captures = captures, |
| 3671 | .is_reified = extra.data.bits.captures_len == .reified, | 3676 | .is_reified = extra.data.bits.captures_len == .reified, |
| 3672 | .name = extra.data.name, | 3677 | .name = extra.data.name, |
| 3678 | .fqn = extra.data.fqn, | ||
| 3673 | .name_nav = extra.data.name_nav, | 3679 | .name_nav = extra.data.name_nav, |
| 3674 | .namespace = extra.data.namespace, | 3680 | .namespace = extra.data.namespace, |
| 3675 | .layout = .@"packed", | 3681 | .layout = .@"packed", |
| ... | @@ -3745,6 +3751,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { | ... | @@ -3745,6 +3751,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { |
| 3745 | .captures = captures, | 3751 | .captures = captures, |
| 3746 | .is_reified = extra.data.flags.any_captures == .reified, | 3752 | .is_reified = extra.data.flags.any_captures == .reified, |
| 3747 | .name = extra.data.name, | 3753 | .name = extra.data.name, |
| 3754 | .fqn = extra.data.fqn, | ||
| 3748 | .name_nav = extra.data.name_nav, | 3755 | .name_nav = extra.data.name_nav, |
| 3749 | .namespace = extra.data.namespace, | 3756 | .namespace = extra.data.namespace, |
| 3750 | .layout = switch (extra.data.flags.layout) { | 3757 | .layout = switch (extra.data.flags.layout) { |
| ... | @@ -3800,6 +3807,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { | ... | @@ -3800,6 +3807,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { |
| 3800 | .captures = captures, | 3807 | .captures = captures, |
| 3801 | .is_reified = extra.data.bits.captures_len == .reified, | 3808 | .is_reified = extra.data.bits.captures_len == .reified, |
| 3802 | .name = extra.data.name, | 3809 | .name = extra.data.name, |
| 3810 | .fqn = extra.data.fqn, | ||
| 3803 | .name_nav = extra.data.name_nav, | 3811 | .name_nav = extra.data.name_nav, |
| 3804 | .namespace = extra.data.namespace, | 3812 | .namespace = extra.data.namespace, |
| 3805 | .layout = .@"packed", | 3813 | .layout = .@"packed", |
| ... | @@ -3880,6 +3888,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { | ... | @@ -3880,6 +3888,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { |
| 3880 | .is_reified = extra.data.bits.captures_len == .reified, | 3888 | .is_reified = extra.data.bits.captures_len == .reified, |
| 3881 | .owner_union = owner_union, | 3889 | .owner_union = owner_union, |
| 3882 | .name = extra.data.name, | 3890 | .name = extra.data.name, |
| 3891 | .fqn = extra.data.fqn, | ||
| 3883 | .name_nav = extra.data.name_nav, | 3892 | .name_nav = extra.data.name_nav, |
| 3884 | .namespace = extra.data.namespace, | 3893 | .namespace = extra.data.namespace, |
| 3885 | .int_tag_type = extra.data.int_tag_type, | 3894 | .int_tag_type = extra.data.int_tag_type, |
| ... | @@ -3906,6 +3915,7 @@ pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType { | ... | @@ -3906,6 +3915,7 @@ pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType { |
| 3906 | .len = extra.data.captures_len, | 3915 | .len = extra.data.captures_len, |
| 3907 | }, | 3916 | }, |
| 3908 | .name = extra.data.name, | 3917 | .name = extra.data.name, |
| 3918 | .fqn = extra.data.fqn, | ||
| 3909 | .name_nav = extra.data.name_nav, | 3919 | .name_nav = extra.data.name_nav, |
| 3910 | .namespace = extra.data.namespace, | 3920 | .namespace = extra.data.namespace, |
| 3911 | }; | 3921 | }; |
| ... | @@ -5538,6 +5548,7 @@ pub const Tag = enum(u8) { | ... | @@ -5538,6 +5548,7 @@ pub const Tag = enum(u8) { |
| 5538 | zir_index: TrackedInst.Index, | 5548 | zir_index: TrackedInst.Index, |
| 5539 | 5549 | ||
| 5540 | name: NullTerminatedString, | 5550 | name: NullTerminatedString, |
| 5551 | fqn: NullTerminatedString, | ||
| 5541 | name_nav: Nav.Index.Optional, | 5552 | name_nav: Nav.Index.Optional, |
| 5542 | namespace: NamespaceIndex, | 5553 | namespace: NamespaceIndex, |
| 5543 | 5554 | ||
| ... | @@ -5580,6 +5591,7 @@ pub const Tag = enum(u8) { | ... | @@ -5580,6 +5591,7 @@ pub const Tag = enum(u8) { |
| 5580 | bits: Bits, | 5591 | bits: Bits, |
| 5581 | 5592 | ||
| 5582 | name: NullTerminatedString, | 5593 | name: NullTerminatedString, |
| 5594 | fqn: NullTerminatedString, | ||
| 5583 | name_nav: Nav.Index.Optional, | 5595 | name_nav: Nav.Index.Optional, |
| 5584 | namespace: NamespaceIndex, | 5596 | namespace: NamespaceIndex, |
| 5585 | 5597 | ||
| ... | @@ -5614,6 +5626,7 @@ pub const Tag = enum(u8) { | ... | @@ -5614,6 +5626,7 @@ pub const Tag = enum(u8) { |
| 5614 | zir_index: TrackedInst.Index, | 5626 | zir_index: TrackedInst.Index, |
| 5615 | 5627 | ||
| 5616 | name: NullTerminatedString, | 5628 | name: NullTerminatedString, |
| 5629 | fqn: NullTerminatedString, | ||
| 5617 | name_nav: Nav.Index.Optional, | 5630 | name_nav: Nav.Index.Optional, |
| 5618 | namespace: NamespaceIndex, | 5631 | namespace: NamespaceIndex, |
| 5619 | /// The enum that provides the list of field names and values. | 5632 | /// The enum that provides the list of field names and values. |
| ... | @@ -5673,6 +5686,7 @@ pub const Tag = enum(u8) { | ... | @@ -5673,6 +5686,7 @@ pub const Tag = enum(u8) { |
| 5673 | bits: Bits, | 5686 | bits: Bits, |
| 5674 | 5687 | ||
| 5675 | name: NullTerminatedString, | 5688 | name: NullTerminatedString, |
| 5689 | fqn: NullTerminatedString, | ||
| 5676 | name_nav: Nav.Index.Optional, | 5690 | name_nav: Nav.Index.Optional, |
| 5677 | namespace: NamespaceIndex, | 5691 | namespace: NamespaceIndex, |
| 5678 | 5692 | ||
| ... | @@ -5708,6 +5722,7 @@ pub const Tag = enum(u8) { | ... | @@ -5708,6 +5722,7 @@ pub const Tag = enum(u8) { |
| 5708 | bits: Bits, | 5722 | bits: Bits, |
| 5709 | 5723 | ||
| 5710 | name: NullTerminatedString, | 5724 | name: NullTerminatedString, |
| 5725 | fqn: NullTerminatedString, | ||
| 5711 | name_nav: Nav.Index.Optional, | 5726 | name_nav: Nav.Index.Optional, |
| 5712 | namespace: NamespaceIndex, | 5727 | namespace: NamespaceIndex, |
| 5713 | 5728 | ||
| ... | @@ -5735,6 +5750,7 @@ pub const Tag = enum(u8) { | ... | @@ -5735,6 +5750,7 @@ pub const Tag = enum(u8) { |
| 5735 | captures_len: u32, | 5750 | captures_len: u32, |
| 5736 | 5751 | ||
| 5737 | name: NullTerminatedString, | 5752 | name: NullTerminatedString, |
| 5753 | fqn: NullTerminatedString, | ||
| 5738 | name_nav: Nav.Index.Optional, | 5754 | name_nav: Nav.Index.Optional, |
| 5739 | namespace: NamespaceIndex, | 5755 | namespace: NamespaceIndex, |
| 5740 | }; | 5756 | }; |
| ... | @@ -8063,6 +8079,7 @@ pub fn getDeclaredStructType( | ... | @@ -8063,6 +8079,7 @@ pub fn getDeclaredStructType( |
| 8063 | .want_layout = false, | 8079 | .want_layout = false, |
| 8064 | }, | 8080 | }, |
| 8065 | .name = undefined, // set by `finish` | 8081 | .name = undefined, // set by `finish` |
| 8082 | .fqn = undefined, // set by `finish` | ||
| 8066 | .name_nav = undefined, // set by `finish` | 8083 | .name_nav = undefined, // set by `finish` |
| 8067 | .namespace = undefined, // set by `finish` | 8084 | .namespace = undefined, // set by `finish` |
| 8068 | .backing_int_type = .none, | 8085 | .backing_int_type = .none, |
| ... | @@ -8086,6 +8103,7 @@ pub fn getDeclaredStructType( | ... | @@ -8086,6 +8103,7 @@ pub fn getDeclaredStructType( |
| 8086 | .index = gop.put(), | 8103 | .index = gop.put(), |
| 8087 | .tid = tid, | 8104 | .tid = tid, |
| 8088 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, | 8105 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, |
| 8106 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "fqn").?, | ||
| 8089 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, | 8107 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, |
| 8090 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, | 8108 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, |
| 8091 | .field_names = undefined, | 8109 | .field_names = undefined, |
| ... | @@ -8111,6 +8129,7 @@ pub fn getDeclaredStructType( | ... | @@ -8111,6 +8129,7 @@ pub fn getDeclaredStructType( |
| 8111 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ | 8129 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ |
| 8112 | .zir_index = ini.zir_index, | 8130 | .zir_index = ini.zir_index, |
| 8113 | .name = undefined, // set by `finish` | 8131 | .name = undefined, // set by `finish` |
| 8132 | .fqn = undefined, // set by `finish` | ||
| 8114 | .name_nav = undefined, // set by `finish` | 8133 | .name_nav = undefined, // set by `finish` |
| 8115 | .namespace = undefined, // set by `finish` | 8134 | .namespace = undefined, // set by `finish` |
| 8116 | .fields_len = ini.fields_len, | 8135 | .fields_len = ini.fields_len, |
| ... | @@ -8154,6 +8173,7 @@ pub fn getDeclaredStructType( | ... | @@ -8154,6 +8173,7 @@ pub fn getDeclaredStructType( |
| 8154 | .index = gop.put(), | 8173 | .index = gop.put(), |
| 8155 | .tid = tid, | 8174 | .tid = tid, |
| 8156 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, | 8175 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, |
| 8176 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "fqn").?, | ||
| 8157 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, | 8177 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, |
| 8158 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, | 8178 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, |
| 8159 | .field_names = undefined, | 8179 | .field_names = undefined, |
| ... | @@ -8207,6 +8227,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe | ... | @@ -8207,6 +8227,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe |
| 8207 | .want_layout = false, | 8227 | .want_layout = false, |
| 8208 | }, | 8228 | }, |
| 8209 | .name = undefined, // set by `finish` | 8229 | .name = undefined, // set by `finish` |
| 8230 | .fqn = undefined, // set by `finish` | ||
| 8210 | .name_nav = undefined, // set by `finish` | 8231 | .name_nav = undefined, // set by `finish` |
| 8211 | .namespace = undefined, // set by `finish` | 8232 | .namespace = undefined, // set by `finish` |
| 8212 | .backing_int_type = ini.packed_backing_int_type, | 8233 | .backing_int_type = ini.packed_backing_int_type, |
| ... | @@ -8233,6 +8254,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe | ... | @@ -8233,6 +8254,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe |
| 8233 | .index = gop.put(), | 8254 | .index = gop.put(), |
| 8234 | .tid = tid, | 8255 | .tid = tid, |
| 8235 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, | 8256 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, |
| 8257 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "fqn").?, | ||
| 8236 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, | 8258 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, |
| 8237 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, | 8259 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, |
| 8238 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | 8260 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, |
| ... | @@ -8260,6 +8282,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe | ... | @@ -8260,6 +8282,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe |
| 8260 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ | 8282 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ |
| 8261 | .zir_index = ini.zir_index, | 8283 | .zir_index = ini.zir_index, |
| 8262 | .name = undefined, // set by `finish` | 8284 | .name = undefined, // set by `finish` |
| 8285 | .fqn = undefined, // set by `finish` | ||
| 8263 | .name_nav = undefined, // set by `finish` | 8286 | .name_nav = undefined, // set by `finish` |
| 8264 | .namespace = undefined, // set by `finish` | 8287 | .namespace = undefined, // set by `finish` |
| 8265 | .fields_len = ini.fields_len, | 8288 | .fields_len = ini.fields_len, |
| ... | @@ -8305,6 +8328,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe | ... | @@ -8305,6 +8328,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe |
| 8305 | .index = gop.put(), | 8328 | .index = gop.put(), |
| 8306 | .tid = tid, | 8329 | .tid = tid, |
| 8307 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, | 8330 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, |
| 8331 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "fqn").?, | ||
| 8308 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, | 8332 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, |
| 8309 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, | 8333 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, |
| 8310 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | 8334 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, |
| ... | @@ -8378,6 +8402,7 @@ pub fn getDeclaredUnionType( | ... | @@ -8378,6 +8402,7 @@ pub fn getDeclaredUnionType( |
| 8378 | .want_layout = false, | 8402 | .want_layout = false, |
| 8379 | }, | 8403 | }, |
| 8380 | .name = undefined, // set by `finish` | 8404 | .name = undefined, // set by `finish` |
| 8405 | .fqn = undefined, // set by `finish` | ||
| 8381 | .name_nav = undefined, // set by `finish` | 8406 | .name_nav = undefined, // set by `finish` |
| 8382 | .namespace = undefined, // set by `finish` | 8407 | .namespace = undefined, // set by `finish` |
| 8383 | .backing_int_type = .none, | 8408 | .backing_int_type = .none, |
| ... | @@ -8397,6 +8422,7 @@ pub fn getDeclaredUnionType( | ... | @@ -8397,6 +8422,7 @@ pub fn getDeclaredUnionType( |
| 8397 | .index = gop.put(), | 8422 | .index = gop.put(), |
| 8398 | .tid = tid, | 8423 | .tid = tid, |
| 8399 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, | 8424 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, |
| 8425 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "fqn").?, | ||
| 8400 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, | 8426 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, |
| 8401 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, | 8427 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, |
| 8402 | .field_names = undefined, | 8428 | .field_names = undefined, |
| ... | @@ -8417,6 +8443,7 @@ pub fn getDeclaredUnionType( | ... | @@ -8417,6 +8443,7 @@ pub fn getDeclaredUnionType( |
| 8417 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ | 8443 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ |
| 8418 | .zir_index = ini.zir_index, | 8444 | .zir_index = ini.zir_index, |
| 8419 | .name = undefined, // set by `finish` | 8445 | .name = undefined, // set by `finish` |
| 8446 | .fqn = undefined, // set by `finish` | ||
| 8420 | .name_nav = undefined, // set by `finish` | 8447 | .name_nav = undefined, // set by `finish` |
| 8421 | .namespace = undefined, // set by `finish` | 8448 | .namespace = undefined, // set by `finish` |
| 8422 | .enum_tag_type = .none, | 8449 | .enum_tag_type = .none, |
| ... | @@ -8451,6 +8478,7 @@ pub fn getDeclaredUnionType( | ... | @@ -8451,6 +8478,7 @@ pub fn getDeclaredUnionType( |
| 8451 | .index = gop.put(), | 8478 | .index = gop.put(), |
| 8452 | .tid = tid, | 8479 | .tid = tid, |
| 8453 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, | 8480 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, |
| 8481 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "fqn").?, | ||
| 8454 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, | 8482 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, |
| 8455 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, | 8483 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, |
| 8456 | .field_names = undefined, | 8484 | .field_names = undefined, |
| ... | @@ -8501,6 +8529,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per | ... | @@ -8501,6 +8529,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per |
| 8501 | .want_layout = false, | 8529 | .want_layout = false, |
| 8502 | }, | 8530 | }, |
| 8503 | .name = undefined, // set by `finish` | 8531 | .name = undefined, // set by `finish` |
| 8532 | .fqn = undefined, // set by `finish` | ||
| 8504 | .name_nav = undefined, // set by `finish` | 8533 | .name_nav = undefined, // set by `finish` |
| 8505 | .namespace = undefined, // set by `finish` | 8534 | .namespace = undefined, // set by `finish` |
| 8506 | .backing_int_type = ini.packed_backing_int_type, | 8535 | .backing_int_type = ini.packed_backing_int_type, |
| ... | @@ -8523,6 +8552,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per | ... | @@ -8523,6 +8552,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per |
| 8523 | .index = gop.put(), | 8552 | .index = gop.put(), |
| 8524 | .tid = tid, | 8553 | .tid = tid, |
| 8525 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, | 8554 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, |
| 8555 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "fqn").?, | ||
| 8526 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, | 8556 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, |
| 8527 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, | 8557 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, |
| 8528 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | 8558 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, |
| ... | @@ -8543,6 +8573,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per | ... | @@ -8543,6 +8573,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per |
| 8543 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ | 8573 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ |
| 8544 | .zir_index = ini.zir_index, | 8574 | .zir_index = ini.zir_index, |
| 8545 | .name = undefined, // set by `finish` | 8575 | .name = undefined, // set by `finish` |
| 8576 | .fqn = undefined, // set by `finish` | ||
| 8546 | .name_nav = undefined, // set by `finish` | 8577 | .name_nav = undefined, // set by `finish` |
| 8547 | .namespace = undefined, // set by `finish` | 8578 | .namespace = undefined, // set by `finish` |
| 8548 | .enum_tag_type = ini.enum_tag_type, | 8579 | .enum_tag_type = ini.enum_tag_type, |
| ... | @@ -8578,6 +8609,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per | ... | @@ -8578,6 +8609,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per |
| 8578 | .index = gop.put(), | 8609 | .index = gop.put(), |
| 8579 | .tid = tid, | 8610 | .tid = tid, |
| 8580 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, | 8611 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, |
| 8612 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "fqn").?, | ||
| 8581 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, | 8613 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, |
| 8582 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, | 8614 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, |
| 8583 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | 8615 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, |
| ... | @@ -8654,6 +8686,7 @@ pub fn getDeclaredEnumType( | ... | @@ -8654,6 +8686,7 @@ pub fn getDeclaredEnumType( |
| 8654 | .want_layout = false, | 8686 | .want_layout = false, |
| 8655 | }, | 8687 | }, |
| 8656 | .name = undefined, // set by `finish` | 8688 | .name = undefined, // set by `finish` |
| 8689 | .fqn = undefined, // set by `finish` | ||
| 8657 | .name_nav = undefined, // set by `finish` | 8690 | .name_nav = undefined, // set by `finish` |
| 8658 | .namespace = undefined, // set by `finish` | 8691 | .namespace = undefined, // set by `finish` |
| 8659 | .int_tag_type = .none, | 8692 | .int_tag_type = .none, |
| ... | @@ -8673,6 +8706,7 @@ pub fn getDeclaredEnumType( | ... | @@ -8673,6 +8706,7 @@ pub fn getDeclaredEnumType( |
| 8673 | .index = gop.put(), | 8706 | .index = gop.put(), |
| 8674 | .tid = tid, | 8707 | .tid = tid, |
| 8675 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, | 8708 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, |
| 8709 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "fqn").?, | ||
| 8676 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, | 8710 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, |
| 8677 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, | 8711 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, |
| 8678 | .field_names = undefined, | 8712 | .field_names = undefined, |
| ... | @@ -8729,6 +8763,7 @@ pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerT | ... | @@ -8729,6 +8763,7 @@ pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerT |
| 8729 | .want_layout = false, | 8763 | .want_layout = false, |
| 8730 | }, | 8764 | }, |
| 8731 | .name = undefined, // set by `finish` | 8765 | .name = undefined, // set by `finish` |
| 8766 | .fqn = undefined, // set by `finish` | ||
| 8732 | .name_nav = undefined, // set by `finish` | 8767 | .name_nav = undefined, // set by `finish` |
| 8733 | .namespace = undefined, // set by `finish` | 8768 | .namespace = undefined, // set by `finish` |
| 8734 | .int_tag_type = ini.int_tag_type, | 8769 | .int_tag_type = ini.int_tag_type, |
| ... | @@ -8750,6 +8785,7 @@ pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerT | ... | @@ -8750,6 +8785,7 @@ pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerT |
| 8750 | .index = gop.put(), | 8785 | .index = gop.put(), |
| 8751 | .tid = tid, | 8786 | .tid = tid, |
| 8752 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, | 8787 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, |
| 8788 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "fqn").?, | ||
| 8753 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, | 8789 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, |
| 8754 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, | 8790 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, |
| 8755 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | 8791 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, |
| ... | @@ -8828,6 +8864,7 @@ pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu | ... | @@ -8828,6 +8864,7 @@ pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu |
| 8828 | .want_layout = false, | 8864 | .want_layout = false, |
| 8829 | }, | 8865 | }, |
| 8830 | .name = undefined, // set by `finish` | 8866 | .name = undefined, // set by `finish` |
| 8867 | .fqn = undefined, // set by `finish` | ||
| 8831 | .name_nav = undefined, // set by `finish` | 8868 | .name_nav = undefined, // set by `finish` |
| 8832 | .namespace = undefined, // set by `finish` | 8869 | .namespace = undefined, // set by `finish` |
| 8833 | .int_tag_type = .none, | 8870 | .int_tag_type = .none, |
| ... | @@ -8849,6 +8886,7 @@ pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu | ... | @@ -8849,6 +8886,7 @@ pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu |
| 8849 | .index = gop.put(), | 8886 | .index = gop.put(), |
| 8850 | .tid = tid, | 8887 | .tid = tid, |
| 8851 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, | 8888 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, |
| 8889 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "fqn").?, | ||
| 8852 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, | 8890 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, |
| 8853 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, | 8891 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, |
| 8854 | .field_names = undefined, | 8892 | .field_names = undefined, |
| ... | @@ -8880,6 +8918,7 @@ pub fn getDeclaredOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.P | ... | @@ -8880,6 +8918,7 @@ pub fn getDeclaredOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.P |
| 8880 | .zir_index = ini.zir_index, | 8918 | .zir_index = ini.zir_index, |
| 8881 | .captures_len = @intCast(ini.captures.len), | 8919 | .captures_len = @intCast(ini.captures.len), |
| 8882 | .name = undefined, // set by `finish` | 8920 | .name = undefined, // set by `finish` |
| 8921 | .fqn = undefined, // set by `finish` | ||
| 8883 | .name_nav = undefined, // set by `finish` | 8922 | .name_nav = undefined, // set by `finish` |
| 8884 | .namespace = undefined, // set by `finish` | 8923 | .namespace = undefined, // set by `finish` |
| 8885 | }); | 8924 | }); |
| ... | @@ -8892,6 +8931,7 @@ pub fn getDeclaredOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.P | ... | @@ -8892,6 +8931,7 @@ pub fn getDeclaredOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.P |
| 8892 | .index = gop.put(), | 8931 | .index = gop.put(), |
| 8893 | .tid = tid, | 8932 | .tid = tid, |
| 8894 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, | 8933 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, |
| 8934 | .type_fqn_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "fqn").?, | ||
| 8895 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?, | 8935 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?, |
| 8896 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, | 8936 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, |
| 8897 | .field_names = undefined, | 8937 | .field_names = undefined, |
| ... | @@ -8906,6 +8946,7 @@ pub const WipContainerType = struct { | ... | @@ -8906,6 +8946,7 @@ pub const WipContainerType = struct { |
| 8906 | index: Index, | 8946 | index: Index, |
| 8907 | tid: Zcu.PerThread.Id, | 8947 | tid: Zcu.PerThread.Id, |
| 8908 | type_name_index: u32, | 8948 | type_name_index: u32, |
| 8949 | type_fqn_index: u32, | ||
| 8909 | name_nav_index: u32, | 8950 | name_nav_index: u32, |
| 8910 | namespace_index: u32, | 8951 | namespace_index: u32, |
| 8911 | 8952 | ||
| ... | @@ -8923,6 +8964,7 @@ pub const WipContainerType = struct { | ... | @@ -8923,6 +8964,7 @@ pub const WipContainerType = struct { |
| 8923 | wip: WipContainerType, | 8964 | wip: WipContainerType, |
| 8924 | ip: *InternPool, | 8965 | ip: *InternPool, |
| 8925 | type_name: NullTerminatedString, | 8966 | type_name: NullTerminatedString, |
| 8967 | type_fqn: NullTerminatedString, | ||
| 8926 | /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise. | 8968 | /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise. |
| 8927 | /// This is also `.none` if we use `.parent` because we are the root struct type for a file. | 8969 | /// This is also `.none` if we use `.parent` because we are the root struct type for a file. |
| 8928 | name_nav: Nav.Index.Optional, | 8970 | name_nav: Nav.Index.Optional, |
| ... | @@ -8930,6 +8972,7 @@ pub const WipContainerType = struct { | ... | @@ -8930,6 +8972,7 @@ pub const WipContainerType = struct { |
| 8930 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); | 8972 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); |
| 8931 | const extra_items = extra.view().items(.@"0"); | 8973 | const extra_items = extra.view().items(.@"0"); |
| 8932 | extra_items[wip.type_name_index] = @backingInt(type_name); | 8974 | extra_items[wip.type_name_index] = @backingInt(type_name); |
| 8975 | extra_items[wip.type_fqn_index] = @backingInt(type_fqn); | ||
| 8933 | extra_items[wip.name_nav_index] = @backingInt(name_nav); | 8976 | extra_items[wip.name_nav_index] = @backingInt(name_nav); |
| 8934 | } | 8977 | } |
| 8935 | 8978 | ||
| ... | @@ -9503,6 +9546,7 @@ pub const GetFuncInstanceKey = struct { | ... | @@ -9503,6 +9546,7 @@ pub const GetFuncInstanceKey = struct { |
| 9503 | is_noinline: bool, | 9546 | is_noinline: bool, |
| 9504 | generic_owner: Index, | 9547 | generic_owner: Index, |
| 9505 | inferred_error_set: bool, | 9548 | inferred_error_set: bool, |
| 9549 | anon_name_counter: *u32, | ||
| 9506 | }; | 9550 | }; |
| 9507 | 9551 | ||
| 9508 | pub fn getFuncInstance( | 9552 | pub fn getFuncInstance( |
| ... | @@ -9580,6 +9624,7 @@ pub fn getFuncInstance( | ... | @@ -9580,6 +9624,7 @@ pub fn getFuncInstance( |
| 9580 | generic_owner, | 9624 | generic_owner, |
| 9581 | func_index, | 9625 | func_index, |
| 9582 | func_extra_index, | 9626 | func_extra_index, |
| 9627 | arg.anon_name_counter, | ||
| 9583 | ); | 9628 | ); |
| 9584 | return gop.put(); | 9629 | return gop.put(); |
| 9585 | } | 9630 | } |
| ... | @@ -9731,6 +9776,7 @@ fn getFuncInstanceIes( | ... | @@ -9731,6 +9776,7 @@ fn getFuncInstanceIes( |
| 9731 | generic_owner, | 9776 | generic_owner, |
| 9732 | func_index, | 9777 | func_index, |
| 9733 | func_extra_index, | 9778 | func_extra_index, |
| 9779 | arg.anon_name_counter, | ||
| 9734 | ); | 9780 | ); |
| 9735 | 9781 | ||
| 9736 | func_gop.putFinal(func_index); | 9782 | func_gop.putFinal(func_index); |
| ... | @@ -9749,14 +9795,16 @@ fn finishFuncInstance( | ... | @@ -9749,14 +9795,16 @@ fn finishFuncInstance( |
| 9749 | generic_owner: Index, | 9795 | generic_owner: Index, |
| 9750 | func_index: Index, | 9796 | func_index: Index, |
| 9751 | func_extra_index: u32, | 9797 | func_extra_index: u32, |
| 9798 | anon_name_counter: *u32, | ||
| 9752 | ) Allocator.Error!void { | 9799 | ) Allocator.Error!void { |
| 9753 | const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav); | 9800 | const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav); |
| 9754 | const fn_namespace = fn_owner_nav.analysis.?.namespace; | 9801 | const fn_namespace = fn_owner_nav.analysis.?.namespace; |
| 9755 | 9802 | ||
| 9756 | // TODO: improve this name | 9803 | // TODO: improve this name |
| 9757 | const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{ | 9804 | const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__func_{d}", .{ |
| 9758 | fn_owner_nav.name.fmt(ip), @backingInt(func_index), | 9805 | fn_owner_nav.name.fmt(ip), anon_name_counter.*, |
| 9759 | }, .no_embedded_nulls); | 9806 | }, .no_embedded_nulls); |
| 9807 | anon_name_counter.* += 1; | ||
| 9760 | const nav_fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name); | 9808 | const nav_fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name); |
| 9761 | const nav_index = try ip.createNav(gpa, io, tid, nav_name, nav_fqn, .{ | 9809 | const nav_index = try ip.createNav(gpa, io, tid, nav_name, nav_fqn, .{ |
| 9762 | .type = ip.typeOf(func_index), | 9810 | .type = ip.typeOf(func_index), |
src/Sema.zig+40-12| ... | @@ -403,6 +403,7 @@ pub const Block = struct { | ... | @@ -403,6 +403,7 @@ pub const Block = struct { |
| 403 | /// is always incorporated into the type name somehow. | 403 | /// is always incorporated into the type name somehow. |
| 404 | /// See `Sema.setTypeName`. | 404 | /// See `Sema.setTypeName`. |
| 405 | type_name_ctx: InternPool.NullTerminatedString, | 405 | type_name_ctx: InternPool.NullTerminatedString, |
| 406 | type_fqn_ctx: InternPool.NullTerminatedString, | ||
| 406 | 407 | ||
| 407 | /// Create a `LazySrcLoc` based on an `Offset` from the code being analyzed in this block. | 408 | /// Create a `LazySrcLoc` based on an `Offset` from the code being analyzed in this block. |
| 408 | /// Specifically, the given `Offset` is treated as relative to `block.src_base_inst`. | 409 | /// Specifically, the given `Offset` is treated as relative to `block.src_base_inst`. |
| ... | @@ -531,6 +532,7 @@ pub const Block = struct { | ... | @@ -531,6 +532,7 @@ pub const Block = struct { |
| 531 | .need_debug_scope = parent.need_debug_scope, | 532 | .need_debug_scope = parent.need_debug_scope, |
| 532 | .src_base_inst = parent.src_base_inst, | 533 | .src_base_inst = parent.src_base_inst, |
| 533 | .type_name_ctx = parent.type_name_ctx, | 534 | .type_name_ctx = parent.type_name_ctx, |
| 535 | .type_fqn_ctx = parent.type_fqn_ctx, | ||
| 534 | }; | 536 | }; |
| 535 | } | 537 | } |
| 536 | 538 | ||
| ... | @@ -4782,7 +4784,7 @@ fn failWithBadStructFieldAccess( | ... | @@ -4782,7 +4784,7 @@ fn failWithBadStructFieldAccess( |
| 4782 | const msg = try sema.errMsg( | 4784 | const msg = try sema.errMsg( |
| 4783 | field_src, | 4785 | field_src, |
| 4784 | "no field named '{f}' in struct '{f}'", | 4786 | "no field named '{f}' in struct '{f}'", |
| 4785 | .{ field_name.fmt(ip), struct_type.name.fmt(ip) }, | 4787 | .{ field_name.fmt(ip), struct_type.fqn.fmt(ip) }, |
| 4786 | ); | 4788 | ); |
| 4787 | errdefer msg.destroy(sema.gpa); | 4789 | errdefer msg.destroy(sema.gpa); |
| 4788 | try sema.errNote(struct_ty.srcLoc(zcu), msg, "struct declared here", .{}); | 4790 | try sema.errNote(struct_ty.srcLoc(zcu), msg, "struct declared here", .{}); |
| ... | @@ -4808,7 +4810,7 @@ fn failWithBadUnionFieldAccess( | ... | @@ -4808,7 +4810,7 @@ fn failWithBadUnionFieldAccess( |
| 4808 | const msg = try sema.errMsg( | 4810 | const msg = try sema.errMsg( |
| 4809 | field_src, | 4811 | field_src, |
| 4810 | "no field named '{f}' in union '{f}'", | 4812 | "no field named '{f}' in union '{f}'", |
| 4811 | .{ field_name.fmt(ip), union_obj.name.fmt(ip) }, | 4813 | .{ field_name.fmt(ip), union_obj.fqn.fmt(ip) }, |
| 4812 | ); | 4814 | ); |
| 4813 | errdefer msg.destroy(gpa); | 4815 | errdefer msg.destroy(gpa); |
| 4814 | try sema.errNote(union_ty.srcLoc(zcu), msg, "union declared here", .{}); | 4816 | try sema.errNote(union_ty.srcLoc(zcu), msg, "union declared here", .{}); |
| ... | @@ -5291,6 +5293,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -5291,6 +5293,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro |
| 5291 | .error_return_trace_index = parent_block.error_return_trace_index, | 5293 | .error_return_trace_index = parent_block.error_return_trace_index, |
| 5292 | .src_base_inst = parent_block.src_base_inst, | 5294 | .src_base_inst = parent_block.src_base_inst, |
| 5293 | .type_name_ctx = parent_block.type_name_ctx, | 5295 | .type_name_ctx = parent_block.type_name_ctx, |
| 5296 | .type_fqn_ctx = parent_block.type_fqn_ctx, | ||
| 5294 | }; | 5297 | }; |
| 5295 | 5298 | ||
| 5296 | defer child_block.instructions.deinit(gpa); | 5299 | defer child_block.instructions.deinit(gpa); |
| ... | @@ -6773,7 +6776,8 @@ fn analyzeCall( | ... | @@ -6773,7 +6776,8 @@ fn analyzeCall( |
| 6773 | .instructions = .empty, | 6776 | .instructions = .empty, |
| 6774 | .inlining = &generic_inlining, | 6777 | .inlining = &generic_inlining, |
| 6775 | .src_base_inst = fn_nav.analysis.?.zir_index, | 6778 | .src_base_inst = fn_nav.analysis.?.zir_index, |
| 6776 | .type_name_ctx = fn_nav.fqn, | 6779 | .type_name_ctx = fn_nav.name, |
| 6780 | .type_fqn_ctx = fn_nav.fqn, | ||
| 6777 | } else undefined; | 6781 | } else undefined; |
| 6778 | defer if (any_generic_types) generic_block.instructions.deinit(gpa); | 6782 | defer if (any_generic_types) generic_block.instructions.deinit(gpa); |
| 6779 | 6783 | ||
| ... | @@ -7039,6 +7043,7 @@ fn analyzeCall( | ... | @@ -7039,6 +7043,7 @@ fn analyzeCall( |
| 7039 | .inferred_error_set = fn_zir_info.inferred_error_set, | 7043 | .inferred_error_set = fn_zir_info.inferred_error_set, |
| 7040 | .generic_owner = func_val.?.toIntern(), | 7044 | .generic_owner = func_val.?.toIntern(), |
| 7041 | .comptime_args = comptime_args, | 7045 | .comptime_args = comptime_args, |
| 7046 | .anon_name_counter = &zcu.anon_name_counter, | ||
| 7042 | }); | 7047 | }); |
| 7043 | if (zcu.comp.debugIncremental()) { | 7048 | if (zcu.comp.debugIncremental()) { |
| 7044 | const nav = ip.indexToKey(func_instance).func.owner_nav; | 7049 | const nav = ip.indexToKey(func_instance).func.owner_nav; |
| ... | @@ -7308,7 +7313,8 @@ fn analyzeCall( | ... | @@ -7308,7 +7313,8 @@ fn analyzeCall( |
| 7308 | .runtime_loop = block.runtime_loop, | 7313 | .runtime_loop = block.runtime_loop, |
| 7309 | .runtime_index = block.runtime_index, | 7314 | .runtime_index = block.runtime_index, |
| 7310 | .src_base_inst = fn_nav.analysis.?.zir_index, | 7315 | .src_base_inst = fn_nav.analysis.?.zir_index, |
| 7311 | .type_name_ctx = fn_nav.fqn, | 7316 | .type_name_ctx = fn_nav.name, |
| 7317 | .type_fqn_ctx = fn_nav.fqn, | ||
| 7312 | }; | 7318 | }; |
| 7313 | 7319 | ||
| 7314 | defer child_block.instructions.deinit(gpa); | 7320 | defer child_block.instructions.deinit(gpa); |
| ... | @@ -17314,6 +17320,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -17314,6 +17320,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 17314 | .error_return_trace_index = block.error_return_trace_index, | 17320 | .error_return_trace_index = block.error_return_trace_index, |
| 17315 | .src_base_inst = block.src_base_inst, | 17321 | .src_base_inst = block.src_base_inst, |
| 17316 | .type_name_ctx = block.type_name_ctx, | 17322 | .type_name_ctx = block.type_name_ctx, |
| 17323 | .type_fqn_ctx = block.type_fqn_ctx, | ||
| 17317 | }; | 17324 | }; |
| 17318 | defer child_block.instructions.deinit(sema.gpa); | 17325 | defer child_block.instructions.deinit(sema.gpa); |
| 17319 | 17326 | ||
| ... | @@ -17380,6 +17387,7 @@ fn zirTypeofPeer( | ... | @@ -17380,6 +17387,7 @@ fn zirTypeofPeer( |
| 17380 | .runtime_index = block.runtime_index, | 17387 | .runtime_index = block.runtime_index, |
| 17381 | .src_base_inst = block.src_base_inst, | 17388 | .src_base_inst = block.src_base_inst, |
| 17382 | .type_name_ctx = block.type_name_ctx, | 17389 | .type_name_ctx = block.type_name_ctx, |
| 17390 | .type_fqn_ctx = block.type_fqn_ctx, | ||
| 17383 | }; | 17391 | }; |
| 17384 | defer child_block.instructions.deinit(sema.gpa); | 17392 | defer child_block.instructions.deinit(sema.gpa); |
| 17385 | // Ignore the result, we only care about the instructions in `args`. | 17393 | // Ignore the result, we only care about the instructions in `args`. |
| ... | @@ -17939,6 +17947,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label | ... | @@ -17939,6 +17947,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label |
| 17939 | .comptime_reason = block.comptime_reason, | 17947 | .comptime_reason = block.comptime_reason, |
| 17940 | .src_base_inst = block.src_base_inst, | 17948 | .src_base_inst = block.src_base_inst, |
| 17941 | .type_name_ctx = block.type_name_ctx, | 17949 | .type_name_ctx = block.type_name_ctx, |
| 17950 | .type_fqn_ctx = block.type_fqn_ctx, | ||
| 17942 | }, | 17951 | }, |
| 17943 | }; | 17952 | }; |
| 17944 | sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block); | 17953 | sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block); |
| ... | @@ -25934,6 +25943,7 @@ fn addSafetyCheck( | ... | @@ -25934,6 +25943,7 @@ fn addSafetyCheck( |
| 25934 | .comptime_reason = null, | 25943 | .comptime_reason = null, |
| 25935 | .src_base_inst = parent_block.src_base_inst, | 25944 | .src_base_inst = parent_block.src_base_inst, |
| 25936 | .type_name_ctx = parent_block.type_name_ctx, | 25945 | .type_name_ctx = parent_block.type_name_ctx, |
| 25946 | .type_fqn_ctx = parent_block.type_fqn_ctx, | ||
| 25937 | }; | 25947 | }; |
| 25938 | 25948 | ||
| 25939 | defer fail_block.instructions.deinit(gpa); | 25949 | defer fail_block.instructions.deinit(gpa); |
| ... | @@ -26028,6 +26038,7 @@ fn addSafetyCheckUnwrapError( | ... | @@ -26028,6 +26038,7 @@ fn addSafetyCheckUnwrapError( |
| 26028 | .comptime_reason = null, | 26038 | .comptime_reason = null, |
| 26029 | .src_base_inst = parent_block.src_base_inst, | 26039 | .src_base_inst = parent_block.src_base_inst, |
| 26030 | .type_name_ctx = parent_block.type_name_ctx, | 26040 | .type_name_ctx = parent_block.type_name_ctx, |
| 26041 | .type_fqn_ctx = parent_block.type_fqn_ctx, | ||
| 26031 | }; | 26042 | }; |
| 26032 | 26043 | ||
| 26033 | defer fail_block.instructions.deinit(gpa); | 26044 | defer fail_block.instructions.deinit(gpa); |
| ... | @@ -26151,6 +26162,7 @@ fn addSafetyCheckCall( | ... | @@ -26151,6 +26162,7 @@ fn addSafetyCheckCall( |
| 26151 | .comptime_reason = null, | 26162 | .comptime_reason = null, |
| 26152 | .src_base_inst = parent_block.src_base_inst, | 26163 | .src_base_inst = parent_block.src_base_inst, |
| 26153 | .type_name_ctx = parent_block.type_name_ctx, | 26164 | .type_name_ctx = parent_block.type_name_ctx, |
| 26165 | .type_fqn_ctx = parent_block.type_fqn_ctx, | ||
| 26154 | }; | 26166 | }; |
| 26155 | 26167 | ||
| 26156 | defer fail_block.instructions.deinit(gpa); | 26168 | defer fail_block.instructions.deinit(gpa); |
| ... | @@ -34993,6 +35005,7 @@ pub fn analyzeMemoizedState(sema: *Sema, stage: InternPool.MemoizedStateStage) C | ... | @@ -34993,6 +35005,7 @@ pub fn analyzeMemoizedState(sema: *Sema, stage: InternPool.MemoizedStateStage) C |
| 34993 | .comptime_reason = null, | 35005 | .comptime_reason = null, |
| 34994 | .src_base_inst = std_type.typeDeclInst(zcu).?, | 35006 | .src_base_inst = std_type.typeDeclInst(zcu).?, |
| 34995 | .type_name_ctx = .empty, | 35007 | .type_name_ctx = .empty, |
| 35008 | .type_fqn_ctx = .empty, | ||
| 34996 | }; | 35009 | }; |
| 34997 | }; | 35010 | }; |
| 34998 | defer block.instructions.deinit(gpa); | 35011 | defer block.instructions.deinit(gpa); |
| ... | @@ -35222,11 +35235,19 @@ pub fn setTypeName( | ... | @@ -35222,11 +35235,19 @@ pub fn setTypeName( |
| 35222 | io, | 35235 | io, |
| 35223 | pt.tid, | 35236 | pt.tid, |
| 35224 | "{f}__{s}_{d}", | 35237 | "{f}__{s}_{d}", |
| 35225 | .{ block.type_name_ctx.fmt(ip), anon_prefix, @backingInt(wip.index) }, | 35238 | .{ block.type_name_ctx.fmt(ip), anon_prefix, zcu.anon_name_counter }, |
| 35239 | .no_embedded_nulls, | ||
| 35240 | ), try ip.getOrPutStringFmt( | ||
| 35241 | gpa, | ||
| 35242 | io, | ||
| 35243 | pt.tid, | ||
| 35244 | "{f}__{s}_{d}", | ||
| 35245 | .{ block.type_fqn_ctx.fmt(ip), anon_prefix, zcu.anon_name_counter }, | ||
| 35226 | .no_embedded_nulls, | 35246 | .no_embedded_nulls, |
| 35227 | ), .none); | 35247 | ), .none); |
| 35248 | zcu.anon_name_counter += 1; | ||
| 35228 | }, | 35249 | }, |
| 35229 | .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()), | 35250 | .parent => wip.setName(ip, block.type_name_ctx, block.type_fqn_ctx, sema.owner.unwrap().nav_val.toOptional()), |
| 35230 | .func => { | 35251 | .func => { |
| 35231 | const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse { | 35252 | const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse { |
| 35232 | return sema.failTransitive(.{ .lost_tracking = ip.funcZirBodyInst(sema.func_index) }); | 35253 | return sema.failTransitive(.{ .lost_tracking = ip.funcZirBodyInst(sema.func_index) }); |
| ... | @@ -35236,7 +35257,7 @@ pub fn setTypeName( | ... | @@ -35236,7 +35257,7 @@ pub fn setTypeName( |
| 35236 | var aw: std.Io.Writer.Allocating = .init(gpa); | 35257 | var aw: std.Io.Writer.Allocating = .init(gpa); |
| 35237 | defer aw.deinit(); | 35258 | defer aw.deinit(); |
| 35238 | const w = &aw.writer; | 35259 | const w = &aw.writer; |
| 35239 | w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory; | 35260 | w.writeByte('(') catch return error.OutOfMemory; |
| 35240 | 35261 | ||
| 35241 | var arg_i: usize = 0; | 35262 | var arg_i: usize = 0; |
| 35242 | for (fn_info.param_body) |zir_inst| switch (zir_tags[@backingInt(zir_inst)]) { | 35263 | for (fn_info.param_body) |zir_inst| switch (zir_tags[@backingInt(zir_inst)]) { |
| ... | @@ -35271,8 +35292,13 @@ pub fn setTypeName( | ... | @@ -35271,8 +35292,13 @@ pub fn setTypeName( |
| 35271 | }; | 35292 | }; |
| 35272 | 35293 | ||
| 35273 | w.writeByte(')') catch return error.OutOfMemory; | 35294 | w.writeByte(')') catch return error.OutOfMemory; |
| 35274 | const name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls); | 35295 | wip.setName(ip, try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}{s}", .{ |
| 35275 | wip.setName(ip, name, .none); | 35296 | block.type_name_ctx.fmt(ip), |
| 35297 | aw.written(), | ||
| 35298 | }, .no_embedded_nulls), try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}{s}", .{ | ||
| 35299 | block.type_fqn_ctx.fmt(ip), | ||
| 35300 | aw.written(), | ||
| 35301 | }, .no_embedded_nulls), .none); | ||
| 35276 | }, | 35302 | }, |
| 35277 | .dbg_var => { | 35303 | .dbg_var => { |
| 35278 | // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. | 35304 | // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. |
| ... | @@ -35287,10 +35313,12 @@ pub fn setTypeName( | ... | @@ -35287,10 +35313,12 @@ pub fn setTypeName( |
| 35287 | } else { | 35313 | } else { |
| 35288 | continue :strat .anon; | 35314 | continue :strat .anon; |
| 35289 | }; | 35315 | }; |
| 35290 | const name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ | 35316 | wip.setName(ip, try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ |
| 35317 | // this "{f}." should be elided, but there's currently no way to get the parent function | ||
| 35291 | block.type_name_ctx.fmt(ip), var_name, | 35318 | block.type_name_ctx.fmt(ip), var_name, |
| 35292 | }, .no_embedded_nulls); | 35319 | }, .no_embedded_nulls), try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ |
| 35293 | wip.setName(ip, name, .none); | 35320 | block.type_fqn_ctx.fmt(ip), var_name, |
| 35321 | }, .no_embedded_nulls), .none); | ||
| 35294 | }, | 35322 | }, |
| 35295 | } | 35323 | } |
| 35296 | } | 35324 | } |
src/Sema/type_resolution.zig+15-4| ... | @@ -187,7 +187,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { | ... | @@ -187,7 +187,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { |
| 187 | 187 | ||
| 188 | const tracy = trace(@src()); | 188 | const tracy = trace(@src()); |
| 189 | defer tracy.end(); | 189 | defer tracy.end(); |
| 190 | tracy.addText(struct_ty.containerTypeName(ip).toSlice(ip)); | 190 | tracy.addText(struct_ty.containerTypeName(ip).fqn.toSlice(ip)); |
| 191 | tracy.addTextFmt("ip_index={d}", .{struct_ty.toIntern()}); | 191 | tracy.addTextFmt("ip_index={d}", .{struct_ty.toIntern()}); |
| 192 | 192 | ||
| 193 | assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); | 193 | assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); |
| ... | @@ -207,6 +207,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { | ... | @@ -207,6 +207,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { |
| 207 | .comptime_reason = undefined, // always set before using `block` | 207 | .comptime_reason = undefined, // always set before using `block` |
| 208 | .src_base_inst = struct_obj.zir_index, | 208 | .src_base_inst = struct_obj.zir_index, |
| 209 | .type_name_ctx = struct_obj.name, | 209 | .type_name_ctx = struct_obj.name, |
| 210 | .type_fqn_ctx = struct_obj.fqn, | ||
| 210 | }; | 211 | }; |
| 211 | defer block.instructions.deinit(gpa); | 212 | defer block.instructions.deinit(gpa); |
| 212 | 213 | ||
| ... | @@ -613,7 +614,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { | ... | @@ -613,7 +614,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { |
| 613 | 614 | ||
| 614 | const tracy = trace(@src()); | 615 | const tracy = trace(@src()); |
| 615 | defer tracy.end(); | 616 | defer tracy.end(); |
| 616 | tracy.addText(struct_ty.containerTypeName(ip).toSlice(ip)); | 617 | tracy.addText(struct_ty.containerTypeName(ip).fqn.toSlice(ip)); |
| 617 | tracy.addTextFmt("ip_index={d}", .{struct_ty.toIntern()}); | 618 | tracy.addTextFmt("ip_index={d}", .{struct_ty.toIntern()}); |
| 618 | 619 | ||
| 619 | assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); | 620 | assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); |
| ... | @@ -653,6 +654,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { | ... | @@ -653,6 +654,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { |
| 653 | .comptime_reason = undefined, // always set before using `block` | 654 | .comptime_reason = undefined, // always set before using `block` |
| 654 | .src_base_inst = struct_obj.zir_index, | 655 | .src_base_inst = struct_obj.zir_index, |
| 655 | .type_name_ctx = struct_obj.name, | 656 | .type_name_ctx = struct_obj.name, |
| 657 | .type_fqn_ctx = struct_obj.fqn, | ||
| 656 | }; | 658 | }; |
| 657 | defer block.instructions.deinit(gpa); | 659 | defer block.instructions.deinit(gpa); |
| 658 | 660 | ||
| ... | @@ -727,7 +729,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { | ... | @@ -727,7 +729,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { |
| 727 | 729 | ||
| 728 | const tracy = trace(@src()); | 730 | const tracy = trace(@src()); |
| 729 | defer tracy.end(); | 731 | defer tracy.end(); |
| 730 | tracy.addText(union_ty.containerTypeName(ip).toSlice(ip)); | 732 | tracy.addText(union_ty.containerTypeName(ip).fqn.toSlice(ip)); |
| 731 | tracy.addTextFmt("ip_index={d}", .{union_ty.toIntern()}); | 733 | tracy.addTextFmt("ip_index={d}", .{union_ty.toIntern()}); |
| 732 | 734 | ||
| 733 | assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); | 735 | assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); |
| ... | @@ -747,6 +749,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { | ... | @@ -747,6 +749,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { |
| 747 | .comptime_reason = undefined, // always set before using `block` | 749 | .comptime_reason = undefined, // always set before using `block` |
| 748 | .src_base_inst = union_obj.zir_index, | 750 | .src_base_inst = union_obj.zir_index, |
| 749 | .type_name_ctx = union_obj.name, | 751 | .type_name_ctx = union_obj.name, |
| 752 | .type_fqn_ctx = union_obj.fqn, | ||
| 750 | }; | 753 | }; |
| 751 | defer block.instructions.deinit(gpa); | 754 | defer block.instructions.deinit(gpa); |
| 752 | 755 | ||
| ... | @@ -801,6 +804,13 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { | ... | @@ -801,6 +804,13 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { |
| 801 | "@typeInfo({f}).@\"union\".tag_type.?", | 804 | "@typeInfo({f}).@\"union\".tag_type.?", |
| 802 | .{union_obj.name.fmt(ip)}, | 805 | .{union_obj.name.fmt(ip)}, |
| 803 | .no_embedded_nulls, | 806 | .no_embedded_nulls, |
| 807 | ), try ip.getOrPutStringFmt( | ||
| 808 | gpa, | ||
| 809 | io, | ||
| 810 | pt.tid, | ||
| 811 | "@typeInfo({f}).@\"union\".tag_type.?", | ||
| 812 | .{union_obj.fqn.fmt(ip)}, | ||
| 813 | .no_embedded_nulls, | ||
| 804 | ), .none); | 814 | ), .none); |
| 805 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | 815 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ |
| 806 | .parent = union_obj.namespace.toOptional(), | 816 | .parent = union_obj.namespace.toOptional(), |
| ... | @@ -1221,7 +1231,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { | ... | @@ -1221,7 +1231,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { |
| 1221 | 1231 | ||
| 1222 | const tracy = trace(@src()); | 1232 | const tracy = trace(@src()); |
| 1223 | defer tracy.end(); | 1233 | defer tracy.end(); |
| 1224 | tracy.addText(enum_ty.containerTypeName(ip).toSlice(ip)); | 1234 | tracy.addText(enum_ty.containerTypeName(ip).fqn.toSlice(ip)); |
| 1225 | tracy.addTextFmt("ip_index={d}", .{enum_ty.toIntern()}); | 1235 | tracy.addTextFmt("ip_index={d}", .{enum_ty.toIntern()}); |
| 1226 | 1236 | ||
| 1227 | assert(sema.owner.unwrap().type_layout == enum_ty.toIntern()); | 1237 | assert(sema.owner.unwrap().type_layout == enum_ty.toIntern()); |
| ... | @@ -1248,6 +1258,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { | ... | @@ -1248,6 +1258,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { |
| 1248 | .comptime_reason = undefined, // always set before using `block` | 1258 | .comptime_reason = undefined, // always set before using `block` |
| 1249 | .src_base_inst = tracked_inst, | 1259 | .src_base_inst = tracked_inst, |
| 1250 | .type_name_ctx = enum_obj.name, | 1260 | .type_name_ctx = enum_obj.name, |
| 1261 | .type_fqn_ctx = enum_obj.fqn, | ||
| 1251 | }; | 1262 | }; |
| 1252 | defer block.instructions.deinit(gpa); | 1263 | defer block.instructions.deinit(gpa); |
| 1253 | 1264 |
src/Type.zig+48-25| ... | @@ -109,6 +109,20 @@ pub const Class = enum(u3) { | ... | @@ -109,6 +109,20 @@ pub const Class = enum(u3) { |
| 109 | /// Then, aggregates containing fully-comptime types may themselves be either fully-comptime or | 109 | /// Then, aggregates containing fully-comptime types may themselves be either fully-comptime or |
| 110 | /// partially-comptime; see the doc comment on `.partially_comptime` for details. | 110 | /// partially-comptime; see the doc comment on `.partially_comptime` for details. |
| 111 | fully_comptime, | 111 | fully_comptime, |
| 112 | |||
| 113 | pub fn hasRuntimeBits(class: Class) bool { | ||
| 114 | return switch (class) { | ||
| 115 | .no_possible_value, .one_possible_value, .fully_comptime => false, | ||
| 116 | .runtime, .partially_comptime => true, | ||
| 117 | }; | ||
| 118 | } | ||
| 119 | |||
| 120 | pub fn comptimeOnly(class: Class) bool { | ||
| 121 | return switch (class) { | ||
| 122 | .no_possible_value, .one_possible_value, .runtime => false, | ||
| 123 | .partially_comptime, .fully_comptime => true, | ||
| 124 | }; | ||
| 125 | } | ||
| 112 | }; | 126 | }; |
| 113 | 127 | ||
| 114 | /// Returns the `Class` for the type `ty`. Asserts that the layout of `ty` is resolved. | 128 | /// Returns the `Class` for the type `ty`. Asserts that the layout of `ty` is resolved. |
| ... | @@ -593,8 +607,8 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari | ... | @@ -593,8 +607,8 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari |
| 593 | .generic_poison => unreachable, | 607 | .generic_poison => unreachable, |
| 594 | }, | 608 | }, |
| 595 | .struct_type => { | 609 | .struct_type => { |
| 596 | const name = ip.loadStructType(ty.toIntern()).name; | 610 | const fqn = ip.loadStructType(ty.toIntern()).fqn; |
| 597 | try writer.print("{f}", .{name.fmt(ip)}); | 611 | try writer.print("{f}", .{fqn.fmt(ip)}); |
| 598 | }, | 612 | }, |
| 599 | .tuple_type => |tuple| { | 613 | .tuple_type => |tuple| { |
| 600 | if (tuple.types.len == 0) { | 614 | if (tuple.types.len == 0) { |
| ... | @@ -611,16 +625,16 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari | ... | @@ -611,16 +625,16 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari |
| 611 | }, | 625 | }, |
| 612 | 626 | ||
| 613 | .union_type => { | 627 | .union_type => { |
| 614 | const name = ip.loadUnionType(ty.toIntern()).name; | 628 | const fqn = ip.loadUnionType(ty.toIntern()).fqn; |
| 615 | try writer.print("{f}", .{name.fmt(ip)}); | 629 | try writer.print("{f}", .{fqn.fmt(ip)}); |
| 616 | }, | 630 | }, |
| 617 | .opaque_type => { | 631 | .opaque_type => { |
| 618 | const name = ip.loadOpaqueType(ty.toIntern()).name; | 632 | const fqn = ip.loadOpaqueType(ty.toIntern()).fqn; |
| 619 | try writer.print("{f}", .{name.fmt(ip)}); | 633 | try writer.print("{f}", .{fqn.fmt(ip)}); |
| 620 | }, | 634 | }, |
| 621 | .enum_type => { | 635 | .enum_type => { |
| 622 | const name = ip.loadEnumType(ty.toIntern()).name; | 636 | const fqn = ip.loadEnumType(ty.toIntern()).fqn; |
| 623 | try writer.print("{f}", .{name.fmt(ip)}); | 637 | try writer.print("{f}", .{fqn.fmt(ip)}); |
| 624 | }, | 638 | }, |
| 625 | .spirv_type => { | 639 | .spirv_type => { |
| 626 | const info = ip.loadSpirvType(ty.toIntern()); | 640 | const info = ip.loadSpirvType(ty.toIntern()); |
| ... | @@ -761,10 +775,7 @@ pub fn toValue(self: Type) Value { | ... | @@ -761,10 +775,7 @@ pub fn toValue(self: Type) Value { |
| 761 | /// | 775 | /// |
| 762 | /// * All other types contain some runtime state, so have runtime bits and a non-zero ABI size. | 776 | /// * All other types contain some runtime state, so have runtime bits and a non-zero ABI size. |
| 763 | pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { | 777 | pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { |
| 764 | return switch (ty.classify(zcu)) { | 778 | return ty.classify(zcu).hasRuntimeBits(); |
| 765 | .no_possible_value, .one_possible_value, .fully_comptime => false, | ||
| 766 | .runtime, .partially_comptime => true, | ||
| 767 | }; | ||
| 768 | } | 779 | } |
| 769 | 780 | ||
| 770 | /// Returns `true` iff the memory layout of `ty` is defined by the Zig language specification. | 781 | /// Returns `true` iff the memory layout of `ty` is defined by the Zig language specification. |
| ... | @@ -2195,10 +2206,7 @@ pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value { | ... | @@ -2195,10 +2206,7 @@ pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value { |
| 2195 | pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool { | 2206 | pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool { |
| 2196 | if (ty.toIntern() == .generic_poison_type) return false; | 2207 | if (ty.toIntern() == .generic_poison_type) return false; |
| 2197 | if (ty.zigTypeTag(zcu) == .error_union and ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) return false; | 2208 | if (ty.zigTypeTag(zcu) == .error_union and ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) return false; |
| 2198 | return switch (ty.classify(zcu)) { | 2209 | return ty.classify(zcu).comptimeOnly(); |
| 2199 | .no_possible_value, .one_possible_value, .runtime => false, | ||
| 2200 | .partially_comptime, .fully_comptime => true, | ||
| 2201 | }; | ||
| 2202 | } | 2210 | } |
| 2203 | 2211 | ||
| 2204 | pub fn isVector(ty: Type, zcu: *const Zcu) bool { | 2212 | pub fn isVector(ty: Type, zcu: *const Zcu) bool { |
| ... | @@ -2685,8 +2693,8 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { | ... | @@ -2685,8 +2693,8 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { |
| 2685 | }; | 2693 | }; |
| 2686 | const inst = zir.instructions.get(@backingInt(info.inst)); | 2694 | const inst = zir.instructions.get(@backingInt(info.inst)); |
| 2687 | return switch (inst.tag) { | 2695 | return switch (inst.tag) { |
| 2688 | .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line, | 2696 | .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.src_line, |
| 2689 | .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_line, | 2697 | .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.src_line, |
| 2690 | .extended => switch (inst.data.extended.opcode) { | 2698 | .extended => switch (inst.data.extended.opcode) { |
| 2691 | .struct_decl => zir.getStructDecl(info.inst).src_line, | 2699 | .struct_decl => zir.getStructDecl(info.inst).src_line, |
| 2692 | .union_decl => zir.getUnionDecl(info.inst).src_line, | 2700 | .union_decl => zir.getUnionDecl(info.inst).src_line, |
| ... | @@ -3012,14 +3020,29 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator | ... | @@ -3012,14 +3020,29 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator |
| 3012 | return pt.ptrType(field_ptr_info); | 3020 | return pt.ptrType(field_ptr_info); |
| 3013 | } | 3021 | } |
| 3014 | 3022 | ||
| 3015 | pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTerminatedString { | 3023 | pub fn containerTypeName(ty: Type, ip: *const InternPool) struct { |
| 3016 | return switch (ip.indexToKey(ty.toIntern())) { | 3024 | name: InternPool.NullTerminatedString, |
| 3017 | .struct_type => ip.loadStructType(ty.toIntern()).name, | 3025 | fqn: InternPool.NullTerminatedString, |
| 3018 | .union_type => ip.loadUnionType(ty.toIntern()).name, | 3026 | } { |
| 3019 | .enum_type => ip.loadEnumType(ty.toIntern()).name, | 3027 | switch (ip.indexToKey(ty.toIntern())) { |
| 3020 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).name, | 3028 | .struct_type => { |
| 3029 | const loaded_struct = ip.loadStructType(ty.toIntern()); | ||
| 3030 | return .{ .name = loaded_struct.name, .fqn = loaded_struct.fqn }; | ||
| 3031 | }, | ||
| 3032 | .union_type => { | ||
| 3033 | const loaded_union = ip.loadUnionType(ty.toIntern()); | ||
| 3034 | return .{ .name = loaded_union.name, .fqn = loaded_union.fqn }; | ||
| 3035 | }, | ||
| 3036 | .enum_type => { | ||
| 3037 | const loaded_enum = ip.loadEnumType(ty.toIntern()); | ||
| 3038 | return .{ .name = loaded_enum.name, .fqn = loaded_enum.fqn }; | ||
| 3039 | }, | ||
| 3040 | .opaque_type => { | ||
| 3041 | const loaded_opaque = ip.loadOpaqueType(ty.toIntern()); | ||
| 3042 | return .{ .name = loaded_opaque.name, .fqn = loaded_opaque.fqn }; | ||
| 3043 | }, | ||
| 3021 | else => unreachable, | 3044 | else => unreachable, |
| 3022 | }; | 3045 | } |
| 3023 | } | 3046 | } |
| 3024 | 3047 | ||
| 3025 | pub fn destructurable(ty: Type, zcu: *const Zcu) bool { | 3048 | pub fn destructurable(ty: Type, zcu: *const Zcu) bool { |
src/Zcu.zig+121-81| ... | @@ -348,6 +348,9 @@ codegen_task_pool: CodegenTaskPool, | ... | @@ -348,6 +348,9 @@ codegen_task_pool: CodegenTaskPool, |
| 348 | 348 | ||
| 349 | generation: u32 = 0, | 349 | generation: u32 = 0, |
| 350 | 350 | ||
| 351 | /// Only access from the Sema thread. | ||
| 352 | anon_name_counter: u32, | ||
| 353 | |||
| 351 | pub const DependencyReason = struct { | 354 | pub const DependencyReason = struct { |
| 352 | src: LazySrcLoc, | 355 | src: LazySrcLoc, |
| 353 | /// Only populated if this is for a `.type_layout` unit. | 356 | /// Only populated if this is for a `.type_layout` unit. |
| ... | @@ -944,9 +947,9 @@ pub const Namespace = struct { | ... | @@ -944,9 +947,9 @@ pub const Namespace = struct { |
| 944 | tid: Zcu.PerThread.Id, | 947 | tid: Zcu.PerThread.Id, |
| 945 | name: InternPool.NullTerminatedString, | 948 | name: InternPool.NullTerminatedString, |
| 946 | ) !InternPool.NullTerminatedString { | 949 | ) !InternPool.NullTerminatedString { |
| 947 | const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip); | 950 | const ns_fqn = Type.fromInterned(ns.owner_type).containerTypeName(ip).fqn; |
| 948 | if (name == .empty) return ns_name; | 951 | if (name == .empty) return ns_fqn; |
| 949 | return ip.getOrPutStringFmt(gpa, io, tid, "{f}.{f}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls); | 952 | return ip.getOrPutStringFmt(gpa, io, tid, "{f}.{f}", .{ ns_fqn.fmt(ip), name.fmt(ip) }, .no_embedded_nulls); |
| 950 | } | 953 | } |
| 951 | }; | 954 | }; |
| 952 | 955 | ||
| ... | @@ -4234,7 +4237,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana | ... | @@ -4234,7 +4237,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana |
| 4234 | const referencer = types.values()[type_idx]; | 4237 | const referencer = types.values()[type_idx]; |
| 4235 | type_idx += 1; | 4238 | type_idx += 1; |
| 4236 | 4239 | ||
| 4237 | refs_log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); | 4240 | refs_log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip)}); |
| 4238 | 4241 | ||
| 4239 | // Queue any decls within this type which would be automatically analyzed. | 4242 | // Queue any decls within this type which would be automatically analyzed. |
| 4240 | // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`. | 4243 | // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`. |
| ... | @@ -4245,7 +4248,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana | ... | @@ -4245,7 +4248,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana |
| 4245 | const gop = try units.getOrPut(gpa, unit); | 4248 | const gop = try units.getOrPut(gpa, unit); |
| 4246 | if (!gop.found_existing) { | 4249 | if (!gop.found_existing) { |
| 4247 | refs_log.debug("type '{f}': ref comptime %{}", .{ | 4250 | refs_log.debug("type '{f}': ref comptime %{}", .{ |
| 4248 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | 4251 | Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), |
| 4249 | @backingInt(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue), | 4252 | @backingInt(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue), |
| 4250 | }); | 4253 | }); |
| 4251 | gop.value_ptr.* = referencer; | 4254 | gop.value_ptr.* = referencer; |
| ... | @@ -4279,7 +4282,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana | ... | @@ -4279,7 +4282,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana |
| 4279 | const gop = try units.getOrPut(gpa, .wrap(.{ .nav_val = nav_id })); | 4282 | const gop = try units.getOrPut(gpa, .wrap(.{ .nav_val = nav_id })); |
| 4280 | if (!gop.found_existing) { | 4283 | if (!gop.found_existing) { |
| 4281 | refs_log.debug("type '{f}': ref test %{}", .{ | 4284 | refs_log.debug("type '{f}': ref test %{}", .{ |
| 4282 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | 4285 | Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), |
| 4283 | @backingInt(inst_info.inst), | 4286 | @backingInt(inst_info.inst), |
| 4284 | }); | 4287 | }); |
| 4285 | gop.value_ptr.* = referencer; | 4288 | gop.value_ptr.* = referencer; |
| ... | @@ -4302,7 +4305,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana | ... | @@ -4302,7 +4305,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana |
| 4302 | const gop = try units.getOrPut(gpa, unit); | 4305 | const gop = try units.getOrPut(gpa, unit); |
| 4303 | if (!gop.found_existing) { | 4306 | if (!gop.found_existing) { |
| 4304 | refs_log.debug("type '{f}': ref named %{}", .{ | 4307 | refs_log.debug("type '{f}': ref named %{}", .{ |
| 4305 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | 4308 | Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), |
| 4306 | @backingInt(inst_info.inst), | 4309 | @backingInt(inst_info.inst), |
| 4307 | }); | 4310 | }); |
| 4308 | gop.value_ptr.* = referencer; | 4311 | gop.value_ptr.* = referencer; |
| ... | @@ -4319,7 +4322,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana | ... | @@ -4319,7 +4322,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana |
| 4319 | const gop = try units.getOrPut(gpa, unit); | 4322 | const gop = try units.getOrPut(gpa, unit); |
| 4320 | if (!gop.found_existing) { | 4323 | if (!gop.found_existing) { |
| 4321 | refs_log.debug("type '{f}': ref named %{}", .{ | 4324 | refs_log.debug("type '{f}': ref named %{}", .{ |
| 4322 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | 4325 | Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), |
| 4323 | @backingInt(inst_info.inst), | 4326 | @backingInt(inst_info.inst), |
| 4324 | }); | 4327 | }); |
| 4325 | gop.value_ptr.* = referencer; | 4328 | gop.value_ptr.* = referencer; |
| ... | @@ -4382,7 +4385,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana | ... | @@ -4382,7 +4385,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana |
| 4382 | if (!gop.found_existing) { | 4385 | if (!gop.found_existing) { |
| 4383 | refs_log.debug("unit '{f}': ref type '{f}'", .{ | 4386 | refs_log.debug("unit '{f}': ref type '{f}'", .{ |
| 4384 | zcu.fmtAnalUnit(unit), | 4387 | zcu.fmtAnalUnit(unit), |
| 4385 | Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip), | 4388 | Type.fromInterned(ref.referenced).containerTypeName(ip).fqn.fmt(ip), |
| 4386 | }); | 4389 | }); |
| 4387 | gop.value_ptr.* = .{ | 4390 | gop.value_ptr.* = .{ |
| 4388 | .referencer = unit, | 4391 | .referencer = unit, |
| ... | @@ -4495,7 +4498,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void | ... | @@ -4495,7 +4498,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void |
| 4495 | } | 4498 | } |
| 4496 | }, | 4499 | }, |
| 4497 | .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @backingInt(nav) }), | 4500 | .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @backingInt(nav) }), |
| 4498 | .type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @backingInt(ty) }), | 4501 | .type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), @backingInt(ty) }), |
| 4499 | .func => |func| { | 4502 | .func => |func| { |
| 4500 | const nav = zcu.funcInfo(func).owner_nav; | 4503 | const nav = zcu.funcInfo(func).owner_nav; |
| 4501 | return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @backingInt(func) }); | 4504 | return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @backingInt(func) }); |
| ... | @@ -4521,8 +4524,8 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void | ... | @@ -4521,8 +4524,8 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void |
| 4521 | return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); | 4524 | return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); |
| 4522 | }, | 4525 | }, |
| 4523 | .type_layout, .struct_defaults => |ip_index, tag| { | 4526 | .type_layout, .struct_defaults => |ip_index, tag| { |
| 4524 | const name = Type.fromInterned(ip_index).containerTypeName(ip); | 4527 | const fqn = Type.fromInterned(ip_index).containerTypeName(ip).fqn; |
| 4525 | return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) }); | 4528 | return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); |
| 4526 | }, | 4529 | }, |
| 4527 | .func_ies => |ip_index| { | 4530 | .func_ies => |ip_index| { |
| 4528 | const fqn = ip.getNav(ip.indexToKey(ip_index).func.owner_nav).fqn; | 4531 | const fqn = ip.getNav(ip.indexToKey(ip_index).func.owner_nav).fqn; |
| ... | @@ -4569,13 +4572,17 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) | ... | @@ -4569,13 +4572,17 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) |
| 4569 | if (allowed_arch == target.cpu.arch) break; | 4572 | if (allowed_arch == target.cpu.arch) break; |
| 4570 | } else return .{ .bad_arch = cc.archs() }, | 4573 | } else return .{ .bad_arch = cc.archs() }, |
| 4571 | } | 4574 | } |
| 4572 | const backend_ok = switch (backend) { | 4575 | const backend_ok = ok: switch (backend) { |
| 4573 | .stage1 => unreachable, | 4576 | .stage1 => unreachable, |
| 4574 | .other => unreachable, | 4577 | .other => unreachable, |
| 4575 | _ => unreachable, | 4578 | _ => unreachable, |
| 4576 | 4579 | ||
| 4577 | .stage2_llvm => @import("codegen/llvm.zig").toLlvmCallConv(cc, target) != null, | 4580 | .stage2_llvm => { |
| 4578 | .stage2_c => ok: { | 4581 | dev.check(.llvm_backend); |
| 4582 | break :ok @import("codegen/llvm.zig").toLlvmCallConv(cc, target) != null; | ||
| 4583 | }, | ||
| 4584 | .stage2_c => { | ||
| 4585 | dev.check(.c_backend); | ||
| 4579 | if (target.cCallingConvention()) |default_c| { | 4586 | if (target.cCallingConvention()) |default_c| { |
| 4580 | if (cc.eql(default_c)) { | 4587 | if (cc.eql(default_c)) { |
| 4581 | break :ok true; | 4588 | break :ok true; |
| ... | @@ -4633,81 +4640,114 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) | ... | @@ -4633,81 +4640,114 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) |
| 4633 | else => false, | 4640 | else => false, |
| 4634 | }; | 4641 | }; |
| 4635 | }, | 4642 | }, |
| 4636 | .stage2_wasm => switch (cc) { | 4643 | .stage2_wasm => { |
| 4637 | .wasm_mvp => |opts| opts.incoming_stack_alignment == null, | 4644 | dev.check(.wasm_backend); |
| 4638 | else => false, | 4645 | break :ok switch (cc) { |
| 4639 | }, | 4646 | .wasm_mvp => |opts| opts.incoming_stack_alignment == null, |
| 4640 | .stage2_arm => switch (cc) { | 4647 | else => false, |
| 4641 | .arm_aapcs => |opts| opts.incoming_stack_alignment == null, | 4648 | }; |
| 4642 | .naked => true, | ||
| 4643 | else => false, | ||
| 4644 | }, | ||
| 4645 | .stage2_x86_64 => switch (cc) { | ||
| 4646 | .x86_64_sysv, .x86_64_win, .naked => true, // incoming stack alignment supported | ||
| 4647 | else => false, | ||
| 4648 | }, | 4649 | }, |
| 4649 | .stage2_aarch64 => switch (cc) { | 4650 | .stage2_arm => { |
| 4650 | .aarch64_aapcs, .aarch64_aapcs_darwin, .naked => true, | 4651 | dev.check(.arm_backend); |
| 4651 | else => false, | 4652 | break :ok switch (cc) { |
| 4653 | .arm_aapcs => |opts| opts.incoming_stack_alignment == null, | ||
| 4654 | .naked => true, | ||
| 4655 | else => false, | ||
| 4656 | }; | ||
| 4652 | }, | 4657 | }, |
| 4653 | .stage2_x86 => switch (cc) { | 4658 | .stage2_x86_64 => { |
| 4654 | .x86_sysv, | 4659 | dev.check(.x86_64_backend); |
| 4655 | .x86_win, | 4660 | break :ok switch (cc) { |
| 4656 | .x86_mingw, | 4661 | .x86_64_sysv, .x86_64_win, .naked => true, // incoming stack alignment supported |
| 4657 | => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, | 4662 | else => false, |
| 4658 | .naked => true, | 4663 | }; |
| 4659 | else => false, | ||
| 4660 | }, | 4664 | }, |
| 4661 | .stage2_powerpc => switch (target.cpu.arch) { | 4665 | .stage2_aarch64 => { |
| 4662 | .powerpc, .powerpcle => switch (cc) { | 4666 | dev.check(.aarch64_backend); |
| 4663 | .powerpc_sysv, | 4667 | break :ok switch (cc) { |
| 4664 | .powerpc_sysv_altivec, | 4668 | .aarch64_aapcs, .aarch64_aapcs_darwin, .naked => true, |
| 4665 | .powerpc_aix, | ||
| 4666 | .powerpc_aix_altivec, | ||
| 4667 | .naked, | ||
| 4668 | => true, | ||
| 4669 | else => false, | 4669 | else => false, |
| 4670 | }, | 4670 | }; |
| 4671 | .powerpc64, .powerpc64le => switch (cc) { | 4671 | }, |
| 4672 | .powerpc64_elf, | 4672 | .stage2_x86 => { |
| 4673 | .powerpc64_elf_altivec, | 4673 | dev.check(.x86_backend); |
| 4674 | .powerpc64_elf_v2, | 4674 | break :ok switch (cc) { |
| 4675 | .naked, | 4675 | .x86_sysv, |
| 4676 | => true, | 4676 | .x86_win, |
| 4677 | .x86_mingw, | ||
| 4678 | => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, | ||
| 4679 | .naked => true, | ||
| 4677 | else => false, | 4680 | else => false, |
| 4678 | }, | 4681 | }; |
| 4679 | else => unreachable, | ||
| 4680 | }, | 4682 | }, |
| 4681 | .stage2_riscv64 => switch (cc) { | 4683 | .stage2_powerpc => { |
| 4682 | .riscv64_lp64 => |opts| opts.incoming_stack_alignment == null, | 4684 | dev.check(.powerpc_backend); |
| 4683 | .naked => true, | 4685 | break :ok switch (target.cpu.arch) { |
| 4684 | else => false, | 4686 | .powerpc, .powerpcle => switch (cc) { |
| 4687 | .powerpc_sysv, | ||
| 4688 | .powerpc_sysv_altivec, | ||
| 4689 | .powerpc_aix, | ||
| 4690 | .powerpc_aix_altivec, | ||
| 4691 | .naked, | ||
| 4692 | => true, | ||
| 4693 | else => false, | ||
| 4694 | }, | ||
| 4695 | .powerpc64, .powerpc64le => switch (cc) { | ||
| 4696 | .powerpc64_elf, | ||
| 4697 | .powerpc64_elf_altivec, | ||
| 4698 | .powerpc64_elf_v2, | ||
| 4699 | .naked, | ||
| 4700 | => true, | ||
| 4701 | else => false, | ||
| 4702 | }, | ||
| 4703 | else => unreachable, | ||
| 4704 | }; | ||
| 4685 | }, | 4705 | }, |
| 4686 | .stage2_sparc64 => switch (cc) { | 4706 | .stage2_riscv64 => { |
| 4687 | .sparc64_sysv => |opts| opts.incoming_stack_alignment == null, | 4707 | dev.check(.riscv64_backend); |
| 4688 | .naked => true, | 4708 | break :ok switch (cc) { |
| 4689 | else => false, | 4709 | .riscv64_lp64 => |opts| opts.incoming_stack_alignment == null, |
| 4710 | .naked => true, | ||
| 4711 | else => false, | ||
| 4712 | }; | ||
| 4690 | }, | 4713 | }, |
| 4691 | .stage2_spirv => switch (cc) { | 4714 | .stage2_sparc64 => { |
| 4692 | .spirv_device, .spirv_kernel => true, | 4715 | dev.check(.sparc64_backend); |
| 4693 | .spirv_fragment, .spirv_vertex => target.os.tag == .vulkan or target.os.tag == .opengl, | 4716 | break :ok switch (cc) { |
| 4694 | .spirv_task, .spirv_mesh => target.os.tag == .vulkan, | 4717 | .sparc64_sysv => |opts| opts.incoming_stack_alignment == null, |
| 4695 | else => false, | 4718 | .naked => true, |
| 4719 | else => false, | ||
| 4720 | }; | ||
| 4696 | }, | 4721 | }, |
| 4697 | .stage2_loongarch => switch (cc) { | 4722 | .stage2_spirv => { |
| 4698 | .loongarch64_lp64, .loongarch32_ilp32, .naked => true, | 4723 | dev.check(.spirv_backend); |
| 4699 | else => false, | 4724 | break :ok switch (cc) { |
| 4725 | .spirv_device, .spirv_kernel => true, | ||
| 4726 | .spirv_fragment, .spirv_vertex => target.os.tag == .vulkan or target.os.tag == .opengl, | ||
| 4727 | .spirv_task, .spirv_mesh => target.os.tag == .vulkan, | ||
| 4728 | else => false, | ||
| 4729 | }; | ||
| 4700 | }, | 4730 | }, |
| 4701 | .zsf_spork8 => switch (cc) { | 4731 | .stage2_loongarch => { |
| 4702 | .spork8, .naked => true, | 4732 | dev.check(.loongarch_backend); |
| 4703 | else => false, | 4733 | break :ok switch (cc) { |
| 4734 | .loongarch64_lp64, .loongarch32_ilp32, .naked => true, | ||
| 4735 | else => false, | ||
| 4736 | }; | ||
| 4737 | }, | ||
| 4738 | .zsf_spork8 => { | ||
| 4739 | dev.check(.spork8_backend); | ||
| 4740 | break :ok switch (cc) { | ||
| 4741 | .spork8, .naked => true, | ||
| 4742 | else => false, | ||
| 4743 | }; | ||
| 4704 | }, | 4744 | }, |
| 4705 | }; | 4745 | }; |
| 4706 | if (!backend_ok) return .{ .bad_backend = backend }; | 4746 | if (!backend_ok) return .{ .bad_backend = backend }; |
| 4707 | return .ok; | 4747 | return .ok; |
| 4708 | } | 4748 | } |
| 4709 | 4749 | ||
| 4710 | pub const CodegenFailError = error{ | 4750 | pub const CodegenFailError = Io.Cancelable || error{ |
| 4711 | /// Indicates the error message has been already stored at `Zcu.failed_codegen`. | 4751 | /// Indicates the error message has been already stored at `Zcu.failed_codegen`. |
| 4712 | AlreadyReported, | 4752 | AlreadyReported, |
| 4713 | OutOfMemory, | 4753 | OutOfMemory, |
| ... | @@ -4999,7 +5039,7 @@ fn addDependencyLoopErrorLine( | ... | @@ -4999,7 +5039,7 @@ fn addDependencyLoopErrorLine( |
| 4999 | }), | 5039 | }), |
| 5000 | .struct_defaults => |ty| try eb.printString( | 5040 | .struct_defaults => |ty| try eb.printString( |
| 5001 | "default field values of '{f}' depend on themselves for initialization here", | 5041 | "default field values of '{f}' depend on themselves for initialization here", |
| 5002 | .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}, | 5042 | .{Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip)}, |
| 5003 | ), | 5043 | ), |
| 5004 | } else switch (dep_node.unit.unwrap()) { | 5044 | } else switch (dep_node.unit.unwrap()) { |
| 5005 | .@"comptime" => unreachable, // cannot be involved in a dependency loop | 5045 | .@"comptime" => unreachable, // cannot be involved in a dependency loop |
| ... | @@ -5018,12 +5058,12 @@ fn addDependencyLoopErrorLine( | ... | @@ -5018,12 +5058,12 @@ fn addDependencyLoopErrorLine( |
| 5018 | }), | 5058 | }), |
| 5019 | .type_layout => |ty| try eb.printString("{f} depends on type '{f}' {s}", .{ | 5059 | .type_layout => |ty| try eb.printString("{f} depends on type '{f}' {s}", .{ |
| 5020 | fmt_source, | 5060 | fmt_source, |
| 5021 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | 5061 | Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), |
| 5022 | dep_node.reason.type_layout_reason.msg(), | 5062 | dep_node.reason.type_layout_reason.msg(), |
| 5023 | }), | 5063 | }), |
| 5024 | .struct_defaults => |ty| try eb.printString( | 5064 | .struct_defaults => |ty| try eb.printString( |
| 5025 | "{f} uses default field values of '{f}' here", | 5065 | "{f} uses default field values of '{f}' here", |
| 5026 | .{ fmt_source, Type.fromInterned(ty).containerTypeName(ip).fmt(ip) }, | 5066 | .{ fmt_source, Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip) }, |
| 5027 | ), | 5067 | ), |
| 5028 | }; | 5068 | }; |
| 5029 | 5069 | ||
| ... | @@ -5065,10 +5105,10 @@ fn formatDependencyLoopSourceUnit(data: FormatAnalUnit, w: *Io.Writer) Io.Writer | ... | @@ -5065,10 +5105,10 @@ fn formatDependencyLoopSourceUnit(data: FormatAnalUnit, w: *Io.Writer) Io.Writer |
| 5065 | else => try w.writeAll("'std.lang' declarations"), | 5105 | else => try w.writeAll("'std.lang' declarations"), |
| 5066 | }, | 5106 | }, |
| 5067 | .type_layout => |ty| try w.print("type '{f}'", .{ | 5107 | .type_layout => |ty| try w.print("type '{f}'", .{ |
| 5068 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | 5108 | Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), |
| 5069 | }), | 5109 | }), |
| 5070 | .struct_defaults => |ty| try w.print("default field value of '{f}'", .{ | 5110 | .struct_defaults => |ty| try w.print("default field value of '{f}'", .{ |
| 5071 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | 5111 | Type.fromInterned(ty).containerTypeName(ip).fqn.fmt(ip), |
| 5072 | }), | 5112 | }), |
| 5073 | .func => |func| try w.print("function '{f}'", .{ | 5113 | .func => |func| try w.print("function '{f}'", .{ |
| 5074 | ip.getNav(zcu.funcInfo(func).owner_nav).fqn.fmt(ip), | 5114 | ip.getNav(zcu.funcInfo(func).owner_nav).fqn.fmt(ip), |
| ... | @@ -5118,7 +5158,7 @@ pub fn populateReferenceTrace( | ... | @@ -5118,7 +5158,7 @@ pub fn populateReferenceTrace( |
| 5118 | const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { | 5158 | const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { |
| 5119 | .@"comptime" => "comptime", | 5159 | .@"comptime" => "comptime", |
| 5120 | .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), | 5160 | .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), |
| 5121 | .type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), | 5161 | .type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).fqn.toSlice(ip), |
| 5122 | .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), | 5162 | .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), |
| 5123 | .memoized_state => null, | 5163 | .memoized_state => null, |
| 5124 | }; | 5164 | }; |
| ... | @@ -5240,7 +5280,7 @@ pub const CodegenTaskPool = struct { | ... | @@ -5240,7 +5280,7 @@ pub const CodegenTaskPool = struct { |
| 5240 | /// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight. | 5280 | /// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight. |
| 5241 | const max_air_bytes_in_flight = 10 * 1024 * 1024; | 5281 | const max_air_bytes_in_flight = 10 * 1024 * 1024; |
| 5242 | 5282 | ||
| 5243 | const max_funcs_in_flight = @import("link.zig").Queue.buffer_size; | 5283 | const max_funcs_in_flight = link.Queue.buffer_size; |
| 5244 | 5284 | ||
| 5245 | available_air_bytes: u32, | 5285 | available_air_bytes: u32, |
| 5246 | 5286 |
src/Zcu/PerThread.zig+75-24| ... | @@ -258,6 +258,8 @@ pub fn update( | ... | @@ -258,6 +258,8 @@ pub fn update( |
| 258 | return; | 258 | return; |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | try comp.link_queue.enqueueZcu(comp, pt.tid, .files_ready); | ||
| 262 | |||
| 261 | if (comp.config.incremental) { | 263 | if (comp.config.incremental) { |
| 262 | const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); | 264 | const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); |
| 263 | defer update_zir_refs_node.end(); | 265 | defer update_zir_refs_node.end(); |
| ... | @@ -859,25 +861,63 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { | ... | @@ -859,25 +861,63 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { |
| 859 | log.debug("tracking failed for %{d}", .{old_inst}); | 861 | log.debug("tracking failed for %{d}", .{old_inst}); |
| 860 | tracked_inst.inst = .lost; | 862 | tracked_inst.inst = .lost; |
| 861 | try zcu.markDependeeOutdated(.not_marked_po, .{ .src_hash = tracked_inst_index }); | 863 | try zcu.markDependeeOutdated(.not_marked_po, .{ .src_hash = tracked_inst_index }); |
| 864 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .lost_tracking = tracked_inst_index }); | ||
| 862 | continue; | 865 | continue; |
| 863 | }; | 866 | }; |
| 864 | tracked_inst.inst = InternPool.TrackedInst.MaybeLost.ZirIndex.wrap(new_inst); | 867 | tracked_inst.inst = .wrap(new_inst); |
| 865 | 868 | ||
| 866 | const old_zir = file.prev_zir.?.*; | 869 | const old_zir = file.prev_zir.?.*; |
| 867 | const new_zir = file.zir.?; | ||
| 868 | const old_tag = old_zir.instructions.items(.tag)[@backingInt(old_inst)]; | 870 | const old_tag = old_zir.instructions.items(.tag)[@backingInt(old_inst)]; |
| 869 | const old_data = old_zir.instructions.items(.data)[@backingInt(old_inst)]; | 871 | const old_data = old_zir.instructions.items(.data)[@backingInt(old_inst)]; |
| 870 | 872 | ||
| 871 | switch (old_tag) { | 873 | const new_zir = file.zir.?; |
| 872 | .declaration => { | 874 | const new_data = new_zir.instructions.items(.data)[@backingInt(new_inst)]; |
| 873 | const old_line = old_zir.getDeclaration(old_inst).src_line; | 875 | |
| 874 | const new_line = new_zir.getDeclaration(new_inst).src_line; | 876 | debug_update_line_number: { |
| 875 | if (old_line != new_line) { | 877 | const old_line, const new_line = switch (old_tag) { |
| 876 | comp.link_prog_node.increaseEstimatedTotalItems(1); | 878 | .declaration => .{ |
| 877 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = tracked_inst_index }); | 879 | old_zir.getDeclaration(old_inst).src_line, |
| 878 | } | 880 | new_zir.getDeclaration(new_inst).src_line, |
| 879 | }, | 881 | }, |
| 880 | else => {}, | 882 | .extended => switch (old_data.extended.opcode) { |
| 883 | .struct_decl => .{ | ||
| 884 | old_zir.getStructDecl(old_inst).src_line, | ||
| 885 | new_zir.getStructDecl(new_inst).src_line, | ||
| 886 | }, | ||
| 887 | .union_decl => .{ | ||
| 888 | old_zir.getUnionDecl(old_inst).src_line, | ||
| 889 | new_zir.getUnionDecl(new_inst).src_line, | ||
| 890 | }, | ||
| 891 | .enum_decl => .{ | ||
| 892 | old_zir.getEnumDecl(old_inst).src_line, | ||
| 893 | new_zir.getEnumDecl(new_inst).src_line, | ||
| 894 | }, | ||
| 895 | .opaque_decl => .{ | ||
| 896 | old_zir.getOpaqueDecl(old_inst).src_line, | ||
| 897 | new_zir.getOpaqueDecl(new_inst).src_line, | ||
| 898 | }, | ||
| 899 | .reify_enum => .{ | ||
| 900 | old_zir.extraData(Zir.Inst.ReifyEnum, old_data.extended.operand).data.src_line, | ||
| 901 | new_zir.extraData(Zir.Inst.ReifyEnum, new_data.extended.operand).data.src_line, | ||
| 902 | }, | ||
| 903 | .reify_struct => .{ | ||
| 904 | old_zir.extraData(Zir.Inst.ReifyStruct, old_data.extended.operand).data.src_line, | ||
| 905 | new_zir.extraData(Zir.Inst.ReifyStruct, new_data.extended.operand).data.src_line, | ||
| 906 | }, | ||
| 907 | .reify_union => .{ | ||
| 908 | old_zir.extraData(Zir.Inst.ReifyUnion, old_data.extended.operand).data.src_line, | ||
| 909 | new_zir.extraData(Zir.Inst.ReifyUnion, new_data.extended.operand).data.src_line, | ||
| 910 | }, | ||
| 911 | else => break :debug_update_line_number, | ||
| 912 | }, | ||
| 913 | else => break :debug_update_line_number, | ||
| 914 | }; | ||
| 915 | if (old_line == new_line) break :debug_update_line_number; | ||
| 916 | comp.link_prog_node.increaseEstimatedTotalItems(1); | ||
| 917 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = .{ | ||
| 918 | .inst = tracked_inst_index, | ||
| 919 | .line = new_line, | ||
| 920 | } }); | ||
| 881 | } | 921 | } |
| 882 | 922 | ||
| 883 | if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: { | 923 | if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: { |
| ... | @@ -979,7 +1019,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { | ... | @@ -979,7 +1019,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { |
| 979 | /// Ensures that `zcu.fileRootType` on this `file_index` is populated (not `.none`). This implies | 1019 | /// Ensures that `zcu.fileRootType` on this `file_index` is populated (not `.none`). This implies |
| 980 | /// that the file's namespace is scanned, discovering declarations. | 1020 | /// that the file's namespace is scanned, discovering declarations. |
| 981 | /// | 1021 | /// |
| 982 | /// Typical Zig compilations begin by claling this function on the root source file of the standard | 1022 | /// Typical Zig compilations begin by calling this function on the root source file of the standard |
| 983 | /// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in | 1023 | /// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in |
| 984 | /// that file, which is queued for analysis, and everything goes from there. | 1024 | /// that file, which is queued for analysis, and everything goes from there. |
| 985 | pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void { | 1025 | pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void { |
| ... | @@ -1020,7 +1060,12 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc | ... | @@ -1020,7 +1060,12 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc |
| 1020 | }; | 1060 | }; |
| 1021 | errdefer wip.cancel(ip, pt.tid); | 1061 | errdefer wip.cancel(ip, pt.tid); |
| 1022 | 1062 | ||
| 1023 | wip.setName(ip, try file.internFullyQualifiedName(pt), .none); | 1063 | wip.setName( |
| 1064 | ip, | ||
| 1065 | try ip.getOrPutString(gpa, io, pt.tid, std.fs.path.stem(file.sub_file_path), .no_embedded_nulls), | ||
| 1066 | try file.internFullyQualifiedName(pt), | ||
| 1067 | .none, | ||
| 1068 | ); | ||
| 1024 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | 1069 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ |
| 1025 | .parent = .none, | 1070 | .parent = .none, |
| 1026 | .owner_type = wip.index, | 1071 | .owner_type = wip.index, |
| ... | @@ -1261,6 +1306,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu | ... | @@ -1261,6 +1306,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 1261 | // The comptime unit declares on the source of the corresponding `comptime` declaration. | 1306 | // The comptime unit declares on the source of the corresponding `comptime` declaration. |
| 1262 | try sema.declareDependency(.{ .src_hash = comptime_unit.zir_index }); | 1307 | try sema.declareDependency(.{ .src_hash = comptime_unit.zir_index }); |
| 1263 | 1308 | ||
| 1309 | const parent_ns = Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip); | ||
| 1264 | var block: Sema.Block = .{ | 1310 | var block: Sema.Block = .{ |
| 1265 | .parent = null, | 1311 | .parent = null, |
| 1266 | .sema = &sema, | 1312 | .sema = &sema, |
| ... | @@ -1276,7 +1322,10 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu | ... | @@ -1276,7 +1322,10 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 1276 | } }, | 1322 | } }, |
| 1277 | .src_base_inst = comptime_unit.zir_index, | 1323 | .src_base_inst = comptime_unit.zir_index, |
| 1278 | .type_name_ctx = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.comptime", .{ | 1324 | .type_name_ctx = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.comptime", .{ |
| 1279 | Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip), | 1325 | parent_ns.name.fmt(ip), |
| 1326 | }, .no_embedded_nulls), | ||
| 1327 | .type_fqn_ctx = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.comptime", .{ | ||
| 1328 | parent_ns.fqn.fmt(ip), | ||
| 1280 | }, .no_embedded_nulls), | 1329 | }, .no_embedded_nulls), |
| 1281 | }; | 1330 | }; |
| 1282 | defer block.instructions.deinit(gpa); | 1331 | defer block.instructions.deinit(gpa); |
| ... | @@ -1352,7 +1401,7 @@ pub fn ensureTypeLayoutUpToDate( | ... | @@ -1352,7 +1401,7 @@ pub fn ensureTypeLayoutUpToDate( |
| 1352 | info.deps.clearRetainingCapacity(); | 1401 | info.deps.clearRetainingCapacity(); |
| 1353 | } | 1402 | } |
| 1354 | 1403 | ||
| 1355 | const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).toSlice(ip), null); | 1404 | const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).fqn.toSlice(ip), null); |
| 1356 | defer unit_tracking.end(zcu); | 1405 | defer unit_tracking.end(zcu); |
| 1357 | 1406 | ||
| 1358 | try zcu.analysis_in_progress.put(gpa, anal_unit, reason); | 1407 | try zcu.analysis_in_progress.put(gpa, anal_unit, reason); |
| ... | @@ -1464,7 +1513,7 @@ pub fn ensureStructDefaultsUpToDate( | ... | @@ -1464,7 +1513,7 @@ pub fn ensureStructDefaultsUpToDate( |
| 1464 | info.deps.clearRetainingCapacity(); | 1513 | info.deps.clearRetainingCapacity(); |
| 1465 | } | 1514 | } |
| 1466 | 1515 | ||
| 1467 | const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).toSlice(ip), null); | 1516 | const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).fqn.toSlice(ip), null); |
| 1468 | defer unit_tracking.end(zcu); | 1517 | defer unit_tracking.end(zcu); |
| 1469 | 1518 | ||
| 1470 | try zcu.analysis_in_progress.put(gpa, anal_unit, reason); | 1519 | try zcu.analysis_in_progress.put(gpa, anal_unit, reason); |
| ... | @@ -1673,7 +1722,8 @@ fn analyzeNavVal( | ... | @@ -1673,7 +1722,8 @@ fn analyzeNavVal( |
| 1673 | .inlining = null, | 1722 | .inlining = null, |
| 1674 | .comptime_reason = undefined, // set below | 1723 | .comptime_reason = undefined, // set below |
| 1675 | .src_base_inst = old_nav.analysis.?.zir_index, | 1724 | .src_base_inst = old_nav.analysis.?.zir_index, |
| 1676 | .type_name_ctx = old_nav.fqn, | 1725 | .type_name_ctx = old_nav.name, |
| 1726 | .type_fqn_ctx = old_nav.fqn, | ||
| 1677 | }; | 1727 | }; |
| 1678 | defer block.instructions.deinit(gpa); | 1728 | defer block.instructions.deinit(gpa); |
| 1679 | 1729 | ||
| ... | @@ -2042,7 +2092,8 @@ fn analyzeNavType( | ... | @@ -2042,7 +2092,8 @@ fn analyzeNavType( |
| 2042 | .inlining = null, | 2092 | .inlining = null, |
| 2043 | .comptime_reason = undefined, // set below | 2093 | .comptime_reason = undefined, // set below |
| 2044 | .src_base_inst = old_nav.analysis.?.zir_index, | 2094 | .src_base_inst = old_nav.analysis.?.zir_index, |
| 2045 | .type_name_ctx = old_nav.fqn, | 2095 | .type_name_ctx = old_nav.name, |
| 2096 | .type_fqn_ctx = old_nav.fqn, | ||
| 2046 | }; | 2097 | }; |
| 2047 | defer block.instructions.deinit(gpa); | 2098 | defer block.instructions.deinit(gpa); |
| 2048 | 2099 | ||
| ... | @@ -2983,11 +3034,11 @@ pub fn scanNamespace( | ... | @@ -2983,11 +3034,11 @@ pub fn scanNamespace( |
| 2983 | 3034 | ||
| 2984 | const tracy_trace = trace(@src()); | 3035 | const tracy_trace = trace(@src()); |
| 2985 | defer tracy_trace.end(); | 3036 | defer tracy_trace.end(); |
| 2986 | tracy_trace.addText(Type.fromInterned(namespace.owner_type).containerTypeName(ip).toSlice(ip)); | 3037 | tracy_trace.addText(Type.fromInterned(namespace.owner_type).containerTypeName(ip).fqn.toSlice(ip)); |
| 2987 | tracy_trace.addTextFmt("type_ip_index={d}", .{namespace.owner_type}); | 3038 | tracy_trace.addTextFmt("type_ip_index={d}", .{namespace.owner_type}); |
| 2988 | 3039 | ||
| 2989 | const tracked_unit = zcu.trackUnitSema( | 3040 | const tracked_unit = zcu.trackUnitSema( |
| 2990 | Type.fromInterned(namespace.owner_type).containerTypeName(ip).toSlice(ip), | 3041 | Type.fromInterned(namespace.owner_type).containerTypeName(ip).fqn.toSlice(ip), |
| 2991 | null, | 3042 | null, |
| 2992 | ); | 3043 | ); |
| 2993 | defer tracked_unit.end(zcu); | 3044 | defer tracked_unit.end(zcu); |
| ... | @@ -3309,7 +3360,8 @@ fn analyzeFuncBodyInner( | ... | @@ -3309,7 +3360,8 @@ fn analyzeFuncBodyInner( |
| 3309 | .inlining = null, | 3360 | .inlining = null, |
| 3310 | .comptime_reason = null, | 3361 | .comptime_reason = null, |
| 3311 | .src_base_inst = decl_analysis.zir_index, | 3362 | .src_base_inst = decl_analysis.zir_index, |
| 3312 | .type_name_ctx = func_nav.fqn, | 3363 | .type_name_ctx = func_nav.name, |
| 3364 | .type_fqn_ctx = func_nav.fqn, | ||
| 3313 | }; | 3365 | }; |
| 3314 | defer inner_block.instructions.deinit(gpa); | 3366 | defer inner_block.instructions.deinit(gpa); |
| 3315 | 3367 | ||
| ... | @@ -4409,8 +4461,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru | ... | @@ -4409,8 +4461,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru |
| 4409 | comp.config.use_llvm, | 4461 | comp.config.use_llvm, |
| 4410 | )) { | 4462 | )) { |
| 4411 | else => unreachable, // assertion failure | 4463 | else => unreachable, // assertion failure |
| 4412 | .stage2_llvm, | 4464 | .stage2_llvm => {}, |
| 4413 | => {}, | ||
| 4414 | }, | 4465 | }, |
| 4415 | error.Canceled => |e| return e, | 4466 | error.Canceled => |e| return e, |
| 4416 | } | 4467 | } |
src/codegen.zig+7-9| ... | @@ -196,7 +196,7 @@ pub fn emitFunction( | ... | @@ -196,7 +196,7 @@ pub fn emitFunction( |
| 196 | any_mir: *const AnyMir, | 196 | any_mir: *const AnyMir, |
| 197 | w: *std.Io.Writer, | 197 | w: *std.Io.Writer, |
| 198 | debug_output: link.File.DebugInfoOutput, | 198 | debug_output: link.File.DebugInfoOutput, |
| 199 | ) (Error || std.Io.Writer.Error)!void { | 199 | ) link.EmitError!void { |
| 200 | const zcu = pt.zcu; | 200 | const zcu = pt.zcu; |
| 201 | const func = zcu.funcInfo(func_index); | 201 | const func = zcu.funcInfo(func_index); |
| 202 | const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result; | 202 | const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result; |
| ... | @@ -228,7 +228,7 @@ pub fn generateLazyFunction( | ... | @@ -228,7 +228,7 @@ pub fn generateLazyFunction( |
| 228 | atom_id: link.File.AtomId, | 228 | atom_id: link.File.AtomId, |
| 229 | w: *std.Io.Writer, | 229 | w: *std.Io.Writer, |
| 230 | debug_output: link.File.DebugInfoOutput, | 230 | debug_output: link.File.DebugInfoOutput, |
| 231 | ) (Error || std.Io.Writer.Error)!void { | 231 | ) link.EmitError!void { |
| 232 | const zcu = pt.zcu; | 232 | const zcu = pt.zcu; |
| 233 | const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index| | 233 | const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index| |
| 234 | &zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result | 234 | &zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result |
| ... | @@ -252,7 +252,7 @@ pub fn generateLazySymbol( | ... | @@ -252,7 +252,7 @@ pub fn generateLazySymbol( |
| 252 | w: *std.Io.Writer, | 252 | w: *std.Io.Writer, |
| 253 | debug_output: link.File.DebugInfoOutput, | 253 | debug_output: link.File.DebugInfoOutput, |
| 254 | reloc_parent: link.File.RelocInfo.Parent, | 254 | reloc_parent: link.File.RelocInfo.Parent, |
| 255 | ) (Error || std.Io.Writer.Error)!void { | 255 | ) link.EmitError!void { |
| 256 | const tracy = trace(@src()); | 256 | const tracy = trace(@src()); |
| 257 | defer tracy.end(); | 257 | defer tracy.end(); |
| 258 | tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(pt) }); | 258 | tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(pt) }); |
| ... | @@ -314,7 +314,7 @@ pub fn generateSymbol( | ... | @@ -314,7 +314,7 @@ pub fn generateSymbol( |
| 314 | val: Value, | 314 | val: Value, |
| 315 | w: *std.Io.Writer, | 315 | w: *std.Io.Writer, |
| 316 | reloc_parent: link.File.RelocInfo.Parent, | 316 | reloc_parent: link.File.RelocInfo.Parent, |
| 317 | ) (Error || std.Io.Writer.Error)!void { | 317 | ) link.EmitError!void { |
| 318 | const tracy = trace(@src()); | 318 | const tracy = trace(@src()); |
| 319 | defer tracy.end(); | 319 | defer tracy.end(); |
| 320 | 320 | ||
| ... | @@ -665,7 +665,7 @@ fn lowerPtr( | ... | @@ -665,7 +665,7 @@ fn lowerPtr( |
| 665 | w: *std.Io.Writer, | 665 | w: *std.Io.Writer, |
| 666 | reloc_parent: link.File.RelocInfo.Parent, | 666 | reloc_parent: link.File.RelocInfo.Parent, |
| 667 | prev_offset: u64, | 667 | prev_offset: u64, |
| 668 | ) (Error || std.Io.Writer.Error)!void { | 668 | ) link.EmitError!void { |
| 669 | const zcu = pt.zcu; | 669 | const zcu = pt.zcu; |
| 670 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; | 670 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 671 | const offset: u64 = prev_offset + ptr.byte_offset; | 671 | const offset: u64 = prev_offset + ptr.byte_offset; |
| ... | @@ -723,7 +723,7 @@ fn lowerUavRef( | ... | @@ -723,7 +723,7 @@ fn lowerUavRef( |
| 723 | w: *std.Io.Writer, | 723 | w: *std.Io.Writer, |
| 724 | reloc_parent: link.File.RelocInfo.Parent, | 724 | reloc_parent: link.File.RelocInfo.Parent, |
| 725 | offset: u64, | 725 | offset: u64, |
| 726 | ) (Error || std.Io.Writer.Error)!void { | 726 | ) link.EmitError!void { |
| 727 | const zcu = pt.zcu; | 727 | const zcu = pt.zcu; |
| 728 | const ip = &zcu.intern_pool; | 728 | const ip = &zcu.intern_pool; |
| 729 | const comp = lf.comp; | 729 | const comp = lf.comp; |
| ... | @@ -744,7 +744,6 @@ fn lowerUavRef( | ... | @@ -744,7 +744,6 @@ fn lowerUavRef( |
| 744 | .c => unreachable, | 744 | .c => unreachable, |
| 745 | .spirv => unreachable, | 745 | .spirv => unreachable, |
| 746 | .wasm => { | 746 | .wasm => { |
| 747 | dev.check(link.File.Tag.wasm.devFeature()); | ||
| 748 | const wasm = lf.cast(.wasm).?; | 747 | const wasm = lf.cast(.wasm).?; |
| 749 | assert(reloc_parent == .none); | 748 | assert(reloc_parent == .none); |
| 750 | try wasm.addUavReloc(w.end, uav.val, uav.orig_ty, @intCast(offset)); | 749 | try wasm.addUavReloc(w.end, uav.val, uav.orig_ty, @intCast(offset)); |
| ... | @@ -781,7 +780,7 @@ fn lowerNavRef( | ... | @@ -781,7 +780,7 @@ fn lowerNavRef( |
| 781 | w: *std.Io.Writer, | 780 | w: *std.Io.Writer, |
| 782 | reloc_parent: link.File.RelocInfo.Parent, | 781 | reloc_parent: link.File.RelocInfo.Parent, |
| 783 | offset: u64, | 782 | offset: u64, |
| 784 | ) (Error || std.Io.Writer.Error)!void { | 783 | ) link.EmitError!void { |
| 785 | const zcu = pt.zcu; | 784 | const zcu = pt.zcu; |
| 786 | const ip = &zcu.intern_pool; | 785 | const ip = &zcu.intern_pool; |
| 787 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; | 786 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| ... | @@ -797,7 +796,6 @@ fn lowerNavRef( | ... | @@ -797,7 +796,6 @@ fn lowerNavRef( |
| 797 | .c => unreachable, | 796 | .c => unreachable, |
| 798 | .spirv => unreachable, | 797 | .spirv => unreachable, |
| 799 | .wasm => { | 798 | .wasm => { |
| 800 | dev.check(link.File.Tag.wasm.devFeature()); | ||
| 801 | const wasm = lf.cast(.wasm).?; | 799 | const wasm = lf.cast(.wasm).?; |
| 802 | assert(reloc_parent == .none); | 800 | assert(reloc_parent == .none); |
| 803 | try wasm.addNavReloc(w.end, nav_index, nav_ty, @intCast(offset)); | 801 | try wasm.addNavReloc(w.end, nav_index, nav_ty, @intCast(offset)); |
src/codegen/aarch64/Select.zig+5-5| ... | @@ -896,7 +896,7 @@ pub fn finishAnalysis(isel: *Select) !void { | ... | @@ -896,7 +896,7 @@ pub fn finishAnalysis(isel: *Select) !void { |
| 896 | } | 896 | } |
| 897 | } | 897 | } |
| 898 | 898 | ||
| 899 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, AlreadyReported }!void { | 899 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void { |
| 900 | const zcu = isel.pt.zcu; | 900 | const zcu = isel.pt.zcu; |
| 901 | const ip = &zcu.intern_pool; | 901 | const ip = &zcu.intern_pool; |
| 902 | const gpa = zcu.gpa; | 902 | const gpa = zcu.gpa; |
| ... | @@ -8024,7 +8024,7 @@ fn emitLiteral(isel: *Select, bytes: []const u8) !void { | ... | @@ -8024,7 +8024,7 @@ fn emitLiteral(isel: *Select, bytes: []const u8) !void { |
| 8024 | } | 8024 | } |
| 8025 | } | 8025 | } |
| 8026 | 8026 | ||
| 8027 | fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } { | 8027 | fn fail(isel: *Select, comptime format: []const u8, args: anytype) codegen.Error { |
| 8028 | @branchHint(.cold); | 8028 | @branchHint(.cold); |
| 8029 | return isel.pt.zcu.codegenFail(isel.nav_index, format, args); | 8029 | return isel.pt.zcu.codegenFail(isel.nav_index, format, args); |
| 8030 | } | 8030 | } |
| ... | @@ -10618,7 +10618,7 @@ pub const Value = struct { | ... | @@ -10618,7 +10618,7 @@ pub const Value = struct { |
| 10618 | vi: Value.Index, | 10618 | vi: Value.Index, |
| 10619 | ra: Register.Alias, | 10619 | ra: Register.Alias, |
| 10620 | 10620 | ||
| 10621 | fn finish(mat: Value.Materialize, isel: *Select) error{ OutOfMemory, AlreadyReported }!void { | 10621 | fn finish(mat: Value.Materialize, isel: *Select) codegen.Error!void { |
| 10622 | const live_vi = isel.live_registers.getPtr(mat.ra); | 10622 | const live_vi = isel.live_registers.getPtr(mat.ra); |
| 10623 | assert(live_vi.* == .allocating); | 10623 | assert(live_vi.* == .allocating); |
| 10624 | var vi = mat.vi; | 10624 | var vi = mat.vi; |
| ... | @@ -11659,7 +11659,7 @@ fn use(isel: *Select, air_ref: Air.Inst.Ref) !Value.Index { | ... | @@ -11659,7 +11659,7 @@ fn use(isel: *Select, air_ref: Air.Inst.Ref) !Value.Index { |
| 11659 | return vi; | 11659 | return vi; |
| 11660 | } | 11660 | } |
| 11661 | 11661 | ||
| 11662 | fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReported }!bool { | 11662 | fn fill(isel: *Select, dst_ra: Register.Alias) codegen.Error!bool { |
| 11663 | switch (dst_ra) { | 11663 | switch (dst_ra) { |
| 11664 | else => {}, | 11664 | else => {}, |
| 11665 | Register.Alias.fp, .zr, .sp, .pc, .fpcr, .fpsr, .ffr => return false, | 11665 | Register.Alias.fp, .zr, .sp, .pc, .fpcr, .fpsr, .ffr => return false, |
| ... | @@ -11692,7 +11692,7 @@ fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReport | ... | @@ -11692,7 +11692,7 @@ fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReport |
| 11692 | return true; | 11692 | return true; |
| 11693 | } | 11693 | } |
| 11694 | 11694 | ||
| 11695 | fn fillMemory(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReported }!bool { | 11695 | fn fillMemory(isel: *Select, dst_ra: Register.Alias) codegen.Error!bool { |
| 11696 | const dst_live_vi = isel.live_registers.getPtr(dst_ra); | 11696 | const dst_live_vi = isel.live_registers.getPtr(dst_ra); |
| 11697 | const dst_vi = switch (dst_live_vi.*) { | 11697 | const dst_vi = switch (dst_live_vi.*) { |
| 11698 | _ => |dst_vi| dst_vi, | 11698 | _ => |dst_vi| dst_vi, |
src/codegen/c.zig+7-7| ... | @@ -6,7 +6,7 @@ const log = std.log.scoped(.c); | ... | @@ -6,7 +6,7 @@ const log = std.log.scoped(.c); |
| 6 | const Allocator = mem.Allocator; | 6 | const Allocator = mem.Allocator; |
| 7 | const Writer = std.Io.Writer; | 7 | const Writer = std.Io.Writer; |
| 8 | 8 | ||
| 9 | const dev = @import("../dev.zig"); | 9 | const codegen = @import("../codegen.zig"); |
| 10 | const link = @import("../link.zig"); | 10 | const link = @import("../link.zig"); |
| 11 | const Zcu = @import("../Zcu.zig"); | 11 | const Zcu = @import("../Zcu.zig"); |
| 12 | const Module = @import("../Module.zig"); | 12 | const Module = @import("../Module.zig"); |
| ... | @@ -24,7 +24,7 @@ const BigIntLimb = std.math.big.Limb; | ... | @@ -24,7 +24,7 @@ const BigIntLimb = std.math.big.Limb; |
| 24 | const BigInt = std.math.big.int; | 24 | const BigInt = std.math.big.int; |
| 25 | 25 | ||
| 26 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { | 26 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { |
| 27 | return comptime switch (dev.env.supports(.legalize)) { | 27 | return comptime switch (@import("../dev.zig").env.supports(.legalize)) { |
| 28 | inline false, true => |supports_legalize| &.init(.{ | 28 | inline false, true => |supports_legalize| &.init(.{ |
| 29 | // we don't currently ask zig1 to use safe optimization modes | 29 | // we don't currently ask zig1 to use safe optimization modes |
| 30 | .expand_bit_cast_safe = supports_legalize, | 30 | .expand_bit_cast_safe = supports_legalize, |
| ... | @@ -86,7 +86,7 @@ pub const Mir = struct { | ... | @@ -86,7 +86,7 @@ pub const Mir = struct { |
| 86 | } | 86 | } |
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | pub const Error = Writer.Error || Allocator.Error || error{AlreadyReported}; | 89 | pub const Error = codegen.Error || Writer.Error; |
| 90 | 90 | ||
| 91 | pub const CType = @import("c/type.zig").CType; | 91 | pub const CType = @import("c/type.zig").CType; |
| 92 | 92 | ||
| ... | @@ -2174,11 +2174,11 @@ pub fn genTagNameFn( | ... | @@ -2174,11 +2174,11 @@ pub fn genTagNameFn( |
| 2174 | } | 2174 | } |
| 2175 | 2175 | ||
| 2176 | if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{ | 2176 | if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{ |
| 2177 | loaded_enum.name.fmt(ip), | 2177 | loaded_enum.fqn.fmt(ip), |
| 2178 | }); | 2178 | }); |
| 2179 | try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ | 2179 | try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ |
| 2180 | slice_const_u8_sentinel_0_type_name, | 2180 | slice_const_u8_sentinel_0_type_name, |
| 2181 | fmtIdentUnsolo(loaded_enum.name.toSlice(ip)), | 2181 | fmtIdentUnsolo(loaded_enum.fqn.toSlice(ip)), |
| 2182 | @backingInt(enum_ty.toIntern()), | 2182 | @backingInt(enum_ty.toIntern()), |
| 2183 | enum_type_name, | 2183 | enum_type_name, |
| 2184 | }); | 2184 | }); |
| ... | @@ -2251,7 +2251,7 @@ pub fn generate( | ... | @@ -2251,7 +2251,7 @@ pub fn generate( |
| 2251 | func_index: InternPool.Index, | 2251 | func_index: InternPool.Index, |
| 2252 | air: *const Air, | 2252 | air: *const Air, |
| 2253 | liveness: *const ?Air.Liveness, | 2253 | liveness: *const ?Air.Liveness, |
| 2254 | ) @import("../codegen.zig").Error!Mir { | 2254 | ) codegen.Error!Mir { |
| 2255 | const zcu = pt.zcu; | 2255 | const zcu = pt.zcu; |
| 2256 | const gpa = zcu.gpa; | 2256 | const gpa = zcu.gpa; |
| 2257 | 2257 | ||
| ... | @@ -6666,7 +6666,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6666,7 +6666,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6666 | try f.writeCValue(w, local, .other); | 6666 | try f.writeCValue(w, local, .other); |
| 6667 | try f.need_tag_name_funcs.put(gpa, enum_ty.toIntern(), {}); | 6667 | try f.need_tag_name_funcs.put(gpa, enum_ty.toIntern(), {}); |
| 6668 | try w.print(" = zig_tagName_{f}__{d}(", .{ | 6668 | try w.print(" = zig_tagName_{f}__{d}(", .{ |
| 6669 | fmtIdentUnsolo(enum_ty.containerTypeName(ip).toSlice(ip)), | 6669 | fmtIdentUnsolo(enum_ty.containerTypeName(ip).fqn.toSlice(ip)), |
| 6670 | @backingInt(enum_ty.toIntern()), | 6670 | @backingInt(enum_ty.toIntern()), |
| 6671 | }); | 6671 | }); |
| 6672 | try f.writeCValue(w, operand, .other); | 6672 | try f.writeCValue(w, operand, .other); |
src/codegen/c/type.zig+3-3| ... | @@ -1140,17 +1140,17 @@ pub const CType = union(enum) { | ... | @@ -1140,17 +1140,17 @@ pub const CType = union(enum) { |
| 1140 | try w.print("_{f}", .{fmtZigType(field_ty, zcu)}); | 1140 | try w.print("_{f}", .{fmtZigType(field_ty, zcu)}); |
| 1141 | } | 1141 | } |
| 1142 | } else { | 1142 | } else { |
| 1143 | const name = ty.containerTypeName(ip).toSlice(ip); | 1143 | const name = ty.containerTypeName(ip).fqn.toSlice(ip); |
| 1144 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); | 1144 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); |
| 1145 | }, | 1145 | }, |
| 1146 | .@"opaque" => if (ty.toIntern() == .anyopaque_type) { | 1146 | .@"opaque" => if (ty.toIntern() == .anyopaque_type) { |
| 1147 | try w.writeAll("anyopaque"); | 1147 | try w.writeAll("anyopaque"); |
| 1148 | } else { | 1148 | } else { |
| 1149 | const name = ty.containerTypeName(ip).toSlice(ip); | 1149 | const name = ty.containerTypeName(ip).fqn.toSlice(ip); |
| 1150 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); | 1150 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); |
| 1151 | }, | 1151 | }, |
| 1152 | .@"union", .@"enum" => { | 1152 | .@"union", .@"enum" => { |
| 1153 | const name = ty.containerTypeName(ip).toSlice(ip); | 1153 | const name = ty.containerTypeName(ip).fqn.toSlice(ip); |
| 1154 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); | 1154 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); |
| 1155 | }, | 1155 | }, |
| 1156 | } | 1156 | } |
src/codegen/llvm.zig+11-13| ... | @@ -10,7 +10,6 @@ const build_options = @import("build_options"); | ... | @@ -10,7 +10,6 @@ const build_options = @import("build_options"); |
| 10 | const Air = @import("../Air.zig"); | 10 | const Air = @import("../Air.zig"); |
| 11 | const codegen = @import("../codegen.zig"); | 11 | const codegen = @import("../codegen.zig"); |
| 12 | const Compilation = @import("../Compilation.zig"); | 12 | const Compilation = @import("../Compilation.zig"); |
| 13 | const dev = @import("../dev.zig"); | ||
| 14 | const InternPool = @import("../InternPool.zig"); | 13 | const InternPool = @import("../InternPool.zig"); |
| 15 | const link = @import("../link.zig"); | 14 | const link = @import("../link.zig"); |
| 16 | const Module = @import("../Module.zig"); | 15 | const Module = @import("../Module.zig"); |
| ... | @@ -155,12 +154,11 @@ pub const Object = struct { | ... | @@ -155,12 +154,11 @@ pub const Object = struct { |
| 155 | /// Values for `@llvm.used`. | 154 | /// Values for `@llvm.used`. |
| 156 | used: std.ArrayList(Builder.Constant), | 155 | used: std.ArrayList(Builder.Constant), |
| 157 | 156 | ||
| 158 | pub const Ptr = if (dev.env.supports(.llvm_backend)) *Object else noreturn; | 157 | pub const Ptr = if (@import("../dev.zig").env.supports(.llvm_backend)) *Object else noreturn; |
| 159 | 158 | ||
| 160 | const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type); | 159 | const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type); |
| 161 | 160 | ||
| 162 | pub fn create(arena: Allocator, zcu: *Zcu) !Ptr { | 161 | pub fn create(arena: Allocator, zcu: *Zcu) !Ptr { |
| 163 | dev.check(.llvm_backend); | ||
| 164 | const comp = zcu.comp; | 162 | const comp = zcu.comp; |
| 165 | const gpa = comp.gpa; | 163 | const gpa = comp.gpa; |
| 166 | const target = zcu.getTarget(); | 164 | const target = zcu.getTarget(); |
| ... | @@ -348,7 +346,7 @@ pub const Object = struct { | ... | @@ -348,7 +346,7 @@ pub const Object = struct { |
| 348 | lto: std.zig.LtoMode, | 346 | lto: std.zig.LtoMode, |
| 349 | }; | 347 | }; |
| 350 | 348 | ||
| 351 | pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ AlreadyReported, OutOfMemory }!void { | 349 | pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) link.Error!void { |
| 352 | const zcu = o.zcu; | 350 | const zcu = o.zcu; |
| 353 | const comp = zcu.comp; | 351 | const comp = zcu.comp; |
| 354 | const io = comp.io; | 352 | const io = comp.io; |
| ... | @@ -1141,7 +1139,7 @@ pub const Object = struct { | ... | @@ -1141,7 +1139,7 @@ pub const Object = struct { |
| 1141 | } | 1139 | } |
| 1142 | } | 1140 | } |
| 1143 | 1141 | ||
| 1144 | fn flushTypePool(o: *Object, pt: Zcu.PerThread) Allocator.Error!void { | 1142 | fn flushTypePool(o: *Object, pt: Zcu.PerThread) link.Error!void { |
| 1145 | try o.type_pool.flushPending(pt, .{ .llvm = o }); | 1143 | try o.type_pool.flushPending(pt, .{ .llvm = o }); |
| 1146 | } | 1144 | } |
| 1147 | 1145 | ||
| ... | @@ -1304,7 +1302,7 @@ pub const Object = struct { | ... | @@ -1304,7 +1302,7 @@ pub const Object = struct { |
| 1304 | }, &o.builder); | 1302 | }, &o.builder); |
| 1305 | } | 1303 | } |
| 1306 | 1304 | ||
| 1307 | pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { | 1305 | pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) link.Error!void { |
| 1308 | _ = o.type_map.remove(ty); | 1306 | _ = o.type_map.remove(ty); |
| 1309 | try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); | 1307 | try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); |
| 1310 | if (o.named_enum_map.get(ty)) |llvm_function| { | 1308 | if (o.named_enum_map.get(ty)) |llvm_function| { |
| ... | @@ -1431,7 +1429,7 @@ pub const Object = struct { | ... | @@ -1431,7 +1429,7 @@ pub const Object = struct { |
| 1431 | 1429 | ||
| 1432 | pub fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata { | 1430 | pub fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata { |
| 1433 | assert(!o.builder.strip); | 1431 | assert(!o.builder.strip); |
| 1434 | const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); | 1432 | const index = o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| return @errorCast(err); |
| 1435 | return o.debug_types.items[@backingInt(index)]; | 1433 | return o.debug_types.items[@backingInt(index)]; |
| 1436 | } | 1434 | } |
| 1437 | 1435 | ||
| ... | @@ -2893,7 +2891,7 @@ pub const Object = struct { | ... | @@ -2893,7 +2891,7 @@ pub const Object = struct { |
| 2893 | } | 2891 | } |
| 2894 | } | 2892 | } |
| 2895 | 2893 | ||
| 2896 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | 2894 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).fqn.toSlice(ip))); |
| 2897 | try o.type_map.put(o.gpa, t.toIntern(), ty); | 2895 | try o.type_map.put(o.gpa, t.toIntern(), ty); |
| 2898 | 2896 | ||
| 2899 | o.builder.namedTypeSetBody( | 2897 | o.builder.namedTypeSetBody( |
| ... | @@ -2983,7 +2981,7 @@ pub const Object = struct { | ... | @@ -2983,7 +2981,7 @@ pub const Object = struct { |
| 2983 | }; | 2981 | }; |
| 2984 | 2982 | ||
| 2985 | if (layout.tag_size == 0) { | 2983 | if (layout.tag_size == 0) { |
| 2986 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | 2984 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).fqn.toSlice(ip))); |
| 2987 | try o.type_map.put(o.gpa, t.toIntern(), ty); | 2985 | try o.type_map.put(o.gpa, t.toIntern(), ty); |
| 2988 | 2986 | ||
| 2989 | o.builder.namedTypeSetBody( | 2987 | o.builder.namedTypeSetBody( |
| ... | @@ -3011,7 +3009,7 @@ pub const Object = struct { | ... | @@ -3011,7 +3009,7 @@ pub const Object = struct { |
| 3011 | llvm_fields_len += 1; | 3009 | llvm_fields_len += 1; |
| 3012 | } | 3010 | } |
| 3013 | 3011 | ||
| 3014 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | 3012 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).fqn.toSlice(ip))); |
| 3015 | try o.type_map.put(o.gpa, t.toIntern(), ty); | 3013 | try o.type_map.put(o.gpa, t.toIntern(), ty); |
| 3016 | 3014 | ||
| 3017 | o.builder.namedTypeSetBody( | 3015 | o.builder.namedTypeSetBody( |
| ... | @@ -4026,7 +4024,7 @@ pub const Object = struct { | ... | @@ -4026,7 +4024,7 @@ pub const Object = struct { |
| 4026 | // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type. | 4024 | // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type. |
| 4027 | // TODO: change the builder API so we don't need to do this. | 4025 | // TODO: change the builder API so we don't need to do this. |
| 4028 | try o.builder.fnType(.void, &.{}, .normal), | 4026 | try o.builder.fnType(.void, &.{}, .normal), |
| 4029 | try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), | 4027 | try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fqn.fmt(ip)}), |
| 4030 | toLlvmAddressSpace(.generic, zcu.getTarget()), | 4028 | toLlvmAddressSpace(.generic, zcu.getTarget()), |
| 4031 | ); | 4029 | ); |
| 4032 | gop.value_ptr.* = llvm_function; | 4030 | gop.value_ptr.* = llvm_function; |
| ... | @@ -4108,7 +4106,7 @@ pub const Object = struct { | ... | @@ -4108,7 +4106,7 @@ pub const Object = struct { |
| 4108 | } | 4106 | } |
| 4109 | 4107 | ||
| 4110 | pub fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy { | 4108 | pub fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy { |
| 4111 | const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); | 4109 | const index = o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| return @errorCast(err); |
| 4112 | return o.lazy_abi_aligns.items[@backingInt(index)]; | 4110 | return o.lazy_abi_aligns.items[@backingInt(index)]; |
| 4113 | } | 4111 | } |
| 4114 | 4112 | ||
| ... | @@ -4123,7 +4121,7 @@ pub const Object = struct { | ... | @@ -4123,7 +4121,7 @@ pub const Object = struct { |
| 4123 | // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. | 4121 | // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. |
| 4124 | // TODO: change the builder API so we don't need to do this. | 4122 | // TODO: change the builder API so we don't need to do this. |
| 4125 | try o.builder.fnType(.void, &.{}, .normal), | 4123 | try o.builder.fnType(.void, &.{}, .normal), |
| 4126 | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), | 4124 | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fqn.fmt(ip)}), |
| 4127 | toLlvmAddressSpace(.generic, zcu.getTarget()), | 4125 | toLlvmAddressSpace(.generic, zcu.getTarget()), |
| 4128 | ); | 4126 | ); |
| 4129 | gop.value_ptr.* = llvm_function; | 4127 | gop.value_ptr.* = llvm_function; |
src/codegen/loongarch/Select.zig+8-8| ... | @@ -1020,7 +1020,7 @@ pub const Value = struct { | ... | @@ -1020,7 +1020,7 @@ pub const Value = struct { |
| 1020 | /// Defines a value with a location. | 1020 | /// Defines a value with a location. |
| 1021 | /// Returned location must be free-ed by caller. | 1021 | /// Returned location must be free-ed by caller. |
| 1022 | /// Extension unchanged. | 1022 | /// Extension unchanged. |
| 1023 | fn def(vi: Value.Index, isel: *Select) error{ AlreadyReported, OutOfMemory }!?Location { | 1023 | fn def(vi: Value.Index, isel: *Select) codegen.Error!?Location { |
| 1024 | try vi.collectDefs(isel); | 1024 | try vi.collectDefs(isel); |
| 1025 | return vi.takeLocationMarkWritten(isel); | 1025 | return vi.takeLocationMarkWritten(isel); |
| 1026 | } | 1026 | } |
| ... | @@ -2046,7 +2046,7 @@ pub const Value = struct { | ... | @@ -2046,7 +2046,7 @@ pub const Value = struct { |
| 2046 | if (!std.debug.runtime_safety) assert(@sizeOf(Mat) <= 32); | 2046 | if (!std.debug.runtime_safety) assert(@sizeOf(Mat) <= 32); |
| 2047 | } | 2047 | } |
| 2048 | 2048 | ||
| 2049 | const Error = error{ OutOfMemory, AlreadyReported }; | 2049 | const Error = codegen.Error; |
| 2050 | 2050 | ||
| 2051 | pub fn ra(mat: Value.Mat) Register.Alias { | 2051 | pub fn ra(mat: Value.Mat) Register.Alias { |
| 2052 | return mat.location.register; | 2052 | return mat.location.register; |
| ... | @@ -2296,13 +2296,13 @@ pub const Value = struct { | ... | @@ -2296,13 +2296,13 @@ pub const Value = struct { |
| 2296 | }; | 2296 | }; |
| 2297 | }; | 2297 | }; |
| 2298 | 2298 | ||
| 2299 | fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } { | 2299 | fn fail(isel: *Select, comptime format: []const u8, args: anytype) codegen.Error { |
| 2300 | @branchHint(.cold); | 2300 | @branchHint(.cold); |
| 2301 | wip_mir_log.debug("codegen error: " ++ format, args); | 2301 | wip_mir_log.debug("codegen error: " ++ format, args); |
| 2302 | return isel.pt.zcu.codegenFail(isel.nav_index, format, args); | 2302 | return isel.pt.zcu.codegenFail(isel.nav_index, format, args); |
| 2303 | } | 2303 | } |
| 2304 | 2304 | ||
| 2305 | fn failUnimplemented(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported }!void { | 2305 | fn failUnimplemented(isel: *Select, comptime format: []const u8, args: anytype) codegen.Error!void { |
| 2306 | @branchHint(.cold); | 2306 | @branchHint(.cold); |
| 2307 | if (debug_trap_unimplemented_code) { | 2307 | if (debug_trap_unimplemented_code) { |
| 2308 | const gpa = isel.pt.zcu.gpa; | 2308 | const gpa = isel.pt.zcu.gpa; |
| ... | @@ -2963,7 +2963,7 @@ pub fn verify(isel: *Select, check_values: bool) void { | ... | @@ -2963,7 +2963,7 @@ pub fn verify(isel: *Select, check_values: bool) void { |
| 2963 | } | 2963 | } |
| 2964 | } | 2964 | } |
| 2965 | 2965 | ||
| 2966 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, AlreadyReported }!void { | 2966 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void { |
| 2967 | const zcu = isel.pt.zcu; | 2967 | const zcu = isel.pt.zcu; |
| 2968 | const ip = &zcu.intern_pool; | 2968 | const ip = &zcu.intern_pool; |
| 2969 | const gpa = zcu.gpa; | 2969 | const gpa = zcu.gpa; |
| ... | @@ -5341,7 +5341,7 @@ fn forgetReg(isel: *Select, dst_reg: Register) error{ OutOfMemory, AlreadyReport | ... | @@ -5341,7 +5341,7 @@ fn forgetReg(isel: *Select, dst_reg: Register) error{ OutOfMemory, AlreadyReport |
| 5341 | 5341 | ||
| 5342 | /// Frees a register by moving it to another place. | 5342 | /// Frees a register by moving it to another place. |
| 5343 | /// Returns true on success, false on failure (i.e. dst_reg is locked/allocated or unallocatable). | 5343 | /// Returns true on success, false on failure (i.e. dst_reg is locked/allocated or unallocatable). |
| 5344 | fn fillReg(isel: *Select, dst_reg: Register) error{ OutOfMemory, AlreadyReported }!bool { | 5344 | fn fillReg(isel: *Select, dst_reg: Register) codegen.Error!bool { |
| 5345 | if (!isRegisterAllocatable(dst_reg)) return false; | 5345 | if (!isRegisterAllocatable(dst_reg)) return false; |
| 5346 | const dst_live_vi = isel.live_registers.getPtr(dst_reg); | 5346 | const dst_live_vi = isel.live_registers.getPtr(dst_reg); |
| 5347 | const dst_vi = switch (dst_live_vi.*) { | 5347 | const dst_vi = switch (dst_live_vi.*) { |
| ... | @@ -5377,7 +5377,7 @@ fn fillReg(isel: *Select, dst_reg: Register) error{ OutOfMemory, AlreadyReported | ... | @@ -5377,7 +5377,7 @@ fn fillReg(isel: *Select, dst_reg: Register) error{ OutOfMemory, AlreadyReported |
| 5377 | /// Frees a set of register. If locked is true, these registers are then locked. | 5377 | /// Frees a set of register. If locked is true, these registers are then locked. |
| 5378 | /// Requires all registers to be unlocked. | 5378 | /// Requires all registers to be unlocked. |
| 5379 | /// Returns true on success. | 5379 | /// Returns true on success. |
| 5380 | fn fillRegsBatch(isel: *Select, regs: RegisterSet, locking: bool) error{ OutOfMemory, AlreadyReported }!void { | 5380 | fn fillRegsBatch(isel: *Select, regs: RegisterSet, locking: bool) codegen.Error!void { |
| 5381 | tracking_log.debug("batch fill: {f}", .{fmtRegisterSet(regs)}); | 5381 | tracking_log.debug("batch fill: {f}", .{fmtRegisterSet(regs)}); |
| 5382 | // lock free registers | 5382 | // lock free registers |
| 5383 | var regs_it = regs.iterator(); | 5383 | var regs_it = regs.iterator(); |
| ... | @@ -5419,7 +5419,7 @@ fn fillRegsBatch(isel: *Select, regs: RegisterSet, locking: bool) error{ OutOfMe | ... | @@ -5419,7 +5419,7 @@ fn fillRegsBatch(isel: *Select, regs: RegisterSet, locking: bool) error{ OutOfMe |
| 5419 | 5419 | ||
| 5420 | /// Frees a register by moving it to stack. | 5420 | /// Frees a register by moving it to stack. |
| 5421 | /// Returns true on success, false on failure (i.e. dst_reg is locked/allocated or unallocatable). | 5421 | /// Returns true on success, false on failure (i.e. dst_reg is locked/allocated or unallocatable). |
| 5422 | fn fillRegToMemory(isel: *Select, dst_reg: Register) error{ OutOfMemory, AlreadyReported }!bool { | 5422 | fn fillRegToMemory(isel: *Select, dst_reg: Register) codegen.Error!bool { |
| 5423 | if (!isRegisterAllocatable(dst_reg)) return false; | 5423 | if (!isRegisterAllocatable(dst_reg)) return false; |
| 5424 | const dst_live_vi = isel.live_registers.getPtr(dst_reg); | 5424 | const dst_live_vi = isel.live_registers.getPtr(dst_reg); |
| 5425 | const dst_vi = switch (dst_live_vi.*) { | 5425 | const dst_vi = switch (dst_live_vi.*) { |
src/codegen/riscv64/CodeGen.zig+3-3| ... | @@ -856,7 +856,7 @@ pub fn generateLazy( | ... | @@ -856,7 +856,7 @@ pub fn generateLazy( |
| 856 | atom_index: link.File.AtomId, | 856 | atom_index: link.File.AtomId, |
| 857 | w: *std.Io.Writer, | 857 | w: *std.Io.Writer, |
| 858 | debug_output: link.File.DebugInfoOutput, | 858 | debug_output: link.File.DebugInfoOutput, |
| 859 | ) (codegen.Error || std.Io.Writer.Error)!void { | 859 | ) link.EmitError!void { |
| 860 | _ = atom_index; | 860 | _ = atom_index; |
| 861 | const comp = bin_file.comp; | 861 | const comp = bin_file.comp; |
| 862 | const gpa = comp.gpa; | 862 | const gpa = comp.gpa; |
| ... | @@ -8349,7 +8349,7 @@ fn wantSafety(func: *Func) bool { | ... | @@ -8349,7 +8349,7 @@ fn wantSafety(func: *Func) bool { |
| 8349 | }; | 8349 | }; |
| 8350 | } | 8350 | } |
| 8351 | 8351 | ||
| 8352 | fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } { | 8352 | fn fail(func: *const Func, comptime format: []const u8, args: anytype) codegen.Error { |
| 8353 | @branchHint(.cold); | 8353 | @branchHint(.cold); |
| 8354 | const zcu = func.pt.zcu; | 8354 | const zcu = func.pt.zcu; |
| 8355 | switch (func.owner) { | 8355 | switch (func.owner) { |
| ... | @@ -8359,7 +8359,7 @@ fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ Ou | ... | @@ -8359,7 +8359,7 @@ fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ Ou |
| 8359 | return error.AlreadyReported; | 8359 | return error.AlreadyReported; |
| 8360 | } | 8360 | } |
| 8361 | 8361 | ||
| 8362 | fn failMsg(func: *const Func, msg: *ErrorMsg) error{ OutOfMemory, AlreadyReported } { | 8362 | fn failMsg(func: *const Func, msg: *ErrorMsg) codegen.Error { |
| 8363 | @branchHint(.cold); | 8363 | @branchHint(.cold); |
| 8364 | const zcu = func.pt.zcu; | 8364 | const zcu = func.pt.zcu; |
| 8365 | switch (func.owner) { | 8365 | switch (func.owner) { |
src/codegen/riscv64/Emit.zig+9-9| ... | @@ -13,7 +13,7 @@ prev_di_pc: usize, | ... | @@ -13,7 +13,7 @@ prev_di_pc: usize, |
| 13 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .empty, | 13 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .empty, |
| 14 | relocs: std.ArrayList(Reloc) = .empty, | 14 | relocs: std.ArrayList(Reloc) = .empty, |
| 15 | 15 | ||
| 16 | pub const Error = Lower.Error || std.Io.Writer.Error || error{ | 16 | pub const Error = Lower.Error || link.EmitError || error{ |
| 17 | EmitFail, | 17 | EmitFail, |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| ... | @@ -118,14 +118,14 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -118,14 +118,14 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 118 | else => unreachable, | 118 | else => unreachable, |
| 119 | .pseudo_dbg_prologue_end => { | 119 | .pseudo_dbg_prologue_end => { |
| 120 | switch (emit.debug_output) { | 120 | switch (emit.debug_output) { |
| 121 | .dwarf => |dw| { | 121 | inline .dwarf, .dwarf2 => |dw| { |
| 122 | try dw.setPrologueEnd(); | 122 | try dw.setPrologueEnd(); |
| 123 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ | 123 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ |
| 124 | emit.prev_di_line, emit.prev_di_column, | 124 | emit.prev_di_line, emit.prev_di_column, |
| 125 | }); | 125 | }); |
| 126 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 126 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 127 | }, | 127 | }, |
| 128 | .none => {}, | 128 | .eh_frame, .none => {}, |
| 129 | } | 129 | } |
| 130 | }, | 130 | }, |
| 131 | .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine( | 131 | .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine( |
| ... | @@ -134,14 +134,14 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -134,14 +134,14 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 134 | ), | 134 | ), |
| 135 | .pseudo_dbg_epilogue_begin => { | 135 | .pseudo_dbg_epilogue_begin => { |
| 136 | switch (emit.debug_output) { | 136 | switch (emit.debug_output) { |
| 137 | .dwarf => |dw| { | 137 | inline .dwarf, .dwarf2 => |dw| { |
| 138 | try dw.setEpilogueBegin(); | 138 | try dw.setEpilogueBegin(); |
| 139 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ | 139 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ |
| 140 | emit.prev_di_line, emit.prev_di_column, | 140 | emit.prev_di_line, emit.prev_di_column, |
| 141 | }); | 141 | }); |
| 142 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 142 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 143 | }, | 143 | }, |
| 144 | .none => {}, | 144 | .eh_frame, .none => {}, |
| 145 | } | 145 | } |
| 146 | }, | 146 | }, |
| 147 | .pseudo_dead => {}, | 147 | .pseudo_dead => {}, |
| ... | @@ -190,15 +190,14 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void { | ... | @@ -190,15 +190,14 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void { |
| 190 | const delta_pc: usize = emit.w.end - emit.prev_di_pc; | 190 | const delta_pc: usize = emit.w.end - emit.prev_di_pc; |
| 191 | log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line }); | 191 | log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line }); |
| 192 | switch (emit.debug_output) { | 192 | switch (emit.debug_output) { |
| 193 | .dwarf => |dw| { | 193 | inline .dwarf, .dwarf2 => |dw| { |
| 194 | if (column != emit.prev_di_column) try dw.setColumn(column); | 194 | if (column != emit.prev_di_column) try dw.setColumn(column); |
| 195 | if (delta_line == 0) return; // TODO: fix these edge cases. | 195 | try dw.advanceLineAndPc(delta_line, delta_pc, false); |
| 196 | try dw.advancePCAndLine(delta_line, delta_pc); | ||
| 197 | emit.prev_di_line = line; | 196 | emit.prev_di_line = line; |
| 198 | emit.prev_di_column = column; | 197 | emit.prev_di_column = column; |
| 199 | emit.prev_di_pc = emit.w.end; | 198 | emit.prev_di_pc = emit.w.end; |
| 200 | }, | 199 | }, |
| 201 | .none => {}, | 200 | .eh_frame, .none => {}, |
| 202 | } | 201 | } |
| 203 | } | 202 | } |
| 204 | 203 | ||
| ... | @@ -209,6 +208,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error { | ... | @@ -209,6 +208,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error { |
| 209 | }; | 208 | }; |
| 210 | } | 209 | } |
| 211 | 210 | ||
| 211 | const codegen = @import("../../codegen.zig"); | ||
| 212 | const link = @import("../../link.zig"); | 212 | const link = @import("../../link.zig"); |
| 213 | const log = std.log.scoped(.emit); | 213 | const log = std.log.scoped(.emit); |
| 214 | const mem = std.mem; | 214 | const mem = std.mem; |
src/codegen/riscv64/Mir.zig+1-1| ... | @@ -111,7 +111,7 @@ pub fn emit( | ... | @@ -111,7 +111,7 @@ pub fn emit( |
| 111 | atom_index: link.File.AtomId, | 111 | atom_index: link.File.AtomId, |
| 112 | w: *std.Io.Writer, | 112 | w: *std.Io.Writer, |
| 113 | debug_output: link.File.DebugInfoOutput, | 113 | debug_output: link.File.DebugInfoOutput, |
| 114 | ) (codegen.Error || std.Io.Writer.Error)!void { | 114 | ) link.EmitError!void { |
| 115 | _ = atom_index; | 115 | _ = atom_index; |
| 116 | const zcu = pt.zcu; | 116 | const zcu = pt.zcu; |
| 117 | const comp = zcu.comp; | 117 | const comp = zcu.comp; |
src/codegen/sparc64/CodeGen.zig+2-2| ... | @@ -3450,7 +3450,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) | ... | @@ -3450,7 +3450,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) |
| 3450 | } | 3450 | } |
| 3451 | } | 3451 | } |
| 3452 | 3452 | ||
| 3453 | fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } { | 3453 | fn fail(self: *Self, comptime format: []const u8, args: anytype) codegen.Error { |
| 3454 | @branchHint(.cold); | 3454 | @branchHint(.cold); |
| 3455 | const zcu = self.pt.zcu; | 3455 | const zcu = self.pt.zcu; |
| 3456 | const func = zcu.funcInfo(self.func_index); | 3456 | const func = zcu.funcInfo(self.func_index); |
| ... | @@ -3458,7 +3458,7 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMem | ... | @@ -3458,7 +3458,7 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMem |
| 3458 | return zcu.codegenFailMsg(func.owner_nav, msg); | 3458 | return zcu.codegenFailMsg(func.owner_nav, msg); |
| 3459 | } | 3459 | } |
| 3460 | 3460 | ||
| 3461 | fn failMsg(self: *Self, msg: *ErrorMsg) error{ OutOfMemory, AlreadyReported } { | 3461 | fn failMsg(self: *Self, msg: *ErrorMsg) codegen.Error { |
| 3462 | @branchHint(.cold); | 3462 | @branchHint(.cold); |
| 3463 | const zcu = self.pt.zcu; | 3463 | const zcu = self.pt.zcu; |
| 3464 | const func = zcu.funcInfo(self.func_index); | 3464 | const func = zcu.funcInfo(self.func_index); |
src/codegen/sparc64/Emit.zig+9-9| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | const std = @import("std"); | 4 | const std = @import("std"); |
| 5 | const Endian = std.lang.Endian; | 5 | const Endian = std.lang.Endian; |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const codegen = @import("../../codegen.zig"); | ||
| 7 | const link = @import("../../link.zig"); | 8 | const link = @import("../../link.zig"); |
| 8 | const Zcu = @import("../../Zcu.zig"); | 9 | const Zcu = @import("../../Zcu.zig"); |
| 9 | const ErrorMsg = Zcu.ErrorMsg; | 10 | const ErrorMsg = Zcu.ErrorMsg; |
| ... | @@ -40,8 +41,7 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayList(M | ... | @@ -40,8 +41,7 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayList(M |
| 40 | /// instruction | 41 | /// instruction |
| 41 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .empty, | 42 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .empty, |
| 42 | 43 | ||
| 43 | const InnerError = std.Io.Writer.Error || error{ | 44 | const InnerError = link.EmitError || error{ |
| 44 | OutOfMemory, | ||
| 45 | EmitFail, | 45 | EmitFail, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| ... | @@ -175,21 +175,21 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -175,21 +175,21 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 175 | 175 | ||
| 176 | fn mirDebugPrologueEnd(emit: *Emit) !void { | 176 | fn mirDebugPrologueEnd(emit: *Emit) !void { |
| 177 | switch (emit.debug_output) { | 177 | switch (emit.debug_output) { |
| 178 | .dwarf => |dbg_out| { | 178 | inline .dwarf, .dwarf2 => |dbg_out| { |
| 179 | try dbg_out.setPrologueEnd(); | 179 | try dbg_out.setPrologueEnd(); |
| 180 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 180 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 181 | }, | 181 | }, |
| 182 | .none => {}, | 182 | .eh_frame, .none => {}, |
| 183 | } | 183 | } |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | fn mirDebugEpilogueBegin(emit: *Emit) !void { | 186 | fn mirDebugEpilogueBegin(emit: *Emit) !void { |
| 187 | switch (emit.debug_output) { | 187 | switch (emit.debug_output) { |
| 188 | .dwarf => |dbg_out| { | 188 | inline .dwarf, .dwarf2 => |dbg_out| { |
| 189 | try dbg_out.setEpilogueBegin(); | 189 | try dbg_out.setEpilogueBegin(); |
| 190 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 190 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 191 | }, | 191 | }, |
| 192 | .none => {}, | 192 | .eh_frame, .none => {}, |
| 193 | } | 193 | } |
| 194 | } | 194 | } |
| 195 | 195 | ||
| ... | @@ -496,13 +496,13 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) !void { | ... | @@ -496,13 +496,13 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) !void { |
| 496 | const delta_line = @as(i32, @intCast(line)) - @as(i32, @intCast(emit.prev_di_line)); | 496 | const delta_line = @as(i32, @intCast(line)) - @as(i32, @intCast(emit.prev_di_line)); |
| 497 | const delta_pc: usize = emit.w.end - emit.prev_di_pc; | 497 | const delta_pc: usize = emit.w.end - emit.prev_di_pc; |
| 498 | switch (emit.debug_output) { | 498 | switch (emit.debug_output) { |
| 499 | .dwarf => |dbg_out| { | 499 | inline .dwarf, .dwarf2 => |dbg_out| { |
| 500 | try dbg_out.advancePCAndLine(delta_line, delta_pc); | 500 | try dbg_out.advanceLineAndPc(delta_line, delta_pc, false); |
| 501 | emit.prev_di_line = line; | 501 | emit.prev_di_line = line; |
| 502 | emit.prev_di_column = column; | 502 | emit.prev_di_column = column; |
| 503 | emit.prev_di_pc = emit.w.end; | 503 | emit.prev_di_pc = emit.w.end; |
| 504 | }, | 504 | }, |
| 505 | else => {}, | 505 | .eh_frame, .none => {}, |
| 506 | } | 506 | } |
| 507 | } | 507 | } |
| 508 | 508 |
src/codegen/sparc64/Mir.zig+1-1| ... | @@ -382,7 +382,7 @@ pub fn emit( | ... | @@ -382,7 +382,7 @@ pub fn emit( |
| 382 | atom_index: link.File.AtomId, | 382 | atom_index: link.File.AtomId, |
| 383 | w: *std.Io.Writer, | 383 | w: *std.Io.Writer, |
| 384 | debug_output: link.File.DebugInfoOutput, | 384 | debug_output: link.File.DebugInfoOutput, |
| 385 | ) (codegen.Error || std.Io.Writer.Error)!void { | 385 | ) link.EmitError!void { |
| 386 | _ = atom_index; | 386 | _ = atom_index; |
| 387 | const zcu = pt.zcu; | 387 | const zcu = pt.zcu; |
| 388 | const func = zcu.funcInfo(func_index); | 388 | const func = zcu.funcInfo(func_index); |
src/codegen/spirv/CodeGen.zig+3-9| ... | @@ -240,10 +240,7 @@ pub fn generate( | ... | @@ -240,10 +240,7 @@ pub fn generate( |
| 240 | }; | 240 | }; |
| 241 | defer cg.deinit(); | 241 | defer cg.deinit(); |
| 242 | 242 | ||
| 243 | cg.genNav(true) catch |err| switch (err) { | 243 | try cg.genNav(true); |
| 244 | error.AlreadyReported => return error.AlreadyReported, | ||
| 245 | error.OutOfMemory => return error.OutOfMemory, | ||
| 246 | }; | ||
| 247 | 244 | ||
| 248 | return cg.serializeToMir(gpa); | 245 | return cg.serializeToMir(gpa); |
| 249 | } | 246 | } |
| ... | @@ -270,10 +267,7 @@ pub fn generateNav( | ... | @@ -270,10 +267,7 @@ pub fn generateNav( |
| 270 | }; | 267 | }; |
| 271 | defer cg.deinit(); | 268 | defer cg.deinit(); |
| 272 | 269 | ||
| 273 | cg.genNav(false) catch |err| switch (err) { | 270 | try cg.genNav(false); |
| 274 | error.AlreadyReported => return error.AlreadyReported, | ||
| 275 | error.OutOfMemory => return error.OutOfMemory, | ||
| 276 | }; | ||
| 277 | 271 | ||
| 278 | return cg.serializeToMir(gpa); | 272 | return cg.serializeToMir(gpa); |
| 279 | } | 273 | } |
| ... | @@ -854,7 +848,7 @@ pub fn storageClass(cg: *const CodeGen, as: std.lang.AddressSpace) spec.StorageC | ... | @@ -854,7 +848,7 @@ pub fn storageClass(cg: *const CodeGen, as: std.lang.AddressSpace) spec.StorageC |
| 854 | }; | 848 | }; |
| 855 | } | 849 | } |
| 856 | 850 | ||
| 857 | const Error = error{ AlreadyReported, OutOfMemory }; | 851 | const Error = codegen.Error; |
| 858 | 852 | ||
| 859 | pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | 853 | pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 860 | const gpa = cg.gpa; | 854 | const gpa = cg.gpa; |
src/codegen/spork8/CodeGen.zig+15-27| ... | @@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator; | ... | @@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator; |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | 5 | ||
| 6 | const CodeGen = @This(); | 6 | const CodeGen = @This(); |
| 7 | const codegen = @import("../../codegen.zig"); | ||
| 7 | const link = @import("../../link.zig"); | 8 | const link = @import("../../link.zig"); |
| 8 | const Spork8 = link.File.Spork8; | 9 | const Spork8 = link.File.Spork8; |
| 9 | const Zcu = @import("../../Zcu.zig"); | 10 | const Zcu = @import("../../Zcu.zig"); |
| ... | @@ -133,37 +134,20 @@ pub fn generate( | ... | @@ -133,37 +134,20 @@ pub fn generate( |
| 133 | _ = bin_file; | 134 | _ = bin_file; |
| 134 | const zcu = pt.zcu; | 135 | const zcu = pt.zcu; |
| 135 | const gpa = zcu.gpa; | 136 | const gpa = zcu.gpa; |
| 136 | const cg = zcu.funcInfo(func_index); | 137 | const func = zcu.funcInfo(func_index); |
| 137 | 138 | ||
| 138 | var code_gen: CodeGen = .{ | 139 | var cg: CodeGen = .{ |
| 139 | .gpa = gpa, | 140 | .gpa = gpa, |
| 140 | .pt = pt, | 141 | .pt = pt, |
| 141 | .air = air.*, | 142 | .air = air.*, |
| 142 | .liveness = liveness.*.?, | 143 | .liveness = liveness.*.?, |
| 143 | .owner_nav = cg.owner_nav, | 144 | .owner_nav = func.owner_nav, |
| 144 | .func_index = func_index, | 145 | .func_index = func_index, |
| 145 | .mir_instructions = .empty, | 146 | .mir_instructions = .empty, |
| 146 | .mir_extra = .empty, | 147 | .mir_extra = .empty, |
| 147 | }; | 148 | }; |
| 148 | defer code_gen.deinit(); | 149 | defer cg.deinit(); |
| 149 | 150 | ||
| 150 | return generateInner(&code_gen) catch |err| switch (err) { | ||
| 151 | error.AlreadyReported, | ||
| 152 | error.OutOfMemory, | ||
| 153 | => |e| return e, | ||
| 154 | }; | ||
| 155 | } | ||
| 156 | |||
| 157 | pub fn deinit(cg: *CodeGen) void { | ||
| 158 | cg.* = undefined; | ||
| 159 | } | ||
| 160 | |||
| 161 | const InnerError = error{ | ||
| 162 | AlreadyReported, | ||
| 163 | OutOfMemory, | ||
| 164 | }; | ||
| 165 | |||
| 166 | fn generateInner(cg: *CodeGen) InnerError!Mir { | ||
| 167 | // Generate MIR for function body | 151 | // Generate MIR for function body |
| 168 | try cg.genBody(cg.air.getMainBody()); | 152 | try cg.genBody(cg.air.getMainBody()); |
| 169 | 153 | ||
| ... | @@ -175,7 +159,11 @@ fn generateInner(cg: *CodeGen) InnerError!Mir { | ... | @@ -175,7 +159,11 @@ fn generateInner(cg: *CodeGen) InnerError!Mir { |
| 175 | }; | 159 | }; |
| 176 | } | 160 | } |
| 177 | 161 | ||
| 178 | fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | 162 | pub fn deinit(cg: *CodeGen) void { |
| 163 | cg.* = undefined; | ||
| 164 | } | ||
| 165 | |||
| 166 | fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) codegen.Error!void { | ||
| 179 | const zcu = cg.pt.zcu; | 167 | const zcu = cg.pt.zcu; |
| 180 | const ip = &zcu.intern_pool; | 168 | const ip = &zcu.intern_pool; |
| 181 | 169 | ||
| ... | @@ -185,7 +173,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -185,7 +173,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 185 | } | 173 | } |
| 186 | } | 174 | } |
| 187 | 175 | ||
| 188 | fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 176 | fn genInst(cg: *CodeGen, inst: Air.Inst.Index) codegen.Error!void { |
| 189 | const air_tags = cg.air.instructions.items(.tag); | 177 | const air_tags = cg.air.instructions.items(.tag); |
| 190 | return switch (air_tags[@backingInt(inst)]) { | 178 | return switch (air_tags[@backingInt(inst)]) { |
| 191 | .inferred_alloc, .inferred_alloc_comptime => unreachable, | 179 | .inferred_alloc, .inferred_alloc_comptime => unreachable, |
| ... | @@ -444,17 +432,17 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -444,17 +432,17 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 444 | }; | 432 | }; |
| 445 | } | 433 | } |
| 446 | 434 | ||
| 447 | fn airUnreachable(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 435 | fn airUnreachable(cg: *CodeGen, inst: Air.Inst.Index) codegen.Error!void { |
| 448 | _ = cg; | 436 | _ = cg; |
| 449 | _ = inst; | 437 | _ = inst; |
| 450 | } | 438 | } |
| 451 | 439 | ||
| 452 | fn airTrap(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 440 | fn airTrap(cg: *CodeGen, inst: Air.Inst.Index) codegen.Error!void { |
| 453 | _ = inst; | 441 | _ = inst; |
| 454 | try cg.addTag(.halt); | 442 | try cg.addTag(.halt); |
| 455 | } | 443 | } |
| 456 | 444 | ||
| 457 | fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 445 | fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) codegen.Error!void { |
| 458 | const unwrapped_asm = cg.air.unwrapAsm(inst); | 446 | const unwrapped_asm = cg.air.unwrapAsm(inst); |
| 459 | const outputs = unwrapped_asm.outputs; | 447 | const outputs = unwrapped_asm.outputs; |
| 460 | // const inputs = unwrapped_asm.inputs; | 448 | // const inputs = unwrapped_asm.inputs; |
| ... | @@ -538,7 +526,7 @@ pub fn addTagImm8(cg: *CodeGen, tag: Mir.Inst.Tag, imm8: u8) error{OutOfMemory}! | ... | @@ -538,7 +526,7 @@ pub fn addTagImm8(cg: *CodeGen, tag: Mir.Inst.Tag, imm8: u8) error{OutOfMemory}! |
| 538 | try cg.addInst(.{ .tag = tag, .data = .{ .imm8 = imm8 } }); | 526 | try cg.addInst(.{ .tag = tag, .data = .{ .imm8 = imm8 } }); |
| 539 | } | 527 | } |
| 540 | 528 | ||
| 541 | fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } { | 529 | fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) codegen.Error { |
| 542 | const zcu = cg.pt.zcu; | 530 | const zcu = cg.pt.zcu; |
| 543 | const func = zcu.funcInfo(cg.func_index); | 531 | const func = zcu.funcInfo(cg.func_index); |
| 544 | return zcu.codegenFail(func.owner_nav, fmt, args); | 532 | return zcu.codegenFail(func.owner_nav, fmt, args); |
src/codegen/wasm/CodeGen.zig+3-8| ... | @@ -332,8 +332,7 @@ const ValueTable = std.array_hash_map.Auto(Air.Inst.Ref, WValue); | ... | @@ -332,8 +332,7 @@ const ValueTable = std.array_hash_map.Auto(Air.Inst.Ref, WValue); |
| 332 | 332 | ||
| 333 | const bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {}; | 333 | const bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {}; |
| 334 | 334 | ||
| 335 | const InnerError = error{ | 335 | const InnerError = Error || error{ |
| 336 | OutOfMemory, | ||
| 337 | /// An error occurred when trying to lower AIR to MIR. | 336 | /// An error occurred when trying to lower AIR to MIR. |
| 338 | AlreadyReported, | 337 | AlreadyReported, |
| 339 | /// Compiler implementation could not handle a large integer. | 338 | /// Compiler implementation could not handle a large integer. |
| ... | @@ -361,7 +360,7 @@ pub fn deinit(cg: *CodeGen) void { | ... | @@ -361,7 +360,7 @@ pub fn deinit(cg: *CodeGen) void { |
| 361 | cg.* = undefined; | 360 | cg.* = undefined; |
| 362 | } | 361 | } |
| 363 | 362 | ||
| 364 | pub fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } { | 363 | pub fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) Error { |
| 365 | const zcu = cg.pt.zcu; | 364 | const zcu = cg.pt.zcu; |
| 366 | const func = zcu.funcInfo(cg.func_index); | 365 | const func = zcu.funcInfo(cg.func_index); |
| 367 | return zcu.codegenFail(func.owner_nav, fmt, args); | 366 | return zcu.codegenFail(func.owner_nav, fmt, args); |
| ... | @@ -760,11 +759,7 @@ fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -760,11 +759,7 @@ fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 760 | return .{ .local = .{ .value = initial_index, .references = 1 } }; | 759 | return .{ .local = .{ .value = initial_index, .references = 1 } }; |
| 761 | } | 760 | } |
| 762 | 761 | ||
| 763 | pub const Error = error{ | 762 | pub const Error = codegen.Error; |
| 764 | OutOfMemory, | ||
| 765 | /// Indicates the error is already stored in Zcu `failed_codegen`. | ||
| 766 | AlreadyReported, | ||
| 767 | }; | ||
| 768 | 763 | ||
| 769 | pub fn generate( | 764 | pub fn generate( |
| 770 | bin_file: *link.File, | 765 | bin_file: *link.File, |
src/codegen/x86_64/CodeGen.zig+20-25| ... | @@ -1072,20 +1072,12 @@ pub fn generate( | ... | @@ -1072,20 +1072,12 @@ pub fn generate( |
| 1072 | ); | 1072 | ); |
| 1073 | } | 1073 | } |
| 1074 | 1074 | ||
| 1075 | function.gen(&file.zir.?, func_zir.inst, func.comptime_args, call_info.air_arg_count) catch |err| switch (err) { | 1075 | function.gen(&file.zir.?, func_zir.inst, &func, call_info.air_arg_count) catch |err| switch (err) { |
| 1076 | error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}), | 1076 | error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}), |
| 1077 | else => |e| return e, | 1077 | else => |e| return e, |
| 1078 | }; | 1078 | }; |
| 1079 | 1079 | ||
| 1080 | // Drop them off at the rbrace. | 1080 | if (!mod.strip) _ = try function.asmPseudo(.pseudo_dbg_end_none); |
| 1081 | if (!mod.strip) _ = try function.addInst(.{ | ||
| 1082 | .tag = .pseudo, | ||
| 1083 | .ops = .pseudo_dbg_line_line_column, | ||
| 1084 | .data = .{ .line_column = .{ | ||
| 1085 | .line = func.rbrace_line, | ||
| 1086 | .column = func.rbrace_column, | ||
| 1087 | } }, | ||
| 1088 | }); | ||
| 1089 | 1081 | ||
| 1090 | try function.mir_extra.shrinkToLen(gpa); | 1082 | try function.mir_extra.shrinkToLen(gpa); |
| 1091 | try function.mir_string_bytes.shrinkToLen(gpa); | 1083 | try function.mir_string_bytes.shrinkToLen(gpa); |
| ... | @@ -1120,7 +1112,7 @@ pub fn generateLazy( | ... | @@ -1120,7 +1112,7 @@ pub fn generateLazy( |
| 1120 | atom_id: link.File.AtomId, | 1112 | atom_id: link.File.AtomId, |
| 1121 | w: *std.Io.Writer, | 1113 | w: *std.Io.Writer, |
| 1122 | debug_output: link.File.DebugInfoOutput, | 1114 | debug_output: link.File.DebugInfoOutput, |
| 1123 | ) codegen.Error!void { | 1115 | ) link.EmitError!void { |
| 1124 | const gpa = pt.zcu.gpa; | 1116 | const gpa = pt.zcu.gpa; |
| 1125 | // This function is for generating global code, so we use the root module. | 1117 | // This function is for generating global code, so we use the root module. |
| 1126 | const mod = pt.zcu.comp.root_mod; | 1118 | const mod = pt.zcu.comp.root_mod; |
| ... | @@ -1228,18 +1220,18 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void { | ... | @@ -1228,18 +1220,18 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void { |
| 1228 | switch (mir_inst.ops) { | 1220 | switch (mir_inst.ops) { |
| 1229 | else => unreachable, | 1221 | else => unreachable, |
| 1230 | .pseudo_dbg_prologue_end_none, | 1222 | .pseudo_dbg_prologue_end_none, |
| 1231 | .pseudo_dbg_epilogue_begin_none, | ||
| 1232 | .pseudo_dbg_enter_block_none, | 1223 | .pseudo_dbg_enter_block_none, |
| 1233 | .pseudo_dbg_leave_block_none, | 1224 | .pseudo_dbg_leave_block_none, |
| 1225 | .pseudo_dbg_end_none, | ||
| 1234 | .pseudo_dbg_arg_none, | 1226 | .pseudo_dbg_arg_none, |
| 1235 | .pseudo_dbg_var_args_none, | 1227 | .pseudo_dbg_var_args_none, |
| 1236 | .pseudo_dbg_var_none, | 1228 | .pseudo_dbg_var_none, |
| 1237 | .pseudo_dead_none, | 1229 | .pseudo_dead_none, |
| 1238 | => {}, | 1230 | => {}, |
| 1239 | .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try w.print( | 1231 | .pseudo_dbg_line_stmt_line_column, |
| 1240 | " {[line]d}, {[column]d}", | 1232 | .pseudo_dbg_line_line_column, |
| 1241 | mir_inst.data.line_column, | 1233 | .pseudo_dbg_epilogue_begin_line_column, |
| 1242 | ), | 1234 | => try w.print(" {[line]d}, {[column]d}", mir_inst.data.line_column), |
| 1243 | .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try w.print(" {f}", .{ | 1235 | .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try w.print(" {f}", .{ |
| 1244 | ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip), | 1236 | ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip), |
| 1245 | }), | 1237 | }), |
| ... | @@ -2069,7 +2061,7 @@ fn gen( | ... | @@ -2069,7 +2061,7 @@ fn gen( |
| 2069 | self: *CodeGen, | 2061 | self: *CodeGen, |
| 2070 | zir: *const std.zig.Zir, | 2062 | zir: *const std.zig.Zir, |
| 2071 | func_zir_inst: std.zig.Zir.Inst.Index, | 2063 | func_zir_inst: std.zig.Zir.Inst.Index, |
| 2072 | comptime_args: InternPool.Index.Slice, | 2064 | func: *const InternPool.Key.Func, |
| 2073 | air_arg_count: u32, | 2065 | air_arg_count: u32, |
| 2074 | ) InnerError!void { | 2066 | ) InnerError!void { |
| 2075 | const pt = self.pt; | 2067 | const pt = self.pt; |
| ... | @@ -2150,7 +2142,7 @@ fn gen( | ... | @@ -2150,7 +2142,7 @@ fn gen( |
| 2150 | 2142 | ||
| 2151 | if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none); | 2143 | if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none); |
| 2152 | 2144 | ||
| 2153 | try self.genMainBody(zir, func_zir_inst, comptime_args, air_arg_count); | 2145 | try self.genMainBody(zir, func_zir_inst, func.comptime_args, air_arg_count); |
| 2154 | 2146 | ||
| 2155 | const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: { | 2147 | const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: { |
| 2156 | var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1); | 2148 | var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1); |
| ... | @@ -2165,7 +2157,14 @@ fn gen( | ... | @@ -2165,7 +2157,14 @@ fn gen( |
| 2165 | } | 2157 | } |
| 2166 | for (self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc); | 2158 | for (self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc); |
| 2167 | 2159 | ||
| 2168 | if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none); | 2160 | if (!self.mod.strip) _ = try self.addInst(.{ |
| 2161 | .tag = .pseudo, | ||
| 2162 | .ops = .pseudo_dbg_epilogue_begin_line_column, | ||
| 2163 | .data = .{ .line_column = .{ | ||
| 2164 | .line = func.rbrace_line, | ||
| 2165 | .column = func.rbrace_column, | ||
| 2166 | } }, | ||
| 2167 | }); | ||
| 2169 | const backpatch_stack_dealloc = try self.asmPlaceholder(); | 2168 | const backpatch_stack_dealloc = try self.asmPlaceholder(); |
| 2170 | const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder(); | 2169 | const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder(); |
| 2171 | try self.asmRegister(.{ ._, .pop }, .rbp); | 2170 | try self.asmRegister(.{ ._, .pop }, .rbp); |
| ... | @@ -2283,11 +2282,7 @@ fn gen( | ... | @@ -2283,11 +2282,7 @@ fn gen( |
| 2283 | .data = .{ .reg_list = frame_layout.save_reg_list }, | 2282 | .data = .{ .reg_list = frame_layout.save_reg_list }, |
| 2284 | }); | 2283 | }); |
| 2285 | } | 2284 | } |
| 2286 | } else { | 2285 | } else try self.genMainBody(zir, func_zir_inst, func.comptime_args, air_arg_count); |
| 2287 | if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none); | ||
| 2288 | try self.genMainBody(zir, func_zir_inst, comptime_args, air_arg_count); | ||
| 2289 | if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none); | ||
| 2290 | } | ||
| 2291 | } | 2286 | } |
| 2292 | 2287 | ||
| 2293 | fn genMainBody( | 2288 | fn genMainBody( |
| ... | @@ -182177,7 +182172,7 @@ fn resolveCallingConventionValues( | ... | @@ -182177,7 +182172,7 @@ fn resolveCallingConventionValues( |
| 182177 | return result; | 182172 | return result; |
| 182178 | } | 182173 | } |
| 182179 | 182174 | ||
| 182180 | fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } { | 182175 | fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) codegen.Error { |
| 182181 | @branchHint(.cold); | 182176 | @branchHint(.cold); |
| 182182 | const zcu = cg.pt.zcu; | 182177 | const zcu = cg.pt.zcu; |
| 182183 | return switch (cg.owner) { | 182178 | return switch (cg.owner) { |
src/codegen/x86_64/Emit.zig+209-192| ... | @@ -16,10 +16,8 @@ code_offset_mapping: std.ArrayList(u32), | ... | @@ -16,10 +16,8 @@ code_offset_mapping: std.ArrayList(u32), |
| 16 | relocs: std.ArrayList(Reloc), | 16 | relocs: std.ArrayList(Reloc), |
| 17 | table_relocs: std.ArrayList(TableReloc), | 17 | table_relocs: std.ArrayList(TableReloc), |
| 18 | 18 | ||
| 19 | pub const Error = Lower.Error || error{ | 19 | pub const Error = Lower.Error || codegen.Error || std.Io.Writer.Error || error{ |
| 20 | AlreadyReported, | ||
| 21 | EmitFail, | 20 | EmitFail, |
| 22 | NotFile, | ||
| 23 | } || std.posix.MMapError || std.posix.MRemapError || link.File.UpdateDebugInfoError; | 21 | } || std.posix.MMapError || std.posix.MRemapError || link.File.UpdateDebugInfoError; |
| 24 | 22 | ||
| 25 | pub fn emitMir(emit: *Emit) Error!void { | 23 | pub fn emitMir(emit: *Emit) Error!void { |
| ... | @@ -38,7 +36,7 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -38,7 +36,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 38 | if (lowered_inst.prefix == .directive) { | 36 | if (lowered_inst.prefix == .directive) { |
| 39 | const start_offset: u32 = @intCast(emit.w.end); | 37 | const start_offset: u32 = @intCast(emit.w.end); |
| 40 | switch (emit.debug_output) { | 38 | switch (emit.debug_output) { |
| 41 | .dwarf => |dwarf| switch (lowered_inst.encoding.mnemonic) { | 39 | inline .dwarf, .dwarf2, .eh_frame => |dwarf| switch (lowered_inst.encoding.mnemonic) { |
| 42 | .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{ | 40 | .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{ |
| 43 | .reg = lowered_inst.ops[0].reg.dwarfNum(), | 41 | .reg = lowered_inst.ops[0].reg.dwarfNum(), |
| 44 | .off = lowered_inst.ops[1].imm.signed, | 42 | .off = lowered_inst.ops[1].imm.signed, |
| ... | @@ -460,204 +458,222 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -460,204 +458,222 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 460 | 458 | ||
| 461 | if (lowered.insts.len == 0) { | 459 | if (lowered.insts.len == 0) { |
| 462 | const mir_inst = emit.lower.mir.instructions.get(mir_index); | 460 | const mir_inst = emit.lower.mir.instructions.get(mir_index); |
| 463 | switch (mir_inst.tag) { | 461 | assert(mir_inst.tag == .pseudo); |
| 462 | switch (mir_inst.ops) { | ||
| 464 | else => unreachable, | 463 | else => unreachable, |
| 465 | .pseudo => switch (mir_inst.ops) { | 464 | .pseudo_dbg_prologue_end_none => switch (emit.debug_output) { |
| 466 | else => unreachable, | 465 | inline .dwarf, .dwarf2 => |dwarf| { |
| 467 | .pseudo_dbg_prologue_end_none => switch (emit.debug_output) { | 466 | try dwarf.setPrologueEnd(); |
| 468 | .dwarf => |dwarf| try dwarf.setPrologueEnd(), | 467 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ |
| 469 | .none => {}, | 468 | emit.prev_di_loc.line, emit.prev_di_loc.column, |
| 469 | }); | ||
| 470 | }, | 470 | }, |
| 471 | .pseudo_dbg_line_stmt_line_column => try emit.dbgAdvancePCAndLine(.{ | 471 | .eh_frame, .none => {}, |
| 472 | .line = mir_inst.data.line_column.line, | 472 | }, |
| 473 | .column = mir_inst.data.line_column.column, | 473 | .pseudo_dbg_line_stmt_line_column => try emit.dbgAdvanceLineAndPc(.{ |
| 474 | .is_stmt = true, | 474 | .line = mir_inst.data.line_column.line, |
| 475 | }), | 475 | .column = mir_inst.data.line_column.column, |
| 476 | .pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(.{ | 476 | .is_stmt = true, |
| 477 | .line = mir_inst.data.line_column.line, | 477 | }), |
| 478 | .column = mir_inst.data.line_column.column, | 478 | .pseudo_dbg_line_line_column => try emit.dbgAdvanceLineAndPc(.{ |
| 479 | .is_stmt = false, | 479 | .line = mir_inst.data.line_column.line, |
| 480 | }), | 480 | .column = mir_inst.data.line_column.column, |
| 481 | .pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) { | 481 | .is_stmt = false, |
| 482 | .dwarf => |dwarf| { | 482 | }), |
| 483 | .pseudo_dbg_epilogue_begin_line_column => { | ||
| 484 | switch (emit.debug_output) { | ||
| 485 | inline .dwarf, .dwarf2 => |dwarf| { | ||
| 483 | try dwarf.setEpilogueBegin(); | 486 | try dwarf.setEpilogueBegin(); |
| 484 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ | 487 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ |
| 485 | emit.prev_di_loc.line, emit.prev_di_loc.column, | 488 | emit.prev_di_loc.line, emit.prev_di_loc.column, |
| 486 | }); | 489 | }); |
| 487 | try emit.dbgAdvancePCAndLine(emit.prev_di_loc); | ||
| 488 | }, | 490 | }, |
| 489 | .none => {}, | 491 | .eh_frame, .none => {}, |
| 490 | }, | 492 | } |
| 491 | .pseudo_dbg_enter_block_none => switch (emit.debug_output) { | 493 | try emit.dbgAdvanceLineAndPc(.{ |
| 492 | .dwarf => |dwarf| { | 494 | .line = mir_inst.data.line_column.line, |
| 493 | log.debug("mirDbgEnterBlock (line={d}, col={d})", .{ | 495 | .column = mir_inst.data.line_column.column, |
| 494 | emit.prev_di_loc.line, emit.prev_di_loc.column, | 496 | }); |
| 495 | }); | 497 | }, |
| 496 | try dwarf.enterBlock(emit.w.end); | 498 | .pseudo_dbg_enter_block_none => switch (emit.debug_output) { |
| 497 | }, | 499 | inline .dwarf, .dwarf2 => |dwarf| { |
| 498 | .none => {}, | 500 | log.debug("mirDbgEnterBlock (line={d}, col={d})", .{ |
| 501 | emit.prev_di_loc.line, emit.prev_di_loc.column, | ||
| 502 | }); | ||
| 503 | try dwarf.enterBlock(emit.w.end); | ||
| 499 | }, | 504 | }, |
| 500 | .pseudo_dbg_leave_block_none => switch (emit.debug_output) { | 505 | .eh_frame, .none => {}, |
| 501 | .dwarf => |dwarf| { | 506 | }, |
| 502 | log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{ | 507 | .pseudo_dbg_leave_block_none => switch (emit.debug_output) { |
| 503 | emit.prev_di_loc.line, emit.prev_di_loc.column, | 508 | inline .dwarf, .dwarf2 => |dwarf| { |
| 504 | }); | 509 | log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{ |
| 505 | try dwarf.leaveBlock(emit.w.end); | 510 | emit.prev_di_loc.line, emit.prev_di_loc.column, |
| 506 | }, | 511 | }); |
| 507 | .none => {}, | 512 | try dwarf.leaveBlock(emit.w.end); |
| 508 | }, | 513 | }, |
| 509 | .pseudo_dbg_enter_inline_func => switch (emit.debug_output) { | 514 | .eh_frame, .none => {}, |
| 510 | .dwarf => |dwarf| { | 515 | }, |
| 511 | log.debug("mirDbgEnterInline (line={d}, col={d})", .{ | 516 | .pseudo_dbg_enter_inline_func => switch (emit.debug_output) { |
| 512 | emit.prev_di_loc.line, emit.prev_di_loc.column, | 517 | inline .dwarf, .dwarf2 => |dwarf| { |
| 513 | }); | 518 | log.debug("mirDbgEnterInline (line={d}, col={d})", .{ |
| 514 | try dwarf.enterInlineFunc(mir_inst.data.ip_index, emit.w.end, emit.prev_di_loc.line, emit.prev_di_loc.column); | 519 | emit.prev_di_loc.line, emit.prev_di_loc.column, |
| 515 | }, | 520 | }); |
| 516 | .none => {}, | 521 | try dwarf.enterInlineFunc(mir_inst.data.ip_index, emit.w.end, emit.prev_di_loc.line, emit.prev_di_loc.column); |
| 517 | }, | 522 | }, |
| 518 | .pseudo_dbg_leave_inline_func => switch (emit.debug_output) { | 523 | .eh_frame, .none => {}, |
| 519 | .dwarf => |dwarf| { | 524 | }, |
| 520 | log.debug("mirDbgLeaveInline (line={d}, col={d})", .{ | 525 | .pseudo_dbg_leave_inline_func => switch (emit.debug_output) { |
| 521 | emit.prev_di_loc.line, emit.prev_di_loc.column, | 526 | inline .dwarf, .dwarf2 => |dwarf| { |
| 522 | }); | 527 | log.debug("mirDbgLeaveInline (line={d}, col={d})", .{ |
| 523 | try dwarf.leaveInlineFunc(mir_inst.data.ip_index, emit.w.end); | 528 | emit.prev_di_loc.line, emit.prev_di_loc.column, |
| 524 | }, | 529 | }); |
| 525 | .none => {}, | 530 | try dwarf.leaveInlineFunc(mir_inst.data.ip_index, emit.w.end); |
| 526 | }, | 531 | }, |
| 527 | .pseudo_dbg_arg_none, | 532 | .eh_frame, .none => {}, |
| 528 | .pseudo_dbg_arg_i_s, | 533 | }, |
| 529 | .pseudo_dbg_arg_i_u, | 534 | .pseudo_dbg_end_none => try emit.dbgAdvanceLineAndPc(.{ |
| 530 | .pseudo_dbg_arg_i_64, | 535 | .line = emit.prev_di_loc.line, |
| 531 | .pseudo_dbg_arg_ro, | 536 | .column = emit.prev_di_loc.column, |
| 532 | .pseudo_dbg_arg_fa, | 537 | .end = true, |
| 533 | .pseudo_dbg_arg_m, | 538 | }), |
| 534 | .pseudo_dbg_var_none, | 539 | .pseudo_dbg_arg_none, |
| 535 | .pseudo_dbg_var_i_s, | 540 | .pseudo_dbg_arg_i_s, |
| 536 | .pseudo_dbg_var_i_u, | 541 | .pseudo_dbg_arg_i_u, |
| 537 | .pseudo_dbg_var_i_64, | 542 | .pseudo_dbg_arg_i_64, |
| 538 | .pseudo_dbg_var_ro, | 543 | .pseudo_dbg_arg_ro, |
| 539 | .pseudo_dbg_var_fa, | 544 | .pseudo_dbg_arg_fa, |
| 540 | .pseudo_dbg_var_m, | 545 | .pseudo_dbg_arg_m, |
| 541 | => switch (emit.debug_output) { | 546 | .pseudo_dbg_var_none, |
| 542 | .dwarf => |dwarf| { | 547 | .pseudo_dbg_var_i_s, |
| 543 | var loc_buf: [2]link.File.Dwarf.Loc = undefined; | 548 | .pseudo_dbg_var_i_u, |
| 544 | const loc: link.File.Dwarf.Loc = loc: switch (mir_inst.ops) { | 549 | .pseudo_dbg_var_i_64, |
| 550 | .pseudo_dbg_var_ro, | ||
| 551 | .pseudo_dbg_var_fa, | ||
| 552 | .pseudo_dbg_var_m, | ||
| 553 | => switch (emit.debug_output) { | ||
| 554 | inline .dwarf, .dwarf2 => |dwarf, tag| { | ||
| 555 | const DwarfLoc = switch (tag) { | ||
| 556 | .dwarf => link.File.Dwarf.Loc, | ||
| 557 | .dwarf2 => link.File.Dwarf2.Loc, | ||
| 558 | .eh_frame, .none => comptime unreachable, | ||
| 559 | }; | ||
| 560 | var loc_buf: [2]DwarfLoc = undefined; | ||
| 561 | const loc: DwarfLoc = loc: switch (mir_inst.ops) { | ||
| 562 | else => unreachable, | ||
| 563 | .pseudo_dbg_arg_none, .pseudo_dbg_var_none => .empty, | ||
| 564 | .pseudo_dbg_arg_i_s, | ||
| 565 | .pseudo_dbg_arg_i_u, | ||
| 566 | .pseudo_dbg_var_i_s, | ||
| 567 | .pseudo_dbg_var_i_u, | ||
| 568 | => .{ .stack_value = stack_value: { | ||
| 569 | loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.i.i)) { | ||
| 570 | .signed => |s| .{ .consts = s }, | ||
| 571 | .unsigned => |u| .{ .constu = u }, | ||
| 572 | }; | ||
| 573 | break :stack_value &loc_buf[0]; | ||
| 574 | } }, | ||
| 575 | .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => .{ .stack_value = stack_value: { | ||
| 576 | loc_buf[0] = .{ .constu = mir_inst.data.i64 }; | ||
| 577 | break :stack_value &loc_buf[0]; | ||
| 578 | } }, | ||
| 579 | .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => { | ||
| 580 | const reg_off = emit.lower.mir.resolveFrameAddr(mir_inst.data.fa); | ||
| 581 | break :loc .{ .plus = .{ | ||
| 582 | reg: { | ||
| 583 | loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() }; | ||
| 584 | break :reg &loc_buf[0]; | ||
| 585 | }, | ||
| 586 | off: { | ||
| 587 | loc_buf[1] = .{ .consts = reg_off.off }; | ||
| 588 | break :off &loc_buf[1]; | ||
| 589 | }, | ||
| 590 | } }; | ||
| 591 | }, | ||
| 592 | .pseudo_dbg_arg_m, .pseudo_dbg_var_m => { | ||
| 593 | const mem = emit.lower.mir.resolveMemoryExtra(mir_inst.data.x.payload).decode(); | ||
| 594 | break :loc .{ .plus = .{ | ||
| 595 | base: { | ||
| 596 | loc_buf[0] = switch (mem.base()) { | ||
| 597 | .none => .{ .constu = 0 }, | ||
| 598 | .reg => |reg| .{ .breg = reg.dwarfNum() }, | ||
| 599 | .frame, .table, .rip_inst => unreachable, | ||
| 600 | .nav => |nav| .{ .addr_reloc = try codegen.genNavRef( | ||
| 601 | emit.bin_file, | ||
| 602 | emit.pt, | ||
| 603 | nav, | ||
| 604 | ) }, | ||
| 605 | .uav => |uav| .{ .addr_reloc = try emit.bin_file.lowerUav( | ||
| 606 | emit.pt, | ||
| 607 | uav.val, | ||
| 608 | Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu), | ||
| 609 | ) }, | ||
| 610 | .lazy_sym, .extern_func => unreachable, | ||
| 611 | }; | ||
| 612 | break :base &loc_buf[0]; | ||
| 613 | }, | ||
| 614 | disp: { | ||
| 615 | loc_buf[1] = switch (mem.disp()) { | ||
| 616 | .signed => |s| .{ .consts = s }, | ||
| 617 | .unsigned => |u| .{ .constu = u }, | ||
| 618 | }; | ||
| 619 | break :disp &loc_buf[1]; | ||
| 620 | }, | ||
| 621 | } }; | ||
| 622 | }, | ||
| 623 | }; | ||
| 624 | |||
| 625 | const local = &emit.lower.mir.locals[local_index]; | ||
| 626 | local_index += 1; | ||
| 627 | try dwarf.genLocalVarDebugInfo( | ||
| 628 | switch (mir_inst.ops) { | ||
| 545 | else => unreachable, | 629 | else => unreachable, |
| 546 | .pseudo_dbg_arg_none, .pseudo_dbg_var_none => .empty, | 630 | .pseudo_dbg_arg_none, |
| 547 | .pseudo_dbg_arg_i_s, | 631 | .pseudo_dbg_arg_i_s, |
| 548 | .pseudo_dbg_arg_i_u, | 632 | .pseudo_dbg_arg_i_u, |
| 633 | .pseudo_dbg_arg_i_64, | ||
| 634 | .pseudo_dbg_arg_ro, | ||
| 635 | .pseudo_dbg_arg_fa, | ||
| 636 | .pseudo_dbg_arg_m, | ||
| 637 | .pseudo_dbg_arg_val, | ||
| 638 | => .arg, | ||
| 639 | .pseudo_dbg_var_none, | ||
| 549 | .pseudo_dbg_var_i_s, | 640 | .pseudo_dbg_var_i_s, |
| 550 | .pseudo_dbg_var_i_u, | 641 | .pseudo_dbg_var_i_u, |
| 551 | => .{ .stack_value = stack_value: { | 642 | .pseudo_dbg_var_i_64, |
| 552 | loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.i.i)) { | 643 | .pseudo_dbg_var_ro, |
| 553 | .signed => |s| .{ .consts = s }, | 644 | .pseudo_dbg_var_fa, |
| 554 | .unsigned => |u| .{ .constu = u }, | 645 | .pseudo_dbg_var_m, |
| 555 | }; | 646 | .pseudo_dbg_var_val, |
| 556 | break :stack_value &loc_buf[0]; | 647 | => .local_var, |
| 557 | } }, | 648 | }, |
| 558 | .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => .{ .stack_value = stack_value: { | 649 | local.name.toSlice(&emit.lower.mir), |
| 559 | loc_buf[0] = .{ .constu = mir_inst.data.i64 }; | 650 | .fromInterned(local.type), |
| 560 | break :stack_value &loc_buf[0]; | 651 | loc, |
| 561 | } }, | 652 | ); |
| 562 | .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => { | ||
| 563 | const reg_off = emit.lower.mir.resolveFrameAddr(mir_inst.data.fa); | ||
| 564 | break :loc .{ .plus = .{ | ||
| 565 | reg: { | ||
| 566 | loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() }; | ||
| 567 | break :reg &loc_buf[0]; | ||
| 568 | }, | ||
| 569 | off: { | ||
| 570 | loc_buf[1] = .{ .consts = reg_off.off }; | ||
| 571 | break :off &loc_buf[1]; | ||
| 572 | }, | ||
| 573 | } }; | ||
| 574 | }, | ||
| 575 | .pseudo_dbg_arg_m, .pseudo_dbg_var_m => { | ||
| 576 | const mem = emit.lower.mir.resolveMemoryExtra(mir_inst.data.x.payload).decode(); | ||
| 577 | break :loc .{ .plus = .{ | ||
| 578 | base: { | ||
| 579 | loc_buf[0] = switch (mem.base()) { | ||
| 580 | .none => .{ .constu = 0 }, | ||
| 581 | .reg => |reg| .{ .breg = reg.dwarfNum() }, | ||
| 582 | .frame, .table, .rip_inst => unreachable, | ||
| 583 | .nav => |nav| .{ .addr_reloc = try codegen.genNavRef( | ||
| 584 | emit.bin_file, | ||
| 585 | emit.pt, | ||
| 586 | nav, | ||
| 587 | ) }, | ||
| 588 | .uav => |uav| .{ .addr_reloc = try emit.bin_file.lowerUav( | ||
| 589 | emit.pt, | ||
| 590 | uav.val, | ||
| 591 | Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu), | ||
| 592 | ) }, | ||
| 593 | .lazy_sym, .extern_func => unreachable, | ||
| 594 | }; | ||
| 595 | break :base &loc_buf[0]; | ||
| 596 | }, | ||
| 597 | disp: { | ||
| 598 | loc_buf[1] = switch (mem.disp()) { | ||
| 599 | .signed => |s| .{ .consts = s }, | ||
| 600 | .unsigned => |u| .{ .constu = u }, | ||
| 601 | }; | ||
| 602 | break :disp &loc_buf[1]; | ||
| 603 | }, | ||
| 604 | } }; | ||
| 605 | }, | ||
| 606 | }; | ||
| 607 | |||
| 608 | const local = &emit.lower.mir.locals[local_index]; | ||
| 609 | local_index += 1; | ||
| 610 | try dwarf.genLocalVarDebugInfo( | ||
| 611 | switch (mir_inst.ops) { | ||
| 612 | else => unreachable, | ||
| 613 | .pseudo_dbg_arg_none, | ||
| 614 | .pseudo_dbg_arg_i_s, | ||
| 615 | .pseudo_dbg_arg_i_u, | ||
| 616 | .pseudo_dbg_arg_i_64, | ||
| 617 | .pseudo_dbg_arg_ro, | ||
| 618 | .pseudo_dbg_arg_fa, | ||
| 619 | .pseudo_dbg_arg_m, | ||
| 620 | .pseudo_dbg_arg_val, | ||
| 621 | => .arg, | ||
| 622 | .pseudo_dbg_var_none, | ||
| 623 | .pseudo_dbg_var_i_s, | ||
| 624 | .pseudo_dbg_var_i_u, | ||
| 625 | .pseudo_dbg_var_i_64, | ||
| 626 | .pseudo_dbg_var_ro, | ||
| 627 | .pseudo_dbg_var_fa, | ||
| 628 | .pseudo_dbg_var_m, | ||
| 629 | .pseudo_dbg_var_val, | ||
| 630 | => .local_var, | ||
| 631 | }, | ||
| 632 | local.name.toSlice(&emit.lower.mir), | ||
| 633 | .fromInterned(local.type), | ||
| 634 | loc, | ||
| 635 | ); | ||
| 636 | }, | ||
| 637 | .none => local_index += 1, | ||
| 638 | }, | ||
| 639 | .pseudo_dbg_arg_val, .pseudo_dbg_var_val => switch (emit.debug_output) { | ||
| 640 | .dwarf => |dwarf| { | ||
| 641 | const local = &emit.lower.mir.locals[local_index]; | ||
| 642 | local_index += 1; | ||
| 643 | try dwarf.genLocalConstDebugInfo( | ||
| 644 | switch (mir_inst.ops) { | ||
| 645 | else => unreachable, | ||
| 646 | .pseudo_dbg_arg_val => .comptime_arg, | ||
| 647 | .pseudo_dbg_var_val => .local_const, | ||
| 648 | }, | ||
| 649 | local.name.toSlice(&emit.lower.mir), | ||
| 650 | .fromInterned(mir_inst.data.ip_index), | ||
| 651 | ); | ||
| 652 | }, | ||
| 653 | .none => local_index += 1, | ||
| 654 | }, | 653 | }, |
| 655 | .pseudo_dbg_var_args_none => switch (emit.debug_output) { | 654 | .eh_frame, .none => local_index += 1, |
| 656 | .dwarf => |dwarf| try dwarf.genVarArgsDebugInfo(), | 655 | }, |
| 657 | .none => {}, | 656 | .pseudo_dbg_arg_val, .pseudo_dbg_var_val => switch (emit.debug_output) { |
| 657 | inline .dwarf, .dwarf2 => |dwarf| { | ||
| 658 | const local = &emit.lower.mir.locals[local_index]; | ||
| 659 | local_index += 1; | ||
| 660 | try dwarf.genLocalConstDebugInfo( | ||
| 661 | switch (mir_inst.ops) { | ||
| 662 | else => unreachable, | ||
| 663 | .pseudo_dbg_arg_val => .comptime_arg, | ||
| 664 | .pseudo_dbg_var_val => .local_const, | ||
| 665 | }, | ||
| 666 | local.name.toSlice(&emit.lower.mir), | ||
| 667 | .fromInterned(mir_inst.data.ip_index), | ||
| 668 | ); | ||
| 658 | }, | 669 | }, |
| 659 | .pseudo_dead_none => {}, | 670 | .eh_frame, .none => local_index += 1, |
| 671 | }, | ||
| 672 | .pseudo_dbg_var_args_none => switch (emit.debug_output) { | ||
| 673 | inline .dwarf, .dwarf2 => |dwarf| try dwarf.genVarArgsDebugInfo(), | ||
| 674 | .eh_frame, .none => {}, | ||
| 660 | }, | 675 | }, |
| 676 | .pseudo_dead_none => {}, | ||
| 661 | } | 677 | } |
| 662 | } | 678 | } |
| 663 | } | 679 | } |
| ... | @@ -971,22 +987,23 @@ const TableReloc = struct { | ... | @@ -971,22 +987,23 @@ const TableReloc = struct { |
| 971 | const Loc = struct { | 987 | const Loc = struct { |
| 972 | line: u32, | 988 | line: u32, |
| 973 | column: u32, | 989 | column: u32, |
| 974 | is_stmt: bool, | 990 | is_stmt: ?bool = null, |
| 991 | end: bool = false, | ||
| 975 | }; | 992 | }; |
| 976 | 993 | ||
| 977 | fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void { | 994 | fn dbgAdvanceLineAndPc(emit: *Emit, loc: Loc) Error!void { |
| 978 | const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line); | ||
| 979 | const delta_pc: usize = emit.w.end - emit.prev_di_pc; | ||
| 980 | log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line }); | ||
| 981 | switch (emit.debug_output) { | 995 | switch (emit.debug_output) { |
| 982 | .dwarf => |dwarf| { | 996 | inline .dwarf, .dwarf2 => |dwarf| { |
| 983 | if (loc.is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt(); | 997 | const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line); |
| 998 | const delta_pc: usize = emit.w.end - emit.prev_di_pc; | ||
| 999 | log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line }); | ||
| 1000 | if (loc.is_stmt) |is_stmt| if (is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt(); | ||
| 984 | if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column); | 1001 | if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column); |
| 985 | try dwarf.advancePCAndLine(delta_line, delta_pc); | 1002 | try dwarf.advanceLineAndPc(delta_line, delta_pc, loc.end); |
| 986 | emit.prev_di_loc = loc; | 1003 | emit.prev_di_loc = loc; |
| 987 | emit.prev_di_pc = emit.w.end; | 1004 | emit.prev_di_pc = emit.w.end; |
| 988 | }, | 1005 | }, |
| 989 | .none => {}, | 1006 | .eh_frame, .none => {}, |
| 990 | } | 1007 | } |
| 991 | } | 1008 | } |
| 992 | 1009 |
src/codegen/x86_64/Lower.zig+2-1| ... | @@ -314,11 +314,12 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -314,11 +314,12 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 314 | .pseudo_dbg_prologue_end_none, | 314 | .pseudo_dbg_prologue_end_none, |
| 315 | .pseudo_dbg_line_stmt_line_column, | 315 | .pseudo_dbg_line_stmt_line_column, |
| 316 | .pseudo_dbg_line_line_column, | 316 | .pseudo_dbg_line_line_column, |
| 317 | .pseudo_dbg_epilogue_begin_none, | 317 | .pseudo_dbg_epilogue_begin_line_column, |
| 318 | .pseudo_dbg_enter_block_none, | 318 | .pseudo_dbg_enter_block_none, |
| 319 | .pseudo_dbg_leave_block_none, | 319 | .pseudo_dbg_leave_block_none, |
| 320 | .pseudo_dbg_enter_inline_func, | 320 | .pseudo_dbg_enter_inline_func, |
| 321 | .pseudo_dbg_leave_inline_func, | 321 | .pseudo_dbg_leave_inline_func, |
| 322 | .pseudo_dbg_end_none, | ||
| 322 | .pseudo_dbg_arg_none, | 323 | .pseudo_dbg_arg_none, |
| 323 | .pseudo_dbg_arg_i_s, | 324 | .pseudo_dbg_arg_i_s, |
| 324 | .pseudo_dbg_arg_i_u, | 325 | .pseudo_dbg_arg_i_u, |
src/codegen/x86_64/Mir.zig+27-21| ... | @@ -1519,30 +1519,33 @@ pub const Inst = struct { | ... | @@ -1519,30 +1519,33 @@ pub const Inst = struct { |
| 1519 | /// Uses `bytes` payload. | 1519 | /// Uses `bytes` payload. |
| 1520 | pseudo_cfi_escape_bytes, | 1520 | pseudo_cfi_escape_bytes, |
| 1521 | 1521 | ||
| 1522 | /// End of prologue | 1522 | /// End of prologue. |
| 1523 | /// Uses `none` payload. | 1523 | /// Uses `none` payload. |
| 1524 | pseudo_dbg_prologue_end_none, | 1524 | pseudo_dbg_prologue_end_none, |
| 1525 | /// Update debug line with is_stmt register set | 1525 | /// Update debug line with is_stmt register set. |
| 1526 | /// Uses `line_column` payload. | 1526 | /// Uses `line_column` payload. |
| 1527 | pseudo_dbg_line_stmt_line_column, | 1527 | pseudo_dbg_line_stmt_line_column, |
| 1528 | /// Update debug line with is_stmt register clear | 1528 | /// Update debug line with is_stmt register clear. |
| 1529 | /// Uses `line_column` payload. | 1529 | /// Uses `line_column` payload. |
| 1530 | pseudo_dbg_line_line_column, | 1530 | pseudo_dbg_line_line_column, |
| 1531 | /// Start of epilogue | 1531 | /// Start of epilogue. |
| 1532 | /// Uses `none` payload. | 1532 | /// Uses `line_column` payload. |
| 1533 | pseudo_dbg_epilogue_begin_none, | 1533 | pseudo_dbg_epilogue_begin_line_column, |
| 1534 | /// Start of lexical block | 1534 | /// Start of lexical block. |
| 1535 | /// Uses `none` payload. | 1535 | /// Uses `none` payload. |
| 1536 | pseudo_dbg_enter_block_none, | 1536 | pseudo_dbg_enter_block_none, |
| 1537 | /// End of lexical block | 1537 | /// End of lexical block. |
| 1538 | /// Uses `none` payload. | 1538 | /// Uses `none` payload. |
| 1539 | pseudo_dbg_leave_block_none, | 1539 | pseudo_dbg_leave_block_none, |
| 1540 | /// Start of inline function | 1540 | /// Start of inline function. |
| 1541 | /// Uses `ip_index` payload. | 1541 | /// Uses `ip_index` payload. |
| 1542 | pseudo_dbg_enter_inline_func, | 1542 | pseudo_dbg_enter_inline_func, |
| 1543 | /// End of inline function | 1543 | /// End of inline function. |
| 1544 | /// Uses `ip_index` payload. | 1544 | /// Uses `ip_index` payload. |
| 1545 | pseudo_dbg_leave_inline_func, | 1545 | pseudo_dbg_leave_inline_func, |
| 1546 | /// End of function. | ||
| 1547 | /// Uses `none` payload. | ||
| 1548 | pseudo_dbg_end_none, | ||
| 1546 | /// Local argument. | 1549 | /// Local argument. |
| 1547 | /// Uses `none` payload. | 1550 | /// Uses `none` payload. |
| 1548 | pseudo_dbg_arg_none, | 1551 | pseudo_dbg_arg_none, |
| ... | @@ -1978,7 +1981,7 @@ pub fn emit( | ... | @@ -1978,7 +1981,7 @@ pub fn emit( |
| 1978 | atom_id: link.File.AtomId, | 1981 | atom_id: link.File.AtomId, |
| 1979 | w: *std.Io.Writer, | 1982 | w: *std.Io.Writer, |
| 1980 | debug_output: link.File.DebugInfoOutput, | 1983 | debug_output: link.File.DebugInfoOutput, |
| 1981 | ) codegen.Error!void { | 1984 | ) link.EmitError!void { |
| 1982 | const zcu = pt.zcu; | 1985 | const zcu = pt.zcu; |
| 1983 | const comp = zcu.comp; | 1986 | const comp = zcu.comp; |
| 1984 | const gpa = comp.gpa; | 1987 | const gpa = comp.gpa; |
| ... | @@ -1986,7 +1989,7 @@ pub fn emit( | ... | @@ -1986,7 +1989,7 @@ pub fn emit( |
| 1986 | const fn_info = zcu.typeToFunc(.fromInterned(func.ty)).?; | 1989 | const fn_info = zcu.typeToFunc(.fromInterned(func.ty)).?; |
| 1987 | const nav = func.owner_nav; | 1990 | const nav = func.owner_nav; |
| 1988 | const mod = zcu.navFileScope(nav).mod.?; | 1991 | const mod = zcu.navFileScope(nav).mod.?; |
| 1989 | var e: Emit = .{ | 1992 | var em: Emit = .{ |
| 1990 | .lower = .{ | 1993 | .lower = .{ |
| 1991 | .target = &mod.resolved_target.result, | 1994 | .target = &mod.resolved_target.result, |
| 1992 | .allocator = gpa, | 1995 | .allocator = gpa, |
| ... | @@ -2006,7 +2009,8 @@ pub fn emit( | ... | @@ -2006,7 +2009,8 @@ pub fn emit( |
| 2006 | .column = func.lbrace_column, | 2009 | .column = func.lbrace_column, |
| 2007 | .is_stmt = switch (debug_output) { | 2010 | .is_stmt = switch (debug_output) { |
| 2008 | .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt, | 2011 | .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt, |
| 2009 | .none => undefined, | 2012 | .dwarf2 => |dwarf| dwarf.wip_nav.dwarf.debug_line.header.default_is_stmt, |
| 2013 | .eh_frame, .none => undefined, | ||
| 2010 | }, | 2014 | }, |
| 2011 | }, | 2015 | }, |
| 2012 | .prev_di_pc = 0, | 2016 | .prev_di_pc = 0, |
| ... | @@ -2015,11 +2019,12 @@ pub fn emit( | ... | @@ -2015,11 +2019,12 @@ pub fn emit( |
| 2015 | .relocs = .empty, | 2019 | .relocs = .empty, |
| 2016 | .table_relocs = .empty, | 2020 | .table_relocs = .empty, |
| 2017 | }; | 2021 | }; |
| 2018 | defer e.deinit(); | 2022 | defer em.deinit(); |
| 2019 | e.emitMir() catch |err| switch (err) { | 2023 | em.emitMir() catch |err| switch (err) { |
| 2020 | error.LowerFail, error.EmitFail => return zcu.codegenFailMsg(nav, e.lower.err_msg.?), | 2024 | error.LowerFail, error.EmitFail => return zcu.codegenFailMsg(nav, em.lower.err_msg.?), |
| 2021 | error.InvalidInstruction, error.CannotEncode => return zcu.codegenFail(nav, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}), | 2025 | error.InvalidInstruction, error.CannotEncode => return zcu.codegenFail(nav, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}), |
| 2022 | else => return zcu.codegenFail(nav, "emit MIR failed: {s}", .{@errorName(err)}), | 2026 | else => return zcu.codegenFail(nav, "emit MIR failed: {s}", .{@errorName(err)}), |
| 2027 | error.AlreadyReported, error.Canceled, error.WriteFailed => |e| return e, | ||
| 2023 | }; | 2028 | }; |
| 2024 | } | 2029 | } |
| 2025 | 2030 | ||
| ... | @@ -2031,12 +2036,12 @@ pub fn emitLazy( | ... | @@ -2031,12 +2036,12 @@ pub fn emitLazy( |
| 2031 | atom_id: link.File.AtomId, | 2036 | atom_id: link.File.AtomId, |
| 2032 | w: *std.Io.Writer, | 2037 | w: *std.Io.Writer, |
| 2033 | debug_output: link.File.DebugInfoOutput, | 2038 | debug_output: link.File.DebugInfoOutput, |
| 2034 | ) codegen.Error!void { | 2039 | ) link.EmitError!void { |
| 2035 | const zcu = pt.zcu; | 2040 | const zcu = pt.zcu; |
| 2036 | const comp = zcu.comp; | 2041 | const comp = zcu.comp; |
| 2037 | const gpa = comp.gpa; | 2042 | const gpa = comp.gpa; |
| 2038 | const mod = comp.root_mod; | 2043 | const mod = comp.root_mod; |
| 2039 | var e: Emit = .{ | 2044 | var em: Emit = .{ |
| 2040 | .lower = .{ | 2045 | .lower = .{ |
| 2041 | .target = &mod.resolved_target.result, | 2046 | .target = &mod.resolved_target.result, |
| 2042 | .allocator = gpa, | 2047 | .allocator = gpa, |
| ... | @@ -2058,11 +2063,12 @@ pub fn emitLazy( | ... | @@ -2058,11 +2063,12 @@ pub fn emitLazy( |
| 2058 | .relocs = .empty, | 2063 | .relocs = .empty, |
| 2059 | .table_relocs = .empty, | 2064 | .table_relocs = .empty, |
| 2060 | }; | 2065 | }; |
| 2061 | defer e.deinit(); | 2066 | defer em.deinit(); |
| 2062 | e.emitMir() catch |err| switch (err) { | 2067 | em.emitMir() catch |err| switch (err) { |
| 2063 | error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.ty, e.lower.err_msg.?), | 2068 | error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.ty, em.lower.err_msg.?), |
| 2064 | error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}), | 2069 | error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}), |
| 2065 | else => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s}", .{@errorName(err)}), | 2070 | else => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s}", .{@errorName(err)}), |
| 2071 | error.AlreadyReported, error.Canceled, error.WriteFailed => |e| return e, | ||
| 2066 | }; | 2072 | }; |
| 2067 | } | 2073 | } |
| 2068 | 2074 |
src/crash_report.zig-1| ... | @@ -215,7 +215,6 @@ const Sema = @import("Sema.zig"); | ... | @@ -215,7 +215,6 @@ const Sema = @import("Sema.zig"); |
| 215 | const Zcu = @import("Zcu.zig"); | 215 | const Zcu = @import("Zcu.zig"); |
| 216 | const link = @import("link.zig"); | 216 | const link = @import("link.zig"); |
| 217 | const InternPool = @import("InternPool.zig"); | 217 | const InternPool = @import("InternPool.zig"); |
| 218 | const dev = @import("dev.zig"); | ||
| 219 | const print_zir = @import("print_zir.zig"); | 218 | const print_zir = @import("print_zir.zig"); |
| 220 | 219 | ||
| 221 | const build_options = @import("build_options"); | 220 | const build_options = @import("build_options"); |
src/dev.zig-1| ... | @@ -227,7 +227,6 @@ pub const Env = enum { | ... | @@ -227,7 +227,6 @@ pub const Env = enum { |
| 227 | else => Env.sema.supports(feature), | 227 | else => Env.sema.supports(feature), |
| 228 | }, | 228 | }, |
| 229 | .@"x86_64-windows" => switch (feature) { | 229 | .@"x86_64-windows" => switch (feature) { |
| 230 | .build_command, | ||
| 231 | .stdio_listen, | 230 | .stdio_listen, |
| 232 | .incremental, | 231 | .incremental, |
| 233 | .legalize, | 232 | .legalize, |
src/link.zig+109-48| ... | @@ -26,9 +26,10 @@ const target_util = @import("target.zig"); | ... | @@ -26,9 +26,10 @@ const target_util = @import("target.zig"); |
| 26 | const codegen = @import("codegen.zig"); | 26 | const codegen = @import("codegen.zig"); |
| 27 | const crash_report = @import("crash_report.zig"); | 27 | const crash_report = @import("crash_report.zig"); |
| 28 | 28 | ||
| 29 | pub const ConstPool = @import("link/ConstPool.zig"); | ||
| 29 | pub const LdScript = @import("link/LdScript.zig"); | 30 | pub const LdScript = @import("link/LdScript.zig"); |
| 31 | pub const MappedFile = @import("link/MappedFile.zig"); | ||
| 30 | pub const Queue = @import("link/Queue.zig"); | 32 | pub const Queue = @import("link/Queue.zig"); |
| 31 | pub const ConstPool = @import("link/ConstPool.zig"); | ||
| 32 | 33 | ||
| 33 | pub const aarch64 = @import("link/aarch64.zig"); | 34 | pub const aarch64 = @import("link/aarch64.zig"); |
| 34 | pub const loongarch = @import("link/loongarch.zig"); | 35 | pub const loongarch = @import("link/loongarch.zig"); |
| ... | @@ -38,6 +39,7 @@ pub const Error = Allocator.Error || Io.Cancelable || error{ | ... | @@ -38,6 +39,7 @@ pub const Error = Allocator.Error || Io.Cancelable || error{ |
| 38 | /// instance in `Compilation.link_diags`. | 39 | /// instance in `Compilation.link_diags`. |
| 39 | AlreadyReported, | 40 | AlreadyReported, |
| 40 | }; | 41 | }; |
| 42 | pub const EmitError = Error || Io.Writer.Error; | ||
| 41 | 43 | ||
| 42 | pub const Diags = struct { | 44 | pub const Diags = struct { |
| 43 | /// Stored here so that function definitions can distinguish between | 45 | /// Stored here so that function definitions can distinguish between |
| ... | @@ -95,7 +97,6 @@ pub const Diags = struct { | ... | @@ -95,7 +97,6 @@ pub const Diags = struct { |
| 95 | return switch (msg.source_location) { | 97 | return switch (msg.source_location) { |
| 96 | .none => try bundle.addString(msg.msg), | 98 | .none => try bundle.addString(msg.msg), |
| 97 | .wasm => |sl| { | 99 | .wasm => |sl| { |
| 98 | dev.check(.wasm_linker); | ||
| 99 | const wasm = base.?.cast(.wasm).?; | 100 | const wasm = base.?.cast(.wasm).?; |
| 100 | return sl.string(msg.msg, bundle, wasm); | 101 | return sl.string(msg.msg, bundle, wasm); |
| 101 | }, | 102 | }, |
| ... | @@ -394,8 +395,6 @@ pub const Diags = struct { | ... | @@ -394,8 +395,6 @@ pub const Diags = struct { |
| 394 | } | 395 | } |
| 395 | }; | 396 | }; |
| 396 | 397 | ||
| 397 | pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version; | ||
| 398 | |||
| 399 | pub const File = struct { | 398 | pub const File = struct { |
| 400 | tag: Tag, | 399 | tag: Tag, |
| 401 | 400 | ||
| ... | @@ -653,7 +652,6 @@ pub const File = struct { | ... | @@ -653,7 +652,6 @@ pub const File = struct { |
| 653 | base.file = try emit.root_dir.handle.openFile(io, emit.sub_path, .{ .mode = .read_write }); | 652 | base.file = try emit.root_dir.handle.openFile(io, emit.sub_path, .{ .mode = .read_write }); |
| 654 | }, | 653 | }, |
| 655 | .elf2, .coff2 => if (base.file == null) { | 654 | .elf2, .coff2 => if (base.file == null) { |
| 656 | dev.checkAny(&.{ .elf2_linker, .coff2_linker }); | ||
| 657 | const mf = if (base.cast(.elf2)) |elf| | 655 | const mf = if (base.cast(.elf2)) |elf| |
| 658 | &elf.mf | 656 | &elf.mf |
| 659 | else if (base.cast(.coff2)) |coff| | 657 | else if (base.cast(.coff2)) |coff| |
| ... | @@ -757,6 +755,8 @@ pub const File = struct { | ... | @@ -757,6 +755,8 @@ pub const File = struct { |
| 757 | 755 | ||
| 758 | pub const DebugInfoOutput = union(enum) { | 756 | pub const DebugInfoOutput = union(enum) { |
| 759 | dwarf: *Dwarf.WipNav, | 757 | dwarf: *Dwarf.WipNav, |
| 758 | eh_frame: *Dwarf2.WipNav, | ||
| 759 | dwarf2: *Dwarf2.WipNav.Debug, | ||
| 760 | none, | 760 | none, |
| 761 | }; | 761 | }; |
| 762 | pub const UpdateDebugInfoError = Dwarf.UpdateError; | 762 | pub const UpdateDebugInfoError = Dwarf.UpdateError; |
| ... | @@ -791,9 +791,31 @@ pub const File = struct { | ... | @@ -791,9 +791,31 @@ pub const File = struct { |
| 791 | } | 791 | } |
| 792 | } | 792 | } |
| 793 | 793 | ||
| 794 | /// When there is a ZCU, this is called exactly once per update, to indicate that all per-file | ||
| 795 | /// state (e.g. `Zcu.alive_files`) has been populated by the frontend, so can now be safely | ||
| 796 | /// accessed by the linker. | ||
| 797 | /// | ||
| 798 | /// This call occurs before any call to any of these functions: | ||
| 799 | /// * `updateNav` | ||
| 800 | /// * `updateFunc` | ||
| 801 | /// * `updateContainerType` | ||
| 802 | /// * `updateLineNumber` | ||
| 803 | /// | ||
| 804 | /// Asserts that the ZCU is not using the LLVM backend. | ||
| 805 | fn zcuFilesReady(base: *File, zcu: *Zcu) Error!void { | ||
| 806 | assert(zcu.llvm_object == null); | ||
| 807 | switch (base.tag) { | ||
| 808 | else => {}, | ||
| 809 | inline .elf2 => |tag| { | ||
| 810 | dev.check(tag.devFeature()); | ||
| 811 | return @as(*tag.Type(), @fieldParentPtr("base", base)).zcuFilesReady(zcu); | ||
| 812 | }, | ||
| 813 | } | ||
| 814 | } | ||
| 815 | |||
| 794 | /// Asserts that the ZCU is not using the LLVM backend. | 816 | /// Asserts that the ZCU is not using the LLVM backend. |
| 795 | fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void { | 817 | fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void { |
| 796 | assert(base.comp.zcu.?.llvm_object == null); | 818 | assert(pt.zcu.llvm_object == null); |
| 797 | const nav = pt.zcu.intern_pool.getNav(nav_index); | 819 | const nav = pt.zcu.intern_pool.getNav(nav_index); |
| 798 | assert(nav.resolved.?.value != .none); | 820 | assert(nav.resolved.?.value != .none); |
| 799 | 821 | ||
| ... | @@ -809,30 +831,17 @@ pub const File = struct { | ... | @@ -809,30 +831,17 @@ pub const File = struct { |
| 809 | 831 | ||
| 810 | /// Never called when LLVM is codegenning the ZCU. | 832 | /// Never called when LLVM is codegenning the ZCU. |
| 811 | fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Error!void { | 833 | fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Error!void { |
| 812 | assert(base.comp.zcu.?.llvm_object == null); | 834 | assert(pt.zcu.llvm_object == null); |
| 813 | switch (base.tag) { | 835 | switch (base.tag) { |
| 814 | .lld => unreachable, | 836 | .lld => unreachable, |
| 815 | else => {}, | 837 | else => {}, |
| 816 | inline .elf, .c => |tag| { | 838 | inline .elf, .elf2, .c, .coff2 => |tag| { |
| 817 | dev.check(tag.devFeature()); | 839 | dev.check(tag.devFeature()); |
| 818 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty, success); | 840 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty, success); |
| 819 | }, | 841 | }, |
| 820 | } | 842 | } |
| 821 | } | 843 | } |
| 822 | 844 | ||
| 823 | /// Never called when LLVM is codegenning the ZCU. | ||
| 824 | fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) Error!void { | ||
| 825 | assert(base.comp.zcu.?.llvm_object == null); | ||
| 826 | switch (base.tag) { | ||
| 827 | .lld => unreachable, | ||
| 828 | else => {}, | ||
| 829 | inline .elf => |tag| { | ||
| 830 | dev.check(tag.devFeature()); | ||
| 831 | return @as(*tag.Type(), @fieldParentPtr("base", base)).clearContainerType(pt, ty); | ||
| 832 | }, | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | /// The active tag of `mir` is determined by the backend used for the module this function is in. | 845 | /// The active tag of `mir` is determined by the backend used for the module this function is in. |
| 837 | /// Never called when LLVM is codegenning the ZCU. | 846 | /// Never called when LLVM is codegenning the ZCU. |
| 838 | fn updateFunc( | 847 | fn updateFunc( |
| ... | @@ -844,7 +853,7 @@ pub const File = struct { | ... | @@ -844,7 +853,7 @@ pub const File = struct { |
| 844 | /// take ownership of an embedded slice and replace it with `&.{}` in `mir`. | 853 | /// take ownership of an embedded slice and replace it with `&.{}` in `mir`. |
| 845 | mir: *codegen.AnyMir, | 854 | mir: *codegen.AnyMir, |
| 846 | ) Error!void { | 855 | ) Error!void { |
| 847 | assert(base.comp.zcu.?.llvm_object == null); | 856 | assert(pt.zcu.llvm_object == null); |
| 848 | switch (base.tag) { | 857 | switch (base.tag) { |
| 849 | .lld => unreachable, | 858 | .lld => unreachable, |
| 850 | .plan9 => unreachable, | 859 | .plan9 => unreachable, |
| ... | @@ -858,23 +867,49 @@ pub const File = struct { | ... | @@ -858,23 +867,49 @@ pub const File = struct { |
| 858 | /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because | 867 | /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because |
| 859 | /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`. | 868 | /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`. |
| 860 | /// Never called when LLVM is codegenning the ZCU. | 869 | /// Never called when LLVM is codegenning the ZCU. |
| 861 | fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) Error!void { | 870 | fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index, line: u32) Error!void { |
| 862 | assert(base.comp.zcu.?.llvm_object == null); | 871 | assert(pt.zcu.llvm_object == null); |
| 863 | { | 872 | { |
| 864 | const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?; | 873 | const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?; |
| 865 | const file = pt.zcu.fileByIndex(ti.file); | 874 | const file = pt.zcu.fileByIndex(ti.file); |
| 866 | const inst = file.zir.?.instructions.get(@backingInt(ti.inst)); | 875 | const inst = file.zir.?.instructions.get(@backingInt(ti.inst)); |
| 867 | assert(inst.tag == .declaration); | 876 | switch (inst.tag) { |
| 877 | .declaration => {}, | ||
| 878 | .extended => switch (inst.data.extended.opcode) { | ||
| 879 | .struct_decl, | ||
| 880 | .union_decl, | ||
| 881 | .enum_decl, | ||
| 882 | .opaque_decl, | ||
| 883 | .reify_enum, | ||
| 884 | .reify_struct, | ||
| 885 | .reify_union, | ||
| 886 | => {}, | ||
| 887 | else => unreachable, | ||
| 888 | }, | ||
| 889 | else => unreachable, | ||
| 890 | } | ||
| 868 | } | 891 | } |
| 869 | |||
| 870 | switch (base.tag) { | 892 | switch (base.tag) { |
| 871 | .lld => unreachable, | 893 | .lld => unreachable, |
| 872 | .spirv => {}, | ||
| 873 | .plan9 => unreachable, | 894 | .plan9 => unreachable, |
| 874 | .elf2, .coff2 => {}, | 895 | .spirv => {}, |
| 896 | .coff2 => {}, | ||
| 875 | inline else => |tag| { | 897 | inline else => |tag| { |
| 876 | dev.check(tag.devFeature()); | 898 | dev.check(tag.devFeature()); |
| 877 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id); | 899 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id, line); |
| 900 | }, | ||
| 901 | } | ||
| 902 | } | ||
| 903 | |||
| 904 | fn lostTracking(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) Error!void { | ||
| 905 | assert(base.comp.zcu.?.llvm_object == null); | ||
| 906 | switch (base.tag) { | ||
| 907 | .lld => unreachable, | ||
| 908 | .plan9 => unreachable, | ||
| 909 | else => {}, | ||
| 910 | inline .elf2 => |tag| { | ||
| 911 | dev.check(tag.devFeature()); | ||
| 912 | return @as(*tag.Type(), @fieldParentPtr("base", base)).lostTracking(pt, ti_id); | ||
| 878 | }, | 913 | }, |
| 879 | } | 914 | } |
| 880 | } | 915 | } |
| ... | @@ -984,7 +1019,7 @@ pub const File = struct { | ... | @@ -984,7 +1019,7 @@ pub const File = struct { |
| 984 | pt: Zcu.PerThread, | 1019 | pt: Zcu.PerThread, |
| 985 | export_indices: []const Zcu.Export.Index, | 1020 | export_indices: []const Zcu.Export.Index, |
| 986 | ) Error!void { | 1021 | ) Error!void { |
| 987 | assert(base.comp.zcu.?.llvm_object == null); | 1022 | assert(pt.zcu.llvm_object == null); |
| 988 | 1023 | ||
| 989 | crash_report.LinkerOp.start(base, pt.tid); | 1024 | crash_report.LinkerOp.start(base, pt.tid); |
| 990 | defer crash_report.LinkerOp.stop(base, pt.tid); | 1025 | defer crash_report.LinkerOp.stop(base, pt.tid); |
| ... | @@ -1019,7 +1054,7 @@ pub const File = struct { | ... | @@ -1019,7 +1054,7 @@ pub const File = struct { |
| 1019 | /// the block/atom. | 1054 | /// the block/atom. |
| 1020 | /// Never called when LLVM is codegenning the ZCU. | 1055 | /// Never called when LLVM is codegenning the ZCU. |
| 1021 | pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 { | 1056 | pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 { |
| 1022 | assert(base.comp.zcu.?.llvm_object == null); | 1057 | assert(pt.zcu.llvm_object == null); |
| 1023 | 1058 | ||
| 1024 | switch (base.tag) { | 1059 | switch (base.tag) { |
| 1025 | .lld => unreachable, | 1060 | .lld => unreachable, |
| ... | @@ -1042,7 +1077,7 @@ pub const File = struct { | ... | @@ -1042,7 +1077,7 @@ pub const File = struct { |
| 1042 | decl_val: InternPool.Index, | 1077 | decl_val: InternPool.Index, |
| 1043 | decl_align: InternPool.Alignment, | 1078 | decl_align: InternPool.Alignment, |
| 1044 | ) Error!SymbolId { | 1079 | ) Error!SymbolId { |
| 1045 | assert(base.comp.zcu.?.llvm_object == null); | 1080 | assert(pt.zcu.llvm_object == null); |
| 1046 | 1081 | ||
| 1047 | switch (base.tag) { | 1082 | switch (base.tag) { |
| 1048 | .lld => unreachable, | 1083 | .lld => unreachable, |
| ... | @@ -1308,7 +1343,7 @@ pub const File = struct { | ... | @@ -1308,7 +1343,7 @@ pub const File = struct { |
| 1308 | }; | 1343 | }; |
| 1309 | } | 1344 | } |
| 1310 | 1345 | ||
| 1311 | pub fn devFeature(tag: Tag) dev.Feature { | 1346 | fn devFeature(tag: Tag) dev.Feature { |
| 1312 | return @field(dev.Feature, @tagName(tag) ++ "_linker"); | 1347 | return @field(dev.Feature, @tagName(tag) ++ "_linker"); |
| 1313 | } | 1348 | } |
| 1314 | }; | 1349 | }; |
| ... | @@ -1391,6 +1426,7 @@ pub const File = struct { | ... | @@ -1391,6 +1426,7 @@ pub const File = struct { |
| 1391 | pub const SpirV = @import("link/SpirV.zig"); | 1426 | pub const SpirV = @import("link/SpirV.zig"); |
| 1392 | pub const Wasm = @import("link/Wasm.zig"); | 1427 | pub const Wasm = @import("link/Wasm.zig"); |
| 1393 | pub const Dwarf = @import("link/Dwarf.zig"); | 1428 | pub const Dwarf = @import("link/Dwarf.zig"); |
| 1429 | pub const Dwarf2 = @import("link/Dwarf2.zig"); | ||
| 1394 | }; | 1430 | }; |
| 1395 | 1431 | ||
| 1396 | pub const PrelinkTask = union(enum) { | 1432 | pub const PrelinkTask = union(enum) { |
| ... | @@ -1413,6 +1449,9 @@ pub const PrelinkTask = union(enum) { | ... | @@ -1413,6 +1449,9 @@ pub const PrelinkTask = union(enum) { |
| 1413 | load_dso: Path, | 1449 | load_dso: Path, |
| 1414 | }; | 1450 | }; |
| 1415 | pub const ZcuTask = union(enum) { | 1451 | pub const ZcuTask = union(enum) { |
| 1452 | /// Sent once per update, as the very first `ZcuTask` in the update. Indicates that all per-file | ||
| 1453 | /// state (e.g. `Zcu.alive_files`) is populated so can now be safely accessed by the linker. | ||
| 1454 | files_ready, | ||
| 1416 | /// Write the constant value for a Decl to the output file. | 1455 | /// Write the constant value for a Decl to the output file. |
| 1417 | link_nav: InternPool.Nav.Index, | 1456 | link_nav: InternPool.Nav.Index, |
| 1418 | /// Write the machine code for a function to the output file. | 1457 | /// Write the machine code for a function to the output file. |
| ... | @@ -1424,7 +1463,11 @@ pub const ZcuTask = union(enum) { | ... | @@ -1424,7 +1463,11 @@ pub const ZcuTask = union(enum) { |
| 1424 | ty: InternPool.Index, | 1463 | ty: InternPool.Index, |
| 1425 | success: bool, | 1464 | success: bool, |
| 1426 | }, | 1465 | }, |
| 1427 | debug_update_line_number: InternPool.TrackedInst.Index, | 1466 | debug_update_line_number: struct { |
| 1467 | inst: InternPool.TrackedInst.Index, | ||
| 1468 | line: u32, | ||
| 1469 | }, | ||
| 1470 | lost_tracking: InternPool.TrackedInst.Index, | ||
| 1428 | }; | 1471 | }; |
| 1429 | 1472 | ||
| 1430 | pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | 1473 | pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| ... | @@ -1616,6 +1659,16 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void | ... | @@ -1616,6 +1659,16 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void |
| 1616 | var timer = comp.startTimer(); | 1659 | var timer = comp.startTimer(); |
| 1617 | 1660 | ||
| 1618 | const maybe_nav: ?InternPool.Nav.Index = switch (task) { | 1661 | const maybe_nav: ?InternPool.Nav.Index = switch (task) { |
| 1662 | .files_ready => { | ||
| 1663 | if (zcu.llvm_object != null) return; | ||
| 1664 | const lf = comp.bin_file orelse return; | ||
| 1665 | lf.zcuFilesReady(zcu) catch |err| switch (err) { | ||
| 1666 | error.Canceled => io.recancel(), | ||
| 1667 | error.AlreadyReported => return, | ||
| 1668 | error.OutOfMemory => return diags.setAllocFailure(), | ||
| 1669 | }; | ||
| 1670 | return; | ||
| 1671 | }, | ||
| 1619 | .link_nav => |nav_index| nav: { | 1672 | .link_nav => |nav_index| nav: { |
| 1620 | const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); | 1673 | const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); |
| 1621 | const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); | 1674 | const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); |
| ... | @@ -1661,32 +1714,40 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void | ... | @@ -1661,32 +1714,40 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void |
| 1661 | break :nav ip.indexToKey(func).func.owner_nav; | 1714 | break :nav ip.indexToKey(func).func.owner_nav; |
| 1662 | }, | 1715 | }, |
| 1663 | .debug_update_container_type => |container_update| nav: { | 1716 | .debug_update_container_type => |container_update| nav: { |
| 1664 | const name = Type.fromInterned(container_update.ty).containerTypeName(ip).toSlice(ip); | 1717 | const fqn = Type.fromInterned(container_update.ty).containerTypeName(ip).fqn.toSlice(ip); |
| 1665 | const ty_prog_node = comp.link_prog_node.start(name, 0); | 1718 | const ty_prog_node = comp.link_prog_node.start(fqn, 0); |
| 1666 | defer ty_prog_node.end(); | 1719 | defer ty_prog_node.end(); |
| 1667 | if (zcu.llvm_object) |llvm_object| { | 1720 | (if (zcu.llvm_object) |llvm_object| |
| 1668 | llvm_object.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) { | 1721 | llvm_object.updateContainerType(pt, container_update.ty, container_update.success) |
| 1669 | error.OutOfMemory => diags.setAllocFailure(), | 1722 | else if (comp.bin_file) |lf| |
| 1670 | }; | 1723 | lf.updateContainerType(pt, container_update.ty, container_update.success)) catch |err| switch (err) { |
| 1671 | } else { | 1724 | error.OutOfMemory => diags.setAllocFailure(), |
| 1725 | error.Canceled => io.recancel(), | ||
| 1726 | error.AlreadyReported => {}, | ||
| 1727 | }; | ||
| 1728 | break :nav null; | ||
| 1729 | }, | ||
| 1730 | .debug_update_line_number => |line_update| nav: { | ||
| 1731 | const nav_prog_node = comp.link_prog_node.start("Update line number", 0); | ||
| 1732 | defer nav_prog_node.end(); | ||
| 1733 | if (pt.zcu.llvm_object == null) { | ||
| 1672 | if (comp.bin_file) |lf| { | 1734 | if (comp.bin_file) |lf| { |
| 1673 | lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) { | 1735 | lf.updateLineNumber(pt, line_update.inst, line_update.line) catch |err| switch (err) { |
| 1674 | error.OutOfMemory => diags.setAllocFailure(), | 1736 | error.OutOfMemory => diags.setAllocFailure(), |
| 1675 | error.Canceled => io.recancel(), | 1737 | else => |e| log.err("update line number failed: {s}", .{@errorName(e)}), |
| 1676 | error.AlreadyReported => {}, | ||
| 1677 | }; | 1738 | }; |
| 1678 | } | 1739 | } |
| 1679 | } | 1740 | } |
| 1680 | break :nav null; | 1741 | break :nav null; |
| 1681 | }, | 1742 | }, |
| 1682 | .debug_update_line_number => |ti| nav: { | 1743 | .lost_tracking => |ti| nav: { |
| 1683 | const nav_prog_node = comp.link_prog_node.start("Update line number", 0); | 1744 | const nav_prog_node = comp.link_prog_node.start("Lost tracking", 0); |
| 1684 | defer nav_prog_node.end(); | 1745 | defer nav_prog_node.end(); |
| 1685 | if (pt.zcu.llvm_object == null) { | 1746 | if (pt.zcu.llvm_object == null) { |
| 1686 | if (comp.bin_file) |lf| { | 1747 | if (comp.bin_file) |lf| { |
| 1687 | lf.updateLineNumber(pt, ti) catch |err| switch (err) { | 1748 | lf.lostTracking(pt, ti) catch |err| switch (err) { |
| 1688 | error.OutOfMemory => diags.setAllocFailure(), | 1749 | error.OutOfMemory => diags.setAllocFailure(), |
| 1689 | else => |e| log.err("update line number failed: {s}", .{@errorName(e)}), | 1750 | else => |e| log.err("lost tracking failed: {s}", .{@errorName(e)}), |
| 1690 | }; | 1751 | }; |
| 1691 | } | 1752 | } |
| 1692 | } | 1753 | } |
src/link/C.zig+19-18| ... | @@ -209,7 +209,7 @@ pub fn addConst( | ... | @@ -209,7 +209,7 @@ pub fn addConst( |
| 209 | pt: Zcu.PerThread, | 209 | pt: Zcu.PerThread, |
| 210 | pool_index: link.ConstPool.Index, | 210 | pool_index: link.ConstPool.Index, |
| 211 | val: InternPool.Index, | 211 | val: InternPool.Index, |
| 212 | ) Allocator.Error!void { | 212 | ) link.Error!void { |
| 213 | const zcu = pt.zcu; | 213 | const zcu = pt.zcu; |
| 214 | const gpa = zcu.comp.gpa; | 214 | const gpa = zcu.comp.gpa; |
| 215 | assert(zcu.intern_pool.typeOf(val) == .type_type); | 215 | assert(zcu.intern_pool.typeOf(val) == .type_type); |
| ... | @@ -310,7 +310,7 @@ pub fn updateConst( | ... | @@ -310,7 +310,7 @@ pub fn updateConst( |
| 310 | pt: Zcu.PerThread, | 310 | pt: Zcu.PerThread, |
| 311 | index: link.ConstPool.Index, | 311 | index: link.ConstPool.Index, |
| 312 | val: InternPool.Index, | 312 | val: InternPool.Index, |
| 313 | ) Allocator.Error!void { | 313 | ) link.Error!void { |
| 314 | const zcu = pt.zcu; | 314 | const zcu = pt.zcu; |
| 315 | const gpa = zcu.comp.gpa; | 315 | const gpa = zcu.comp.gpa; |
| 316 | 316 | ||
| ... | @@ -498,7 +498,7 @@ pub fn updateFunc( | ... | @@ -498,7 +498,7 @@ pub fn updateFunc( |
| 498 | pt: Zcu.PerThread, | 498 | pt: Zcu.PerThread, |
| 499 | func_index: InternPool.Index, | 499 | func_index: InternPool.Index, |
| 500 | mir: *AnyMir, | 500 | mir: *AnyMir, |
| 501 | ) Allocator.Error!void { | 501 | ) link.Error!void { |
| 502 | const zcu = pt.zcu; | 502 | const zcu = pt.zcu; |
| 503 | const gpa = zcu.gpa; | 503 | const gpa = zcu.gpa; |
| 504 | const nav = zcu.funcInfo(func_index).owner_nav; | 504 | const nav = zcu.funcInfo(func_index).owner_nav; |
| ... | @@ -536,11 +536,7 @@ pub fn updateFunc( | ... | @@ -536,11 +536,7 @@ pub fn updateFunc( |
| 536 | try c.type_pool.flushPending(pt, .{ .c = c }); | 536 | try c.type_pool.flushPending(pt, .{ .c = c }); |
| 537 | } | 537 | } |
| 538 | 538 | ||
| 539 | pub fn updateNav( | 539 | pub fn updateNav(c: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void { |
| 540 | c: *C, | ||
| 541 | pt: Zcu.PerThread, | ||
| 542 | nav_index: InternPool.Nav.Index, | ||
| 543 | ) Allocator.Error!void { | ||
| 544 | const tracy = trace(@src()); | 540 | const tracy = trace(@src()); |
| 545 | defer tracy.end(); | 541 | defer tracy.end(); |
| 546 | 542 | ||
| ... | @@ -603,7 +599,8 @@ pub fn updateNav( | ... | @@ -603,7 +599,8 @@ pub fn updateNav( |
| 603 | const start = aw.written().len; | 599 | const start = aw.written().len; |
| 604 | codegen.genDeclFwd(&dg, &aw.writer) catch |err| switch (err) { | 600 | codegen.genDeclFwd(&dg, &aw.writer) catch |err| switch (err) { |
| 605 | error.AlreadyReported => return, | 601 | error.AlreadyReported => return, |
| 606 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | 602 | error.WriteFailed => return error.OutOfMemory, |
| 603 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 607 | }; | 604 | }; |
| 608 | break :fwd_decl .{ | 605 | break :fwd_decl .{ |
| 609 | .start = @intCast(start), | 606 | .start = @intCast(start), |
| ... | @@ -617,7 +614,8 @@ pub fn updateNav( | ... | @@ -617,7 +614,8 @@ pub fn updateNav( |
| 617 | const start = aw.written().len; | 614 | const start = aw.written().len; |
| 618 | codegen.genDecl(&dg, &aw.writer) catch |err| switch (err) { | 615 | codegen.genDecl(&dg, &aw.writer) catch |err| switch (err) { |
| 619 | error.AlreadyReported => return, | 616 | error.AlreadyReported => return, |
| 620 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | 617 | error.WriteFailed => return error.OutOfMemory, |
| 618 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 621 | }; | 619 | }; |
| 622 | break :code .{ | 620 | break :code .{ |
| 623 | .start = @intCast(start), | 621 | .start = @intCast(start), |
| ... | @@ -655,7 +653,7 @@ fn updateUav( | ... | @@ -655,7 +653,7 @@ fn updateUav( |
| 655 | pt: Zcu.PerThread, | 653 | pt: Zcu.PerThread, |
| 656 | val: Value, | 654 | val: Value, |
| 657 | rendered_decl: *RenderedDecl, | 655 | rendered_decl: *RenderedDecl, |
| 658 | ) Allocator.Error!void { | 656 | ) link.Error!void { |
| 659 | const tracy = trace(@src()); | 657 | const tracy = trace(@src()); |
| 660 | defer tracy.end(); | 658 | defer tracy.end(); |
| 661 | 659 | ||
| ... | @@ -691,7 +689,8 @@ fn updateUav( | ... | @@ -691,7 +689,8 @@ fn updateUav( |
| 691 | .init_val = val, | 689 | .init_val = val, |
| 692 | }) catch |err| switch (err) { | 690 | }) catch |err| switch (err) { |
| 693 | error.AlreadyReported => return, | 691 | error.AlreadyReported => return, |
| 694 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | 692 | error.WriteFailed => return error.OutOfMemory, |
| 693 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 695 | }; | 694 | }; |
| 696 | break :fwd_decl .{ | 695 | break :fwd_decl .{ |
| 697 | .start = @intCast(start), | 696 | .start = @intCast(start), |
| ... | @@ -710,7 +709,8 @@ fn updateUav( | ... | @@ -710,7 +709,8 @@ fn updateUav( |
| 710 | .init_val = val, | 709 | .init_val = val, |
| 711 | }) catch |err| switch (err) { | 710 | }) catch |err| switch (err) { |
| 712 | error.AlreadyReported => return, | 711 | error.AlreadyReported => return, |
| 713 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | 712 | error.WriteFailed => return error.OutOfMemory, |
| 713 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 714 | }; | 714 | }; |
| 715 | break :code .{ | 715 | break :code .{ |
| 716 | .start = @intCast(start), | 716 | .start = @intCast(start), |
| ... | @@ -721,12 +721,13 @@ fn updateUav( | ... | @@ -721,12 +721,13 @@ fn updateUav( |
| 721 | rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps); | 721 | rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps); |
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) error{}!void { | 724 | pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index, line: u32) error{}!void { |
| 725 | // The C backend does not currently emit "#line" directives. Even if it did, it would not be | 725 | // The C backend does not currently emit "#line" directives. Even if it did, it would not be |
| 726 | // capable of updating those line numbers without re-generating the entire declaration. | 726 | // capable of updating those line numbers without re-generating the entire declaration. |
| 727 | _ = c; | 727 | _ = c; |
| 728 | _ = pt; | 728 | _ = pt; |
| 729 | _ = ti_id; | 729 | _ = ti_id; |
| 730 | _ = line; | ||
| 730 | } | 731 | } |
| 731 | 732 | ||
| 732 | pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.Error!void { | 733 | pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.Error!void { |
| ... | @@ -1144,14 +1145,14 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog | ... | @@ -1144,14 +1145,14 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog |
| 1144 | for (need_never_tail_funcs.keys()) |fn_nav| { | 1145 | for (need_never_tail_funcs.keys()) |fn_nav| { |
| 1145 | codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_tail, &lazy_decls_aw.writer) catch |err| switch (err) { | 1146 | codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_tail, &lazy_decls_aw.writer) catch |err| switch (err) { |
| 1146 | error.WriteFailed => return error.OutOfMemory, | 1147 | error.WriteFailed => return error.OutOfMemory, |
| 1147 | error.OutOfMemory => |e| return e, | 1148 | error.Canceled, error.OutOfMemory => |e| return e, |
| 1148 | error.AlreadyReported => unreachable, | 1149 | error.AlreadyReported => unreachable, |
| 1149 | }; | 1150 | }; |
| 1150 | } | 1151 | } |
| 1151 | for (need_never_inline_funcs.keys()) |fn_nav| { | 1152 | for (need_never_inline_funcs.keys()) |fn_nav| { |
| 1152 | codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_inline, &lazy_decls_aw.writer) catch |err| switch (err) { | 1153 | codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_inline, &lazy_decls_aw.writer) catch |err| switch (err) { |
| 1153 | error.WriteFailed => return error.OutOfMemory, | 1154 | error.WriteFailed => return error.OutOfMemory, |
| 1154 | error.OutOfMemory => |e| return e, | 1155 | error.Canceled, error.OutOfMemory => |e| return e, |
| 1155 | error.AlreadyReported => unreachable, | 1156 | error.AlreadyReported => unreachable, |
| 1156 | }; | 1157 | }; |
| 1157 | } | 1158 | } |
| ... | @@ -1343,7 +1344,7 @@ fn addCTypeDependencies( | ... | @@ -1343,7 +1344,7 @@ fn addCTypeDependencies( |
| 1343 | c: *C, | 1344 | c: *C, |
| 1344 | pt: Zcu.PerThread, | 1345 | pt: Zcu.PerThread, |
| 1345 | deps: *const codegen.CType.Dependencies, | 1346 | deps: *const codegen.CType.Dependencies, |
| 1346 | ) Allocator.Error!CTypeDependencies { | 1347 | ) link.Error!CTypeDependencies { |
| 1347 | const gpa = pt.zcu.comp.gpa; | 1348 | const gpa = pt.zcu.comp.gpa; |
| 1348 | 1349 | ||
| 1349 | try c.bigint_types.ensureUnusedCapacity(gpa, deps.bigint.count()); | 1350 | try c.bigint_types.ensureUnusedCapacity(gpa, deps.bigint.count()); |
| ... | @@ -1399,7 +1400,7 @@ fn addCTypeDependencies( | ... | @@ -1399,7 +1400,7 @@ fn addCTypeDependencies( |
| 1399 | }; | 1400 | }; |
| 1400 | } | 1401 | } |
| 1401 | 1402 | ||
| 1402 | fn updateNewUavs(c: *C, pt: Zcu.PerThread, old_uavs_len: usize) Allocator.Error!void { | 1403 | fn updateNewUavs(c: *C, pt: Zcu.PerThread, old_uavs_len: usize) link.Error!void { |
| 1403 | const gpa = pt.zcu.comp.gpa; | 1404 | const gpa = pt.zcu.comp.gpa; |
| 1404 | var index = old_uavs_len; | 1405 | var index = old_uavs_len; |
| 1405 | while (index < c.uavs.count()) : (index += 1) { | 1406 | while (index < c.uavs.count()) : (index += 1) { |
src/link/Coff.zig+190-155| ... | @@ -13,7 +13,7 @@ const codegen = @import("../codegen.zig"); | ... | @@ -13,7 +13,7 @@ const codegen = @import("../codegen.zig"); |
| 13 | const Compilation = @import("../Compilation.zig"); | 13 | const Compilation = @import("../Compilation.zig"); |
| 14 | const InternPool = @import("../InternPool.zig"); | 14 | const InternPool = @import("../InternPool.zig"); |
| 15 | const link = @import("../link.zig"); | 15 | const link = @import("../link.zig"); |
| 16 | const MappedFile = @import("MappedFile.zig"); | 16 | const MappedFile = link.MappedFile; |
| 17 | const target_util = @import("../target.zig"); | 17 | const target_util = @import("../target.zig"); |
| 18 | const Type = @import("../Type.zig"); | 18 | const Type = @import("../Type.zig"); |
| 19 | const Value = @import("../Value.zig"); | 19 | const Value = @import("../Value.zig"); |
| ... | @@ -536,7 +536,7 @@ pub const Member = struct { | ... | @@ -536,7 +536,7 @@ pub const Member = struct { |
| 536 | const new_size = Alignment.@"4".forward(old_size + name.len + 1); | 536 | const new_size = Alignment.@"4".forward(old_size + name.len + 1); |
| 537 | assert(new_size < comptime try std.math.powi(u64, 10, max_name_len - 1)); | 537 | assert(new_size < comptime try std.math.powi(u64, 10, max_name_len - 1)); |
| 538 | 538 | ||
| 539 | try Node.known.longnames_member.resizeLeaf(&coff.mf, gpa, new_size); | 539 | try Node.known.longnames_member.resizeLeaf(gpa, &coff.mf, new_size); |
| 540 | const name_table_slice = Node.known.longnames_member.slice(&coff.mf); | 540 | const name_table_slice = Node.known.longnames_member.slice(&coff.mf); |
| 541 | const name_slice = name_table_slice[@intCast(old_size)..][0 .. name.len + 1]; | 541 | const name_slice = name_table_slice[@intCast(old_size)..][0 .. name.len + 1]; |
| 542 | @memcpy(name_slice[0..name.len], name); | 542 | @memcpy(name_slice[0..name.len], name); |
| ... | @@ -1666,7 +1666,7 @@ fn create( | ... | @@ -1666,7 +1666,7 @@ fn create( |
| 1666 | .global_pending_index = 0, | 1666 | .global_pending_index = 0, |
| 1667 | .navs = .empty, | 1667 | .navs = .empty, |
| 1668 | .uavs = .empty, | 1668 | .uavs = .empty, |
| 1669 | .lazy = .initFill(.{ | 1669 | .lazy = comptime .initFill(.{ |
| 1670 | .map = .empty, | 1670 | .map = .empty, |
| 1671 | .pending_index = 0, | 1671 | .pending_index = 0, |
| 1672 | }), | 1672 | }), |
| ... | @@ -1840,13 +1840,13 @@ fn initHeaders( | ... | @@ -1840,13 +1840,13 @@ fn initHeaders( |
| 1840 | coff.nodes.appendAssumeCapacity(.file); | 1840 | coff.nodes.appendAssumeCapacity(.file); |
| 1841 | 1841 | ||
| 1842 | const header_ni = Node.known.header; | 1842 | const header_ni = Node.known.header; |
| 1843 | assert(header_ni == try Node.known.file.addOnlyHeaderChild(&coff.mf, gpa, .{ | 1843 | assert(header_ni == try Node.known.file.addOnlyHeaderChild(gpa, &coff.mf, .{ |
| 1844 | .alignment = coff.mf.flags.block_size, | 1844 | .alignment = coff.mf.flags.block_size, |
| 1845 | })); | 1845 | })); |
| 1846 | coff.nodes.appendAssumeCapacity(.header); | 1846 | coff.nodes.appendAssumeCapacity(.header); |
| 1847 | 1847 | ||
| 1848 | const coff_parent_ni: MappedFile.Node.Index = if (is_archive) parent: { | 1848 | const coff_parent_ni: MappedFile.Node.Index = if (is_archive) parent: { |
| 1849 | assert(try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, .wrap(header_ni), .{ | 1849 | assert(try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, .wrap(header_ni), .{ |
| 1850 | .size = std.coff.archive_signature.len, | 1850 | .size = std.coff.archive_signature.len, |
| 1851 | .alignment = .@"4", | 1851 | .alignment = .@"4", |
| 1852 | }) == Node.known.signature); | 1852 | }) == Node.known.signature); |
| ... | @@ -1879,7 +1879,7 @@ fn initHeaders( | ... | @@ -1879,7 +1879,7 @@ fn initHeaders( |
| 1879 | const zcu_member = zcu_mi.get(coff); | 1879 | const zcu_member = zcu_mi.get(coff); |
| 1880 | try zcu_member.initHeader(coff, zcu.main_mod.fully_qualified_name, timestamp); | 1880 | try zcu_member.initHeader(coff, zcu.main_mod.fully_qualified_name, timestamp); |
| 1881 | 1881 | ||
| 1882 | assert(try zcu_member.content_ni.addOnlyHeaderChild(&coff.mf, gpa, .{ | 1882 | assert(try zcu_member.content_ni.addOnlyHeaderChild(gpa, &coff.mf, .{ |
| 1883 | .size = @sizeOf(std.coff.Header), | 1883 | .size = @sizeOf(std.coff.Header), |
| 1884 | .alignment = .@"4", | 1884 | .alignment = .@"4", |
| 1885 | }) == Node.known.coff_header); | 1885 | }) == Node.known.coff_header); |
| ... | @@ -1894,13 +1894,13 @@ fn initHeaders( | ... | @@ -1894,13 +1894,13 @@ fn initHeaders( |
| 1894 | // no other members then the last linker member (longnames) needs to expand | 1894 | // no other members then the last linker member (longnames) needs to expand |
| 1895 | // to fill the padding at the end of the file. | 1895 | // to fill the padding at the end of the file. |
| 1896 | while (coff.nodes.len < Node.known_count) { | 1896 | while (coff.nodes.len < Node.known_count) { |
| 1897 | _ = try Node.known.header.addHeaderChildAfter(&coff.mf, gpa, .none, .{}); | 1897 | _ = try Node.known.header.addHeaderChildAfter(gpa, &coff.mf, .none, .{}); |
| 1898 | coff.nodes.appendAssumeCapacity(.placeholder); | 1898 | coff.nodes.appendAssumeCapacity(.placeholder); |
| 1899 | } | 1899 | } |
| 1900 | 1900 | ||
| 1901 | return; | 1901 | return; |
| 1902 | } else parent: { | 1902 | } else parent: { |
| 1903 | assert(try header_ni.addOnlyHeaderChild(&coff.mf, gpa, .{ | 1903 | assert(try header_ni.addOnlyHeaderChild(gpa, &coff.mf, .{ |
| 1904 | .size = if (is_image) msdos_stub.len + std.coff.pe_signature.len else 0, | 1904 | .size = if (is_image) msdos_stub.len + std.coff.pe_signature.len else 0, |
| 1905 | .alignment = .@"4", | 1905 | .alignment = .@"4", |
| 1906 | }) == Node.known.signature); | 1906 | }) == Node.known.signature); |
| ... | @@ -1913,12 +1913,12 @@ fn initHeaders( | ... | @@ -1913,12 +1913,12 @@ fn initHeaders( |
| 1913 | 1913 | ||
| 1914 | // TODO: Not ideal to have this many placeholder nodes - use two distinct `Node.known` types? | 1914 | // TODO: Not ideal to have this many placeholder nodes - use two distinct `Node.known` types? |
| 1915 | while (true) { | 1915 | while (true) { |
| 1916 | const placeholder_ni = try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, .none, .{}); | 1916 | const placeholder_ni = try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, .none, .{}); |
| 1917 | coff.nodes.appendAssumeCapacity(.placeholder); | 1917 | coff.nodes.appendAssumeCapacity(.placeholder); |
| 1918 | if (placeholder_ni == Node.known.zcu_member) break; | 1918 | if (placeholder_ni == Node.known.zcu_member) break; |
| 1919 | } | 1919 | } |
| 1920 | 1920 | ||
| 1921 | assert(try header_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(Node.known.signature), .{ | 1921 | assert(try header_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(Node.known.signature), .{ |
| 1922 | .size = @sizeOf(std.coff.Header), | 1922 | .size = @sizeOf(std.coff.Header), |
| 1923 | .alignment = .@"4", | 1923 | .alignment = .@"4", |
| 1924 | }) == Node.known.coff_header); | 1924 | }) == Node.known.coff_header); |
| ... | @@ -1949,7 +1949,7 @@ fn initHeaders( | ... | @@ -1949,7 +1949,7 @@ fn initHeaders( |
| 1949 | } | 1949 | } |
| 1950 | 1950 | ||
| 1951 | const optional_header_ni = Node.known.optional_header; | 1951 | const optional_header_ni = Node.known.optional_header; |
| 1952 | assert(optional_header_ni == try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(Node.known.coff_header), .{ | 1952 | assert(optional_header_ni == try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(Node.known.coff_header), .{ |
| 1953 | .size = optional_header_size, | 1953 | .size = optional_header_size, |
| 1954 | .alignment = .@"4", | 1954 | .alignment = .@"4", |
| 1955 | })); | 1955 | })); |
| ... | @@ -2060,7 +2060,7 @@ fn initHeaders( | ... | @@ -2060,7 +2060,7 @@ fn initHeaders( |
| 2060 | } | 2060 | } |
| 2061 | 2061 | ||
| 2062 | const data_directories_ni = Node.known.data_directories; | 2062 | const data_directories_ni = Node.known.data_directories; |
| 2063 | assert(data_directories_ni == try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(optional_header_ni), .{ | 2063 | assert(data_directories_ni == try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(optional_header_ni), .{ |
| 2064 | .size = data_directories_size, | 2064 | .size = data_directories_size, |
| 2065 | .alignment = .@"4", | 2065 | .alignment = .@"4", |
| 2066 | })); | 2066 | })); |
| ... | @@ -2075,7 +2075,7 @@ fn initHeaders( | ... | @@ -2075,7 +2075,7 @@ fn initHeaders( |
| 2075 | } | 2075 | } |
| 2076 | 2076 | ||
| 2077 | const section_table_ni = Node.known.section_table; | 2077 | const section_table_ni = Node.known.section_table; |
| 2078 | assert(section_table_ni == try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(data_directories_ni), .{ | 2078 | assert(section_table_ni == try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(data_directories_ni), .{ |
| 2079 | .alignment = .@"4", | 2079 | .alignment = .@"4", |
| 2080 | })); | 2080 | })); |
| 2081 | coff.nodes.appendAssumeCapacity(.section_table); | 2081 | coff.nodes.appendAssumeCapacity(.section_table); |
| ... | @@ -2084,13 +2084,13 @@ fn initHeaders( | ... | @@ -2084,13 +2084,13 @@ fn initHeaders( |
| 2084 | 2084 | ||
| 2085 | if (!is_image) { | 2085 | if (!is_image) { |
| 2086 | // TODO: These two nodes could be inside one movable node? | 2086 | // TODO: These two nodes could be inside one movable node? |
| 2087 | coff.symbol_table.ni = try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(section_table_ni), .{ | 2087 | coff.symbol_table.ni = try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(section_table_ni), .{ |
| 2088 | .alignment = .@"2", | 2088 | .alignment = .@"2", |
| 2089 | .moved = true, | 2089 | .moved = true, |
| 2090 | }); | 2090 | }); |
| 2091 | coff.nodes.appendAssumeCapacity(.symbol_table); | 2091 | coff.nodes.appendAssumeCapacity(.symbol_table); |
| 2092 | 2092 | ||
| 2093 | coff.symbol_table.strings_ni = try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(coff.symbol_table.ni), .{ | 2093 | coff.symbol_table.strings_ni = try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(coff.symbol_table.ni), .{ |
| 2094 | .size = @sizeOf(u32), | 2094 | .size = @sizeOf(u32), |
| 2095 | .resized = true, | 2095 | .resized = true, |
| 2096 | }); | 2096 | }); |
| ... | @@ -2143,7 +2143,7 @@ fn initHeaders( | ... | @@ -2143,7 +2143,7 @@ fn initHeaders( |
| 2143 | coff.mf.flags.block_size, | 2143 | coff.mf.flags.block_size, |
| 2144 | .{ .read = true, .initialized = true }, | 2144 | .{ .read = true, .initialized = true }, |
| 2145 | )).symbol(coff).node(coff); | 2145 | )).symbol(coff).node(coff); |
| 2146 | coff.import_table.ni = try import_table_parent_ni.addFloatingChild(&coff.mf, gpa, .{ | 2146 | coff.import_table.ni = try import_table_parent_ni.addFloatingChild(gpa, &coff.mf, .{ |
| 2147 | .alignment = .@"4", | 2147 | .alignment = .@"4", |
| 2148 | }); | 2148 | }); |
| 2149 | coff.nodes.appendAssumeCapacity(.import_directory_table); | 2149 | coff.nodes.appendAssumeCapacity(.import_directory_table); |
| ... | @@ -2154,7 +2154,7 @@ fn initHeaders( | ... | @@ -2154,7 +2154,7 @@ fn initHeaders( |
| 2154 | .{ .read = true, .initialized = true }, | 2154 | .{ .read = true, .initialized = true }, |
| 2155 | )).symbol(coff).node(coff); | 2155 | )).symbol(coff).node(coff); |
| 2156 | 2156 | ||
| 2157 | coff.export_table.export_directory_table_ni = try coff.export_table.ni.addHeaderChildAfter(&coff.mf, gpa, coff.export_table.ni.last(&coff.mf), .{ | 2157 | coff.export_table.export_directory_table_ni = try coff.export_table.ni.addHeaderChildAfter(gpa, &coff.mf, coff.export_table.ni.last(&coff.mf), .{ |
| 2158 | .size = @sizeOf(std.coff.ExportDirectoryTable) + file_name.len + 1, | 2158 | .size = @sizeOf(std.coff.ExportDirectoryTable) + file_name.len + 1, |
| 2159 | .moved = true, | 2159 | .moved = true, |
| 2160 | }); | 2160 | }); |
| ... | @@ -2165,7 +2165,7 @@ fn initHeaders( | ... | @@ -2165,7 +2165,7 @@ fn initHeaders( |
| 2165 | @memcpy(table_slice[name_index..][0..file_name.len], file_name[0..file_name.len]); | 2165 | @memcpy(table_slice[name_index..][0..file_name.len], file_name[0..file_name.len]); |
| 2166 | @memset(table_slice[name_index + file_name.len ..], 0); | 2166 | @memset(table_slice[name_index + file_name.len ..], 0); |
| 2167 | 2167 | ||
| 2168 | const export_address_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{ | 2168 | const export_address_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{ |
| 2169 | .alignment = .of(std.coff.ExportAddressTableEntry), | 2169 | .alignment = .of(std.coff.ExportAddressTableEntry), |
| 2170 | .moved = true, | 2170 | .moved = true, |
| 2171 | }); | 2171 | }); |
| ... | @@ -2181,19 +2181,19 @@ fn initHeaders( | ... | @@ -2181,19 +2181,19 @@ fn initHeaders( |
| 2181 | export_address_table_sym.section_number = | 2181 | export_address_table_sym.section_number = |
| 2182 | coff.getNode(coff.export_table.ni).pseudo_section.symbol(coff).get(coff).section_number; | 2182 | coff.getNode(coff.export_table.ni).pseudo_section.symbol(coff).get(coff).section_number; |
| 2183 | 2183 | ||
| 2184 | coff.export_table.name_pointer_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{ | 2184 | coff.export_table.name_pointer_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{ |
| 2185 | .alignment = .of(std.coff.ExportNamePointerTableEntry), | 2185 | .alignment = .of(std.coff.ExportNamePointerTableEntry), |
| 2186 | .moved = true, | 2186 | .moved = true, |
| 2187 | }); | 2187 | }); |
| 2188 | coff.nodes.appendAssumeCapacity(.export_name_pointer_table); | 2188 | coff.nodes.appendAssumeCapacity(.export_name_pointer_table); |
| 2189 | 2189 | ||
| 2190 | coff.export_table.ordinal_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{ | 2190 | coff.export_table.ordinal_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{ |
| 2191 | .alignment = .of(std.coff.ExportOrdinalTableEntry), | 2191 | .alignment = .of(std.coff.ExportOrdinalTableEntry), |
| 2192 | .moved = true, | 2192 | .moved = true, |
| 2193 | }); | 2193 | }); |
| 2194 | coff.nodes.appendAssumeCapacity(.export_ordinal_table); | 2194 | coff.nodes.appendAssumeCapacity(.export_ordinal_table); |
| 2195 | 2195 | ||
| 2196 | coff.export_table.name_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{ | 2196 | coff.export_table.name_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{ |
| 2197 | .alignment = .of(u8), | 2197 | .alignment = .of(u8), |
| 2198 | .moved = true, | 2198 | .moved = true, |
| 2199 | }); | 2199 | }); |
| ... | @@ -2286,7 +2286,7 @@ pub fn initBuiltins(coff: *Coff) !void { | ... | @@ -2286,7 +2286,7 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2286 | const list_len_si = try coff.globalSymbol(.{ .name = list.global, .type = .data }); | 2286 | const list_len_si = try coff.globalSymbol(.{ .name = list.global, .type = .data }); |
| 2287 | const list_len_sym = list_len_si.get(coff); | 2287 | const list_len_sym = list_len_si.get(coff); |
| 2288 | list_len_sym.setExtra(.{ .size = addr_info.size }); | 2288 | list_len_sym.setExtra(.{ .size = addr_info.size }); |
| 2289 | list_len_sym.ni = .wrap(try start_sym.ni.unwrap().?.addHeaderChildAfter(&coff.mf, gpa, .none, .{ | 2289 | list_len_sym.ni = .wrap(try start_sym.ni.unwrap().?.addHeaderChildAfter(gpa, &coff.mf, .none, .{ |
| 2290 | .size = addr_info.size, | 2290 | .size = addr_info.size, |
| 2291 | })); | 2291 | })); |
| 2292 | coff.nodes.appendAssumeCapacity(.{ .builtin = list_len_si }); | 2292 | coff.nodes.appendAssumeCapacity(.{ .builtin = list_len_si }); |
| ... | @@ -2307,7 +2307,7 @@ pub fn initBuiltins(coff: *Coff) !void { | ... | @@ -2307,7 +2307,7 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2307 | const list_end_si = coff.addSymbolAssumeCapacity(); | 2307 | const list_end_si = coff.addSymbolAssumeCapacity(); |
| 2308 | const list_end_sym = list_end_si.get(coff); | 2308 | const list_end_sym = list_end_si.get(coff); |
| 2309 | list_end_sym.setExtra(.{ .size = addr_info.size }); | 2309 | list_end_sym.setExtra(.{ .size = addr_info.size }); |
| 2310 | list_end_sym.ni = .wrap(try end_sym.ni.unwrap().?.addHeaderChildAfter(&coff.mf, gpa, .none, .{ | 2310 | list_end_sym.ni = .wrap(try end_sym.ni.unwrap().?.addHeaderChildAfter(gpa, &coff.mf, .none, .{ |
| 2311 | .size = addr_info.size, | 2311 | .size = addr_info.size, |
| 2312 | })); | 2312 | })); |
| 2313 | coff.nodes.appendAssumeCapacity(.{ .builtin = list_end_si }); | 2313 | coff.nodes.appendAssumeCapacity(.{ .builtin = list_end_si }); |
| ... | @@ -2723,7 +2723,7 @@ fn getOrPutSymbolName(coff: *Coff, name: []const u8, opt_string: ?String) !Symbo | ... | @@ -2723,7 +2723,7 @@ fn getOrPutSymbolName(coff: *Coff, name: []const u8, opt_string: ?String) !Symbo |
| 2723 | const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1]; | 2723 | const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1]; |
| 2724 | string_gop.value_ptr.* = @fromBackingInt(@intCast(string_index)); | 2724 | string_gop.value_ptr.* = @fromBackingInt(@intCast(string_index)); |
| 2725 | 2725 | ||
| 2726 | try coff.symbol_table.strings_ni.resizeLeaf(&coff.mf, gpa, string_index + name.len + 1); | 2726 | try coff.symbol_table.strings_ni.resizeLeaf(gpa, &coff.mf, string_index + name.len + 1); |
| 2727 | const slice = coff.symbol_table.strings_ni.slice(&coff.mf); | 2727 | const slice = coff.symbol_table.strings_ni.slice(&coff.mf); |
| 2728 | @memcpy(slice[@intCast(string_index)..][0..name.len], name); | 2728 | @memcpy(slice[@intCast(string_index)..][0..name.len], name); |
| 2729 | slice[@intCast(string_index + name.len)] = 0; | 2729 | slice[@intCast(string_index + name.len)] = 0; |
| ... | @@ -2948,7 +2948,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind, | ... | @@ -2948,7 +2948,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind, |
| 2948 | const comp = coff.base.comp; | 2948 | const comp = coff.base.comp; |
| 2949 | const gpa = comp.gpa; | 2949 | const gpa = comp.gpa; |
| 2950 | 2950 | ||
| 2951 | const header_ni = try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, Node.known.file.last(&coff.mf), .{ | 2951 | const header_ni = try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, Node.known.file.last(&coff.mf), .{ |
| 2952 | .size = @sizeOf(std.coff.ArchiveMemberHeader), | 2952 | .size = @sizeOf(std.coff.ArchiveMemberHeader), |
| 2953 | .alignment = .@"2", | 2953 | .alignment = .@"2", |
| 2954 | .moved = true, | 2954 | .moved = true, |
| ... | @@ -2960,7 +2960,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind, | ... | @@ -2960,7 +2960,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind, |
| 2960 | .first_linker, .second_linker, .longnames, .coff => .@"4", | 2960 | .first_linker, .second_linker, .longnames, .coff => .@"4", |
| 2961 | else => .@"2", | 2961 | else => .@"2", |
| 2962 | }; | 2962 | }; |
| 2963 | const content_ni = try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, .wrap(header_ni), .{ | 2963 | const content_ni = try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, .wrap(header_ni), .{ |
| 2964 | .alignment = content_align, | 2964 | .alignment = content_align, |
| 2965 | .size = content_align.forward(size), | 2965 | .size = content_align.forward(size), |
| 2966 | .resized = size > 0, | 2966 | .resized = size > 0, |
| ... | @@ -2989,7 +2989,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind, | ... | @@ -2989,7 +2989,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind, |
| 2989 | const old_size = Node.known.second_linker_member.location(&coff.mf).resolve(&coff.mf)[1]; | 2989 | const old_size = Node.known.second_linker_member.location(&coff.mf).resolve(&coff.mf)[1]; |
| 2990 | const old_header_size = new_num_members * @sizeOf(u32); | 2990 | const old_header_size = new_num_members * @sizeOf(u32); |
| 2991 | const trailing_size: usize = @intCast(old_size - old_header_size); | 2991 | const trailing_size: usize = @intCast(old_size - old_header_size); |
| 2992 | try Node.known.second_linker_member.resizeLeaf(&coff.mf, gpa, old_size + @sizeOf(u32)); | 2992 | try Node.known.second_linker_member.resizeLeaf(gpa, &coff.mf, old_size + @sizeOf(u32)); |
| 2993 | 2993 | ||
| 2994 | const slice = Node.known.second_linker_member.slice(&coff.mf); | 2994 | const slice = Node.known.second_linker_member.slice(&coff.mf); |
| 2995 | @memmove( | 2995 | @memmove( |
| ... | @@ -3060,7 +3060,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { | ... | @@ -3060,7 +3060,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { |
| 3060 | { | 3060 | { |
| 3061 | const old_header_size: usize = @intCast(@sizeOf(u32) + @backingInt(mfli) * @sizeOf(u32)); | 3061 | const old_header_size: usize = @intCast(@sizeOf(u32) + @backingInt(mfli) * @sizeOf(u32)); |
| 3062 | const new_header_size: usize = @intCast(old_header_size + @sizeOf(u32)); | 3062 | const new_header_size: usize = @intCast(old_header_size + @sizeOf(u32)); |
| 3063 | try Node.known.first_linker_member.resizeLeaf(&coff.mf, gpa, Alignment.@"4".forward(new_header_size + new_string_table_size)); | 3063 | try Node.known.first_linker_member.resizeLeaf(gpa, &coff.mf, Alignment.@"4".forward(new_header_size + new_string_table_size)); |
| 3064 | 3064 | ||
| 3065 | const slice = Node.known.first_linker_member.slice(&coff.mf); | 3065 | const slice = Node.known.first_linker_member.slice(&coff.mf); |
| 3066 | @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]); | 3066 | @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]); |
| ... | @@ -3074,7 +3074,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { | ... | @@ -3074,7 +3074,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { |
| 3074 | const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr()); | 3074 | const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr()); |
| 3075 | const old_header_size = 2 * @sizeOf(u32) + num_members * @sizeOf(u32) + @backingInt(mfli) * @sizeOf(u16); | 3075 | const old_header_size = 2 * @sizeOf(u32) + num_members * @sizeOf(u32) + @backingInt(mfli) * @sizeOf(u16); |
| 3076 | const new_header_size = old_header_size + @sizeOf(u16); | 3076 | const new_header_size = old_header_size + @sizeOf(u16); |
| 3077 | try Node.known.second_linker_member.resizeLeaf(&coff.mf, gpa, Alignment.@"4".forward(new_header_size + new_string_table_size)); | 3077 | try Node.known.second_linker_member.resizeLeaf(gpa, &coff.mf, Alignment.@"4".forward(new_header_size + new_string_table_size)); |
| 3078 | 3078 | ||
| 3079 | const old_needs_sort = coff.pending_members.get(Member.Index.second) != null; | 3079 | const old_needs_sort = coff.pending_members.get(Member.Index.second) != null; |
| 3080 | const needs_sort = old_needs_sort or (if (coff.lib_string_table.items.len > 0) | 3080 | const needs_sort = old_needs_sort or (if (coff.lib_string_table.items.len > 0) |
| ... | @@ -3108,7 +3108,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { | ... | @@ -3108,7 +3108,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { |
| 3108 | coff.member_prog_node.increaseEstimatedTotalItems(1); | 3108 | coff.member_prog_node.increaseEstimatedTotalItems(1); |
| 3109 | } | 3109 | } |
| 3110 | 3110 | ||
| 3111 | fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void { | 3111 | fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { |
| 3112 | assert(!coff.isImage()); | 3112 | assert(!coff.isImage()); |
| 3113 | const gpa = coff.base.comp.gpa; | 3113 | const gpa = coff.base.comp.gpa; |
| 3114 | 3114 | ||
| ... | @@ -3119,7 +3119,6 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void { | ... | @@ -3119,7 +3119,6 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void { |
| 3119 | assert(sym.ni != .none or sym.gmi != .none); | 3119 | assert(sym.ni != .none or sym.gmi != .none); |
| 3120 | 3120 | ||
| 3121 | const entry = coff.symbolTableEntryPtr(sti.*) orelse entry: { | 3121 | const entry = coff.symbolTableEntryPtr(sti.*) orelse entry: { |
| 3122 | var buf: [15]u8 = undefined; | ||
| 3123 | const symbol_name, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType = | 3122 | const symbol_name, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType = |
| 3124 | if (sym.gmi != .none) blk: { | 3123 | if (sym.gmi != .none) blk: { |
| 3125 | const name = sym.gmi.name(coff); | 3124 | const name = sym.gmi.name(coff); |
| ... | @@ -3148,21 +3147,22 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void { | ... | @@ -3148,21 +3147,22 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void { |
| 3148 | }; | 3147 | }; |
| 3149 | }, | 3148 | }, |
| 3150 | .uav => |umi| { | 3149 | .uav => |umi| { |
| 3151 | var w = Io.Writer.fixed(&buf); | 3150 | var name_buf: [std.fmt.count("__anon_{d}", .{std.math.maxInt(u32)})]u8 = undefined; |
| 3152 | w.print("__anon_{x}", .{umi.uavValue(coff)}) catch unreachable; | 3151 | const name = std.mem.print(&name_buf, "__anon_{d}", .{umi}) catch unreachable; |
| 3153 | break :blk .{ | 3152 | break :blk .{ |
| 3154 | try coff.getOrPutSymbolName(w.buffered(), null), | 3153 | try coff.getOrPutSymbolName(name, null), |
| 3155 | 0, | 3154 | 0, |
| 3156 | .NULL, | 3155 | .NULL, |
| 3157 | }; | 3156 | }; |
| 3158 | }, | 3157 | }, |
| 3159 | inline .lazy_code, .lazy_const_data => |mi, tag| { | 3158 | inline .lazy_code, .lazy_const_data => |mi, tag| { |
| 3160 | const lazy_sym = mi.lazySymbol(coff); | 3159 | const lazy_sym = mi.lazySymbol(coff); |
| 3161 | const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{ | 3160 | var name_buf: [ |
| 3162 | @tagName(lazy_sym.kind), | 3161 | std.fmt.count("__lazy_const_data_{d}", .{std.math.maxInt(u32)}) |
| 3163 | Type.fromInterned(lazy_sym.ty).fmt(pt), | 3162 | ]u8 = undefined; |
| 3164 | }); | 3163 | const name = std.mem.print(&name_buf, "__lazy_{t}_{d}", .{ |
| 3165 | defer gpa.free(name); | 3164 | lazy_sym.kind, mi, |
| 3165 | }) catch unreachable; | ||
| 3166 | 3166 | ||
| 3167 | const string = try coff.getOrPutString(name); | 3167 | const string = try coff.getOrPutString(name); |
| 3168 | break :blk .{ | 3168 | break :blk .{ |
| ... | @@ -3181,7 +3181,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void { | ... | @@ -3181,7 +3181,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void { |
| 3181 | const new_num_symbols = old_num_symbols + 1 + num_aux_symbols; | 3181 | const new_num_symbols = old_num_symbols + 1 + num_aux_symbols; |
| 3182 | coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols); | 3182 | coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols); |
| 3183 | 3183 | ||
| 3184 | try coff.symbol_table.ni.resizeLeaf(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf()); | 3184 | try coff.symbol_table.ni.resizeLeaf(gpa, &coff.mf, new_num_symbols * std.coff.Symbol.sizeOf()); |
| 3185 | 3185 | ||
| 3186 | sti.* = .wrap(old_num_symbols); | 3186 | sti.* = .wrap(old_num_symbols); |
| 3187 | si.flushSymbolTableIndex(coff); | 3187 | si.flushSymbolTableIndex(coff); |
| ... | @@ -3317,7 +3317,7 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void { | ... | @@ -3317,7 +3317,7 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void { |
| 3317 | try fr.seekTo(file_loc.offset); | 3317 | try fr.seekTo(file_loc.offset); |
| 3318 | var nw: MappedFile.Node.Writer = undefined; | 3318 | var nw: MappedFile.Node.Writer = undefined; |
| 3319 | const si = isi.symbol(coff); | 3319 | const si = isi.symbol(coff); |
| 3320 | si.node(coff).writer(&coff.mf, gpa, &nw); | 3320 | si.node(coff).writer(gpa, &coff.mf, &nw); |
| 3321 | defer nw.deinit(); | 3321 | defer nw.deinit(); |
| 3322 | log.debug("flushInputSection({f}{f}, {s}, {d}, n{d})", .{ | 3322 | log.debug("flushInputSection({f}{f}, {s}, {d}, n{d})", .{ |
| 3323 | path, | 3323 | path, |
| ... | @@ -3345,12 +3345,12 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S | ... | @@ -3345,12 +3345,12 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S |
| 3345 | const section_table_len = section_index + 1; | 3345 | const section_table_len = section_index + 1; |
| 3346 | coff.targetStore(&coff_header.number_of_sections, section_table_len); | 3346 | coff.targetStore(&coff_header.number_of_sections, section_table_len); |
| 3347 | try Node.known.section_table.resizeLeaf( | 3347 | try Node.known.section_table.resizeLeaf( |
| 3348 | &coff.mf, | ||
| 3349 | gpa, | 3348 | gpa, |
| 3349 | &coff.mf, | ||
| 3350 | @sizeOf(std.coff.SectionHeader) * section_table_len, | 3350 | @sizeOf(std.coff.SectionHeader) * section_table_len, |
| 3351 | ); | 3351 | ); |
| 3352 | 3352 | ||
| 3353 | const ni = try coff.sectionParent().addFloatingChild(&coff.mf, gpa, .{ | 3353 | const ni = try coff.sectionParent().addFloatingChild(gpa, &coff.mf, .{ |
| 3354 | .alignment = coff.mf.flags.block_size, | 3354 | .alignment = coff.mf.flags.block_size, |
| 3355 | .moved = true, | 3355 | .moved = true, |
| 3356 | .bubbles_moved = false, | 3356 | .bubbles_moved = false, |
| ... | @@ -3486,7 +3486,7 @@ fn pseudoSectionMapIndex( | ... | @@ -3486,7 +3486,7 @@ fn pseudoSectionMapIndex( |
| 3486 | 3486 | ||
| 3487 | try coff.nodes.ensureUnusedCapacity(gpa, 1); | 3487 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 3488 | try coff.symbols.ensureUnusedCapacity(gpa, 1); | 3488 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 3489 | const ni = try parent.node(coff).addFloatingChild(&coff.mf, gpa, .{ .alignment = alignment }); | 3489 | const ni = try parent.node(coff).addFloatingChild(gpa, &coff.mf, .{ .alignment = alignment }); |
| 3490 | const si = coff.addSymbolAssumeCapacity(); | 3490 | const si = coff.addSymbolAssumeCapacity(); |
| 3491 | pseudo_section_gop.value_ptr.* = si; | 3491 | pseudo_section_gop.value_ptr.* = si; |
| 3492 | const sym = si.get(coff); | 3492 | const sym = si.get(coff); |
| ... | @@ -3560,7 +3560,7 @@ fn objectSectionMapIndex( | ... | @@ -3560,7 +3560,7 @@ fn objectSectionMapIndex( |
| 3560 | } | 3560 | } |
| 3561 | } | 3561 | } |
| 3562 | } | 3562 | } |
| 3563 | const ni = try parent_ni.addHeaderChildAfter(&coff.mf, gpa, prev_oni, .{ | 3563 | const ni = try parent_ni.addHeaderChildAfter(gpa, &coff.mf, prev_oni, .{ |
| 3564 | .alignment = alignment, | 3564 | .alignment = alignment, |
| 3565 | }); | 3565 | }); |
| 3566 | const si = coff.addSymbolAssumeCapacity(); | 3566 | const si = coff.addSymbolAssumeCapacity(); |
| ... | @@ -3579,13 +3579,13 @@ fn objectSectionMapIndex( | ... | @@ -3579,13 +3579,13 @@ fn objectSectionMapIndex( |
| 3579 | const parent_alignment = parent_ni.alignment(&coff.mf); | 3579 | const parent_alignment = parent_ni.alignment(&coff.mf); |
| 3580 | if (alignment.compare(.gt, parent_alignment)) { | 3580 | if (alignment.compare(.gt, parent_alignment)) { |
| 3581 | log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment }); | 3581 | log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment }); |
| 3582 | try parent_ni.realign(&coff.mf, gpa, alignment); | 3582 | try parent_ni.realign(gpa, &coff.mf, alignment); |
| 3583 | } | 3583 | } |
| 3584 | 3584 | ||
| 3585 | const old_alignment = sym.ni.unwrap().?.alignment(&coff.mf); | 3585 | const old_alignment = sym.ni.unwrap().?.alignment(&coff.mf); |
| 3586 | if (alignment.compare(.gt, old_alignment)) { | 3586 | if (alignment.compare(.gt, old_alignment)) { |
| 3587 | log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment }); | 3587 | log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment }); |
| 3588 | try sym.ni.unwrap().?.realign(&coff.mf, gpa, alignment); | 3588 | try sym.ni.unwrap().?.realign(gpa, &coff.mf, alignment); |
| 3589 | } | 3589 | } |
| 3590 | 3590 | ||
| 3591 | try coff.verifyParentSectionAttributes( | 3591 | try coff.verifyParentSectionAttributes( |
| ... | @@ -3742,9 +3742,9 @@ fn addRelocAssumeCapacity( | ... | @@ -3742,9 +3742,9 @@ fn addRelocAssumeCapacity( |
| 3742 | coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations); | 3742 | coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations); |
| 3743 | 3743 | ||
| 3744 | if (section.relocation_table_ni.unwrap()) |relocation_table_ni| { | 3744 | if (section.relocation_table_ni.unwrap()) |relocation_table_ni| { |
| 3745 | try relocation_table_ni.resizeLeaf(&coff.mf, gpa, new_size); | 3745 | try relocation_table_ni.resizeLeaf(gpa, &coff.mf, new_size); |
| 3746 | } else { | 3746 | } else { |
| 3747 | section.relocation_table_ni = .wrap(try coff.sectionParent().addFloatingChild(&coff.mf, gpa, .{ | 3747 | section.relocation_table_ni = .wrap(try coff.sectionParent().addFloatingChild(gpa, &coff.mf, .{ |
| 3748 | .size = new_size, | 3748 | .size = new_size, |
| 3749 | .alignment = .@"2", | 3749 | .alignment = .@"2", |
| 3750 | .moved = true, | 3750 | .moved = true, |
| ... | @@ -4094,7 +4094,7 @@ fn loadObject( | ... | @@ -4094,7 +4094,7 @@ fn loadObject( |
| 4094 | { | 4094 | { |
| 4095 | // TODO: This should be deferred to an idle task (but resize it here!) | 4095 | // TODO: This should be deferred to an idle task (but resize it here!) |
| 4096 | var nw: MappedFile.Node.Writer = undefined; | 4096 | var nw: MappedFile.Node.Writer = undefined; |
| 4097 | member.content_ni.writer(&coff.mf, gpa, &nw); | 4097 | member.content_ni.writer(gpa, &coff.mf, &nw); |
| 4098 | defer nw.deinit(); | 4098 | defer nw.deinit(); |
| 4099 | 4099 | ||
| 4100 | try fr.seekTo(fl.offset); | 4100 | try fr.seekTo(fl.offset); |
| ... | @@ -4653,7 +4653,7 @@ fn loadObject( | ... | @@ -4653,7 +4653,7 @@ fn loadObject( |
| 4653 | if (section.parent_si == .null) continue; | 4653 | if (section.parent_si == .null) continue; |
| 4654 | 4654 | ||
| 4655 | const alignment: Alignment = .fromByteUnits(section.header.flags.ALIGN.toByteUnits() orelse 1); | 4655 | const alignment: Alignment = .fromByteUnits(section.header.flags.ALIGN.toByteUnits() orelse 1); |
| 4656 | const ni = try section.parent_si.node(coff).addFloatingChild(&coff.mf, gpa, .{ | 4656 | const ni = try section.parent_si.node(coff).addFloatingChild(gpa, &coff.mf, .{ |
| 4657 | .size = alignment.forward(section.header.size_of_raw_data), | 4657 | .size = alignment.forward(section.header.size_of_raw_data), |
| 4658 | .alignment = alignment, | 4658 | .alignment = alignment, |
| 4659 | .moved = true, | 4659 | .moved = true, |
| ... | @@ -5064,7 +5064,9 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) Loa | ... | @@ -5064,7 +5064,9 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) Loa |
| 5064 | offset: u32, | 5064 | offset: u32, |
| 5065 | iami: ?InputArchive.Member.Index, | 5065 | iami: ?InputArchive.Member.Index, |
| 5066 | }) = .empty; | 5066 | }) = .empty; |
| 5067 | defer members.deinit(gpa); | ||
| 5067 | var symbol_member_indices: std.ArrayList(u32) = .empty; | 5068 | var symbol_member_indices: std.ArrayList(u32) = .empty; |
| 5069 | defer symbol_member_indices.deinit(gpa); | ||
| 5068 | 5070 | ||
| 5069 | const iai: InputArchive.Index = @fromBackingInt(@intCast(coff.input_archives.items.len)); | 5071 | const iai: InputArchive.Index = @fromBackingInt(@intCast(coff.input_archives.items.len)); |
| 5070 | (try coff.input_archives.addOne(gpa)).* = .{ | 5072 | (try coff.input_archives.addOne(gpa)).* = .{ |
| ... | @@ -5447,7 +5449,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde | ... | @@ -5447,7 +5449,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 5447 | const sec_si = try coff.navSection(zcu, nav.resolved.?); | 5449 | const sec_si = try coff.navSection(zcu, nav.resolved.?); |
| 5448 | try coff.nodes.ensureUnusedCapacity(gpa, 1); | 5450 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 5449 | if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1); | 5451 | if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1); |
| 5450 | const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{ | 5452 | const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{ |
| 5451 | .alignment = .fromIp(zcu.navAlignment(nav_index)), | 5453 | .alignment = .fromIp(zcu.navAlignment(nav_index)), |
| 5452 | .moved = true, | 5454 | .moved = true, |
| 5453 | }); | 5455 | }); |
| ... | @@ -5469,7 +5471,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde | ... | @@ -5469,7 +5471,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 5469 | 5471 | ||
| 5470 | { | 5472 | { |
| 5471 | var nw: MappedFile.Node.Writer = undefined; | 5473 | var nw: MappedFile.Node.Writer = undefined; |
| 5472 | ni.writer(&coff.mf, gpa, &nw); | 5474 | ni.writer(gpa, &coff.mf, &nw); |
| 5473 | defer nw.deinit(); | 5475 | defer nw.deinit(); |
| 5474 | codegen.generateSymbol( | 5476 | codegen.generateSymbol( |
| 5475 | &coff.base, | 5477 | &coff.base, |
| ... | @@ -5486,8 +5488,26 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde | ... | @@ -5486,8 +5488,26 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 5486 | } | 5488 | } |
| 5487 | 5489 | ||
| 5488 | if (nav.resolved.?.@"linksection".unwrap()) |_| { | 5490 | if (nav.resolved.?.@"linksection".unwrap()) |_| { |
| 5489 | try ni.resizeLeaf(&coff.mf, gpa, si.get(coff).extra.size); | 5491 | try ni.resizeLeaf(gpa, &coff.mf, si.get(coff).extra.size); |
| 5490 | } | 5492 | } |
| 5493 | |||
| 5494 | // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs. | ||
| 5495 | try coff.genPending(pt); | ||
| 5496 | } | ||
| 5497 | |||
| 5498 | pub fn updateContainerType( | ||
| 5499 | coff: *Coff, | ||
| 5500 | pt: Zcu.PerThread, | ||
| 5501 | ty: InternPool.Index, | ||
| 5502 | success: bool, | ||
| 5503 | ) link.Error!void { | ||
| 5504 | if (!success) return; | ||
| 5505 | var lazy_it = coff.lazy.iterator(); | ||
| 5506 | while (lazy_it.next()) |lazy| if (lazy.value.map.getIndex(ty)) |lmi| { | ||
| 5507 | if (lazy.value.pending_index <= lmi) continue; | ||
| 5508 | // This type has changed on this incremental update, so update the lazy code/data. | ||
| 5509 | try coff.genLazy(pt, .{ .kind = lazy.key, .index = @intCast(lmi) }); | ||
| 5510 | }; | ||
| 5491 | } | 5511 | } |
| 5492 | 5512 | ||
| 5493 | pub fn lowerUav( | 5513 | pub fn lowerUav( |
| ... | @@ -5558,7 +5578,7 @@ fn updateFuncInner( | ... | @@ -5558,7 +5578,7 @@ fn updateFuncInner( |
| 5558 | if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1); | 5578 | if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1); |
| 5559 | const mod = zcu.navFileScope(func.owner_nav).mod.?; | 5579 | const mod = zcu.navFileScope(func.owner_nav).mod.?; |
| 5560 | const target = &mod.resolved_target.result; | 5580 | const target = &mod.resolved_target.result; |
| 5561 | const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{ | 5581 | const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{ |
| 5562 | .alignment = switch (nav.resolved.?.@"align") { | 5582 | .alignment = switch (nav.resolved.?.@"align") { |
| 5563 | .none => switch (mod.optimize_mode) { | 5583 | .none => switch (mod.optimize_mode) { |
| 5564 | .debug, | 5584 | .debug, |
| ... | @@ -5587,7 +5607,7 @@ fn updateFuncInner( | ... | @@ -5587,7 +5607,7 @@ fn updateFuncInner( |
| 5587 | }; | 5607 | }; |
| 5588 | 5608 | ||
| 5589 | var nw: MappedFile.Node.Writer = undefined; | 5609 | var nw: MappedFile.Node.Writer = undefined; |
| 5590 | ni.writer(&coff.mf, gpa, &nw); | 5610 | ni.writer(gpa, &coff.mf, &nw); |
| 5591 | defer nw.deinit(); | 5611 | defer nw.deinit(); |
| 5592 | codegen.emitFunction( | 5612 | codegen.emitFunction( |
| 5593 | &coff.base, | 5613 | &coff.base, |
| ... | @@ -5603,10 +5623,13 @@ fn updateFuncInner( | ... | @@ -5603,10 +5623,13 @@ fn updateFuncInner( |
| 5603 | }; | 5623 | }; |
| 5604 | si.get(coff).extra.size = @intCast(nw.interface.end); | 5624 | si.get(coff).extra.size = @intCast(nw.interface.end); |
| 5605 | try si.applyLocationRelocs(coff); | 5625 | try si.applyLocationRelocs(coff); |
| 5626 | |||
| 5627 | // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs. | ||
| 5628 | try coff.genPending(pt); | ||
| 5606 | } | 5629 | } |
| 5607 | 5630 | ||
| 5608 | pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void { | 5631 | pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void { |
| 5609 | coff.flushLazy(pt, .{ | 5632 | coff.genLazyInner(pt, .{ |
| 5610 | .kind = .const_data, | 5633 | .kind = .const_data, |
| 5611 | .index = @intCast(coff.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return), | 5634 | .index = @intCast(coff.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return), |
| 5612 | }) catch |err| switch (err) { | 5635 | }) catch |err| switch (err) { |
| ... | @@ -5863,8 +5886,8 @@ pub fn flush( | ... | @@ -5863,8 +5886,8 @@ pub fn flush( |
| 5863 | 5886 | ||
| 5864 | const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols); | 5887 | const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols); |
| 5865 | coff.symbol_table.ni.resizeLeaf( | 5888 | coff.symbol_table.ni.resizeLeaf( |
| 5866 | &coff.mf, | ||
| 5867 | comp.gpa, | 5889 | comp.gpa, |
| 5890 | &coff.mf, | ||
| 5868 | number_of_symbols * std.coff.Symbol.sizeOf(), | 5891 | number_of_symbols * std.coff.Symbol.sizeOf(), |
| 5869 | ) catch |err| switch (err) { | 5892 | ) catch |err| switch (err) { |
| 5870 | else => |e| return e, | 5893 | else => |e| return e, |
| ... | @@ -5919,22 +5942,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5919,22 +5942,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5919 | }; | 5942 | }; |
| 5920 | break :task; | 5943 | break :task; |
| 5921 | } | 5944 | } |
| 5922 | while (coff.pending_uavs.pop()) |pending_uav| { | ||
| 5923 | const sub_prog_node = coff.idleProgNode(tid, coff.const_prog_node, .{ .uav = pending_uav.key }); | ||
| 5924 | defer sub_prog_node.end(); | ||
| 5925 | coff.flushUav( | ||
| 5926 | .{ .zcu = comp.zcu.?, .tid = tid }, | ||
| 5927 | pending_uav.key, | ||
| 5928 | pending_uav.value.alignment, | ||
| 5929 | ) catch |err| switch (err) { | ||
| 5930 | else => |e| return e, | ||
| 5931 | error.MappedFileIo => return comp.link_diags.fail( | ||
| 5932 | "linker failed to lower constant: {t}", | ||
| 5933 | .{coff.mf.io_err.?}, | ||
| 5934 | ), | ||
| 5935 | }; | ||
| 5936 | break :task; | ||
| 5937 | } | ||
| 5938 | if (coff.pending_input) |pending_iami| { | 5945 | if (coff.pending_input) |pending_iami| { |
| 5939 | const name_slice = pending_iami.member(coff).name.toSlice(coff); | 5946 | const name_slice = pending_iami.member(coff).name.toSlice(coff); |
| 5940 | const sub_prog_node = coff.input_prog_node.start( | 5947 | const sub_prog_node = coff.input_prog_node.start( |
| ... | @@ -5983,33 +5990,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5983,33 +5990,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5983 | }; | 5990 | }; |
| 5984 | break :task; | 5991 | break :task; |
| 5985 | } | 5992 | } |
| 5986 | var lazy_it = coff.lazy.iterator(); | ||
| 5987 | while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) { | ||
| 5988 | const pt: Zcu.PerThread = .{ .zcu = comp.zcu.?, .tid = tid }; | ||
| 5989 | const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index }; | ||
| 5990 | lazy.value.pending_index += 1; | ||
| 5991 | const kind = switch (lmr.kind) { | ||
| 5992 | .code => "code", | ||
| 5993 | .const_data => "data", | ||
| 5994 | }; | ||
| 5995 | var name: [std.Progress.Node.max_name_len]u8 = undefined; | ||
| 5996 | const sub_prog_node = coff.synth_prog_node.start( | ||
| 5997 | std.mem.print(&name, "lazy {s} for {f}", .{ | ||
| 5998 | kind, | ||
| 5999 | Type.fromInterned(lmr.lazySymbol(coff).ty).fmt(pt), | ||
| 6000 | }) catch &name, | ||
| 6001 | 0, | ||
| 6002 | ); | ||
| 6003 | defer sub_prog_node.end(); | ||
| 6004 | coff.flushLazy(pt, lmr) catch |err| switch (err) { | ||
| 6005 | else => |e| return e, | ||
| 6006 | error.MappedFileIo => return comp.link_diags.fail( | ||
| 6007 | "linker failed to lower lazy {s}: {t}", | ||
| 6008 | .{ kind, coff.mf.io_err.? }, | ||
| 6009 | ), | ||
| 6010 | }; | ||
| 6011 | break :task; | ||
| 6012 | }; | ||
| 6013 | if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) { | 5993 | if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) { |
| 6014 | defer coff.symbol_table.pending_symbol_index += 1; | 5994 | defer coff.symbol_table.pending_symbol_index += 1; |
| 6015 | const si = coff.symbol_table.symbols.keys()[coff.symbol_table.pending_symbol_index]; | 5995 | const si = coff.symbol_table.symbols.keys()[coff.symbol_table.pending_symbol_index]; |
| ... | @@ -6025,7 +6005,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -6025,7 +6005,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 6025 | defer sub_prog_node.end(); | 6005 | defer sub_prog_node.end(); |
| 6026 | coff.flushSymbolTableEntry( | 6006 | coff.flushSymbolTableEntry( |
| 6027 | coff.symbol_table.pending_symbol_index, | 6007 | coff.symbol_table.pending_symbol_index, |
| 6028 | .{ .zcu = comp.zcu.?, .tid = tid }, | ||
| 6029 | ) catch |err| switch (err) { | 6008 | ) catch |err| switch (err) { |
| 6030 | error.OutOfMemory => return error.OutOfMemory, | 6009 | error.OutOfMemory => return error.OutOfMemory, |
| 6031 | else => |e| return comp.link_diags.fail( | 6010 | else => |e| return comp.link_diags.fail( |
| ... | @@ -6038,12 +6017,10 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -6038,12 +6017,10 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 6038 | } | 6017 | } |
| 6039 | 6018 | ||
| 6040 | if (coff.section_merge_pending_index < coff.section_merges.count()) return true; | 6019 | if (coff.section_merge_pending_index < coff.section_merges.count()) return true; |
| 6041 | if (coff.pending_uavs.count() > 0) return true; | ||
| 6042 | if (coff.pending_input != null) return true; | 6020 | if (coff.pending_input != null) return true; |
| 6043 | if (coff.exports_complete and coff.globals.count() > coff.global_pending_index) return true; | 6021 | if (coff.exports_complete and coff.globals.count() > coff.global_pending_index) return true; |
| 6044 | assert(!coff.exports_complete or coff.inputs_complete); | 6022 | assert(!coff.exports_complete or coff.inputs_complete); |
| 6045 | if (coff.exports_complete and coff.pending_special_symbol != .none) return true; | 6023 | if (coff.exports_complete and coff.pending_special_symbol != .none) return true; |
| 6046 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; | ||
| 6047 | if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) return true; | 6024 | if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) return true; |
| 6048 | return false; | 6025 | return false; |
| 6049 | } | 6026 | } |
| ... | @@ -6077,17 +6054,18 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -6077,17 +6054,18 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 6077 | }; | 6054 | }; |
| 6078 | break :task; | 6055 | break :task; |
| 6079 | } | 6056 | } |
| 6080 | while (coff.mf.updates.pop()) |ni| { | 6057 | while (coff.mf.updates.pop()) |ni| : (coff.mf.update_prog_node.completeOne()) { |
| 6058 | if (ni.pendingDelete(&coff.mf)) continue; | ||
| 6081 | const clean_moved = ni.cleanMoved(&coff.mf); | 6059 | const clean_moved = ni.cleanMoved(&coff.mf); |
| 6082 | const clean_resized = ni.cleanResized(&coff.mf); | 6060 | const clean_resized = ni.cleanResized(&coff.mf); |
| 6083 | if (clean_moved or clean_resized) { | 6061 | const clean_next_moved = ni.cleanNextMoved(&coff.mf); |
| 6084 | const sub_prog_node = | 6062 | if (!clean_moved and !clean_resized and !clean_next_moved) continue; |
| 6085 | coff.idleProgNode(tid, coff.mf.update_prog_node, coff.getNode(ni)); | 6063 | const sub_prog_node = |
| 6086 | defer sub_prog_node.end(); | 6064 | coff.idleProgNode(tid, coff.mf.update_prog_node, coff.getNode(ni)); |
| 6087 | if (clean_moved) try coff.flushMoved(ni); | 6065 | defer sub_prog_node.end(); |
| 6088 | if (clean_resized) try coff.flushResized(ni); | 6066 | if (clean_moved) try coff.flushMoved(ni); |
| 6089 | break :task; | 6067 | if (clean_resized) try coff.flushResized(ni); |
| 6090 | } else coff.mf.update_prog_node.completeOne(); | 6068 | break :task; |
| 6091 | } | 6069 | } |
| 6092 | while (coff.pending_members.pop()) |pending_mi| { | 6070 | while (coff.pending_members.pop()) |pending_mi| { |
| 6093 | const sub_prog_node = coff.idleProgNode( | 6071 | const sub_prog_node = coff.idleProgNode( |
| ... | @@ -6153,7 +6131,27 @@ fn idleProgNode( | ... | @@ -6153,7 +6131,27 @@ fn idleProgNode( |
| 6153 | }, 0); | 6131 | }, 0); |
| 6154 | } | 6132 | } |
| 6155 | 6133 | ||
| 6156 | fn flushUav( | 6134 | fn genPending(coff: *Coff, pt: Zcu.PerThread) Error!void { |
| 6135 | const comp = pt.zcu.comp; | ||
| 6136 | while (coff.pending_uavs.pop()) |pending_uav| { | ||
| 6137 | const sub_prog_node = coff.idleProgNode(pt.tid, coff.const_prog_node, .{ .uav = pending_uav.key }); | ||
| 6138 | defer sub_prog_node.end(); | ||
| 6139 | coff.genUav(pt, pending_uav.key, pending_uav.value.alignment) catch |err| switch (err) { | ||
| 6140 | else => |e| return e, | ||
| 6141 | error.MappedFileIo => return comp.link_diags.fail( | ||
| 6142 | "linker failed to lower constant: {t}", | ||
| 6143 | .{coff.mf.io_err.?}, | ||
| 6144 | ), | ||
| 6145 | }; | ||
| 6146 | } | ||
| 6147 | var lazy_it = coff.lazy.iterator(); | ||
| 6148 | while (lazy_it.next()) |lazy| while (lazy.value.pending_index < lazy.value.map.count()) { | ||
| 6149 | try coff.genLazy(pt, .{ .kind = lazy.key, .index = lazy.value.pending_index }); | ||
| 6150 | lazy.value.pending_index += 1; | ||
| 6151 | }; | ||
| 6152 | } | ||
| 6153 | |||
| 6154 | fn genUav( | ||
| 6157 | coff: *Coff, | 6155 | coff: *Coff, |
| 6158 | pt: Zcu.PerThread, | 6156 | pt: Zcu.PerThread, |
| 6159 | umi: Node.UavMapIndex, | 6157 | umi: Node.UavMapIndex, |
| ... | @@ -6175,7 +6173,7 @@ fn flushUav( | ... | @@ -6175,7 +6173,7 @@ fn flushUav( |
| 6175 | try coff.nodes.ensureUnusedCapacity(gpa, 1); | 6173 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 6176 | if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1); | 6174 | if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1); |
| 6177 | const sym = si.get(coff); | 6175 | const sym = si.get(coff); |
| 6178 | const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{ | 6176 | const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{ |
| 6179 | .alignment = .fromIp(uav_align), | 6177 | .alignment = .fromIp(uav_align), |
| 6180 | .moved = true, | 6178 | .moved = true, |
| 6181 | }); | 6179 | }); |
| ... | @@ -6204,7 +6202,7 @@ fn flushUav( | ... | @@ -6204,7 +6202,7 @@ fn flushUav( |
| 6204 | }; | 6202 | }; |
| 6205 | 6203 | ||
| 6206 | var nw: MappedFile.Node.Writer = undefined; | 6204 | var nw: MappedFile.Node.Writer = undefined; |
| 6207 | ni.writer(&coff.mf, gpa, &nw); | 6205 | ni.writer(gpa, &coff.mf, &nw); |
| 6208 | defer nw.deinit(); | 6206 | defer nw.deinit(); |
| 6209 | codegen.generateSymbol( | 6207 | codegen.generateSymbol( |
| 6210 | &coff.base, | 6208 | &coff.base, |
| ... | @@ -6311,7 +6309,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6311,7 +6309,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6311 | .{ name, imp_match } | 6309 | .{ name, imp_match } |
| 6312 | else name: { | 6310 | else name: { |
| 6313 | try coff.ensureUnusedStringCapacity(imp_prefix.len + name_slice.len); | 6311 | try coff.ensureUnusedStringCapacity(imp_prefix.len + name_slice.len); |
| 6314 | const imp_name = try std.fmt.allocPrint(gpa, imp_prefix ++ "{s}", .{name_slice}); | 6312 | const imp_name = try gpa.print(imp_prefix ++ "{s}", .{name_slice}); |
| 6315 | defer gpa.free(imp_name); | 6313 | defer gpa.free(imp_name); |
| 6316 | break :name .{ coff.getOrPutStringAssumeCapacity(imp_name), true }; | 6314 | break :name .{ coff.getOrPutStringAssumeCapacity(imp_name), true }; |
| 6317 | }; | 6315 | }; |
| ... | @@ -6468,19 +6466,19 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6468,19 +6466,19 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6468 | if (!gop.found_existing) { | 6466 | if (!gop.found_existing) { |
| 6469 | errdefer _ = coff.import_table.entries.pop(); | 6467 | errdefer _ = coff.import_table.entries.pop(); |
| 6470 | try coff.import_table.ni.resizeLeaf( | 6468 | try coff.import_table.ni.resizeLeaf( |
| 6471 | &coff.mf, | ||
| 6472 | gpa, | 6469 | gpa, |
| 6470 | &coff.mf, | ||
| 6473 | @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2), | 6471 | @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2), |
| 6474 | ); | 6472 | ); |
| 6475 | const import_hint_name_table_len = | 6473 | const import_hint_name_table_len = |
| 6476 | import_hint_name_align.forward(lib_name.len + ".dll".len + 1); | 6474 | import_hint_name_align.forward(lib_name.len + ".dll".len + 1); |
| 6477 | const idata_section_ni = coff.import_table.ni.parent(&coff.mf).unwrap().?; | 6475 | const idata_section_ni = coff.import_table.ni.parent(&coff.mf).unwrap().?; |
| 6478 | const import_lookup_table_ni = try idata_section_ni.addFloatingChild(&coff.mf, gpa, .{ | 6476 | const import_lookup_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{ |
| 6479 | .size = addr_info.size * 2, | 6477 | .size = addr_info.size * 2, |
| 6480 | .alignment = addr_info.alignment, | 6478 | .alignment = addr_info.alignment, |
| 6481 | .moved = true, | 6479 | .moved = true, |
| 6482 | }); | 6480 | }); |
| 6483 | const import_address_table_ni = try idata_section_ni.addFloatingChild(&coff.mf, gpa, .{ | 6481 | const import_address_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{ |
| 6484 | .size = addr_info.size * 2, | 6482 | .size = addr_info.size * 2, |
| 6485 | .alignment = addr_info.alignment, | 6483 | .alignment = addr_info.alignment, |
| 6486 | .moved = true, | 6484 | .moved = true, |
| ... | @@ -6494,7 +6492,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6494,7 +6492,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6494 | import_address_table_sym.section_number = | 6492 | import_address_table_sym.section_number = |
| 6495 | coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number; | 6493 | coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number; |
| 6496 | } | 6494 | } |
| 6497 | const import_hint_name_table_ni = try idata_section_ni.addFloatingChild(&coff.mf, gpa, .{ | 6495 | const import_hint_name_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{ |
| 6498 | .size = import_hint_name_table_len, | 6496 | .size = import_hint_name_table_len, |
| 6499 | .alignment = import_hint_name_align, | 6497 | .alignment = import_hint_name_align, |
| 6500 | .moved = true, | 6498 | .moved = true, |
| ... | @@ -6550,9 +6548,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6550,9 +6548,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6550 | gop.value_ptr.len = import_symbol_index + 1; | 6548 | gop.value_ptr.len = import_symbol_index + 1; |
| 6551 | const new_symbol_table_size = addr_info.size * (import_symbol_index + 2); | 6549 | const new_symbol_table_size = addr_info.size * (import_symbol_index + 2); |
| 6552 | 6550 | ||
| 6553 | try gop.value_ptr.import_lookup_table_ni.resizeLeaf(&coff.mf, gpa, new_symbol_table_size); | 6551 | try gop.value_ptr.import_lookup_table_ni.resizeLeaf(gpa, &coff.mf, new_symbol_table_size); |
| 6554 | const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff); | 6552 | const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff); |
| 6555 | try import_address_table_ni.resizeLeaf(&coff.mf, gpa, new_symbol_table_size); | 6553 | try import_address_table_ni.resizeLeaf(gpa, &coff.mf, new_symbol_table_size); |
| 6556 | 6554 | ||
| 6557 | const opt_imp_name = import.name.toSlice(coff); | 6555 | const opt_imp_name = import.name.toSlice(coff); |
| 6558 | const opt_import_hint_name_index = if (opt_imp_name) |imp_name| blk: { | 6556 | const opt_import_hint_name_index = if (opt_imp_name) |imp_name| blk: { |
| ... | @@ -6560,7 +6558,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6560,7 +6558,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6560 | gop.value_ptr.hint_name_len = @intCast( | 6558 | gop.value_ptr.hint_name_len = @intCast( |
| 6561 | import_hint_name_align.forward(import_hint_name_index + 2 + imp_name.len + 1), | 6559 | import_hint_name_align.forward(import_hint_name_index + 2 + imp_name.len + 1), |
| 6562 | ); | 6560 | ); |
| 6563 | try gop.value_ptr.import_hint_name_table_ni.resizeLeaf(&coff.mf, gpa, gop.value_ptr.hint_name_len); | 6561 | try gop.value_ptr.import_hint_name_table_ni.resizeLeaf(gpa, &coff.mf, gop.value_ptr.hint_name_len); |
| 6564 | break :blk import_hint_name_index; | 6562 | break :blk import_hint_name_index; |
| 6565 | } else null; | 6563 | } else null; |
| 6566 | 6564 | ||
| ... | @@ -6635,7 +6633,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6635,7 +6633,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6635 | else => |tag| @panic(@tagName(tag)), | 6633 | else => |tag| @panic(@tagName(tag)), |
| 6636 | .AMD64 => { | 6634 | .AMD64 => { |
| 6637 | const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }; | 6635 | const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }; |
| 6638 | const ni = try parent_sym.ni.unwrap().?.addFloatingChild(&coff.mf, gpa, .{ | 6636 | const ni = try parent_sym.ni.unwrap().?.addFloatingChild(gpa, &coff.mf, .{ |
| 6639 | .alignment = alignment, | 6637 | .alignment = alignment, |
| 6640 | .size = alignment.forward(init.len), | 6638 | .size = alignment.forward(init.len), |
| 6641 | }); | 6639 | }); |
| ... | @@ -6773,7 +6771,31 @@ fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol { | ... | @@ -6773,7 +6771,31 @@ fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol { |
| 6773 | }; | 6771 | }; |
| 6774 | } | 6772 | } |
| 6775 | 6773 | ||
| 6776 | fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { | 6774 | fn genLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| 6775 | const lazy = lmr.lazySymbol(coff); | ||
| 6776 | if (lazy.ty == .anyerror_type) return; | ||
| 6777 | const kind = switch (lmr.kind) { | ||
| 6778 | .code => "code", | ||
| 6779 | .const_data => "data", | ||
| 6780 | }; | ||
| 6781 | var name: [std.Progress.Node.max_name_len]u8 = undefined; | ||
| 6782 | const sub_prog_node = coff.synth_prog_node.start( | ||
| 6783 | std.mem.print(&name, "lazy {s} for {f}", .{ | ||
| 6784 | kind, | ||
| 6785 | Type.fromInterned(lazy.ty).fmt(pt), | ||
| 6786 | }) catch &name, | ||
| 6787 | 0, | ||
| 6788 | ); | ||
| 6789 | defer sub_prog_node.end(); | ||
| 6790 | coff.genLazyInner(pt, lmr) catch |err| switch (err) { | ||
| 6791 | else => |e| return e, | ||
| 6792 | error.MappedFileIo => return coff.base.comp.link_diags.fail( | ||
| 6793 | "linker failed to lower lazy {s}: {t}", | ||
| 6794 | .{ kind, coff.mf.io_err.? }, | ||
| 6795 | ), | ||
| 6796 | }; | ||
| 6797 | } | ||
| 6798 | fn genLazyInner(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { | ||
| 6777 | const zcu = pt.zcu; | 6799 | const zcu = pt.zcu; |
| 6778 | const gpa = zcu.gpa; | 6800 | const gpa = zcu.gpa; |
| 6779 | 6801 | ||
| ... | @@ -6788,7 +6810,7 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { | ... | @@ -6788,7 +6810,7 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| 6788 | .code => .text, | 6810 | .code => .text, |
| 6789 | .const_data => .rdata, | 6811 | .const_data => .rdata, |
| 6790 | }; | 6812 | }; |
| 6791 | const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{ .moved = true }); | 6813 | const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{ .moved = true }); |
| 6792 | coff.nodes.appendAssumeCapacity(switch (lazy.kind) { | 6814 | coff.nodes.appendAssumeCapacity(switch (lazy.kind) { |
| 6793 | .code => .{ .lazy_code = @fromBackingInt(@intCast(lmr.index)) }, | 6815 | .code => .{ .lazy_code = @fromBackingInt(@intCast(lmr.index)) }, |
| 6794 | .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(lmr.index)) }, | 6816 | .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(lmr.index)) }, |
| ... | @@ -6808,7 +6830,7 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { | ... | @@ -6808,7 +6830,7 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| 6808 | 6830 | ||
| 6809 | var required_alignment: InternPool.Alignment = .none; | 6831 | var required_alignment: InternPool.Alignment = .none; |
| 6810 | var nw: MappedFile.Node.Writer = undefined; | 6832 | var nw: MappedFile.Node.Writer = undefined; |
| 6811 | ni.writer(&coff.mf, gpa, &nw); | 6833 | ni.writer(gpa, &coff.mf, &nw); |
| 6812 | defer nw.deinit(); | 6834 | defer nw.deinit(); |
| 6813 | codegen.generateLazySymbol( | 6835 | codegen.generateLazySymbol( |
| 6814 | &coff.base, | 6836 | &coff.base, |
| ... | @@ -7356,7 +7378,7 @@ fn updateExportInner( | ... | @@ -7356,7 +7378,7 @@ fn updateExportInner( |
| 7356 | pt: Zcu.PerThread, | 7378 | pt: Zcu.PerThread, |
| 7357 | export_index: Zcu.Export.Index, | 7379 | export_index: Zcu.Export.Index, |
| 7358 | alias_syms: *std.array_hash_map.Auto(Symbol.Index, Symbol.Index), | 7380 | alias_syms: *std.array_hash_map.Auto(Symbol.Index, Symbol.Index), |
| 7359 | ) !void { | 7381 | ) Error!void { |
| 7360 | const zcu = pt.zcu; | 7382 | const zcu = pt.zcu; |
| 7361 | const gpa = zcu.gpa; | 7383 | const gpa = zcu.gpa; |
| 7362 | const ip = &zcu.intern_pool; | 7384 | const ip = &zcu.intern_pool; |
| ... | @@ -7380,6 +7402,8 @@ fn updateExportInner( | ... | @@ -7380,6 +7402,8 @@ fn updateExportInner( |
| 7380 | exported_si, | 7402 | exported_si, |
| 7381 | }), | 7403 | }), |
| 7382 | } | 7404 | } |
| 7405 | |||
| 7406 | try coff.genPending(pt); | ||
| 7383 | while (try coff.resolve(pt.tid)) {} | 7407 | while (try coff.resolve(pt.tid)) {} |
| 7384 | while (try coff.idle(pt.tid)) {} | 7408 | while (try coff.idle(pt.tid)) {} |
| 7385 | 7409 | ||
| ... | @@ -7444,7 +7468,7 @@ fn updateExportInner( | ... | @@ -7444,7 +7468,7 @@ fn updateExportInner( |
| 7444 | if (new_name_table_size > std.math.maxInt(@FieldType(ExportTable.Entry, "name_index"))) | 7468 | if (new_name_table_size > std.math.maxInt(@FieldType(ExportTable.Entry, "name_index"))) |
| 7445 | return coff.base.comp.link_diags.fail("exports name table limit reached", .{}); | 7469 | return coff.base.comp.link_diags.fail("exports name table limit reached", .{}); |
| 7446 | 7470 | ||
| 7447 | try coff.export_table.name_table_ni.resizeLeaf(&coff.mf, gpa, new_name_table_size); | 7471 | try coff.export_table.name_table_ni.resizeLeaf(gpa, &coff.mf, new_name_table_size); |
| 7448 | 7472 | ||
| 7449 | const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf); | 7473 | const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf); |
| 7450 | @memcpy(name_table_slice[name_index..][0 .. name.len + 1], name[0 .. name.len + 1]); | 7474 | @memcpy(name_table_slice[name_index..][0 .. name.len + 1], name[0 .. name.len + 1]); |
| ... | @@ -7468,20 +7492,20 @@ fn updateExportInner( | ... | @@ -7468,20 +7492,20 @@ fn updateExportInner( |
| 7468 | // TODO: These should all be resized ahead of time to fit all exports | 7492 | // TODO: These should all be resized ahead of time to fit all exports |
| 7469 | // after https://github.com/ziglang/zig/issues/23616 | 7493 | // after https://github.com/ziglang/zig/issues/23616 |
| 7470 | try coff.export_table.export_address_table_si.node(coff).resizeLeaf( | 7494 | try coff.export_table.export_address_table_si.node(coff).resizeLeaf( |
| 7471 | &coff.mf, | ||
| 7472 | gpa, | 7495 | gpa, |
| 7496 | &coff.mf, | ||
| 7473 | export_count * @sizeOf(std.coff.ExportAddressTableEntry), | 7497 | export_count * @sizeOf(std.coff.ExportAddressTableEntry), |
| 7474 | ); | 7498 | ); |
| 7475 | 7499 | ||
| 7476 | try coff.export_table.name_pointer_table_ni.resizeLeaf( | 7500 | try coff.export_table.name_pointer_table_ni.resizeLeaf( |
| 7477 | &coff.mf, | ||
| 7478 | gpa, | 7501 | gpa, |
| 7502 | &coff.mf, | ||
| 7479 | export_count * @sizeOf(std.coff.ExportNamePointerTableEntry), | 7503 | export_count * @sizeOf(std.coff.ExportNamePointerTableEntry), |
| 7480 | ); | 7504 | ); |
| 7481 | 7505 | ||
| 7482 | try coff.export_table.ordinal_table_ni.resizeLeaf( | 7506 | try coff.export_table.ordinal_table_ni.resizeLeaf( |
| 7483 | &coff.mf, | ||
| 7484 | gpa, | 7507 | gpa, |
| 7508 | &coff.mf, | ||
| 7485 | export_count * @sizeOf(std.coff.ExportOrdinalTableEntry), | 7509 | export_count * @sizeOf(std.coff.ExportOrdinalTableEntry), |
| 7486 | ); | 7510 | ); |
| 7487 | 7511 | ||
| ... | @@ -7519,17 +7543,19 @@ fn updateExportInner( | ... | @@ -7519,17 +7543,19 @@ fn updateExportInner( |
| 7519 | } | 7543 | } |
| 7520 | } | 7544 | } |
| 7521 | 7545 | ||
| 7522 | fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void { | 7546 | fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) Io.File.Writer.Error!void { |
| 7523 | const comp = coff.base.comp; | 7547 | const comp = coff.base.comp; |
| 7524 | const io = comp.io; | 7548 | const io = comp.io; |
| 7525 | var buffer: [512]u8 = undefined; | 7549 | var buffer: [512]u8 = undefined; |
| 7526 | const stderr = try io.lockStderr(&buffer, null); | 7550 | const stderr = try io.lockStderr(&buffer, null); |
| 7527 | defer io.unlockStderr(); | 7551 | defer io.unlockStderr(); |
| 7528 | const w = &stderr.file_writer.interface; | 7552 | const w = &stderr.file_writer.interface; |
| 7529 | _ = try coff.dump(w, tid); | 7553 | _ = coff.dump(w, tid) catch |err| switch (err) { |
| 7554 | error.WriteFailed => return stderr.file_writer.err.?, | ||
| 7555 | }; | ||
| 7530 | } | 7556 | } |
| 7531 | 7557 | ||
| 7532 | pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult { | 7558 | pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) Io.Writer.Error!link.File.DumpResult { |
| 7533 | if (coff.options.enable_link_snapshots) { | 7559 | if (coff.options.enable_link_snapshots) { |
| 7534 | try coff.printNode(tid, w, .root, 0); | 7560 | try coff.printNode(tid, w, .root, 0); |
| 7535 | try w.writeAll("Section table:\n"); | 7561 | try w.writeAll("Section table:\n"); |
| ... | @@ -7544,7 +7570,7 @@ pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpRe | ... | @@ -7544,7 +7570,7 @@ pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpRe |
| 7544 | return .disabled; | 7570 | return .disabled; |
| 7545 | } | 7571 | } |
| 7546 | 7572 | ||
| 7547 | fn printSection(coff: *Coff, w: *Io.Writer, name: String, si: Symbol.Index) !void { | 7573 | fn printSection(coff: *Coff, w: *Io.Writer, name: String, si: Symbol.Index) Io.Writer.Error!void { |
| 7548 | const sym = si.get(coff); | 7574 | const sym = si.get(coff); |
| 7549 | try w.print("{d:0>6}@{d:0>2} {x:08} n{d:0>8} | {s}\n", .{ | 7575 | try w.print("{d:0>6}@{d:0>2} {x:08} n{d:0>8} | {s}\n", .{ |
| 7550 | si, | 7576 | si, |
| ... | @@ -7560,7 +7586,7 @@ fn printSymbol( | ... | @@ -7560,7 +7586,7 @@ fn printSymbol( |
| 7560 | w: *Io.Writer, | 7586 | w: *Io.Writer, |
| 7561 | tid: Zcu.PerThread.Id, | 7587 | tid: Zcu.PerThread.Id, |
| 7562 | si: Symbol.Index, | 7588 | si: Symbol.Index, |
| 7563 | ) !void { | 7589 | ) Io.Writer.Error!void { |
| 7564 | const sym = si.get(coff); | 7590 | const sym = si.get(coff); |
| 7565 | try w.print("{d:0>6}@{d:0>2} {x:08} {s} {s} {s} n{d:0>8}+{x:08}:{s: <26} | {x:08} ", .{ | 7591 | try w.print("{d:0>6}@{d:0>2} {x:08} {s} {s} {s} n{d:0>8}+{x:08}:{s: <26} | {x:08} ", .{ |
| 7566 | si, | 7592 | si, |
| ... | @@ -7622,7 +7648,7 @@ fn printNodeName( | ... | @@ -7622,7 +7648,7 @@ fn printNodeName( |
| 7622 | w: *std.Io.Writer, | 7648 | w: *std.Io.Writer, |
| 7623 | tid: Zcu.PerThread.Id, | 7649 | tid: Zcu.PerThread.Id, |
| 7624 | node: Node, | 7650 | node: Node, |
| 7625 | ) !void { | 7651 | ) Io.Writer.Error!void { |
| 7626 | switch (node) { | 7652 | switch (node) { |
| 7627 | else => {}, | 7653 | else => {}, |
| 7628 | .image_section => |si| try w.print("({s})", .{ | 7654 | .image_section => |si| try w.print("({s})", .{ |
| ... | @@ -7702,7 +7728,7 @@ pub fn printNode( | ... | @@ -7702,7 +7728,7 @@ pub fn printNode( |
| 7702 | w: *Io.Writer, | 7728 | w: *Io.Writer, |
| 7703 | ni: MappedFile.Node.Index, | 7729 | ni: MappedFile.Node.Index, |
| 7704 | indent: usize, | 7730 | indent: usize, |
| 7705 | ) !void { | 7731 | ) Io.Writer.Error!void { |
| 7706 | const node = coff.getNode(ni); | 7732 | const node = coff.getNode(ni); |
| 7707 | try w.splatByteAll(' ', indent); | 7733 | try w.splatByteAll(' ', indent); |
| 7708 | try w.writeAll(@tagName(node)); | 7734 | try w.writeAll(@tagName(node)); |
| ... | @@ -7710,12 +7736,13 @@ pub fn printNode( | ... | @@ -7710,12 +7736,13 @@ pub fn printNode( |
| 7710 | { | 7736 | { |
| 7711 | const mf_node = &coff.mf.nodes.items[@backingInt(ni)]; | 7737 | const mf_node = &coff.mf.nodes.items[@backingInt(ni)]; |
| 7712 | const off, const size = mf_node.location().resolve(&coff.mf); | 7738 | const off, const size = mf_node.location().resolve(&coff.mf); |
| 7713 | try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x} {t}{s}{s}{s}\n", .{ | 7739 | try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x} {t}{s}{s}{s}{s}\n", .{ |
| 7714 | @backingInt(ni), | 7740 | @backingInt(ni), |
| 7715 | off, | 7741 | off, |
| 7716 | size, | 7742 | size, |
| 7717 | mf_node.flags.alignment.toByteUnits(), | 7743 | mf_node.flags.alignment.toByteUnits(), |
| 7718 | mf_node.flags.position, | 7744 | mf_node.flags.position, |
| 7745 | if (mf_node.flags.bubbles_moved) " bubbles_moved" else "", | ||
| 7719 | if (mf_node.flags.moved) " moved" else "", | 7746 | if (mf_node.flags.moved) " moved" else "", |
| 7720 | if (mf_node.flags.resized) " resized" else "", | 7747 | if (mf_node.flags.resized) " resized" else "", |
| 7721 | if (mf_node.flags.has_content) " has_content" else "", | 7748 | if (mf_node.flags.has_content) " has_content" else "", |
| ... | @@ -7730,22 +7757,30 @@ pub fn printNode( | ... | @@ -7730,22 +7757,30 @@ pub fn printNode( |
| 7730 | } | 7757 | } |
| 7731 | return; | 7758 | return; |
| 7732 | } | 7759 | } |
| 7733 | const file_loc = ni.fileLocation(&coff.mf, false); | 7760 | const start_address: usize, const end_address: usize = file_loc: { |
| 7734 | if (file_loc.size == 0) return; | 7761 | const file_loc = ni.fileLocation(&coff.mf, false); |
| 7735 | var address = file_loc.offset; | 7762 | break :file_loc .{ @intCast(file_loc.offset), @intCast(file_loc.offset + file_loc.size) }; |
| 7763 | }; | ||
| 7764 | var address = start_address; | ||
| 7736 | const line_len = 0x10; | 7765 | const line_len = 0x10; |
| 7737 | var line_it = std.mem.window( | 7766 | while (true) : (address = @min(std.mem.alignForward(usize, address + 1, line_len), end_address)) { |
| 7738 | u8, | ||
| 7739 | coff.mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)], | ||
| 7740 | line_len, | ||
| 7741 | line_len, | ||
| 7742 | ); | ||
| 7743 | while (line_it.next()) |line_bytes| : (address += line_len) { | ||
| 7744 | try w.splatByteAll(' ', indent + 1); | 7767 | try w.splatByteAll(' ', indent + 1); |
| 7745 | try w.print("{x:0>8} ", .{address}); | 7768 | try w.print("{x:0>8}", .{address}); |
| 7746 | for (line_bytes) |byte| try w.print("{x:0>2} ", .{byte}); | 7769 | if (address == end_address) break try w.writeByte('\n'); |
| 7747 | try w.splatByteAll(' ', 3 * (line_len - line_bytes.len) + 1); | 7770 | try w.splatByteAll(' ', 2); |
| 7748 | for (line_bytes) |byte| try w.writeByte(if (std.ascii.isPrint(byte)) byte else '.'); | 7771 | const start_byte_address = std.mem.alignBackward(usize, address, line_len); |
| 7772 | const end_byte_address = start_byte_address + line_len; | ||
| 7773 | for (start_byte_address..end_byte_address) |byte_address| | ||
| 7774 | if (byte_address < start_address or byte_address >= end_address) | ||
| 7775 | try w.splatByteAll(' ', 3) | ||
| 7776 | else | ||
| 7777 | try w.print("{x:0>2} ", .{coff.mf.memory_map.memory[byte_address]}); | ||
| 7778 | try w.writeByte(' '); | ||
| 7779 | for (start_byte_address..@min(end_address, end_byte_address)) |byte_address| | ||
| 7780 | try w.writeByte(if (byte_address < start_address or byte_address >= end_address) ' ' else char: { | ||
| 7781 | const byte = coff.mf.memory_map.memory[byte_address]; | ||
| 7782 | break :char if (std.ascii.isPrint(byte)) byte else '.'; | ||
| 7783 | }); | ||
| 7749 | try w.writeByte('\n'); | 7784 | try w.writeByte('\n'); |
| 7750 | } | 7785 | } |
| 7751 | } | 7786 | } |
src/link/ConstPool.zig+38-12| ... | @@ -45,10 +45,22 @@ pub const Index = enum(u32) { | ... | @@ -45,10 +45,22 @@ pub const Index = enum(u32) { |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | pub const User = union(enum) { | 47 | pub const User = union(enum) { |
| 48 | dwarf: *@import("Dwarf.zig"), | 48 | elf: *@import("Dwarf.zig"), |
| 49 | elf2: *@import("Elf2.zig"), | ||
| 50 | macho: *@import("Dwarf.zig"), | ||
| 49 | c: *@import("C.zig"), | 51 | c: *@import("C.zig"), |
| 50 | llvm: @import("../codegen/llvm.zig").Object.Ptr, | 52 | llvm: @import("../codegen/llvm.zig").Object.Ptr, |
| 51 | 53 | ||
| 54 | fn devFeature(tag: @typeInfo(User).@"union".tag_type.?) dev.Feature { | ||
| 55 | return switch (tag) { | ||
| 56 | .elf => .elf_linker, | ||
| 57 | .elf2 => .elf2_linker, | ||
| 58 | .macho => .macho_linker, | ||
| 59 | .c => .c_linker, | ||
| 60 | .llvm => .llvm_backend, | ||
| 61 | }; | ||
| 62 | } | ||
| 63 | |||
| 52 | /// Inform the debug info implementation that the new constant `val` was added to the pool at | 64 | /// Inform the debug info implementation that the new constant `val` was added to the pool at |
| 53 | /// the given index (which equals the current pool length) due to a `get` call. It is guaranteed | 65 | /// the given index (which equals the current pool length) due to a `get` call. It is guaranteed |
| 54 | /// that there will eventually be a call to either `updateConst` or `updateConstIncomplete` | 66 | /// that there will eventually be a call to either `updateConst` or `updateConstIncomplete` |
| ... | @@ -58,9 +70,12 @@ pub const User = union(enum) { | ... | @@ -58,9 +70,12 @@ pub const User = union(enum) { |
| 58 | pt: Zcu.PerThread, | 70 | pt: Zcu.PerThread, |
| 59 | index: Index, | 71 | index: Index, |
| 60 | val: InternPool.Index, | 72 | val: InternPool.Index, |
| 61 | ) Allocator.Error!void { | 73 | ) link.Error!void { |
| 62 | switch (user) { | 74 | switch (user) { |
| 63 | inline else => |impl| return impl.addConst(pt, index, val), | 75 | inline else => |impl, tag| { |
| 76 | dev.check(devFeature(tag)); | ||
| 77 | return impl.addConst(pt, index, val); | ||
| 78 | }, | ||
| 64 | } | 79 | } |
| 65 | } | 80 | } |
| 66 | 81 | ||
| ... | @@ -73,9 +88,12 @@ pub const User = union(enum) { | ... | @@ -73,9 +88,12 @@ pub const User = union(enum) { |
| 73 | pt: Zcu.PerThread, | 88 | pt: Zcu.PerThread, |
| 74 | index: Index, | 89 | index: Index, |
| 75 | val: InternPool.Index, | 90 | val: InternPool.Index, |
| 76 | ) Allocator.Error!void { | 91 | ) link.Error!void { |
| 77 | switch (user) { | 92 | switch (user) { |
| 78 | inline else => |impl| return impl.updateConst(pt, index, val), | 93 | inline else => |impl, tag| { |
| 94 | dev.check(devFeature(tag)); | ||
| 95 | return impl.updateConst(pt, index, val); | ||
| 96 | }, | ||
| 79 | } | 97 | } |
| 80 | } | 98 | } |
| 81 | 99 | ||
| ... | @@ -89,9 +107,12 @@ pub const User = union(enum) { | ... | @@ -89,9 +107,12 @@ pub const User = union(enum) { |
| 89 | pt: Zcu.PerThread, | 107 | pt: Zcu.PerThread, |
| 90 | index: Index, | 108 | index: Index, |
| 91 | val: InternPool.Index, | 109 | val: InternPool.Index, |
| 92 | ) Allocator.Error!void { | 110 | ) link.Error!void { |
| 93 | switch (user) { | 111 | switch (user) { |
| 94 | inline else => |impl| return impl.updateConstIncomplete(pt, index, val), | 112 | inline else => |impl, tag| { |
| 113 | dev.check(devFeature(tag)); | ||
| 114 | return impl.updateConstIncomplete(pt, index, val); | ||
| 115 | }, | ||
| 95 | } | 116 | } |
| 96 | } | 117 | } |
| 97 | }; | 118 | }; |
| ... | @@ -128,12 +149,12 @@ pub fn updateContainerType( | ... | @@ -128,12 +149,12 @@ pub fn updateContainerType( |
| 128 | user: User, | 149 | user: User, |
| 129 | container_ty: InternPool.Index, | 150 | container_ty: InternPool.Index, |
| 130 | success: bool, | 151 | success: bool, |
| 131 | ) Allocator.Error!void { | 152 | ) link.Error!void { |
| 132 | if (success) { | 153 | if (success) { |
| 133 | const gpa = pt.zcu.comp.gpa; | 154 | const gpa = pt.zcu.comp.gpa; |
| 134 | try pool.complete_containers.put(gpa, container_ty, {}); | 155 | try pool.complete_containers.put(gpa, container_ty, {}); |
| 135 | } else { | 156 | } else { |
| 136 | _ = pool.complete_containers.fetchSwapRemove(container_ty); | 157 | _ = pool.complete_containers.swapRemove(container_ty); |
| 137 | } | 158 | } |
| 138 | var opt_dep = pool.container_deps.get(container_ty); | 159 | var opt_dep = pool.container_deps.get(container_ty); |
| 139 | while (opt_dep) |dep| : (opt_dep = dep.ptr(pool).next.unwrap()) { | 160 | while (opt_dep) |dep| : (opt_dep = dep.ptr(pool).next.unwrap()) { |
| ... | @@ -143,7 +164,7 @@ pub fn updateContainerType( | ... | @@ -143,7 +164,7 @@ pub fn updateContainerType( |
| 143 | 164 | ||
| 144 | /// After this is called, there may be a constant for which debug information (complete or not) has | 165 | /// After this is called, there may be a constant for which debug information (complete or not) has |
| 145 | /// not yet been emitted, so the user must call `flushPending` at some point after this call. | 166 | /// not yet been emitted, so the user must call `flushPending` at some point after this call. |
| 146 | pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) Allocator.Error!ConstPool.Index { | 167 | pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) link.Error!ConstPool.Index { |
| 147 | const zcu = pt.zcu; | 168 | const zcu = pt.zcu; |
| 148 | const ip = &zcu.intern_pool; | 169 | const ip = &zcu.intern_pool; |
| 149 | const gpa = zcu.comp.gpa; | 170 | const gpa = zcu.comp.gpa; |
| ... | @@ -160,13 +181,16 @@ pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Inde | ... | @@ -160,13 +181,16 @@ pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Inde |
| 160 | } | 181 | } |
| 161 | return index; | 182 | return index; |
| 162 | } | 183 | } |
| 163 | pub fn flushPending(pool: *ConstPool, pt: Zcu.PerThread, user: User) Allocator.Error!void { | 184 | pub fn getIfExists(pool: *ConstPool, val: InternPool.Index) ?ConstPool.Index { |
| 185 | return @fromBackingInt(@intCast(pool.values.getIndex(val) orelse return null)); | ||
| 186 | } | ||
| 187 | pub fn flushPending(pool: *ConstPool, pt: Zcu.PerThread, user: User) link.Error!void { | ||
| 164 | while (pool.pending.pop()) |pending_ty| { | 188 | while (pool.pending.pop()) |pending_ty| { |
| 165 | try pool.update(pt, user, pending_ty); | 189 | try pool.update(pt, user, pending_ty); |
| 166 | } | 190 | } |
| 167 | } | 191 | } |
| 168 | 192 | ||
| 169 | fn update(pool: *ConstPool, pt: Zcu.PerThread, user: User, index: ConstPool.Index) Allocator.Error!void { | 193 | fn update(pool: *ConstPool, pt: Zcu.PerThread, user: User, index: ConstPool.Index) link.Error!void { |
| 170 | const zcu = pt.zcu; | 194 | const zcu = pt.zcu; |
| 171 | const ip = &zcu.intern_pool; | 195 | const ip = &zcu.intern_pool; |
| 172 | const val = index.val(pool); | 196 | const val = index.val(pool); |
| ... | @@ -285,6 +309,8 @@ fn registerTypeDeps(pool: *ConstPool, root: Index, ty: Type, zcu: *const Zcu) Al | ... | @@ -285,6 +309,8 @@ fn registerTypeDeps(pool: *ConstPool, root: Index, ty: Type, zcu: *const Zcu) Al |
| 285 | const std = @import("std"); | 309 | const std = @import("std"); |
| 286 | const Allocator = std.mem.Allocator; | 310 | const Allocator = std.mem.Allocator; |
| 287 | 311 | ||
| 312 | const dev = @import("../dev.zig"); | ||
| 288 | const InternPool = @import("../InternPool.zig"); | 313 | const InternPool = @import("../InternPool.zig"); |
| 314 | const link = @import("../link.zig"); | ||
| 289 | const Type = @import("../Type.zig"); | 315 | const Type = @import("../Type.zig"); |
| 290 | const Zcu = @import("../Zcu.zig"); | 316 | const Zcu = @import("../Zcu.zig"); |
src/link/Dwarf.zig+135-121| ... | @@ -122,7 +122,7 @@ const DebugFrame = struct { | ... | @@ -122,7 +122,7 @@ const DebugFrame = struct { |
| 122 | uleb128Bytes(1) + 1, | 122 | uleb128Bytes(1) + 1, |
| 123 | } + switch (target.cpu.arch) { | 123 | } + switch (target.cpu.arch) { |
| 124 | .x86_64 => len: { | 124 | .x86_64 => len: { |
| 125 | dev.check(.x86_64_backend); | 125 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 126 | const Register = @import("../codegen/x86_64/bits.zig").Register; | 126 | const Register = @import("../codegen/x86_64/bits.zig").Register; |
| 127 | break :len uleb128Bytes(1) + sleb128Bytes(-8) + uleb128Bytes(Register.rip.dwarfNum()) + | 127 | break :len uleb128Bytes(1) + sleb128Bytes(-8) + uleb128Bytes(Register.rip.dwarfNum()) + |
| 128 | 1 + uleb128Bytes(Register.rsp.dwarfNum()) + sleb128Bytes(-1) + | 128 | 1 + uleb128Bytes(Register.rsp.dwarfNum()) + sleb128Bytes(-1) + |
| ... | @@ -1626,15 +1626,25 @@ pub const WipNav = struct { | ... | @@ -1626,15 +1626,25 @@ pub const WipNav = struct { |
| 1626 | wip_nav.any_children = true; | 1626 | wip_nav.any_children = true; |
| 1627 | } | 1627 | } |
| 1628 | 1628 | ||
| 1629 | pub fn advancePCAndLine(wip_nav: *WipNav, delta_line: i33, delta_pc: u64) Allocator.Error!void { | 1629 | pub fn advanceLineAndPc( |
| 1630 | return wip_nav.advancePCAndLineWriterError(delta_line, delta_pc) catch |err| switch (err) { | 1630 | wip_nav: *WipNav, |
| 1631 | delta_line: i33, | ||
| 1632 | delta_pc: u64, | ||
| 1633 | end: bool, | ||
| 1634 | ) Allocator.Error!void { | ||
| 1635 | return wip_nav.advanceLineAndPcWriterError( | ||
| 1636 | delta_line, | ||
| 1637 | delta_pc, | ||
| 1638 | end, | ||
| 1639 | ) catch |err| switch (err) { | ||
| 1631 | error.WriteFailed => error.OutOfMemory, | 1640 | error.WriteFailed => error.OutOfMemory, |
| 1632 | }; | 1641 | }; |
| 1633 | } | 1642 | } |
| 1634 | fn advancePCAndLineWriterError( | 1643 | fn advanceLineAndPcWriterError( |
| 1635 | wip_nav: *WipNav, | 1644 | wip_nav: *WipNav, |
| 1636 | delta_line: i33, | 1645 | delta_line: i33, |
| 1637 | delta_pc: u64, | 1646 | delta_pc: u64, |
| 1647 | end: bool, | ||
| 1638 | ) Writer.Error!void { | 1648 | ) Writer.Error!void { |
| 1639 | const dlw = &wip_nav.debug_line.writer; | 1649 | const dlw = &wip_nav.debug_line.writer; |
| 1640 | 1650 | ||
| ... | @@ -1654,20 +1664,30 @@ pub const WipNav = struct { | ... | @@ -1654,20 +1664,30 @@ pub const WipNav = struct { |
| 1654 | const op_advance = @divExact(delta_pc, header.minimum_instruction_length) * | 1664 | const op_advance = @divExact(delta_pc, header.minimum_instruction_length) * |
| 1655 | header.maximum_operations_per_instruction + delta_op; | 1665 | header.maximum_operations_per_instruction + delta_op; |
| 1656 | const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range; | 1666 | const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range; |
| 1657 | const remaining_op_advance: u8 = @intCast(if (op_advance >= 2 * max_op_advance) remaining: { | 1667 | const remaining_op_advance: u8 = @intCast(if (end or |
| 1658 | try dlw.writeByte(DW.LNS.advance_pc); | 1668 | op_advance >= 2 * max_op_advance) |
| 1659 | try dlw.writeUleb128(op_advance); | 1669 | remaining: { |
| 1670 | if (op_advance == max_op_advance) { | ||
| 1671 | try dlw.writeByte(DW.LNS.const_add_pc); | ||
| 1672 | } else if (op_advance != 0) { | ||
| 1673 | try dlw.writeByte(DW.LNS.advance_pc); | ||
| 1674 | try dlw.writeUleb128(op_advance); | ||
| 1675 | } else assert(end); | ||
| 1660 | break :remaining 0; | 1676 | break :remaining 0; |
| 1661 | } else if (op_advance >= max_op_advance) remaining: { | 1677 | } else if (op_advance >= max_op_advance) remaining: { |
| 1662 | try dlw.writeByte(DW.LNS.const_add_pc); | 1678 | try dlw.writeByte(DW.LNS.const_add_pc); |
| 1663 | break :remaining op_advance - max_op_advance; | 1679 | break :remaining op_advance - max_op_advance; |
| 1664 | } else op_advance); | 1680 | } else op_advance); |
| 1665 | 1681 | ||
| 1666 | if (remaining_delta_line == 0 and remaining_op_advance == 0) | 1682 | if (remaining_delta_line != 0 or remaining_op_advance != 0) { |
| 1667 | try dlw.writeByte(DW.LNS.copy) | 1683 | assert(!end); |
| 1668 | else | ||
| 1669 | try dlw.writeByte(@intCast((remaining_delta_line - header.line_base) + | 1684 | try dlw.writeByte(@intCast((remaining_delta_line - header.line_base) + |
| 1670 | (header.line_range * remaining_op_advance) + header.opcode_base)); | 1685 | (header.line_range * remaining_op_advance) + header.opcode_base)); |
| 1686 | } else if (end) { | ||
| 1687 | try dlw.writeByte(DW.LNS.extended_op); | ||
| 1688 | try dlw.writeUleb128(1); | ||
| 1689 | try dlw.writeByte(DW.LNE.end_sequence); | ||
| 1690 | } else try dlw.writeByte(DW.LNS.copy); | ||
| 1671 | } | 1691 | } |
| 1672 | 1692 | ||
| 1673 | pub fn setColumn(wip_nav: *WipNav, column: u32) Allocator.Error!void { | 1693 | pub fn setColumn(wip_nav: *WipNav, column: u32) Allocator.Error!void { |
| ... | @@ -1990,7 +2010,7 @@ pub const WipNav = struct { | ... | @@ -1990,7 +2010,7 @@ pub const WipNav = struct { |
| 1990 | try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); | 2010 | try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); |
| 1991 | } | 2011 | } |
| 1992 | } = .{ .wip_nav = wip_nav }; | 2012 | } = .{ .wip_nav = wip_nav }; |
| 1993 | try adapter.writer().writeUleb128(counter.dw.count + counter.dw.writer.end); | 2013 | try adapter.writer().writeUleb128(counter.dw.fullCount()); |
| 1994 | try loc.write(adapter); | 2014 | try loc.write(adapter); |
| 1995 | } | 2015 | } |
| 1996 | 2016 | ||
| ... | @@ -2032,7 +2052,7 @@ pub const WipNav = struct { | ... | @@ -2032,7 +2052,7 @@ pub const WipNav = struct { |
| 2032 | try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0); | 2052 | try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0); |
| 2033 | } | 2053 | } |
| 2034 | } = .{ .wip_nav = wip_nav }; | 2054 | } = .{ .wip_nav = wip_nav }; |
| 2035 | try adapter.writer().writeUleb128(counter.dw.count + counter.dw.writer.end); | 2055 | try adapter.writer().writeUleb128(counter.dw.fullCount()); |
| 2036 | try loc.write(adapter); | 2056 | try loc.write(adapter); |
| 2037 | } | 2057 | } |
| 2038 | 2058 | ||
| ... | @@ -2072,7 +2092,7 @@ pub const WipNav = struct { | ... | @@ -2072,7 +2092,7 @@ pub const WipNav = struct { |
| 2072 | assert(value.typeOf(wip_nav.pt.zcu).comptimeOnly(wip_nav.pt.zcu)); | 2092 | assert(value.typeOf(wip_nav.pt.zcu).comptimeOnly(wip_nav.pt.zcu)); |
| 2073 | } | 2093 | } |
| 2074 | const dwarf = wip_nav.dwarf; | 2094 | const dwarf = wip_nav.dwarf; |
| 2075 | const index = try dwarf.const_pool.get(wip_nav.pt, .{ .dwarf = dwarf }, value.toIntern()); | 2095 | const index = try dwarf.const_pool.get(wip_nav.pt, dwarf.constPoolUser(), value.toIntern()); |
| 2076 | return dwarf.values.items[@backingInt(index)]; | 2096 | return dwarf.values.items[@backingInt(index)]; |
| 2077 | } | 2097 | } |
| 2078 | 2098 | ||
| ... | @@ -2105,20 +2125,20 @@ pub const WipNav = struct { | ... | @@ -2105,20 +2125,20 @@ pub const WipNav = struct { |
| 2105 | const size = ty.abiSize(wip_nav.pt.zcu); | 2125 | const size = ty.abiSize(wip_nav.pt.zcu); |
| 2106 | try diw.writeUleb128(size); | 2126 | try diw.writeUleb128(size); |
| 2107 | if (size == 0) return; | 2127 | if (size == 0) return; |
| 2108 | const old_end = wip_nav.debug_info.writer.end; | 2128 | const old_end = diw.end; |
| 2109 | try codegen.generateSymbol( | 2129 | try codegen.generateSymbol( |
| 2110 | wip_nav.dwarf.bin_file, | 2130 | wip_nav.dwarf.bin_file, |
| 2111 | wip_nav.pt, | 2131 | wip_nav.pt, |
| 2112 | val, | 2132 | val, |
| 2113 | &wip_nav.debug_info.writer, | 2133 | diw, |
| 2114 | .{ .debug_output = .{ .dwarf = wip_nav } }, | 2134 | .{ .debug_output = .{ .dwarf = wip_nav } }, |
| 2115 | ); | 2135 | ); |
| 2116 | if (old_end + size != wip_nav.debug_info.writer.end) { | 2136 | if (old_end + size != diw.end) { |
| 2117 | std.debug.print("{f} [{}]: {} != {}\n", .{ | 2137 | std.debug.print("{f} [{}]: {} != {}\n", .{ |
| 2118 | ty.fmt(wip_nav.pt), | 2138 | ty.fmt(wip_nav.pt), |
| 2119 | ty.toIntern(), | 2139 | ty.toIntern(), |
| 2120 | size, | 2140 | size, |
| 2121 | wip_nav.debug_info.writer.end - old_end, | 2141 | diw.end - old_end, |
| 2122 | }); | 2142 | }); |
| 2123 | unreachable; | 2143 | unreachable; |
| 2124 | } | 2144 | } |
| ... | @@ -2182,7 +2202,7 @@ pub const WipNav = struct { | ... | @@ -2182,7 +2202,7 @@ pub const WipNav = struct { |
| 2182 | wip_nav: *WipNav, | 2202 | wip_nav: *WipNav, |
| 2183 | abbrev_code: struct { | 2203 | abbrev_code: struct { |
| 2184 | decl: AbbrevCode, | 2204 | decl: AbbrevCode, |
| 2185 | generic_decl: AbbrevCode, | 2205 | decl_specification: AbbrevCode, |
| 2186 | decl_instance: AbbrevCode, | 2206 | decl_instance: AbbrevCode, |
| 2187 | }, | 2207 | }, |
| 2188 | nav: *const InternPool.Nav, | 2208 | nav: *const InternPool.Nav, |
| ... | @@ -2196,11 +2216,11 @@ pub const WipNav = struct { | ... | @@ -2196,11 +2216,11 @@ pub const WipNav = struct { |
| 2196 | 2216 | ||
| 2197 | const orig_entry = wip_nav.entry; | 2217 | const orig_entry = wip_nav.entry; |
| 2198 | defer wip_nav.entry = orig_entry; | 2218 | defer wip_nav.entry = orig_entry; |
| 2199 | const parent_type, const is_generic_decl = if (nav.analysis) |analysis| parent_info: { | 2219 | const parent_type, const is_specification = if (nav.analysis) |analysis| parent_info: { |
| 2200 | const parent_type: Type = .fromInterned(zcu.namespacePtr(analysis.namespace).owner_type); | 2220 | const parent_type: Type = .fromInterned(zcu.namespacePtr(analysis.namespace).owner_type); |
| 2201 | const decl_gop = try dwarf.decls.getOrPut(dwarf.gpa, analysis.zir_index); | 2221 | const decl_gop = try dwarf.decls.getOrPut(dwarf.gpa, analysis.zir_index); |
| 2202 | errdefer _ = if (!decl_gop.found_existing) dwarf.decls.pop(); | 2222 | errdefer _ = if (!decl_gop.found_existing) dwarf.decls.pop(); |
| 2203 | const was_generic_decl = decl_gop.found_existing and | 2223 | const was_specification = decl_gop.found_existing and |
| 2204 | switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, decl_gop.value_ptr.*)) { | 2224 | switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, decl_gop.value_ptr.*)) { |
| 2205 | .null, | 2225 | .null, |
| 2206 | .decl_alias, | 2226 | .decl_alias, |
| ... | @@ -2222,9 +2242,9 @@ pub const WipNav = struct { | ... | @@ -2222,9 +2242,9 @@ pub const WipNav = struct { |
| 2222 | .decl_extern_nullary_func, | 2242 | .decl_extern_nullary_func, |
| 2223 | .decl_extern_func, | 2243 | .decl_extern_func, |
| 2224 | => false, | 2244 | => false, |
| 2225 | .generic_decl_var, | 2245 | .decl_specification_var, |
| 2226 | .generic_decl_const, | 2246 | .decl_specification_const, |
| 2227 | .generic_decl_func, | 2247 | .decl_specification_func, |
| 2228 | => true, | 2248 | => true, |
| 2229 | 2249 | ||
| 2230 | // This comes from a decl which was previously generated as an incomplete value | 2250 | // This comes from a decl which was previously generated as an incomplete value |
| ... | @@ -2235,11 +2255,11 @@ pub const WipNav = struct { | ... | @@ -2235,11 +2255,11 @@ pub const WipNav = struct { |
| 2235 | else => |t| std.debug.panic("bad decl abbrev code: {t}", .{t}), | 2255 | else => |t| std.debug.panic("bad decl abbrev code: {t}", .{t}), |
| 2236 | }; | 2256 | }; |
| 2237 | if (parent_type.getCaptures(zcu).len == 0) { | 2257 | if (parent_type.getCaptures(zcu).len == 0) { |
| 2238 | if (was_generic_decl) try dwarf.freeCommonEntry(wip_nav.unit, decl_gop.value_ptr.*); | 2258 | if (was_specification) try dwarf.freeCommonEntry(wip_nav.unit, decl_gop.value_ptr.*); |
| 2239 | decl_gop.value_ptr.* = orig_entry; | 2259 | decl_gop.value_ptr.* = orig_entry; |
| 2240 | break :parent_info .{ parent_type, false }; | 2260 | break :parent_info .{ parent_type, false }; |
| 2241 | } else { | 2261 | } else { |
| 2242 | if (was_generic_decl) | 2262 | if (was_specification) |
| 2243 | dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(decl_gop.value_ptr.*).clear() | 2263 | dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(decl_gop.value_ptr.*).clear() |
| 2244 | else | 2264 | else |
| 2245 | decl_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); | 2265 | decl_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); |
| ... | @@ -2248,8 +2268,8 @@ pub const WipNav = struct { | ... | @@ -2248,8 +2268,8 @@ pub const WipNav = struct { |
| 2248 | } | 2268 | } |
| 2249 | } else .{ null, false }; | 2269 | } else .{ null, false }; |
| 2250 | 2270 | ||
| 2251 | try wip_nav.abbrevCode(if (is_generic_decl) abbrev_code.generic_decl else abbrev_code.decl); | 2271 | try wip_nav.abbrevCode(if (is_specification) abbrev_code.decl_specification else abbrev_code.decl); |
| 2252 | try wip_nav.refType((if (is_generic_decl) null else parent_type) orelse | 2272 | try wip_nav.refType((if (is_specification) null else parent_type) orelse |
| 2253 | .fromInterned(zcu.fileRootType(file))); | 2273 | .fromInterned(zcu.fileRootType(file))); |
| 2254 | assert(diw.end == DebugInfo.declEntryLineOff(dwarf)); | 2274 | assert(diw.end == DebugInfo.declEntryLineOff(dwarf)); |
| 2255 | try diw.writeInt(u32, decl.src_line + 1, dwarf.endian); | 2275 | try diw.writeInt(u32, decl.src_line + 1, dwarf.endian); |
| ... | @@ -2257,14 +2277,14 @@ pub const WipNav = struct { | ... | @@ -2257,14 +2277,14 @@ pub const WipNav = struct { |
| 2257 | try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | 2277 | try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); |
| 2258 | try wip_nav.strp(nav.name.toSlice(ip)); | 2278 | try wip_nav.strp(nav.name.toSlice(ip)); |
| 2259 | 2279 | ||
| 2260 | if (!is_generic_decl) return; | 2280 | if (!is_specification) return; |
| 2261 | const generic_decl_entry = wip_nav.entry; | 2281 | const specification_entry = wip_nav.entry; |
| 2262 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.written()); | 2282 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, specification_entry, dwarf, wip_nav.debug_info.written()); |
| 2263 | wip_nav.debug_info.clearRetainingCapacity(); | 2283 | wip_nav.debug_info.clearRetainingCapacity(); |
| 2264 | wip_nav.entry = orig_entry; | 2284 | wip_nav.entry = orig_entry; |
| 2265 | try wip_nav.abbrevCode(abbrev_code.decl_instance); | 2285 | try wip_nav.abbrevCode(abbrev_code.decl_instance); |
| 2266 | try wip_nav.refType(parent_type.?); | 2286 | try wip_nav.refType(parent_type.?); |
| 2267 | try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, generic_decl_entry, 0); | 2287 | try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, specification_entry, 0); |
| 2268 | } | 2288 | } |
| 2269 | }; | 2289 | }; |
| 2270 | 2290 | ||
| ... | @@ -2278,10 +2298,9 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -2278,10 +2298,9 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 2278 | 2298 | ||
| 2279 | pub fn init(lf: *link.File, format: DW.Format) Dwarf { | 2299 | pub fn init(lf: *link.File, format: DW.Format) Dwarf { |
| 2280 | const comp = lf.comp; | 2300 | const comp = lf.comp; |
| 2281 | const gpa = comp.gpa; | ||
| 2282 | const target = &comp.root_mod.resolved_target.result; | 2301 | const target = &comp.root_mod.resolved_target.result; |
| 2283 | return .{ | 2302 | return .{ |
| 2284 | .gpa = gpa, | 2303 | .gpa = comp.gpa, |
| 2285 | .bin_file = lf, | 2304 | .bin_file = lf, |
| 2286 | .format = format, | 2305 | .format = format, |
| 2287 | .address_size = switch (target.ptrBitWidth()) { | 2306 | .address_size = switch (target.ptrBitWidth()) { |
| ... | @@ -2566,7 +2585,7 @@ pub fn initWipNav( | ... | @@ -2566,7 +2585,7 @@ pub fn initWipNav( |
| 2566 | pt: Zcu.PerThread, | 2585 | pt: Zcu.PerThread, |
| 2567 | nav_index: InternPool.Nav.Index, | 2586 | nav_index: InternPool.Nav.Index, |
| 2568 | sym_index: link.File.SymbolId, | 2587 | sym_index: link.File.SymbolId, |
| 2569 | ) error{ OutOfMemory, AlreadyReported }!WipNav { | 2588 | ) link.Error!WipNav { |
| 2570 | return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) { | 2589 | return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) { |
| 2571 | error.OutOfMemory => error.OutOfMemory, | 2590 | error.OutOfMemory => error.OutOfMemory, |
| 2572 | else => |e| pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}), | 2591 | else => |e| pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}), |
| ... | @@ -2661,11 +2680,11 @@ fn initWipNavInner( | ... | @@ -2661,11 +2680,11 @@ fn initWipNavInner( |
| 2661 | const diw = &wip_nav.debug_info.writer; | 2680 | const diw = &wip_nav.debug_info.writer; |
| 2662 | try wip_nav.declCommon(if (func_type.param_types.len > 0 or func_type.is_var_args) .{ | 2681 | try wip_nav.declCommon(if (func_type.param_types.len > 0 or func_type.is_var_args) .{ |
| 2663 | .decl = .decl_extern_func, | 2682 | .decl = .decl_extern_func, |
| 2664 | .generic_decl = .generic_decl_func, | 2683 | .decl_specification = .decl_specification_func, |
| 2665 | .decl_instance = .decl_instance_extern_func, | 2684 | .decl_instance = .decl_instance_extern_func, |
| 2666 | } else .{ | 2685 | } else .{ |
| 2667 | .decl = .decl_extern_nullary_func, | 2686 | .decl = .decl_extern_nullary_func, |
| 2668 | .generic_decl = .generic_decl_func, | 2687 | .decl_specification = .decl_specification_func, |
| 2669 | .decl_instance = .decl_instance_extern_nullary_func, | 2688 | .decl_instance = .decl_instance_extern_nullary_func, |
| 2670 | }, &nav, inst_info.file, &decl); | 2689 | }, &nav, inst_info.file, &decl); |
| 2671 | try wip_nav.strp(@"extern".name.toSlice(ip)); | 2690 | try wip_nav.strp(@"extern".name.toSlice(ip)); |
| ... | @@ -2686,7 +2705,7 @@ fn initWipNavInner( | ... | @@ -2686,7 +2705,7 @@ fn initWipNavInner( |
| 2686 | .func => |func| if (func.owner_nav != nav_index) { | 2705 | .func => |func| if (func.owner_nav != nav_index) { |
| 2687 | try wip_nav.declCommon(.{ | 2706 | try wip_nav.declCommon(.{ |
| 2688 | .decl = .decl_alias, | 2707 | .decl = .decl_alias, |
| 2689 | .generic_decl = .generic_decl_const, | 2708 | .decl_specification = .decl_specification_const, |
| 2690 | .decl_instance = .decl_instance_alias, | 2709 | .decl_instance = .decl_instance_alias, |
| 2691 | }, &nav, inst_info.file, &decl); | 2710 | }, &nav, inst_info.file, &decl); |
| 2692 | try wip_nav.refNav(func.owner_nav); | 2711 | try wip_nav.refNav(func.owner_nav); |
| ... | @@ -2739,7 +2758,7 @@ fn initWipNavInner( | ... | @@ -2739,7 +2758,7 @@ fn initWipNavInner( |
| 2739 | const diw = &wip_nav.debug_info.writer; | 2758 | const diw = &wip_nav.debug_info.writer; |
| 2740 | try wip_nav.declCommon(.{ | 2759 | try wip_nav.declCommon(.{ |
| 2741 | .decl = .decl_func, | 2760 | .decl = .decl_func, |
| 2742 | .generic_decl = .generic_decl_func, | 2761 | .decl_specification = .decl_specification_func, |
| 2743 | .decl_instance = .decl_instance_func, | 2762 | .decl_instance = .decl_instance_func, |
| 2744 | }, &nav, inst_info.file, &decl); | 2763 | }, &nav, inst_info.file, &decl); |
| 2745 | try wip_nav.strp(switch (decl.linkage) { | 2764 | try wip_nav.strp(switch (decl.linkage) { |
| ... | @@ -2774,7 +2793,7 @@ fn initWipNavInner( | ... | @@ -2774,7 +2793,7 @@ fn initWipNavInner( |
| 2774 | try dlw.writeByte(DW.LNS.set_column); | 2793 | try dlw.writeByte(DW.LNS.set_column); |
| 2775 | try dlw.writeUleb128(func.lbrace_column + 1); | 2794 | try dlw.writeUleb128(func.lbrace_column + 1); |
| 2776 | 2795 | ||
| 2777 | try wip_nav.advancePCAndLine(func.lbrace_line, 0); | 2796 | try wip_nav.advanceLineAndPc(func.lbrace_line, 0, false); |
| 2778 | } else { | 2797 | } else { |
| 2779 | try dlw.writeUleb128(1 + @backingInt(dwarf.address_size)); | 2798 | try dlw.writeUleb128(1 + @backingInt(dwarf.address_size)); |
| 2780 | try dlw.writeByte(DW.LNE.set_address); | 2799 | try dlw.writeByte(DW.LNE.set_address); |
| ... | @@ -2791,17 +2810,17 @@ fn initWipNavInner( | ... | @@ -2791,17 +2810,17 @@ fn initWipNavInner( |
| 2791 | try dlw.writeByte(DW.LNS.set_column); | 2810 | try dlw.writeByte(DW.LNS.set_column); |
| 2792 | try dlw.writeUleb128(func.lbrace_column + 1); | 2811 | try dlw.writeUleb128(func.lbrace_column + 1); |
| 2793 | 2812 | ||
| 2794 | try wip_nav.advancePCAndLine(@intCast(decl.src_line + func.lbrace_line), 0); | 2813 | try wip_nav.advanceLineAndPc(decl.src_line + func.lbrace_line, 0, false); |
| 2795 | } | 2814 | } |
| 2796 | }, | 2815 | }, |
| 2797 | else => { | 2816 | else => { |
| 2798 | const diw = &wip_nav.debug_info.writer; | 2817 | const diw = &wip_nav.debug_info.writer; |
| 2799 | try wip_nav.declCommon(.{ | 2818 | try wip_nav.declCommon(.{ |
| 2800 | .decl = .decl_var, | 2819 | .decl = .decl_var, |
| 2801 | .generic_decl = switch (decl.kind) { | 2820 | .decl_specification = switch (decl.kind) { |
| 2802 | .unnamed_test, .@"test", .decltest, .@"comptime" => unreachable, | 2821 | .unnamed_test, .@"test", .decltest, .@"comptime" => unreachable, |
| 2803 | .@"const" => .generic_decl_const, | 2822 | .@"const" => .decl_specification_const, |
| 2804 | .@"var" => .generic_decl_var, | 2823 | .@"var" => .decl_specification_var, |
| 2805 | }, | 2824 | }, |
| 2806 | .decl_instance = .decl_instance_var, | 2825 | .decl_instance = .decl_instance_var, |
| 2807 | }, &nav, inst_info.file, &decl); | 2826 | }, &nav, inst_info.file, &decl); |
| ... | @@ -2983,19 +3002,13 @@ fn finishWipNavWriterError( | ... | @@ -2983,19 +3002,13 @@ fn finishWipNavWriterError( |
| 2983 | log.debug("finishWipNav({f})", .{nav.fqn.fmt(ip)}); | 3002 | log.debug("finishWipNav({f})", .{nav.fqn.fmt(ip)}); |
| 2984 | 3003 | ||
| 2985 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | 3004 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); |
| 2986 | const dlw = &wip_nav.debug_line.writer; | 3005 | try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.written()); |
| 2987 | if (dlw.end > 0) { | ||
| 2988 | try dlw.writeByte(DW.LNS.extended_op); | ||
| 2989 | try dlw.writeUleb128(1); | ||
| 2990 | try dlw.writeByte(DW.LNE.end_sequence); | ||
| 2991 | try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.written()); | ||
| 2992 | } | ||
| 2993 | try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written()); | 3006 | try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written()); |
| 2994 | 3007 | ||
| 2995 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | 3008 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); |
| 2996 | } | 3009 | } |
| 2997 | 3010 | ||
| 2998 | pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, AlreadyReported }!void { | 3011 | pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void { |
| 2999 | return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) { | 3012 | return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) { |
| 3000 | error.OutOfMemory => error.OutOfMemory, | 3013 | error.OutOfMemory => error.OutOfMemory, |
| 3001 | else => |e| pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}), | 3014 | else => |e| pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}), |
| ... | @@ -3054,8 +3067,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3054,8 +3067,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3054 | const loaded_struct = ip.loadStructType(nav_val.toIntern()); | 3067 | const loaded_struct = ip.loadStructType(nav_val.toIntern()); |
| 3055 | if (nav_index.toOptional() == loaded_struct.name_nav) { | 3068 | if (nav_index.toOptional() == loaded_struct.name_nav) { |
| 3056 | // This Nav's entry is populated by the type, not the actual Nav. | 3069 | // This Nav's entry is populated by the type, not the actual Nav. |
| 3057 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | 3070 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); |
| 3058 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | 3071 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); |
| 3059 | return; | 3072 | return; |
| 3060 | } | 3073 | } |
| 3061 | break :tag .alias; | 3074 | break :tag .alias; |
| ... | @@ -3064,8 +3077,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3064,8 +3077,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3064 | const loaded_enum = ip.loadEnumType(nav_val.toIntern()); | 3077 | const loaded_enum = ip.loadEnumType(nav_val.toIntern()); |
| 3065 | if (nav_index.toOptional() == loaded_enum.name_nav) { | 3078 | if (nav_index.toOptional() == loaded_enum.name_nav) { |
| 3066 | // This Nav's entry is populated by the type, not the actual Nav. | 3079 | // This Nav's entry is populated by the type, not the actual Nav. |
| 3067 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | 3080 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); |
| 3068 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | 3081 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); |
| 3069 | return; | 3082 | return; |
| 3070 | } | 3083 | } |
| 3071 | break :tag .alias; | 3084 | break :tag .alias; |
| ... | @@ -3074,8 +3087,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3074,8 +3087,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3074 | const loaded_union = ip.loadUnionType(nav_val.toIntern()); | 3087 | const loaded_union = ip.loadUnionType(nav_val.toIntern()); |
| 3075 | if (nav_index.toOptional() == loaded_union.name_nav) { | 3088 | if (nav_index.toOptional() == loaded_union.name_nav) { |
| 3076 | // This Nav's entry is populated by the type, not the actual Nav. | 3089 | // This Nav's entry is populated by the type, not the actual Nav. |
| 3077 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | 3090 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); |
| 3078 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | 3091 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); |
| 3079 | return; | 3092 | return; |
| 3080 | } | 3093 | } |
| 3081 | break :tag .alias; | 3094 | break :tag .alias; |
| ... | @@ -3084,8 +3097,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3084,8 +3097,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3084 | const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); | 3097 | const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); |
| 3085 | if (nav_index.toOptional() == loaded_opaque.name_nav) { | 3098 | if (nav_index.toOptional() == loaded_opaque.name_nav) { |
| 3086 | // This Nav's entry is populated by the type, not the actual Nav. | 3099 | // This Nav's entry is populated by the type, not the actual Nav. |
| 3087 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | 3100 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); |
| 3088 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | 3101 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); |
| 3089 | return; | 3102 | return; |
| 3090 | } | 3103 | } |
| 3091 | break :tag .alias; | 3104 | break :tag .alias; |
| ... | @@ -3168,7 +3181,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3168,7 +3181,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3168 | .alias => { | 3181 | .alias => { |
| 3169 | try wip_nav.declCommon(.{ | 3182 | try wip_nav.declCommon(.{ |
| 3170 | .decl = .decl_alias, | 3183 | .decl = .decl_alias, |
| 3171 | .generic_decl = .generic_decl_const, | 3184 | .decl_specification = .decl_specification_const, |
| 3172 | .decl_instance = .decl_instance_alias, | 3185 | .decl_instance = .decl_instance_alias, |
| 3173 | }, &nav, inst_info.file, &decl); | 3186 | }, &nav, inst_info.file, &decl); |
| 3174 | try wip_nav.refType(nav_val.toType()); | 3187 | try wip_nav.refType(nav_val.toType()); |
| ... | @@ -3176,7 +3189,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3176,7 +3189,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3176 | .@"var" => { | 3189 | .@"var" => { |
| 3177 | try wip_nav.declCommon(.{ | 3190 | try wip_nav.declCommon(.{ |
| 3178 | .decl = .decl_var, | 3191 | .decl = .decl_var, |
| 3179 | .generic_decl = .generic_decl_var, | 3192 | .decl_specification = .decl_specification_var, |
| 3180 | .decl_instance = .decl_instance_var, | 3193 | .decl_instance = .decl_instance_var, |
| 3181 | }, &nav, inst_info.file, &decl); | 3194 | }, &nav, inst_info.file, &decl); |
| 3182 | try wip_nav.strp(switch (decl.linkage) { | 3195 | try wip_nav.strp(switch (decl.linkage) { |
| ... | @@ -3196,19 +3209,19 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3196,19 +3209,19 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3196 | const has_comptime_state = nav_ty.comptimeOnly(zcu); | 3209 | const has_comptime_state = nav_ty.comptimeOnly(zcu); |
| 3197 | try wip_nav.declCommon(if (has_runtime_bits and has_comptime_state) .{ | 3210 | try wip_nav.declCommon(if (has_runtime_bits and has_comptime_state) .{ |
| 3198 | .decl = .decl_const_runtime_bits_comptime_state, | 3211 | .decl = .decl_const_runtime_bits_comptime_state, |
| 3199 | .generic_decl = .generic_decl_const, | 3212 | .decl_specification = .decl_specification_const, |
| 3200 | .decl_instance = .decl_instance_const_runtime_bits_comptime_state, | 3213 | .decl_instance = .decl_instance_const_runtime_bits_comptime_state, |
| 3201 | } else if (has_comptime_state) .{ | 3214 | } else if (has_comptime_state) .{ |
| 3202 | .decl = .decl_const_comptime_state, | 3215 | .decl = .decl_const_comptime_state, |
| 3203 | .generic_decl = .generic_decl_const, | 3216 | .decl_specification = .decl_specification_const, |
| 3204 | .decl_instance = .decl_instance_const_comptime_state, | 3217 | .decl_instance = .decl_instance_const_comptime_state, |
| 3205 | } else if (has_runtime_bits) .{ | 3218 | } else if (has_runtime_bits) .{ |
| 3206 | .decl = .decl_const_runtime_bits, | 3219 | .decl = .decl_const_runtime_bits, |
| 3207 | .generic_decl = .generic_decl_const, | 3220 | .decl_specification = .decl_specification_const, |
| 3208 | .decl_instance = .decl_instance_const_runtime_bits, | 3221 | .decl_instance = .decl_instance_const_runtime_bits, |
| 3209 | } else .{ | 3222 | } else .{ |
| 3210 | .decl = .decl_const, | 3223 | .decl = .decl_const, |
| 3211 | .generic_decl = .generic_decl_const, | 3224 | .decl_specification = .decl_specification_const, |
| 3212 | .decl_instance = .decl_instance_const, | 3225 | .decl_instance = .decl_instance_const, |
| 3213 | }, &nav, inst_info.file, &decl); | 3226 | }, &nav, inst_info.file, &decl); |
| 3214 | try wip_nav.strp(switch (decl.linkage) { | 3227 | try wip_nav.strp(switch (decl.linkage) { |
| ... | @@ -3232,11 +3245,11 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3232,11 +3245,11 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3232 | } else true; | 3245 | } else true; |
| 3233 | try wip_nav.declCommon(if (is_nullary) .{ | 3246 | try wip_nav.declCommon(if (is_nullary) .{ |
| 3234 | .decl = .decl_nullary_func_generic, | 3247 | .decl = .decl_nullary_func_generic, |
| 3235 | .generic_decl = .generic_decl_func, | 3248 | .decl_specification = .decl_specification_func, |
| 3236 | .decl_instance = .decl_instance_nullary_func_generic, | 3249 | .decl_instance = .decl_instance_nullary_func_generic, |
| 3237 | } else .{ | 3250 | } else .{ |
| 3238 | .decl = .decl_func_generic, | 3251 | .decl = .decl_func_generic, |
| 3239 | .generic_decl = .generic_decl_func, | 3252 | .decl_specification = .decl_specification_func, |
| 3240 | .decl_instance = .decl_instance_func_generic, | 3253 | .decl_instance = .decl_instance_func_generic, |
| 3241 | }, &nav, inst_info.file, &decl); | 3254 | }, &nav, inst_info.file, &decl); |
| 3242 | try wip_nav.refType(.fromInterned(func_type.return_type)); | 3255 | try wip_nav.refType(.fromInterned(func_type.return_type)); |
| ... | @@ -3254,14 +3267,14 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -3254,14 +3267,14 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3254 | .func_alias => |owner_nav| { | 3267 | .func_alias => |owner_nav| { |
| 3255 | try wip_nav.declCommon(.{ | 3268 | try wip_nav.declCommon(.{ |
| 3256 | .decl = .decl_alias, | 3269 | .decl = .decl_alias, |
| 3257 | .generic_decl = .generic_decl_const, | 3270 | .decl_specification = .decl_specification_const, |
| 3258 | .decl_instance = .decl_instance_alias, | 3271 | .decl_instance = .decl_instance_alias, |
| 3259 | }, &nav, inst_info.file, &decl); | 3272 | }, &nav, inst_info.file, &decl); |
| 3260 | try wip_nav.refNav(owner_nav); | 3273 | try wip_nav.refNav(owner_nav); |
| 3261 | }, | 3274 | }, |
| 3262 | } | 3275 | } |
| 3263 | try dwarf.debug_info.section.replaceEntry(unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | 3276 | try dwarf.debug_info.section.replaceEntry(unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); |
| 3264 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | 3277 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); |
| 3265 | } | 3278 | } |
| 3266 | 3279 | ||
| 3267 | pub fn updateContainerType( | 3280 | pub fn updateContainerType( |
| ... | @@ -3270,7 +3283,7 @@ pub fn updateContainerType( | ... | @@ -3270,7 +3283,7 @@ pub fn updateContainerType( |
| 3270 | ty: InternPool.Index, | 3283 | ty: InternPool.Index, |
| 3271 | success: bool, | 3284 | success: bool, |
| 3272 | ) !void { | 3285 | ) !void { |
| 3273 | try dwarf.const_pool.updateContainerType(pt, .{ .dwarf = dwarf }, ty, success); | 3286 | try dwarf.const_pool.updateContainerType(pt, dwarf.constPoolUser(), ty, success); |
| 3274 | } | 3287 | } |
| 3275 | /// Should only be called by the `link.ConstPool` implementation. | 3288 | /// Should only be called by the `link.ConstPool` implementation. |
| 3276 | pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { | 3289 | pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { |
| ... | @@ -3374,12 +3387,12 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde | ... | @@ -3374,12 +3387,12 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde |
| 3374 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file_index); | 3387 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file_index); |
| 3375 | try wip_nav.abbrevCode(.empty_file); | 3388 | try wip_nav.abbrevCode(.empty_file); |
| 3376 | try wip_nav.debug_info.writer.writeUleb128(file_gop.index); | 3389 | try wip_nav.debug_info.writer.writeUleb128(file_gop.index); |
| 3377 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | 3390 | try wip_nav.strp(loaded_struct.fqn.toSlice(ip)); |
| 3378 | } else { | 3391 | } else { |
| 3379 | try dwarf.emitIncompleteContainerType( | 3392 | try dwarf.emitIncompleteContainerType( |
| 3380 | &wip_nav, | 3393 | &wip_nav, |
| 3381 | loaded_struct.zir_index, | 3394 | loaded_struct.zir_index, |
| 3382 | loaded_struct.name, | 3395 | loaded_struct.fqn, |
| 3383 | loaded_struct.name_nav, | 3396 | loaded_struct.name_nav, |
| 3384 | ); | 3397 | ); |
| 3385 | } | 3398 | } |
| ... | @@ -3389,7 +3402,7 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde | ... | @@ -3389,7 +3402,7 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde |
| 3389 | try dwarf.emitIncompleteContainerType( | 3402 | try dwarf.emitIncompleteContainerType( |
| 3390 | &wip_nav, | 3403 | &wip_nav, |
| 3391 | loaded_union.zir_index, | 3404 | loaded_union.zir_index, |
| 3392 | loaded_union.name, | 3405 | loaded_union.fqn, |
| 3393 | loaded_union.name_nav, | 3406 | loaded_union.name_nav, |
| 3394 | ); | 3407 | ); |
| 3395 | }, | 3408 | }, |
| ... | @@ -3399,12 +3412,12 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde | ... | @@ -3399,12 +3412,12 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde |
| 3399 | try dwarf.emitIncompleteContainerType( | 3412 | try dwarf.emitIncompleteContainerType( |
| 3400 | &wip_nav, | 3413 | &wip_nav, |
| 3401 | zir_index, | 3414 | zir_index, |
| 3402 | loaded_enum.name, | 3415 | loaded_enum.fqn, |
| 3403 | loaded_enum.name_nav, | 3416 | loaded_enum.name_nav, |
| 3404 | ); | 3417 | ); |
| 3405 | } else { | 3418 | } else { |
| 3406 | try wip_nav.abbrevCode(.generated_empty_struct_type); | 3419 | try wip_nav.abbrevCode(.generated_empty_struct_type); |
| 3407 | try wip_nav.strp(loaded_enum.name.toSlice(ip)); | 3420 | try wip_nav.strp(loaded_enum.fqn.toSlice(ip)); |
| 3408 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | 3421 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); |
| 3409 | } | 3422 | } |
| 3410 | }, | 3423 | }, |
| ... | @@ -3413,7 +3426,7 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde | ... | @@ -3413,7 +3426,7 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde |
| 3413 | try dwarf.emitIncompleteContainerType( | 3426 | try dwarf.emitIncompleteContainerType( |
| 3414 | &wip_nav, | 3427 | &wip_nav, |
| 3415 | loaded_opaque.zir_index, | 3428 | loaded_opaque.zir_index, |
| 3416 | loaded_opaque.name, | 3429 | loaded_opaque.fqn, |
| 3417 | loaded_opaque.name_nav, | 3430 | loaded_opaque.name_nav, |
| 3418 | ); | 3431 | ); |
| 3419 | }, | 3432 | }, |
| ... | @@ -3438,7 +3451,7 @@ fn emitIncompleteContainerType( | ... | @@ -3438,7 +3451,7 @@ fn emitIncompleteContainerType( |
| 3438 | dwarf: *Dwarf, | 3451 | dwarf: *Dwarf, |
| 3439 | wip_nav: *WipNav, | 3452 | wip_nav: *WipNav, |
| 3440 | zir_index: InternPool.TrackedInst.Index, | 3453 | zir_index: InternPool.TrackedInst.Index, |
| 3441 | name: InternPool.NullTerminatedString, | 3454 | fqn: InternPool.NullTerminatedString, |
| 3442 | name_nav: InternPool.Nav.Index.Optional, | 3455 | name_nav: InternPool.Nav.Index.Optional, |
| 3443 | ) !void { | 3456 | ) !void { |
| 3444 | const zcu = wip_nav.pt.zcu; | 3457 | const zcu = wip_nav.pt.zcu; |
| ... | @@ -3450,7 +3463,7 @@ fn emitIncompleteContainerType( | ... | @@ -3450,7 +3463,7 @@ fn emitIncompleteContainerType( |
| 3450 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | 3463 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); |
| 3451 | try wip_nav.declCommon(.{ | 3464 | try wip_nav.declCommon(.{ |
| 3452 | .decl = .decl_namespace_struct, | 3465 | .decl = .decl_namespace_struct, |
| 3453 | .generic_decl = .generic_decl_const, | 3466 | .decl_specification = .decl_specification_const, |
| 3454 | .decl_instance = .decl_instance_namespace_struct, | 3467 | .decl_instance = .decl_instance_namespace_struct, |
| 3455 | }, &nav, file, &decl); | 3468 | }, &nav, file, &decl); |
| 3456 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | 3469 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); |
| ... | @@ -3459,7 +3472,7 @@ fn emitIncompleteContainerType( | ... | @@ -3459,7 +3472,7 @@ fn emitIncompleteContainerType( |
| 3459 | const file_gop = try dwarf.getModInfo(wip_nav.unit).files.getOrPut(dwarf.gpa, file); | 3472 | const file_gop = try dwarf.getModInfo(wip_nav.unit).files.getOrPut(dwarf.gpa, file); |
| 3460 | try wip_nav.abbrevCode(.empty_struct_type); | 3473 | try wip_nav.abbrevCode(.empty_struct_type); |
| 3461 | try diw.writeUleb128(file_gop.index); | 3474 | try diw.writeUleb128(file_gop.index); |
| 3462 | try wip_nav.strp(name.toSlice(ip)); | 3475 | try wip_nav.strp(fqn.toSlice(ip)); |
| 3463 | try diw.writeByte(@intFromBool(true)); | 3476 | try diw.writeByte(@intFromBool(true)); |
| 3464 | } | 3477 | } |
| 3465 | } | 3478 | } |
| ... | @@ -3868,11 +3881,11 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -3868,11 +3881,11 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3868 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | 3881 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); |
| 3869 | try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{ | 3882 | try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{ |
| 3870 | .decl = .decl_namespace_struct, | 3883 | .decl = .decl_namespace_struct, |
| 3871 | .generic_decl = .generic_decl_const, | 3884 | .decl_specification = .decl_specification_const, |
| 3872 | .decl_instance = .decl_instance_namespace_struct, | 3885 | .decl_instance = .decl_instance_namespace_struct, |
| 3873 | } else .{ | 3886 | } else .{ |
| 3874 | .decl = .decl_struct, | 3887 | .decl = .decl_struct, |
| 3875 | .generic_decl = .generic_decl_const, | 3888 | .decl_specification = .decl_specification_const, |
| 3876 | .decl_instance = .decl_instance_struct, | 3889 | .decl_instance = .decl_instance_struct, |
| 3877 | }, &nav, file, &decl); | 3890 | }, &nav, file, &decl); |
| 3878 | } else { | 3891 | } else { |
| ... | @@ -3882,7 +3895,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -3882,7 +3895,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3882 | else => if (struct_is_file) .file else .struct_type, | 3895 | else => if (struct_is_file) .file else .struct_type, |
| 3883 | }); | 3896 | }); |
| 3884 | try diw.writeUleb128(file_gop.index); | 3897 | try diw.writeUleb128(file_gop.index); |
| 3885 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | 3898 | try wip_nav.strp(loaded_struct.fqn.toSlice(ip)); |
| 3886 | } | 3899 | } |
| 3887 | if (loaded_struct.field_types.len == 0) { | 3900 | if (loaded_struct.field_types.len == 0) { |
| 3888 | if (!struct_is_file) try diw.writeByte(@intFromBool(false)); | 3901 | if (!struct_is_file) try diw.writeByte(@intFromBool(false)); |
| ... | @@ -3947,7 +3960,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -3947,7 +3960,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3947 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | 3960 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); |
| 3948 | try wip_nav.declCommon(.{ | 3961 | try wip_nav.declCommon(.{ |
| 3949 | .decl = .decl_packed_struct, | 3962 | .decl = .decl_packed_struct, |
| 3950 | .generic_decl = .generic_decl_const, | 3963 | .decl_specification = .decl_specification_const, |
| 3951 | .decl_instance = .decl_instance_packed_struct, | 3964 | .decl_instance = .decl_instance_packed_struct, |
| 3952 | }, &nav, file, &decl); | 3965 | }, &nav, file, &decl); |
| 3953 | break :t true; | 3966 | break :t true; |
| ... | @@ -3955,7 +3968,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -3955,7 +3968,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3955 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | 3968 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); |
| 3956 | try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); | 3969 | try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); |
| 3957 | try diw.writeUleb128(file_gop.index); | 3970 | try diw.writeUleb128(file_gop.index); |
| 3958 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | 3971 | try wip_nav.strp(loaded_struct.fqn.toSlice(ip)); |
| 3959 | break :t loaded_struct.field_types.len > 0; | 3972 | break :t loaded_struct.field_types.len > 0; |
| 3960 | }; | 3973 | }; |
| 3961 | try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); | 3974 | try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); |
| ... | @@ -3984,7 +3997,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -3984,7 +3997,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3984 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | 3997 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); |
| 3985 | try wip_nav.declCommon(.{ | 3998 | try wip_nav.declCommon(.{ |
| 3986 | .decl = .decl_union, | 3999 | .decl = .decl_union, |
| 3987 | .generic_decl = .generic_decl_const, | 4000 | .decl_specification = .decl_specification_const, |
| 3988 | .decl_instance = .decl_instance_union, | 4001 | .decl_instance = .decl_instance_union, |
| 3989 | }, &nav, file, &decl); | 4002 | }, &nav, file, &decl); |
| 3990 | break :t true; | 4003 | break :t true; |
| ... | @@ -3992,7 +4005,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -3992,7 +4005,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3992 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | 4005 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); |
| 3993 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); | 4006 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); |
| 3994 | try diw.writeUleb128(file_gop.index); | 4007 | try diw.writeUleb128(file_gop.index); |
| 3995 | try wip_nav.strp(loaded_union.name.toSlice(ip)); | 4008 | try wip_nav.strp(loaded_union.fqn.toSlice(ip)); |
| 3996 | break :t loaded_union.field_types.len > 0; | 4009 | break :t loaded_union.field_types.len > 0; |
| 3997 | }; | 4010 | }; |
| 3998 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | 4011 | const union_layout = Type.getUnionLayout(loaded_union, zcu); |
| ... | @@ -4046,7 +4059,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -4046,7 +4059,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4046 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | 4059 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); |
| 4047 | try wip_nav.declCommon(.{ | 4060 | try wip_nav.declCommon(.{ |
| 4048 | .decl = .decl_packed_union, | 4061 | .decl = .decl_packed_union, |
| 4049 | .generic_decl = .generic_decl_const, | 4062 | .decl_specification = .decl_specification_const, |
| 4050 | .decl_instance = .decl_instance_packed_union, | 4063 | .decl_instance = .decl_instance_packed_union, |
| 4051 | }, &nav, file, &decl); | 4064 | }, &nav, file, &decl); |
| 4052 | break :t true; | 4065 | break :t true; |
| ... | @@ -4054,7 +4067,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -4054,7 +4067,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4054 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | 4067 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); |
| 4055 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .packed_union_type else .empty_packed_union_type); | 4068 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .packed_union_type else .empty_packed_union_type); |
| 4056 | try diw.writeUleb128(file_gop.index); | 4069 | try diw.writeUleb128(file_gop.index); |
| 4057 | try wip_nav.strp(loaded_union.name.toSlice(ip)); | 4070 | try wip_nav.strp(loaded_union.fqn.toSlice(ip)); |
| 4058 | break :t loaded_union.field_types.len > 0; | 4071 | break :t loaded_union.field_types.len > 0; |
| 4059 | }; | 4072 | }; |
| 4060 | try wip_nav.refType(.fromInterned(loaded_union.packed_backing_int_type)); | 4073 | try wip_nav.refType(.fromInterned(loaded_union.packed_backing_int_type)); |
| ... | @@ -4079,18 +4092,18 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -4079,18 +4092,18 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4079 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | 4092 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); |
| 4080 | try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{ | 4093 | try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{ |
| 4081 | .decl = .decl_enum, | 4094 | .decl = .decl_enum, |
| 4082 | .generic_decl = .generic_decl_const, | 4095 | .decl_specification = .decl_specification_const, |
| 4083 | .decl_instance = .decl_instance_enum, | 4096 | .decl_instance = .decl_instance_enum, |
| 4084 | } else .{ | 4097 | } else .{ |
| 4085 | .decl = .decl_empty_enum, | 4098 | .decl = .decl_empty_enum, |
| 4086 | .generic_decl = .generic_decl_const, | 4099 | .decl_specification = .decl_specification_const, |
| 4087 | .decl_instance = .decl_instance_empty_enum, | 4100 | .decl_instance = .decl_instance_empty_enum, |
| 4088 | }, &nav, file, &decl); | 4101 | }, &nav, file, &decl); |
| 4089 | } else { | 4102 | } else { |
| 4090 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | 4103 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); |
| 4091 | try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type); | 4104 | try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type); |
| 4092 | try diw.writeUleb128(file_gop.index); | 4105 | try diw.writeUleb128(file_gop.index); |
| 4093 | try wip_nav.strp(loaded_enum.name.toSlice(ip)); | 4106 | try wip_nav.strp(loaded_enum.fqn.toSlice(ip)); |
| 4094 | } | 4107 | } |
| 4095 | try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); | 4108 | try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); |
| 4096 | for (0..loaded_enum.field_names.len) |field_index| { | 4109 | for (0..loaded_enum.field_names.len) |field_index| { |
| ... | @@ -4102,7 +4115,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -4102,7 +4115,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4102 | } else { | 4115 | } else { |
| 4103 | assert(loaded_enum.owner_union != .none); | 4116 | assert(loaded_enum.owner_union != .none); |
| 4104 | try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type); | 4117 | try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type); |
| 4105 | try wip_nav.strp(loaded_enum.name.toSlice(ip)); | 4118 | try wip_nav.strp(loaded_enum.fqn.toSlice(ip)); |
| 4106 | try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); | 4119 | try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); |
| 4107 | for (0..loaded_enum.field_names.len) |field_index| { | 4120 | for (0..loaded_enum.field_names.len) |field_index| { |
| 4108 | try wip_nav.abbrevCode(.enum_field); | 4121 | try wip_nav.abbrevCode(.enum_field); |
| ... | @@ -4121,14 +4134,14 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -4121,14 +4134,14 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4121 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | 4134 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); |
| 4122 | try wip_nav.declCommon(.{ | 4135 | try wip_nav.declCommon(.{ |
| 4123 | .decl = .decl_namespace_struct, | 4136 | .decl = .decl_namespace_struct, |
| 4124 | .generic_decl = .generic_decl_const, | 4137 | .decl_specification = .decl_specification_const, |
| 4125 | .decl_instance = .decl_instance_namespace_struct, | 4138 | .decl_instance = .decl_instance_namespace_struct, |
| 4126 | }, &nav, file, &decl); | 4139 | }, &nav, file, &decl); |
| 4127 | } else { | 4140 | } else { |
| 4128 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | 4141 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); |
| 4129 | try wip_nav.abbrevCode(.empty_struct_type); | 4142 | try wip_nav.abbrevCode(.empty_struct_type); |
| 4130 | try diw.writeUleb128(file_gop.index); | 4143 | try diw.writeUleb128(file_gop.index); |
| 4131 | try wip_nav.strp(loaded_opaque.name.toSlice(ip)); | 4144 | try wip_nav.strp(loaded_opaque.fqn.toSlice(ip)); |
| 4132 | } | 4145 | } |
| 4133 | try diw.writeByte(@intFromBool(true)); | 4146 | try diw.writeByte(@intFromBool(true)); |
| 4134 | }, | 4147 | }, |
| ... | @@ -4614,6 +4627,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co | ... | @@ -4614,6 +4627,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4614 | } | 4627 | } |
| 4615 | try diw.writeUleb128(@backingInt(AbbrevCode.null)); | 4628 | try diw.writeUleb128(@backingInt(AbbrevCode.null)); |
| 4616 | }, | 4629 | }, |
| 4630 | |||
| 4617 | .memoized_call => unreachable, // not a value | 4631 | .memoized_call => unreachable, // not a value |
| 4618 | } | 4632 | } |
| 4619 | try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); | 4633 | try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); |
| ... | @@ -4632,25 +4646,17 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, err | ... | @@ -4632,25 +4646,17 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, err |
| 4632 | }; | 4646 | }; |
| 4633 | } | 4647 | } |
| 4634 | 4648 | ||
| 4635 | pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void { | 4649 | pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index, line: u32) UpdateError!void { |
| 4636 | const comp = dwarf.bin_file.comp; | 4650 | const comp = dwarf.bin_file.comp; |
| 4637 | const io = comp.io; | 4651 | const io = comp.io; |
| 4638 | const ip = &zcu.intern_pool; | 4652 | const ip = &zcu.intern_pool; |
| 4639 | 4653 | ||
| 4640 | const inst_info = zir_index.resolveFull(ip).?; | 4654 | const inst_info = zir_index.resolveFull(ip).?; |
| 4641 | assert(inst_info.inst != .main_struct_inst); | 4655 | if (inst_info.inst == .main_struct_inst) return; |
| 4642 | const file = zcu.fileByIndex(inst_info.file); | 4656 | const file = zcu.fileByIndex(inst_info.file); |
| 4643 | const decl = file.zir.?.getDeclaration(inst_info.inst); | ||
| 4644 | log.debug("updateLineNumber({s}:{d}:{d} %{d} = {s})", .{ | ||
| 4645 | file.sub_file_path, | ||
| 4646 | decl.src_line + 1, | ||
| 4647 | decl.src_column + 1, | ||
| 4648 | @backingInt(inst_info.inst), | ||
| 4649 | file.zir.?.nullTerminatedString(decl.name), | ||
| 4650 | }); | ||
| 4651 | 4657 | ||
| 4652 | var line_buf: [4]u8 = undefined; | 4658 | var line_buf: [4]u8 = undefined; |
| 4653 | std.mem.writeInt(u32, &line_buf, decl.src_line + 1, dwarf.endian); | 4659 | std.mem.writeInt(u32, &line_buf, line + 1, dwarf.endian); |
| 4654 | 4660 | ||
| 4655 | const unit = dwarf.debug_info.section.getUnit(dwarf.getUnitIfExists(file.mod.?) orelse return); | 4661 | const unit = dwarf.debug_info.section.getUnit(dwarf.getUnitIfExists(file.mod.?) orelse return); |
| 4656 | const entry = unit.getEntry(dwarf.decls.get(zir_index) orelse return); | 4662 | const entry = unit.getEntry(dwarf.decls.get(zir_index) orelse return); |
| ... | @@ -4696,7 +4702,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err | ... | @@ -4696,7 +4702,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err |
| 4696 | 4702 | ||
| 4697 | // Update `anyerror` based on the finished global error set. | 4703 | // Update `anyerror` based on the finished global error set. |
| 4698 | { | 4704 | { |
| 4699 | const index = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, .anyerror_type); | 4705 | const index = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), .anyerror_type); |
| 4700 | const unit, const entry = dwarf.values.items[@backingInt(index)]; | 4706 | const unit, const entry = dwarf.values.items[@backingInt(index)]; |
| 4701 | var wip_nav: WipNav = .{ | 4707 | var wip_nav: WipNav = .{ |
| 4702 | .dwarf = dwarf, | 4708 | .dwarf = dwarf, |
| ... | @@ -4731,7 +4737,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err | ... | @@ -4731,7 +4737,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err |
| 4731 | } | 4737 | } |
| 4732 | if (global_error_set_names.len > 0) try diw.writeUleb128(@backingInt(AbbrevCode.null)); | 4738 | if (global_error_set_names.len > 0) try diw.writeUleb128(@backingInt(AbbrevCode.null)); |
| 4733 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | 4739 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); |
| 4734 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | 4740 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); |
| 4735 | } | 4741 | } |
| 4736 | 4742 | ||
| 4737 | for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| { | 4743 | for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| { |
| ... | @@ -4783,7 +4789,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err | ... | @@ -4783,7 +4789,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err |
| 4783 | .debug_frame => unreachable, | 4789 | .debug_frame => unreachable, |
| 4784 | .eh_frame => switch (target.cpu.arch) { | 4790 | .eh_frame => switch (target.cpu.arch) { |
| 4785 | .x86_64 => { | 4791 | .x86_64 => { |
| 4786 | dev.check(.x86_64_backend); | 4792 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 4787 | const Register = @import("../codegen/x86_64/bits.zig").Register; | 4793 | const Register = @import("../codegen/x86_64/bits.zig").Register; |
| 4788 | for (dwarf.debug_frame.section.units.items) |*unit| { | 4794 | for (dwarf.debug_frame.section.units.items) |*unit| { |
| 4789 | header_aw.clearRetainingCapacity(); | 4795 | header_aw.clearRetainingCapacity(); |
| ... | @@ -5131,9 +5137,9 @@ const AbbrevCode = enum { | ... | @@ -5131,9 +5137,9 @@ const AbbrevCode = enum { |
| 5131 | decl_func_generic, | 5137 | decl_func_generic, |
| 5132 | decl_extern_nullary_func, | 5138 | decl_extern_nullary_func, |
| 5133 | decl_extern_func, | 5139 | decl_extern_func, |
| 5134 | generic_decl_var, | 5140 | decl_specification_var, |
| 5135 | generic_decl_const, | 5141 | decl_specification_const, |
| 5136 | generic_decl_func, | 5142 | decl_specification_func, |
| 5137 | decl_instance_alias, | 5143 | decl_instance_alias, |
| 5138 | decl_instance_empty_enum, | 5144 | decl_instance_empty_enum, |
| 5139 | decl_instance_enum, | 5145 | decl_instance_enum, |
| ... | @@ -5257,7 +5263,7 @@ const AbbrevCode = enum { | ... | @@ -5257,7 +5263,7 @@ const AbbrevCode = enum { |
| 5257 | .{ .accessibility, .data1 }, | 5263 | .{ .accessibility, .data1 }, |
| 5258 | .{ .name, .strp }, | 5264 | .{ .name, .strp }, |
| 5259 | }; | 5265 | }; |
| 5260 | const generic_decl_abbrev_common_attrs = decl_abbrev_common_attrs ++ &[_]Attr{ | 5266 | const decl_specification_abbrev_common_attrs = decl_abbrev_common_attrs ++ &[_]Attr{ |
| 5261 | .{ .declaration, .flag_present }, | 5267 | .{ .declaration, .flag_present }, |
| 5262 | }; | 5268 | }; |
| 5263 | const decl_instance_abbrev_common_attrs = &[_]Attr{ | 5269 | const decl_instance_abbrev_common_attrs = &[_]Attr{ |
| ... | @@ -5442,17 +5448,17 @@ const AbbrevCode = enum { | ... | @@ -5442,17 +5448,17 @@ const AbbrevCode = enum { |
| 5442 | .{ .noreturn, .flag }, | 5448 | .{ .noreturn, .flag }, |
| 5443 | }, | 5449 | }, |
| 5444 | }, | 5450 | }, |
| 5445 | .generic_decl_var = .{ | 5451 | .decl_specification_var = .{ |
| 5446 | .tag = .variable, | 5452 | .tag = .variable, |
| 5447 | .attrs = generic_decl_abbrev_common_attrs, | 5453 | .attrs = decl_specification_abbrev_common_attrs, |
| 5448 | }, | 5454 | }, |
| 5449 | .generic_decl_const = .{ | 5455 | .decl_specification_const = .{ |
| 5450 | .tag = .constant, | 5456 | .tag = .constant, |
| 5451 | .attrs = generic_decl_abbrev_common_attrs, | 5457 | .attrs = decl_specification_abbrev_common_attrs, |
| 5452 | }, | 5458 | }, |
| 5453 | .generic_decl_func = .{ | 5459 | .decl_specification_func = .{ |
| 5454 | .tag = .subprogram, | 5460 | .tag = .subprogram, |
| 5455 | .attrs = generic_decl_abbrev_common_attrs, | 5461 | .attrs = decl_specification_abbrev_common_attrs, |
| 5456 | }, | 5462 | }, |
| 5457 | .decl_instance_alias = .{ | 5463 | .decl_instance_alias = .{ |
| 5458 | .tag = .imported_declaration, | 5464 | .tag = .imported_declaration, |
| ... | @@ -6301,6 +6307,14 @@ fn getFile(dwarf: *Dwarf) ?Io.File { | ... | @@ -6301,6 +6307,14 @@ fn getFile(dwarf: *Dwarf) ?Io.File { |
| 6301 | return dwarf.bin_file.file; | 6307 | return dwarf.bin_file.file; |
| 6302 | } | 6308 | } |
| 6303 | 6309 | ||
| 6310 | fn constPoolUser(dwarf: *Dwarf) link.ConstPool.User { | ||
| 6311 | return switch (dwarf.bin_file.tag) { | ||
| 6312 | else => unreachable, | ||
| 6313 | .elf => .{ .elf = dwarf }, | ||
| 6314 | .macho => .{ .macho = dwarf }, | ||
| 6315 | }; | ||
| 6316 | } | ||
| 6317 | |||
| 6304 | fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index { | 6318 | fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index { |
| 6305 | const entry = try dwarf.debug_aranges.section.getUnit(unit).addEntry(dwarf.gpa); | 6319 | const entry = try dwarf.debug_aranges.section.getUnit(unit).addEntry(dwarf.gpa); |
| 6306 | assert(try dwarf.debug_frame.section.getUnit(unit).addEntry(dwarf.gpa) == entry); | 6320 | assert(try dwarf.debug_frame.section.getUnit(unit).addEntry(dwarf.gpa) == entry); |
| ... | @@ -6362,14 +6376,14 @@ fn uleb128Bytes(value: anytype) u32 { | ... | @@ -6362,14 +6376,14 @@ fn uleb128Bytes(value: anytype) u32 { |
| 6362 | var buf: [64]u8 = undefined; | 6376 | var buf: [64]u8 = undefined; |
| 6363 | var dw: Writer.Discarding = .init(&buf); | 6377 | var dw: Writer.Discarding = .init(&buf); |
| 6364 | dw.writer.writeUleb128(value) catch unreachable; | 6378 | dw.writer.writeUleb128(value) catch unreachable; |
| 6365 | return @intCast(dw.count + dw.writer.end); | 6379 | return @intCast(dw.fullCount()); |
| 6366 | } | 6380 | } |
| 6367 | 6381 | ||
| 6368 | fn sleb128Bytes(value: anytype) u32 { | 6382 | fn sleb128Bytes(value: anytype) u32 { |
| 6369 | var buf: [64]u8 = undefined; | 6383 | var buf: [64]u8 = undefined; |
| 6370 | var dw: Writer.Discarding = .init(&buf); | 6384 | var dw: Writer.Discarding = .init(&buf); |
| 6371 | dw.writer.writeSleb128(value) catch unreachable; | 6385 | dw.writer.writeSleb128(value) catch unreachable; |
| 6372 | return @intCast(dw.count + dw.writer.end); | 6386 | return @intCast(dw.fullCount()); |
| 6373 | } | 6387 | } |
| 6374 | 6388 | ||
| 6375 | /// overrides `-fno-incremental` for testing incremental debug info until `-fincremental` is functional | 6389 | /// overrides `-fno-incremental` for testing incremental debug info until `-fincremental` is functional |
src/link/Dwarf2.zig created+5247| ... | @@ -0,0 +1,5247 @@ | ||
| 1 | lf: *link.File, | ||
| 2 | format: DW.Format, | ||
| 3 | endian: std.lang.Endian, | ||
| 4 | address_size: AddressSize, | ||
| 5 | const_pool: link.ConstPool, | ||
| 6 | |||
| 7 | units: []Unit, | ||
| 8 | /// Indices are `link.ConstPool.Index`. | ||
| 9 | consts: std.ArrayList(Const), | ||
| 10 | globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global), | ||
| 11 | funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func), | ||
| 12 | decls: std.array_hash_map.Auto(InternPool.TrackedInst.Index, Decl), | ||
| 13 | pending_decl: struct { di: Decl.Index, instance_val: InternPool.Index }, | ||
| 14 | |||
| 15 | debug_abbrev: Abbrev, | ||
| 16 | frame: Frame, | ||
| 17 | debug_info: Info, | ||
| 18 | debug_line: Line, | ||
| 19 | debug_line_str: Str, | ||
| 20 | debug_rnglists: Rnglists, | ||
| 21 | debug_str: Str, | ||
| 22 | debug_str_offsets: StrOffsets, | ||
| 23 | |||
| 24 | pub const AddressSize = enum(u8) { @"32" = 4, @"64" = 8, _ }; | ||
| 25 | |||
| 26 | pub const Unit = struct { | ||
| 27 | alive: bool, | ||
| 28 | dirs: std.array_hash_map.Auto(Unit.Index, void), | ||
| 29 | files: std.array_hash_map.Auto(Zcu.File.Index, void), | ||
| 30 | frame_ni: link.MappedFile.Node.Index.Optional, | ||
| 31 | cie_ni: link.MappedFile.Node.Index.Optional, | ||
| 32 | debug_info_ni: link.MappedFile.Node.Index.Optional, | ||
| 33 | debug_info_header_ni: link.MappedFile.Node.Index.Optional, | ||
| 34 | debug_info_footer_ni: link.MappedFile.Node.Index.Optional, | ||
| 35 | debug_line_ni: link.MappedFile.Node.Index.Optional, | ||
| 36 | debug_line_header_ni: link.MappedFile.Node.Index.Optional, | ||
| 37 | debug_line_header_changed: bool, | ||
| 38 | debug_rnglists_ni: link.MappedFile.Node.Index.Optional, | ||
| 39 | debug_rnglists_offsets_table_offset: usize, | ||
| 40 | debug_rnglists_end: usize, | ||
| 41 | |||
| 42 | pub const Index = enum(u32) { | ||
| 43 | _, | ||
| 44 | |||
| 45 | pub fn mod(ui: Unit.Index, dwarf: *Dwarf) *Module { | ||
| 46 | return dwarf.lf.comp.zcu.?.module_roots.keys()[@backingInt(ui)]; | ||
| 47 | } | ||
| 48 | |||
| 49 | pub fn get(ui: Unit.Index, dwarf: *Dwarf) *Unit { | ||
| 50 | return &dwarf.units[@backingInt(ui)]; | ||
| 51 | } | ||
| 52 | }; | ||
| 53 | |||
| 54 | pub const DirIndex = enum(u32) { | ||
| 55 | root = 0, | ||
| 56 | _, | ||
| 57 | |||
| 58 | fn get(di: DirIndex, unit: *Unit) Unit.Index { | ||
| 59 | return unit.dirs.keys()[@backingInt(di)]; | ||
| 60 | } | ||
| 61 | }; | ||
| 62 | |||
| 63 | pub const FileIndex = enum(u32) { | ||
| 64 | root = 0, | ||
| 65 | _, | ||
| 66 | |||
| 67 | fn get(fi: FileIndex, unit: *Unit) Zcu.File.Index { | ||
| 68 | return unit.files.keys()[@backingInt(fi)]; | ||
| 69 | } | ||
| 70 | }; | ||
| 71 | |||
| 72 | fn deinit(unit: *Unit, gpa: std.mem.Allocator) void { | ||
| 73 | unit.dirs.deinit(gpa); | ||
| 74 | unit.files.deinit(gpa); | ||
| 75 | unit.* = undefined; | ||
| 76 | } | ||
| 77 | |||
| 78 | fn getFile( | ||
| 79 | unit: *Unit, | ||
| 80 | gpa: std.mem.Allocator, | ||
| 81 | ui: Unit.Index, | ||
| 82 | zfi: Zcu.File.Index, | ||
| 83 | ) std.mem.Allocator.Error!struct { DirIndex, FileIndex } { | ||
| 84 | try unit.dirs.ensureUnusedCapacity(gpa, 1); | ||
| 85 | try unit.files.ensureUnusedCapacity(gpa, 1); | ||
| 86 | const dir_gop = unit.dirs.getOrPutAssumeCapacity(ui); | ||
| 87 | const file_gop = unit.files.getOrPutAssumeCapacity(zfi); | ||
| 88 | if (!dir_gop.found_existing or !file_gop.found_existing) unit.debug_line_header_changed = true; | ||
| 89 | return .{ @fromBackingInt(@intCast(dir_gop.index)), @fromBackingInt(@intCast(file_gop.index)) }; | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn cleanDebugLineHeaderChanged(unit: *Unit) bool { | ||
| 93 | defer unit.debug_line_header_changed = false; | ||
| 94 | return unit.debug_line_header_changed; | ||
| 95 | } | ||
| 96 | }; | ||
| 97 | |||
| 98 | pub const Const = struct { | ||
| 99 | debug_info_ni: link.MappedFile.Node.Index.Optional, | ||
| 100 | |||
| 101 | pub fn get(cpi: link.ConstPool.Index, dwarf: *Dwarf) *Const { | ||
| 102 | return &dwarf.consts.items[@backingInt(cpi)]; | ||
| 103 | } | ||
| 104 | }; | ||
| 105 | |||
| 106 | pub const Global = struct { | ||
| 107 | debug_info_ni: link.MappedFile.Node.Index.Optional, | ||
| 108 | |||
| 109 | pub const Index = enum(u32) { | ||
| 110 | _, | ||
| 111 | |||
| 112 | pub fn nav(gi: Global.Index, dwarf: *Dwarf) InternPool.Nav.Index { | ||
| 113 | return dwarf.globals.keys()[@backingInt(gi)]; | ||
| 114 | } | ||
| 115 | |||
| 116 | pub fn get(gi: Global.Index, dwarf: *Dwarf) *Global { | ||
| 117 | return &dwarf.globals.values()[@backingInt(gi)]; | ||
| 118 | } | ||
| 119 | }; | ||
| 120 | }; | ||
| 121 | |||
| 122 | pub const Func = struct { | ||
| 123 | state: State, | ||
| 124 | fde_ni: link.MappedFile.Node.Index.Optional, | ||
| 125 | debug_info_ni: link.MappedFile.Node.Index.Optional, | ||
| 126 | debug_line_ni: link.MappedFile.Node.Index.Optional, | ||
| 127 | |||
| 128 | pub const State = enum { unresolved, resolved }; | ||
| 129 | |||
| 130 | pub const Index = enum(u32) { | ||
| 131 | _, | ||
| 132 | |||
| 133 | pub fn nav(fi: Func.Index, dwarf: *Dwarf) InternPool.Nav.Index { | ||
| 134 | return dwarf.funcs.keys()[@backingInt(fi)]; | ||
| 135 | } | ||
| 136 | |||
| 137 | pub fn get(fi: Func.Index, dwarf: *Dwarf) *Func { | ||
| 138 | return &dwarf.funcs.values()[@backingInt(fi)]; | ||
| 139 | } | ||
| 140 | }; | ||
| 141 | }; | ||
| 142 | |||
| 143 | pub const Decl = struct { | ||
| 144 | debug_info_ni: link.MappedFile.Node.Index.Optional, | ||
| 145 | |||
| 146 | pub const Index = enum(u32) { | ||
| 147 | _, | ||
| 148 | |||
| 149 | pub fn srcInst(di: Decl.Index, dwarf: *Dwarf) InternPool.TrackedInst.Index { | ||
| 150 | return dwarf.decls.keys()[@backingInt(di)]; | ||
| 151 | } | ||
| 152 | |||
| 153 | pub fn get(di: Decl.Index, dwarf: *Dwarf) *Decl { | ||
| 154 | return &dwarf.decls.values()[@backingInt(di)]; | ||
| 155 | } | ||
| 156 | }; | ||
| 157 | }; | ||
| 158 | |||
| 159 | pub const Frame = struct { | ||
| 160 | header: Header, | ||
| 161 | |||
| 162 | pub const Header = struct { | ||
| 163 | code_alignment_factor: u32, | ||
| 164 | data_alignment_factor: i32, | ||
| 165 | return_address_register: u32, | ||
| 166 | initial_instructions: []const Cfa, | ||
| 167 | }; | ||
| 168 | |||
| 169 | pub const Format = std.debug.Dwarf.Unwind.Section; | ||
| 170 | }; | ||
| 171 | |||
| 172 | pub const Abbrev = struct { | ||
| 173 | ni: link.MappedFile.Node.Index.Optional, | ||
| 174 | end: usize, | ||
| 175 | set: std.enums.EnumSet(AbbrevCode), | ||
| 176 | }; | ||
| 177 | |||
| 178 | pub const Info = struct {}; | ||
| 179 | |||
| 180 | pub const Line = struct { | ||
| 181 | header: Header, | ||
| 182 | |||
| 183 | pub const Header = struct { | ||
| 184 | minimum_instruction_length: u8, | ||
| 185 | maximum_operations_per_instruction: u8, | ||
| 186 | default_is_stmt: bool, | ||
| 187 | line_base: i8, | ||
| 188 | line_range: u8, | ||
| 189 | opcode_base: u8, | ||
| 190 | }; | ||
| 191 | }; | ||
| 192 | |||
| 193 | pub const Str = struct { | ||
| 194 | ni: link.MappedFile.Node.Index.Optional, | ||
| 195 | offset: usize, | ||
| 196 | map: std.HashMapUnmanaged(usize, void, Context, std.hash_map.default_max_load_percentage), | ||
| 197 | |||
| 198 | fn get( | ||
| 199 | s: *Str, | ||
| 200 | gpa: std.mem.Allocator, | ||
| 201 | mf: *link.MappedFile, | ||
| 202 | str: []const u8, | ||
| 203 | ) link.MappedFile.Error!usize { | ||
| 204 | const ni = s.ni.unwrap().?; | ||
| 205 | const slice = ni.sliceConst(mf); | ||
| 206 | const gop = try s.map.getOrPutContextAdapted( | ||
| 207 | gpa, | ||
| 208 | str, | ||
| 209 | Adapter{ .slice = slice }, | ||
| 210 | .{ .slice = slice }, | ||
| 211 | ); | ||
| 212 | if (!gop.found_existing) { | ||
| 213 | gop.key_ptr.* = s.offset; | ||
| 214 | try ni.ensureMinimumSize(gpa, mf, s.offset + str.len + 1); | ||
| 215 | const slice_mut = ni.slice(mf); | ||
| 216 | @memcpy(slice_mut[s.offset..][0..str.len], str); | ||
| 217 | s.offset += str.len; | ||
| 218 | slice_mut[s.offset] = 0; | ||
| 219 | s.offset += 1; | ||
| 220 | } | ||
| 221 | return gop.key_ptr.*; | ||
| 222 | } | ||
| 223 | |||
| 224 | const Context = struct { | ||
| 225 | slice: []const u8, | ||
| 226 | pub fn hash(context: Context, offset: usize) u64 { | ||
| 227 | return std.hash.Wyhash.hash(0, std.mem.sliceTo(context.slice[offset..], 0)); | ||
| 228 | } | ||
| 229 | pub fn eql(_: Context, lhs_offset: usize, rhs_offset: usize) bool { | ||
| 230 | return lhs_offset == rhs_offset; | ||
| 231 | } | ||
| 232 | }; | ||
| 233 | |||
| 234 | const Adapter = struct { | ||
| 235 | slice: []const u8, | ||
| 236 | pub fn hash(_: Adapter, key: []const u8) u64 { | ||
| 237 | return std.hash.Wyhash.hash(0, key); | ||
| 238 | } | ||
| 239 | pub fn eql(adapter: Adapter, key: []const u8, rhs_offset: usize) bool { | ||
| 240 | return std.mem.startsWith(u8, adapter.slice[rhs_offset..], key) and | ||
| 241 | adapter.slice[rhs_offset + key.len] == 0; | ||
| 242 | } | ||
| 243 | }; | ||
| 244 | }; | ||
| 245 | |||
| 246 | pub const Rnglists = struct { | ||
| 247 | fn offsetsTableOffset(dwarf: *Dwarf) usize { | ||
| 248 | return dwarf.unitLengthSize() + 2 + 1 + 1 + 4; | ||
| 249 | } | ||
| 250 | }; | ||
| 251 | |||
| 252 | pub const StrOffsets = struct { | ||
| 253 | ni: link.MappedFile.Node.Index.Optional, | ||
| 254 | offset: usize, | ||
| 255 | }; | ||
| 256 | |||
| 257 | pub const SharedSection = enum { debug_abbrev, debug_line_str, debug_str, debug_str_offsets }; | ||
| 258 | |||
| 259 | pub const Loc = union(enum) { | ||
| 260 | empty, | ||
| 261 | addr_reloc: link.File.SymbolId, | ||
| 262 | deref: *const Loc, | ||
| 263 | constu: u64, | ||
| 264 | consts: i64, | ||
| 265 | plus: Bin, | ||
| 266 | reg: u32, | ||
| 267 | breg: u32, | ||
| 268 | push_object_address, | ||
| 269 | call: struct { | ||
| 270 | args: []const Loc = &.{}, | ||
| 271 | node: link.MappedFile.Node.Index, | ||
| 272 | }, | ||
| 273 | form_tls_address: *const Loc, | ||
| 274 | implicit_value: []const u8, | ||
| 275 | stack_value: *const Loc, | ||
| 276 | implicit_pointer: struct { | ||
| 277 | node: link.MappedFile.Node.Index, | ||
| 278 | offset: i65 = 0, | ||
| 279 | }, | ||
| 280 | wasm_ext: union(enum) { | ||
| 281 | local: u32, | ||
| 282 | global: u32, | ||
| 283 | operand_stack: u32, | ||
| 284 | }, | ||
| 285 | |||
| 286 | pub const Bin = struct { *const Loc, *const Loc }; | ||
| 287 | |||
| 288 | fn getConst(loc: Loc, comptime Int: type) ?Int { | ||
| 289 | return switch (loc) { | ||
| 290 | .constu => |constu| std.math.cast(Int, constu), | ||
| 291 | .consts => |consts| std.math.cast(Int, consts), | ||
| 292 | else => null, | ||
| 293 | }; | ||
| 294 | } | ||
| 295 | |||
| 296 | fn getBaseReg(loc: Loc) ?u32 { | ||
| 297 | return switch (loc) { | ||
| 298 | .breg => |breg| breg, | ||
| 299 | else => null, | ||
| 300 | }; | ||
| 301 | } | ||
| 302 | |||
| 303 | fn writeReg(reg: u32, op0: u8, opx: u8, writer: *std.Io.Writer) std.Io.Writer.Error!void { | ||
| 304 | if (std.math.cast(u5, reg)) |small_reg| { | ||
| 305 | try writer.writeByte(op0 + small_reg); | ||
| 306 | } else { | ||
| 307 | try writer.writeByte(opx); | ||
| 308 | try writer.writeUleb128(reg); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | fn write(loc: Loc, writer: union(enum) { | ||
| 313 | io: *std.Io.Writer, | ||
| 314 | mf: *link.MappedFile.Node.Writer, | ||
| 315 | }, dwarf: *Dwarf) link.EmitError!void { | ||
| 316 | const w = switch (writer) { | ||
| 317 | .io => |w| w, | ||
| 318 | .mf => |nw| &nw.interface, | ||
| 319 | }; | ||
| 320 | switch (loc) { | ||
| 321 | .empty => {}, | ||
| 322 | .addr_reloc => |si| { | ||
| 323 | try w.writeByte(DW.OP.addr); | ||
| 324 | switch (writer) { | ||
| 325 | .io => try dwarf.addrPlaceholder(w), | ||
| 326 | .mf => |nw| try dwarf.addrSym(nw, si, 0), | ||
| 327 | } | ||
| 328 | }, | ||
| 329 | .deref => |addr| { | ||
| 330 | try addr.write(writer, dwarf); | ||
| 331 | try w.writeByte(DW.OP.deref); | ||
| 332 | }, | ||
| 333 | .constu => |constu| if (std.math.cast(u5, constu)) |lit| { | ||
| 334 | try w.writeByte(@as(u8, DW.OP.lit0) + lit); | ||
| 335 | } else if (std.math.cast(u8, constu)) |const1u| { | ||
| 336 | try w.writeAll(&.{ DW.OP.const1u, const1u }); | ||
| 337 | } else if (std.math.cast(u16, constu)) |const2u| { | ||
| 338 | try w.writeByte(DW.OP.const2u); | ||
| 339 | try w.writeInt(u16, const2u, dwarf.endian); | ||
| 340 | } else if (std.math.cast(u21, constu)) |const3u| { | ||
| 341 | try w.writeByte(DW.OP.constu); | ||
| 342 | try w.writeUleb128(const3u); | ||
| 343 | } else if (std.math.cast(u32, constu)) |const4u| { | ||
| 344 | try w.writeByte(DW.OP.const4u); | ||
| 345 | try w.writeInt(u32, const4u, dwarf.endian); | ||
| 346 | } else if (std.math.cast(u49, constu)) |const7u| { | ||
| 347 | try w.writeByte(DW.OP.constu); | ||
| 348 | try w.writeUleb128(const7u); | ||
| 349 | } else { | ||
| 350 | try w.writeByte(DW.OP.const8u); | ||
| 351 | try w.writeInt(u64, constu, dwarf.endian); | ||
| 352 | }, | ||
| 353 | .consts => |consts| if (std.math.cast(i8, consts)) |const1s| { | ||
| 354 | try w.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) }); | ||
| 355 | } else if (std.math.cast(i16, consts)) |const2s| { | ||
| 356 | try w.writeByte(DW.OP.const2s); | ||
| 357 | try w.writeInt(i16, const2s, dwarf.endian); | ||
| 358 | } else if (std.math.cast(i21, consts)) |const3s| { | ||
| 359 | try w.writeByte(DW.OP.consts); | ||
| 360 | try w.writeSleb128(const3s); | ||
| 361 | } else if (std.math.cast(i32, consts)) |const4s| { | ||
| 362 | try w.writeByte(DW.OP.const4s); | ||
| 363 | try w.writeInt(i32, const4s, dwarf.endian); | ||
| 364 | } else if (std.math.cast(i49, consts)) |const7s| { | ||
| 365 | try w.writeByte(DW.OP.consts); | ||
| 366 | try w.writeSleb128(const7s); | ||
| 367 | } else { | ||
| 368 | try w.writeByte(DW.OP.const8s); | ||
| 369 | try w.writeInt(i64, consts, dwarf.endian); | ||
| 370 | }, | ||
| 371 | .plus => |plus| done: { | ||
| 372 | if (plus[0].getConst(u0)) |_| { | ||
| 373 | try plus[1].write(writer, dwarf); | ||
| 374 | break :done; | ||
| 375 | } | ||
| 376 | if (plus[1].getConst(u0)) |_| { | ||
| 377 | try plus[0].write(writer, dwarf); | ||
| 378 | break :done; | ||
| 379 | } | ||
| 380 | if (plus[0].getBaseReg()) |breg| { | ||
| 381 | if (plus[1].getConst(i65)) |offset| { | ||
| 382 | try writeReg(breg, DW.OP.breg0, DW.OP.bregx, w); | ||
| 383 | try w.writeSleb128(offset); | ||
| 384 | break :done; | ||
| 385 | } | ||
| 386 | } | ||
| 387 | if (plus[1].getBaseReg()) |breg| { | ||
| 388 | if (plus[0].getConst(i65)) |offset| { | ||
| 389 | try writeReg(breg, DW.OP.breg0, DW.OP.bregx, w); | ||
| 390 | try w.writeSleb128(offset); | ||
| 391 | break :done; | ||
| 392 | } | ||
| 393 | } | ||
| 394 | if (plus[0].getConst(u64)) |uconst| { | ||
| 395 | try plus[1].write(writer, dwarf); | ||
| 396 | try w.writeByte(DW.OP.plus_uconst); | ||
| 397 | try w.writeUleb128(uconst); | ||
| 398 | break :done; | ||
| 399 | } | ||
| 400 | if (plus[1].getConst(u64)) |uconst| { | ||
| 401 | try plus[0].write(writer, dwarf); | ||
| 402 | try w.writeByte(DW.OP.plus_uconst); | ||
| 403 | try w.writeUleb128(uconst); | ||
| 404 | break :done; | ||
| 405 | } | ||
| 406 | try plus[0].write(writer, dwarf); | ||
| 407 | try plus[1].write(writer, dwarf); | ||
| 408 | try w.writeByte(DW.OP.plus); | ||
| 409 | }, | ||
| 410 | .reg => |reg| try writeReg(reg, DW.OP.reg0, DW.OP.regx, w), | ||
| 411 | .breg => |breg| { | ||
| 412 | try writeReg(breg, DW.OP.breg0, DW.OP.bregx, w); | ||
| 413 | try w.writeSleb128(0); | ||
| 414 | }, | ||
| 415 | .push_object_address => try w.writeByte(DW.OP.push_object_address), | ||
| 416 | .call => |call| { | ||
| 417 | for (call.args) |arg| try arg.write(writer, dwarf); | ||
| 418 | try w.writeByte(DW.OP.call_ref); | ||
| 419 | switch (writer) { | ||
| 420 | .io => try dwarf.secOffsetPlaceholder(w), | ||
| 421 | .mf => |nw| try dwarf.secOffset(nw, call.node, 0), | ||
| 422 | } | ||
| 423 | }, | ||
| 424 | .form_tls_address => |addr| { | ||
| 425 | try addr.write(writer, dwarf); | ||
| 426 | try w.writeByte(DW.OP.form_tls_address); | ||
| 427 | }, | ||
| 428 | .implicit_value => |value| { | ||
| 429 | try w.writeByte(DW.OP.implicit_value); | ||
| 430 | try w.writeUleb128(value.len); | ||
| 431 | try w.writeAll(value); | ||
| 432 | }, | ||
| 433 | .stack_value => |value| { | ||
| 434 | try value.write(writer, dwarf); | ||
| 435 | try w.writeByte(DW.OP.stack_value); | ||
| 436 | }, | ||
| 437 | .implicit_pointer => |implicit_pointer| { | ||
| 438 | try w.writeByte(DW.OP.implicit_pointer); | ||
| 439 | switch (writer) { | ||
| 440 | .io => try dwarf.secOffsetPlaceholder(w), | ||
| 441 | .mf => |nw| try dwarf.secOffset(nw, implicit_pointer.node, 0), | ||
| 442 | } | ||
| 443 | try w.writeSleb128(implicit_pointer.offset); | ||
| 444 | }, | ||
| 445 | .wasm_ext => |wasm_ext| { | ||
| 446 | try w.writeByte(DW.OP.WASM_location); | ||
| 447 | switch (wasm_ext) { | ||
| 448 | .local => |local| { | ||
| 449 | try w.writeByte(DW.OP.WASM_local); | ||
| 450 | try w.writeUleb128(local); | ||
| 451 | }, | ||
| 452 | .global => |global| if (std.math.cast(u21, global)) |global_u21| { | ||
| 453 | try w.writeByte(DW.OP.WASM_global); | ||
| 454 | try w.writeUleb128(global_u21); | ||
| 455 | } else { | ||
| 456 | try w.writeByte(DW.OP.WASM_global_u32); | ||
| 457 | try w.writeInt(u32, global, dwarf.endian); | ||
| 458 | }, | ||
| 459 | .operand_stack => |operand_stack| { | ||
| 460 | try w.writeByte(DW.OP.WASM_operand_stack); | ||
| 461 | try w.writeUleb128(operand_stack); | ||
| 462 | }, | ||
| 463 | } | ||
| 464 | }, | ||
| 465 | } | ||
| 466 | } | ||
| 467 | }; | ||
| 468 | |||
| 469 | pub const Cfa = union(enum) { | ||
| 470 | nop, | ||
| 471 | advance_loc: u32, | ||
| 472 | offset: RegOff, | ||
| 473 | rel_offset: RegOff, | ||
| 474 | restore: u32, | ||
| 475 | undefined: u32, | ||
| 476 | same_value: u32, | ||
| 477 | register: [2]u32, | ||
| 478 | remember_state, | ||
| 479 | restore_state, | ||
| 480 | def_cfa: RegOff, | ||
| 481 | def_cfa_register: u32, | ||
| 482 | def_cfa_offset: i64, | ||
| 483 | adjust_cfa_offset: i64, | ||
| 484 | def_cfa_expression: Loc, | ||
| 485 | expression: RegExpr, | ||
| 486 | val_offset: RegOff, | ||
| 487 | val_expression: RegExpr, | ||
| 488 | escape: []const u8, | ||
| 489 | |||
| 490 | const RegOff = struct { reg: u32, off: i64 }; | ||
| 491 | const RegExpr = struct { reg: u32, expr: Loc }; | ||
| 492 | |||
| 493 | fn write(cfa: Cfa, wip_nav: *WipNav) link.EmitError!void { | ||
| 494 | const df_nw = &wip_nav.fde_writer; | ||
| 495 | const df_w = &df_nw.interface; | ||
| 496 | switch (cfa) { | ||
| 497 | .nop => try df_w.writeByte(DW.CFA.nop), | ||
| 498 | .advance_loc => |loc| { | ||
| 499 | const delta = | ||
| 500 | @divExact(loc - wip_nav.cfi.loc, wip_nav.dwarf.frame.header.code_alignment_factor); | ||
| 501 | if (delta == 0) {} else if (std.math.cast(u6, delta)) |small_delta| | ||
| 502 | try df_w.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta) | ||
| 503 | else if (std.math.cast(u8, delta)) |ubyte_delta| | ||
| 504 | try df_w.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta }) | ||
| 505 | else if (std.math.cast(u16, delta)) |uhalf_delta| { | ||
| 506 | try df_w.writeByte(DW.CFA.advance_loc2); | ||
| 507 | try df_w.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian); | ||
| 508 | } else if (std.math.cast(u32, delta)) |uword_delta| { | ||
| 509 | try df_w.writeByte(DW.CFA.advance_loc4); | ||
| 510 | try df_w.writeInt(u32, uword_delta, wip_nav.dwarf.endian); | ||
| 511 | } | ||
| 512 | wip_nav.cfi.loc = loc; | ||
| 513 | }, | ||
| 514 | .offset, .rel_offset => |reg_off| { | ||
| 515 | const factored_off = @divExact(reg_off.off - switch (cfa) { | ||
| 516 | else => unreachable, | ||
| 517 | .offset => 0, | ||
| 518 | .rel_offset => wip_nav.cfi.cfa.off, | ||
| 519 | }, wip_nav.dwarf.frame.header.data_alignment_factor); | ||
| 520 | if (std.math.cast(u63, factored_off)) |unsigned_off| { | ||
| 521 | if (std.math.cast(u6, reg_off.reg)) |small_reg| { | ||
| 522 | try df_w.writeByte(@as(u8, DW.CFA.offset) + small_reg); | ||
| 523 | } else { | ||
| 524 | try df_w.writeByte(DW.CFA.offset_extended); | ||
| 525 | try df_w.writeUleb128(reg_off.reg); | ||
| 526 | } | ||
| 527 | try df_w.writeUleb128(unsigned_off); | ||
| 528 | } else { | ||
| 529 | try df_w.writeByte(DW.CFA.offset_extended_sf); | ||
| 530 | try df_w.writeUleb128(reg_off.reg); | ||
| 531 | try df_w.writeSleb128(factored_off); | ||
| 532 | } | ||
| 533 | }, | ||
| 534 | .restore => |reg| if (std.math.cast(u6, reg)) |small_reg| | ||
| 535 | try df_w.writeByte(@as(u8, DW.CFA.restore) + small_reg) | ||
| 536 | else { | ||
| 537 | try df_w.writeByte(DW.CFA.restore_extended); | ||
| 538 | try df_w.writeUleb128(reg); | ||
| 539 | }, | ||
| 540 | .undefined => |reg| { | ||
| 541 | try df_w.writeByte(DW.CFA.undefined); | ||
| 542 | try df_w.writeUleb128(reg); | ||
| 543 | }, | ||
| 544 | .same_value => |reg| { | ||
| 545 | try df_w.writeByte(DW.CFA.same_value); | ||
| 546 | try df_w.writeUleb128(reg); | ||
| 547 | }, | ||
| 548 | .register => |regs| if (regs[0] != regs[1]) { | ||
| 549 | try df_w.writeByte(DW.CFA.register); | ||
| 550 | for (regs) |reg| try df_w.writeUleb128(reg); | ||
| 551 | } else { | ||
| 552 | try df_w.writeByte(DW.CFA.same_value); | ||
| 553 | try df_w.writeUleb128(regs[0]); | ||
| 554 | }, | ||
| 555 | .remember_state => try df_w.writeByte(DW.CFA.remember_state), | ||
| 556 | .restore_state => try df_w.writeByte(DW.CFA.restore_state), | ||
| 557 | .def_cfa, .def_cfa_register, .def_cfa_offset, .adjust_cfa_offset => { | ||
| 558 | const reg_off: RegOff = switch (cfa) { | ||
| 559 | else => unreachable, | ||
| 560 | .def_cfa => |reg_off| reg_off, | ||
| 561 | .def_cfa_register => |reg| .{ .reg = reg, .off = wip_nav.cfi.cfa.off }, | ||
| 562 | .def_cfa_offset => |off| .{ .reg = wip_nav.cfi.cfa.reg, .off = off }, | ||
| 563 | .adjust_cfa_offset => |off| .{ | ||
| 564 | .reg = wip_nav.cfi.cfa.reg, | ||
| 565 | .off = wip_nav.cfi.cfa.off + off, | ||
| 566 | }, | ||
| 567 | }; | ||
| 568 | const changed_reg = reg_off.reg != wip_nav.cfi.cfa.reg; | ||
| 569 | const unsigned_off = std.math.cast(u63, reg_off.off); | ||
| 570 | if (reg_off.off == wip_nav.cfi.cfa.off) { | ||
| 571 | if (changed_reg) { | ||
| 572 | try df_w.writeByte(DW.CFA.def_cfa_register); | ||
| 573 | try df_w.writeUleb128(reg_off.reg); | ||
| 574 | } | ||
| 575 | } else if (switch (wip_nav.dwarf.frame.header.data_alignment_factor) { | ||
| 576 | 0 => unreachable, | ||
| 577 | 1 => unsigned_off != null, | ||
| 578 | else => |data_alignment_factor| @rem(reg_off.off, data_alignment_factor) != 0, | ||
| 579 | }) { | ||
| 580 | try df_w.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset); | ||
| 581 | if (changed_reg) try df_w.writeUleb128(reg_off.reg); | ||
| 582 | try df_w.writeUleb128(unsigned_off.?); | ||
| 583 | } else { | ||
| 584 | try df_w.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf); | ||
| 585 | if (changed_reg) try df_w.writeUleb128(reg_off.reg); | ||
| 586 | try df_w.writeSleb128( | ||
| 587 | @divExact(reg_off.off, wip_nav.dwarf.frame.header.data_alignment_factor), | ||
| 588 | ); | ||
| 589 | } | ||
| 590 | wip_nav.cfi.cfa = reg_off; | ||
| 591 | }, | ||
| 592 | .def_cfa_expression => |expr| { | ||
| 593 | try df_w.writeByte(DW.CFA.def_cfa_expression); | ||
| 594 | try wip_nav.dwarf.exprLoc(df_nw, expr); | ||
| 595 | }, | ||
| 596 | .expression => |reg_expr| { | ||
| 597 | try df_w.writeByte(DW.CFA.expression); | ||
| 598 | try df_w.writeUleb128(reg_expr.reg); | ||
| 599 | try wip_nav.dwarf.exprLoc(df_nw, reg_expr.expr); | ||
| 600 | }, | ||
| 601 | .val_offset => |reg_off| { | ||
| 602 | const factored_off = | ||
| 603 | @divExact(reg_off.off, wip_nav.dwarf.frame.header.data_alignment_factor); | ||
| 604 | if (std.math.cast(u63, factored_off)) |unsigned_off| { | ||
| 605 | try df_w.writeByte(DW.CFA.val_offset); | ||
| 606 | try df_w.writeUleb128(reg_off.reg); | ||
| 607 | try df_w.writeUleb128(unsigned_off); | ||
| 608 | } else { | ||
| 609 | try df_w.writeByte(DW.CFA.val_offset_sf); | ||
| 610 | try df_w.writeUleb128(reg_off.reg); | ||
| 611 | try df_w.writeSleb128(factored_off); | ||
| 612 | } | ||
| 613 | }, | ||
| 614 | .val_expression => |reg_expr| { | ||
| 615 | try df_w.writeByte(DW.CFA.val_expression); | ||
| 616 | try df_w.writeUleb128(reg_expr.reg); | ||
| 617 | try wip_nav.dwarf.exprLoc(df_nw, reg_expr.expr); | ||
| 618 | }, | ||
| 619 | .escape => |bytes| try df_w.writeAll(bytes), | ||
| 620 | } | ||
| 621 | } | ||
| 622 | }; | ||
| 623 | |||
| 624 | pub const WipNav = struct { | ||
| 625 | dwarf: *Dwarf, | ||
| 626 | unit: Unit.Index, | ||
| 627 | func: InternPool.Index, | ||
| 628 | func_si: link.File.SymbolId, | ||
| 629 | cfi: struct { | ||
| 630 | loc: u32, | ||
| 631 | cfa: Cfa.RegOff, | ||
| 632 | }, | ||
| 633 | frame_format: Frame.Format, | ||
| 634 | fde_writer: link.MappedFile.Node.Writer, | ||
| 635 | frame_func_length: struct { offset: usize, size: AddressSize }, | ||
| 636 | |||
| 637 | pub const Debug = struct { | ||
| 638 | wip_nav: WipNav, | ||
| 639 | pt: Zcu.PerThread, | ||
| 640 | any_children: bool, | ||
| 641 | blocks: std.ArrayList(struct { | ||
| 642 | abbrev_code: u32, | ||
| 643 | low_pc_off: usize, | ||
| 644 | high_pc: u32, | ||
| 645 | }), | ||
| 646 | info_writer: link.MappedFile.Node.Writer, | ||
| 647 | info_func_length_offset: usize, | ||
| 648 | line_writer: link.MappedFile.Node.Writer, | ||
| 649 | |||
| 650 | pub fn deinit(debug: *Debug) void { | ||
| 651 | const gpa = debug.pt.zcu.gpa; | ||
| 652 | debug.line_writer.deinit(); | ||
| 653 | debug.info_writer.deinit(); | ||
| 654 | debug.blocks.deinit(gpa); | ||
| 655 | debug.wip_nav.deinit(); | ||
| 656 | debug.* = undefined; | ||
| 657 | } | ||
| 658 | |||
| 659 | pub fn genDebugFrame(debug: *Debug, loc: u32, cfa: Cfa) link.Error!void { | ||
| 660 | return debug.wip_nav.genDebugFrame(loc, cfa); | ||
| 661 | } | ||
| 662 | |||
| 663 | pub fn startFuncDebugInfo(debug: *Debug) link.Error!void { | ||
| 664 | assert(debug.wip_nav.func != .none); | ||
| 665 | debug.startFuncDebugInfoInner() catch |err| switch (err) { | ||
| 666 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 667 | else => |e| return e, | ||
| 668 | }; | ||
| 669 | } | ||
| 670 | fn startFuncDebugInfoInner(debug: *Debug) link.EmitError!void { | ||
| 671 | const dwarf = debug.wip_nav.dwarf; | ||
| 672 | const pt = debug.pt; | ||
| 673 | const zcu = pt.zcu; | ||
| 674 | const ip = &zcu.intern_pool; | ||
| 675 | const func = zcu.funcInfo(debug.wip_nav.func); | ||
| 676 | const nav = ip.getNav(func.owner_nav); | ||
| 677 | const func_type = ip.indexToKey(func.ty).func_type; | ||
| 678 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; | ||
| 679 | const zf = zcu.fileByIndex(inst_info.file); | ||
| 680 | const target = &zf.mod.?.resolved_target.result; | ||
| 681 | const decl = zf.zir.?.getDeclaration(inst_info.inst); | ||
| 682 | const di_nw = &debug.info_writer; | ||
| 683 | const di_w = &di_nw.interface; | ||
| 684 | try dwarf.abbrevCode(di_nw, .decl_func); | ||
| 685 | try dwarf.refType(pt, di_nw, .fromInterned(ip.namespacePtr(switch (func.generic_owner) { | ||
| 686 | .none => nav, | ||
| 687 | else => |generic_owner| ip.getNav(zcu.funcInfo(generic_owner).owner_nav), | ||
| 688 | }.analysis.?.namespace).owner_type)); | ||
| 689 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 690 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 691 | try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | ||
| 692 | try dwarf.strp(&dwarf.debug_str, di_nw, nav.name.toSlice(ip)); | ||
| 693 | try dwarf.strp(&dwarf.debug_str, di_nw, switch (decl.linkage) { | ||
| 694 | .normal => nav.fqn, | ||
| 695 | .@"extern", .@"export" => nav.name, | ||
| 696 | }.toSlice(ip)); | ||
| 697 | try dwarf.refType(pt, di_nw, .fromInterned(func_type.return_type)); | ||
| 698 | try dwarf.addrSym(di_nw, debug.wip_nav.func_si, 0); | ||
| 699 | debug.info_func_length_offset = di_w.end; | ||
| 700 | try di_w.writeInt(u32, undefined, dwarf.endian); | ||
| 701 | try di_w.writeUleb128( | ||
| 702 | target_info.minFunctionAlignment(target).max(nav.resolved.?.@"align").toByteUnits().?, | ||
| 703 | ); | ||
| 704 | try di_w.writeByte(@intFromBool(decl.linkage != .normal)); | ||
| 705 | try di_w.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); | ||
| 706 | } | ||
| 707 | |||
| 708 | pub fn startDebugLine(debug: *Debug) link.Error!void { | ||
| 709 | assert(debug.wip_nav.func != .none); | ||
| 710 | debug.startDebugLineInner() catch |err| switch (err) { | ||
| 711 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), | ||
| 712 | else => |e| return e, | ||
| 713 | }; | ||
| 714 | } | ||
| 715 | fn startDebugLineInner(debug: *Debug) link.EmitError!void { | ||
| 716 | const dwarf = debug.wip_nav.dwarf; | ||
| 717 | const zcu = debug.pt.zcu; | ||
| 718 | const ip = &zcu.intern_pool; | ||
| 719 | const func = zcu.funcInfo(debug.wip_nav.func); | ||
| 720 | const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?; | ||
| 721 | const zf = zcu.fileByIndex(inst_info.file); | ||
| 722 | const decl = zf.zir.?.getDeclaration(inst_info.inst); | ||
| 723 | const dl_nw = &debug.line_writer; | ||
| 724 | const dl_w = &dl_nw.interface; | ||
| 725 | try dl_w.writeByte(DW.LNS.extended_op); | ||
| 726 | if (zcu.comp.config.incremental) { | ||
| 727 | try dl_w.writeUleb128(1 + dwarf.secOffsetSize()); | ||
| 728 | try dl_w.writeByte(DW.LNE.ZIG_set_decl); | ||
| 729 | try dwarf.secOffset(dl_nw, debug.info_writer.ni, 0); | ||
| 730 | |||
| 731 | try dl_w.writeByte(DW.LNS.set_column); | ||
| 732 | try dl_w.writeUleb128(func.lbrace_column + 1); | ||
| 733 | |||
| 734 | try debug.advanceLineAndPc(func.lbrace_line, 0, false); | ||
| 735 | } else { | ||
| 736 | try dl_w.writeUleb128(1 + @backingInt(dwarf.address_size)); | ||
| 737 | try dl_w.writeByte(DW.LNE.set_address); | ||
| 738 | try dwarf.addrSym(dl_nw, debug.wip_nav.func_si, 0); | ||
| 739 | |||
| 740 | const unit = dwarf.getUnit(zf.mod.?); | ||
| 741 | _, const fi = try unit.get(dwarf).getFile(zcu.gpa, unit, inst_info.file); | ||
| 742 | try dl_w.writeByte(DW.LNS.set_file); | ||
| 743 | try dl_w.writeUleb128(@backingInt(fi)); | ||
| 744 | |||
| 745 | try dl_w.writeByte(DW.LNS.set_column); | ||
| 746 | try dl_w.writeUleb128(func.lbrace_column + 1); | ||
| 747 | |||
| 748 | try debug.advanceLineAndPc(decl.src_line + func.lbrace_line, 0, false); | ||
| 749 | } | ||
| 750 | } | ||
| 751 | |||
| 752 | pub fn finishFunc(debug: *Debug, func_length: u64) link.Error!void { | ||
| 753 | assert(debug.wip_nav.func != .none); | ||
| 754 | const di_nw = &debug.info_writer; | ||
| 755 | debug.finishDebugInfo(func_length) catch |err| switch (err) { | ||
| 756 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(di_nw), | ||
| 757 | else => |e| return e, | ||
| 758 | }; | ||
| 759 | debug.finishDebugLine() catch |err| switch (err) { | ||
| 760 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(di_nw), | ||
| 761 | else => |e| return e, | ||
| 762 | }; | ||
| 763 | } | ||
| 764 | fn finishDebugInfo(debug: *Debug, func_length: u64) link.EmitError!void { | ||
| 765 | const dwarf = debug.wip_nav.dwarf; | ||
| 766 | const di_w = &debug.info_writer.interface; | ||
| 767 | std.mem.writeInt( | ||
| 768 | u32, | ||
| 769 | di_w.buffered()[debug.info_func_length_offset..][0..4], | ||
| 770 | @intCast(func_length), | ||
| 771 | dwarf.endian, | ||
| 772 | ); | ||
| 773 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 774 | try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); | ||
| 775 | } | ||
| 776 | fn finishDebugLine(debug: *Debug) link.EmitError!void { | ||
| 777 | const dl_w = &debug.line_writer.interface; | ||
| 778 | try genDebugLinePadding(dl_w, dl_w.unusedCapacityLen()); | ||
| 779 | } | ||
| 780 | |||
| 781 | pub const LocalVarTag = enum { arg, local_var }; | ||
| 782 | pub fn genLocalVarDebugInfo( | ||
| 783 | debug: *Debug, | ||
| 784 | tag: LocalVarTag, | ||
| 785 | opt_name: ?[]const u8, | ||
| 786 | ty: Type, | ||
| 787 | loc: Loc, | ||
| 788 | ) link.Error!void { | ||
| 789 | return debug.genLocalVarDebugInfoInner(tag, opt_name, ty, loc) catch |err| switch (err) { | ||
| 790 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 791 | else => |e| e, | ||
| 792 | }; | ||
| 793 | } | ||
| 794 | fn genLocalVarDebugInfoInner( | ||
| 795 | debug: *Debug, | ||
| 796 | tag: LocalVarTag, | ||
| 797 | opt_name: ?[]const u8, | ||
| 798 | ty: Type, | ||
| 799 | loc: Loc, | ||
| 800 | ) link.EmitError!void { | ||
| 801 | assert(debug.wip_nav.func != .none); | ||
| 802 | const dwarf = debug.wip_nav.dwarf; | ||
| 803 | const di_nw = &debug.info_writer; | ||
| 804 | try dwarf.abbrevCode(di_nw, switch (tag) { | ||
| 805 | .arg => if (opt_name) |_| .arg else .unnamed_arg, | ||
| 806 | .local_var => if (opt_name) |_| .local_var else unreachable, | ||
| 807 | }); | ||
| 808 | if (opt_name) |name| try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 809 | try dwarf.refType(debug.pt, di_nw, ty); | ||
| 810 | try dwarf.exprLoc(di_nw, loc); | ||
| 811 | debug.any_children = true; | ||
| 812 | } | ||
| 813 | |||
| 814 | pub const LocalConstTag = enum { comptime_arg, local_const }; | ||
| 815 | pub fn genLocalConstDebugInfo( | ||
| 816 | debug: *Debug, | ||
| 817 | tag: LocalConstTag, | ||
| 818 | opt_name: ?[]const u8, | ||
| 819 | val: Value, | ||
| 820 | ) link.Error!void { | ||
| 821 | return debug.genLocalConstDebugInfoInner(tag, opt_name, val) catch |err| switch (err) { | ||
| 822 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 823 | else => |e| e, | ||
| 824 | }; | ||
| 825 | } | ||
| 826 | fn genLocalConstDebugInfoInner( | ||
| 827 | debug: *Debug, | ||
| 828 | tag: LocalConstTag, | ||
| 829 | opt_name: ?[]const u8, | ||
| 830 | val: Value, | ||
| 831 | ) link.EmitError!void { | ||
| 832 | assert(debug.wip_nav.func != .none); | ||
| 833 | const dwarf = debug.wip_nav.dwarf; | ||
| 834 | const pt = debug.pt; | ||
| 835 | const zcu = debug.pt.zcu; | ||
| 836 | const ty = val.typeOf(zcu); | ||
| 837 | const ty_class = ty.classify(zcu); | ||
| 838 | const di_nw = &debug.info_writer; | ||
| 839 | try dwarf.abbrevCode(di_nw, switch (tag) { | ||
| 840 | .comptime_arg => if (opt_name) |_| switch (ty_class) { | ||
| 841 | .no_possible_value => unreachable, | ||
| 842 | .one_possible_value => .comptime_arg, | ||
| 843 | .runtime => .comptime_arg_fully_runtime, | ||
| 844 | .partially_comptime => .comptime_arg_partially_comptime, | ||
| 845 | .fully_comptime => .comptime_arg_fully_comptime, | ||
| 846 | } else switch (ty_class) { | ||
| 847 | .no_possible_value => unreachable, | ||
| 848 | .one_possible_value => .unnamed_comptime_arg, | ||
| 849 | .runtime => .unnamed_comptime_arg_fully_runtime, | ||
| 850 | .partially_comptime => .unnamed_comptime_arg_partially_comptime, | ||
| 851 | .fully_comptime => .unnamed_comptime_arg_fully_comptime, | ||
| 852 | }, | ||
| 853 | .local_const => if (opt_name) |_| switch (ty_class) { | ||
| 854 | .no_possible_value => unreachable, | ||
| 855 | .one_possible_value => .local_const, | ||
| 856 | .runtime => .local_const_fully_runtime, | ||
| 857 | .partially_comptime => .local_const_partially_comptime, | ||
| 858 | .fully_comptime => .local_const_fully_comptime, | ||
| 859 | } else unreachable, | ||
| 860 | }); | ||
| 861 | if (opt_name) |name| try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 862 | try dwarf.refType(pt, di_nw, ty); | ||
| 863 | if (ty_class.hasRuntimeBits()) try dwarf.blockConst(pt, di_nw, val); | ||
| 864 | if (ty_class.comptimeOnly()) try dwarf.refConst(pt, di_nw, val); | ||
| 865 | debug.any_children = true; | ||
| 866 | } | ||
| 867 | |||
| 868 | pub fn genVarArgsDebugInfo(debug: *Debug) link.Error!void { | ||
| 869 | return debug.genVarArgsDebugInfoInner() catch |err| switch (err) { | ||
| 870 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 871 | else => |e| e, | ||
| 872 | }; | ||
| 873 | } | ||
| 874 | fn genVarArgsDebugInfoInner(debug: *Debug) link.EmitError!void { | ||
| 875 | assert(debug.wip_nav.func != .none); | ||
| 876 | try debug.wip_nav.dwarf.abbrevCode(&debug.info_writer, .is_var_args); | ||
| 877 | debug.any_children = true; | ||
| 878 | } | ||
| 879 | |||
| 880 | pub fn advanceLineAndPc( | ||
| 881 | debug: *Debug, | ||
| 882 | delta_line: i33, | ||
| 883 | delta_pc: u64, | ||
| 884 | end: bool, | ||
| 885 | ) link.Error!void { | ||
| 886 | return debug.advanceLineAndPcInner(delta_line, delta_pc, end) catch |err| switch (err) { | ||
| 887 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), | ||
| 888 | }; | ||
| 889 | } | ||
| 890 | fn advanceLineAndPcInner( | ||
| 891 | debug: *Debug, | ||
| 892 | delta_line: i33, | ||
| 893 | delta_pc: u64, | ||
| 894 | end: bool, | ||
| 895 | ) std.Io.Writer.Error!void { | ||
| 896 | const dl_w = &debug.line_writer.interface; | ||
| 897 | |||
| 898 | const header = debug.wip_nav.dwarf.debug_line.header; | ||
| 899 | assert(header.maximum_operations_per_instruction == 1); | ||
| 900 | const delta_op: u64 = 0; | ||
| 901 | |||
| 902 | const remaining_delta_line: i9 = @intCast(if (delta_line < header.line_base or | ||
| 903 | delta_line - header.line_base >= header.line_range) | ||
| 904 | remaining: { | ||
| 905 | assert(delta_line != 0); | ||
| 906 | try dl_w.writeByte(DW.LNS.advance_line); | ||
| 907 | try dl_w.writeSleb128(delta_line); | ||
| 908 | break :remaining 0; | ||
| 909 | } else delta_line); | ||
| 910 | |||
| 911 | const op_advance = @divExact(delta_pc, header.minimum_instruction_length) * | ||
| 912 | header.maximum_operations_per_instruction + delta_op; | ||
| 913 | const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range; | ||
| 914 | const remaining_op_advance: u8 = @intCast(if (end or | ||
| 915 | op_advance >= 2 * max_op_advance) | ||
| 916 | remaining: { | ||
| 917 | if (op_advance == max_op_advance) { | ||
| 918 | try dl_w.writeByte(DW.LNS.const_add_pc); | ||
| 919 | } else if (op_advance != 0) { | ||
| 920 | try dl_w.writeByte(DW.LNS.advance_pc); | ||
| 921 | try dl_w.writeUleb128(op_advance); | ||
| 922 | } else assert(end); | ||
| 923 | break :remaining 0; | ||
| 924 | } else if (op_advance >= max_op_advance) remaining: { | ||
| 925 | try dl_w.writeByte(DW.LNS.const_add_pc); | ||
| 926 | break :remaining op_advance - max_op_advance; | ||
| 927 | } else op_advance); | ||
| 928 | |||
| 929 | if (remaining_delta_line != 0 or remaining_op_advance != 0) { | ||
| 930 | assert(!end); | ||
| 931 | try dl_w.writeByte(@intCast((remaining_delta_line - header.line_base) + | ||
| 932 | (header.line_range * remaining_op_advance) + header.opcode_base)); | ||
| 933 | } else if (end) { | ||
| 934 | try dl_w.writeByte(DW.LNS.extended_op); | ||
| 935 | try dl_w.writeUleb128(1); | ||
| 936 | try dl_w.writeByte(DW.LNE.end_sequence); | ||
| 937 | } else try dl_w.writeByte(DW.LNS.copy); | ||
| 938 | } | ||
| 939 | |||
| 940 | pub fn setColumn(debug: *Debug, column: u32) link.Error!void { | ||
| 941 | return debug.setColumnInner(column) catch |err| switch (err) { | ||
| 942 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), | ||
| 943 | }; | ||
| 944 | } | ||
| 945 | fn setColumnInner(debug: *Debug, column: u32) std.Io.Writer.Error!void { | ||
| 946 | const dl_w = &debug.line_writer.interface; | ||
| 947 | try dl_w.writeByte(DW.LNS.set_column); | ||
| 948 | try dl_w.writeUleb128(column + 1); | ||
| 949 | } | ||
| 950 | |||
| 951 | pub fn negateStmt(debug: *Debug) link.Error!void { | ||
| 952 | return debug.negateStmtInner() catch |err| switch (err) { | ||
| 953 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), | ||
| 954 | }; | ||
| 955 | } | ||
| 956 | fn negateStmtInner(debug: *Debug) std.Io.Writer.Error!void { | ||
| 957 | try debug.line_writer.interface.writeByte(DW.LNS.negate_stmt); | ||
| 958 | } | ||
| 959 | |||
| 960 | pub fn setPrologueEnd(debug: *Debug) link.Error!void { | ||
| 961 | return debug.setPrologueEndInner() catch |err| switch (err) { | ||
| 962 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), | ||
| 963 | }; | ||
| 964 | } | ||
| 965 | fn setPrologueEndInner(debug: *Debug) std.Io.Writer.Error!void { | ||
| 966 | try debug.line_writer.interface.writeByte(DW.LNS.set_prologue_end); | ||
| 967 | } | ||
| 968 | |||
| 969 | pub fn setEpilogueBegin(debug: *Debug) link.Error!void { | ||
| 970 | return debug.setEpilogueBeginInner() catch |err| switch (err) { | ||
| 971 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), | ||
| 972 | }; | ||
| 973 | } | ||
| 974 | fn setEpilogueBeginInner(debug: *Debug) std.Io.Writer.Error!void { | ||
| 975 | try debug.line_writer.interface.writeByte(DW.LNS.set_epilogue_begin); | ||
| 976 | } | ||
| 977 | |||
| 978 | pub fn enterBlock(debug: *Debug, code_off: usize) link.Error!void { | ||
| 979 | return debug.enterBlockInner(code_off) catch |err| switch (err) { | ||
| 980 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 981 | else => |e| e, | ||
| 982 | }; | ||
| 983 | } | ||
| 984 | fn enterBlockInner(debug: *Debug, code_off: usize) link.EmitError!void { | ||
| 985 | const dwarf = debug.wip_nav.dwarf; | ||
| 986 | const block = try debug.blocks.addOne(dwarf.lf.comp.gpa); | ||
| 987 | |||
| 988 | const di_nw = &debug.info_writer; | ||
| 989 | const di_w = &di_nw.interface; | ||
| 990 | block.abbrev_code = @intCast(di_w.end); | ||
| 991 | try dwarf.abbrevCode(di_nw, .block); | ||
| 992 | block.low_pc_off = code_off; | ||
| 993 | try dwarf.addrSym(di_nw, debug.wip_nav.func_si, code_off); | ||
| 994 | block.high_pc = @intCast(di_w.end); | ||
| 995 | try di_w.writeInt(u32, 0, dwarf.endian); | ||
| 996 | debug.any_children = false; | ||
| 997 | } | ||
| 998 | |||
| 999 | pub fn leaveBlock(debug: *Debug, code_off: usize) link.Error!void { | ||
| 1000 | return debug.leaveBlockInner(code_off) catch |err| switch (err) { | ||
| 1001 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 1002 | else => |e| e, | ||
| 1003 | }; | ||
| 1004 | } | ||
| 1005 | fn leaveBlockInner(debug: *Debug, code_off: usize) link.EmitError!void { | ||
| 1006 | const dwarf = debug.wip_nav.dwarf; | ||
| 1007 | const block_size = comptime uleb128Size(@backingInt(AbbrevCode.block)); | ||
| 1008 | const block = debug.blocks.pop().?; | ||
| 1009 | |||
| 1010 | const di_nw = &debug.info_writer; | ||
| 1011 | const di_w = &di_nw.interface; | ||
| 1012 | if (debug.any_children) | ||
| 1013 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)) | ||
| 1014 | else | ||
| 1015 | std.leb.writeUnsignedFixed( | ||
| 1016 | block_size, | ||
| 1017 | di_w.buffered()[block.abbrev_code..][0..block_size], | ||
| 1018 | @intCast(try dwarf.refAbbrevCode(di_nw.mf, .empty_block)), | ||
| 1019 | ); | ||
| 1020 | std.mem.writeInt( | ||
| 1021 | u32, | ||
| 1022 | di_nw.interface.buffered()[block.high_pc..][0..4], | ||
| 1023 | @intCast(code_off - block.low_pc_off), | ||
| 1024 | dwarf.endian, | ||
| 1025 | ); | ||
| 1026 | debug.any_children = true; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | pub fn enterInlineFunc( | ||
| 1030 | debug: *Debug, | ||
| 1031 | func: InternPool.Index, | ||
| 1032 | code_off: usize, | ||
| 1033 | line: u32, | ||
| 1034 | column: u32, | ||
| 1035 | ) link.Error!void { | ||
| 1036 | return debug.enterInlineFuncInner(func, code_off, line, column) catch |err| switch (err) { | ||
| 1037 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 1038 | else => |e| e, | ||
| 1039 | }; | ||
| 1040 | } | ||
| 1041 | fn enterInlineFuncInner( | ||
| 1042 | debug: *Debug, | ||
| 1043 | func: InternPool.Index, | ||
| 1044 | code_off: usize, | ||
| 1045 | line: u32, | ||
| 1046 | column: u32, | ||
| 1047 | ) link.EmitError!void { | ||
| 1048 | const dwarf = debug.wip_nav.dwarf; | ||
| 1049 | const zcu = debug.pt.zcu; | ||
| 1050 | const block = try debug.blocks.addOne(zcu.gpa); | ||
| 1051 | |||
| 1052 | const di_nw = &debug.info_writer; | ||
| 1053 | const di_w = &di_nw.interface; | ||
| 1054 | block.abbrev_code = @intCast(di_w.end); | ||
| 1055 | try dwarf.abbrevCode(di_nw, .inlined_func); | ||
| 1056 | try debug.refFunc(func); | ||
| 1057 | try di_w.writeUleb128((if (zcu.comp.config.incremental) | ||
| 1058 | 0 | ||
| 1059 | else | ||
| 1060 | zcu.navSrcLine(zcu.funcInfo(debug.wip_nav.func).owner_nav) + 1) + line); | ||
| 1061 | try di_w.writeUleb128(column + 1); | ||
| 1062 | block.low_pc_off = code_off; | ||
| 1063 | try dwarf.addrSym(di_nw, debug.wip_nav.func_si, code_off); | ||
| 1064 | block.high_pc = @intCast(di_w.end); | ||
| 1065 | try di_w.writeInt(u32, 0, dwarf.endian); | ||
| 1066 | try debug.setInlineFunc(func); | ||
| 1067 | debug.any_children = false; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | pub fn leaveInlineFunc(debug: *Debug, func: InternPool.Index, code_off: usize) link.Error!void { | ||
| 1071 | return debug.leaveInlineFuncInner(func, code_off) catch |err| switch (err) { | ||
| 1072 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer), | ||
| 1073 | else => |e| e, | ||
| 1074 | }; | ||
| 1075 | } | ||
| 1076 | fn leaveInlineFuncInner( | ||
| 1077 | debug: *Debug, | ||
| 1078 | func: InternPool.Index, | ||
| 1079 | code_off: usize, | ||
| 1080 | ) link.EmitError!void { | ||
| 1081 | const dwarf = debug.wip_nav.dwarf; | ||
| 1082 | const inlined_func_size = comptime uleb128Size(@backingInt(AbbrevCode.inlined_func)); | ||
| 1083 | const block = debug.blocks.pop().?; | ||
| 1084 | |||
| 1085 | const di_nw = &debug.info_writer; | ||
| 1086 | const di_w = &di_nw.interface; | ||
| 1087 | if (debug.any_children) | ||
| 1088 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)) | ||
| 1089 | else | ||
| 1090 | std.leb.writeUnsignedFixed( | ||
| 1091 | inlined_func_size, | ||
| 1092 | di_w.buffered()[block.abbrev_code..][0..inlined_func_size], | ||
| 1093 | @intCast(try dwarf.refAbbrevCode(di_nw.mf, .empty_inlined_func)), | ||
| 1094 | ); | ||
| 1095 | std.mem.writeInt( | ||
| 1096 | u32, | ||
| 1097 | di_w.buffered()[block.high_pc..][0..4], | ||
| 1098 | @intCast(code_off - block.low_pc_off), | ||
| 1099 | dwarf.endian, | ||
| 1100 | ); | ||
| 1101 | try debug.setInlineFunc(func); | ||
| 1102 | debug.any_children = true; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | pub fn setInlineFunc(debug: *Debug, func: InternPool.Index) link.Error!void { | ||
| 1106 | return debug.setInlineFuncInner(func) catch |err| switch (err) { | ||
| 1107 | error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.line_writer), | ||
| 1108 | else => |e| e, | ||
| 1109 | }; | ||
| 1110 | } | ||
| 1111 | fn setInlineFuncInner(debug: *Debug, func: InternPool.Index) link.EmitError!void { | ||
| 1112 | const zcu = debug.pt.zcu; | ||
| 1113 | const ip = &zcu.intern_pool; | ||
| 1114 | const dwarf = debug.wip_nav.dwarf; | ||
| 1115 | if (debug.wip_nav.func == func) return; | ||
| 1116 | |||
| 1117 | const dl_nw = &debug.line_writer; | ||
| 1118 | const dl_w = &dl_nw.interface; | ||
| 1119 | const new_owner_nav = zcu.funcInfo(func).owner_nav; | ||
| 1120 | if (zcu.comp.config.incremental) { | ||
| 1121 | const new_func = try dwarf.getFunc(new_owner_nav); | ||
| 1122 | try dl_w.writeByte(DW.LNS.extended_op); | ||
| 1123 | try dl_w.writeUleb128(1 + dwarf.secOffsetSize()); | ||
| 1124 | try dl_w.writeByte(DW.LNE.ZIG_set_decl); | ||
| 1125 | try dwarf.secOffset(dl_nw, new_func.get(dwarf).debug_info_ni.unwrap().?, 0); | ||
| 1126 | return; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | const old_owner_nav = zcu.funcInfo(debug.wip_nav.func).owner_nav; | ||
| 1130 | const old_inst_info = ip.getNav(old_owner_nav).srcInst(ip).resolveFull(ip).?; | ||
| 1131 | const old_zf = zcu.fileByIndex(old_inst_info.file); | ||
| 1132 | const new_inst_info = ip.getNav(new_owner_nav).srcInst(ip).resolveFull(ip).?; | ||
| 1133 | const new_zf = zcu.fileByIndex(new_inst_info.file); | ||
| 1134 | if (old_inst_info.file != new_inst_info.file) { | ||
| 1135 | const new_ui = dwarf.getUnit(new_zf.mod.?); | ||
| 1136 | _, const new_fi = | ||
| 1137 | try debug.wip_nav.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_inst_info.file); | ||
| 1138 | |||
| 1139 | try dl_w.writeByte(DW.LNS.set_file); | ||
| 1140 | try dl_w.writeUleb128(@backingInt(new_fi)); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | const old_src_line: i33 = old_zf.zir.?.getDeclaration(old_inst_info.inst).src_line; | ||
| 1144 | const new_src_line: i33 = new_zf.zir.?.getDeclaration(new_inst_info.inst).src_line; | ||
| 1145 | if (new_src_line != old_src_line) { | ||
| 1146 | try dl_w.writeByte(DW.LNS.advance_line); | ||
| 1147 | try dl_w.writeSleb128(new_src_line - old_src_line); | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | debug.wip_nav.func = func; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | fn refFunc(debug: *Debug, func: InternPool.Index) link.EmitError!void { | ||
| 1154 | const dwarf = debug.wip_nav.dwarf; | ||
| 1155 | const fi = try dwarf.getFunc(debug.pt.zcu.funcInfo(func).owner_nav); | ||
| 1156 | try debug.wip_nav.dwarf.secOffset( | ||
| 1157 | &debug.info_writer, | ||
| 1158 | fi.get(dwarf).debug_info_ni.unwrap().?, | ||
| 1159 | 0, | ||
| 1160 | ); | ||
| 1161 | } | ||
| 1162 | }; | ||
| 1163 | |||
| 1164 | pub fn deinit(wip_nav: *WipNav) void { | ||
| 1165 | wip_nav.fde_writer.deinit(); | ||
| 1166 | wip_nav.* = undefined; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | pub fn genDebugFrameHeader(wip_nav: *WipNav) link.Error!void { | ||
| 1170 | wip_nav.genDebugFrameHeaderInner() catch |err| switch (err) { | ||
| 1171 | error.WriteFailed => return wip_nav.dwarf.reportWriteError(&wip_nav.fde_writer), | ||
| 1172 | else => |e| return e, | ||
| 1173 | }; | ||
| 1174 | } | ||
| 1175 | fn genDebugFrameHeaderInner(wip_nav: *WipNav) link.EmitError!void { | ||
| 1176 | assert(wip_nav.func != .none); | ||
| 1177 | const dwarf = wip_nav.dwarf; | ||
| 1178 | const df_nw = &wip_nav.fde_writer; | ||
| 1179 | const df_w = &df_nw.interface; | ||
| 1180 | try dwarf.genUnitLength(df_w); | ||
| 1181 | switch (wip_nav.frame_format) { | ||
| 1182 | .eh_frame => { | ||
| 1183 | try df_w.writeInt(u32, undefined, dwarf.endian); | ||
| 1184 | { | ||
| 1185 | const offset = df_w.end; | ||
| 1186 | try df_w.writeInt(u32, 0, dwarf.endian); | ||
| 1187 | if (dwarf.lf.cast(.elf2)) |elf| try elf.addReloc( | ||
| 1188 | @bitCast(df_nw.ni), | ||
| 1189 | offset, | ||
| 1190 | wip_nav.func_si, | ||
| 1191 | 0, | ||
| 1192 | .rel32(elf), | ||
| 1193 | ) else unreachable; | ||
| 1194 | } | ||
| 1195 | wip_nav.frame_func_length = .{ .offset = df_w.end, .size = .@"32" }; | ||
| 1196 | try df_w.writeInt(u32, undefined, dwarf.endian); | ||
| 1197 | try df_w.writeUleb128(0); | ||
| 1198 | }, | ||
| 1199 | .debug_frame => { | ||
| 1200 | try dwarf.secOffset(df_nw, wip_nav.unit.get(dwarf).cie_ni.unwrap().?, 0); | ||
| 1201 | try dwarf.addrSym(df_nw, wip_nav.func_si, 0); | ||
| 1202 | wip_nav.frame_func_length = .{ .offset = df_w.end, .size = dwarf.address_size }; | ||
| 1203 | try dwarf.addrPlaceholder(df_w); | ||
| 1204 | }, | ||
| 1205 | } | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) link.Error!void { | ||
| 1209 | return wip_nav.genDebugFrameInner(loc, cfa) catch |err| switch (err) { | ||
| 1210 | error.WriteFailed => return wip_nav.dwarf.reportWriteError(&wip_nav.fde_writer), | ||
| 1211 | else => |e| return e, | ||
| 1212 | }; | ||
| 1213 | } | ||
| 1214 | fn genDebugFrameInner(wip_nav: *WipNav, loc: u32, cfa: Cfa) link.EmitError!void { | ||
| 1215 | assert(wip_nav.func != .none); | ||
| 1216 | const loc_cfa: Cfa = .{ .advance_loc = loc }; | ||
| 1217 | try loc_cfa.write(wip_nav); | ||
| 1218 | try cfa.write(wip_nav); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | pub fn finishDebugFrameFde(wip_nav: *WipNav, func_length: u64) void { | ||
| 1222 | const dwarf = wip_nav.dwarf; | ||
| 1223 | const df_w = &wip_nav.fde_writer.interface; | ||
| 1224 | switch (wip_nav.frame_func_length.size) { | ||
| 1225 | _ => unreachable, | ||
| 1226 | .@"32" => std.mem.writeInt( | ||
| 1227 | u32, | ||
| 1228 | df_w.buffered()[wip_nav.frame_func_length.offset..][0..4], | ||
| 1229 | @intCast(func_length), | ||
| 1230 | dwarf.endian, | ||
| 1231 | ), | ||
| 1232 | .@"64" => std.mem.writeInt( | ||
| 1233 | u64, | ||
| 1234 | df_w.buffered()[wip_nav.frame_func_length.offset..][0..8], | ||
| 1235 | func_length, | ||
| 1236 | dwarf.endian, | ||
| 1237 | ), | ||
| 1238 | } | ||
| 1239 | @memset(df_w.unusedCapacitySlice(), DW.CFA.nop); | ||
| 1240 | } | ||
| 1241 | }; | ||
| 1242 | |||
| 1243 | pub fn init(lf: *link.File, format: DW.Format) Dwarf { | ||
| 1244 | const target = &lf.comp.root_mod.resolved_target.result; | ||
| 1245 | return .{ | ||
| 1246 | .lf = lf, | ||
| 1247 | .format = format, | ||
| 1248 | .address_size = switch (target.ptrBitWidth()) { | ||
| 1249 | 0...32 => .@"32", | ||
| 1250 | 33...64 => .@"64", | ||
| 1251 | else => unreachable, | ||
| 1252 | }, | ||
| 1253 | .endian = target.cpu.arch.endian(), | ||
| 1254 | .const_pool = .empty, | ||
| 1255 | |||
| 1256 | .units = &.{}, | ||
| 1257 | .consts = .empty, | ||
| 1258 | .globals = .empty, | ||
| 1259 | .funcs = .empty, | ||
| 1260 | .decls = .empty, | ||
| 1261 | .pending_decl = .{ .di = undefined, .instance_val = .none }, | ||
| 1262 | |||
| 1263 | .debug_abbrev = .{ | ||
| 1264 | .ni = .none, | ||
| 1265 | .end = 0, | ||
| 1266 | .set = .empty, | ||
| 1267 | }, | ||
| 1268 | .frame = .{ | ||
| 1269 | .header = if (target.cpu.arch == .x86_64 and target.ofmt == .elf) header: { | ||
| 1270 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 1271 | const Register = @import("../codegen/x86_64/bits.zig").Register; | ||
| 1272 | break :header comptime .{ | ||
| 1273 | .code_alignment_factor = 1, | ||
| 1274 | .data_alignment_factor = -8, | ||
| 1275 | .return_address_register = Register.rip.dwarfNum(), | ||
| 1276 | .initial_instructions = &.{ | ||
| 1277 | .{ .def_cfa = .{ .reg = Register.rsp.dwarfNum(), .off = 8 } }, | ||
| 1278 | .{ .offset = .{ .reg = Register.rip.dwarfNum(), .off = -8 } }, | ||
| 1279 | }, | ||
| 1280 | }; | ||
| 1281 | } else .{ | ||
| 1282 | .code_alignment_factor = undefined, | ||
| 1283 | .data_alignment_factor = undefined, | ||
| 1284 | .return_address_register = undefined, | ||
| 1285 | .initial_instructions = &.{}, | ||
| 1286 | }, | ||
| 1287 | }, | ||
| 1288 | .debug_info = .{}, | ||
| 1289 | .debug_line = .{ | ||
| 1290 | .header = switch (target.cpu.arch) { | ||
| 1291 | .x86_64, .aarch64 => .{ | ||
| 1292 | .minimum_instruction_length = 1, | ||
| 1293 | .maximum_operations_per_instruction = 1, | ||
| 1294 | .default_is_stmt = true, | ||
| 1295 | .line_base = -5, | ||
| 1296 | .line_range = 14, | ||
| 1297 | .opcode_base = DW.LNS.set_isa + 1, | ||
| 1298 | }, | ||
| 1299 | else => .{ | ||
| 1300 | .minimum_instruction_length = 1, | ||
| 1301 | .maximum_operations_per_instruction = 1, | ||
| 1302 | .default_is_stmt = true, | ||
| 1303 | .line_base = 0, | ||
| 1304 | .line_range = 1, | ||
| 1305 | .opcode_base = DW.LNS.set_isa + 1, | ||
| 1306 | }, | ||
| 1307 | }, | ||
| 1308 | }, | ||
| 1309 | .debug_line_str = .{ | ||
| 1310 | .ni = .none, | ||
| 1311 | .offset = 0, | ||
| 1312 | .map = .empty, | ||
| 1313 | }, | ||
| 1314 | .debug_rnglists = .{}, | ||
| 1315 | .debug_str = .{ | ||
| 1316 | .ni = .none, | ||
| 1317 | .offset = 0, | ||
| 1318 | .map = .empty, | ||
| 1319 | }, | ||
| 1320 | .debug_str_offsets = .{ | ||
| 1321 | .ni = .none, | ||
| 1322 | .offset = 0, | ||
| 1323 | }, | ||
| 1324 | }; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | pub fn deinit(dwarf: *Dwarf) void { | ||
| 1328 | const gpa = dwarf.lf.comp.gpa; | ||
| 1329 | dwarf.const_pool.deinit(gpa); | ||
| 1330 | for (dwarf.units) |*unit| unit.deinit(gpa); | ||
| 1331 | gpa.free(dwarf.units); | ||
| 1332 | dwarf.consts.deinit(gpa); | ||
| 1333 | dwarf.globals.deinit(gpa); | ||
| 1334 | dwarf.funcs.deinit(gpa); | ||
| 1335 | dwarf.decls.deinit(gpa); | ||
| 1336 | dwarf.debug_line_str.map.deinit(gpa); | ||
| 1337 | dwarf.debug_str.map.deinit(gpa); | ||
| 1338 | dwarf.* = undefined; | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | pub fn initUnits(dwarf: *Dwarf, gpa: std.mem.Allocator, units_len: usize) std.mem.Allocator.Error!void { | ||
| 1342 | assert(dwarf.units.len == 0); | ||
| 1343 | dwarf.units = try gpa.alloc(Unit, units_len); | ||
| 1344 | @memset(dwarf.units, .{ | ||
| 1345 | .alive = false, | ||
| 1346 | .dirs = .empty, | ||
| 1347 | .files = .empty, | ||
| 1348 | .frame_ni = .none, | ||
| 1349 | .cie_ni = .none, | ||
| 1350 | .debug_info_ni = .none, | ||
| 1351 | .debug_info_header_ni = .none, | ||
| 1352 | .debug_info_footer_ni = .none, | ||
| 1353 | .debug_line_ni = .none, | ||
| 1354 | .debug_line_header_ni = .none, | ||
| 1355 | .debug_line_header_changed = false, | ||
| 1356 | .debug_rnglists_ni = .none, | ||
| 1357 | .debug_rnglists_offsets_table_offset = undefined, | ||
| 1358 | .debug_rnglists_end = undefined, | ||
| 1359 | }); | ||
| 1360 | } | ||
| 1361 | pub fn updateUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!bool { | ||
| 1362 | var units_changed = false; | ||
| 1363 | for (zcu.module_roots.values(), dwarf.units, 0..) |root, *unit, ui| { | ||
| 1364 | const root_zfi = root.unwrap() orelse continue; // non-zig | ||
| 1365 | const alive = zcu.alive_files.contains(root_zfi); | ||
| 1366 | if (unit.alive == alive) continue; // unchanged | ||
| 1367 | unit.alive = alive; | ||
| 1368 | units_changed = true; | ||
| 1369 | if (!alive) continue; // unreferenced | ||
| 1370 | assert(zcu.fileByIndex(root_zfi).mod != null); | ||
| 1371 | const root_di, const root_fi = try unit.getFile( | ||
| 1372 | zcu.gpa, | ||
| 1373 | @fromBackingInt(@intCast(ui)), | ||
| 1374 | root_zfi, | ||
| 1375 | ); | ||
| 1376 | assert(root_di == .root and root_fi == .root); | ||
| 1377 | } | ||
| 1378 | return units_changed; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index { | ||
| 1382 | return @fromBackingInt(@intCast(dwarf.lf.comp.zcu.?.module_roots.getIndex(mod).?)); | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | pub fn getConst(dwarf: *Dwarf, pt: Zcu.PerThread, val: Value) link.Error!link.ConstPool.Index { | ||
| 1386 | assert(val.typeOf(pt.zcu).comptimeOnly(pt.zcu)); | ||
| 1387 | return dwarf.const_pool.get(pt, dwarf.constPoolUser(), val.toIntern()); | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Index { | ||
| 1391 | const comp = dwarf.lf.comp; | ||
| 1392 | const gpa = comp.gpa; | ||
| 1393 | const global_gop = try dwarf.globals.getOrPut(gpa, nav); | ||
| 1394 | if (!global_gop.found_existing) global_gop.value_ptr.* = .{ | ||
| 1395 | .debug_info_ni = .none, | ||
| 1396 | }; | ||
| 1397 | const gi: Global.Index = @fromBackingInt(@intCast(global_gop.index)); | ||
| 1398 | if (global_gop.value_ptr.debug_info_ni != .none) return gi; | ||
| 1399 | const mod = comp.zcu.?.navFileScope(nav).mod.?; | ||
| 1400 | assert(!mod.strip); | ||
| 1401 | const elf = dwarf.lf.cast(.elf2).?; | ||
| 1402 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | ||
| 1403 | try elf.dwarf_globals.append(gpa, .{ | ||
| 1404 | .debug_info_first_target_reloc = .none, | ||
| 1405 | .debug_info_first_node_reloc = .none, | ||
| 1406 | .debug_info_first_symbol_reloc = .none, | ||
| 1407 | }); | ||
| 1408 | const unit = dwarf.getUnit(mod).get(dwarf); | ||
| 1409 | global_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity( | ||
| 1410 | unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ | ||
| 1411 | .enable_next_moved = true, | ||
| 1412 | }) catch |err| switch (err) { | ||
| 1413 | else => |e| return e, | ||
| 1414 | error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ | ||
| 1415 | elf.mf.io_err.?, | ||
| 1416 | }), | ||
| 1417 | }, | ||
| 1418 | .{ .global_debug_info = gi }, | ||
| 1419 | )); | ||
| 1420 | return gi; | ||
| 1421 | } | ||
| 1422 | pub fn getGlobalIfExists(dwarf: *Dwarf, nav: InternPool.Nav.Index) ?Global.Index { | ||
| 1423 | return @fromBackingInt(@intCast(dwarf.globals.getIndex(nav) orelse return null)); | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | pub fn getFunc(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Func.Index { | ||
| 1427 | const comp = dwarf.lf.comp; | ||
| 1428 | const gpa = comp.gpa; | ||
| 1429 | const func_gop = try dwarf.funcs.getOrPut(gpa, nav); | ||
| 1430 | if (!func_gop.found_existing) func_gop.value_ptr.* = .{ | ||
| 1431 | .state = .unresolved, | ||
| 1432 | .fde_ni = .none, | ||
| 1433 | .debug_info_ni = .none, | ||
| 1434 | .debug_line_ni = .none, | ||
| 1435 | }; | ||
| 1436 | const fi: Func.Index = @fromBackingInt(@intCast(func_gop.index)); | ||
| 1437 | if (func_gop.value_ptr.debug_info_ni != .none) return fi; | ||
| 1438 | const mod = comp.zcu.?.navFileScope(nav).mod.?; | ||
| 1439 | const elf = dwarf.lf.cast(.elf2).?; | ||
| 1440 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | ||
| 1441 | try elf.dwarf_funcs.append(gpa, .{ | ||
| 1442 | .frame_fde_first_symbol_reloc = .none, | ||
| 1443 | .frame_fde_first_node_reloc = .none, | ||
| 1444 | .debug_info_first_target_reloc = .none, | ||
| 1445 | .debug_info_first_symbol_reloc = .none, | ||
| 1446 | .debug_info_first_node_reloc = .none, | ||
| 1447 | .debug_line_first_symbol_reloc = .none, | ||
| 1448 | .debug_line_first_node_reloc = .none, | ||
| 1449 | }); | ||
| 1450 | if (mod.strip) return fi; | ||
| 1451 | const unit = dwarf.getUnit(mod).get(dwarf); | ||
| 1452 | func_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity( | ||
| 1453 | unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ | ||
| 1454 | .enable_next_moved = true, | ||
| 1455 | }) catch |err| switch (err) { | ||
| 1456 | else => |e| return e, | ||
| 1457 | error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ | ||
| 1458 | elf.mf.io_err.?, | ||
| 1459 | }), | ||
| 1460 | }, | ||
| 1461 | .{ .func_debug_info = fi }, | ||
| 1462 | )); | ||
| 1463 | return fi; | ||
| 1464 | } | ||
| 1465 | pub fn getFuncIfExists(dwarf: *Dwarf, nav: InternPool.Nav.Index) ?Func.Index { | ||
| 1466 | return @fromBackingInt(@intCast(dwarf.funcs.getIndex(nav) orelse return null)); | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | fn getDeclInst(dwarf: *Dwarf, val: InternPool.Index) ?InternPool.TrackedInst.Index { | ||
| 1470 | const ip = &dwarf.lf.comp.zcu.?.intern_pool; | ||
| 1471 | switch (ip.indexToKey(val)) { | ||
| 1472 | else => unreachable, | ||
| 1473 | .struct_type, .union_type, .enum_type, .opaque_type => |container, tag| switch (container) { | ||
| 1474 | .declared => |declared| switch (declared.captures.owned.len) { | ||
| 1475 | 0 => return null, | ||
| 1476 | else => switch (tag) { | ||
| 1477 | else => unreachable, | ||
| 1478 | .struct_type => { | ||
| 1479 | const loaded_struct = ip.loadStructType(val); | ||
| 1480 | return ip.getNav(loaded_struct.name_nav.unwrap() orelse | ||
| 1481 | return loaded_struct.zir_index).srcInst(ip); | ||
| 1482 | }, | ||
| 1483 | .union_type => { | ||
| 1484 | const loaded_union = ip.loadUnionType(val); | ||
| 1485 | return ip.getNav(loaded_union.name_nav.unwrap() orelse | ||
| 1486 | return loaded_union.zir_index).srcInst(ip); | ||
| 1487 | }, | ||
| 1488 | .enum_type => { | ||
| 1489 | const loaded_enum = ip.loadEnumType(val); | ||
| 1490 | return ip.getNav(loaded_enum.name_nav.unwrap() orelse | ||
| 1491 | return loaded_enum.zir_index.unwrap().?).srcInst(ip); | ||
| 1492 | }, | ||
| 1493 | .opaque_type => { | ||
| 1494 | const loaded_opaque = ip.loadOpaqueType(val); | ||
| 1495 | return ip.getNav(loaded_opaque.name_nav.unwrap() orelse | ||
| 1496 | return loaded_opaque.zir_index).srcInst(ip); | ||
| 1497 | }, | ||
| 1498 | }, | ||
| 1499 | }, | ||
| 1500 | .reified => |reified| { | ||
| 1501 | assert(reified.zir_index.resolve(ip).? != .main_struct_inst); | ||
| 1502 | return reified.zir_index; | ||
| 1503 | }, | ||
| 1504 | .generated_union_tag => unreachable, | ||
| 1505 | }, | ||
| 1506 | .func => |func| return ip.getNav(switch (func.generic_owner) { | ||
| 1507 | .none => func.owner_nav, | ||
| 1508 | else => |generic_owner| ip.indexToKey(generic_owner).func.owner_nav, | ||
| 1509 | }).srcInst(ip), | ||
| 1510 | } | ||
| 1511 | } | ||
| 1512 | pub fn getDecl( | ||
| 1513 | dwarf: *Dwarf, | ||
| 1514 | pt: Zcu.PerThread, | ||
| 1515 | instance_val: InternPool.Index, | ||
| 1516 | ) link.Error!link.MappedFile.Node.Index { | ||
| 1517 | assert(dwarf.pending_decl.instance_val == .none); | ||
| 1518 | const comp = dwarf.lf.comp; | ||
| 1519 | const gpa = comp.gpa; | ||
| 1520 | const zcu = pt.zcu; | ||
| 1521 | const ip = &zcu.intern_pool; | ||
| 1522 | const inst = dwarf.getDeclInst(instance_val) orelse { | ||
| 1523 | const cpi = try dwarf.getConst(pt, .fromInterned(instance_val)); | ||
| 1524 | return Const.get(cpi, dwarf).debug_info_ni.unwrap().?; | ||
| 1525 | }; | ||
| 1526 | const decl_gop = try dwarf.decls.getOrPut(gpa, inst); | ||
| 1527 | if (!decl_gop.found_existing) decl_gop.value_ptr.* = .{ | ||
| 1528 | .debug_info_ni = .none, | ||
| 1529 | }; | ||
| 1530 | const di: Decl.Index = @fromBackingInt(@intCast(decl_gop.index)); | ||
| 1531 | if (decl_gop.value_ptr.debug_info_ni.unwrap()) |debug_info_ni| return debug_info_ni; | ||
| 1532 | dwarf.pending_decl = .{ .di = di, .instance_val = instance_val }; | ||
| 1533 | const elf = dwarf.lf.cast(.elf2).?; | ||
| 1534 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | ||
| 1535 | try elf.dwarf_decls.putNoClobber(gpa, di, .{ | ||
| 1536 | .debug_info_first_target_reloc = .none, | ||
| 1537 | .debug_info_first_node_reloc = .none, | ||
| 1538 | }); | ||
| 1539 | const unit = dwarf.getUnit(zcu.fileByIndex(di.srcInst(dwarf).resolveFile(ip)).mod.?).get(dwarf); | ||
| 1540 | const debug_info_ni = elf.addNodeAssumeCapacity( | ||
| 1541 | unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ | ||
| 1542 | .enable_next_moved = true, | ||
| 1543 | }) catch |err| switch (err) { | ||
| 1544 | else => |e| return e, | ||
| 1545 | error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ | ||
| 1546 | elf.mf.io_err.?, | ||
| 1547 | }), | ||
| 1548 | }, | ||
| 1549 | .{ .decl_debug_info = di }, | ||
| 1550 | ); | ||
| 1551 | decl_gop.value_ptr.debug_info_ni = .wrap(debug_info_ni); | ||
| 1552 | return debug_info_ni; | ||
| 1553 | } | ||
| 1554 | pub fn getDeclIfExists(dwarf: *Dwarf, inst: InternPool.TrackedInst.Index) ?Decl.Index { | ||
| 1555 | return @fromBackingInt(@intCast(dwarf.decls.getIndex(inst) orelse return null)); | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | pub fn unitLengthSize(dwarf: *Dwarf) usize { | ||
| 1559 | return switch (dwarf.format) { | ||
| 1560 | .@"32" => 4, | ||
| 1561 | .@"64" => 4 + 8, | ||
| 1562 | }; | ||
| 1563 | } | ||
| 1564 | pub fn genUnitLength(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { | ||
| 1565 | switch (dwarf.format) { | ||
| 1566 | .@"32" => try w.writeInt(u32, undefined, dwarf.endian), | ||
| 1567 | .@"64" => { | ||
| 1568 | try w.writeInt(u32, std.math.maxInt(u32), dwarf.endian); | ||
| 1569 | try w.writeInt(u64, undefined, dwarf.endian); | ||
| 1570 | }, | ||
| 1571 | } | ||
| 1572 | } | ||
| 1573 | pub fn updateUnitLength(dwarf: *Dwarf, header: []u8, unit_length: u64) void { | ||
| 1574 | switch (dwarf.format) { | ||
| 1575 | .@"32" => std.mem.writeInt(u32, header[0..4], @intCast(unit_length - 4), dwarf.endian), | ||
| 1576 | .@"64" => std.mem.writeInt(u64, header[4..12], unit_length - 12, dwarf.endian), | ||
| 1577 | } | ||
| 1578 | } | ||
| 1579 | |||
| 1580 | pub fn genUnitPadding(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { | ||
| 1581 | try dwarf.genUnitLength(w); | ||
| 1582 | try w.writeInt(u16, 0, dwarf.endian); | ||
| 1583 | } | ||
| 1584 | |||
| 1585 | pub const EhFrameHdr = extern struct { | ||
| 1586 | version: u8, | ||
| 1587 | eh_frame_ptr_enc: std.dwarf.EH.PE, | ||
| 1588 | fde_count_enc: std.dwarf.EH.PE, | ||
| 1589 | table_enc: std.dwarf.EH.PE, | ||
| 1590 | eh_frame_ptr: u32, | ||
| 1591 | }; | ||
| 1592 | pub fn genEhFrameHdr( | ||
| 1593 | dwarf: *Dwarf, | ||
| 1594 | eh_frame_hdr_ai: link.File.AtomId, | ||
| 1595 | eh_frame_hdr: *EhFrameHdr, | ||
| 1596 | eh_frame_si: link.File.SymbolId, | ||
| 1597 | ) link.Error!void { | ||
| 1598 | eh_frame_hdr.* = .{ | ||
| 1599 | .version = 1, | ||
| 1600 | .eh_frame_ptr_enc = .{ .type = .sdata4, .rel = .pcrel }, | ||
| 1601 | .fde_count_enc = .omit, | ||
| 1602 | .table_enc = .omit, | ||
| 1603 | .eh_frame_ptr = undefined, | ||
| 1604 | }; | ||
| 1605 | if (dwarf.lf.cast(.elf2)) |elf| try elf.addReloc( | ||
| 1606 | eh_frame_hdr_ai, | ||
| 1607 | @offsetOf(EhFrameHdr, "eh_frame_ptr"), | ||
| 1608 | eh_frame_si, | ||
| 1609 | 0, | ||
| 1610 | .rel32(elf), | ||
| 1611 | ) else unreachable; | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | pub fn genDebugFrameCie( | ||
| 1615 | dwarf: *Dwarf, | ||
| 1616 | df_w: *std.Io.Writer, | ||
| 1617 | /// `null` means to generate an architecture-agnostic padding cie | ||
| 1618 | arch: ?std.Target.Cpu.Arch, | ||
| 1619 | format: Frame.Format, | ||
| 1620 | ) std.Io.Writer.Error!void { | ||
| 1621 | try dwarf.genUnitLength(df_w); | ||
| 1622 | switch (format) { | ||
| 1623 | .eh_frame => try df_w.writeInt(u32, 0, dwarf.endian), | ||
| 1624 | .debug_frame => switch (dwarf.format) { | ||
| 1625 | .@"32" => try df_w.writeInt(u32, std.math.maxInt(u32), dwarf.endian), | ||
| 1626 | .@"64" => try df_w.writeInt(u64, std.math.maxInt(u64), dwarf.endian), | ||
| 1627 | }, | ||
| 1628 | } | ||
| 1629 | try df_w.writeByte(if (arch) |_| switch (format) { | ||
| 1630 | .eh_frame => 1, | ||
| 1631 | .debug_frame => 4, | ||
| 1632 | } else 0); | ||
| 1633 | switch (arch orelse return) { | ||
| 1634 | else => unreachable, | ||
| 1635 | .x86_64 => { | ||
| 1636 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 1637 | const Register = @import("../codegen/x86_64/bits.zig").Register; | ||
| 1638 | switch (format) { | ||
| 1639 | .eh_frame => try df_w.writeAll("zR\x00"), | ||
| 1640 | .debug_frame => { | ||
| 1641 | try df_w.writeAll("\x00"); | ||
| 1642 | try df_w.writeByte(@backingInt(dwarf.address_size)); | ||
| 1643 | try df_w.writeByte(0); | ||
| 1644 | }, | ||
| 1645 | } | ||
| 1646 | try df_w.writeUleb128(dwarf.frame.header.code_alignment_factor); | ||
| 1647 | try df_w.writeSleb128(dwarf.frame.header.data_alignment_factor); | ||
| 1648 | switch (format) { | ||
| 1649 | .eh_frame => try df_w.writeByte(@intCast(dwarf.frame.header.return_address_register)), | ||
| 1650 | .debug_frame => try df_w.writeUleb128(dwarf.frame.header.return_address_register), | ||
| 1651 | } | ||
| 1652 | switch (format) { | ||
| 1653 | .eh_frame => { | ||
| 1654 | try df_w.writeUleb128(1); | ||
| 1655 | try df_w.writeByte(@bitCast(@as(DW.EH.PE, .{ .type = .sdata4, .rel = .pcrel }))); | ||
| 1656 | }, | ||
| 1657 | .debug_frame => {}, | ||
| 1658 | } | ||
| 1659 | try df_w.writeByte(DW.CFA.def_cfa_sf); | ||
| 1660 | try df_w.writeUleb128(Register.rsp.dwarfNum()); | ||
| 1661 | try df_w.writeSleb128(-1); | ||
| 1662 | try df_w.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum()); | ||
| 1663 | try df_w.writeUleb128(1); | ||
| 1664 | }, | ||
| 1665 | } | ||
| 1666 | @memset(df_w.unusedCapacitySlice(), DW.CFA.nop); | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void { | ||
| 1670 | const cie_pointer_offset = dwarf.unitLengthSize(); | ||
| 1671 | std.mem.writeInt( | ||
| 1672 | u32, | ||
| 1673 | fde[cie_pointer_offset..][0..4], | ||
| 1674 | @intCast(fde_offset + cie_pointer_offset), | ||
| 1675 | dwarf.endian, | ||
| 1676 | ); | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | pub fn genDebugInfoHeader( | ||
| 1680 | dwarf: *Dwarf, | ||
| 1681 | zcu: *Zcu, | ||
| 1682 | mod: *Module, | ||
| 1683 | unit: *Unit, | ||
| 1684 | dih_nw: *link.MappedFile.Node.Writer, | ||
| 1685 | ) link.EmitError!void { | ||
| 1686 | const comp = zcu.comp; | ||
| 1687 | const dih_w = &dih_nw.interface; | ||
| 1688 | if (!unit.alive) return dwarf.genUnitPadding(dih_w); | ||
| 1689 | try dwarf.genUnitLength(dih_w); | ||
| 1690 | try dih_w.writeInt(u16, 5, dwarf.endian); | ||
| 1691 | try dih_w.writeByte(DW.UT.compile); | ||
| 1692 | try dih_w.writeByte(@backingInt(dwarf.address_size)); | ||
| 1693 | try dwarf.secOffset(dih_nw, dwarf.debug_abbrev.ni.unwrap().?, 0); | ||
| 1694 | const compile_unit_offset = dih_w.end; | ||
| 1695 | try dwarf.abbrevCode(dih_nw, .compile_unit); | ||
| 1696 | try dih_w.writeByte(DW.LANG.Zig); | ||
| 1697 | try dwarf.strp(&dwarf.debug_str, dih_nw, "zig " ++ @import("build_options").version); | ||
| 1698 | const root_dir_path = try mod.root.toAbsolute(&comp.dirs, comp.gpa); | ||
| 1699 | defer comp.gpa.free(root_dir_path); | ||
| 1700 | try dwarf.strp(&dwarf.debug_line_str, dih_nw, root_dir_path); | ||
| 1701 | try dwarf.strp(&dwarf.debug_line_str, dih_nw, mod.root_src_path); | ||
| 1702 | try dwarf.secOffset( | ||
| 1703 | dih_nw, | ||
| 1704 | dwarf.getUnit(zcu.root_mod).get(dwarf).debug_info_header_ni.unwrap().?, | ||
| 1705 | compile_unit_offset, | ||
| 1706 | ); | ||
| 1707 | try dwarf.secOffset(dih_nw, unit.debug_line_header_ni.unwrap().?, 0); | ||
| 1708 | try dwarf.secOffset(dih_nw, unit.debug_rnglists_ni.unwrap().?, Rnglists.offsetsTableOffset(dwarf)); | ||
| 1709 | try dih_w.writeUleb128(0); | ||
| 1710 | const module_offset = dih_w.end; | ||
| 1711 | try dwarf.abbrevCode(dih_nw, .module); | ||
| 1712 | try dwarf.strp(&dwarf.debug_str, dih_nw, mod.fully_qualified_name); | ||
| 1713 | try dih_w.writeUleb128(0); | ||
| 1714 | try dwarf.genModuleDependency( | ||
| 1715 | dih_nw, | ||
| 1716 | "builtin", | ||
| 1717 | zcu.builtin_modules.get(mod.getBuiltinOptions(comp.config).hash()).?, | ||
| 1718 | module_offset, | ||
| 1719 | ); | ||
| 1720 | try dwarf.genModuleDependency(dih_nw, "root", zcu.root_mod, module_offset); | ||
| 1721 | try dwarf.genModuleDependency(dih_nw, "std", zcu.std_mod, module_offset); | ||
| 1722 | for (mod.deps.keys(), mod.deps.values()) |name, dep| | ||
| 1723 | try dwarf.genModuleDependency(dih_nw, name, dep, module_offset); | ||
| 1724 | for ([2]AbbrevCode{ .pad_1, .pad_n }) |pad| _ = try dwarf.refAbbrevCode(dih_nw.mf, pad); | ||
| 1725 | try dwarf.genDebugInfoPadding(dih_w, dih_w.unusedCapacityLen()); | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | fn genModuleDependency( | ||
| 1729 | dwarf: *Dwarf, | ||
| 1730 | di_nw: *link.MappedFile.Node.Writer, | ||
| 1731 | name: []const u8, | ||
| 1732 | dep: *Module, | ||
| 1733 | module_offset: usize, | ||
| 1734 | ) link.EmitError!void { | ||
| 1735 | const dep_unit = dwarf.getUnit(dep).get(dwarf); | ||
| 1736 | if (!dep_unit.alive) return; | ||
| 1737 | try dwarf.abbrevCode(di_nw, .module_dependency); | ||
| 1738 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 1739 | try dwarf.secOffset(di_nw, dep_unit.debug_info_header_ni.unwrap().?, module_offset); | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | pub fn genDebugInfoPadding(dwarf: *Dwarf, di_w: *std.Io.Writer, size: u64) std.Io.Writer.Error!void { | ||
| 1743 | switch (size) { | ||
| 1744 | 0 => {}, | ||
| 1745 | 1 => try di_w.writeUleb128(dwarf.refAbbrevCodeIfExists(.pad_1).?), | ||
| 1746 | else => { | ||
| 1747 | const abbrev_code_offset = di_w.end; | ||
| 1748 | try di_w.writeUleb128(dwarf.refAbbrevCodeIfExists(.pad_n).?); | ||
| 1749 | const abbrev_code_size = di_w.end - abbrev_code_offset; | ||
| 1750 | var block_len_size: u5 = 1; | ||
| 1751 | while (true) switch (std.math.order( | ||
| 1752 | size - abbrev_code_size - block_len_size, | ||
| 1753 | @as(u64, 1) << 7 * block_len_size, | ||
| 1754 | )) { | ||
| 1755 | .lt => break try di_w.writeUleb128(size - abbrev_code_size - block_len_size), | ||
| 1756 | .eq => { | ||
| 1757 | // no length will ever work, so undercount and futz with | ||
| 1758 | // the leb encoding to make up the missing byte | ||
| 1759 | block_len_size += 1; | ||
| 1760 | std.leb.writeUnsignedExtended( | ||
| 1761 | try di_w.writableSlice(block_len_size), | ||
| 1762 | size - abbrev_code_size - block_len_size, | ||
| 1763 | ); | ||
| 1764 | break; | ||
| 1765 | }, | ||
| 1766 | .gt => block_len_size += 1, | ||
| 1767 | }; | ||
| 1768 | }, | ||
| 1769 | } | ||
| 1770 | } | ||
| 1771 | |||
| 1772 | pub fn genDebugLineHeader( | ||
| 1773 | dwarf: *Dwarf, | ||
| 1774 | unit: *Unit, | ||
| 1775 | dlh_nw: *link.MappedFile.Node.Writer, | ||
| 1776 | zcu: *Zcu, | ||
| 1777 | ) link.EmitError!void { | ||
| 1778 | const comp = zcu.comp; | ||
| 1779 | const dlh_w = &dlh_nw.interface; | ||
| 1780 | try dwarf.genUnitLength(dlh_w); | ||
| 1781 | try dlh_w.writeInt(u16, 5, dwarf.endian); | ||
| 1782 | try dlh_w.writeByte(@backingInt(dwarf.address_size)); | ||
| 1783 | try dlh_w.writeByte(0); | ||
| 1784 | const header_length_offset = dlh_w.end; | ||
| 1785 | switch (dwarf.format) { | ||
| 1786 | .@"32" => try dlh_w.writeInt(u32, undefined, dwarf.endian), | ||
| 1787 | .@"64" => try dlh_w.writeInt(u64, undefined, dwarf.endian), | ||
| 1788 | } | ||
| 1789 | const header_start = dlh_w.end; | ||
| 1790 | const StandardOpcode = DeclValEnum(DW.LNS); | ||
| 1791 | try dlh_w.writeAll(&.{ | ||
| 1792 | dwarf.debug_line.header.minimum_instruction_length, | ||
| 1793 | dwarf.debug_line.header.maximum_operations_per_instruction, | ||
| 1794 | @intFromBool(dwarf.debug_line.header.default_is_stmt), | ||
| 1795 | @bitCast(dwarf.debug_line.header.line_base), | ||
| 1796 | dwarf.debug_line.header.line_range, | ||
| 1797 | dwarf.debug_line.header.opcode_base, | ||
| 1798 | }); | ||
| 1799 | try dlh_w.writeAll(std.enums.EnumArray(StandardOpcode, u8).init(.{ | ||
| 1800 | .extended_op = undefined, | ||
| 1801 | .copy = 0, | ||
| 1802 | .advance_pc = 1, | ||
| 1803 | .advance_line = 1, | ||
| 1804 | .set_file = 1, | ||
| 1805 | .set_column = 1, | ||
| 1806 | .negate_stmt = 0, | ||
| 1807 | .set_basic_block = 0, | ||
| 1808 | .const_add_pc = 0, | ||
| 1809 | .fixed_advance_pc = 1, | ||
| 1810 | .set_prologue_end = 0, | ||
| 1811 | .set_epilogue_begin = 0, | ||
| 1812 | .set_isa = 1, | ||
| 1813 | }).values[1..dwarf.debug_line.header.opcode_base]); | ||
| 1814 | try dlh_w.writeByte(1); | ||
| 1815 | try dlh_w.writeUleb128(DW.LNCT.path); | ||
| 1816 | try dlh_w.writeUleb128(DW.FORM.line_strp); | ||
| 1817 | const dir_count = unit.dirs.count(); | ||
| 1818 | const directory_index_form: DeclValEnum(DW.FORM) = if (dir_count <= 1 << 8) | ||
| 1819 | .data1 | ||
| 1820 | else if (dir_count <= 1 << 16) | ||
| 1821 | .data2 | ||
| 1822 | else | ||
| 1823 | .udata; | ||
| 1824 | try dlh_w.writeUleb128(dir_count); | ||
| 1825 | for (unit.dirs.keys()) |ui| { | ||
| 1826 | const root_dir_path = try ui.mod(dwarf).root.toAbsolute(&zcu.comp.dirs, comp.gpa); | ||
| 1827 | defer comp.gpa.free(root_dir_path); | ||
| 1828 | try dwarf.strp(&dwarf.debug_line_str, dlh_nw, root_dir_path); | ||
| 1829 | } | ||
| 1830 | try dlh_w.writeByte(5); | ||
| 1831 | try dlh_w.writeUleb128(DW.LNCT.path); | ||
| 1832 | try dlh_w.writeUleb128(DW.FORM.line_strp); | ||
| 1833 | try dlh_w.writeUleb128(DW.LNCT.directory_index); | ||
| 1834 | try dlh_w.writeUleb128(@backingInt(directory_index_form)); | ||
| 1835 | try dlh_w.writeUleb128(DW.LNCT.timestamp); | ||
| 1836 | try dlh_w.writeUleb128(DW.FORM.data8); | ||
| 1837 | try dlh_w.writeUleb128(DW.LNCT.size); | ||
| 1838 | try dlh_w.writeUleb128(DW.FORM.data8); | ||
| 1839 | try dlh_w.writeUleb128(DW.LNCT.LLVM_source); | ||
| 1840 | try dlh_w.writeUleb128(DW.FORM.line_strp); | ||
| 1841 | try dlh_w.writeUleb128(unit.files.count()); | ||
| 1842 | for (unit.files.keys()) |zfi| { | ||
| 1843 | const zf = zcu.fileByIndex(zfi); | ||
| 1844 | try dwarf.strp(&dwarf.debug_line_str, dlh_nw, zf.sub_file_path); | ||
| 1845 | const di = | ||
| 1846 | if (zcu.alive_files.contains(zfi)) unit.dirs.getIndex(dwarf.getUnit(zf.mod.?)).? else 0; | ||
| 1847 | switch (directory_index_form) { | ||
| 1848 | else => unreachable, | ||
| 1849 | .data1 => try dlh_w.writeByte(@intCast(di)), | ||
| 1850 | .data2 => try dlh_w.writeInt(u16, @intCast(di), dwarf.endian), | ||
| 1851 | .udata => try dlh_w.writeUleb128(di), | ||
| 1852 | } | ||
| 1853 | try dlh_w.writeInt(i64, @truncate(zf.stat.mtime.nanoseconds), dwarf.endian); | ||
| 1854 | try dlh_w.writeInt(u64, zf.stat.size, dwarf.endian); | ||
| 1855 | try dwarf.strp( | ||
| 1856 | &dwarf.debug_line_str, | ||
| 1857 | dlh_nw, | ||
| 1858 | if (zf.is_builtin) zf.source.? else "", | ||
| 1859 | ); | ||
| 1860 | } | ||
| 1861 | switch (dwarf.format) { | ||
| 1862 | .@"32" => std.mem.writeInt( | ||
| 1863 | u32, | ||
| 1864 | dlh_w.buffer[header_length_offset..][0..4], | ||
| 1865 | @intCast(dlh_w.end - header_start), | ||
| 1866 | dwarf.endian, | ||
| 1867 | ), | ||
| 1868 | .@"64" => std.mem.writeInt( | ||
| 1869 | u64, | ||
| 1870 | dlh_w.buffer[header_length_offset..][0..8], | ||
| 1871 | dlh_w.end - header_start, | ||
| 1872 | dwarf.endian, | ||
| 1873 | ), | ||
| 1874 | } | ||
| 1875 | try genDebugLinePadding(dlh_w, dlh_w.unusedCapacityLen()); | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | pub fn genDebugLinePadding(dl_w: *std.Io.Writer, size: u64) std.Io.Writer.Error!void { | ||
| 1879 | switch (size) { | ||
| 1880 | 0 => {}, | ||
| 1881 | 1 => try dl_w.writeByte(DW.LNS.const_add_pc), | ||
| 1882 | 2 => try dl_w.writeAll(&.{ DW.LNS.negate_stmt, DW.LNS.negate_stmt }), | ||
| 1883 | else => { | ||
| 1884 | const extended_op_offset = dl_w.end; | ||
| 1885 | try dl_w.writeByte(DW.LNS.extended_op); | ||
| 1886 | const extended_op_size = dl_w.end - extended_op_offset; | ||
| 1887 | var op_len_size: u5 = 1; | ||
| 1888 | while (true) switch (std.math.order( | ||
| 1889 | size - extended_op_size - op_len_size, | ||
| 1890 | @as(u64, 1) << 7 * op_len_size, | ||
| 1891 | )) { | ||
| 1892 | .lt => break try dl_w.writeUleb128(size - extended_op_size - op_len_size), | ||
| 1893 | .eq => { | ||
| 1894 | // no length will ever work, so undercount and futz with | ||
| 1895 | // the leb encoding to make up the missing byte | ||
| 1896 | op_len_size += 1; | ||
| 1897 | std.leb.writeUnsignedExtended( | ||
| 1898 | try dl_w.writableSlice(op_len_size), | ||
| 1899 | size - extended_op_size - op_len_size, | ||
| 1900 | ); | ||
| 1901 | break; | ||
| 1902 | }, | ||
| 1903 | .gt => op_len_size += 1, | ||
| 1904 | }; | ||
| 1905 | try dl_w.writeByte(DW.LNE.padding); | ||
| 1906 | }, | ||
| 1907 | } | ||
| 1908 | } | ||
| 1909 | |||
| 1910 | pub fn genDebugRnglistsHeader( | ||
| 1911 | dwarf: *Dwarf, | ||
| 1912 | unit: *Unit, | ||
| 1913 | drh_nw: *link.MappedFile.Node.Writer, | ||
| 1914 | ) std.Io.Writer.Error!void { | ||
| 1915 | const drh_w = &drh_nw.interface; | ||
| 1916 | try dwarf.genUnitLength(drh_w); | ||
| 1917 | try drh_w.writeInt(u16, 5, dwarf.endian); | ||
| 1918 | try drh_w.writeByte(@backingInt(dwarf.address_size)); | ||
| 1919 | try drh_w.writeByte(0); | ||
| 1920 | try drh_w.writeInt(u32, 1, dwarf.endian); | ||
| 1921 | assert(drh_w.end == Rnglists.offsetsTableOffset(dwarf)); | ||
| 1922 | switch (dwarf.format) { | ||
| 1923 | .@"32" => try drh_w.writeInt(u32, 4, dwarf.endian), | ||
| 1924 | .@"64" => try drh_w.writeInt(u64, 8, dwarf.endian), | ||
| 1925 | } | ||
| 1926 | unit.debug_rnglists_end = drh_w.end; | ||
| 1927 | try drh_w.writeByte(DW.RLE.end_of_list); | ||
| 1928 | } | ||
| 1929 | |||
| 1930 | pub fn genDebugRnglists( | ||
| 1931 | dwarf: *Dwarf, | ||
| 1932 | unit: *Unit, | ||
| 1933 | dr_nw: *link.MappedFile.Node.Writer, | ||
| 1934 | func_si: link.File.SymbolId, | ||
| 1935 | func_length: u64, | ||
| 1936 | ) link.EmitError!void { | ||
| 1937 | const dr_w = &dr_nw.interface; | ||
| 1938 | dr_w.end = unit.debug_rnglists_end; | ||
| 1939 | try dr_w.writeByte(DW.RLE.start_length); | ||
| 1940 | try dwarf.addrSym(dr_nw, func_si, 0); | ||
| 1941 | try dr_w.writeUleb128(func_length); | ||
| 1942 | unit.debug_rnglists_end = dr_w.end; | ||
| 1943 | try dr_w.writeByte(DW.RLE.end_of_list); | ||
| 1944 | } | ||
| 1945 | |||
| 1946 | pub fn updateComptimeNav( | ||
| 1947 | dwarf: *Dwarf, | ||
| 1948 | pt: Zcu.PerThread, | ||
| 1949 | nav_index: InternPool.Nav.Index, | ||
| 1950 | ) link.Error!void { | ||
| 1951 | const zcu = pt.zcu; | ||
| 1952 | const ip = &zcu.intern_pool; | ||
| 1953 | const nav = ip.getNav(nav_index); | ||
| 1954 | log.debug("updateComptimeNav({f})", .{nav.fqn.fmt(ip)}); | ||
| 1955 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; | ||
| 1956 | const nav_val: Value = .fromInterned(nav.resolved.?.value); | ||
| 1957 | const zf = zcu.fileByIndex(inst_info.file); | ||
| 1958 | const decl = zf.zir.?.getDeclaration(inst_info.inst); | ||
| 1959 | switch (decl.kind) { | ||
| 1960 | .unnamed_test, .@"test", .decltest => return, | ||
| 1961 | .@"comptime", .@"const", .@"var" => {}, | ||
| 1962 | } | ||
| 1963 | done: switch (ip.indexToKey(nav_val.toIntern())) { | ||
| 1964 | .struct_type => { | ||
| 1965 | const loaded_struct = ip.loadStructType(nav_val.toIntern()); | ||
| 1966 | if (nav_index.toOptional() == loaded_struct.name_nav) { | ||
| 1967 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); | ||
| 1968 | break :done; | ||
| 1969 | } | ||
| 1970 | return; | ||
| 1971 | }, | ||
| 1972 | .enum_type => { | ||
| 1973 | const loaded_enum = ip.loadEnumType(nav_val.toIntern()); | ||
| 1974 | if (nav_index.toOptional() == loaded_enum.name_nav) { | ||
| 1975 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); | ||
| 1976 | break :done; | ||
| 1977 | } | ||
| 1978 | return; | ||
| 1979 | }, | ||
| 1980 | .union_type => { | ||
| 1981 | const loaded_union = ip.loadUnionType(nav_val.toIntern()); | ||
| 1982 | if (nav_index.toOptional() == loaded_union.name_nav) { | ||
| 1983 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); | ||
| 1984 | break :done; | ||
| 1985 | } | ||
| 1986 | return; | ||
| 1987 | }, | ||
| 1988 | .opaque_type => { | ||
| 1989 | const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); | ||
| 1990 | if (nav_index.toOptional() == loaded_opaque.name_nav) { | ||
| 1991 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); | ||
| 1992 | break :done; | ||
| 1993 | } | ||
| 1994 | return; | ||
| 1995 | }, | ||
| 1996 | .func => |func| if (func.owner_nav == nav_index and func.generic_owner == .none) { | ||
| 1997 | _ = try dwarf.const_pool.get(pt, dwarf.constPoolUser(), nav_val.toIntern()); | ||
| 1998 | break :done; | ||
| 1999 | } else return, | ||
| 2000 | |||
| 2001 | else => return, | ||
| 2002 | |||
| 2003 | // memoization, not values | ||
| 2004 | .memoized_call => unreachable, | ||
| 2005 | } | ||
| 2006 | try dwarf.const_pool.flushPending(pt, dwarf.constPoolUser()); | ||
| 2007 | } | ||
| 2008 | |||
| 2009 | pub fn addConst( | ||
| 2010 | dwarf: *Dwarf, | ||
| 2011 | cpi: link.ConstPool.Index, | ||
| 2012 | val: InternPool.Index, | ||
| 2013 | addConstNode: *const fn ( | ||
| 2014 | lf: *link.File, | ||
| 2015 | ui: Unit.Index, | ||
| 2016 | cpi: link.ConstPool.Index, | ||
| 2017 | ) link.Error!link.MappedFile.Node.Index, | ||
| 2018 | ) link.Error!void { | ||
| 2019 | const zcu = dwarf.lf.comp.zcu.?; | ||
| 2020 | const ip = &zcu.intern_pool; | ||
| 2021 | assert(@backingInt(cpi) == dwarf.consts.items.len); | ||
| 2022 | dwarf.consts.appendAssumeCapacity(.{ | ||
| 2023 | .debug_info_ni = debug_info_ni: switch (ip.indexToKey(val)) { | ||
| 2024 | else => try addConstNode(dwarf.lf, dwarf.getUnit(zcu.root_mod), cpi), | ||
| 2025 | .func => |func| { | ||
| 2026 | const fi = try dwarf.getFunc(func.owner_nav); | ||
| 2027 | break :debug_info_ni fi.get(dwarf).debug_info_ni.unwrap().?; | ||
| 2028 | }, | ||
| 2029 | .@"extern" => |@"extern"| { | ||
| 2030 | const gi = try dwarf.getGlobal(@"extern".owner_nav); | ||
| 2031 | break :debug_info_ni gi.get(dwarf).debug_info_ni.unwrap().?; | ||
| 2032 | }, | ||
| 2033 | .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| { | ||
| 2034 | if (switch (tag) { | ||
| 2035 | else => unreachable, | ||
| 2036 | .struct_type => ip.loadStructType(val).name_nav, | ||
| 2037 | .union_type => ip.loadUnionType(val).name_nav, | ||
| 2038 | .enum_type => ip.loadEnumType(val).name_nav, | ||
| 2039 | .opaque_type => ip.loadOpaqueType(val).name_nav, | ||
| 2040 | }.unwrap()) |name_nav| { | ||
| 2041 | const name_gi = try dwarf.getGlobal(name_nav); | ||
| 2042 | break :debug_info_ni name_gi.get(dwarf).debug_info_ni.unwrap().?; | ||
| 2043 | } | ||
| 2044 | break :debug_info_ni try addConstNode(dwarf.lf, dwarf.getUnit(zcu.fileByIndex( | ||
| 2045 | Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip), | ||
| 2046 | ).mod.?), cpi); | ||
| 2047 | }, | ||
| 2048 | }.toOptional(), | ||
| 2049 | }); | ||
| 2050 | } | ||
| 2051 | |||
| 2052 | pub fn updateConst( | ||
| 2053 | dwarf: *Dwarf, | ||
| 2054 | pt: Zcu.PerThread, | ||
| 2055 | di_nw: *link.MappedFile.Node.Writer, | ||
| 2056 | val: InternPool.Index, | ||
| 2057 | ) link.Error!void { | ||
| 2058 | switch (val) { | ||
| 2059 | .generic_poison_type => log.debug("updateConst(anytype)", .{}), | ||
| 2060 | else => log.debug("updateConst({f})", .{Value.fromInterned(val).fmtValue(pt)}), | ||
| 2061 | } | ||
| 2062 | dwarf.updateConstInner(pt, di_nw, val) catch |err| switch (err) { | ||
| 2063 | else => |e| return e, | ||
| 2064 | error.WriteFailed => return dwarf.reportWriteError(di_nw), | ||
| 2065 | }; | ||
| 2066 | } | ||
| 2067 | fn updateConstInner( | ||
| 2068 | dwarf: *Dwarf, | ||
| 2069 | pt: Zcu.PerThread, | ||
| 2070 | di_nw: *link.MappedFile.Node.Writer, | ||
| 2071 | val: InternPool.Index, | ||
| 2072 | ) link.EmitError!void { | ||
| 2073 | const zcu = pt.zcu; | ||
| 2074 | const ip = &zcu.intern_pool; | ||
| 2075 | const di_w = &di_nw.interface; | ||
| 2076 | switch (ip.indexToKey(val)) { | ||
| 2077 | .int_type => |int_type| { | ||
| 2078 | const ty: Type = .fromInterned(val); | ||
| 2079 | try dwarf.abbrevCode(di_nw, .numeric_type); | ||
| 2080 | var name_buf: [std.fmt.count("i{d}", .{std.math.maxInt(u16)})]u8 = undefined; | ||
| 2081 | try dwarf.strp(&dwarf.debug_str, di_nw, std.mem.print(&name_buf, "{f}", .{ | ||
| 2082 | ty.fmt(pt), | ||
| 2083 | }) catch unreachable); | ||
| 2084 | try di_w.writeByte(switch (int_type.signedness) { | ||
| 2085 | .signed => DW.ATE.signed, | ||
| 2086 | .unsigned => DW.ATE.unsigned, | ||
| 2087 | }); | ||
| 2088 | try di_w.writeUleb128(int_type.bits); | ||
| 2089 | try di_w.writeUleb128(ty.abiSize(zcu)); | ||
| 2090 | try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2091 | }, | ||
| 2092 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | ||
| 2093 | .one, .many, .c => { | ||
| 2094 | const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); | ||
| 2095 | defer zcu.gpa.free(name); | ||
| 2096 | try dwarf.abbrevCode(di_nw, switch (ptr_type.sentinel) { | ||
| 2097 | .none => switch (ptr_type.flags.alignment) { | ||
| 2098 | .none => .ptr_type, | ||
| 2099 | else => .ptr_aligned_type, | ||
| 2100 | }, | ||
| 2101 | else => switch (ptr_type.flags.alignment) { | ||
| 2102 | .none => .ptr_sentinel_type, | ||
| 2103 | else => .ptr_aligned_sentinel_type, | ||
| 2104 | }, | ||
| 2105 | }); | ||
| 2106 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2107 | switch (ptr_type.sentinel) { | ||
| 2108 | .none => {}, | ||
| 2109 | else => |sentinel| try dwarf.blockConst(pt, di_nw, .fromInterned(sentinel)), | ||
| 2110 | } | ||
| 2111 | if (ptr_type.flags.alignment.toByteUnits()) |a| try di_w.writeUleb128(a); | ||
| 2112 | try di_w.writeByte(@backingInt(ptr_type.flags.address_space)); | ||
| 2113 | if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try dwarf.secOffset( | ||
| 2114 | di_nw, | ||
| 2115 | di_nw.ni, | ||
| 2116 | di_w.end + dwarf.secOffsetSize(), | ||
| 2117 | ); | ||
| 2118 | if (ptr_type.flags.is_const) { | ||
| 2119 | try dwarf.abbrevCode(di_nw, .is_const); | ||
| 2120 | if (ptr_type.flags.is_volatile) try dwarf.secOffset( | ||
| 2121 | di_nw, | ||
| 2122 | di_nw.ni, | ||
| 2123 | di_w.end + dwarf.secOffsetSize(), | ||
| 2124 | ); | ||
| 2125 | } | ||
| 2126 | if (ptr_type.flags.is_volatile) try dwarf.abbrevCode(di_nw, .is_volatile); | ||
| 2127 | try dwarf.refType(pt, di_nw, .fromInterned(ptr_type.child)); | ||
| 2128 | }, | ||
| 2129 | .slice => { | ||
| 2130 | const ty: Type = .fromInterned(val); | ||
| 2131 | const name = try zcu.gpa.print("{f}", .{ty.fmt(pt)}); | ||
| 2132 | defer zcu.gpa.free(name); | ||
| 2133 | try dwarf.abbrevCode(di_nw, .generated_struct_type); | ||
| 2134 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2135 | try di_w.writeUleb128(ty.abiSize(zcu)); | ||
| 2136 | try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2137 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2138 | try dwarf.strp(&dwarf.debug_str, di_nw, "ptr"); | ||
| 2139 | const ptr_field_ty = ty.slicePtrFieldType(zcu); | ||
| 2140 | try dwarf.refType(pt, di_nw, ptr_field_ty); | ||
| 2141 | try di_w.writeUleb128(0); | ||
| 2142 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2143 | try dwarf.strp(&dwarf.debug_str, di_nw, "len"); | ||
| 2144 | const len_field_ty: Type = .usize; | ||
| 2145 | try dwarf.refType(pt, di_nw, len_field_ty); | ||
| 2146 | try di_w.writeUleb128(len_field_ty.abiAlignment(zcu).forward(ptr_field_ty.abiSize(zcu))); | ||
| 2147 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2148 | }, | ||
| 2149 | }, | ||
| 2150 | .array_type => |array_type| { | ||
| 2151 | const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); | ||
| 2152 | defer zcu.gpa.free(name); | ||
| 2153 | try dwarf.abbrevCode( | ||
| 2154 | di_nw, | ||
| 2155 | if (array_type.sentinel == .none) .array_type else .array_sentinel_type, | ||
| 2156 | ); | ||
| 2157 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2158 | if (array_type.sentinel != .none) | ||
| 2159 | try dwarf.blockConst(pt, di_nw, .fromInterned(array_type.sentinel)); | ||
| 2160 | try dwarf.refType(pt, di_nw, .fromInterned(array_type.child)); | ||
| 2161 | try dwarf.abbrevCode(di_nw, .array_len); | ||
| 2162 | try dwarf.refType(pt, di_nw, .usize); | ||
| 2163 | try di_w.writeUleb128(array_type.len); | ||
| 2164 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2165 | }, | ||
| 2166 | .vector_type => |vector_type| { | ||
| 2167 | const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); | ||
| 2168 | defer zcu.gpa.free(name); | ||
| 2169 | try dwarf.abbrevCode(di_nw, .vector_type); | ||
| 2170 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2171 | try dwarf.refType(pt, di_nw, .fromInterned(vector_type.child)); | ||
| 2172 | try dwarf.abbrevCode(di_nw, .array_len); | ||
| 2173 | try dwarf.refType(pt, di_nw, .usize); | ||
| 2174 | try di_w.writeUleb128(vector_type.len); | ||
| 2175 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2176 | }, | ||
| 2177 | .opt_type => |opt_child_type_index| { | ||
| 2178 | const opt_ty: Type = .fromInterned(val); | ||
| 2179 | const opt_child_ty: Type = .fromInterned(opt_child_type_index); | ||
| 2180 | const opt_repr = optRepr(opt_child_ty, zcu); | ||
| 2181 | const name = try zcu.gpa.print("{f}", .{opt_ty.fmt(pt)}); | ||
| 2182 | defer zcu.gpa.free(name); | ||
| 2183 | try dwarf.abbrevCode(di_nw, .generated_union_type); | ||
| 2184 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2185 | try di_w.writeUleb128(opt_ty.abiSize(zcu)); | ||
| 2186 | try di_w.writeUleb128(opt_ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2187 | switch (opt_repr) { | ||
| 2188 | .opv_null => { | ||
| 2189 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2190 | try dwarf.strp(&dwarf.debug_str, di_nw, "null"); | ||
| 2191 | try dwarf.refType(pt, di_nw, .null); | ||
| 2192 | try di_w.writeUleb128(0); | ||
| 2193 | }, | ||
| 2194 | .unpacked, .error_set, .pointer => { | ||
| 2195 | try dwarf.abbrevCode(di_nw, .tagged_union); | ||
| 2196 | try dwarf.secOffset(di_nw, di_nw.ni, di_w.end + dwarf.secOffsetSize()); | ||
| 2197 | { | ||
| 2198 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2199 | try dwarf.strp(&dwarf.debug_str, di_nw, "has_value"); | ||
| 2200 | switch (opt_repr) { | ||
| 2201 | .opv_null => unreachable, | ||
| 2202 | .unpacked => { | ||
| 2203 | try dwarf.refType(pt, di_nw, .bool); | ||
| 2204 | try di_w.writeUleb128(if (opt_child_ty.hasRuntimeBits(zcu)) | ||
| 2205 | opt_child_ty.abiSize(zcu) | ||
| 2206 | else | ||
| 2207 | 0); | ||
| 2208 | }, | ||
| 2209 | .error_set => { | ||
| 2210 | try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); | ||
| 2211 | try di_w.writeUleb128(0); | ||
| 2212 | }, | ||
| 2213 | .pointer => { | ||
| 2214 | try dwarf.refType(pt, di_nw, .usize); | ||
| 2215 | try di_w.writeUleb128(0); | ||
| 2216 | }, | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | try dwarf.abbrevCode(di_nw, .tagged_union_field); | ||
| 2220 | try di_w.writeUleb128(DW.FORM.data1); | ||
| 2221 | try di_w.writeByte(0); | ||
| 2222 | { | ||
| 2223 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2224 | try dwarf.strp(&dwarf.debug_str, di_nw, "null"); | ||
| 2225 | try dwarf.refType(pt, di_nw, .null); | ||
| 2226 | try di_w.writeUleb128(0); | ||
| 2227 | } | ||
| 2228 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2229 | |||
| 2230 | try dwarf.abbrevCode(di_nw, .tagged_union_default_field); | ||
| 2231 | { | ||
| 2232 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2233 | try dwarf.strp(&dwarf.debug_str, di_nw, "?"); | ||
| 2234 | try dwarf.refType(pt, di_nw, opt_child_ty); | ||
| 2235 | try di_w.writeUleb128(0); | ||
| 2236 | } | ||
| 2237 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2238 | } | ||
| 2239 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2240 | }, | ||
| 2241 | } | ||
| 2242 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2243 | }, | ||
| 2244 | .anyframe_type => unreachable, | ||
| 2245 | .error_union_type => |error_union_type| { | ||
| 2246 | const eu_ty: Type = .fromInterned(val); | ||
| 2247 | const eu_error_set_ty: Type = .fromInterned(error_union_type.error_set_type); | ||
| 2248 | const eu_payload_ty: Type = .fromInterned(error_union_type.payload_type); | ||
| 2249 | const eu_error_set_offset, const eu_payload_offset = switch (error_union_type.payload_type) { | ||
| 2250 | .generic_poison_type => .{ 0, 0 }, | ||
| 2251 | else => .{ | ||
| 2252 | codegen.errUnionErrorOffset(eu_payload_ty, zcu), | ||
| 2253 | codegen.errUnionPayloadOffset(eu_payload_ty, zcu), | ||
| 2254 | }, | ||
| 2255 | }; | ||
| 2256 | const name = try zcu.gpa.print("{f}", .{eu_ty.fmt(pt)}); | ||
| 2257 | defer zcu.gpa.free(name); | ||
| 2258 | |||
| 2259 | try dwarf.abbrevCode(di_nw, .generated_union_type); | ||
| 2260 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2261 | if (error_union_type.error_set_type != .generic_poison_type and | ||
| 2262 | error_union_type.payload_type != .generic_poison_type) | ||
| 2263 | { | ||
| 2264 | try di_w.writeUleb128(eu_ty.abiSize(zcu)); | ||
| 2265 | try di_w.writeUleb128(eu_ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2266 | } else { | ||
| 2267 | try di_w.writeUleb128(0); | ||
| 2268 | try di_w.writeUleb128(1); | ||
| 2269 | } | ||
| 2270 | { | ||
| 2271 | try dwarf.abbrevCode(di_nw, .tagged_union); | ||
| 2272 | try dwarf.secOffset(di_nw, di_nw.ni, di_w.end + dwarf.secOffsetSize()); | ||
| 2273 | { | ||
| 2274 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2275 | try dwarf.strp(&dwarf.debug_str, di_nw, "is_error"); | ||
| 2276 | try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); | ||
| 2277 | try di_w.writeUleb128(eu_error_set_offset); | ||
| 2278 | |||
| 2279 | try dwarf.abbrevCode(di_nw, .tagged_union_field); | ||
| 2280 | try di_w.writeUleb128(DW.FORM.udata); | ||
| 2281 | try di_w.writeUleb128(0); | ||
| 2282 | { | ||
| 2283 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2284 | try dwarf.strp(&dwarf.debug_str, di_nw, "value"); | ||
| 2285 | try dwarf.refType(pt, di_nw, eu_payload_ty); | ||
| 2286 | try di_w.writeUleb128(eu_payload_offset); | ||
| 2287 | } | ||
| 2288 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2289 | |||
| 2290 | try dwarf.abbrevCode(di_nw, .tagged_union_default_field); | ||
| 2291 | { | ||
| 2292 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2293 | try dwarf.strp(&dwarf.debug_str, di_nw, "error"); | ||
| 2294 | try dwarf.refType(pt, di_nw, eu_error_set_ty); | ||
| 2295 | try di_w.writeUleb128(eu_error_set_offset); | ||
| 2296 | } | ||
| 2297 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2298 | } | ||
| 2299 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2300 | } | ||
| 2301 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2302 | }, | ||
| 2303 | .simple_type => |simple_type| switch (simple_type) { | ||
| 2304 | .f16, | ||
| 2305 | .f32, | ||
| 2306 | .f64, | ||
| 2307 | .f80, | ||
| 2308 | .f128, | ||
| 2309 | .usize, | ||
| 2310 | .isize, | ||
| 2311 | .c_char, | ||
| 2312 | .c_short, | ||
| 2313 | .c_ushort, | ||
| 2314 | .c_int, | ||
| 2315 | .c_uint, | ||
| 2316 | .c_long, | ||
| 2317 | .c_ulong, | ||
| 2318 | .c_longlong, | ||
| 2319 | .c_ulonglong, | ||
| 2320 | .c_longdouble, | ||
| 2321 | .bool, | ||
| 2322 | => { | ||
| 2323 | const ty: Type = .fromInterned(val); | ||
| 2324 | try dwarf.abbrevCode(di_nw, .numeric_type); | ||
| 2325 | try dwarf.strp(&dwarf.debug_str, di_nw, @tagName(simple_type)); | ||
| 2326 | try di_w.writeByte(if (val == .bool_type) | ||
| 2327 | DW.ATE.boolean | ||
| 2328 | else if (ty.isRuntimeFloat()) | ||
| 2329 | DW.ATE.float | ||
| 2330 | else if (ty.isSignedInt(zcu)) | ||
| 2331 | DW.ATE.signed | ||
| 2332 | else if (ty.isUnsignedInt(zcu)) | ||
| 2333 | DW.ATE.unsigned | ||
| 2334 | else | ||
| 2335 | unreachable); | ||
| 2336 | try di_w.writeUleb128(ty.bitSize(zcu)); | ||
| 2337 | try di_w.writeUleb128(ty.abiSize(zcu)); | ||
| 2338 | try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2339 | }, | ||
| 2340 | .generic_poison => { | ||
| 2341 | try dwarf.abbrevCode(di_nw, .void_type); | ||
| 2342 | try dwarf.strp(&dwarf.debug_str, di_nw, "anytype"); | ||
| 2343 | }, | ||
| 2344 | .anyopaque, | ||
| 2345 | .void, | ||
| 2346 | .type, | ||
| 2347 | .comptime_int, | ||
| 2348 | .comptime_float, | ||
| 2349 | .noreturn, | ||
| 2350 | .null, | ||
| 2351 | .undefined, | ||
| 2352 | .enum_literal, | ||
| 2353 | => { | ||
| 2354 | const ty: Type = .fromInterned(val); | ||
| 2355 | try dwarf.abbrevCode(di_nw, .void_type); | ||
| 2356 | var name_buf: ["@TypeOf(undefined)".len]u8 = undefined; | ||
| 2357 | try dwarf.strp(&dwarf.debug_str, di_nw, std.mem.print(&name_buf, "{f}", .{ | ||
| 2358 | ty.fmt(pt), | ||
| 2359 | }) catch unreachable); | ||
| 2360 | }, | ||
| 2361 | .anyerror => { | ||
| 2362 | const global_error_set_names = ip.global_error_set.getNamesFromMainThread(); | ||
| 2363 | try dwarf.abbrevCode(di_nw, if (global_error_set_names.len > 0) | ||
| 2364 | .generated_enum_type | ||
| 2365 | else | ||
| 2366 | .generated_empty_enum_type); | ||
| 2367 | try dwarf.strp(&dwarf.debug_str, di_nw, "anyerror"); | ||
| 2368 | try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); | ||
| 2369 | for (global_error_set_names, 1..) |name, value| { | ||
| 2370 | try dwarf.abbrevCode(di_nw, .enum_field); | ||
| 2371 | try di_w.writeUleb128(DW.FORM.udata); | ||
| 2372 | try di_w.writeUleb128(value); | ||
| 2373 | try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); | ||
| 2374 | } | ||
| 2375 | if (global_error_set_names.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2376 | }, | ||
| 2377 | .adhoc_inferred_error_set => unreachable, | ||
| 2378 | }, | ||
| 2379 | .tuple_type => |tuple_type| { | ||
| 2380 | const ty: Type = .fromInterned(val); | ||
| 2381 | const name = try zcu.gpa.print("{f}", .{ty.fmt(pt)}); | ||
| 2382 | defer zcu.gpa.free(name); | ||
| 2383 | if (tuple_type.types.len == 0) { | ||
| 2384 | try dwarf.abbrevCode(di_nw, .generated_empty_struct_type); | ||
| 2385 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2386 | try di_w.writeByte(@intFromBool(false)); | ||
| 2387 | } else { | ||
| 2388 | try dwarf.abbrevCode(di_nw, .generated_struct_type); | ||
| 2389 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2390 | try di_w.writeUleb128(ty.abiSize(zcu)); | ||
| 2391 | try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2392 | var field_byte_offset: u64 = 0; | ||
| 2393 | for (0..tuple_type.types.len) |field_index| { | ||
| 2394 | const comptime_value = tuple_type.values.get(ip)[field_index]; | ||
| 2395 | const field_ty: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); | ||
| 2396 | const comptime_value_class = switch (comptime_value) { | ||
| 2397 | .none => .no_possible_value, | ||
| 2398 | else => field_ty.classify(zcu), | ||
| 2399 | }; | ||
| 2400 | try dwarf.abbrevCode(di_nw, switch (comptime_value) { | ||
| 2401 | .none => .field, | ||
| 2402 | else => switch (comptime_value_class) { | ||
| 2403 | .no_possible_value, .one_possible_value => .field_comptime, | ||
| 2404 | .runtime => .field_comptime_fully_runtime, | ||
| 2405 | .partially_comptime => .field_comptime_partially_comptime, | ||
| 2406 | .fully_comptime => .field_comptime_fully_comptime, | ||
| 2407 | }, | ||
| 2408 | }); | ||
| 2409 | var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; | ||
| 2410 | try dwarf.strp(&dwarf.debug_str, di_nw, std.mem.print(&field_name_buf, "{d}", .{ | ||
| 2411 | field_index, | ||
| 2412 | }) catch unreachable); | ||
| 2413 | try dwarf.refType(pt, di_nw, field_ty); | ||
| 2414 | if (comptime_value == .none) { | ||
| 2415 | const field_align = field_ty.abiAlignment(zcu); | ||
| 2416 | field_byte_offset = field_align.forward(field_byte_offset); | ||
| 2417 | try di_w.writeUleb128(field_byte_offset); | ||
| 2418 | try di_w.writeUleb128(field_ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2419 | field_byte_offset += field_ty.abiSize(zcu); | ||
| 2420 | } | ||
| 2421 | if (comptime_value_class.hasRuntimeBits()) | ||
| 2422 | try dwarf.blockConst(pt, di_nw, .fromInterned(comptime_value)); | ||
| 2423 | if (comptime_value_class.comptimeOnly()) | ||
| 2424 | try dwarf.refConst(pt, di_nw, .fromInterned(comptime_value)); | ||
| 2425 | } | ||
| 2426 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2427 | } | ||
| 2428 | }, | ||
| 2429 | .struct_type => { | ||
| 2430 | const loaded_struct = ip.loadStructType(val); | ||
| 2431 | const zfi = loaded_struct.zir_index.resolveFile(ip); | ||
| 2432 | const zf = zcu.fileByIndex(zfi); | ||
| 2433 | const src_inst = loaded_struct.zir_index.resolve(ip); | ||
| 2434 | if (src_inst == .main_struct_inst) { | ||
| 2435 | assert(loaded_struct.captures.len == 0); | ||
| 2436 | const ui = dwarf.getUnit(zf.mod.?); | ||
| 2437 | _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, zfi); | ||
| 2438 | try dwarf.abbrevCode(di_nw, switch (loaded_struct.layout) { | ||
| 2439 | .auto => if (loaded_struct.field_types.len > 0) .file else .empty_file, | ||
| 2440 | .@"extern", .@"packed" => unreachable, | ||
| 2441 | }); | ||
| 2442 | try di_w.writeUleb128(@backingInt(fi)); | ||
| 2443 | try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); | ||
| 2444 | } else if (loaded_struct.captures.len > 0 or loaded_struct.is_reified) { | ||
| 2445 | try dwarf.abbrevCode(di_nw, if (loaded_struct.captures.len > 0 or | ||
| 2446 | loaded_struct.field_types.len > 0) switch (loaded_struct.layout) { | ||
| 2447 | .auto, .@"extern" => .decl_instance_struct, | ||
| 2448 | .@"packed" => .decl_instance_packed_struct, | ||
| 2449 | } else switch (loaded_struct.layout) { | ||
| 2450 | .auto, .@"extern" => .decl_instance_empty_struct, | ||
| 2451 | .@"packed" => .decl_instance_empty_packed_struct, | ||
| 2452 | }); | ||
| 2453 | try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); | ||
| 2454 | } else if (loaded_struct.name_nav.unwrap()) |name_ni| { | ||
| 2455 | const name_nav = ip.getNav(name_ni); | ||
| 2456 | const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); | ||
| 2457 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 2458 | name_nav.analysis.?.namespace, | ||
| 2459 | ).owner_type); | ||
| 2460 | try dwarf.abbrevCode(di_nw, if (loaded_struct.field_types.len > 0) | ||
| 2461 | switch (loaded_struct.layout) { | ||
| 2462 | .auto, .@"extern" => .decl_struct, | ||
| 2463 | .@"packed" => .decl_packed_struct, | ||
| 2464 | } | ||
| 2465 | else switch (loaded_struct.layout) { | ||
| 2466 | .auto, .@"extern" => .decl_empty_struct, | ||
| 2467 | .@"packed" => .decl_empty_packed_struct, | ||
| 2468 | }); | ||
| 2469 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 2470 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 2471 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 2472 | try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | ||
| 2473 | try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); | ||
| 2474 | } else { | ||
| 2475 | const decl = zf.zir.?.getStructDecl(src_inst.?); | ||
| 2476 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 2477 | ip.namespacePtr(loaded_struct.namespace).parent.unwrap().?, | ||
| 2478 | ).owner_type); | ||
| 2479 | try dwarf.abbrevCode(di_nw, if (loaded_struct.field_types.len > 0) | ||
| 2480 | switch (loaded_struct.layout) { | ||
| 2481 | .auto, .@"extern" => .type_decl_struct, | ||
| 2482 | .@"packed" => .type_decl_packed_struct, | ||
| 2483 | } | ||
| 2484 | else switch (loaded_struct.layout) { | ||
| 2485 | .auto, .@"extern" => .type_decl_empty_struct, | ||
| 2486 | .@"packed" => .type_decl_empty_packed_struct, | ||
| 2487 | }); | ||
| 2488 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 2489 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 2490 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 2491 | try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); | ||
| 2492 | } | ||
| 2493 | switch (loaded_struct.layout) { | ||
| 2494 | .auto, .@"extern" => { | ||
| 2495 | const ty: Type = .fromInterned(val); | ||
| 2496 | try di_w.writeUleb128(ty.abiSize(zcu)); | ||
| 2497 | try di_w.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2498 | try dwarf.genCaptures(pt, di_nw, loaded_struct.captures); | ||
| 2499 | for (0..loaded_struct.field_types.len) |field_index| { | ||
| 2500 | const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); | ||
| 2501 | // TODO: we currently don't emit information about default values for | ||
| 2502 | // non-`comptime` fields, because these default values are resolved at a | ||
| 2503 | // separate time in the compiler frontend. To emit this information, the | ||
| 2504 | // frontend needs to tell us when the default values are available: like | ||
| 2505 | // how `Zcu.PerThread.ensureTypeLayoutUpToDate` enqueues a link task to | ||
| 2506 | // indicate completion of the type's layout, a task should be enqueued | ||
| 2507 | // by `Zcu.PerThread.ensureStructDefaultsUpToDate`, and upon receiving | ||
| 2508 | // it we should patch the correct default field values in. | ||
| 2509 | const field_default = if (is_comptime) | ||
| 2510 | loaded_struct.field_defaults.getOrNone(ip, field_index) | ||
| 2511 | else | ||
| 2512 | .none; | ||
| 2513 | assert(!(is_comptime and field_default == .none)); | ||
| 2514 | const field_ty: Type = | ||
| 2515 | .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | ||
| 2516 | const field_default_class = switch (field_default) { | ||
| 2517 | .none => .no_possible_value, | ||
| 2518 | else => field_ty.classify(zcu), | ||
| 2519 | }; | ||
| 2520 | try dwarf.abbrevCode(di_nw, if (is_comptime) switch (field_default_class) { | ||
| 2521 | .no_possible_value, .one_possible_value => .field_comptime, | ||
| 2522 | .runtime => .field_comptime_fully_runtime, | ||
| 2523 | .partially_comptime => .field_comptime_partially_comptime, | ||
| 2524 | .fully_comptime => .field_comptime_fully_comptime, | ||
| 2525 | } else switch (field_default_class) { | ||
| 2526 | .no_possible_value, .one_possible_value => .field, | ||
| 2527 | .runtime => .field_default_fully_runtime, | ||
| 2528 | .partially_comptime => .field_default_partially_comptime, | ||
| 2529 | .fully_comptime => .field_default_fully_comptime, | ||
| 2530 | }); | ||
| 2531 | try dwarf.strp( | ||
| 2532 | &dwarf.debug_str, | ||
| 2533 | di_nw, | ||
| 2534 | loaded_struct.field_names.get(ip)[field_index].toSlice(ip), | ||
| 2535 | ); | ||
| 2536 | try dwarf.refType(pt, di_nw, field_ty); | ||
| 2537 | if (!is_comptime) { | ||
| 2538 | try di_w.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); | ||
| 2539 | try di_w.writeUleb128(loaded_struct.field_aligns.getOrNone( | ||
| 2540 | ip, | ||
| 2541 | field_index, | ||
| 2542 | ).toByteUnits() orelse field_ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2543 | } | ||
| 2544 | if (field_default_class.hasRuntimeBits()) | ||
| 2545 | try dwarf.blockConst(pt, di_nw, .fromInterned(field_default)); | ||
| 2546 | if (field_default_class.comptimeOnly()) | ||
| 2547 | try dwarf.refConst(pt, di_nw, .fromInterned(field_default)); | ||
| 2548 | } | ||
| 2549 | }, | ||
| 2550 | .@"packed" => { | ||
| 2551 | try dwarf.refType(pt, di_nw, .fromInterned(loaded_struct.packed_backing_int_type)); | ||
| 2552 | try dwarf.genCaptures(pt, di_nw, loaded_struct.captures); | ||
| 2553 | var field_bit_offset: u16 = 0; | ||
| 2554 | for (0..loaded_struct.field_types.len) |field_index| { | ||
| 2555 | try dwarf.abbrevCode(di_nw, .packed_field); | ||
| 2556 | try dwarf.strp( | ||
| 2557 | &dwarf.debug_str, | ||
| 2558 | di_nw, | ||
| 2559 | loaded_struct.field_names.get(ip)[field_index].toSlice(ip), | ||
| 2560 | ); | ||
| 2561 | const field_ty: Type = | ||
| 2562 | .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | ||
| 2563 | try dwarf.refType(pt, di_nw, field_ty); | ||
| 2564 | try di_w.writeUleb128(field_bit_offset); | ||
| 2565 | field_bit_offset += @intCast(field_ty.bitSize(zcu)); | ||
| 2566 | } | ||
| 2567 | }, | ||
| 2568 | } | ||
| 2569 | if (loaded_struct.captures.len > 0 or loaded_struct.field_types.len > 0) | ||
| 2570 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2571 | }, | ||
| 2572 | .union_type => { | ||
| 2573 | const loaded_union = ip.loadUnionType(val); | ||
| 2574 | const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); | ||
| 2575 | const zfi = loaded_union.zir_index.resolveFile(ip); | ||
| 2576 | const zf = zcu.fileByIndex(zfi); | ||
| 2577 | if (loaded_union.captures.len > 0 or loaded_union.is_reified) { | ||
| 2578 | try dwarf.abbrevCode(di_nw, if (loaded_union.captures.len > 0 or | ||
| 2579 | loaded_union.field_types.len > 0) switch (loaded_union.layout) { | ||
| 2580 | .auto, .@"extern" => .decl_instance_union, | ||
| 2581 | .@"packed" => .decl_instance_packed_union, | ||
| 2582 | } else switch (loaded_union.layout) { | ||
| 2583 | .auto, .@"extern" => .decl_instance_empty_union, | ||
| 2584 | .@"packed" => .decl_instance_empty_packed_union, | ||
| 2585 | }); | ||
| 2586 | try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); | ||
| 2587 | } else if (loaded_union.name_nav.unwrap()) |name_ni| { | ||
| 2588 | const name_nav = ip.getNav(name_ni); | ||
| 2589 | const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); | ||
| 2590 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 2591 | name_nav.analysis.?.namespace, | ||
| 2592 | ).owner_type); | ||
| 2593 | try dwarf.abbrevCode(di_nw, if (loaded_union.field_types.len > 0) | ||
| 2594 | switch (loaded_union.layout) { | ||
| 2595 | .auto, .@"extern" => .decl_union, | ||
| 2596 | .@"packed" => .decl_packed_union, | ||
| 2597 | } | ||
| 2598 | else switch (loaded_union.layout) { | ||
| 2599 | .auto, .@"extern" => .decl_empty_union, | ||
| 2600 | .@"packed" => .decl_empty_packed_union, | ||
| 2601 | }); | ||
| 2602 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 2603 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 2604 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 2605 | try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | ||
| 2606 | try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); | ||
| 2607 | } else { | ||
| 2608 | const decl = zf.zir.?.getUnionDecl(loaded_union.zir_index.resolve(ip).?); | ||
| 2609 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 2610 | ip.namespacePtr(loaded_union.namespace).parent.unwrap().?, | ||
| 2611 | ).owner_type); | ||
| 2612 | try dwarf.abbrevCode(di_nw, if (loaded_union.field_types.len > 0) | ||
| 2613 | switch (loaded_union.layout) { | ||
| 2614 | .auto, .@"extern" => .type_decl_union, | ||
| 2615 | .@"packed" => .type_decl_packed_union, | ||
| 2616 | } | ||
| 2617 | else switch (loaded_union.layout) { | ||
| 2618 | .auto, .@"extern" => .type_decl_empty_union, | ||
| 2619 | .@"packed" => .type_decl_empty_packed_union, | ||
| 2620 | }); | ||
| 2621 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 2622 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 2623 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 2624 | try dwarf.strp(&dwarf.debug_str, di_nw, loaded_union.name.toSlice(ip)); | ||
| 2625 | } | ||
| 2626 | switch (loaded_union.layout) { | ||
| 2627 | .auto, .@"extern" => { | ||
| 2628 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | ||
| 2629 | try di_w.writeUleb128(union_layout.abi_size); | ||
| 2630 | try di_w.writeUleb128(union_layout.abi_align.toByteUnits().?); | ||
| 2631 | try dwarf.genCaptures(pt, di_nw, loaded_union.captures); | ||
| 2632 | if (loaded_union.has_runtime_tag) { | ||
| 2633 | try dwarf.abbrevCode(di_nw, .tagged_union); | ||
| 2634 | try dwarf.secOffset(di_nw, di_nw.ni, di_w.end + dwarf.secOffsetSize()); | ||
| 2635 | { | ||
| 2636 | try dwarf.abbrevCode(di_nw, .generated_field); | ||
| 2637 | try dwarf.strp(&dwarf.debug_str, di_nw, "tag"); | ||
| 2638 | try dwarf.refType(pt, di_nw, .fromInterned(loaded_union.enum_tag_type)); | ||
| 2639 | try di_w.writeUleb128(union_layout.tagOffset()); | ||
| 2640 | |||
| 2641 | for (0..loaded_union.field_types.len) |field_index| { | ||
| 2642 | try dwarf.abbrevCode(di_nw, .tagged_union_field); | ||
| 2643 | try dwarf.enumConstValue(di_w, loaded_tag, field_index); | ||
| 2644 | { | ||
| 2645 | try dwarf.abbrevCode(di_nw, .field); | ||
| 2646 | try dwarf.strp( | ||
| 2647 | &dwarf.debug_str, | ||
| 2648 | di_nw, | ||
| 2649 | loaded_tag.field_names.get(ip)[field_index].toSlice(ip), | ||
| 2650 | ); | ||
| 2651 | const field_ty: Type = | ||
| 2652 | .fromInterned(loaded_union.field_types.get(ip)[field_index]); | ||
| 2653 | try dwarf.refType(pt, di_nw, field_ty); | ||
| 2654 | try di_w.writeUleb128(union_layout.payloadOffset()); | ||
| 2655 | try di_w.writeUleb128(loaded_union.field_aligns.getOrNone( | ||
| 2656 | ip, | ||
| 2657 | field_index, | ||
| 2658 | ).toByteUnits() orelse if (field_ty.isNoReturn(zcu)) | ||
| 2659 | 1 | ||
| 2660 | else | ||
| 2661 | field_ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2662 | } | ||
| 2663 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2664 | } | ||
| 2665 | } | ||
| 2666 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2667 | } else for (0..loaded_union.field_types.len) |field_index| { | ||
| 2668 | try dwarf.abbrevCode(di_nw, .field); | ||
| 2669 | try dwarf.strp( | ||
| 2670 | &dwarf.debug_str, | ||
| 2671 | di_nw, | ||
| 2672 | loaded_tag.field_names.get(ip)[field_index].toSlice(ip), | ||
| 2673 | ); | ||
| 2674 | const field_ty: Type = | ||
| 2675 | .fromInterned(loaded_union.field_types.get(ip)[field_index]); | ||
| 2676 | try dwarf.refType(pt, di_nw, field_ty); | ||
| 2677 | try di_w.writeUleb128(0); | ||
| 2678 | try di_w.writeUleb128(loaded_union.field_aligns.getOrNone( | ||
| 2679 | ip, | ||
| 2680 | field_index, | ||
| 2681 | ).toByteUnits() orelse if (field_ty.isNoReturn(zcu)) | ||
| 2682 | 1 | ||
| 2683 | else | ||
| 2684 | field_ty.abiAlignment(zcu).toByteUnits().?); | ||
| 2685 | } | ||
| 2686 | }, | ||
| 2687 | .@"packed" => { | ||
| 2688 | try dwarf.refType(pt, di_nw, .fromInterned(loaded_union.packed_backing_int_type)); | ||
| 2689 | for (0..loaded_union.field_types.len) |field_index| { | ||
| 2690 | try dwarf.abbrevCode(di_nw, .packed_field); | ||
| 2691 | try dwarf.strp( | ||
| 2692 | &dwarf.debug_str, | ||
| 2693 | di_nw, | ||
| 2694 | loaded_tag.field_names.get(ip)[field_index].toSlice(ip), | ||
| 2695 | ); | ||
| 2696 | try dwarf.refType(pt, di_nw, .fromInterned( | ||
| 2697 | loaded_union.field_types.get(ip)[field_index], | ||
| 2698 | )); | ||
| 2699 | try di_w.writeUleb128(0); | ||
| 2700 | } | ||
| 2701 | }, | ||
| 2702 | } | ||
| 2703 | if (loaded_union.captures.len > 0 or loaded_union.field_types.len > 0) | ||
| 2704 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2705 | }, | ||
| 2706 | .enum_type => { | ||
| 2707 | const loaded_enum = ip.loadEnumType(val); | ||
| 2708 | switch (loaded_enum.owner_union) { | ||
| 2709 | .none => { | ||
| 2710 | const zfi = loaded_enum.zir_index.unwrap().?.resolveFile(ip); | ||
| 2711 | const zf = zcu.fileByIndex(zfi); | ||
| 2712 | if (loaded_enum.captures.len > 0 or loaded_enum.is_reified) { | ||
| 2713 | try dwarf.abbrevCode(di_nw, if (loaded_enum.captures.len > 0 or | ||
| 2714 | loaded_enum.field_names.len > 0) | ||
| 2715 | .decl_instance_enum | ||
| 2716 | else | ||
| 2717 | .decl_instance_empty_enum); | ||
| 2718 | try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); | ||
| 2719 | } else if (loaded_enum.name_nav.unwrap()) |name_ni| { | ||
| 2720 | const name_nav = ip.getNav(name_ni); | ||
| 2721 | const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); | ||
| 2722 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 2723 | name_nav.analysis.?.namespace, | ||
| 2724 | ).owner_type); | ||
| 2725 | try dwarf.abbrevCode( | ||
| 2726 | di_nw, | ||
| 2727 | if (loaded_enum.field_names.len > 0) .decl_enum else .decl_empty_enum, | ||
| 2728 | ); | ||
| 2729 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 2730 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 2731 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 2732 | try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | ||
| 2733 | try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); | ||
| 2734 | } else { | ||
| 2735 | const decl = | ||
| 2736 | zf.zir.?.getEnumDecl(loaded_enum.zir_index.unwrap().?.resolve(ip).?); | ||
| 2737 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 2738 | ip.namespacePtr(loaded_enum.namespace).parent.unwrap().?, | ||
| 2739 | ).owner_type); | ||
| 2740 | try dwarf.abbrevCode(di_nw, if (loaded_enum.field_names.len > 0) | ||
| 2741 | .type_decl_enum | ||
| 2742 | else | ||
| 2743 | .type_decl_empty_enum); | ||
| 2744 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 2745 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 2746 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 2747 | try dwarf.strp(&dwarf.debug_str, di_nw, loaded_enum.name.toSlice(ip)); | ||
| 2748 | } | ||
| 2749 | }, | ||
| 2750 | else => { | ||
| 2751 | try dwarf.abbrevCode(di_nw, if (loaded_enum.field_names.len > 0) | ||
| 2752 | .generated_enum_type | ||
| 2753 | else | ||
| 2754 | .generated_empty_enum_type); | ||
| 2755 | try dwarf.strp(&dwarf.debug_str, di_nw, loaded_enum.fqn.toSlice(ip)); | ||
| 2756 | }, | ||
| 2757 | } | ||
| 2758 | try dwarf.refType(pt, di_nw, .fromInterned(loaded_enum.int_tag_type)); | ||
| 2759 | for (0..loaded_enum.field_names.len) |field_index| { | ||
| 2760 | try dwarf.abbrevCode(di_nw, .enum_field); | ||
| 2761 | try dwarf.enumConstValue(di_w, loaded_enum, field_index); | ||
| 2762 | try dwarf.strp( | ||
| 2763 | &dwarf.debug_str, | ||
| 2764 | di_nw, | ||
| 2765 | loaded_enum.field_names.get(ip)[field_index].toSlice(ip), | ||
| 2766 | ); | ||
| 2767 | } | ||
| 2768 | if (loaded_enum.captures.len > 0 or loaded_enum.field_names.len > 0) | ||
| 2769 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2770 | }, | ||
| 2771 | // no defined size, so lowered the same as incomplete struct types | ||
| 2772 | .opaque_type => return dwarf.updateConstIncompleteInner(pt, di_nw, val), | ||
| 2773 | .spirv_type => unreachable, | ||
| 2774 | .func_type => |func_type| { | ||
| 2775 | const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args; | ||
| 2776 | const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); | ||
| 2777 | defer zcu.gpa.free(name); | ||
| 2778 | try dwarf.abbrevCode(di_nw, if (is_nullary) .nullary_func_type else .func_type); | ||
| 2779 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2780 | const cc: DW.CC = cc: { | ||
| 2781 | if (zcu.getTarget().cCallingConvention()) |cc| { | ||
| 2782 | if (@as(std.lang.CallingConvention.Tag, cc) == func_type.cc) { | ||
| 2783 | break :cc .normal; | ||
| 2784 | } | ||
| 2785 | } | ||
| 2786 | // For better or worse, we try to match what Clang emits. | ||
| 2787 | break :cc switch (func_type.cc) { | ||
| 2788 | .@"inline" => .nocall, | ||
| 2789 | .async, .auto, .naked => .normal, | ||
| 2790 | .x86_64_sysv => .LLVM_X86_64SysV, | ||
| 2791 | .x86_64_win => .LLVM_Win64, | ||
| 2792 | .x86_64_regcall_v3_sysv => .LLVM_X86RegCall, | ||
| 2793 | .x86_64_regcall_v4_win => .LLVM_X86RegCall, | ||
| 2794 | .x86_64_vectorcall => .LLVM_vectorcall, | ||
| 2795 | .x86_sysv, .x86_win, .x86_mingw => .normal, | ||
| 2796 | .x86_64_preserve_none => .LLVM_PreserveNone, | ||
| 2797 | .x86_stdcall => .BORLAND_stdcall, | ||
| 2798 | .x86_fastcall => .BORLAND_msfastcall, | ||
| 2799 | .x86_thiscall => .BORLAND_thiscall, | ||
| 2800 | .x86_thiscall_mingw => .BORLAND_thiscall, | ||
| 2801 | .x86_regcall_v3 => .LLVM_X86RegCall, | ||
| 2802 | .x86_regcall_v4_win => .LLVM_X86RegCall, | ||
| 2803 | .x86_vectorcall => .LLVM_vectorcall, | ||
| 2804 | |||
| 2805 | .aarch64_aapcs => .normal, | ||
| 2806 | .aarch64_aapcs_darwin => .normal, | ||
| 2807 | .aarch64_aapcs_win => .normal, | ||
| 2808 | .aarch64_vfabi => .LLVM_AAPCS, | ||
| 2809 | .aarch64_vfabi_sve => .LLVM_AAPCS, | ||
| 2810 | .aarch64_preserve_none => .LLVM_PreserveNone, | ||
| 2811 | |||
| 2812 | .arm_aapcs => .LLVM_AAPCS, | ||
| 2813 | .arm_aapcs_vfp => .LLVM_AAPCS_VFP, | ||
| 2814 | |||
| 2815 | .riscv64_lp64_v, | ||
| 2816 | .riscv32_ilp32_v, | ||
| 2817 | => .LLVM_RISCVVectorCall, | ||
| 2818 | |||
| 2819 | .m68k_rtd => .LLVM_M68kRTD, | ||
| 2820 | |||
| 2821 | .sh_renesas => .GNU_renesas_sh, | ||
| 2822 | |||
| 2823 | .amdgcn_kernel => .LLVM_OpenCLKernel, | ||
| 2824 | .nvptx_kernel, | ||
| 2825 | .spirv_kernel, | ||
| 2826 | => .nocall, | ||
| 2827 | |||
| 2828 | .x86_64_interrupt, | ||
| 2829 | .x86_interrupt, | ||
| 2830 | .arm_interrupt, | ||
| 2831 | .mips64_interrupt, | ||
| 2832 | .mips_interrupt, | ||
| 2833 | .riscv64_interrupt, | ||
| 2834 | .riscv32_interrupt, | ||
| 2835 | .sh_interrupt, | ||
| 2836 | .arc_interrupt, | ||
| 2837 | .avr_builtin, | ||
| 2838 | .avr_signal, | ||
| 2839 | .avr_interrupt, | ||
| 2840 | .csky_interrupt, | ||
| 2841 | .m68k_interrupt, | ||
| 2842 | .microblaze_interrupt, | ||
| 2843 | .msp430_interrupt, | ||
| 2844 | => .normal, | ||
| 2845 | |||
| 2846 | else => .nocall, | ||
| 2847 | }; | ||
| 2848 | }; | ||
| 2849 | try di_w.writeByte(@backingInt(cc)); | ||
| 2850 | try dwarf.refType(pt, di_nw, .fromInterned(func_type.return_type)); | ||
| 2851 | if (!is_nullary) { | ||
| 2852 | for (0..func_type.param_types.len) |param_index| { | ||
| 2853 | try dwarf.abbrevCode(di_nw, .unnamed_param); | ||
| 2854 | try dwarf.refType(pt, di_nw, .fromInterned( | ||
| 2855 | func_type.param_types.get(ip)[param_index], | ||
| 2856 | )); | ||
| 2857 | } | ||
| 2858 | if (func_type.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args); | ||
| 2859 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2860 | } | ||
| 2861 | }, | ||
| 2862 | .error_set_type => |error_set_type| { | ||
| 2863 | const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); | ||
| 2864 | defer zcu.gpa.free(name); | ||
| 2865 | try dwarf.abbrevCode( | ||
| 2866 | di_nw, | ||
| 2867 | if (error_set_type.names.len > 0) .generated_enum_type else .generated_empty_enum_type, | ||
| 2868 | ); | ||
| 2869 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2870 | try dwarf.refType(pt, di_nw, try pt.intType(.unsigned, zcu.errorSetBits())); | ||
| 2871 | for (0..error_set_type.names.len) |field_index| { | ||
| 2872 | const field_name = error_set_type.names.get(ip)[field_index]; | ||
| 2873 | try dwarf.abbrevCode(di_nw, .enum_field); | ||
| 2874 | try di_w.writeUleb128(DW.FORM.udata); | ||
| 2875 | try di_w.writeUleb128(ip.getErrorValueIfExists(field_name).?); | ||
| 2876 | try dwarf.strp(&dwarf.debug_str, di_nw, field_name.toSlice(ip)); | ||
| 2877 | } | ||
| 2878 | if (error_set_type.names.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2879 | }, | ||
| 2880 | .inferred_error_set_type => |func| { | ||
| 2881 | const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); | ||
| 2882 | defer zcu.gpa.free(name); | ||
| 2883 | try dwarf.abbrevCode(di_nw, .inferred_error_set_type); | ||
| 2884 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 2885 | try dwarf.refType(pt, di_nw, switch (ies: { | ||
| 2886 | const fi = dwarf.getFuncIfExists(ip.indexToKey(func).func.owner_nav) orelse | ||
| 2887 | break :ies .none; | ||
| 2888 | break :ies switch (fi.get(dwarf).state) { | ||
| 2889 | .unresolved => .none, | ||
| 2890 | .resolved => ip.funcIesResolvedUnordered(func), | ||
| 2891 | }; | ||
| 2892 | }) { | ||
| 2893 | .none => .anyerror, | ||
| 2894 | else => |ies| .fromInterned(ies), | ||
| 2895 | }); | ||
| 2896 | }, | ||
| 2897 | |||
| 2898 | else => return, | ||
| 2899 | .func => |func| { | ||
| 2900 | const fn_ty = ip.indexToKey(func.ty).func_type; | ||
| 2901 | const nav = ip.getNav(func.owner_nav); | ||
| 2902 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; | ||
| 2903 | const zf = zcu.fileByIndex(inst_info.file); | ||
| 2904 | const decl = zf.zir.?.getDeclaration(inst_info.inst); | ||
| 2905 | const parent_ty: Type = .fromInterned(ip.namespacePtr(nav.analysis.?.namespace).owner_type); | ||
| 2906 | try dwarf.abbrevCode(di_nw, .decl_func_generic); | ||
| 2907 | try dwarf.refType(pt, di_nw, parent_ty); | ||
| 2908 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 2909 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 2910 | try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | ||
| 2911 | try dwarf.strp(&dwarf.debug_str, di_nw, nav.name.toSlice(ip)); | ||
| 2912 | try dwarf.refType(pt, di_nw, .fromInterned(fn_ty.return_type)); | ||
| 2913 | var param_index: u32 = 0; | ||
| 2914 | for (zf.zir.?.getParamBody(func.zir_body_inst.resolve(ip).?)) |param_inst| { | ||
| 2915 | switch (zf.zir.?.getParamName(param_inst) orelse break) { | ||
| 2916 | .empty => try dwarf.abbrevCode(di_nw, .unnamed_param), | ||
| 2917 | else => |param_name| { | ||
| 2918 | try dwarf.abbrevCode(di_nw, .param); | ||
| 2919 | try dwarf.strp(&dwarf.debug_str, di_nw, zf.zir.?.nullTerminatedString( | ||
| 2920 | param_name, | ||
| 2921 | )); | ||
| 2922 | }, | ||
| 2923 | } | ||
| 2924 | try dwarf.refType(pt, di_nw, .fromInterned( | ||
| 2925 | fn_ty.param_types.get(&zcu.intern_pool)[param_index], | ||
| 2926 | )); | ||
| 2927 | param_index += 1; | ||
| 2928 | } | ||
| 2929 | if (fn_ty.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args); | ||
| 2930 | try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 2931 | }, | ||
| 2932 | |||
| 2933 | .memoized_call => unreachable, // not a value | ||
| 2934 | } | ||
| 2935 | try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); | ||
| 2936 | } | ||
| 2937 | |||
| 2938 | fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } { | ||
| 2939 | if (opt_child_type.isNoReturn(zcu)) return .opv_null; | ||
| 2940 | return switch (opt_child_type.toIntern()) { | ||
| 2941 | .anyerror_type => .error_set, | ||
| 2942 | else => switch (zcu.intern_pool.indexToKey(opt_child_type.toIntern())) { | ||
| 2943 | else => .unpacked, | ||
| 2944 | .error_set_type, .inferred_error_set_type => .error_set, | ||
| 2945 | .ptr_type => |ptr_type| if (ptr_type.flags.is_allowzero) .unpacked else .pointer, | ||
| 2946 | }, | ||
| 2947 | }; | ||
| 2948 | } | ||
| 2949 | |||
| 2950 | pub fn updateConstIncomplete( | ||
| 2951 | dwarf: *Dwarf, | ||
| 2952 | pt: Zcu.PerThread, | ||
| 2953 | di_nw: *link.MappedFile.Node.Writer, | ||
| 2954 | val: InternPool.Index, | ||
| 2955 | ) link.Error!void { | ||
| 2956 | log.debug("updateConstIncomplete({f})", .{Value.fromInterned(val).fmtValue(pt)}); | ||
| 2957 | dwarf.updateConstIncompleteInner(pt, di_nw, val) catch |err| switch (err) { | ||
| 2958 | else => |e| return e, | ||
| 2959 | error.WriteFailed => return dwarf.reportWriteError(di_nw), | ||
| 2960 | }; | ||
| 2961 | } | ||
| 2962 | fn updateConstIncompleteInner( | ||
| 2963 | dwarf: *Dwarf, | ||
| 2964 | pt: Zcu.PerThread, | ||
| 2965 | di_nw: *link.MappedFile.Node.Writer, | ||
| 2966 | val: InternPool.Index, | ||
| 2967 | ) link.EmitError!void { | ||
| 2968 | const zcu = pt.zcu; | ||
| 2969 | const ip = &zcu.intern_pool; | ||
| 2970 | const di_w = &di_nw.interface; | ||
| 2971 | done: { | ||
| 2972 | const kind: enum { @"struct", @"union", @"enum" }, const zf, const src_line, const src_column, const is_reified, const captures, const name, const maybe_name_nav, const namespace = container: switch (ip.indexToKey(val)) { | ||
| 2973 | .struct_type => { | ||
| 2974 | const loaded_struct = ip.loadStructType(val); | ||
| 2975 | const src_inst = loaded_struct.zir_index.resolveFull(ip) orelse { | ||
| 2976 | try dwarf.lostTracking(di_nw); | ||
| 2977 | break :done; | ||
| 2978 | }; | ||
| 2979 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 2980 | switch (src_inst.inst) { | ||
| 2981 | .main_struct_inst => { | ||
| 2982 | const ui = dwarf.getUnit(zf.mod.?); | ||
| 2983 | _, const fi = try ui.get(dwarf).getFile(zcu.gpa, ui, src_inst.file); | ||
| 2984 | try dwarf.abbrevCode(di_nw, .empty_file); | ||
| 2985 | try di_w.writeUleb128(@backingInt(fi)); | ||
| 2986 | try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); | ||
| 2987 | try di_w.writeByte(@intFromBool(true)); | ||
| 2988 | break :done; | ||
| 2989 | }, | ||
| 2990 | else => { | ||
| 2991 | const data = | ||
| 2992 | zf.zir.?.instructions.items(.data)[@backingInt(src_inst.inst)].extended; | ||
| 2993 | const src_line, const src_column = src_loc: switch (data.opcode) { | ||
| 2994 | else => unreachable, | ||
| 2995 | .struct_decl => { | ||
| 2996 | const decl = zf.zir.?.getStructDecl(src_inst.inst); | ||
| 2997 | break :src_loc .{ decl.src_line, decl.src_column }; | ||
| 2998 | }, | ||
| 2999 | .reify_struct => { | ||
| 3000 | const decl = zf.zir.?.extraData( | ||
| 3001 | std.zig.Zir.Inst.ReifyStruct, | ||
| 3002 | data.operand, | ||
| 3003 | ).data; | ||
| 3004 | break :src_loc .{ decl.src_line, decl.src_column }; | ||
| 3005 | }, | ||
| 3006 | }; | ||
| 3007 | break :container .{ | ||
| 3008 | .@"struct", | ||
| 3009 | zf, | ||
| 3010 | src_line, | ||
| 3011 | src_column, | ||
| 3012 | loaded_struct.is_reified, | ||
| 3013 | loaded_struct.captures, | ||
| 3014 | loaded_struct.name, | ||
| 3015 | loaded_struct.name_nav, | ||
| 3016 | loaded_struct.namespace, | ||
| 3017 | }; | ||
| 3018 | }, | ||
| 3019 | } | ||
| 3020 | }, | ||
| 3021 | .union_type => { | ||
| 3022 | const loaded_union = ip.loadUnionType(val); | ||
| 3023 | const src_inst = loaded_union.zir_index.resolveFull(ip) orelse { | ||
| 3024 | try dwarf.lostTracking(di_nw); | ||
| 3025 | break :done; | ||
| 3026 | }; | ||
| 3027 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 3028 | const data = zf.zir.?.instructions.items(.data)[@backingInt(src_inst.inst)].extended; | ||
| 3029 | const src_line, const src_column = src_loc: switch (data.opcode) { | ||
| 3030 | else => unreachable, | ||
| 3031 | .union_decl => { | ||
| 3032 | const decl = zf.zir.?.getUnionDecl(src_inst.inst); | ||
| 3033 | break :src_loc .{ decl.src_line, decl.src_column }; | ||
| 3034 | }, | ||
| 3035 | .reify_union => { | ||
| 3036 | const decl = zf.zir.?.extraData(std.zig.Zir.Inst.ReifyUnion, data.operand).data; | ||
| 3037 | break :src_loc .{ decl.src_line, decl.src_column }; | ||
| 3038 | }, | ||
| 3039 | }; | ||
| 3040 | break :container .{ | ||
| 3041 | .@"union", | ||
| 3042 | zf, | ||
| 3043 | src_line, | ||
| 3044 | src_column, | ||
| 3045 | loaded_union.is_reified, | ||
| 3046 | loaded_union.captures, | ||
| 3047 | loaded_union.name, | ||
| 3048 | loaded_union.name_nav, | ||
| 3049 | loaded_union.namespace, | ||
| 3050 | }; | ||
| 3051 | }, | ||
| 3052 | .enum_type => { | ||
| 3053 | const loaded_enum = ip.loadEnumType(val); | ||
| 3054 | const zir_index = loaded_enum.zir_index.unwrap() orelse { | ||
| 3055 | try dwarf.abbrevCode(di_nw, .generated_empty_struct_type); | ||
| 3056 | try dwarf.strp(&dwarf.debug_str, di_nw, loaded_enum.name.toSlice(ip)); | ||
| 3057 | try di_w.writeByte(@intFromBool(true)); | ||
| 3058 | break :done; | ||
| 3059 | }; | ||
| 3060 | const src_inst = zir_index.resolveFull(ip) orelse { | ||
| 3061 | try dwarf.lostTracking(di_nw); | ||
| 3062 | break :done; | ||
| 3063 | }; | ||
| 3064 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 3065 | const data = zf.zir.?.instructions.items(.data)[@backingInt(src_inst.inst)].extended; | ||
| 3066 | const src_line, const src_column = src_loc: switch (data.opcode) { | ||
| 3067 | else => unreachable, | ||
| 3068 | .enum_decl => { | ||
| 3069 | const decl = zf.zir.?.getEnumDecl(src_inst.inst); | ||
| 3070 | break :src_loc .{ decl.src_line, decl.src_column }; | ||
| 3071 | }, | ||
| 3072 | .reify_enum => { | ||
| 3073 | const decl = zf.zir.?.extraData(std.zig.Zir.Inst.ReifyEnum, data.operand).data; | ||
| 3074 | break :src_loc .{ decl.src_line, decl.src_column }; | ||
| 3075 | }, | ||
| 3076 | }; | ||
| 3077 | break :container .{ | ||
| 3078 | .@"enum", | ||
| 3079 | zf, | ||
| 3080 | src_line, | ||
| 3081 | src_column, | ||
| 3082 | loaded_enum.is_reified, | ||
| 3083 | loaded_enum.captures, | ||
| 3084 | loaded_enum.name, | ||
| 3085 | loaded_enum.name_nav, | ||
| 3086 | loaded_enum.namespace, | ||
| 3087 | }; | ||
| 3088 | }, | ||
| 3089 | // always complete, but forwarded from `updateConstInner` | ||
| 3090 | .opaque_type => { | ||
| 3091 | const loaded_opaque = ip.loadOpaqueType(val); | ||
| 3092 | const src_inst = loaded_opaque.zir_index.resolveFull(ip) orelse { | ||
| 3093 | try dwarf.lostTracking(di_nw); | ||
| 3094 | break :done; | ||
| 3095 | }; | ||
| 3096 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 3097 | const decl = zf.zir.?.getOpaqueDecl(src_inst.inst); | ||
| 3098 | break :container .{ | ||
| 3099 | .@"struct", | ||
| 3100 | zf, | ||
| 3101 | decl.src_line, | ||
| 3102 | decl.src_column, | ||
| 3103 | false, | ||
| 3104 | loaded_opaque.captures, | ||
| 3105 | loaded_opaque.name, | ||
| 3106 | loaded_opaque.name_nav, | ||
| 3107 | loaded_opaque.namespace, | ||
| 3108 | }; | ||
| 3109 | }, | ||
| 3110 | else => |val_key| break :done switch (val_key.typeOf()) { | ||
| 3111 | .type_type => { | ||
| 3112 | const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); | ||
| 3113 | defer zcu.gpa.free(name); | ||
| 3114 | try dwarf.abbrevCode(di_nw, .generated_empty_struct_type); | ||
| 3115 | try dwarf.strp(&dwarf.debug_str, di_nw, name); | ||
| 3116 | try di_w.writeByte(@intFromBool(true)); | ||
| 3117 | }, | ||
| 3118 | else => |ty| { | ||
| 3119 | try dwarf.abbrevCode(di_nw, .undefined_comptime_value); | ||
| 3120 | try dwarf.refType(pt, di_nw, .fromInterned(ty)); | ||
| 3121 | }, | ||
| 3122 | }, | ||
| 3123 | }; | ||
| 3124 | if (captures.len > 0 or is_reified) { | ||
| 3125 | try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { | ||
| 3126 | .@"struct" => .decl_instance_incomplete_struct, | ||
| 3127 | .@"union" => .decl_instance_incomplete_union, | ||
| 3128 | .@"enum" => .decl_instance_incomplete_enum, | ||
| 3129 | } else switch (kind) { | ||
| 3130 | .@"struct" => .decl_instance_empty_incomplete_struct, | ||
| 3131 | .@"union" => .decl_instance_empty_incomplete_union, | ||
| 3132 | .@"enum" => .decl_instance_empty_incomplete_enum, | ||
| 3133 | }); | ||
| 3134 | try dwarf.secOffset(di_nw, try dwarf.getDecl(pt, val), 0); | ||
| 3135 | } else if (maybe_name_nav.unwrap()) |name_ni| { | ||
| 3136 | const name_nav = ip.getNav(name_ni); | ||
| 3137 | const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); | ||
| 3138 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 3139 | name_nav.analysis.?.namespace, | ||
| 3140 | ).owner_type); | ||
| 3141 | try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { | ||
| 3142 | .@"struct" => .decl_incomplete_struct, | ||
| 3143 | .@"union" => .decl_incomplete_union, | ||
| 3144 | .@"enum" => .decl_incomplete_enum, | ||
| 3145 | } else switch (kind) { | ||
| 3146 | .@"struct" => .decl_empty_incomplete_struct, | ||
| 3147 | .@"union" => .decl_empty_incomplete_union, | ||
| 3148 | .@"enum" => .decl_empty_incomplete_enum, | ||
| 3149 | }); | ||
| 3150 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 3151 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 3152 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 3153 | try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | ||
| 3154 | try dwarf.strp(&dwarf.debug_str, di_nw, name_nav.name.toSlice(ip)); | ||
| 3155 | } else { | ||
| 3156 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 3157 | ip.namespacePtr(namespace).parent.unwrap().?, | ||
| 3158 | ).owner_type); | ||
| 3159 | try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { | ||
| 3160 | .@"struct" => .type_decl_incomplete_struct, | ||
| 3161 | .@"union" => .type_decl_incomplete_union, | ||
| 3162 | .@"enum" => .type_decl_incomplete_enum, | ||
| 3163 | } else switch (kind) { | ||
| 3164 | .@"struct" => .type_decl_empty_incomplete_struct, | ||
| 3165 | .@"union" => .type_decl_empty_incomplete_union, | ||
| 3166 | .@"enum" => .type_decl_empty_incomplete_enum, | ||
| 3167 | }); | ||
| 3168 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 3169 | try di_w.writeInt(u32, src_line + 1, dwarf.endian); | ||
| 3170 | try di_w.writeUleb128(src_column + 1); | ||
| 3171 | try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); | ||
| 3172 | } | ||
| 3173 | try dwarf.genCaptures(pt, di_nw, captures); | ||
| 3174 | if (captures.len > 0) try di_w.writeByte(@backingInt(AbbrevCode.null)); | ||
| 3175 | } | ||
| 3176 | try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); | ||
| 3177 | } | ||
| 3178 | |||
| 3179 | fn genCaptures( | ||
| 3180 | dwarf: *Dwarf, | ||
| 3181 | pt: Zcu.PerThread, | ||
| 3182 | di_nw: *link.MappedFile.Node.Writer, | ||
| 3183 | captures: anytype, | ||
| 3184 | ) link.EmitError!void { | ||
| 3185 | const zcu = pt.zcu; | ||
| 3186 | const ip = &zcu.intern_pool; | ||
| 3187 | for (captures.get(ip)) |capture| switch (capture.unwrap()) { | ||
| 3188 | .@"comptime" => |capture_val| { | ||
| 3189 | const ty: Type = .fromInterned(ip.typeOf(capture_val)); | ||
| 3190 | const ty_class = ty.classify(zcu); | ||
| 3191 | try dwarf.abbrevCode(di_nw, switch (ty_class) { | ||
| 3192 | .no_possible_value => unreachable, | ||
| 3193 | .one_possible_value => .comptime_capture, | ||
| 3194 | .runtime => .comptime_capture_runtime, | ||
| 3195 | .partially_comptime => .comptime_capture_partially_comptime, | ||
| 3196 | .fully_comptime => .comptime_capture_fully_comptime, | ||
| 3197 | }); | ||
| 3198 | try dwarf.refType(pt, di_nw, ty); | ||
| 3199 | if (ty_class.hasRuntimeBits()) try dwarf.blockConst(pt, di_nw, .fromInterned(capture_val)); | ||
| 3200 | if (ty_class.comptimeOnly()) try dwarf.refConst(pt, di_nw, .fromInterned(capture_val)); | ||
| 3201 | }, | ||
| 3202 | .runtime => |capture_ty| { | ||
| 3203 | try dwarf.abbrevCode(di_nw, .runtime_capture); | ||
| 3204 | try dwarf.refType(pt, di_nw, .fromInterned(capture_ty)); | ||
| 3205 | }, | ||
| 3206 | .nav_val => |capture_nav| { | ||
| 3207 | const gi = try dwarf.getGlobal(capture_nav); | ||
| 3208 | try dwarf.abbrevCode(di_nw, .nav_capture); | ||
| 3209 | try dwarf.exprLoc(di_nw, .{ .implicit_pointer = .{ | ||
| 3210 | .node = gi.get(dwarf).debug_info_ni.unwrap().?, | ||
| 3211 | } }); | ||
| 3212 | }, | ||
| 3213 | .nav_ref => |capture_nav| { | ||
| 3214 | const gi = try dwarf.getGlobal(capture_nav); | ||
| 3215 | try dwarf.abbrevCode(di_nw, .nav_capture); | ||
| 3216 | try dwarf.exprLoc(di_nw, .{ .stack_value = &.{ .implicit_pointer = .{ | ||
| 3217 | .node = gi.get(dwarf).debug_info_ni.unwrap().?, | ||
| 3218 | } } }); | ||
| 3219 | }, | ||
| 3220 | }; | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | pub fn genDecl( | ||
| 3224 | dwarf: *Dwarf, | ||
| 3225 | pt: Zcu.PerThread, | ||
| 3226 | di_nw: *link.MappedFile.Node.Writer, | ||
| 3227 | instance_val: InternPool.Index, | ||
| 3228 | ) link.Error!void { | ||
| 3229 | log.debug("genDecl({f})", .{Value.fromInterned(instance_val).fmtValue(pt)}); | ||
| 3230 | dwarf.genDeclInner(pt, di_nw, instance_val) catch |err| switch (err) { | ||
| 3231 | else => |e| return e, | ||
| 3232 | error.WriteFailed => return dwarf.reportWriteError(di_nw), | ||
| 3233 | }; | ||
| 3234 | } | ||
| 3235 | fn genDeclInner( | ||
| 3236 | dwarf: *Dwarf, | ||
| 3237 | pt: Zcu.PerThread, | ||
| 3238 | di_nw: *link.MappedFile.Node.Writer, | ||
| 3239 | instance_val: InternPool.Index, | ||
| 3240 | ) link.EmitError!void { | ||
| 3241 | const zcu = pt.zcu; | ||
| 3242 | const ip = &zcu.intern_pool; | ||
| 3243 | const di_w = &di_nw.interface; | ||
| 3244 | done: { | ||
| 3245 | const kind: enum { @"struct", @"union", @"enum" }, const zf, const src_line, const src_column, const capture_names, const captures, const name, const maybe_name_nav, const namespace = container: switch (ip.indexToKey(instance_val)) { | ||
| 3246 | else => unreachable, | ||
| 3247 | .struct_type => { | ||
| 3248 | const loaded_struct = ip.loadStructType(instance_val); | ||
| 3249 | const src_inst = loaded_struct.zir_index.resolveFull(ip) orelse { | ||
| 3250 | try dwarf.lostTracking(di_nw); | ||
| 3251 | break :done; | ||
| 3252 | }; | ||
| 3253 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 3254 | const inst = zf.zir.?.instructions.get(@backingInt(src_inst.inst)); | ||
| 3255 | const src_line, const src_column, const capture_names = decl: switch (inst.tag) { | ||
| 3256 | else => unreachable, | ||
| 3257 | .struct_init, .struct_init_ref => { | ||
| 3258 | const decl = zf.zir.?.extraData( | ||
| 3259 | std.zig.Zir.Inst.StructInit, | ||
| 3260 | inst.data.pl_node.payload_index, | ||
| 3261 | ).data; | ||
| 3262 | break :decl .{ decl.src_line, decl.src_column, &.{} }; | ||
| 3263 | }, | ||
| 3264 | .struct_init_anon => { | ||
| 3265 | const decl = zf.zir.?.extraData( | ||
| 3266 | std.zig.Zir.Inst.StructInitAnon, | ||
| 3267 | inst.data.pl_node.payload_index, | ||
| 3268 | ).data; | ||
| 3269 | break :decl .{ decl.src_line, decl.src_column, &.{} }; | ||
| 3270 | }, | ||
| 3271 | .extended => switch (inst.data.extended.opcode) { | ||
| 3272 | else => unreachable, | ||
| 3273 | .struct_decl => { | ||
| 3274 | const decl = zf.zir.?.getStructDecl(src_inst.inst); | ||
| 3275 | break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; | ||
| 3276 | }, | ||
| 3277 | .reify_struct => { | ||
| 3278 | const decl = zf.zir.?.extraData( | ||
| 3279 | std.zig.Zir.Inst.ReifyStruct, | ||
| 3280 | inst.data.extended.operand, | ||
| 3281 | ).data; | ||
| 3282 | break :decl .{ decl.src_line, decl.src_column, &.{} }; | ||
| 3283 | }, | ||
| 3284 | }, | ||
| 3285 | }; | ||
| 3286 | break :container .{ | ||
| 3287 | .@"struct", | ||
| 3288 | zf, | ||
| 3289 | src_line, | ||
| 3290 | src_column, | ||
| 3291 | capture_names, | ||
| 3292 | loaded_struct.captures, | ||
| 3293 | loaded_struct.name, | ||
| 3294 | loaded_struct.name_nav, | ||
| 3295 | loaded_struct.namespace, | ||
| 3296 | }; | ||
| 3297 | }, | ||
| 3298 | .union_type => { | ||
| 3299 | const loaded_union = ip.loadUnionType(instance_val); | ||
| 3300 | const src_inst = loaded_union.zir_index.resolveFull(ip) orelse { | ||
| 3301 | try dwarf.lostTracking(di_nw); | ||
| 3302 | break :done; | ||
| 3303 | }; | ||
| 3304 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 3305 | const inst = zf.zir.?.instructions.get(@backingInt(src_inst.inst)); | ||
| 3306 | const src_line, const src_column, const capture_names = decl: switch (inst.tag) { | ||
| 3307 | else => unreachable, | ||
| 3308 | .extended => switch (inst.data.extended.opcode) { | ||
| 3309 | else => unreachable, | ||
| 3310 | .union_decl => { | ||
| 3311 | const decl = zf.zir.?.getUnionDecl(src_inst.inst); | ||
| 3312 | break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; | ||
| 3313 | }, | ||
| 3314 | .reify_union => { | ||
| 3315 | const decl = zf.zir.?.extraData( | ||
| 3316 | std.zig.Zir.Inst.ReifyUnion, | ||
| 3317 | inst.data.extended.operand, | ||
| 3318 | ).data; | ||
| 3319 | break :decl .{ decl.src_line, decl.src_column, &.{} }; | ||
| 3320 | }, | ||
| 3321 | }, | ||
| 3322 | }; | ||
| 3323 | break :container .{ | ||
| 3324 | .@"union", | ||
| 3325 | zf, | ||
| 3326 | src_line, | ||
| 3327 | src_column, | ||
| 3328 | capture_names, | ||
| 3329 | loaded_union.captures, | ||
| 3330 | loaded_union.name, | ||
| 3331 | loaded_union.name_nav, | ||
| 3332 | loaded_union.namespace, | ||
| 3333 | }; | ||
| 3334 | }, | ||
| 3335 | .enum_type => { | ||
| 3336 | const loaded_enum = ip.loadEnumType(instance_val); | ||
| 3337 | const src_inst = loaded_enum.zir_index.unwrap().?.resolveFull(ip) orelse { | ||
| 3338 | try dwarf.lostTracking(di_nw); | ||
| 3339 | break :done; | ||
| 3340 | }; | ||
| 3341 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 3342 | const inst = zf.zir.?.instructions.get(@backingInt(src_inst.inst)); | ||
| 3343 | const src_line, const src_column, const capture_names = decl: switch (inst.tag) { | ||
| 3344 | else => unreachable, | ||
| 3345 | .extended => switch (inst.data.extended.opcode) { | ||
| 3346 | else => unreachable, | ||
| 3347 | .enum_decl => { | ||
| 3348 | const decl = zf.zir.?.getEnumDecl(src_inst.inst); | ||
| 3349 | break :decl .{ decl.src_line, decl.src_column, decl.capture_names }; | ||
| 3350 | }, | ||
| 3351 | .reify_enum => { | ||
| 3352 | const decl = zf.zir.?.extraData( | ||
| 3353 | std.zig.Zir.Inst.ReifyEnum, | ||
| 3354 | inst.data.extended.operand, | ||
| 3355 | ).data; | ||
| 3356 | break :decl .{ decl.src_line, decl.src_column, &.{} }; | ||
| 3357 | }, | ||
| 3358 | }, | ||
| 3359 | }; | ||
| 3360 | break :container .{ | ||
| 3361 | .@"enum", | ||
| 3362 | zf, | ||
| 3363 | src_line, | ||
| 3364 | src_column, | ||
| 3365 | capture_names, | ||
| 3366 | loaded_enum.captures, | ||
| 3367 | loaded_enum.name, | ||
| 3368 | loaded_enum.name_nav, | ||
| 3369 | loaded_enum.namespace, | ||
| 3370 | }; | ||
| 3371 | }, | ||
| 3372 | .opaque_type => { | ||
| 3373 | const loaded_opaque = ip.loadOpaqueType(instance_val); | ||
| 3374 | const src_inst = loaded_opaque.zir_index.resolveFull(ip) orelse { | ||
| 3375 | try dwarf.lostTracking(di_nw); | ||
| 3376 | break :done; | ||
| 3377 | }; | ||
| 3378 | const zf = zcu.fileByIndex(src_inst.file); | ||
| 3379 | const decl = zf.zir.?.getOpaqueDecl(src_inst.inst); | ||
| 3380 | break :container .{ | ||
| 3381 | .@"struct", | ||
| 3382 | zf, | ||
| 3383 | decl.src_line, | ||
| 3384 | decl.src_column, | ||
| 3385 | decl.capture_names, | ||
| 3386 | loaded_opaque.captures, | ||
| 3387 | loaded_opaque.name, | ||
| 3388 | loaded_opaque.name_nav, | ||
| 3389 | loaded_opaque.namespace, | ||
| 3390 | }; | ||
| 3391 | }, | ||
| 3392 | }; | ||
| 3393 | if (maybe_name_nav.unwrap()) |name_ni| { | ||
| 3394 | const name_nav = ip.getNav(name_ni); | ||
| 3395 | const decl = zf.zir.?.getDeclaration(name_nav.srcInst(ip).resolve(ip).?); | ||
| 3396 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 3397 | name_nav.analysis.?.namespace, | ||
| 3398 | ).owner_type); | ||
| 3399 | try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { | ||
| 3400 | .@"struct" => .decl_specification_struct, | ||
| 3401 | .@"union" => .decl_specification_union, | ||
| 3402 | .@"enum" => .decl_specification_enum, | ||
| 3403 | } else switch (kind) { | ||
| 3404 | .@"struct" => .decl_specification_empty_struct, | ||
| 3405 | .@"union" => .decl_specification_empty_union, | ||
| 3406 | .@"enum" => .decl_specification_empty_enum, | ||
| 3407 | }); | ||
| 3408 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 3409 | try di_w.writeInt(u32, decl.src_line + 1, dwarf.endian); | ||
| 3410 | try di_w.writeUleb128(decl.src_column + 1); | ||
| 3411 | try di_w.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); | ||
| 3412 | try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); | ||
| 3413 | } else { | ||
| 3414 | const parent_ni = try dwarf.getDecl(pt, ip.namespacePtr( | ||
| 3415 | ip.namespacePtr(namespace).parent.unwrap().?, | ||
| 3416 | ).owner_type); | ||
| 3417 | try dwarf.abbrevCode(di_nw, if (captures.len > 0) switch (kind) { | ||
| 3418 | .@"struct" => .type_decl_specification_struct, | ||
| 3419 | .@"union" => .type_decl_specification_union, | ||
| 3420 | .@"enum" => .type_decl_specification_enum, | ||
| 3421 | } else switch (kind) { | ||
| 3422 | .@"struct" => .type_decl_specification_empty_struct, | ||
| 3423 | .@"union" => .type_decl_specification_empty_union, | ||
| 3424 | .@"enum" => .type_decl_specification_empty_enum, | ||
| 3425 | }); | ||
| 3426 | try dwarf.secOffset(di_nw, parent_ni, 0); | ||
| 3427 | try di_w.writeInt(u32, src_line + 1, dwarf.endian); | ||
| 3428 | try di_w.writeUleb128(src_column + 1); | ||
| 3429 | try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); | ||
| 3430 | } | ||
| 3431 | for (capture_names, captures.get(ip)) |capture_name, capture| { | ||
| 3432 | try dwarf.abbrevCode(di_nw, .capture_specification); | ||
| 3433 | switch (capture.unwrap()) { | ||
| 3434 | .@"comptime", .runtime, .nav_val => try dwarf.strp( | ||
| 3435 | &dwarf.debug_str, | ||
| 3436 | di_nw, | ||
| 3437 | zf.zir.?.nullTerminatedString(capture_name), | ||
| 3438 | ), | ||
| 3439 | .nav_ref => { | ||
| 3440 | const capture_name_slice = try zcu.gpa.print("&{s}", .{ | ||
| 3441 | zf.zir.?.nullTerminatedString(capture_name), | ||
| 3442 | }); | ||
| 3443 | defer zcu.gpa.free(capture_name_slice); | ||
| 3444 | try dwarf.strp(&dwarf.debug_str, di_nw, capture_name_slice); | ||
| 3445 | }, | ||
| 3446 | } | ||
| 3447 | } | ||
| 3448 | if (captures.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null)); | ||
| 3449 | } | ||
| 3450 | try dwarf.genDebugInfoPadding(di_w, di_w.unusedCapacityLen()); | ||
| 3451 | } | ||
| 3452 | |||
| 3453 | pub fn updateLineNumber( | ||
| 3454 | dwarf: *Dwarf, | ||
| 3455 | mf: *link.MappedFile, | ||
| 3456 | inst: InternPool.TrackedInst.Index, | ||
| 3457 | line: u32, | ||
| 3458 | ) void { | ||
| 3459 | const di = dwarf.getDeclIfExists(inst) orelse return; | ||
| 3460 | const decl_ni = di.get(dwarf).debug_info_ni.unwrap().?; | ||
| 3461 | std.mem.writeInt( | ||
| 3462 | u32, | ||
| 3463 | decl_ni.slice(mf)[AbbrevCode.decl_size..][0..4], | ||
| 3464 | line + 1, | ||
| 3465 | dwarf.endian, | ||
| 3466 | ); | ||
| 3467 | } | ||
| 3468 | |||
| 3469 | pub fn lostTracking(dwarf: *Dwarf, di_nw: *link.MappedFile.Node.Writer) link.EmitError!void { | ||
| 3470 | try dwarf.abbrevCode(di_nw, .decl_lost); | ||
| 3471 | } | ||
| 3472 | |||
| 3473 | fn refAbbrevCodeIfExists( | ||
| 3474 | dwarf: *Dwarf, | ||
| 3475 | abbrev_code: AbbrevCode, | ||
| 3476 | ) ?@typeInfo(AbbrevCode).@"enum".tag_type { | ||
| 3477 | assert(abbrev_code != .null); | ||
| 3478 | return if (dwarf.debug_abbrev.set.contains(abbrev_code)) @backingInt(abbrev_code) else null; | ||
| 3479 | } | ||
| 3480 | fn refAbbrevCode( | ||
| 3481 | dwarf: *Dwarf, | ||
| 3482 | mf: *link.MappedFile, | ||
| 3483 | abbrev_code: AbbrevCode, | ||
| 3484 | ) link.Error!@typeInfo(AbbrevCode).@"enum".tag_type { | ||
| 3485 | if (dwarf.refAbbrevCodeIfExists(abbrev_code)) |backing_int| { | ||
| 3486 | @branchHint(.likely); | ||
| 3487 | return backing_int; | ||
| 3488 | } | ||
| 3489 | var da_nw: link.MappedFile.Node.Writer = undefined; | ||
| 3490 | dwarf.debug_abbrev.ni.unwrap().?.writer(dwarf.lf.comp.gpa, mf, &da_nw); | ||
| 3491 | defer da_nw.deinit(); | ||
| 3492 | dwarf.genDebugAbbrev(&da_nw, abbrev_code) catch |err| switch (err) { | ||
| 3493 | else => |e| return e, | ||
| 3494 | error.WriteFailed => return dwarf.reportWriteError(&da_nw), | ||
| 3495 | }; | ||
| 3496 | dwarf.debug_abbrev.set.insert(abbrev_code); | ||
| 3497 | return dwarf.refAbbrevCodeIfExists(abbrev_code).?; | ||
| 3498 | } | ||
| 3499 | fn abbrevCode( | ||
| 3500 | dwarf: *Dwarf, | ||
| 3501 | nw: *link.MappedFile.Node.Writer, | ||
| 3502 | abbrev_code: AbbrevCode, | ||
| 3503 | ) link.EmitError!void { | ||
| 3504 | try nw.interface.writeUleb128(try dwarf.refAbbrevCode(nw.mf, abbrev_code)); | ||
| 3505 | } | ||
| 3506 | |||
| 3507 | fn genDebugAbbrev( | ||
| 3508 | dwarf: *Dwarf, | ||
| 3509 | da_nw: *link.MappedFile.Node.Writer, | ||
| 3510 | abbrev_code: AbbrevCode, | ||
| 3511 | ) link.EmitError!void { | ||
| 3512 | const abbrev = AbbrevCode.abbrevs.get(abbrev_code); | ||
| 3513 | const da_w = &da_nw.interface; | ||
| 3514 | da_w.end = dwarf.debug_abbrev.end; | ||
| 3515 | try da_w.writeUleb128(@backingInt(abbrev_code)); | ||
| 3516 | try da_w.writeUleb128(@backingInt(abbrev.tag)); | ||
| 3517 | try da_w.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no); | ||
| 3518 | for (abbrev.attrs) |*attr| { | ||
| 3519 | try da_w.writeUleb128(@backingInt(switch (attr[0]) { | ||
| 3520 | else => |at| at, | ||
| 3521 | .ZIG_call_line_relative => |at| if (dwarf.lf.comp.config.incremental) at else .call_line, | ||
| 3522 | })); | ||
| 3523 | try da_w.writeUleb128(@backingInt(attr[1])); | ||
| 3524 | } | ||
| 3525 | for (0..2) |_| try da_w.writeUleb128(0); | ||
| 3526 | dwarf.debug_abbrev.end = da_w.end; | ||
| 3527 | } | ||
| 3528 | |||
| 3529 | pub fn secOffsetSize(dwarf: *Dwarf) usize { | ||
| 3530 | return switch (dwarf.format) { | ||
| 3531 | .@"32" => 4, | ||
| 3532 | .@"64" => 8, | ||
| 3533 | }; | ||
| 3534 | } | ||
| 3535 | fn secOffsetPlaceholder(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { | ||
| 3536 | @memset(try w.writableSlice(dwarf.secOffsetSize()), undefined); | ||
| 3537 | } | ||
| 3538 | fn secOffset( | ||
| 3539 | dwarf: *Dwarf, | ||
| 3540 | nw: *link.MappedFile.Node.Writer, | ||
| 3541 | target_ni: link.MappedFile.Node.Index, | ||
| 3542 | addend: usize, | ||
| 3543 | ) link.EmitError!void { | ||
| 3544 | const offset = nw.interface.end; | ||
| 3545 | try dwarf.secOffsetPlaceholder(&nw.interface); | ||
| 3546 | if (dwarf.lf.cast(.elf2)) |elf| try elf.addNodeReloc( | ||
| 3547 | nw.ni, | ||
| 3548 | offset, | ||
| 3549 | target_ni, | ||
| 3550 | @bitCast(@as(u64, addend)), | ||
| 3551 | switch (dwarf.format) { | ||
| 3552 | .@"32" => .abs32, | ||
| 3553 | .@"64" => .abs64, | ||
| 3554 | }, | ||
| 3555 | ) else unreachable; | ||
| 3556 | } | ||
| 3557 | |||
| 3558 | fn addrPlaceholder(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void { | ||
| 3559 | @memset(try w.writableSlice(@backingInt(dwarf.address_size)), undefined); | ||
| 3560 | } | ||
| 3561 | fn addrSym( | ||
| 3562 | dwarf: *Dwarf, | ||
| 3563 | nw: *link.MappedFile.Node.Writer, | ||
| 3564 | target_si: link.File.SymbolId, | ||
| 3565 | addend: usize, | ||
| 3566 | ) link.EmitError!void { | ||
| 3567 | const offset = nw.interface.end; | ||
| 3568 | try dwarf.addrPlaceholder(&nw.interface); | ||
| 3569 | if (dwarf.lf.cast(.elf2)) |elf| try elf.addReloc( | ||
| 3570 | @bitCast(nw.ni), | ||
| 3571 | offset, | ||
| 3572 | target_si, | ||
| 3573 | @bitCast(@as(u64, addend)), | ||
| 3574 | .absAddr(elf), | ||
| 3575 | ) else unreachable; | ||
| 3576 | } | ||
| 3577 | |||
| 3578 | fn blockConst( | ||
| 3579 | dwarf: *Dwarf, | ||
| 3580 | pt: Zcu.PerThread, | ||
| 3581 | nw: *link.MappedFile.Node.Writer, | ||
| 3582 | val: Value, | ||
| 3583 | ) link.EmitError!void { | ||
| 3584 | const ty = val.typeOf(pt.zcu); | ||
| 3585 | const size = ty.abiSize(pt.zcu); | ||
| 3586 | try nw.interface.writeUleb128(size); | ||
| 3587 | const start = nw.interface.end; | ||
| 3588 | if (size > 0) try codegen.generateSymbol( | ||
| 3589 | dwarf.lf, | ||
| 3590 | pt, | ||
| 3591 | val, | ||
| 3592 | &nw.interface, | ||
| 3593 | .{ .atom_index = @bitCast(nw.ni) }, | ||
| 3594 | ); | ||
| 3595 | assert(start + size == nw.interface.end); | ||
| 3596 | } | ||
| 3597 | |||
| 3598 | fn refType( | ||
| 3599 | dwarf: *Dwarf, | ||
| 3600 | pt: Zcu.PerThread, | ||
| 3601 | nw: *link.MappedFile.Node.Writer, | ||
| 3602 | ty: Type, | ||
| 3603 | ) link.EmitError!void { | ||
| 3604 | return dwarf.refConst(pt, nw, ty.toValue()); | ||
| 3605 | } | ||
| 3606 | fn refConst( | ||
| 3607 | dwarf: *Dwarf, | ||
| 3608 | pt: Zcu.PerThread, | ||
| 3609 | nw: *link.MappedFile.Node.Writer, | ||
| 3610 | val: Value, | ||
| 3611 | ) link.EmitError!void { | ||
| 3612 | try dwarf.secOffset(nw, Const.get(try dwarf.getConst(pt, val), dwarf).debug_info_ni.unwrap().?, 0); | ||
| 3613 | } | ||
| 3614 | |||
| 3615 | fn bigIntConstValue( | ||
| 3616 | dwarf: *Dwarf, | ||
| 3617 | di_w: *std.Io.Writer, | ||
| 3618 | ty: Type, | ||
| 3619 | big_int: std.math.big.int.Const, | ||
| 3620 | ) link.EmitError!void { | ||
| 3621 | const zcu = dwarf.lf.comp.zcu.?; | ||
| 3622 | const signedness = switch (ty.toIntern()) { | ||
| 3623 | .comptime_int_type => .signed, | ||
| 3624 | else => ty.intInfo(zcu).signedness, | ||
| 3625 | }; | ||
| 3626 | const bits = @max(1, big_int.bitCountTwosCompForSignedness(signedness)); | ||
| 3627 | if (bits <= 64) { | ||
| 3628 | try di_w.writeUleb128(@as(u13, switch (signedness) { | ||
| 3629 | .signed => DW.FORM.sdata, | ||
| 3630 | .unsigned => DW.FORM.udata, | ||
| 3631 | })); | ||
| 3632 | var bit: usize = 0; | ||
| 3633 | var carry: u1 = 1; | ||
| 3634 | for (try di_w.writableSlice(@divCeil(bits, 7))) |*byte| { | ||
| 3635 | const limb_bits = @typeInfo(std.math.big.Limb).int.bits; | ||
| 3636 | const limb_index = bit / limb_bits; | ||
| 3637 | const limb_shift: std.math.Log2Int(std.math.big.Limb) = @intCast(bit % limb_bits); | ||
| 3638 | const low_abs_part: u7 = @truncate(big_int.limbs[limb_index] >> limb_shift); | ||
| 3639 | const abs_part = if (limb_shift > limb_bits - 7 and | ||
| 3640 | limb_index + 1 < big_int.limbs.len) | ||
| 3641 | abs_part: { | ||
| 3642 | const high_abs_part: u7 = @truncate(big_int.limbs[limb_index + 1] << -%limb_shift); | ||
| 3643 | break :abs_part high_abs_part | low_abs_part; | ||
| 3644 | } else low_abs_part; | ||
| 3645 | const twos_comp_part = if (big_int.positive) abs_part else twos_comp_part: { | ||
| 3646 | const twos_comp_part, carry = @addWithOverflow(~abs_part, carry); | ||
| 3647 | break :twos_comp_part twos_comp_part; | ||
| 3648 | }; | ||
| 3649 | bit += 7; | ||
| 3650 | byte.* = @as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part; | ||
| 3651 | } | ||
| 3652 | } else { | ||
| 3653 | try di_w.writeUleb128(DW.FORM.block); | ||
| 3654 | const size = switch (ty.toIntern()) { | ||
| 3655 | .comptime_int_type => @divCeil(bits, 8), | ||
| 3656 | else => ty.abiSize(zcu), | ||
| 3657 | }; | ||
| 3658 | try di_w.writeUleb128(size); | ||
| 3659 | big_int.writeTwosComplement(try di_w.writableSlice(@intCast(size)), dwarf.endian); | ||
| 3660 | } | ||
| 3661 | } | ||
| 3662 | |||
| 3663 | fn enumConstValue( | ||
| 3664 | dwarf: *Dwarf, | ||
| 3665 | di_w: *std.Io.Writer, | ||
| 3666 | loaded_enum: InternPool.LoadedEnumType, | ||
| 3667 | field_index: usize, | ||
| 3668 | ) link.EmitError!void { | ||
| 3669 | const zcu = dwarf.lf.comp.zcu.?; | ||
| 3670 | var big_int_space: Value.BigIntSpace = undefined; | ||
| 3671 | try dwarf.bigIntConstValue( | ||
| 3672 | di_w, | ||
| 3673 | .fromInterned(loaded_enum.int_tag_type), | ||
| 3674 | if (loaded_enum.field_values.len > 0) | ||
| 3675 | Value.fromInterned(loaded_enum.field_values.get(&zcu.intern_pool)[field_index]) | ||
| 3676 | .toBigInt(&big_int_space, zcu) | ||
| 3677 | else | ||
| 3678 | std.math.big.int.Mutable.init(&big_int_space.limbs, field_index).toConst(), | ||
| 3679 | ); | ||
| 3680 | } | ||
| 3681 | |||
| 3682 | fn exprLoc(dwarf: *Dwarf, nw: *link.MappedFile.Node.Writer, loc: Loc) link.EmitError!void { | ||
| 3683 | var buf: [@max(8, std.atomic.cache_line)]u8 = undefined; | ||
| 3684 | var dw: std.Io.Writer.Discarding = .init(&buf); | ||
| 3685 | try loc.write(.{ .io = &dw.writer }, dwarf); | ||
| 3686 | |||
| 3687 | try nw.interface.writeUleb128(dw.fullCount()); | ||
| 3688 | try loc.write(.{ .mf = nw }, dwarf); | ||
| 3689 | } | ||
| 3690 | |||
| 3691 | fn strp(dwarf: *Dwarf, s: *Str, nw: *link.MappedFile.Node.Writer, str: []const u8) link.EmitError!void { | ||
| 3692 | const comp = dwarf.lf.comp; | ||
| 3693 | try dwarf.secOffset(nw, s.ni.unwrap().?, s.get(comp.gpa, nw.mf, str) catch |err| switch (err) { | ||
| 3694 | error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ | ||
| 3695 | nw.mf.io_err.?, | ||
| 3696 | }), | ||
| 3697 | else => |e| return e, | ||
| 3698 | }); | ||
| 3699 | } | ||
| 3700 | |||
| 3701 | fn reportWriteError(dwarf: *Dwarf, nw: *const link.MappedFile.Node.Writer) link.Error { | ||
| 3702 | switch (nw.err.?) { | ||
| 3703 | else => |e| return e, | ||
| 3704 | error.MappedFileIo => return dwarf.lf.comp.link_diags.fail( | ||
| 3705 | "failed to write output file: {t}", | ||
| 3706 | .{nw.mf.io_err.?}, | ||
| 3707 | ), | ||
| 3708 | } | ||
| 3709 | } | ||
| 3710 | |||
| 3711 | fn constPoolUser(dwarf: *Dwarf) link.ConstPool.User { | ||
| 3712 | return if (dwarf.lf.cast(.elf2)) |elf| .{ | ||
| 3713 | .elf2 = elf, | ||
| 3714 | } else unreachable; | ||
| 3715 | } | ||
| 3716 | |||
| 3717 | fn DeclValEnum(comptime T: type) type { | ||
| 3718 | const decl_names = @typeInfo(T).@"struct".decl_names; | ||
| 3719 | @setEvalBranchQuota(10 * decl_names.len); | ||
| 3720 | var field_names: [decl_names.len][]const u8 = undefined; | ||
| 3721 | var fields_len = 0; | ||
| 3722 | var min_value: ?comptime_int = null; | ||
| 3723 | var max_value: ?comptime_int = null; | ||
| 3724 | for (decl_names) |decl_name| { | ||
| 3725 | if (std.mem.startsWith(u8, decl_name, "HP_") or | ||
| 3726 | std.mem.endsWith(u8, decl_name, "_user")) continue; | ||
| 3727 | const value = @field(T, decl_name); | ||
| 3728 | field_names[fields_len] = decl_name; | ||
| 3729 | fields_len += 1; | ||
| 3730 | if (min_value == null or min_value.? > value) min_value = value; | ||
| 3731 | if (max_value == null or max_value.? < value) max_value = value; | ||
| 3732 | } | ||
| 3733 | if (fields_len == 0) return enum {}; | ||
| 3734 | const TagInt = std.math.IntFittingRange(min_value orelse 0, max_value orelse 0); | ||
| 3735 | var field_vals: [fields_len]TagInt = undefined; | ||
| 3736 | for (field_names[0..fields_len], &field_vals) |name, *val| val.* = @field(T, name); | ||
| 3737 | return @Enum(TagInt, .exhaustive, field_names[0..fields_len], &field_vals); | ||
| 3738 | } | ||
| 3739 | |||
| 3740 | pub const AbbrevCode = enum { | ||
| 3741 | null, | ||
| 3742 | // padding codes must be one byte uleb128 values to function | ||
| 3743 | pad_1, | ||
| 3744 | pad_n, | ||
| 3745 | // decl, specification, and instance codes are assumed to all have the same uleb128 size | ||
| 3746 | decl_lost, | ||
| 3747 | decl_alias, | ||
| 3748 | decl_empty_incomplete_enum, | ||
| 3749 | decl_incomplete_enum, | ||
| 3750 | decl_empty_enum, | ||
| 3751 | decl_enum, | ||
| 3752 | type_decl_empty_incomplete_enum, | ||
| 3753 | type_decl_incomplete_enum, | ||
| 3754 | type_decl_empty_enum, | ||
| 3755 | type_decl_enum, | ||
| 3756 | decl_empty_incomplete_struct, | ||
| 3757 | decl_incomplete_struct, | ||
| 3758 | decl_empty_struct, | ||
| 3759 | decl_struct, | ||
| 3760 | type_decl_empty_incomplete_struct, | ||
| 3761 | type_decl_incomplete_struct, | ||
| 3762 | type_decl_empty_struct, | ||
| 3763 | type_decl_struct, | ||
| 3764 | decl_empty_packed_struct, | ||
| 3765 | decl_packed_struct, | ||
| 3766 | type_decl_empty_packed_struct, | ||
| 3767 | type_decl_packed_struct, | ||
| 3768 | decl_empty_incomplete_union, | ||
| 3769 | decl_incomplete_union, | ||
| 3770 | decl_empty_union, | ||
| 3771 | decl_union, | ||
| 3772 | type_decl_empty_incomplete_union, | ||
| 3773 | type_decl_incomplete_union, | ||
| 3774 | type_decl_empty_union, | ||
| 3775 | type_decl_union, | ||
| 3776 | decl_empty_packed_union, | ||
| 3777 | decl_packed_union, | ||
| 3778 | type_decl_empty_packed_union, | ||
| 3779 | type_decl_packed_union, | ||
| 3780 | decl_var, | ||
| 3781 | decl_const, | ||
| 3782 | decl_const_runtime_bits, | ||
| 3783 | decl_const_comptime_state, | ||
| 3784 | decl_const_runtime_bits_comptime_state, | ||
| 3785 | decl_nullary_func, | ||
| 3786 | decl_func, | ||
| 3787 | decl_nullary_func_generic, | ||
| 3788 | decl_func_generic, | ||
| 3789 | decl_extern_nullary_func, | ||
| 3790 | decl_extern_func, | ||
| 3791 | decl_specification_empty_struct, | ||
| 3792 | decl_specification_struct, | ||
| 3793 | type_decl_specification_empty_struct, | ||
| 3794 | type_decl_specification_struct, | ||
| 3795 | decl_specification_empty_enum, | ||
| 3796 | decl_specification_enum, | ||
| 3797 | type_decl_specification_empty_enum, | ||
| 3798 | type_decl_specification_enum, | ||
| 3799 | decl_specification_empty_union, | ||
| 3800 | decl_specification_union, | ||
| 3801 | type_decl_specification_empty_union, | ||
| 3802 | type_decl_specification_union, | ||
| 3803 | decl_specification_func, | ||
| 3804 | decl_instance_alias, | ||
| 3805 | decl_instance_empty_incomplete_enum, | ||
| 3806 | decl_instance_incomplete_enum, | ||
| 3807 | decl_instance_empty_enum, | ||
| 3808 | decl_instance_enum, | ||
| 3809 | decl_instance_empty_incomplete_struct, | ||
| 3810 | decl_instance_incomplete_struct, | ||
| 3811 | decl_instance_empty_struct, | ||
| 3812 | decl_instance_struct, | ||
| 3813 | decl_instance_empty_packed_struct, | ||
| 3814 | decl_instance_packed_struct, | ||
| 3815 | decl_instance_empty_incomplete_union, | ||
| 3816 | decl_instance_incomplete_union, | ||
| 3817 | decl_instance_empty_union, | ||
| 3818 | decl_instance_union, | ||
| 3819 | decl_instance_empty_packed_union, | ||
| 3820 | decl_instance_packed_union, | ||
| 3821 | decl_instance_var, | ||
| 3822 | decl_instance_const, | ||
| 3823 | decl_instance_const_runtime_bits, | ||
| 3824 | decl_instance_const_comptime_state, | ||
| 3825 | decl_instance_const_runtime_bits_comptime_state, | ||
| 3826 | decl_instance_nullary_func, | ||
| 3827 | decl_instance_func, | ||
| 3828 | decl_instance_nullary_func_generic, | ||
| 3829 | decl_instance_func_generic, | ||
| 3830 | decl_instance_extern_nullary_func, | ||
| 3831 | decl_instance_extern_func, | ||
| 3832 | // the rest are unrestricted other than empty variants must not be longer | ||
| 3833 | // than the non-empty variant, and so should appear first | ||
| 3834 | compile_unit, | ||
| 3835 | module, | ||
| 3836 | module_dependency, | ||
| 3837 | empty_file, | ||
| 3838 | file, | ||
| 3839 | access, | ||
| 3840 | enum_field, | ||
| 3841 | generated_field, | ||
| 3842 | field, | ||
| 3843 | field_default_fully_runtime, | ||
| 3844 | field_default_partially_comptime, | ||
| 3845 | field_default_fully_comptime, | ||
| 3846 | field_comptime, | ||
| 3847 | field_comptime_fully_runtime, | ||
| 3848 | field_comptime_partially_comptime, | ||
| 3849 | field_comptime_fully_comptime, | ||
| 3850 | packed_field, | ||
| 3851 | tagged_union, | ||
| 3852 | tagged_union_field, | ||
| 3853 | tagged_union_default_field, | ||
| 3854 | void_type, | ||
| 3855 | numeric_type, | ||
| 3856 | inferred_error_set_type, | ||
| 3857 | ptr_type, | ||
| 3858 | ptr_sentinel_type, | ||
| 3859 | ptr_aligned_type, | ||
| 3860 | ptr_aligned_sentinel_type, | ||
| 3861 | is_const, | ||
| 3862 | is_volatile, | ||
| 3863 | array_type, | ||
| 3864 | array_sentinel_type, | ||
| 3865 | vector_type, | ||
| 3866 | array_index, | ||
| 3867 | array_len, | ||
| 3868 | nullary_func_type, | ||
| 3869 | func_type, | ||
| 3870 | param, | ||
| 3871 | unnamed_param, | ||
| 3872 | is_var_args, | ||
| 3873 | generated_empty_enum_type, | ||
| 3874 | generated_enum_type, | ||
| 3875 | generated_empty_struct_type, | ||
| 3876 | generated_struct_type, | ||
| 3877 | generated_union_type, | ||
| 3878 | capture_specification, | ||
| 3879 | comptime_capture, | ||
| 3880 | comptime_capture_runtime, | ||
| 3881 | comptime_capture_partially_comptime, | ||
| 3882 | comptime_capture_fully_comptime, | ||
| 3883 | runtime_capture, | ||
| 3884 | nav_capture, | ||
| 3885 | builtin_extern_nullary_func, | ||
| 3886 | builtin_extern_func, | ||
| 3887 | builtin_extern_var, | ||
| 3888 | empty_block, | ||
| 3889 | block, | ||
| 3890 | empty_inlined_func, | ||
| 3891 | inlined_func, | ||
| 3892 | arg, | ||
| 3893 | unnamed_arg, | ||
| 3894 | comptime_arg, | ||
| 3895 | comptime_arg_fully_runtime, | ||
| 3896 | comptime_arg_partially_comptime, | ||
| 3897 | comptime_arg_fully_comptime, | ||
| 3898 | unnamed_comptime_arg, | ||
| 3899 | unnamed_comptime_arg_fully_runtime, | ||
| 3900 | unnamed_comptime_arg_partially_comptime, | ||
| 3901 | unnamed_comptime_arg_fully_comptime, | ||
| 3902 | extern_param, | ||
| 3903 | local_var, | ||
| 3904 | local_const, | ||
| 3905 | local_const_fully_runtime, | ||
| 3906 | local_const_partially_comptime, | ||
| 3907 | local_const_fully_comptime, | ||
| 3908 | undefined_comptime_value, | ||
| 3909 | comptime_value, | ||
| 3910 | location_comptime_value, | ||
| 3911 | aggregate_undefined_comptime_value, | ||
| 3912 | aggregate_comptime_value, | ||
| 3913 | aggregate_location_comptime_value, | ||
| 3914 | comptime_value_field_runtime_bits, | ||
| 3915 | comptime_value_field_comptime_state, | ||
| 3916 | comptime_value_elem_runtime_bits, | ||
| 3917 | comptime_value_elem_comptime_state, | ||
| 3918 | |||
| 3919 | const decl_size = uleb128Size(@backingInt(AbbrevCode.decl_instance_extern_func)); | ||
| 3920 | comptime { | ||
| 3921 | assert(uleb128Size(@backingInt(AbbrevCode.pad_1)) == 1); | ||
| 3922 | assert(uleb128Size(@backingInt(AbbrevCode.pad_n)) == 1); | ||
| 3923 | assert(uleb128Size(@backingInt(AbbrevCode.decl_alias)) == decl_size); | ||
| 3924 | } | ||
| 3925 | |||
| 3926 | const Attr = struct { | ||
| 3927 | DeclValEnum(DW.AT), | ||
| 3928 | DeclValEnum(DW.FORM), | ||
| 3929 | }; | ||
| 3930 | const decl_attrs = &[_]Attr{ | ||
| 3931 | .{ .ZIG_parent, .ref_addr }, | ||
| 3932 | .{ .decl_line, .data4 }, | ||
| 3933 | .{ .decl_column, .udata }, | ||
| 3934 | .{ .accessibility, .data1 }, | ||
| 3935 | .{ .name, .strp }, | ||
| 3936 | }; | ||
| 3937 | const type_decl_attrs = &[_]Attr{ | ||
| 3938 | .{ .ZIG_parent, .ref_addr }, | ||
| 3939 | .{ .decl_line, .data4 }, | ||
| 3940 | .{ .decl_column, .udata }, | ||
| 3941 | .{ .name, .strp }, | ||
| 3942 | }; | ||
| 3943 | const decl_specification_attrs = decl_attrs ++ &[_]Attr{ | ||
| 3944 | .{ .declaration, .flag_present }, | ||
| 3945 | }; | ||
| 3946 | const type_decl_specification_attrs = type_decl_attrs ++ &[_]Attr{ | ||
| 3947 | .{ .declaration, .flag_present }, | ||
| 3948 | }; | ||
| 3949 | const decl_instance_attrs = &[_]Attr{ | ||
| 3950 | .{ .specification, .ref_addr }, | ||
| 3951 | }; | ||
| 3952 | |||
| 3953 | const abbrevs = std.EnumArray(AbbrevCode, struct { | ||
| 3954 | tag: DeclValEnum(DW.TAG), | ||
| 3955 | children: bool = false, | ||
| 3956 | attrs: []const Attr = &.{}, | ||
| 3957 | }).init(.{ | ||
| 3958 | .null = undefined, | ||
| 3959 | .pad_1 = .{ | ||
| 3960 | .tag = .ZIG_padding, | ||
| 3961 | }, | ||
| 3962 | .pad_n = .{ | ||
| 3963 | .tag = .ZIG_padding, | ||
| 3964 | .attrs = &.{ | ||
| 3965 | .{ .ZIG_padding, .block }, | ||
| 3966 | }, | ||
| 3967 | }, | ||
| 3968 | .decl_lost = .{ | ||
| 3969 | .tag = .ZIG_lost_declaration, | ||
| 3970 | }, | ||
| 3971 | .decl_alias = .{ | ||
| 3972 | .tag = .imported_declaration, | ||
| 3973 | .attrs = decl_attrs ++ .{ | ||
| 3974 | .{ .import, .ref_addr }, | ||
| 3975 | }, | ||
| 3976 | }, | ||
| 3977 | .decl_empty_incomplete_enum = .{ | ||
| 3978 | .tag = .enumeration_type, | ||
| 3979 | .attrs = decl_attrs, | ||
| 3980 | }, | ||
| 3981 | .decl_incomplete_enum = .{ | ||
| 3982 | .tag = .enumeration_type, | ||
| 3983 | .children = true, | ||
| 3984 | .attrs = decl_attrs, | ||
| 3985 | }, | ||
| 3986 | .decl_empty_enum = .{ | ||
| 3987 | .tag = .enumeration_type, | ||
| 3988 | .attrs = decl_attrs ++ .{ | ||
| 3989 | .{ .type, .ref_addr }, | ||
| 3990 | }, | ||
| 3991 | }, | ||
| 3992 | .decl_enum = .{ | ||
| 3993 | .tag = .enumeration_type, | ||
| 3994 | .children = true, | ||
| 3995 | .attrs = decl_attrs ++ .{ | ||
| 3996 | .{ .type, .ref_addr }, | ||
| 3997 | }, | ||
| 3998 | }, | ||
| 3999 | .type_decl_empty_incomplete_enum = .{ | ||
| 4000 | .tag = .enumeration_type, | ||
| 4001 | .attrs = type_decl_attrs, | ||
| 4002 | }, | ||
| 4003 | .type_decl_incomplete_enum = .{ | ||
| 4004 | .tag = .enumeration_type, | ||
| 4005 | .children = true, | ||
| 4006 | .attrs = type_decl_attrs, | ||
| 4007 | }, | ||
| 4008 | .type_decl_empty_enum = .{ | ||
| 4009 | .tag = .enumeration_type, | ||
| 4010 | .attrs = type_decl_attrs ++ .{ | ||
| 4011 | .{ .type, .ref_addr }, | ||
| 4012 | }, | ||
| 4013 | }, | ||
| 4014 | .type_decl_enum = .{ | ||
| 4015 | .tag = .enumeration_type, | ||
| 4016 | .children = true, | ||
| 4017 | .attrs = type_decl_attrs ++ .{ | ||
| 4018 | .{ .type, .ref_addr }, | ||
| 4019 | }, | ||
| 4020 | }, | ||
| 4021 | .decl_empty_incomplete_struct = .{ | ||
| 4022 | .tag = .structure_type, | ||
| 4023 | .attrs = decl_attrs, | ||
| 4024 | }, | ||
| 4025 | .decl_incomplete_struct = .{ | ||
| 4026 | .tag = .structure_type, | ||
| 4027 | .children = true, | ||
| 4028 | .attrs = decl_attrs, | ||
| 4029 | }, | ||
| 4030 | .decl_empty_struct = .{ | ||
| 4031 | .tag = .structure_type, | ||
| 4032 | .attrs = decl_attrs ++ .{ | ||
| 4033 | .{ .byte_size, .udata }, | ||
| 4034 | .{ .alignment, .udata }, | ||
| 4035 | }, | ||
| 4036 | }, | ||
| 4037 | .decl_struct = .{ | ||
| 4038 | .tag = .structure_type, | ||
| 4039 | .children = true, | ||
| 4040 | .attrs = decl_attrs ++ .{ | ||
| 4041 | .{ .byte_size, .udata }, | ||
| 4042 | .{ .alignment, .udata }, | ||
| 4043 | }, | ||
| 4044 | }, | ||
| 4045 | .type_decl_empty_incomplete_struct = .{ | ||
| 4046 | .tag = .structure_type, | ||
| 4047 | .attrs = type_decl_attrs, | ||
| 4048 | }, | ||
| 4049 | .type_decl_incomplete_struct = .{ | ||
| 4050 | .tag = .structure_type, | ||
| 4051 | .children = true, | ||
| 4052 | .attrs = type_decl_attrs, | ||
| 4053 | }, | ||
| 4054 | .type_decl_empty_struct = .{ | ||
| 4055 | .tag = .structure_type, | ||
| 4056 | .attrs = type_decl_attrs ++ .{ | ||
| 4057 | .{ .byte_size, .udata }, | ||
| 4058 | .{ .alignment, .udata }, | ||
| 4059 | }, | ||
| 4060 | }, | ||
| 4061 | .type_decl_struct = .{ | ||
| 4062 | .tag = .structure_type, | ||
| 4063 | .children = true, | ||
| 4064 | .attrs = type_decl_attrs ++ .{ | ||
| 4065 | .{ .byte_size, .udata }, | ||
| 4066 | .{ .alignment, .udata }, | ||
| 4067 | }, | ||
| 4068 | }, | ||
| 4069 | .decl_empty_packed_struct = .{ | ||
| 4070 | .tag = .structure_type, | ||
| 4071 | .attrs = decl_attrs ++ .{ | ||
| 4072 | .{ .type, .ref_addr }, | ||
| 4073 | }, | ||
| 4074 | }, | ||
| 4075 | .decl_packed_struct = .{ | ||
| 4076 | .tag = .structure_type, | ||
| 4077 | .children = true, | ||
| 4078 | .attrs = decl_attrs ++ .{ | ||
| 4079 | .{ .type, .ref_addr }, | ||
| 4080 | }, | ||
| 4081 | }, | ||
| 4082 | .type_decl_empty_packed_struct = .{ | ||
| 4083 | .tag = .structure_type, | ||
| 4084 | .attrs = type_decl_attrs ++ .{ | ||
| 4085 | .{ .type, .ref_addr }, | ||
| 4086 | }, | ||
| 4087 | }, | ||
| 4088 | .type_decl_packed_struct = .{ | ||
| 4089 | .tag = .structure_type, | ||
| 4090 | .children = true, | ||
| 4091 | .attrs = type_decl_attrs ++ .{ | ||
| 4092 | .{ .type, .ref_addr }, | ||
| 4093 | }, | ||
| 4094 | }, | ||
| 4095 | .decl_empty_incomplete_union = .{ | ||
| 4096 | .tag = .union_type, | ||
| 4097 | .attrs = decl_attrs, | ||
| 4098 | }, | ||
| 4099 | .decl_incomplete_union = .{ | ||
| 4100 | .tag = .union_type, | ||
| 4101 | .children = true, | ||
| 4102 | .attrs = decl_attrs, | ||
| 4103 | }, | ||
| 4104 | .decl_empty_union = .{ | ||
| 4105 | .tag = .union_type, | ||
| 4106 | .attrs = decl_attrs ++ .{ | ||
| 4107 | .{ .byte_size, .udata }, | ||
| 4108 | .{ .alignment, .udata }, | ||
| 4109 | }, | ||
| 4110 | }, | ||
| 4111 | .decl_union = .{ | ||
| 4112 | .tag = .union_type, | ||
| 4113 | .children = true, | ||
| 4114 | .attrs = decl_attrs ++ .{ | ||
| 4115 | .{ .byte_size, .udata }, | ||
| 4116 | .{ .alignment, .udata }, | ||
| 4117 | }, | ||
| 4118 | }, | ||
| 4119 | .type_decl_empty_incomplete_union = .{ | ||
| 4120 | .tag = .union_type, | ||
| 4121 | .attrs = type_decl_attrs, | ||
| 4122 | }, | ||
| 4123 | .type_decl_incomplete_union = .{ | ||
| 4124 | .tag = .union_type, | ||
| 4125 | .children = true, | ||
| 4126 | .attrs = type_decl_attrs, | ||
| 4127 | }, | ||
| 4128 | .type_decl_empty_union = .{ | ||
| 4129 | .tag = .union_type, | ||
| 4130 | .attrs = type_decl_attrs ++ .{ | ||
| 4131 | .{ .byte_size, .udata }, | ||
| 4132 | .{ .alignment, .udata }, | ||
| 4133 | }, | ||
| 4134 | }, | ||
| 4135 | .type_decl_union = .{ | ||
| 4136 | .tag = .union_type, | ||
| 4137 | .children = true, | ||
| 4138 | .attrs = type_decl_attrs ++ .{ | ||
| 4139 | .{ .byte_size, .udata }, | ||
| 4140 | .{ .alignment, .udata }, | ||
| 4141 | }, | ||
| 4142 | }, | ||
| 4143 | .decl_empty_packed_union = .{ | ||
| 4144 | .tag = .union_type, | ||
| 4145 | .attrs = decl_attrs ++ .{ | ||
| 4146 | .{ .type, .ref_addr }, | ||
| 4147 | }, | ||
| 4148 | }, | ||
| 4149 | .decl_packed_union = .{ | ||
| 4150 | .tag = .union_type, | ||
| 4151 | .children = true, | ||
| 4152 | .attrs = decl_attrs ++ .{ | ||
| 4153 | .{ .type, .ref_addr }, | ||
| 4154 | }, | ||
| 4155 | }, | ||
| 4156 | .type_decl_empty_packed_union = .{ | ||
| 4157 | .tag = .union_type, | ||
| 4158 | .attrs = type_decl_attrs ++ .{ | ||
| 4159 | .{ .type, .ref_addr }, | ||
| 4160 | }, | ||
| 4161 | }, | ||
| 4162 | .type_decl_packed_union = .{ | ||
| 4163 | .tag = .union_type, | ||
| 4164 | .children = true, | ||
| 4165 | .attrs = type_decl_attrs ++ .{ | ||
| 4166 | .{ .type, .ref_addr }, | ||
| 4167 | }, | ||
| 4168 | }, | ||
| 4169 | .decl_var = .{ | ||
| 4170 | .tag = .variable, | ||
| 4171 | .attrs = decl_attrs ++ .{ | ||
| 4172 | .{ .linkage_name, .strp }, | ||
| 4173 | .{ .type, .ref_addr }, | ||
| 4174 | .{ .location, .exprloc }, | ||
| 4175 | .{ .alignment, .udata }, | ||
| 4176 | .{ .external, .flag }, | ||
| 4177 | }, | ||
| 4178 | }, | ||
| 4179 | .decl_const = .{ | ||
| 4180 | .tag = .constant, | ||
| 4181 | .attrs = decl_attrs ++ .{ | ||
| 4182 | .{ .linkage_name, .strp }, | ||
| 4183 | .{ .type, .ref_addr }, | ||
| 4184 | .{ .alignment, .udata }, | ||
| 4185 | .{ .external, .flag }, | ||
| 4186 | }, | ||
| 4187 | }, | ||
| 4188 | .decl_const_runtime_bits = .{ | ||
| 4189 | .tag = .constant, | ||
| 4190 | .attrs = decl_attrs ++ .{ | ||
| 4191 | .{ .linkage_name, .strp }, | ||
| 4192 | .{ .type, .ref_addr }, | ||
| 4193 | .{ .alignment, .udata }, | ||
| 4194 | .{ .external, .flag }, | ||
| 4195 | .{ .const_value, .block }, | ||
| 4196 | }, | ||
| 4197 | }, | ||
| 4198 | .decl_const_comptime_state = .{ | ||
| 4199 | .tag = .constant, | ||
| 4200 | .attrs = decl_attrs ++ .{ | ||
| 4201 | .{ .linkage_name, .strp }, | ||
| 4202 | .{ .type, .ref_addr }, | ||
| 4203 | .{ .alignment, .udata }, | ||
| 4204 | .{ .external, .flag }, | ||
| 4205 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4206 | }, | ||
| 4207 | }, | ||
| 4208 | .decl_const_runtime_bits_comptime_state = .{ | ||
| 4209 | .tag = .constant, | ||
| 4210 | .attrs = decl_attrs ++ .{ | ||
| 4211 | .{ .linkage_name, .strp }, | ||
| 4212 | .{ .type, .ref_addr }, | ||
| 4213 | .{ .alignment, .udata }, | ||
| 4214 | .{ .external, .flag }, | ||
| 4215 | .{ .const_value, .block }, | ||
| 4216 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4217 | }, | ||
| 4218 | }, | ||
| 4219 | .decl_nullary_func = .{ | ||
| 4220 | .tag = .subprogram, | ||
| 4221 | .attrs = decl_attrs ++ .{ | ||
| 4222 | .{ .linkage_name, .strp }, | ||
| 4223 | .{ .type, .ref_addr }, | ||
| 4224 | .{ .low_pc, .addr }, | ||
| 4225 | .{ .high_pc, .data4 }, | ||
| 4226 | .{ .alignment, .udata }, | ||
| 4227 | .{ .external, .flag }, | ||
| 4228 | .{ .noreturn, .flag }, | ||
| 4229 | }, | ||
| 4230 | }, | ||
| 4231 | .decl_func = .{ | ||
| 4232 | .tag = .subprogram, | ||
| 4233 | .children = true, | ||
| 4234 | .attrs = decl_attrs ++ .{ | ||
| 4235 | .{ .linkage_name, .strp }, | ||
| 4236 | .{ .type, .ref_addr }, | ||
| 4237 | .{ .low_pc, .addr }, | ||
| 4238 | .{ .high_pc, .data4 }, | ||
| 4239 | .{ .alignment, .udata }, | ||
| 4240 | .{ .external, .flag }, | ||
| 4241 | .{ .noreturn, .flag }, | ||
| 4242 | }, | ||
| 4243 | }, | ||
| 4244 | .decl_nullary_func_generic = .{ | ||
| 4245 | .tag = .subprogram, | ||
| 4246 | .attrs = decl_attrs ++ .{ | ||
| 4247 | .{ .type, .ref_addr }, | ||
| 4248 | .{ .noreturn, .flag }, | ||
| 4249 | }, | ||
| 4250 | }, | ||
| 4251 | .decl_func_generic = .{ | ||
| 4252 | .tag = .subprogram, | ||
| 4253 | .children = true, | ||
| 4254 | .attrs = decl_attrs ++ .{ | ||
| 4255 | .{ .type, .ref_addr }, | ||
| 4256 | }, | ||
| 4257 | }, | ||
| 4258 | .decl_extern_nullary_func = .{ | ||
| 4259 | .tag = .subprogram, | ||
| 4260 | .attrs = decl_attrs ++ .{ | ||
| 4261 | .{ .linkage_name, .strp }, | ||
| 4262 | .{ .type, .ref_addr }, | ||
| 4263 | .{ .low_pc, .addr }, | ||
| 4264 | .{ .external, .flag_present }, | ||
| 4265 | .{ .noreturn, .flag }, | ||
| 4266 | }, | ||
| 4267 | }, | ||
| 4268 | .decl_extern_func = .{ | ||
| 4269 | .tag = .subprogram, | ||
| 4270 | .children = true, | ||
| 4271 | .attrs = decl_attrs ++ .{ | ||
| 4272 | .{ .linkage_name, .strp }, | ||
| 4273 | .{ .type, .ref_addr }, | ||
| 4274 | .{ .low_pc, .addr }, | ||
| 4275 | .{ .external, .flag_present }, | ||
| 4276 | .{ .noreturn, .flag }, | ||
| 4277 | }, | ||
| 4278 | }, | ||
| 4279 | .decl_specification_empty_struct = .{ | ||
| 4280 | .tag = .structure_type, | ||
| 4281 | .attrs = decl_specification_attrs, | ||
| 4282 | }, | ||
| 4283 | .decl_specification_struct = .{ | ||
| 4284 | .tag = .structure_type, | ||
| 4285 | .children = true, | ||
| 4286 | .attrs = decl_specification_attrs, | ||
| 4287 | }, | ||
| 4288 | .type_decl_specification_empty_struct = .{ | ||
| 4289 | .tag = .structure_type, | ||
| 4290 | .attrs = type_decl_specification_attrs, | ||
| 4291 | }, | ||
| 4292 | .type_decl_specification_struct = .{ | ||
| 4293 | .tag = .structure_type, | ||
| 4294 | .children = true, | ||
| 4295 | .attrs = type_decl_specification_attrs, | ||
| 4296 | }, | ||
| 4297 | .decl_specification_empty_enum = .{ | ||
| 4298 | .tag = .enumeration_type, | ||
| 4299 | .attrs = decl_specification_attrs, | ||
| 4300 | }, | ||
| 4301 | .decl_specification_enum = .{ | ||
| 4302 | .tag = .enumeration_type, | ||
| 4303 | .children = true, | ||
| 4304 | .attrs = decl_specification_attrs, | ||
| 4305 | }, | ||
| 4306 | .type_decl_specification_empty_enum = .{ | ||
| 4307 | .tag = .enumeration_type, | ||
| 4308 | .attrs = type_decl_specification_attrs, | ||
| 4309 | }, | ||
| 4310 | .type_decl_specification_enum = .{ | ||
| 4311 | .tag = .enumeration_type, | ||
| 4312 | .children = true, | ||
| 4313 | .attrs = type_decl_specification_attrs, | ||
| 4314 | }, | ||
| 4315 | .decl_specification_empty_union = .{ | ||
| 4316 | .tag = .union_type, | ||
| 4317 | .attrs = decl_specification_attrs, | ||
| 4318 | }, | ||
| 4319 | .decl_specification_union = .{ | ||
| 4320 | .tag = .union_type, | ||
| 4321 | .children = true, | ||
| 4322 | .attrs = decl_specification_attrs, | ||
| 4323 | }, | ||
| 4324 | .type_decl_specification_empty_union = .{ | ||
| 4325 | .tag = .union_type, | ||
| 4326 | .attrs = type_decl_specification_attrs, | ||
| 4327 | }, | ||
| 4328 | .type_decl_specification_union = .{ | ||
| 4329 | .tag = .union_type, | ||
| 4330 | .children = true, | ||
| 4331 | .attrs = type_decl_specification_attrs, | ||
| 4332 | }, | ||
| 4333 | .decl_specification_func = .{ | ||
| 4334 | .tag = .subprogram, | ||
| 4335 | .attrs = decl_specification_attrs, | ||
| 4336 | }, | ||
| 4337 | .decl_instance_alias = .{ | ||
| 4338 | .tag = .imported_declaration, | ||
| 4339 | .attrs = decl_instance_attrs ++ .{ | ||
| 4340 | .{ .import, .ref_addr }, | ||
| 4341 | }, | ||
| 4342 | }, | ||
| 4343 | .decl_instance_empty_incomplete_enum = .{ | ||
| 4344 | .tag = .enumeration_type, | ||
| 4345 | .attrs = decl_instance_attrs, | ||
| 4346 | }, | ||
| 4347 | .decl_instance_incomplete_enum = .{ | ||
| 4348 | .tag = .enumeration_type, | ||
| 4349 | .children = true, | ||
| 4350 | .attrs = decl_instance_attrs, | ||
| 4351 | }, | ||
| 4352 | .decl_instance_empty_enum = .{ | ||
| 4353 | .tag = .enumeration_type, | ||
| 4354 | .attrs = decl_instance_attrs ++ .{ | ||
| 4355 | .{ .type, .ref_addr }, | ||
| 4356 | }, | ||
| 4357 | }, | ||
| 4358 | .decl_instance_enum = .{ | ||
| 4359 | .tag = .enumeration_type, | ||
| 4360 | .children = true, | ||
| 4361 | .attrs = decl_instance_attrs ++ .{ | ||
| 4362 | .{ .type, .ref_addr }, | ||
| 4363 | }, | ||
| 4364 | }, | ||
| 4365 | .decl_instance_empty_incomplete_struct = .{ | ||
| 4366 | .tag = .structure_type, | ||
| 4367 | .attrs = decl_instance_attrs, | ||
| 4368 | }, | ||
| 4369 | .decl_instance_incomplete_struct = .{ | ||
| 4370 | .tag = .structure_type, | ||
| 4371 | .children = true, | ||
| 4372 | .attrs = decl_instance_attrs, | ||
| 4373 | }, | ||
| 4374 | .decl_instance_empty_struct = .{ | ||
| 4375 | .tag = .structure_type, | ||
| 4376 | .attrs = decl_instance_attrs ++ .{ | ||
| 4377 | .{ .byte_size, .udata }, | ||
| 4378 | .{ .alignment, .udata }, | ||
| 4379 | }, | ||
| 4380 | }, | ||
| 4381 | .decl_instance_struct = .{ | ||
| 4382 | .tag = .structure_type, | ||
| 4383 | .children = true, | ||
| 4384 | .attrs = decl_instance_attrs ++ .{ | ||
| 4385 | .{ .byte_size, .udata }, | ||
| 4386 | .{ .alignment, .udata }, | ||
| 4387 | }, | ||
| 4388 | }, | ||
| 4389 | .decl_instance_empty_packed_struct = .{ | ||
| 4390 | .tag = .structure_type, | ||
| 4391 | .attrs = decl_instance_attrs ++ .{ | ||
| 4392 | .{ .type, .ref_addr }, | ||
| 4393 | }, | ||
| 4394 | }, | ||
| 4395 | .decl_instance_packed_struct = .{ | ||
| 4396 | .tag = .structure_type, | ||
| 4397 | .children = true, | ||
| 4398 | .attrs = decl_instance_attrs ++ .{ | ||
| 4399 | .{ .type, .ref_addr }, | ||
| 4400 | }, | ||
| 4401 | }, | ||
| 4402 | .decl_instance_empty_incomplete_union = .{ | ||
| 4403 | .tag = .union_type, | ||
| 4404 | .attrs = decl_instance_attrs, | ||
| 4405 | }, | ||
| 4406 | .decl_instance_incomplete_union = .{ | ||
| 4407 | .tag = .union_type, | ||
| 4408 | .children = true, | ||
| 4409 | .attrs = decl_instance_attrs, | ||
| 4410 | }, | ||
| 4411 | .decl_instance_empty_union = .{ | ||
| 4412 | .tag = .union_type, | ||
| 4413 | .attrs = decl_instance_attrs ++ .{ | ||
| 4414 | .{ .byte_size, .udata }, | ||
| 4415 | .{ .alignment, .udata }, | ||
| 4416 | }, | ||
| 4417 | }, | ||
| 4418 | .decl_instance_union = .{ | ||
| 4419 | .tag = .union_type, | ||
| 4420 | .children = true, | ||
| 4421 | .attrs = decl_instance_attrs ++ .{ | ||
| 4422 | .{ .byte_size, .udata }, | ||
| 4423 | .{ .alignment, .udata }, | ||
| 4424 | }, | ||
| 4425 | }, | ||
| 4426 | .decl_instance_empty_packed_union = .{ | ||
| 4427 | .tag = .union_type, | ||
| 4428 | .attrs = decl_instance_attrs ++ .{ | ||
| 4429 | .{ .type, .ref_addr }, | ||
| 4430 | }, | ||
| 4431 | }, | ||
| 4432 | .decl_instance_packed_union = .{ | ||
| 4433 | .tag = .union_type, | ||
| 4434 | .children = true, | ||
| 4435 | .attrs = decl_instance_attrs ++ .{ | ||
| 4436 | .{ .type, .ref_addr }, | ||
| 4437 | }, | ||
| 4438 | }, | ||
| 4439 | .decl_instance_var = .{ | ||
| 4440 | .tag = .variable, | ||
| 4441 | .attrs = decl_instance_attrs ++ .{ | ||
| 4442 | .{ .linkage_name, .strp }, | ||
| 4443 | .{ .type, .ref_addr }, | ||
| 4444 | .{ .location, .exprloc }, | ||
| 4445 | .{ .alignment, .udata }, | ||
| 4446 | .{ .external, .flag }, | ||
| 4447 | }, | ||
| 4448 | }, | ||
| 4449 | .decl_instance_const = .{ | ||
| 4450 | .tag = .constant, | ||
| 4451 | .attrs = decl_instance_attrs ++ .{ | ||
| 4452 | .{ .linkage_name, .strp }, | ||
| 4453 | .{ .type, .ref_addr }, | ||
| 4454 | .{ .alignment, .udata }, | ||
| 4455 | .{ .external, .flag }, | ||
| 4456 | }, | ||
| 4457 | }, | ||
| 4458 | .decl_instance_const_runtime_bits = .{ | ||
| 4459 | .tag = .constant, | ||
| 4460 | .attrs = decl_instance_attrs ++ .{ | ||
| 4461 | .{ .linkage_name, .strp }, | ||
| 4462 | .{ .type, .ref_addr }, | ||
| 4463 | .{ .alignment, .udata }, | ||
| 4464 | .{ .external, .flag }, | ||
| 4465 | .{ .const_value, .block }, | ||
| 4466 | }, | ||
| 4467 | }, | ||
| 4468 | .decl_instance_const_comptime_state = .{ | ||
| 4469 | .tag = .constant, | ||
| 4470 | .attrs = decl_instance_attrs ++ .{ | ||
| 4471 | .{ .linkage_name, .strp }, | ||
| 4472 | .{ .type, .ref_addr }, | ||
| 4473 | .{ .alignment, .udata }, | ||
| 4474 | .{ .external, .flag }, | ||
| 4475 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4476 | }, | ||
| 4477 | }, | ||
| 4478 | .decl_instance_const_runtime_bits_comptime_state = .{ | ||
| 4479 | .tag = .constant, | ||
| 4480 | .attrs = decl_instance_attrs ++ .{ | ||
| 4481 | .{ .linkage_name, .strp }, | ||
| 4482 | .{ .type, .ref_addr }, | ||
| 4483 | .{ .alignment, .udata }, | ||
| 4484 | .{ .external, .flag }, | ||
| 4485 | .{ .const_value, .block }, | ||
| 4486 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4487 | }, | ||
| 4488 | }, | ||
| 4489 | .decl_instance_nullary_func = .{ | ||
| 4490 | .tag = .subprogram, | ||
| 4491 | .attrs = decl_instance_attrs ++ .{ | ||
| 4492 | .{ .linkage_name, .strp }, | ||
| 4493 | .{ .type, .ref_addr }, | ||
| 4494 | .{ .low_pc, .addr }, | ||
| 4495 | .{ .high_pc, .data4 }, | ||
| 4496 | .{ .alignment, .udata }, | ||
| 4497 | .{ .external, .flag }, | ||
| 4498 | .{ .noreturn, .flag }, | ||
| 4499 | }, | ||
| 4500 | }, | ||
| 4501 | .decl_instance_func = .{ | ||
| 4502 | .tag = .subprogram, | ||
| 4503 | .children = true, | ||
| 4504 | .attrs = decl_instance_attrs ++ .{ | ||
| 4505 | .{ .linkage_name, .strp }, | ||
| 4506 | .{ .type, .ref_addr }, | ||
| 4507 | .{ .low_pc, .addr }, | ||
| 4508 | .{ .high_pc, .data4 }, | ||
| 4509 | .{ .alignment, .udata }, | ||
| 4510 | .{ .external, .flag }, | ||
| 4511 | .{ .noreturn, .flag }, | ||
| 4512 | }, | ||
| 4513 | }, | ||
| 4514 | .decl_instance_nullary_func_generic = .{ | ||
| 4515 | .tag = .subprogram, | ||
| 4516 | .attrs = decl_instance_attrs ++ .{ | ||
| 4517 | .{ .type, .ref_addr }, | ||
| 4518 | }, | ||
| 4519 | }, | ||
| 4520 | .decl_instance_func_generic = .{ | ||
| 4521 | .tag = .subprogram, | ||
| 4522 | .children = true, | ||
| 4523 | .attrs = decl_instance_attrs ++ .{ | ||
| 4524 | .{ .type, .ref_addr }, | ||
| 4525 | }, | ||
| 4526 | }, | ||
| 4527 | .decl_instance_extern_nullary_func = .{ | ||
| 4528 | .tag = .subprogram, | ||
| 4529 | .attrs = decl_instance_attrs ++ .{ | ||
| 4530 | .{ .linkage_name, .strp }, | ||
| 4531 | .{ .type, .ref_addr }, | ||
| 4532 | .{ .low_pc, .addr }, | ||
| 4533 | .{ .external, .flag_present }, | ||
| 4534 | .{ .noreturn, .flag }, | ||
| 4535 | }, | ||
| 4536 | }, | ||
| 4537 | .decl_instance_extern_func = .{ | ||
| 4538 | .tag = .subprogram, | ||
| 4539 | .children = true, | ||
| 4540 | .attrs = decl_instance_attrs ++ .{ | ||
| 4541 | .{ .linkage_name, .strp }, | ||
| 4542 | .{ .type, .ref_addr }, | ||
| 4543 | .{ .low_pc, .addr }, | ||
| 4544 | .{ .external, .flag_present }, | ||
| 4545 | .{ .noreturn, .flag }, | ||
| 4546 | }, | ||
| 4547 | }, | ||
| 4548 | .compile_unit = .{ | ||
| 4549 | .tag = .compile_unit, | ||
| 4550 | .children = true, | ||
| 4551 | .attrs = &.{ | ||
| 4552 | .{ .language, .data1 }, | ||
| 4553 | .{ .producer, .strp }, | ||
| 4554 | .{ .comp_dir, .line_strp }, | ||
| 4555 | .{ .name, .line_strp }, | ||
| 4556 | .{ .base_types, .ref_addr }, | ||
| 4557 | .{ .stmt_list, .sec_offset }, | ||
| 4558 | .{ .rnglists_base, .sec_offset }, | ||
| 4559 | .{ .ranges, .rnglistx }, | ||
| 4560 | .{ .use_UTF8, .flag_present }, | ||
| 4561 | }, | ||
| 4562 | }, | ||
| 4563 | .module = .{ | ||
| 4564 | .tag = .module, | ||
| 4565 | .children = true, | ||
| 4566 | .attrs = &.{ | ||
| 4567 | .{ .name, .strp }, | ||
| 4568 | .{ .ranges, .rnglistx }, | ||
| 4569 | }, | ||
| 4570 | }, | ||
| 4571 | .module_dependency = .{ | ||
| 4572 | .tag = .imported_module, | ||
| 4573 | .attrs = &.{ | ||
| 4574 | .{ .name, .strp }, | ||
| 4575 | .{ .import, .ref_addr }, | ||
| 4576 | }, | ||
| 4577 | }, | ||
| 4578 | .empty_file = .{ | ||
| 4579 | .tag = .structure_type, | ||
| 4580 | .attrs = &.{ | ||
| 4581 | .{ .decl_file, .udata }, | ||
| 4582 | .{ .name, .strp }, | ||
| 4583 | .{ .declaration, .flag }, | ||
| 4584 | }, | ||
| 4585 | }, | ||
| 4586 | .file = .{ | ||
| 4587 | .tag = .structure_type, | ||
| 4588 | .children = true, | ||
| 4589 | .attrs = &.{ | ||
| 4590 | .{ .decl_file, .udata }, | ||
| 4591 | .{ .name, .strp }, | ||
| 4592 | .{ .byte_size, .udata }, | ||
| 4593 | .{ .alignment, .udata }, | ||
| 4594 | }, | ||
| 4595 | }, | ||
| 4596 | .access = .{ | ||
| 4597 | .tag = .member, | ||
| 4598 | .attrs = &.{ | ||
| 4599 | .{ .name, .strp }, | ||
| 4600 | }, | ||
| 4601 | }, | ||
| 4602 | .enum_field = .{ | ||
| 4603 | .tag = .enumerator, | ||
| 4604 | .attrs = &.{ | ||
| 4605 | .{ .const_value, .indirect }, | ||
| 4606 | .{ .name, .strp }, | ||
| 4607 | }, | ||
| 4608 | }, | ||
| 4609 | .generated_field = .{ | ||
| 4610 | .tag = .member, | ||
| 4611 | .attrs = &.{ | ||
| 4612 | .{ .name, .strp }, | ||
| 4613 | .{ .type, .ref_addr }, | ||
| 4614 | .{ .data_member_location, .udata }, | ||
| 4615 | .{ .artificial, .flag_present }, | ||
| 4616 | }, | ||
| 4617 | }, | ||
| 4618 | .field = .{ | ||
| 4619 | .tag = .member, | ||
| 4620 | .attrs = &.{ | ||
| 4621 | .{ .name, .strp }, | ||
| 4622 | .{ .type, .ref_addr }, | ||
| 4623 | .{ .data_member_location, .udata }, | ||
| 4624 | .{ .alignment, .udata }, | ||
| 4625 | }, | ||
| 4626 | }, | ||
| 4627 | .field_default_fully_runtime = .{ | ||
| 4628 | .tag = .member, | ||
| 4629 | .attrs = &.{ | ||
| 4630 | .{ .name, .strp }, | ||
| 4631 | .{ .type, .ref_addr }, | ||
| 4632 | .{ .data_member_location, .udata }, | ||
| 4633 | .{ .alignment, .udata }, | ||
| 4634 | .{ .default_value, .block }, | ||
| 4635 | }, | ||
| 4636 | }, | ||
| 4637 | .field_default_partially_comptime = .{ | ||
| 4638 | .tag = .member, | ||
| 4639 | .attrs = &.{ | ||
| 4640 | .{ .name, .strp }, | ||
| 4641 | .{ .type, .ref_addr }, | ||
| 4642 | .{ .data_member_location, .udata }, | ||
| 4643 | .{ .alignment, .udata }, | ||
| 4644 | .{ .default_value, .block }, | ||
| 4645 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4646 | }, | ||
| 4647 | }, | ||
| 4648 | .field_default_fully_comptime = .{ | ||
| 4649 | .tag = .member, | ||
| 4650 | .attrs = &.{ | ||
| 4651 | .{ .name, .strp }, | ||
| 4652 | .{ .type, .ref_addr }, | ||
| 4653 | .{ .data_member_location, .udata }, | ||
| 4654 | .{ .alignment, .udata }, | ||
| 4655 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4656 | }, | ||
| 4657 | }, | ||
| 4658 | .field_comptime = .{ | ||
| 4659 | .tag = .member, | ||
| 4660 | .attrs = &.{ | ||
| 4661 | .{ .const_expr, .flag_present }, | ||
| 4662 | .{ .name, .strp }, | ||
| 4663 | .{ .type, .ref_addr }, | ||
| 4664 | }, | ||
| 4665 | }, | ||
| 4666 | .field_comptime_fully_runtime = .{ | ||
| 4667 | .tag = .member, | ||
| 4668 | .attrs = &.{ | ||
| 4669 | .{ .const_expr, .flag_present }, | ||
| 4670 | .{ .name, .strp }, | ||
| 4671 | .{ .type, .ref_addr }, | ||
| 4672 | .{ .const_value, .block }, | ||
| 4673 | }, | ||
| 4674 | }, | ||
| 4675 | .field_comptime_partially_comptime = .{ | ||
| 4676 | .tag = .member, | ||
| 4677 | .attrs = &.{ | ||
| 4678 | .{ .const_expr, .flag_present }, | ||
| 4679 | .{ .name, .strp }, | ||
| 4680 | .{ .type, .ref_addr }, | ||
| 4681 | .{ .const_value, .block }, | ||
| 4682 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4683 | }, | ||
| 4684 | }, | ||
| 4685 | .field_comptime_fully_comptime = .{ | ||
| 4686 | .tag = .member, | ||
| 4687 | .attrs = &.{ | ||
| 4688 | .{ .const_expr, .flag_present }, | ||
| 4689 | .{ .name, .strp }, | ||
| 4690 | .{ .type, .ref_addr }, | ||
| 4691 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4692 | }, | ||
| 4693 | }, | ||
| 4694 | .packed_field = .{ | ||
| 4695 | .tag = .member, | ||
| 4696 | .attrs = &.{ | ||
| 4697 | .{ .name, .strp }, | ||
| 4698 | .{ .type, .ref_addr }, | ||
| 4699 | .{ .data_bit_offset, .udata }, | ||
| 4700 | }, | ||
| 4701 | }, | ||
| 4702 | .tagged_union = .{ | ||
| 4703 | .tag = .variant_part, | ||
| 4704 | .children = true, | ||
| 4705 | .attrs = &.{ | ||
| 4706 | .{ .discr, .ref_addr }, | ||
| 4707 | }, | ||
| 4708 | }, | ||
| 4709 | .tagged_union_field = .{ | ||
| 4710 | .tag = .variant, | ||
| 4711 | .children = true, | ||
| 4712 | .attrs = &.{ | ||
| 4713 | .{ .discr_value, .indirect }, | ||
| 4714 | }, | ||
| 4715 | }, | ||
| 4716 | .tagged_union_default_field = .{ | ||
| 4717 | .tag = .variant, | ||
| 4718 | .children = true, | ||
| 4719 | }, | ||
| 4720 | .void_type = .{ | ||
| 4721 | .tag = .unspecified_type, | ||
| 4722 | .attrs = &.{ | ||
| 4723 | .{ .name, .strp }, | ||
| 4724 | }, | ||
| 4725 | }, | ||
| 4726 | .numeric_type = .{ | ||
| 4727 | .tag = .base_type, | ||
| 4728 | .attrs = &.{ | ||
| 4729 | .{ .name, .strp }, | ||
| 4730 | .{ .encoding, .data1 }, | ||
| 4731 | .{ .bit_size, .udata }, | ||
| 4732 | .{ .byte_size, .udata }, | ||
| 4733 | .{ .alignment, .udata }, | ||
| 4734 | }, | ||
| 4735 | }, | ||
| 4736 | .inferred_error_set_type = .{ | ||
| 4737 | .tag = .typedef, | ||
| 4738 | .attrs = &.{ | ||
| 4739 | .{ .name, .strp }, | ||
| 4740 | .{ .type, .ref_addr }, | ||
| 4741 | }, | ||
| 4742 | }, | ||
| 4743 | .ptr_type = .{ | ||
| 4744 | .tag = .pointer_type, | ||
| 4745 | .attrs = &.{ | ||
| 4746 | .{ .name, .strp }, | ||
| 4747 | .{ .address_class, .data1 }, | ||
| 4748 | .{ .type, .ref_addr }, | ||
| 4749 | }, | ||
| 4750 | }, | ||
| 4751 | .ptr_sentinel_type = .{ | ||
| 4752 | .tag = .pointer_type, | ||
| 4753 | .attrs = &.{ | ||
| 4754 | .{ .name, .strp }, | ||
| 4755 | .{ .ZIG_sentinel, .block }, | ||
| 4756 | .{ .address_class, .data1 }, | ||
| 4757 | .{ .type, .ref_addr }, | ||
| 4758 | }, | ||
| 4759 | }, | ||
| 4760 | .ptr_aligned_type = .{ | ||
| 4761 | .tag = .pointer_type, | ||
| 4762 | .attrs = &.{ | ||
| 4763 | .{ .name, .strp }, | ||
| 4764 | .{ .alignment, .udata }, | ||
| 4765 | .{ .address_class, .data1 }, | ||
| 4766 | .{ .type, .ref_addr }, | ||
| 4767 | }, | ||
| 4768 | }, | ||
| 4769 | .ptr_aligned_sentinel_type = .{ | ||
| 4770 | .tag = .pointer_type, | ||
| 4771 | .attrs = &.{ | ||
| 4772 | .{ .name, .strp }, | ||
| 4773 | .{ .ZIG_sentinel, .block }, | ||
| 4774 | .{ .alignment, .udata }, | ||
| 4775 | .{ .address_class, .data1 }, | ||
| 4776 | .{ .type, .ref_addr }, | ||
| 4777 | }, | ||
| 4778 | }, | ||
| 4779 | .is_const = .{ | ||
| 4780 | .tag = .const_type, | ||
| 4781 | .attrs = &.{ | ||
| 4782 | .{ .type, .ref_addr }, | ||
| 4783 | }, | ||
| 4784 | }, | ||
| 4785 | .is_volatile = .{ | ||
| 4786 | .tag = .volatile_type, | ||
| 4787 | .attrs = &.{ | ||
| 4788 | .{ .type, .ref_addr }, | ||
| 4789 | }, | ||
| 4790 | }, | ||
| 4791 | .array_type = .{ | ||
| 4792 | .tag = .array_type, | ||
| 4793 | .children = true, | ||
| 4794 | .attrs = &.{ | ||
| 4795 | .{ .name, .strp }, | ||
| 4796 | .{ .type, .ref_addr }, | ||
| 4797 | }, | ||
| 4798 | }, | ||
| 4799 | .array_sentinel_type = .{ | ||
| 4800 | .tag = .array_type, | ||
| 4801 | .children = true, | ||
| 4802 | .attrs = &.{ | ||
| 4803 | .{ .name, .strp }, | ||
| 4804 | .{ .ZIG_sentinel, .block }, | ||
| 4805 | .{ .type, .ref_addr }, | ||
| 4806 | }, | ||
| 4807 | }, | ||
| 4808 | .vector_type = .{ | ||
| 4809 | .tag = .array_type, | ||
| 4810 | .children = true, | ||
| 4811 | .attrs = &.{ | ||
| 4812 | .{ .name, .strp }, | ||
| 4813 | .{ .type, .ref_addr }, | ||
| 4814 | .{ .GNU_vector, .flag_present }, | ||
| 4815 | }, | ||
| 4816 | }, | ||
| 4817 | .array_index = .{ | ||
| 4818 | .tag = .subrange_type, | ||
| 4819 | .attrs = &.{ | ||
| 4820 | .{ .lower_bound, .udata }, | ||
| 4821 | }, | ||
| 4822 | }, | ||
| 4823 | .array_len = .{ | ||
| 4824 | .tag = .subrange_type, | ||
| 4825 | .attrs = &.{ | ||
| 4826 | .{ .type, .ref_addr }, | ||
| 4827 | .{ .count, .udata }, | ||
| 4828 | }, | ||
| 4829 | }, | ||
| 4830 | .nullary_func_type = .{ | ||
| 4831 | .tag = .subroutine_type, | ||
| 4832 | .attrs = &.{ | ||
| 4833 | .{ .name, .strp }, | ||
| 4834 | .{ .calling_convention, .data1 }, | ||
| 4835 | .{ .type, .ref_addr }, | ||
| 4836 | }, | ||
| 4837 | }, | ||
| 4838 | .func_type = .{ | ||
| 4839 | .tag = .subroutine_type, | ||
| 4840 | .children = true, | ||
| 4841 | .attrs = &.{ | ||
| 4842 | .{ .name, .strp }, | ||
| 4843 | .{ .calling_convention, .data1 }, | ||
| 4844 | .{ .type, .ref_addr }, | ||
| 4845 | }, | ||
| 4846 | }, | ||
| 4847 | .param = .{ | ||
| 4848 | .tag = .formal_parameter, | ||
| 4849 | .attrs = &.{ | ||
| 4850 | .{ .name, .strp }, | ||
| 4851 | .{ .type, .ref_addr }, | ||
| 4852 | }, | ||
| 4853 | }, | ||
| 4854 | .unnamed_param = .{ | ||
| 4855 | .tag = .formal_parameter, | ||
| 4856 | .attrs = &.{ | ||
| 4857 | .{ .type, .ref_addr }, | ||
| 4858 | }, | ||
| 4859 | }, | ||
| 4860 | .is_var_args = .{ | ||
| 4861 | .tag = .unspecified_parameters, | ||
| 4862 | }, | ||
| 4863 | .generated_empty_enum_type = .{ | ||
| 4864 | .tag = .enumeration_type, | ||
| 4865 | .attrs = &.{ | ||
| 4866 | .{ .name, .strp }, | ||
| 4867 | .{ .type, .ref_addr }, | ||
| 4868 | }, | ||
| 4869 | }, | ||
| 4870 | .generated_enum_type = .{ | ||
| 4871 | .tag = .enumeration_type, | ||
| 4872 | .children = true, | ||
| 4873 | .attrs = &.{ | ||
| 4874 | .{ .name, .strp }, | ||
| 4875 | .{ .type, .ref_addr }, | ||
| 4876 | }, | ||
| 4877 | }, | ||
| 4878 | .generated_empty_struct_type = .{ | ||
| 4879 | .tag = .structure_type, | ||
| 4880 | .attrs = &.{ | ||
| 4881 | .{ .name, .strp }, | ||
| 4882 | .{ .declaration, .flag }, | ||
| 4883 | }, | ||
| 4884 | }, | ||
| 4885 | .generated_struct_type = .{ | ||
| 4886 | .tag = .structure_type, | ||
| 4887 | .children = true, | ||
| 4888 | .attrs = &.{ | ||
| 4889 | .{ .name, .strp }, | ||
| 4890 | .{ .byte_size, .udata }, | ||
| 4891 | .{ .alignment, .udata }, | ||
| 4892 | }, | ||
| 4893 | }, | ||
| 4894 | .generated_union_type = .{ | ||
| 4895 | .tag = .union_type, | ||
| 4896 | .children = true, | ||
| 4897 | .attrs = &.{ | ||
| 4898 | .{ .name, .strp }, | ||
| 4899 | .{ .byte_size, .udata }, | ||
| 4900 | .{ .alignment, .udata }, | ||
| 4901 | }, | ||
| 4902 | }, | ||
| 4903 | .capture_specification = .{ | ||
| 4904 | .tag = .template_value_parameter, | ||
| 4905 | .attrs = &.{ | ||
| 4906 | .{ .name, .strp }, | ||
| 4907 | }, | ||
| 4908 | }, | ||
| 4909 | .comptime_capture = .{ | ||
| 4910 | .tag = .template_value_parameter, | ||
| 4911 | .attrs = &.{ | ||
| 4912 | .{ .type, .ref_addr }, | ||
| 4913 | }, | ||
| 4914 | }, | ||
| 4915 | .comptime_capture_runtime = .{ | ||
| 4916 | .tag = .template_value_parameter, | ||
| 4917 | .attrs = &.{ | ||
| 4918 | .{ .type, .ref_addr }, | ||
| 4919 | .{ .const_value, .block }, | ||
| 4920 | }, | ||
| 4921 | }, | ||
| 4922 | .comptime_capture_partially_comptime = .{ | ||
| 4923 | .tag = .template_value_parameter, | ||
| 4924 | .attrs = &.{ | ||
| 4925 | .{ .type, .ref_addr }, | ||
| 4926 | .{ .const_value, .block }, | ||
| 4927 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4928 | }, | ||
| 4929 | }, | ||
| 4930 | .comptime_capture_fully_comptime = .{ | ||
| 4931 | .tag = .template_value_parameter, | ||
| 4932 | .attrs = &.{ | ||
| 4933 | .{ .type, .ref_addr }, | ||
| 4934 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 4935 | }, | ||
| 4936 | }, | ||
| 4937 | .runtime_capture = .{ | ||
| 4938 | .tag = .template_type_parameter, | ||
| 4939 | .attrs = &.{ | ||
| 4940 | .{ .type, .ref_addr }, | ||
| 4941 | }, | ||
| 4942 | }, | ||
| 4943 | .nav_capture = .{ | ||
| 4944 | .tag = .template_value_parameter, | ||
| 4945 | .attrs = &.{ | ||
| 4946 | .{ .location, .exprloc }, | ||
| 4947 | }, | ||
| 4948 | }, | ||
| 4949 | .builtin_extern_nullary_func = .{ | ||
| 4950 | .tag = .subprogram, | ||
| 4951 | .attrs = &.{ | ||
| 4952 | .{ .ZIG_parent, .ref_addr }, | ||
| 4953 | .{ .linkage_name, .strp }, | ||
| 4954 | .{ .type, .ref_addr }, | ||
| 4955 | .{ .low_pc, .addr }, | ||
| 4956 | .{ .external, .flag_present }, | ||
| 4957 | .{ .noreturn, .flag }, | ||
| 4958 | }, | ||
| 4959 | }, | ||
| 4960 | .builtin_extern_func = .{ | ||
| 4961 | .tag = .subprogram, | ||
| 4962 | .children = true, | ||
| 4963 | .attrs = &.{ | ||
| 4964 | .{ .ZIG_parent, .ref_addr }, | ||
| 4965 | .{ .linkage_name, .strp }, | ||
| 4966 | .{ .type, .ref_addr }, | ||
| 4967 | .{ .low_pc, .addr }, | ||
| 4968 | .{ .external, .flag_present }, | ||
| 4969 | .{ .noreturn, .flag }, | ||
| 4970 | }, | ||
| 4971 | }, | ||
| 4972 | .builtin_extern_var = .{ | ||
| 4973 | .tag = .variable, | ||
| 4974 | .attrs = &.{ | ||
| 4975 | .{ .ZIG_parent, .ref_addr }, | ||
| 4976 | .{ .linkage_name, .strp }, | ||
| 4977 | .{ .type, .ref_addr }, | ||
| 4978 | .{ .location, .exprloc }, | ||
| 4979 | .{ .external, .flag_present }, | ||
| 4980 | }, | ||
| 4981 | }, | ||
| 4982 | .empty_block = .{ | ||
| 4983 | .tag = .lexical_block, | ||
| 4984 | .attrs = &.{ | ||
| 4985 | .{ .low_pc, .addr }, | ||
| 4986 | .{ .high_pc, .data4 }, | ||
| 4987 | }, | ||
| 4988 | }, | ||
| 4989 | .block = .{ | ||
| 4990 | .tag = .lexical_block, | ||
| 4991 | .children = true, | ||
| 4992 | .attrs = &.{ | ||
| 4993 | .{ .low_pc, .addr }, | ||
| 4994 | .{ .high_pc, .data4 }, | ||
| 4995 | }, | ||
| 4996 | }, | ||
| 4997 | .empty_inlined_func = .{ | ||
| 4998 | .tag = .inlined_subroutine, | ||
| 4999 | .attrs = &.{ | ||
| 5000 | .{ .abstract_origin, .ref_addr }, | ||
| 5001 | .{ .ZIG_call_line_relative, .udata }, | ||
| 5002 | .{ .call_column, .udata }, | ||
| 5003 | .{ .low_pc, .addr }, | ||
| 5004 | .{ .high_pc, .data4 }, | ||
| 5005 | }, | ||
| 5006 | }, | ||
| 5007 | .inlined_func = .{ | ||
| 5008 | .tag = .inlined_subroutine, | ||
| 5009 | .children = true, | ||
| 5010 | .attrs = &.{ | ||
| 5011 | .{ .abstract_origin, .ref_addr }, | ||
| 5012 | .{ .ZIG_call_line_relative, .udata }, | ||
| 5013 | .{ .call_column, .udata }, | ||
| 5014 | .{ .low_pc, .addr }, | ||
| 5015 | .{ .high_pc, .data4 }, | ||
| 5016 | }, | ||
| 5017 | }, | ||
| 5018 | .arg = .{ | ||
| 5019 | .tag = .formal_parameter, | ||
| 5020 | .attrs = &.{ | ||
| 5021 | .{ .name, .strp }, | ||
| 5022 | .{ .type, .ref_addr }, | ||
| 5023 | .{ .location, .exprloc }, | ||
| 5024 | }, | ||
| 5025 | }, | ||
| 5026 | .unnamed_arg = .{ | ||
| 5027 | .tag = .formal_parameter, | ||
| 5028 | .attrs = &.{ | ||
| 5029 | .{ .type, .ref_addr }, | ||
| 5030 | .{ .location, .exprloc }, | ||
| 5031 | }, | ||
| 5032 | }, | ||
| 5033 | .comptime_arg = .{ | ||
| 5034 | .tag = .formal_parameter, | ||
| 5035 | .attrs = &.{ | ||
| 5036 | .{ .const_expr, .flag_present }, | ||
| 5037 | .{ .name, .strp }, | ||
| 5038 | .{ .type, .ref_addr }, | ||
| 5039 | }, | ||
| 5040 | }, | ||
| 5041 | .comptime_arg_fully_runtime = .{ | ||
| 5042 | .tag = .formal_parameter, | ||
| 5043 | .attrs = &.{ | ||
| 5044 | .{ .const_expr, .flag_present }, | ||
| 5045 | .{ .name, .strp }, | ||
| 5046 | .{ .type, .ref_addr }, | ||
| 5047 | .{ .const_value, .block }, | ||
| 5048 | }, | ||
| 5049 | }, | ||
| 5050 | .comptime_arg_partially_comptime = .{ | ||
| 5051 | .tag = .formal_parameter, | ||
| 5052 | .attrs = &.{ | ||
| 5053 | .{ .const_expr, .flag_present }, | ||
| 5054 | .{ .name, .strp }, | ||
| 5055 | .{ .type, .ref_addr }, | ||
| 5056 | .{ .const_value, .block }, | ||
| 5057 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5058 | }, | ||
| 5059 | }, | ||
| 5060 | .comptime_arg_fully_comptime = .{ | ||
| 5061 | .tag = .formal_parameter, | ||
| 5062 | .attrs = &.{ | ||
| 5063 | .{ .const_expr, .flag_present }, | ||
| 5064 | .{ .name, .strp }, | ||
| 5065 | .{ .type, .ref_addr }, | ||
| 5066 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5067 | }, | ||
| 5068 | }, | ||
| 5069 | .unnamed_comptime_arg = .{ | ||
| 5070 | .tag = .formal_parameter, | ||
| 5071 | .attrs = &.{ | ||
| 5072 | .{ .const_expr, .flag_present }, | ||
| 5073 | .{ .type, .ref_addr }, | ||
| 5074 | }, | ||
| 5075 | }, | ||
| 5076 | .unnamed_comptime_arg_fully_runtime = .{ | ||
| 5077 | .tag = .formal_parameter, | ||
| 5078 | .attrs = &.{ | ||
| 5079 | .{ .const_expr, .flag_present }, | ||
| 5080 | .{ .type, .ref_addr }, | ||
| 5081 | .{ .const_value, .block }, | ||
| 5082 | }, | ||
| 5083 | }, | ||
| 5084 | .unnamed_comptime_arg_partially_comptime = .{ | ||
| 5085 | .tag = .formal_parameter, | ||
| 5086 | .attrs = &.{ | ||
| 5087 | .{ .const_expr, .flag_present }, | ||
| 5088 | .{ .type, .ref_addr }, | ||
| 5089 | .{ .const_value, .block }, | ||
| 5090 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5091 | }, | ||
| 5092 | }, | ||
| 5093 | .unnamed_comptime_arg_fully_comptime = .{ | ||
| 5094 | .tag = .formal_parameter, | ||
| 5095 | .attrs = &.{ | ||
| 5096 | .{ .const_expr, .flag_present }, | ||
| 5097 | .{ .type, .ref_addr }, | ||
| 5098 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5099 | }, | ||
| 5100 | }, | ||
| 5101 | .extern_param = .{ | ||
| 5102 | .tag = .formal_parameter, | ||
| 5103 | .attrs = &.{ | ||
| 5104 | .{ .type, .ref_addr }, | ||
| 5105 | }, | ||
| 5106 | }, | ||
| 5107 | .local_var = .{ | ||
| 5108 | .tag = .variable, | ||
| 5109 | .attrs = &.{ | ||
| 5110 | .{ .name, .strp }, | ||
| 5111 | .{ .type, .ref_addr }, | ||
| 5112 | .{ .location, .exprloc }, | ||
| 5113 | }, | ||
| 5114 | }, | ||
| 5115 | .local_const = .{ | ||
| 5116 | .tag = .constant, | ||
| 5117 | .attrs = &.{ | ||
| 5118 | .{ .name, .strp }, | ||
| 5119 | .{ .type, .ref_addr }, | ||
| 5120 | }, | ||
| 5121 | }, | ||
| 5122 | .local_const_fully_runtime = .{ | ||
| 5123 | .tag = .constant, | ||
| 5124 | .attrs = &.{ | ||
| 5125 | .{ .name, .strp }, | ||
| 5126 | .{ .type, .ref_addr }, | ||
| 5127 | .{ .const_value, .block }, | ||
| 5128 | }, | ||
| 5129 | }, | ||
| 5130 | .local_const_partially_comptime = .{ | ||
| 5131 | .tag = .constant, | ||
| 5132 | .attrs = &.{ | ||
| 5133 | .{ .name, .strp }, | ||
| 5134 | .{ .type, .ref_addr }, | ||
| 5135 | .{ .const_value, .block }, | ||
| 5136 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5137 | }, | ||
| 5138 | }, | ||
| 5139 | .local_const_fully_comptime = .{ | ||
| 5140 | .tag = .constant, | ||
| 5141 | .attrs = &.{ | ||
| 5142 | .{ .name, .strp }, | ||
| 5143 | .{ .type, .ref_addr }, | ||
| 5144 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5145 | }, | ||
| 5146 | }, | ||
| 5147 | .undefined_comptime_value = .{ | ||
| 5148 | .tag = .ZIG_comptime_value, | ||
| 5149 | .attrs = &.{ | ||
| 5150 | .{ .type, .ref_addr }, | ||
| 5151 | }, | ||
| 5152 | }, | ||
| 5153 | .aggregate_undefined_comptime_value = .{ | ||
| 5154 | .tag = .ZIG_comptime_value, | ||
| 5155 | .children = true, | ||
| 5156 | .attrs = &.{ | ||
| 5157 | .{ .type, .ref_addr }, | ||
| 5158 | }, | ||
| 5159 | }, | ||
| 5160 | .comptime_value = .{ | ||
| 5161 | .tag = .ZIG_comptime_value, | ||
| 5162 | .attrs = &.{ | ||
| 5163 | .{ .type, .ref_addr }, | ||
| 5164 | .{ .const_value, .indirect }, | ||
| 5165 | }, | ||
| 5166 | }, | ||
| 5167 | .aggregate_comptime_value = .{ | ||
| 5168 | .tag = .ZIG_comptime_value, | ||
| 5169 | .children = true, | ||
| 5170 | .attrs = &.{ | ||
| 5171 | .{ .type, .ref_addr }, | ||
| 5172 | .{ .const_value, .indirect }, | ||
| 5173 | }, | ||
| 5174 | }, | ||
| 5175 | .location_comptime_value = .{ | ||
| 5176 | .tag = .ZIG_comptime_value, | ||
| 5177 | .attrs = &.{ | ||
| 5178 | .{ .type, .ref_addr }, | ||
| 5179 | .{ .location, .exprloc }, | ||
| 5180 | }, | ||
| 5181 | }, | ||
| 5182 | .aggregate_location_comptime_value = .{ | ||
| 5183 | .tag = .ZIG_comptime_value, | ||
| 5184 | .children = true, | ||
| 5185 | .attrs = &.{ | ||
| 5186 | .{ .type, .ref_addr }, | ||
| 5187 | .{ .location, .exprloc }, | ||
| 5188 | }, | ||
| 5189 | }, | ||
| 5190 | .comptime_value_field_runtime_bits = .{ | ||
| 5191 | .tag = .member, | ||
| 5192 | .attrs = &.{ | ||
| 5193 | .{ .name, .strp }, | ||
| 5194 | .{ .const_value, .block }, | ||
| 5195 | }, | ||
| 5196 | }, | ||
| 5197 | .comptime_value_field_comptime_state = .{ | ||
| 5198 | .tag = .member, | ||
| 5199 | .attrs = &.{ | ||
| 5200 | .{ .name, .strp }, | ||
| 5201 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5202 | }, | ||
| 5203 | }, | ||
| 5204 | .comptime_value_elem_runtime_bits = .{ | ||
| 5205 | .tag = .member, | ||
| 5206 | .attrs = &.{ | ||
| 5207 | .{ .const_value, .block }, | ||
| 5208 | }, | ||
| 5209 | }, | ||
| 5210 | .comptime_value_elem_comptime_state = .{ | ||
| 5211 | .tag = .member, | ||
| 5212 | .attrs = &.{ | ||
| 5213 | .{ .ZIG_comptime_value, .ref_addr }, | ||
| 5214 | }, | ||
| 5215 | }, | ||
| 5216 | }); | ||
| 5217 | }; | ||
| 5218 | |||
| 5219 | pub fn uleb128Size(value: anytype) u32 { | ||
| 5220 | var buf: [std.atomic.cache_line]u8 = undefined; | ||
| 5221 | var dw: std.Io.Writer.Discarding = .init(&buf); | ||
| 5222 | dw.writer.writeUleb128(value) catch unreachable; | ||
| 5223 | return @intCast(dw.fullCount()); | ||
| 5224 | } | ||
| 5225 | |||
| 5226 | pub fn sleb128Size(value: anytype) u32 { | ||
| 5227 | var buf: [std.atomic.cache_line]u8 = undefined; | ||
| 5228 | var dw: std.Io.Writer.Discarding = .init(&buf); | ||
| 5229 | dw.writer.writeSleb128(value) catch unreachable; | ||
| 5230 | return @intCast(dw.fullCount()); | ||
| 5231 | } | ||
| 5232 | |||
| 5233 | const assert = std.debug.assert; | ||
| 5234 | const codegen = @import("../codegen.zig"); | ||
| 5235 | const Compilation = @import("../Compilation.zig"); | ||
| 5236 | const dev = @import("../dev.zig"); | ||
| 5237 | const DW = std.dwarf; | ||
| 5238 | const Dwarf = @This(); | ||
| 5239 | const InternPool = @import("../InternPool.zig"); | ||
| 5240 | const link = @import("../link.zig"); | ||
| 5241 | const log = std.log.scoped(.dwarf); | ||
| 5242 | const Module = @import("../Module.zig"); | ||
| 5243 | const std = @import("std"); | ||
| 5244 | const target_info = @import("../target.zig"); | ||
| 5245 | const Type = @import("../Type.zig"); | ||
| 5246 | const Value = @import("../Value.zig"); | ||
| 5247 | const Zcu = @import("../Zcu.zig"); | ||
src/link/Elf.zig+3-6| ... | @@ -1677,9 +1677,7 @@ pub fn updateContainerType( | ... | @@ -1677,9 +1677,7 @@ pub fn updateContainerType( |
| 1677 | ty: InternPool.Index, | 1677 | ty: InternPool.Index, |
| 1678 | success: bool, | 1678 | success: bool, |
| 1679 | ) link.Error!void { | 1679 | ) link.Error!void { |
| 1680 | return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) { | 1680 | try self.zigObjectPtr().?.updateContainerType(pt, ty, success); |
| 1681 | error.OutOfMemory => |e| return e, | ||
| 1682 | }; | ||
| 1683 | } | 1681 | } |
| 1684 | 1682 | ||
| 1685 | pub fn updateExports( | 1683 | pub fn updateExports( |
| ... | @@ -1690,8 +1688,8 @@ pub fn updateExports( | ... | @@ -1690,8 +1688,8 @@ pub fn updateExports( |
| 1690 | return self.zigObjectPtr().?.updateExports(self, pt, export_indices); | 1688 | return self.zigObjectPtr().?.updateExports(self, pt, export_indices); |
| 1691 | } | 1689 | } |
| 1692 | 1690 | ||
| 1693 | pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void { | 1691 | pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, inst: InternPool.TrackedInst.Index, line: u32) link.Error!void { |
| 1694 | return self.zigObjectPtr().?.updateLineNumber(pt, ti_id); | 1692 | return self.zigObjectPtr().?.updateLineNumber(pt, inst, line); |
| 1695 | } | 1693 | } |
| 1696 | 1694 | ||
| 1697 | fn checkDuplicates(self: *Elf) !void { | 1695 | fn checkDuplicates(self: *Elf) !void { |
| ... | @@ -4412,7 +4410,6 @@ const Path = std.Build.Cache.Path; | ... | @@ -4412,7 +4410,6 @@ const Path = std.Build.Cache.Path; |
| 4412 | const Stat = std.Build.Cache.File.Stat; | 4410 | const Stat = std.Build.Cache.File.Stat; |
| 4413 | 4411 | ||
| 4414 | const codegen = @import("../codegen.zig"); | 4412 | const codegen = @import("../codegen.zig"); |
| 4415 | const dev = @import("../dev.zig"); | ||
| 4416 | const eh_frame = @import("Elf/eh_frame.zig"); | 4413 | const eh_frame = @import("Elf/eh_frame.zig"); |
| 4417 | const gc = @import("Elf/gc.zig"); | 4414 | const gc = @import("Elf/gc.zig"); |
| 4418 | const musl = @import("../libs/musl.zig"); | 4415 | const musl = @import("../libs/musl.zig"); |
src/link/Elf/Atom.zig+17-11| ... | @@ -945,7 +945,7 @@ const x86_64 = struct { | ... | @@ -945,7 +945,7 @@ const x86_64 = struct { |
| 945 | code: ?[]const u8, | 945 | code: ?[]const u8, |
| 946 | it: *RelocsIterator, | 946 | it: *RelocsIterator, |
| 947 | ) !void { | 947 | ) !void { |
| 948 | dev.check(.x86_64_backend); | 948 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 949 | const t = &elf_file.base.comp.root_mod.resolved_target.result; | 949 | const t = &elf_file.base.comp.root_mod.resolved_target.result; |
| 950 | const is_static = elf_file.base.isStatic(); | 950 | const is_static = elf_file.base.isStatic(); |
| 951 | const is_dyn_lib = elf_file.isEffectivelyDynLib(); | 951 | const is_dyn_lib = elf_file.isEffectivelyDynLib(); |
| ... | @@ -1059,7 +1059,7 @@ const x86_64 = struct { | ... | @@ -1059,7 +1059,7 @@ const x86_64 = struct { |
| 1059 | it: *RelocsIterator, | 1059 | it: *RelocsIterator, |
| 1060 | code: []u8, | 1060 | code: []u8, |
| 1061 | ) !void { | 1061 | ) !void { |
| 1062 | dev.check(.x86_64_backend); | 1062 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1063 | const t = &elf_file.base.comp.root_mod.resolved_target.result; | 1063 | const t = &elf_file.base.comp.root_mod.resolved_target.result; |
| 1064 | const diags = &elf_file.base.comp.link_diags; | 1064 | const diags = &elf_file.base.comp.link_diags; |
| 1065 | const r_type: elf.R_X86_64 = @fromBackingInt(@intCast(rel.r_type())); | 1065 | const r_type: elf.R_X86_64 = @fromBackingInt(@intCast(rel.r_type())); |
| ... | @@ -1200,7 +1200,7 @@ const x86_64 = struct { | ... | @@ -1200,7 +1200,7 @@ const x86_64 = struct { |
| 1200 | args: ResolveArgs, | 1200 | args: ResolveArgs, |
| 1201 | code: []u8, | 1201 | code: []u8, |
| 1202 | ) !void { | 1202 | ) !void { |
| 1203 | dev.check(.x86_64_backend); | 1203 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1204 | const r_type: elf.R_X86_64 = @fromBackingInt(@intCast(rel.r_type())); | 1204 | const r_type: elf.R_X86_64 = @fromBackingInt(@intCast(rel.r_type())); |
| 1205 | 1205 | ||
| 1206 | _, const A, const S, const GOT, _, _, const DTP = args; | 1206 | _, const A, const S, const GOT, _, _, const DTP = args; |
| ... | @@ -1240,7 +1240,7 @@ const x86_64 = struct { | ... | @@ -1240,7 +1240,7 @@ const x86_64 = struct { |
| 1240 | } | 1240 | } |
| 1241 | 1241 | ||
| 1242 | fn relaxGotpcrelx(code: []u8, t: *const std.Target) !void { | 1242 | fn relaxGotpcrelx(code: []u8, t: *const std.Target) !void { |
| 1243 | dev.check(.x86_64_backend); | 1243 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1244 | const old_inst = disassemble(code) orelse return error.RelaxFailure; | 1244 | const old_inst = disassemble(code) orelse return error.RelaxFailure; |
| 1245 | const inst: Instruction = switch (old_inst.encoding.mnemonic) { | 1245 | const inst: Instruction = switch (old_inst.encoding.mnemonic) { |
| 1246 | .call => try .new(old_inst.prefix, .call, &.{ | 1246 | .call => try .new(old_inst.prefix, .call, &.{ |
| ... | @@ -1259,7 +1259,7 @@ const x86_64 = struct { | ... | @@ -1259,7 +1259,7 @@ const x86_64 = struct { |
| 1259 | } | 1259 | } |
| 1260 | 1260 | ||
| 1261 | fn relaxRexGotpcrelx(code: []u8, t: *const std.Target) !void { | 1261 | fn relaxRexGotpcrelx(code: []u8, t: *const std.Target) !void { |
| 1262 | dev.check(.x86_64_backend); | 1262 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1263 | const old_inst = disassemble(code) orelse return error.RelaxFailure; | 1263 | const old_inst = disassemble(code) orelse return error.RelaxFailure; |
| 1264 | switch (old_inst.encoding.mnemonic) { | 1264 | switch (old_inst.encoding.mnemonic) { |
| 1265 | .mov => { | 1265 | .mov => { |
| ... | @@ -1279,7 +1279,7 @@ const x86_64 = struct { | ... | @@ -1279,7 +1279,7 @@ const x86_64 = struct { |
| 1279 | code: []u8, | 1279 | code: []u8, |
| 1280 | r_offset: usize, | 1280 | r_offset: usize, |
| 1281 | ) !void { | 1281 | ) !void { |
| 1282 | dev.check(.x86_64_backend); | 1282 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1283 | assert(rels.len == 2); | 1283 | assert(rels.len == 2); |
| 1284 | const diags = &elf_file.base.comp.link_diags; | 1284 | const diags = &elf_file.base.comp.link_diags; |
| 1285 | const rel: elf.R_X86_64 = @fromBackingInt(@intCast(rels[1].r_type())); | 1285 | const rel: elf.R_X86_64 = @fromBackingInt(@intCast(rels[1].r_type())); |
| ... | @@ -1319,7 +1319,7 @@ const x86_64 = struct { | ... | @@ -1319,7 +1319,7 @@ const x86_64 = struct { |
| 1319 | code: []u8, | 1319 | code: []u8, |
| 1320 | r_offset: usize, | 1320 | r_offset: usize, |
| 1321 | ) !void { | 1321 | ) !void { |
| 1322 | dev.check(.x86_64_backend); | 1322 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1323 | assert(rels.len == 2); | 1323 | assert(rels.len == 2); |
| 1324 | const diags = &elf_file.base.comp.link_diags; | 1324 | const diags = &elf_file.base.comp.link_diags; |
| 1325 | const rel: elf.R_X86_64 = @fromBackingInt(@intCast(rels[1].r_type())); | 1325 | const rel: elf.R_X86_64 = @fromBackingInt(@intCast(rels[1].r_type())); |
| ... | @@ -1366,7 +1366,7 @@ const x86_64 = struct { | ... | @@ -1366,7 +1366,7 @@ const x86_64 = struct { |
| 1366 | } | 1366 | } |
| 1367 | 1367 | ||
| 1368 | fn canRelaxGotTpOff(code: []const u8, t: *const std.Target) bool { | 1368 | fn canRelaxGotTpOff(code: []const u8, t: *const std.Target) bool { |
| 1369 | dev.check(.x86_64_backend); | 1369 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1370 | const old_inst = disassemble(code) orelse return false; | 1370 | const old_inst = disassemble(code) orelse return false; |
| 1371 | switch (old_inst.encoding.mnemonic) { | 1371 | switch (old_inst.encoding.mnemonic) { |
| 1372 | .mov => { | 1372 | .mov => { |
| ... | @@ -1384,7 +1384,7 @@ const x86_64 = struct { | ... | @@ -1384,7 +1384,7 @@ const x86_64 = struct { |
| 1384 | } | 1384 | } |
| 1385 | 1385 | ||
| 1386 | fn relaxGotTpOff(code: []u8, t: *const std.Target) void { | 1386 | fn relaxGotTpOff(code: []u8, t: *const std.Target) void { |
| 1387 | dev.check(.x86_64_backend); | 1387 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1388 | const old_inst = disassemble(code) orelse unreachable; | 1388 | const old_inst = disassemble(code) orelse unreachable; |
| 1389 | switch (old_inst.encoding.mnemonic) { | 1389 | switch (old_inst.encoding.mnemonic) { |
| 1390 | .mov => { | 1390 | .mov => { |
| ... | @@ -1401,7 +1401,7 @@ const x86_64 = struct { | ... | @@ -1401,7 +1401,7 @@ const x86_64 = struct { |
| 1401 | } | 1401 | } |
| 1402 | 1402 | ||
| 1403 | fn relaxGotPcTlsDesc(code: []u8, target: *const std.Target) !void { | 1403 | fn relaxGotPcTlsDesc(code: []u8, target: *const std.Target) !void { |
| 1404 | dev.check(.x86_64_backend); | 1404 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1405 | const old_inst = disassemble(code) orelse return error.RelaxFailure; | 1405 | const old_inst = disassemble(code) orelse return error.RelaxFailure; |
| 1406 | switch (old_inst.encoding.mnemonic) { | 1406 | switch (old_inst.encoding.mnemonic) { |
| 1407 | .lea => { | 1407 | .lea => { |
| ... | @@ -1425,7 +1425,7 @@ const x86_64 = struct { | ... | @@ -1425,7 +1425,7 @@ const x86_64 = struct { |
| 1425 | code: []u8, | 1425 | code: []u8, |
| 1426 | r_offset: usize, | 1426 | r_offset: usize, |
| 1427 | ) !void { | 1427 | ) !void { |
| 1428 | dev.check(.x86_64_backend); | 1428 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 1429 | assert(rels.len == 2); | 1429 | assert(rels.len == 2); |
| 1430 | const diags = &elf_file.base.comp.link_diags; | 1430 | const diags = &elf_file.base.comp.link_diags; |
| 1431 | const rel: elf.R_X86_64 = @fromBackingInt(@intCast(rels[1].r_type())); | 1431 | const rel: elf.R_X86_64 = @fromBackingInt(@intCast(rels[1].r_type())); |
| ... | @@ -1492,6 +1492,7 @@ const aarch64 = struct { | ... | @@ -1492,6 +1492,7 @@ const aarch64 = struct { |
| 1492 | ) !void { | 1492 | ) !void { |
| 1493 | _ = code; | 1493 | _ = code; |
| 1494 | _ = it; | 1494 | _ = it; |
| 1495 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 1495 | 1496 | ||
| 1496 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); | 1497 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); |
| 1497 | const is_dyn_lib = elf_file.isEffectivelyDynLib(); | 1498 | const is_dyn_lib = elf_file.isEffectivelyDynLib(); |
| ... | @@ -1569,6 +1570,7 @@ const aarch64 = struct { | ... | @@ -1569,6 +1570,7 @@ const aarch64 = struct { |
| 1569 | code_buffer: []u8, | 1570 | code_buffer: []u8, |
| 1570 | ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void { | 1571 | ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void { |
| 1571 | _ = it; | 1572 | _ = it; |
| 1573 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 1572 | 1574 | ||
| 1573 | const diags = &elf_file.base.comp.link_diags; | 1575 | const diags = &elf_file.base.comp.link_diags; |
| 1574 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); | 1576 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); |
| ... | @@ -1742,6 +1744,7 @@ const aarch64 = struct { | ... | @@ -1742,6 +1744,7 @@ const aarch64 = struct { |
| 1742 | args: ResolveArgs, | 1744 | args: ResolveArgs, |
| 1743 | code: []u8, | 1745 | code: []u8, |
| 1744 | ) !void { | 1746 | ) !void { |
| 1747 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 1745 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); | 1748 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); |
| 1746 | 1749 | ||
| 1747 | _, const A, const S, _, _, _, _ = args; | 1750 | _, const A, const S, _, _, _, _ = args; |
| ... | @@ -1772,6 +1775,7 @@ const riscv = struct { | ... | @@ -1772,6 +1775,7 @@ const riscv = struct { |
| 1772 | ) !void { | 1775 | ) !void { |
| 1773 | _ = code; | 1776 | _ = code; |
| 1774 | _ = it; | 1777 | _ = it; |
| 1778 | dev.checkAny(&.{ .llvm_backend, .riscv64_backend }); | ||
| 1775 | 1779 | ||
| 1776 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); | 1780 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); |
| 1777 | 1781 | ||
| ... | @@ -1815,6 +1819,7 @@ const riscv = struct { | ... | @@ -1815,6 +1819,7 @@ const riscv = struct { |
| 1815 | it: *RelocsIterator, | 1819 | it: *RelocsIterator, |
| 1816 | code: []u8, | 1820 | code: []u8, |
| 1817 | ) !void { | 1821 | ) !void { |
| 1822 | dev.checkAny(&.{ .llvm_backend, .riscv64_backend }); | ||
| 1818 | const diags = &elf_file.base.comp.link_diags; | 1823 | const diags = &elf_file.base.comp.link_diags; |
| 1819 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); | 1824 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); |
| 1820 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; | 1825 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| ... | @@ -1951,6 +1956,7 @@ const riscv = struct { | ... | @@ -1951,6 +1956,7 @@ const riscv = struct { |
| 1951 | args: ResolveArgs, | 1956 | args: ResolveArgs, |
| 1952 | code: []u8, | 1957 | code: []u8, |
| 1953 | ) !void { | 1958 | ) !void { |
| 1959 | dev.checkAny(&.{ .llvm_backend, .riscv64_backend }); | ||
| 1954 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); | 1960 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); |
| 1955 | 1961 | ||
| 1956 | _, const A, const S, const GOT, _, _, const DTP = args; | 1962 | _, const A, const S, const GOT, _, _, const DTP = args; |
src/link/Elf/Object.zig+15-22| ... | @@ -1236,29 +1236,22 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index | ... | @@ -1236,29 +1236,22 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index |
| 1236 | 1236 | ||
| 1237 | if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { | 1237 | if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { |
| 1238 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; | 1238 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; |
| 1239 | var compressed_reader: Io.Reader = .fixed(data[@sizeOf(elf.Elf64_Chdr)..]); | ||
| 1240 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; | ||
| 1241 | var aw: Io.Writer.Allocating = try .initCapacity(gpa, size); | ||
| 1242 | defer aw.deinit(); | ||
| 1239 | switch (chdr.ch_type) { | 1243 | switch (chdr.ch_type) { |
| 1240 | .ZLIB => { | 1244 | .ZLIB => { |
| 1241 | var stream: std.Io.Reader = .fixed(data[@sizeOf(elf.Elf64_Chdr)..]); | 1245 | var decompress: std.compress.flate.Decompress = .init(&compressed_reader, .zlib, &.{}); |
| 1242 | var zlib_stream: std.compress.flate.Decompress = .init(&stream, .zlib, &.{}); | 1246 | _ = try decompress.reader.streamRemaining(&aw.writer); |
| 1243 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; | ||
| 1244 | var aw: std.Io.Writer.Allocating = .init(gpa); | ||
| 1245 | try aw.ensureUnusedCapacity(size); | ||
| 1246 | defer aw.deinit(); | ||
| 1247 | _ = try zlib_stream.reader.streamRemaining(&aw.writer); | ||
| 1248 | return aw.toOwnedSlice(); | ||
| 1249 | }, | 1247 | }, |
| 1250 | .ZSTD => { | 1248 | .ZSTD => { |
| 1251 | var input: std.Io.Reader = .fixed(data[@sizeOf(elf.Elf64_Chdr)..]); | 1249 | var decompress: std.compress.zstd.Decompress = .init(&compressed_reader, &.{}, .{}); |
| 1252 | var stream: std.compress.zstd.Decompress = .init(&input, &.{}, .{}); | 1250 | _ = try decompress.reader.streamRemaining(&aw.writer); |
| 1253 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; | ||
| 1254 | var aw: std.Io.Writer.Allocating = try .initCapacity(gpa, size); | ||
| 1255 | defer aw.deinit(); | ||
| 1256 | _ = try stream.reader.streamRemaining(&aw.writer); | ||
| 1257 | |||
| 1258 | return aw.toOwnedSlice(); | ||
| 1259 | }, | 1251 | }, |
| 1260 | else => @panic("TODO unhandled compression scheme"), | 1252 | else => @panic("TODO unhandled compression scheme"), |
| 1261 | } | 1253 | } |
| 1254 | return aw.toOwnedSlice(); | ||
| 1262 | } | 1255 | } |
| 1263 | 1256 | ||
| 1264 | return data; | 1257 | return data; |
| ... | @@ -1492,7 +1485,7 @@ const Format = struct { | ... | @@ -1492,7 +1485,7 @@ const Format = struct { |
| 1492 | object: *Object, | 1485 | object: *Object, |
| 1493 | elf_file: *Elf, | 1486 | elf_file: *Elf, |
| 1494 | 1487 | ||
| 1495 | fn symtab(f: Format, writer: *std.Io.Writer) std.Io.Writer.Error!void { | 1488 | fn symtab(f: Format, writer: *Io.Writer) Io.Writer.Error!void { |
| 1496 | const object = f.object; | 1489 | const object = f.object; |
| 1497 | const elf_file = f.elf_file; | 1490 | const elf_file = f.elf_file; |
| 1498 | try writer.writeAll(" locals\n"); | 1491 | try writer.writeAll(" locals\n"); |
| ... | @@ -1511,7 +1504,7 @@ const Format = struct { | ... | @@ -1511,7 +1504,7 @@ const Format = struct { |
| 1511 | } | 1504 | } |
| 1512 | } | 1505 | } |
| 1513 | 1506 | ||
| 1514 | fn atoms(f: Format, writer: *std.Io.Writer) std.Io.Writer.Error!void { | 1507 | fn atoms(f: Format, writer: *Io.Writer) Io.Writer.Error!void { |
| 1515 | const object = f.object; | 1508 | const object = f.object; |
| 1516 | try writer.writeAll(" atoms\n"); | 1509 | try writer.writeAll(" atoms\n"); |
| 1517 | for (object.atoms_indexes.items) |atom_index| { | 1510 | for (object.atoms_indexes.items) |atom_index| { |
| ... | @@ -1520,7 +1513,7 @@ const Format = struct { | ... | @@ -1520,7 +1513,7 @@ const Format = struct { |
| 1520 | } | 1513 | } |
| 1521 | } | 1514 | } |
| 1522 | 1515 | ||
| 1523 | fn cies(f: Format, writer: *std.Io.Writer) std.Io.Writer.Error!void { | 1516 | fn cies(f: Format, writer: *Io.Writer) Io.Writer.Error!void { |
| 1524 | const object = f.object; | 1517 | const object = f.object; |
| 1525 | try writer.writeAll(" cies\n"); | 1518 | try writer.writeAll(" cies\n"); |
| 1526 | for (object.cies.items, 0..) |cie, i| { | 1519 | for (object.cies.items, 0..) |cie, i| { |
| ... | @@ -1528,7 +1521,7 @@ const Format = struct { | ... | @@ -1528,7 +1521,7 @@ const Format = struct { |
| 1528 | } | 1521 | } |
| 1529 | } | 1522 | } |
| 1530 | 1523 | ||
| 1531 | fn fdes(f: Format, writer: *std.Io.Writer) std.Io.Writer.Error!void { | 1524 | fn fdes(f: Format, writer: *Io.Writer) Io.Writer.Error!void { |
| 1532 | const object = f.object; | 1525 | const object = f.object; |
| 1533 | try writer.writeAll(" fdes\n"); | 1526 | try writer.writeAll(" fdes\n"); |
| 1534 | for (object.fdes.items, 0..) |fde, i| { | 1527 | for (object.fdes.items, 0..) |fde, i| { |
| ... | @@ -1536,7 +1529,7 @@ const Format = struct { | ... | @@ -1536,7 +1529,7 @@ const Format = struct { |
| 1536 | } | 1529 | } |
| 1537 | } | 1530 | } |
| 1538 | 1531 | ||
| 1539 | fn groups(f: Format, writer: *std.Io.Writer) std.Io.Writer.Error!void { | 1532 | fn groups(f: Format, writer: *Io.Writer) Io.Writer.Error!void { |
| 1540 | const object = f.object; | 1533 | const object = f.object; |
| 1541 | const elf_file = f.elf_file; | 1534 | const elf_file = f.elf_file; |
| 1542 | try writer.writeAll(" groups\n"); | 1535 | try writer.writeAll(" groups\n"); |
| ... | @@ -1586,7 +1579,7 @@ pub fn fmtPath(self: Object) std.fmt.Alt(Object, formatPath) { | ... | @@ -1586,7 +1579,7 @@ pub fn fmtPath(self: Object) std.fmt.Alt(Object, formatPath) { |
| 1586 | return .{ .data = self }; | 1579 | return .{ .data = self }; |
| 1587 | } | 1580 | } |
| 1588 | 1581 | ||
| 1589 | fn formatPath(object: Object, writer: *std.Io.Writer) std.Io.Writer.Error!void { | 1582 | fn formatPath(object: Object, writer: *Io.Writer) Io.Writer.Error!void { |
| 1590 | if (object.archive) |ar| { | 1583 | if (object.archive) |ar| { |
| 1591 | try writer.print("{f}({f})", .{ ar.path, object.path }); | 1584 | try writer.print("{f}({f})", .{ ar.path, object.path }); |
| 1592 | } else { | 1585 | } else { |
src/link/Elf/Thunk.zig+2| ... | @@ -91,6 +91,7 @@ pub const Index = u32; | ... | @@ -91,6 +91,7 @@ pub const Index = u32; |
| 91 | 91 | ||
| 92 | const aarch64 = struct { | 92 | const aarch64 = struct { |
| 93 | fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { | 93 | fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { |
| 94 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 94 | for (thunk.symbols.keys(), 0..) |ref, i| { | 95 | for (thunk.symbols.keys(), 0..) |ref, i| { |
| 95 | const sym = elf_file.symbol(ref).?; | 96 | const sym = elf_file.symbol(ref).?; |
| 96 | const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size)); | 97 | const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size)); |
| ... | @@ -113,6 +114,7 @@ const aarch64 = struct { | ... | @@ -113,6 +114,7 @@ const aarch64 = struct { |
| 113 | }; | 114 | }; |
| 114 | 115 | ||
| 115 | const assert = std.debug.assert; | 116 | const assert = std.debug.assert; |
| 117 | const dev = @import("../../dev.zig"); | ||
| 116 | const elf = std.elf; | 118 | const elf = std.elf; |
| 117 | const log = std.log.scoped(.link); | 119 | const log = std.log.scoped(.link); |
| 118 | const math = std.math; | 120 | const math = std.math; |
src/link/Elf/ZigObject.zig+14-18| ... | @@ -946,14 +946,11 @@ pub fn getNavVAddr( | ... | @@ -946,14 +946,11 @@ pub fn getNavVAddr( |
| 946 | .r_addend = reloc_info.addend, | 946 | .r_addend = reloc_info.addend, |
| 947 | }, self); | 947 | }, self); |
| 948 | }, | 948 | }, |
| 949 | .debug_output => |debug_output| switch (debug_output) { | 949 | .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{ |
| 950 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 950 | .source_off = @intCast(reloc_info.offset), |
| 951 | .source_off = @intCast(reloc_info.offset), | 951 | .target_sym = @fromBackingInt(@intCast(this_sym_index)), |
| 952 | .target_sym = @fromBackingInt(@intCast(this_sym_index)), | 952 | .target_off = reloc_info.addend, |
| 953 | .target_off = reloc_info.addend, | 953 | }), |
| 954 | }), | ||
| 955 | .none => unreachable, | ||
| 956 | }, | ||
| 957 | } | 954 | } |
| 958 | return @intCast(vaddr); | 955 | return @intCast(vaddr); |
| 959 | } | 956 | } |
| ... | @@ -978,14 +975,11 @@ pub fn getUavVAddr( | ... | @@ -978,14 +975,11 @@ pub fn getUavVAddr( |
| 978 | .r_addend = reloc_info.addend, | 975 | .r_addend = reloc_info.addend, |
| 979 | }, self); | 976 | }, self); |
| 980 | }, | 977 | }, |
| 981 | .debug_output => |debug_output| switch (debug_output) { | 978 | .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{ |
| 982 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 979 | .source_off = @intCast(reloc_info.offset), |
| 983 | .source_off = @intCast(reloc_info.offset), | 980 | .target_sym = @fromBackingInt(@intCast(sym_index)), |
| 984 | .target_sym = @fromBackingInt(@intCast(sym_index)), | 981 | .target_off = reloc_info.addend, |
| 985 | .target_off = reloc_info.addend, | 982 | }), |
| 986 | }), | ||
| 987 | .none => unreachable, | ||
| 988 | }, | ||
| 989 | } | 983 | } |
| 990 | return @intCast(vaddr); | 984 | return @intCast(vaddr); |
| 991 | } | 985 | } |
| ... | @@ -1952,11 +1946,11 @@ pub fn updateExports( | ... | @@ -1952,11 +1946,11 @@ pub fn updateExports( |
| 1952 | } | 1946 | } |
| 1953 | } | 1947 | } |
| 1954 | 1948 | ||
| 1955 | pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void { | 1949 | pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index, line: u32) link.Error!void { |
| 1956 | if (self.dwarf) |*dwarf| { | 1950 | if (self.dwarf) |*dwarf| { |
| 1957 | const comp = dwarf.bin_file.comp; | 1951 | const comp = dwarf.bin_file.comp; |
| 1958 | const diags = &comp.link_diags; | 1952 | const diags = &comp.link_diags; |
| 1959 | dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) { | 1953 | dwarf.updateLineNumber(pt.zcu, ti_id, line) catch |err| switch (err) { |
| 1960 | error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e, | 1954 | error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e, |
| 1961 | else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}), | 1955 | else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}), |
| 1962 | }; | 1956 | }; |
| ... | @@ -2402,6 +2396,7 @@ const TlsTable = std.array_hash_map.Auto(Atom.Index, void); | ... | @@ -2402,6 +2396,7 @@ const TlsTable = std.array_hash_map.Auto(Atom.Index, void); |
| 2402 | 2396 | ||
| 2403 | const x86_64 = struct { | 2397 | const x86_64 = struct { |
| 2404 | fn writeTrampolineCode(source_addr: i64, target_addr: i64, buf: *[max_trampoline_len]u8) ![]u8 { | 2398 | fn writeTrampolineCode(source_addr: i64, target_addr: i64, buf: *[max_trampoline_len]u8) ![]u8 { |
| 2399 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 2405 | const disp = @as(i64, @intCast(target_addr)) - source_addr - 5; | 2400 | const disp = @as(i64, @intCast(target_addr)) - source_addr - 5; |
| 2406 | var bytes = [_]u8{ | 2401 | var bytes = [_]u8{ |
| 2407 | 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp rel32 | 2402 | 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp rel32 |
| ... | @@ -2417,6 +2412,7 @@ const assert = std.debug.assert; | ... | @@ -2417,6 +2412,7 @@ const assert = std.debug.assert; |
| 2417 | const build_options = @import("build_options"); | 2412 | const build_options = @import("build_options"); |
| 2418 | const builtin = @import("builtin"); | 2413 | const builtin = @import("builtin"); |
| 2419 | const codegen = @import("../../codegen.zig"); | 2414 | const codegen = @import("../../codegen.zig"); |
| 2415 | const dev = @import("../../dev.zig"); | ||
| 2420 | const elf = std.elf; | 2416 | const elf = std.elf; |
| 2421 | const link = @import("../../link.zig"); | 2417 | const link = @import("../../link.zig"); |
| 2422 | const log = std.log.scoped(.link); | 2418 | const log = std.log.scoped(.link); |
src/link/Elf/eh_frame.zig+4| ... | @@ -535,6 +535,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { | ... | @@ -535,6 +535,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { |
| 535 | 535 | ||
| 536 | const x86_64 = struct { | 536 | const x86_64 = struct { |
| 537 | fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void { | 537 | fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void { |
| 538 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 538 | const r_type: elf.R_X86_64 = @fromBackingInt(@intCast(rel.r_type())); | 539 | const r_type: elf.R_X86_64 = @fromBackingInt(@intCast(rel.r_type())); |
| 539 | switch (r_type) { | 540 | switch (r_type) { |
| 540 | .NONE => {}, | 541 | .NONE => {}, |
| ... | @@ -549,6 +550,7 @@ const x86_64 = struct { | ... | @@ -549,6 +550,7 @@ const x86_64 = struct { |
| 549 | 550 | ||
| 550 | const aarch64 = struct { | 551 | const aarch64 = struct { |
| 551 | fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void { | 552 | fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void { |
| 553 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 552 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); | 554 | const r_type: elf.R_AARCH64 = @fromBackingInt(@intCast(rel.r_type())); |
| 553 | switch (r_type) { | 555 | switch (r_type) { |
| 554 | .NONE => {}, | 556 | .NONE => {}, |
| ... | @@ -562,6 +564,7 @@ const aarch64 = struct { | ... | @@ -562,6 +564,7 @@ const aarch64 = struct { |
| 562 | 564 | ||
| 563 | const riscv = struct { | 565 | const riscv = struct { |
| 564 | fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void { | 566 | fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void { |
| 567 | dev.checkAny(&.{ .llvm_backend, .riscv64_backend }); | ||
| 565 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); | 568 | const r_type: elf.R_RISCV = @fromBackingInt(@intCast(rel.r_type())); |
| 566 | switch (r_type) { | 569 | switch (r_type) { |
| 567 | .NONE => {}, | 570 | .NONE => {}, |
| ... | @@ -584,6 +587,7 @@ fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void { | ... | @@ -584,6 +587,7 @@ fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void { |
| 584 | 587 | ||
| 585 | const std = @import("std"); | 588 | const std = @import("std"); |
| 586 | const assert = std.debug.assert; | 589 | const assert = std.debug.assert; |
| 590 | const dev = @import("../../dev.zig"); | ||
| 587 | const elf = std.elf; | 591 | const elf = std.elf; |
| 588 | const math = std.math; | 592 | const math = std.math; |
| 589 | const relocs_log = std.log.scoped(.link_relocs); | 593 | const relocs_log = std.log.scoped(.link_relocs); |
src/link/Elf/synthetic_sections.zig+5| ... | @@ -772,6 +772,7 @@ pub const PltSection = struct { | ... | @@ -772,6 +772,7 @@ pub const PltSection = struct { |
| 772 | 772 | ||
| 773 | const x86_64 = struct { | 773 | const x86_64 = struct { |
| 774 | fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | 774 | fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { |
| 775 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 775 | const shdrs = elf_file.sections.items(.shdr); | 776 | const shdrs = elf_file.sections.items(.shdr); |
| 776 | const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr; | 777 | const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr; |
| 777 | const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr; | 778 | const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr; |
| ... | @@ -807,6 +808,7 @@ pub const PltSection = struct { | ... | @@ -807,6 +808,7 @@ pub const PltSection = struct { |
| 807 | 808 | ||
| 808 | const aarch64 = struct { | 809 | const aarch64 = struct { |
| 809 | fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | 810 | fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { |
| 811 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 810 | { | 812 | { |
| 811 | const shdrs = elf_file.sections.items(.shdr); | 813 | const shdrs = elf_file.sections.items(.shdr); |
| 812 | const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr); | 814 | const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr); |
| ... | @@ -949,6 +951,7 @@ pub const PltGotSection = struct { | ... | @@ -949,6 +951,7 @@ pub const PltGotSection = struct { |
| 949 | 951 | ||
| 950 | const x86_64 = struct { | 952 | const x86_64 = struct { |
| 951 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | 953 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { |
| 954 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 952 | for (plt_got.symbols.items) |ref| { | 955 | for (plt_got.symbols.items) |ref| { |
| 953 | const sym = elf_file.symbol(ref).?; | 956 | const sym = elf_file.symbol(ref).?; |
| 954 | const target_addr = sym.gotAddress(elf_file); | 957 | const target_addr = sym.gotAddress(elf_file); |
| ... | @@ -967,6 +970,7 @@ pub const PltGotSection = struct { | ... | @@ -967,6 +970,7 @@ pub const PltGotSection = struct { |
| 967 | 970 | ||
| 968 | const aarch64 = struct { | 971 | const aarch64 = struct { |
| 969 | fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | 972 | fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { |
| 973 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 970 | for (plt_got.symbols.items) |ref| { | 974 | for (plt_got.symbols.items) |ref| { |
| 971 | const sym = elf_file.symbol(ref).?; | 975 | const sym = elf_file.symbol(ref).?; |
| 972 | const target_addr = sym.gotAddress(elf_file); | 976 | const target_addr = sym.gotAddress(elf_file); |
| ... | @@ -1518,6 +1522,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: *std.Io.Writer) !void { | ... | @@ -1518,6 +1522,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: *std.Io.Writer) !void { |
| 1518 | 1522 | ||
| 1519 | const assert = std.debug.assert; | 1523 | const assert = std.debug.assert; |
| 1520 | const builtin = @import("builtin"); | 1524 | const builtin = @import("builtin"); |
| 1525 | const dev = @import("../../dev.zig"); | ||
| 1521 | const elf = std.elf; | 1526 | const elf = std.elf; |
| 1522 | const math = std.math; | 1527 | const math = std.math; |
| 1523 | const mem = std.mem; | 1528 | const mem = std.mem; |
src/link/Elf2.zig+3350-1425| ... | @@ -1,8 +1,5 @@ | ... | @@ -1,8 +1,5 @@ |
| 1 | const Elf = @This(); | 1 | const Elf = @This(); |
| 2 | 2 | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const native_endian = builtin.cpu.arch.endian(); | ||
| 5 | |||
| 6 | const std = @import("std"); | 3 | const std = @import("std"); |
| 7 | const Io = std.Io; | 4 | const Io = std.Io; |
| 8 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| ... | @@ -10,9 +7,10 @@ const log = std.log.scoped(.link); | ... | @@ -10,9 +7,10 @@ const log = std.log.scoped(.link); |
| 10 | 7 | ||
| 11 | const codegen = @import("../codegen.zig"); | 8 | const codegen = @import("../codegen.zig"); |
| 12 | const Compilation = @import("../Compilation.zig"); | 9 | const Compilation = @import("../Compilation.zig"); |
| 10 | const Dwarf = @import("Dwarf2.zig"); | ||
| 13 | const InternPool = @import("../InternPool.zig"); | 11 | const InternPool = @import("../InternPool.zig"); |
| 14 | const link = @import("../link.zig"); | 12 | const link = @import("../link.zig"); |
| 15 | const MappedFile = @import("MappedFile.zig"); | 13 | const MappedFile = link.MappedFile; |
| 16 | const target_util = @import("../target.zig"); | 14 | const target_util = @import("../target.zig"); |
| 17 | const tracy = @import("../tracy.zig"); | 15 | const tracy = @import("../tracy.zig"); |
| 18 | const Type = @import("../Type.zig"); | 16 | const Type = @import("../Type.zig"); |
| ... | @@ -23,7 +21,18 @@ const Alignment = MappedFile.Alignment; | ... | @@ -23,7 +21,18 @@ const Alignment = MappedFile.Alignment; |
| 23 | base: link.File, | 21 | base: link.File, |
| 24 | options: link.File.OpenOptions, | 22 | options: link.File.OpenOptions, |
| 25 | mf: MappedFile, | 23 | mf: MappedFile, |
| 26 | ni: Node.Known, | 24 | ni: struct { |
| 25 | elf: MappedFile.Node.Index, | ||
| 26 | ehdr: MappedFile.Node.Index, | ||
| 27 | shdr: MappedFile.Node.Index, | ||
| 28 | rodata: MappedFile.Node.Index, | ||
| 29 | phdr: MappedFile.Node.Index, | ||
| 30 | text: MappedFile.Node.Index, | ||
| 31 | data: MappedFile.Node.Index, | ||
| 32 | data_rel_ro: MappedFile.Node.Index, | ||
| 33 | tls: MappedFile.Node.Index.Optional, | ||
| 34 | gnu_eh_frame: MappedFile.Node.Index.Optional, | ||
| 35 | }, | ||
| 27 | archive: ?Archive, | 36 | archive: ?Archive, |
| 28 | nodes: std.MultiArrayList(Node), | 37 | nodes: std.MultiArrayList(Node), |
| 29 | /// Does not contain an item for `SHN_UNDEF`. | 38 | /// Does not contain an item for `SHN_UNDEF`. |
| ... | @@ -43,6 +52,16 @@ shndx: struct { | ... | @@ -43,6 +52,16 @@ shndx: struct { |
| 43 | tdata: Section.Index, | 52 | tdata: Section.Index, |
| 44 | rela_dyn: Section.Index, | 53 | rela_dyn: Section.Index, |
| 45 | rela_plt: Section.Index, | 54 | rela_plt: Section.Index, |
| 55 | debug_abbrev: Section.Index, | ||
| 56 | eh_frame_hdr: Section.Index, | ||
| 57 | eh_frame: Section.Index, | ||
| 58 | debug_frame: Section.Index, | ||
| 59 | debug_info: Section.Index, | ||
| 60 | debug_line: Section.Index, | ||
| 61 | debug_line_str: Section.Index, | ||
| 62 | debug_rnglists: Section.Index, | ||
| 63 | debug_str: Section.Index, | ||
| 64 | debug_str_offsets: Section.Index, | ||
| 46 | // These sections are created only as needed, and are initially `.UNDEF`. | 65 | // These sections are created only as needed, and are initially `.UNDEF`. |
| 47 | init_array: Section.Index, | 66 | init_array: Section.Index, |
| 48 | fini_array: Section.Index, | 67 | fini_array: Section.Index, |
| ... | @@ -123,6 +142,8 @@ got: std.array_hash_map.Auto(GotKey, Section.RelaIndex.Optional), | ... | @@ -123,6 +142,8 @@ got: std.array_hash_map.Auto(GotKey, Section.RelaIndex.Optional), |
| 123 | plt: std.array_hash_map.Auto(String(.strtab), void), | 142 | plt: std.array_hash_map.Auto(String(.strtab), void), |
| 124 | /// The `.plt` section contains zero or more symbol relocations starting at this index. | 143 | /// The `.plt` section contains zero or more symbol relocations starting at this index. |
| 125 | plt_first_symbol_reloc: SymbolReloc.Index, | 144 | plt_first_symbol_reloc: SymbolReloc.Index, |
| 145 | /// The `.eh_frame_hdr` section contains zero or more symbol relocations starting at this index. | ||
| 146 | eh_frame_hdr_first_symbol_reloc: SymbolReloc.Index, | ||
| 126 | 147 | ||
| 127 | needed: std.array_hash_map.Auto(String(.dynstr), void), | 148 | needed: std.array_hash_map.Auto(String(.dynstr), void), |
| 128 | inputs: std.ArrayList(struct { | 149 | inputs: std.ArrayList(struct { |
| ... | @@ -175,6 +196,7 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { | ... | @@ -175,6 +196,7 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { |
| 175 | }), | 196 | }), |
| 176 | pending_uavs: std.ArrayList(Node.UavMapIndex), | 197 | pending_uavs: std.ArrayList(Node.UavMapIndex), |
| 177 | symbol_relocs: std.ArrayList(SymbolReloc), | 198 | symbol_relocs: std.ArrayList(SymbolReloc), |
| 199 | node_relocs: std.ArrayList(NodeReloc), | ||
| 178 | got_relocs: std.ArrayList(GotReloc), | 200 | got_relocs: std.ArrayList(GotReloc), |
| 179 | /// Set of relocations which must be re-applied if the size of the TLS segment changes. | 201 | /// Set of relocations which must be re-applied if the size of the TLS segment changes. |
| 180 | tls_size_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), | 202 | tls_size_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), |
| ... | @@ -191,16 +213,25 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), | ... | @@ -191,16 +213,25 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), |
| 191 | /// section in `flush` only when it is actually necessary. See also `nodeWantsDsoRelocation`. | 213 | /// section in `flush` only when it is actually necessary. See also `nodeWantsDsoRelocation`. |
| 192 | textrel_count: u32, | 214 | textrel_count: u32, |
| 193 | 215 | ||
| 216 | dwarf: Dwarf, | ||
| 217 | dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, dwarf_relocs.Shared), | ||
| 218 | dwarf_units: []dwarf_relocs.Unit, | ||
| 219 | dwarf_consts: std.array_hash_map.Auto(link.ConstPool.Index, dwarf_relocs.Const), | ||
| 220 | dwarf_globals: std.ArrayList(dwarf_relocs.Global), | ||
| 221 | dwarf_funcs: std.ArrayList(dwarf_relocs.Func), | ||
| 222 | dwarf_decls: std.array_hash_map.Auto(Dwarf.Decl.Index, dwarf_relocs.Decl), | ||
| 223 | |||
| 194 | overflowed_reloc_count: u32, | 224 | overflowed_reloc_count: u32, |
| 195 | misaligned_reloc_count: u32, | 225 | misaligned_reloc_count: u32, |
| 196 | 226 | ||
| 197 | const_prog_node: std.Progress.Node, | 227 | const_prog_node: std.Progress.Node, |
| 198 | synth_prog_node: std.Progress.Node, | ||
| 199 | input_prog_node: std.Progress.Node, | 228 | input_prog_node: std.Progress.Node, |
| 200 | 229 | ||
| 201 | const Error = link.Error || error{MappedFileIo}; | 230 | const Error = link.Error || error{MappedFileIo}; |
| 202 | 231 | ||
| 203 | const Node = union(enum) { | 232 | const Node = union(enum) { |
| 233 | deleted, | ||
| 234 | |||
| 204 | /// Only used when emitting a static library. | 235 | /// Only used when emitting a static library. |
| 205 | /// | 236 | /// |
| 206 | /// Contains a header node which is an `.archive_header`. | 237 | /// Contains a header node which is an `.archive_header`. |
| ... | @@ -232,8 +263,9 @@ const Node = union(enum) { | ... | @@ -232,8 +263,9 @@ const Node = union(enum) { |
| 232 | ehdr, | 263 | ehdr, |
| 233 | shdr, | 264 | shdr, |
| 234 | segment: u32, | 265 | segment: u32, |
| 235 | /// The section '.plt' may contain relocations via `elf.plt_first_symbol_reloc`. | ||
| 236 | section: Section.Index, | 266 | section: Section.Index, |
| 267 | /// The section '.plt' may contain relocations via `elf.plt_first_symbol_reloc`. | ||
| 268 | section_manual_size: Section.Index, | ||
| 237 | /// May contain relocations. | 269 | /// May contain relocations. |
| 238 | input_section: InputSection.Index, | 270 | input_section: InputSection.Index, |
| 239 | /// Value is the name of a global which has an entry in `elf.copied_globals`, so, a global for | 271 | /// Value is the name of a global which has an entry in `elf.copied_globals`, so, a global for |
| ... | @@ -253,6 +285,25 @@ const Node = union(enum) { | ... | @@ -253,6 +285,25 @@ const Node = union(enum) { |
| 253 | /// May contain relocations. | 285 | /// May contain relocations. |
| 254 | lazy_const_data: LazyMapRef.Index(.const_data), | 286 | lazy_const_data: LazyMapRef.Index(.const_data), |
| 255 | 287 | ||
| 288 | debug_shared: Dwarf.SharedSection, | ||
| 289 | eh_frame_footer, | ||
| 290 | unit_padding, | ||
| 291 | unit_frame: Dwarf.Unit.Index, | ||
| 292 | unit_frame_cie: Dwarf.Unit.Index, | ||
| 293 | unit_debug_info: Dwarf.Unit.Index, | ||
| 294 | unit_debug_info_header: Dwarf.Unit.Index, | ||
| 295 | unit_debug_info_footer: Dwarf.Unit.Index, | ||
| 296 | unit_debug_line: Dwarf.Unit.Index, | ||
| 297 | unit_debug_line_header: Dwarf.Unit.Index, | ||
| 298 | unit_debug_rnglists: Dwarf.Unit.Index, | ||
| 299 | |||
| 300 | const_debug_info: link.ConstPool.Index, | ||
| 301 | global_debug_info: Dwarf.Global.Index, | ||
| 302 | func_frame_fde: Dwarf.Func.Index, | ||
| 303 | func_debug_info: Dwarf.Func.Index, | ||
| 304 | func_debug_line: Dwarf.Func.Index, | ||
| 305 | decl_debug_info: Dwarf.Decl.Index, | ||
| 306 | |||
| 256 | pub const InputIndex = enum(u32) { | 307 | pub const InputIndex = enum(u32) { |
| 257 | _, | 308 | _, |
| 258 | 309 | ||
| ... | @@ -288,7 +339,7 @@ const Node = union(enum) { | ... | @@ -288,7 +339,7 @@ const Node = union(enum) { |
| 288 | pub const NavMapIndex = enum(u32) { | 339 | pub const NavMapIndex = enum(u32) { |
| 289 | _, | 340 | _, |
| 290 | 341 | ||
| 291 | pub fn navIndex(nmi: NavMapIndex, elf: *const Elf) InternPool.Nav.Index { | 342 | pub fn nav(nmi: NavMapIndex, elf: *const Elf) InternPool.Nav.Index { |
| 292 | return elf.navs.keys()[@backingInt(nmi)]; | 343 | return elf.navs.keys()[@backingInt(nmi)]; |
| 293 | } | 344 | } |
| 294 | 345 | ||
| ... | @@ -363,18 +414,6 @@ const Node = union(enum) { | ... | @@ -363,18 +414,6 @@ const Node = union(enum) { |
| 363 | } | 414 | } |
| 364 | }; | 415 | }; |
| 365 | 416 | ||
| 366 | pub const Known = struct { | ||
| 367 | elf: MappedFile.Node.Index, | ||
| 368 | ehdr: MappedFile.Node.Index, | ||
| 369 | shdr: MappedFile.Node.Index, | ||
| 370 | rodata: MappedFile.Node.Index, | ||
| 371 | phdr: MappedFile.Node.Index, | ||
| 372 | text: MappedFile.Node.Index, | ||
| 373 | data: MappedFile.Node.Index, | ||
| 374 | data_rel_ro: MappedFile.Node.Index, | ||
| 375 | tls: MappedFile.Node.Index.Optional, | ||
| 376 | }; | ||
| 377 | |||
| 378 | comptime { | 417 | comptime { |
| 379 | if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Node) == 8); | 418 | if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Node) == 8); |
| 380 | } | 419 | } |
| ... | @@ -439,7 +478,7 @@ const Section = struct { | ... | @@ -439,7 +478,7 @@ const Section = struct { |
| 439 | ni: MappedFile.Node.Index, | 478 | ni: MappedFile.Node.Index, |
| 440 | /// A symbol which is exactly at the start of this section. | 479 | /// A symbol which is exactly at the start of this section. |
| 441 | /// | 480 | /// |
| 442 | /// If the section does not have flag `std.elf.SHF.ALLOC`, this is `.null`. | 481 | /// When not emitting a relocatable, or for special section types, this is `.null`. |
| 443 | lsi: Symbol.LocalIndex, | 482 | lsi: Symbol.LocalIndex, |
| 444 | rela: union { | 483 | rela: union { |
| 445 | /// This field is active if and only if this section is *not* a `SHT_RELA` section. | 484 | /// This field is active if and only if this section is *not* a `SHT_RELA` section. |
| ... | @@ -526,8 +565,8 @@ const Section = struct { | ... | @@ -526,8 +565,8 @@ const Section = struct { |
| 526 | std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(reserve(sec)), | 565 | std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(reserve(sec)), |
| 527 | }; | 566 | }; |
| 528 | } | 567 | } |
| 529 | pub fn toSection(s: Index) ?std.elf.Section { | 568 | pub fn toSection(shndx: Index) ?std.elf.Section { |
| 530 | return switch (@backingInt(s)) { | 569 | return switch (@backingInt(shndx)) { |
| 531 | std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => |sec| @intCast(sec), | 570 | std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => |sec| @intCast(sec), |
| 532 | std.elf.SHN_LORESERVE...reserve(std.elf.SHN_LORESERVE) - 1 => null, | 571 | std.elf.SHN_LORESERVE...reserve(std.elf.SHN_LORESERVE) - 1 => null, |
| 533 | reserve(std.elf.SHN_LORESERVE)...reserve(std.elf.SHN_HIRESERVE) => |sec| @intCast( | 572 | reserve(std.elf.SHN_LORESERVE)...reserve(std.elf.SHN_HIRESERVE) => |sec| @intCast( |
| ... | @@ -536,28 +575,40 @@ const Section = struct { | ... | @@ -536,28 +575,40 @@ const Section = struct { |
| 536 | }; | 575 | }; |
| 537 | } | 576 | } |
| 538 | 577 | ||
| 539 | fn get(s: Index, elf: *Elf) *Section { | 578 | fn get(shndx: Index, elf: *Elf) *Section { |
| 540 | return &elf.shdrs.items[@backingInt(s) - 1]; // overflow means you tried to get the `.UNDEF` section | 579 | return &elf.shdrs.items[@backingInt(shndx) - 1]; // overflow means you tried to get the `.UNDEF` section |
| 541 | } | 580 | } |
| 542 | 581 | ||
| 543 | fn name(s: Index, elf: *Elf) String(.shstrtab) { | 582 | fn name(shndx: Index, elf: *Elf) String(.shstrtab) { |
| 544 | return switch (elf.shdrPtr(s)) { | 583 | return switch (elf.shdrPtr(shndx)) { |
| 545 | inline else => |shdr| @fromBackingInt(elf.targetLoad(&shdr.name)), | 584 | inline else => |shdr| @fromBackingInt(elf.targetLoad(&shdr.name)), |
| 546 | }; | 585 | }; |
| 547 | } | 586 | } |
| 548 | 587 | ||
| 549 | fn vaddr(s: Index, elf: *Elf) u64 { | 588 | fn vaddr(shndx: Index, elf: *Elf) u64 { |
| 550 | return switch (elf.shdrPtr(s)) { | 589 | return switch (elf.shdrPtr(shndx)) { |
| 551 | inline else => |shdr| elf.targetLoad(&shdr.addr), | 590 | inline else => |shdr| elf.targetLoad(&shdr.addr), |
| 552 | }; | 591 | }; |
| 553 | } | 592 | } |
| 554 | 593 | ||
| 555 | fn size(s: Index, elf: *Elf) u64 { | 594 | fn size(shndx: Index, elf: *Elf) u64 { |
| 556 | return switch (elf.shdrPtr(s)) { | 595 | return switch (elf.shdrPtr(shndx)) { |
| 557 | inline else => |shdr| elf.targetLoad(&shdr.size), | 596 | inline else => |shdr| elf.targetLoad(&shdr.size), |
| 558 | }; | 597 | }; |
| 559 | } | 598 | } |
| 560 | 599 | ||
| 600 | fn setSize(shndx: Index, elf: *Elf, new_size: u64) void { | ||
| 601 | return switch (elf.shdrPtr(shndx)) { | ||
| 602 | inline else => |shdr| { | ||
| 603 | elf.targetStore(&shdr.type, switch (new_size) { | ||
| 604 | 0 => .NULL, | ||
| 605 | else => .PROGBITS, | ||
| 606 | }); | ||
| 607 | elf.targetStore(&shdr.size, @intCast(new_size)); | ||
| 608 | }, | ||
| 609 | }; | ||
| 610 | } | ||
| 611 | |||
| 561 | fn flags(s: Index, elf: *Elf) std.elf.SHF { | 612 | fn flags(s: Index, elf: *Elf) std.elf.SHF { |
| 562 | return switch (elf.shdrPtr(s)) { | 613 | return switch (elf.shdrPtr(s)) { |
| 563 | inline else => |shdr| elf.targetLoad(&shdr.flags).shf, | 614 | inline else => |shdr| elf.targetLoad(&shdr.flags).shf, |
| ... | @@ -582,7 +633,7 @@ const Section = struct { | ... | @@ -582,7 +633,7 @@ const Section = struct { |
| 582 | } | 633 | } |
| 583 | const ni = shndx.get(elf).ni; | 634 | const ni = shndx.get(elf).ni; |
| 584 | if (min_align.compare(.gt, ni.alignment(&elf.mf))) { | 635 | if (min_align.compare(.gt, ni.alignment(&elf.mf))) { |
| 585 | try ni.realign(&elf.mf, elf.base.comp.gpa, min_align); | 636 | try ni.realign(elf.base.comp.gpa, &elf.mf, min_align); |
| 586 | } | 637 | } |
| 587 | switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) { | 638 | switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) { |
| 588 | .elf => {}, | 639 | .elf => {}, |
| ... | @@ -615,7 +666,7 @@ const Section = struct { | ... | @@ -615,7 +666,7 @@ const Section = struct { |
| 615 | break :need_size cur_size + need_additional * ent_size; | 666 | break :need_size cur_size + need_additional * ent_size; |
| 616 | }, | 667 | }, |
| 617 | }; | 668 | }; |
| 618 | try node.ensureMinimumSize(&elf.mf, elf.base.comp.gpa, need_size); | 669 | try node.ensureMinimumSize(elf.base.comp.gpa, &elf.mf, need_size); |
| 619 | } | 670 | } |
| 620 | 671 | ||
| 621 | /// Asserts that `rela_shndx` is a `SHT_RELA` section and deletes the `ElfN.Rela` entry at | 672 | /// Asserts that `rela_shndx` is a `SHT_RELA` section and deletes the `ElfN.Rela` entry at |
| ... | @@ -649,7 +700,7 @@ const Section = struct { | ... | @@ -649,7 +700,7 @@ const Section = struct { |
| 649 | }, | 700 | }, |
| 650 | .addend = @intCast(old_free_len + 1), // list length | 701 | .addend = @intCast(old_free_len + 1), // list length |
| 651 | }; | 702 | }; |
| 652 | if (elf.targetEndian() != native_endian) { | 703 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 653 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(index)]); | 704 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(index)]); |
| 654 | } | 705 | } |
| 655 | }, | 706 | }, |
| ... | @@ -708,7 +759,7 @@ const Section = struct { | ... | @@ -708,7 +759,7 @@ const Section = struct { |
| 708 | }, | 759 | }, |
| 709 | .addend = @intCast(opts.addend), | 760 | .addend = @intCast(opts.addend), |
| 710 | }; | 761 | }; |
| 711 | if (elf.targetEndian() != native_endian) { | 762 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 712 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(new_index)]); | 763 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(new_index)]); |
| 713 | } | 764 | } |
| 714 | return new_index; | 765 | return new_index; |
| ... | @@ -786,10 +837,10 @@ const Section = struct { | ... | @@ -786,10 +837,10 @@ const Section = struct { |
| 786 | } | 837 | } |
| 787 | } | 838 | } |
| 788 | 839 | ||
| 789 | /// Asserts that `rela_shndx` is a `SHT_RELA` section, and asserts that `index` refers to an | 840 | /// Asserts that `rela_shndx` is a `SHT_RELA` section and updates the `addend` field of the |
| 790 | /// `R_*_RELATIVE` relocation inside of it; then, updates that relocation's addend (which is | 841 | /// `ElfN.Rela` entry at the given index. Asserts that `index` is not in the free-list (i.e. |
| 791 | /// an address in this DSO without the runtime load offset applied) to the given value. | 842 | /// it is not deleted). |
| 792 | fn relaSetRelativeOffset(rela_shndx: Index, elf: *Elf, index: RelaIndex, new_addend: u64) void { | 843 | fn relaSetAddend(rela_shndx: Index, elf: *Elf, index: RelaIndex, new_addend: u64) void { |
| 793 | switch (elf.shdrPtr(rela_shndx)) { | 844 | switch (elf.shdrPtr(rela_shndx)) { |
| 794 | inline else => |shdr, class| { | 845 | inline else => |shdr, class| { |
| 795 | assert(elf.targetLoad(&shdr.type) == .RELA); | 846 | assert(elf.targetLoad(&shdr.type) == .RELA); |
| ... | @@ -807,44 +858,322 @@ const Section = struct { | ... | @@ -807,44 +858,322 @@ const Section = struct { |
| 807 | }, | 858 | }, |
| 808 | } | 859 | } |
| 809 | } | 860 | } |
| 861 | |||
| 862 | fn debugFrameFormat(shndx: Index, elf: *Elf) ?Dwarf.Frame.Format { | ||
| 863 | if (shndx == elf.shndx.eh_frame) return .eh_frame; | ||
| 864 | if (shndx == elf.shndx.debug_frame) return .debug_frame; | ||
| 865 | return null; | ||
| 866 | } | ||
| 810 | }; | 867 | }; |
| 811 | }; | 868 | }; |
| 869 | fn debugFrameFooterSize(elf: *Elf, frame_format: Dwarf.Frame.Format) usize { | ||
| 870 | return switch (frame_format) { | ||
| 871 | .eh_frame => switch (elf.ehdrType()) { | ||
| 872 | .REL => 0, | ||
| 873 | .EXEC, .DYN => 4, | ||
| 874 | }, | ||
| 875 | .debug_frame => 0, | ||
| 876 | }; | ||
| 877 | } | ||
| 812 | 878 | ||
| 813 | /// Identifies a single entry in the GOT. | 879 | const dwarf_relocs = struct { |
| 814 | const GotKey = union(enum) { | 880 | const Shared = struct { |
| 815 | /// The entry is a reserved word, initialized to zero. `initHeaders` will add as many of these | 881 | first_target_reloc: NodeReloc.Index, |
| 816 | /// as the target machine ABI requires. | 882 | }; |
| 817 | /// | 883 | const Unit = struct { |
| 818 | /// This `u32` value exists to allow reserving multiple words with distinct keys. | 884 | frame_cie_first_target_reloc: NodeReloc.Index, |
| 819 | reserved: u32, | 885 | debug_info_header_first_target_reloc: NodeReloc.Index, |
| 886 | debug_info_header_first_node_reloc: NodeReloc.Index, | ||
| 887 | debug_line_header_first_target_reloc: NodeReloc.Index, | ||
| 888 | debug_line_header_first_node_reloc: NodeReloc.Index, | ||
| 889 | debug_rnglists_first_target_reloc: NodeReloc.Index, | ||
| 890 | debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), | ||
| 891 | }; | ||
| 892 | const Const = struct { | ||
| 893 | debug_info_first_target_reloc: NodeReloc.Index, | ||
| 894 | debug_info_first_symbol_reloc: SymbolReloc.Index, | ||
| 895 | debug_info_first_node_reloc: NodeReloc.Index, | ||
| 896 | }; | ||
| 897 | const Global = struct { | ||
| 898 | debug_info_first_target_reloc: NodeReloc.Index, | ||
| 899 | debug_info_first_symbol_reloc: SymbolReloc.Index, | ||
| 900 | debug_info_first_node_reloc: NodeReloc.Index, | ||
| 901 | }; | ||
| 902 | const Func = struct { | ||
| 903 | frame_fde_first_symbol_reloc: SymbolReloc.Index, | ||
| 904 | frame_fde_first_node_reloc: NodeReloc.Index, | ||
| 905 | debug_info_first_target_reloc: NodeReloc.Index, | ||
| 906 | debug_info_first_symbol_reloc: SymbolReloc.Index, | ||
| 907 | debug_info_first_node_reloc: NodeReloc.Index, | ||
| 908 | debug_line_first_symbol_reloc: SymbolReloc.Index, | ||
| 909 | debug_line_first_node_reloc: NodeReloc.Index, | ||
| 910 | }; | ||
| 911 | const Decl = struct { | ||
| 912 | debug_info_first_target_reloc: NodeReloc.Index, | ||
| 913 | debug_info_first_node_reloc: NodeReloc.Index, | ||
| 914 | }; | ||
| 915 | }; | ||
| 820 | 916 | ||
| 821 | /// Value is the address of the given symbol. | 917 | pub const MachineRelocType = union { |
| 822 | symbol: Symbol.Id, | 918 | AARCH64: std.elf.R_AARCH64, |
| 919 | LARCH: std.elf.R_LARCH, | ||
| 920 | PPC64: std.elf.R_PPC64, | ||
| 921 | RISCV: std.elf.R_RISCV, | ||
| 922 | SPARC: std.elf.R_SPARC, | ||
| 923 | X86_64: std.elf.R_X86_64, | ||
| 823 | 924 | ||
| 824 | /// Value is the signed offset of the given symbol from the TLS pointer. | 925 | pub const Format = struct { |
| 825 | tpoff: Symbol.Id, | 926 | rt: MachineRelocType, |
| 927 | elf: *const Elf, | ||
| 826 | 928 | ||
| 827 | /// Value is the TLS module ID of the DSO we are creating. | 929 | pub fn format(f: Format, w: *Io.Writer) Io.Writer.Error!void { |
| 828 | /// | 930 | switch (f.elf.ehdrMachine()) { |
| 829 | /// Used for the first of the two GOT entries generated by a TLSLD relocation. | 931 | .AARCH64 => try w.print("R_AARCH64_{t}", .{f.rt.AARCH64}), |
| 830 | tlsld0, | 932 | .LOONGARCH => try w.print("R_LARCH_{t}", .{f.rt.LARCH}), |
| 831 | /// Value is always 0. | 933 | .PPC64 => try w.print("R_PPC64_{t}", .{f.rt.PPC64}), |
| 832 | /// | 934 | .RISCV => try w.print("R_RISCV_{t}", .{f.rt.RISCV}), |
| 833 | /// Used for the second of the two GOT entries generated by a TLSLD relocation. | 935 | .SPARCV9 => try w.print("R_SPARC_{t}", .{f.rt.SPARC}), |
| 834 | tlsld1, | 936 | .X86_64 => try w.print("R_X86_64_{t}", .{f.rt.X86_64}), |
| 937 | } | ||
| 938 | } | ||
| 939 | }; | ||
| 835 | 940 | ||
| 836 | /// Value is the TLS module ID for the given STT_TLS symbol. | 941 | pub fn fmt(rt: MachineRelocType, elf: *const Elf) Format { |
| 837 | /// | 942 | return .{ .rt = rt, .elf = elf }; |
| 838 | /// Used for the first of the two GOT entries generated by a TLSGD relocation. | 943 | } |
| 839 | tlsgd0: Symbol.Id, | 944 | |
| 840 | /// Value is the offset of the given STT_TLS symbol from the base of the per-module TLS area. | 945 | pub fn none(elf: *const Elf) MachineRelocType { |
| 841 | /// | 946 | return switch (elf.ehdrMachine()) { |
| 842 | /// Used for the second of the two GOT entries generated by a TLSGD relocation. | 947 | .AARCH64 => .{ .AARCH64 = .NONE }, |
| 843 | tlsgd1: Symbol.Id, | 948 | .LOONGARCH => .{ .LARCH = .NONE }, |
| 949 | .PPC64 => .{ .PPC64 = .NONE }, | ||
| 950 | .RISCV => .{ .RISCV = .NONE }, | ||
| 951 | .SPARCV9 => .{ .SPARC = .NONE }, | ||
| 952 | .X86_64 => .{ .X86_64 = .NONE }, | ||
| 953 | }; | ||
| 954 | } | ||
| 955 | pub fn copy(elf: *const Elf) MachineRelocType { | ||
| 956 | return switch (elf.ehdrMachine()) { | ||
| 957 | .AARCH64 => .{ .AARCH64 = .COPY }, | ||
| 958 | .LOONGARCH => .{ .LARCH = .COPY }, | ||
| 959 | .PPC64 => .{ .PPC64 = .COPY }, | ||
| 960 | .RISCV => .{ .RISCV = .COPY }, | ||
| 961 | .SPARCV9 => .{ .SPARC = .COPY }, | ||
| 962 | .X86_64 => .{ .X86_64 = .COPY }, | ||
| 963 | }; | ||
| 964 | } | ||
| 965 | pub fn relative(elf: *const Elf) MachineRelocType { | ||
| 966 | return switch (elf.ehdrMachine()) { | ||
| 967 | .AARCH64 => .{ .AARCH64 = .RELATIVE }, | ||
| 968 | .LOONGARCH => .{ .LARCH = .RELATIVE }, | ||
| 969 | .PPC64 => .{ .PPC64 = .RELATIVE }, | ||
| 970 | .RISCV => .{ .RISCV = .RELATIVE }, | ||
| 971 | .SPARCV9 => .{ .SPARC = .RELATIVE }, | ||
| 972 | .X86_64 => .{ .X86_64 = .RELATIVE }, | ||
| 973 | }; | ||
| 974 | } | ||
| 975 | pub fn jumpSlot(elf: *const Elf) MachineRelocType { | ||
| 976 | return switch (elf.ehdrMachine()) { | ||
| 977 | .AARCH64 => .{ .AARCH64 = .JUMP_SLOT }, | ||
| 978 | .LOONGARCH => .{ .LARCH = .JUMP_SLOT }, | ||
| 979 | .PPC64 => .{ .PPC64 = .JMP_SLOT }, | ||
| 980 | .RISCV => .{ .RISCV = .JUMP_SLOT }, | ||
| 981 | .SPARCV9 => .{ .SPARC = .JMP_SLOT }, | ||
| 982 | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, | ||
| 983 | }; | ||
| 984 | } | ||
| 985 | pub fn globDat(elf: *const Elf) MachineRelocType { | ||
| 986 | return switch (elf.ehdrMachine()) { | ||
| 987 | .AARCH64 => .{ .AARCH64 = .GLOB_DAT }, | ||
| 988 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { | ||
| 989 | .NONE, _ => unreachable, | ||
| 990 | .@"32" => .@"32", | ||
| 991 | .@"64" => .@"64", | ||
| 992 | } }, | ||
| 993 | .PPC64 => .{ .PPC64 = .GLOB_DAT }, | ||
| 994 | .RISCV => .{ .RISCV = switch (elf.identClass()) { | ||
| 995 | .NONE, _ => unreachable, | ||
| 996 | .@"32" => .@"32", | ||
| 997 | .@"64" => .@"64", | ||
| 998 | } }, | ||
| 999 | .SPARCV9 => .{ .SPARC = .GLOB_DAT }, | ||
| 1000 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, | ||
| 1001 | }; | ||
| 1002 | } | ||
| 1003 | pub fn dtpMod(elf: *const Elf) MachineRelocType { | ||
| 1004 | return switch (elf.ehdrMachine()) { | ||
| 1005 | .AARCH64 => .{ .AARCH64 = switch (elf.identClass()) { | ||
| 1006 | .NONE, _ => unreachable, | ||
| 1007 | .@"32" => .P32_TLS_DTPMOD, | ||
| 1008 | .@"64" => .TLS_DTPMOD, | ||
| 1009 | } }, | ||
| 1010 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { | ||
| 1011 | .NONE, _ => unreachable, | ||
| 1012 | .@"32" => .TLS_DTPMOD32, | ||
| 1013 | .@"64" => .TLS_DTPMOD64, | ||
| 1014 | } }, | ||
| 1015 | .PPC64 => .{ .PPC64 = .DTPMOD64 }, | ||
| 1016 | .RISCV => .{ .RISCV = switch (elf.identClass()) { | ||
| 1017 | .NONE, _ => unreachable, | ||
| 1018 | .@"32" => .TLS_DTPMOD32, | ||
| 1019 | .@"64" => .TLS_DTPMOD64, | ||
| 1020 | } }, | ||
| 1021 | .SPARCV9 => .{ .SPARC = switch (elf.identClass()) { | ||
| 1022 | .NONE, _ => unreachable, | ||
| 1023 | .@"32" => .TLS_DTPMOD32, | ||
| 1024 | .@"64" => .TLS_DTPMOD64, | ||
| 1025 | } }, | ||
| 1026 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, | ||
| 1027 | }; | ||
| 1028 | } | ||
| 1029 | pub fn dtpOff(elf: *const Elf) MachineRelocType { | ||
| 1030 | return switch (elf.ehdrMachine()) { | ||
| 1031 | .AARCH64 => .{ .AARCH64 = switch (elf.identClass()) { | ||
| 1032 | .NONE, _ => unreachable, | ||
| 1033 | .@"32" => .P32_TLS_DTPREL, | ||
| 1034 | .@"64" => .TLS_DTPREL, | ||
| 1035 | } }, | ||
| 1036 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { | ||
| 1037 | .NONE, _ => unreachable, | ||
| 1038 | .@"32" => .TLS_DTPREL32, | ||
| 1039 | .@"64" => .TLS_DTPREL64, | ||
| 1040 | } }, | ||
| 1041 | .PPC64 => .{ .PPC64 = .DTPREL64 }, | ||
| 1042 | .RISCV => .{ .RISCV = switch (elf.identClass()) { | ||
| 1043 | .NONE, _ => unreachable, | ||
| 1044 | .@"32" => .TLS_DTPREL32, | ||
| 1045 | .@"64" => .TLS_DTPREL64, | ||
| 1046 | } }, | ||
| 1047 | .SPARCV9 => .{ .SPARC = switch (elf.identClass()) { | ||
| 1048 | .NONE, _ => unreachable, | ||
| 1049 | .@"32" => .TLS_DTPOFF32, | ||
| 1050 | .@"64" => .TLS_DTPOFF64, | ||
| 1051 | } }, | ||
| 1052 | .X86_64 => .{ .X86_64 = .DTPOFF64 }, | ||
| 1053 | }; | ||
| 1054 | } | ||
| 1055 | pub fn tpOff(elf: *const Elf) MachineRelocType { | ||
| 1056 | return switch (elf.ehdrMachine()) { | ||
| 1057 | .AARCH64 => .{ .AARCH64 = switch (elf.identClass()) { | ||
| 1058 | .NONE, _ => unreachable, | ||
| 1059 | .@"32" => .P32_TLS_TPREL, | ||
| 1060 | .@"64" => .TLS_TPREL, | ||
| 1061 | } }, | ||
| 1062 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { | ||
| 1063 | .NONE, _ => unreachable, | ||
| 1064 | .@"32" => .TLS_TPREL32, | ||
| 1065 | .@"64" => .TLS_TPREL64, | ||
| 1066 | } }, | ||
| 1067 | .PPC64 => .{ .PPC64 = .TPREL64 }, | ||
| 1068 | .RISCV => .{ .RISCV = switch (elf.identClass()) { | ||
| 1069 | .NONE, _ => unreachable, | ||
| 1070 | .@"32" => .TLS_TPREL32, | ||
| 1071 | .@"64" => .TLS_TPREL64, | ||
| 1072 | } }, | ||
| 1073 | .SPARCV9 => .{ .SPARC = switch (elf.identClass()) { | ||
| 1074 | .NONE, _ => unreachable, | ||
| 1075 | .@"32" => .TLS_TPOFF32, | ||
| 1076 | .@"64" => .TLS_TPOFF64, | ||
| 1077 | } }, | ||
| 1078 | .X86_64 => .{ .X86_64 = .TPOFF64 }, | ||
| 1079 | }; | ||
| 1080 | } | ||
| 1081 | pub fn absAddr(elf: *const Elf) MachineRelocType { | ||
| 1082 | return switch (elf.identClass()) { | ||
| 1083 | .NONE, _ => unreachable, | ||
| 1084 | .@"32" => .abs32(elf), | ||
| 1085 | .@"64" => .abs64(elf), | ||
| 1086 | }; | ||
| 1087 | } | ||
| 1088 | pub fn abs32(elf: *const Elf) MachineRelocType { | ||
| 1089 | return switch (elf.ehdrMachine()) { | ||
| 1090 | .AARCH64 => .{ .AARCH64 = .P32_ABS32 }, | ||
| 1091 | .LOONGARCH => .{ .LARCH = .@"32" }, | ||
| 1092 | .PPC64 => .{ .PPC64 = .ADDR32 }, | ||
| 1093 | .RISCV => .{ .RISCV = .@"32" }, | ||
| 1094 | .SPARCV9 => .{ .SPARC = .@"32" }, | ||
| 1095 | .X86_64 => .{ .X86_64 = .@"32" }, | ||
| 1096 | }; | ||
| 1097 | } | ||
| 1098 | pub fn abs64(elf: *const Elf) MachineRelocType { | ||
| 1099 | return switch (elf.ehdrMachine()) { | ||
| 1100 | .AARCH64 => .{ .AARCH64 = .ABS64 }, | ||
| 1101 | .LOONGARCH => .{ .LARCH = .@"64" }, | ||
| 1102 | .PPC64 => .{ .PPC64 = .ADDR64 }, | ||
| 1103 | .RISCV => .{ .RISCV = .@"64" }, | ||
| 1104 | .SPARCV9 => .{ .SPARC = .@"64" }, | ||
| 1105 | .X86_64 => .{ .X86_64 = .@"64" }, | ||
| 1106 | }; | ||
| 1107 | } | ||
| 1108 | pub fn rel32(elf: *const Elf) MachineRelocType { | ||
| 1109 | return switch (elf.ehdrMachine()) { | ||
| 1110 | .AARCH64 => .{ .AARCH64 = .PREL32 }, | ||
| 1111 | .LOONGARCH => .{ .LARCH = .@"32_PCREL" }, | ||
| 1112 | .PPC64 => .{ .PPC64 = .REL32 }, | ||
| 1113 | .RISCV => .{ .RISCV = .@"32_PCREL" }, | ||
| 1114 | .SPARCV9 => .{ .SPARC = .DISP32 }, | ||
| 1115 | .X86_64 => .{ .X86_64 = .PC32 }, | ||
| 1116 | }; | ||
| 1117 | } | ||
| 1118 | pub fn rel64(elf: *const Elf) MachineRelocType { | ||
| 1119 | return switch (elf.ehdrMachine()) { | ||
| 1120 | .AARCH64 => .{ .AARCH64 = .PREL64 }, | ||
| 1121 | .LOONGARCH => unreachable, | ||
| 1122 | .PPC64 => .{ .PPC64 = .REL64 }, | ||
| 1123 | .RISCV => unreachable, | ||
| 1124 | .SPARCV9 => .{ .SPARC = .DISP64 }, | ||
| 1125 | .X86_64 => .{ .X86_64 = .PC64 }, | ||
| 1126 | }; | ||
| 1127 | } | ||
| 1128 | pub fn size32(elf: *const Elf) ?MachineRelocType { | ||
| 1129 | return switch (elf.ehdrMachine()) { | ||
| 1130 | .AARCH64, | ||
| 1131 | .LOONGARCH, | ||
| 1132 | .PPC64, | ||
| 1133 | .RISCV, | ||
| 1134 | => null, | ||
| 1135 | |||
| 1136 | .SPARCV9 => .{ .SPARC = .SIZE32 }, | ||
| 1137 | .X86_64 => .{ .X86_64 = .SIZE32 }, | ||
| 1138 | }; | ||
| 1139 | } | ||
| 1140 | pub fn size64(elf: *const Elf) ?MachineRelocType { | ||
| 1141 | return switch (elf.ehdrMachine()) { | ||
| 1142 | .AARCH64, | ||
| 1143 | .LOONGARCH, | ||
| 1144 | .PPC64, | ||
| 1145 | .RISCV, | ||
| 1146 | => null, | ||
| 1147 | |||
| 1148 | .SPARCV9 => .{ .SPARC = .SIZE64 }, | ||
| 1149 | .X86_64 => .{ .X86_64 = .SIZE64 }, | ||
| 1150 | }; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | pub fn wrap(int: u32, elf: *const Elf) MachineRelocType { | ||
| 1154 | return switch (elf.ehdrMachine()) { | ||
| 1155 | .AARCH64 => .{ .AARCH64 = @fromBackingInt(int) }, | ||
| 1156 | .LOONGARCH => .{ .LARCH = @fromBackingInt(int) }, | ||
| 1157 | .PPC64 => .{ .PPC64 = @fromBackingInt(int) }, | ||
| 1158 | .RISCV => .{ .RISCV = @fromBackingInt(int) }, | ||
| 1159 | .SPARCV9 => .{ .SPARC = @fromBackingInt(int) }, | ||
| 1160 | .X86_64 => .{ .X86_64 = @fromBackingInt(int) }, | ||
| 1161 | }; | ||
| 1162 | } | ||
| 1163 | pub fn unwrap(rt: MachineRelocType, elf: *const Elf) u32 { | ||
| 1164 | return switch (elf.ehdrMachine()) { | ||
| 1165 | .AARCH64 => @backingInt(rt.AARCH64), | ||
| 1166 | .LOONGARCH => @backingInt(rt.LARCH), | ||
| 1167 | .PPC64 => @backingInt(rt.PPC64), | ||
| 1168 | .RISCV => @backingInt(rt.RISCV), | ||
| 1169 | .SPARCV9 => @backingInt(rt.SPARC), | ||
| 1170 | .X86_64 => @backingInt(rt.X86_64), | ||
| 1171 | }; | ||
| 1172 | } | ||
| 844 | }; | 1173 | }; |
| 845 | 1174 | ||
| 846 | /// A relocation targeting a particular GOT entry. | 1175 | /// A relocation targeting an arbitrary symbol with a fixed addend. |
| 847 | const GotReloc = struct { | 1176 | const SymbolReloc = struct { |
| 848 | /// The node containing this relocation. Possible values are: | 1177 | /// The node containing this relocation. Possible values are: |
| 849 | /// * An input section | 1178 | /// * An input section |
| 850 | /// * A section | 1179 | /// * A section |
| ... | @@ -853,137 +1182,488 @@ const GotReloc = struct { | ... | @@ -853,137 +1182,488 @@ const GotReloc = struct { |
| 853 | node: MappedFile.Node.Index.Optional, | 1182 | node: MappedFile.Node.Index.Optional, |
| 854 | /// The offset of the relocation inside of `node`. | 1183 | /// The offset of the relocation inside of `node`. |
| 855 | offset: u64, | 1184 | offset: u64, |
| 856 | target: GotKey, | 1185 | /// A symbol used to compute the relocated value. Precise meaning depends on `@"type"`. |
| 1186 | target: Symbol.Id, | ||
| 1187 | /// A signed constant used to compute the relocated value. Precise meaning depends on `@"type"`. | ||
| 857 | addend: i64, | 1188 | addend: i64, |
| 858 | type: GotReloc.Type, | 1189 | /// Specifies how to apply the relocation. |
| 859 | result: enum(u8) { ok, overflowed, misaligned }, | 1190 | /// |
| 860 | 1191 | /// When emitting a relocatable, this field is `undefined`. | |
| 861 | /// `GotReloc.Type` has the same structure as `SymbolReloc.Type`, just with different `Target` | 1192 | type: SymbolReloc.Type, |
| 862 | /// and `Special` enums---consult doc comments on `SymbolReloc.Type` for an overview. | 1193 | /// Forms a linked list of all symbol relocations with the same `target`. This list exists so |
| 1194 | /// that all relocations targeting a particular symbol can be re-applied if that symbol moves. | ||
| 1195 | /// Doubly-linked so that relocations can be removed. | ||
| 1196 | next: SymbolReloc.Index, | ||
| 1197 | /// Back-reference in a doubly-linked list---see `next`. | ||
| 1198 | prev: SymbolReloc.Index, | ||
| 1199 | /// If this relocation has a corresponding output relocation, this is its index within the | ||
| 1200 | /// appropriate SHT_RELA section (see `relaSection`). If there is no output relocation | ||
| 1201 | /// corresponding to this relocation, this is `.none`. | ||
| 1202 | /// | ||
| 1203 | /// If we are producing a relocatable, this field is always populated, because all relocations | ||
| 1204 | /// are emitted as output relocations. | ||
| 1205 | /// | ||
| 1206 | /// If we are producing a DSO, this field is populated if this relocation requires a runtime | ||
| 1207 | /// relocation entry. The entry will be removed if we discover a definition which allows us to | ||
| 1208 | /// statically resolve the relocation. | ||
| 1209 | rela_index: Section.RelaIndex.Optional, | ||
| 1210 | result: enum(u8) { ok, overflowed, misaligned }, | ||
| 1211 | |||
| 1212 | /// Determines the section in which this relocation will be placed if it is outstanding. | ||
| 1213 | /// | ||
| 1214 | /// When producing a relocatable (ET_REL), the relocation section is `Section.rela.shndx` for | ||
| 1215 | /// the section of `node`, and this function asserts that the aforementioned `rela.shndx` field | ||
| 1216 | /// is populated. | ||
| 1217 | /// | ||
| 1218 | /// When producing a DSO, the relocation section is always `.rela.dyn`. It is not `.rela.plt` | ||
| 1219 | /// because relocations in the GOTPLT are handled specially, without `SymbolReloc` entries. | ||
| 1220 | fn relaSection(sr: *const SymbolReloc, elf: *Elf) Section.Index { | ||
| 1221 | const shndx = switch (elf.ehdrType()) { | ||
| 1222 | .REL => elf.getNodeShndx(sr.node.unwrap().?).get(elf).rela.shndx, | ||
| 1223 | .EXEC, .DYN => elf.shndx.rela_dyn, | ||
| 1224 | }; | ||
| 1225 | assert(shndx != .UNDEF); | ||
| 1226 | return shndx; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | /// Instead of using the ELF relocation enums, we have our own internal representation for | ||
| 1230 | /// relocation types. This representation is more compact (requiring only 16 bits), and allows | ||
| 1231 | /// sharing a lot of relocation handling between multiple relocs and target architectures. | ||
| 1232 | /// | ||
| 1233 | /// A relocation type can be "simple" or "special". | ||
| 1234 | /// | ||
| 1235 | /// "Simple" relocations are designed to cover the majority of cases. They can represent most | ||
| 1236 | /// relocations which either write 8-bit, 16-bit, 32-bit, or 64-bit integers, or which write one | ||
| 1237 | /// contiguous bit-field within such an integer (e.g. an instruction operand). For more details, | ||
| 1238 | /// see `Simple`. | ||
| 1239 | /// | ||
| 1240 | /// "Special" relocations handle anything which does not fit into the above category, such as | ||
| 1241 | /// relocations which write multiple sequences of bits or which need to do unusual arithmetic on | ||
| 1242 | /// a symbol value. The representation is simply a big enum containing all of these exceptional | ||
| 1243 | /// cases---see `Special`. This representation is in use when `Type.target == .special`. | ||
| 863 | const Type = packed struct(u16) { | 1244 | const Type = packed struct(u16) { |
| 864 | fn simple(target: Target, action: Simple) GotReloc.Type { | 1245 | /// Helper function for constructing a "simple" relocation type. This mainly exists to |
| 1246 | /// improve readability in the relocation lowering logic in `addRelocAssumeCapacity`. | ||
| 1247 | fn simple(target: Target, action: Simple) SymbolReloc.Type { | ||
| 865 | assert(target != .special); | 1248 | assert(target != .special); |
| 866 | return .{ .target = target, .action = .{ .simple = action } }; | 1249 | return .{ .target = target, .action = .{ .simple = action } }; |
| 867 | } | 1250 | } |
| 868 | 1251 | ||
| 869 | fn special(s: Special) GotReloc.Type { | 1252 | /// Helper function for constructing a "special" relocation type. This mainly exists to |
| 1253 | /// improve readability in the relocation lowering logic in `addRelocAssumeCapacity`. | ||
| 1254 | fn special(s: Special) SymbolReloc.Type { | ||
| 870 | return .{ .target = .special, .action = .{ .special = s } }; | 1255 | return .{ .target = .special, .action = .{ .special = s } }; |
| 871 | } | 1256 | } |
| 872 | 1257 | ||
| 1258 | /// See doc comment on `Target`. | ||
| 873 | target: Target, | 1259 | target: Target, |
| 1260 | /// If `target == .special`, the `special` field is used. | ||
| 1261 | /// | ||
| 1262 | /// Otherwise, the `.simple` field is used. | ||
| 874 | action: packed union { | 1263 | action: packed union { |
| 875 | simple: Simple, | 1264 | simple: Simple, |
| 876 | special: Special, | 1265 | special: Special, |
| 877 | }, | 1266 | }, |
| 878 | 1267 | ||
| 879 | /// Like `SymbolReloc.Target`, but for GOT relocations. There are fewer tags because there | 1268 | /// If a relocation is "special", indicates that using the value `.@"special"`. |
| 880 | /// are fewer different kinds of GOT relocation. | 1269 | /// |
| 1270 | /// Otherwise (for "simple" relocations), `Target` indicates the first step in computing the | ||
| 1271 | /// relocation---whether we care about the target symbol's absolute address, its PC-relative | ||
| 1272 | /// address, its PLT entry, etc. | ||
| 881 | const Target = enum(u3) { | 1273 | const Target = enum(u3) { |
| 882 | /// This is a "special" relocation whose specific type is in the `action.special` field. | 1274 | /// This is a "special" relocation whose specific type is in the `action.special` field. |
| 883 | special, | 1275 | special, |
| 884 | 1276 | ||
| 885 | /// Absolute address of the GOT entry. | 1277 | /// Absolute value of the target symbol. |
| 886 | abs, | 1278 | abs, |
| 887 | /// Offset from the relocation itself to the GOT entry ("PC-relative"). | 1279 | /// Offset from the relocation itself to the target symbol ("PC-relative"). |
| 888 | rel, | 1280 | rel, |
| 889 | /// Offset from the base of the GOT to the GOT entry. | 1281 | /// Address of the target symbol's PLT entry. |
| 890 | offset, | 1282 | /// |
| 1283 | /// If the target symbol does not have a PLT entry, equivalent to `.abs`. | ||
| 1284 | pltabs, | ||
| 1285 | /// Offset from the relocation itself to the target symbol's PLT entry ("PC-relative"). | ||
| 1286 | /// | ||
| 1287 | /// If the target symbol does not have a PLT entry, equivalent to `.rel`. | ||
| 1288 | pltrel, | ||
| 1289 | /// Offset of the target TLS symbol from the base of this DSO's own TLS region. | ||
| 1290 | dtpoff, | ||
| 1291 | /// Offset of the target TLS symbol from the raw thread pointer. | ||
| 1292 | tpoff, | ||
| 1293 | /// Size of the target symbol. | ||
| 1294 | size, | ||
| 891 | }; | 1295 | }; |
| 892 | 1296 | ||
| 893 | const Simple = SymbolReloc.Type.Simple; | 1297 | /// For a "simple" relocation, after the initial value is computed according to `Target`, a |
| 894 | 1298 | /// `Simple` value communicates how to shift, truncate, and store that value into memory. | |
| 895 | /// Like `SymbolReloc.Special`, but for GOT relocations. | 1299 | const Simple = packed struct(u13) { |
| 896 | const Special = enum(u13) { | 1300 | /// The field being written to, represented as a sequence of bits in a backing integer |
| 897 | larch_pcala_hi20, | 1301 | /// of 8, 16, 32, or 64 bits. |
| 898 | larch_pcala64_lo20, | 1302 | /// |
| 899 | larch_pcala64_hi12, | 1303 | /// The `.@"8"`, `.@"16"`, `.@"32"`, and `.@"64"` fields simply write to all bits of the |
| 1304 | /// backing integer; i.e. the existing value is entirely overwritten. | ||
| 1305 | /// | ||
| 1306 | /// Other fields are named like "B[H:L]", where "B" is the backing integer type, and | ||
| 1307 | /// "H" and "L" are the indices of the highest and lowest bits in the bit field (in | ||
| 1308 | /// other words, an inclusive bit range). This notation was chosen because it seems to | ||
| 1309 | /// be one of the more common ways that bit relocations are written in ABIs. | ||
| 1310 | /// | ||
| 1311 | /// e.g. 8[6:3] writes the relocated value to this 4-bit field in an 8-bit integer: | ||
| 1312 | /// | ||
| 1313 | /// MSB ___ ### ### ### ### ___ ___ ___ LSB | ||
| 1314 | /// 7 6 5 4 3 2 1 0 | ||
| 1315 | /// bit index | ||
| 1316 | /// | ||
| 1317 | /// This enum is not intended to be able to represent every possible bit field in the | ||
| 1318 | /// backing integer types. Instead, to keep `SymbolReloc.Type` compact, fields are added | ||
| 1319 | /// to this enum only as needed. If the enum ever becomes full, some lesser-used tags | ||
| 1320 | /// can have their handling moved into `Special` to free up space. | ||
| 1321 | dest: enum(u6) { | ||
| 1322 | @"8", | ||
| 1323 | @"16", | ||
| 1324 | @"32", | ||
| 1325 | @"64", | ||
| 900 | 1326 | ||
| 901 | sparc_op_lox10, | 1327 | @"32[4:0]", |
| 902 | sparc_op_hix22, | 1328 | @"32[5:0]", |
| 1329 | @"32[6:0]", | ||
| 1330 | @"32[9:0]", | ||
| 1331 | @"32[10:0]", | ||
| 1332 | @"32[11:0]", | ||
| 1333 | @"32[12:0]", | ||
| 1334 | @"32[21:0]", | ||
| 1335 | @"32[21:10]", | ||
| 1336 | @"32[24:5]", | ||
| 1337 | @"32[25:10]", | ||
| 1338 | @"32[29:0]", | ||
| 903 | 1339 | ||
| 904 | fn applyInner( | 1340 | /// Returns `true` iff `dest` writes a full address for the target. |
| 905 | s: Special, | 1341 | /// |
| 906 | elf: *Elf, | 1342 | /// i.e. checks for `.@"32"` on 32-bit targets; for `.@"64"` on 64-bit targets. |
| 907 | got_vaddr: u64, | 1343 | fn isAddr(dest: @This(), elf: *const Elf) bool { |
| 908 | got_offset: u64, | 1344 | return switch (elf.identClass()) { |
| 909 | addend: u64, | 1345 | .NONE, _ => unreachable, |
| 910 | dest_vaddr: u64, | 1346 | .@"32" => dest == .@"32", |
| 911 | dest_slice: []u8, | 1347 | .@"64" => dest == .@"64", |
| 912 | ) error{ RelocationMisaligned, RelocationOverflow }!void { | 1348 | }; |
| 913 | switch (s) { | ||
| 914 | .larch_pcala_hi20 => { | ||
| 915 | const val = got_vaddr +% got_offset +% addend; | ||
| 916 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | ||
| 917 | elf.targetStore(inst, .{ | ||
| 918 | .b0_4 = elf.targetLoad(inst).b0_4, | ||
| 919 | .j20 = link.loongarch.pcalaHi20(val, dest_vaddr), | ||
| 920 | .b25_31 = elf.targetLoad(inst).b25_31, | ||
| 921 | }); | ||
| 922 | }, | ||
| 923 | .larch_pcala64_lo20 => { | ||
| 924 | const val = got_vaddr +% got_offset +% addend; | ||
| 925 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | ||
| 926 | elf.targetStore(inst, .{ | ||
| 927 | .b0_4 = elf.targetLoad(inst).b0_4, | ||
| 928 | .j20 = link.loongarch.pcala64Lo20(val, dest_vaddr), | ||
| 929 | .b25_31 = elf.targetLoad(inst).b25_31, | ||
| 930 | }); | ||
| 931 | }, | ||
| 932 | .larch_pcala64_hi12 => { | ||
| 933 | const val = got_vaddr +% got_offset +% addend; | ||
| 934 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); | ||
| 935 | elf.targetStore(inst, .{ | ||
| 936 | .b0_9 = elf.targetLoad(inst).b0_9, | ||
| 937 | .k12 = link.loongarch.pcala64Hi12(val, dest_vaddr), | ||
| 938 | .b22_31 = elf.targetLoad(inst).b22_31, | ||
| 939 | }); | ||
| 940 | }, | ||
| 941 | .sparc_op_lox10 => { | ||
| 942 | const dest_ptr: *align(1) packed struct(u32) { | ||
| 943 | imm13: u13, | ||
| 944 | b13_31: u19, | ||
| 945 | } = @ptrCast(dest_slice); | ||
| 946 | elf.targetStore(dest_ptr, .{ | ||
| 947 | .imm13 = @as(u10, @truncate(got_offset)), | ||
| 948 | .b13_31 = elf.targetLoad(dest_ptr).b13_31, | ||
| 949 | }); | ||
| 950 | }, | ||
| 951 | .sparc_op_hix22 => { | ||
| 952 | const dest_ptr: *align(1) packed struct(u32) { | ||
| 953 | imm22: u22, | ||
| 954 | b22_31: u10, | ||
| 955 | } = @ptrCast(dest_slice); | ||
| 956 | elf.targetStore(dest_ptr, .{ | ||
| 957 | .imm22 = @truncate(got_offset >> 10), | ||
| 958 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, | ||
| 959 | }); | ||
| 960 | }, | ||
| 961 | } | 1349 | } |
| 962 | } | 1350 | }, |
| 963 | }; | ||
| 964 | }; | ||
| 965 | 1351 | ||
| 966 | const Index = enum(u32) { | 1352 | /// After the relocation value is shifted (see `shift`), it is truncated to the size of |
| 967 | none = std.math.maxInt(u32), | 1353 | /// the bit field (see `dest`). This field specifies whether the linker will check for, |
| 968 | _, | 1354 | /// and error in the case of, truncated bits (in other words, relocation overflow). |
| 1355 | cast: enum(u2) { | ||
| 1356 | /// Do not perform any check when truncating unused bits. | ||
| 1357 | trunc, | ||
| 1358 | /// Error if the truncated value cannot be zero-extended back to the original value, | ||
| 1359 | /// i.e. if the truncated value is different when interpreted as unsigned. | ||
| 1360 | unsigned, | ||
| 1361 | /// Error if the truncated value cannot be sign-extended back to the original value. | ||
| 1362 | /// i.e. if the truncated value is different when interpreted as signed. | ||
| 1363 | signed, | ||
| 1364 | }, | ||
| 969 | 1365 | ||
| 970 | fn get(index: GotReloc.Index, elf: *Elf) *GotReloc { | 1366 | /// The relocation value (computed based on the `Target`) gets shifted to the right by |
| 971 | return &elf.got_relocs.items[@backingInt(index)]; | 1367 | /// this amount. By default, the shifted-out bits can be anything, but tags ending in |
| 972 | } | 1368 | /// "_exact" introduce a check that the shifted-out bits are all zeroes (an error is |
| 973 | }; | 1369 | /// emitted if not), similar to the behavior of `@shrExact`. |
| 1370 | shift: enum(u5) { | ||
| 1371 | @"0", | ||
| 1372 | @"2_exact", | ||
| 1373 | @"10", | ||
| 1374 | @"12", | ||
| 1375 | @"22", | ||
| 1376 | @"32", | ||
| 1377 | @"52", | ||
| 1378 | }, | ||
| 974 | 1379 | ||
| 975 | fn apply(reloc: *GotReloc, elf: *Elf) void { | 1380 | /// Given a value (computed based on the `Target`), applies the shift and truncation |
| 976 | assert(elf.ehdrType() != .REL); | 1381 | /// operations specified by `s`, then writes the result to the start of `dest_slice` as |
| 977 | const node = reloc.node.unwrap() orelse { | 1382 | /// specified by `s.dest`. |
| 978 | return; // deleted | 1383 | fn write( |
| 979 | }; | 1384 | s: Simple, |
| 980 | if (node.hasMoved(&elf.mf) or elf.shndx.got.get(elf).ni.hasMoved(&elf.mf)) { | 1385 | val: u64, |
| 981 | // There's no point applying the relocation now, because it will be re-applied by | 1386 | dest_slice: []u8, |
| 982 | // `flushMoved` at some point anyway. | 1387 | target_endian: std.lang.Endian, |
| 983 | return; | 1388 | ) error{ RelocationMisaligned, RelocationOverflow }!void { |
| 984 | } | 1389 | const shift: u6, const shift_exact: bool = switch (s.shift) { |
| 985 | switch (reloc.result) { | 1390 | .@"0" => .{ 0, false }, |
| 986 | .ok => {}, | 1391 | .@"2_exact" => .{ 2, true }, |
| 1392 | .@"10" => .{ 10, false }, | ||
| 1393 | .@"12" => .{ 12, false }, | ||
| 1394 | .@"22" => .{ 22, false }, | ||
| 1395 | .@"32" => .{ 32, false }, | ||
| 1396 | .@"52" => .{ 52, false }, | ||
| 1397 | }; | ||
| 1398 | |||
| 1399 | if (shift_exact and (val >> shift) << shift != val) { | ||
| 1400 | return error.RelocationMisaligned; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | const dest_word_bits: u8, const dest_high_bit: u6, const dest_low_bit: u6 = switch (s.dest) { | ||
| 1404 | // zig fmt: off | ||
| 1405 | .@"8" => .{ 8, 7, 0 }, | ||
| 1406 | .@"16" => .{ 16, 15, 0 }, | ||
| 1407 | .@"32" => .{ 32, 31, 0 }, | ||
| 1408 | .@"64" => .{ 64, 63, 0 }, | ||
| 1409 | .@"32[4:0]" => .{ 32, 4, 0 }, | ||
| 1410 | .@"32[5:0]" => .{ 32, 5, 0 }, | ||
| 1411 | .@"32[6:0]" => .{ 32, 6, 0 }, | ||
| 1412 | .@"32[9:0]" => .{ 32, 9, 0 }, | ||
| 1413 | .@"32[10:0]" => .{ 32, 10, 0 }, | ||
| 1414 | .@"32[11:0]" => .{ 32, 11, 0 }, | ||
| 1415 | .@"32[12:0]" => .{ 32, 12, 0 }, | ||
| 1416 | .@"32[21:0]" => .{ 32, 21, 0 }, | ||
| 1417 | .@"32[21:10]" => .{ 32, 21, 10 }, | ||
| 1418 | .@"32[24:5]" => .{ 32, 24, 5 }, | ||
| 1419 | .@"32[25:10]" => .{ 32, 25, 10 }, | ||
| 1420 | .@"32[29:0]" => .{ 32, 29, 0 }, | ||
| 1421 | // zig fmt: on | ||
| 1422 | }; | ||
| 1423 | |||
| 1424 | // The number of bits we are truncating from the full 64-bit relocation value. | ||
| 1425 | const trunc_bits: u6 = 63 - dest_high_bit + dest_low_bit; | ||
| 1426 | |||
| 1427 | // When we shift, whether we do an arithmetic or logical shift depends on what cast | ||
| 1428 | // behavior we are going to use. If we'll be doing a signed int cast, we must shift | ||
| 1429 | // in sign bits so that we don't incorrectly cause a failure, and vice versa for an | ||
| 1430 | // unsigned int cast. Either is fine when truncating (here we pick logical shift). | ||
| 1431 | const shifted_val: u64 = switch (s.cast) { | ||
| 1432 | .trunc => val >> shift, | ||
| 1433 | inline else => |cast| shifted: { | ||
| 1434 | const ShiftInt = if (cast == .signed) i64 else u64; | ||
| 1435 | const x: ShiftInt = @bitCast(val); | ||
| 1436 | const shifted: ShiftInt = x >> shift; | ||
| 1437 | |||
| 1438 | if ((shifted << trunc_bits) >> trunc_bits != shifted) { | ||
| 1439 | return error.RelocationOverflow; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | break :shifted @bitCast(shifted); | ||
| 1443 | }, | ||
| 1444 | }; | ||
| 1445 | |||
| 1446 | // Create a bit-mask for the field being populated, e.g. 8[3:1] -> 0b00001110 | ||
| 1447 | const field_mask = (~@as(u64, 0) >> trunc_bits) << dest_low_bit; | ||
| 1448 | |||
| 1449 | // Shift and mask the value to be in the correct bits, leaving the others zeroed. | ||
| 1450 | const masked_field: u64 = (shifted_val << dest_low_bit) & field_mask; | ||
| 1451 | |||
| 1452 | // Now we just need to actually apply the relocation by loading a word, replacing | ||
| 1453 | // the field bits with those in `masked_field`, and storing the result back. | ||
| 1454 | switch (dest_word_bits) { | ||
| 1455 | inline 8, 16, 32, 64 => |bits| { | ||
| 1456 | const word_slice = dest_slice[0..@divExact(bits, 8)]; | ||
| 1457 | const Int = @Int(.unsigned, bits); | ||
| 1458 | const old: u64 = std.mem.readInt(Int, word_slice, target_endian); | ||
| 1459 | const new: u64 = (old & ~field_mask) | masked_field; | ||
| 1460 | std.mem.writeInt(Int, word_slice, @intCast(new), target_endian); | ||
| 1461 | }, | ||
| 1462 | else => unreachable, | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | }; | ||
| 1466 | |||
| 1467 | /// Enum representing "special" relocation types, i.e. those which cannot be represented | ||
| 1468 | /// just with `Target` and `Simple`. These relocations have completely custom handling in | ||
| 1469 | /// the `Special.applyInner` function. | ||
| 1470 | const Special = enum(u13) { | ||
| 1471 | larch_pcala_hi20, | ||
| 1472 | larch_pcala64_lo20, | ||
| 1473 | larch_pcala64_hi12, | ||
| 1474 | larch_b21, | ||
| 1475 | larch_b26, | ||
| 1476 | larch_call36, | ||
| 1477 | |||
| 1478 | sparc_le_hix22, | ||
| 1479 | |||
| 1480 | fn applyInner( | ||
| 1481 | s: Special, | ||
| 1482 | elf: *Elf, | ||
| 1483 | target: Symbol.Id, | ||
| 1484 | addend: u64, | ||
| 1485 | dest_vaddr: u64, | ||
| 1486 | dest_slice: []u8, | ||
| 1487 | ) error{ RelocationMisaligned, RelocationOverflow }!void { | ||
| 1488 | switch (s) { | ||
| 1489 | .larch_pcala_hi20 => { | ||
| 1490 | const val = target.value(elf) +% addend; | ||
| 1491 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | ||
| 1492 | elf.targetStore(inst, .{ | ||
| 1493 | .b0_4 = elf.targetLoad(inst).b0_4, | ||
| 1494 | .j20 = link.loongarch.pcalaHi20(val, dest_vaddr), | ||
| 1495 | .b25_31 = elf.targetLoad(inst).b25_31, | ||
| 1496 | }); | ||
| 1497 | }, | ||
| 1498 | .larch_pcala64_lo20 => { | ||
| 1499 | const val = target.value(elf) +% addend; | ||
| 1500 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | ||
| 1501 | elf.targetStore(inst, .{ | ||
| 1502 | .b0_4 = elf.targetLoad(inst).b0_4, | ||
| 1503 | .j20 = link.loongarch.pcala64Lo20(val, dest_vaddr), | ||
| 1504 | .b25_31 = elf.targetLoad(inst).b25_31, | ||
| 1505 | }); | ||
| 1506 | }, | ||
| 1507 | .larch_pcala64_hi12 => { | ||
| 1508 | const val = target.value(elf) +% addend; | ||
| 1509 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); | ||
| 1510 | elf.targetStore(inst, .{ | ||
| 1511 | .b0_9 = elf.targetLoad(inst).b0_9, | ||
| 1512 | .k12 = link.loongarch.pcala64Hi12(val, dest_vaddr), | ||
| 1513 | .b22_31 = elf.targetLoad(inst).b22_31, | ||
| 1514 | }); | ||
| 1515 | }, | ||
| 1516 | .larch_b21, .larch_b26, .larch_call36 => { | ||
| 1517 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target) orelse target.value(elf); | ||
| 1518 | const jump_offset: i64 = @bitCast(target_vaddr +% addend -% dest_vaddr); | ||
| 1519 | if ((jump_offset >> 2) << 2 != jump_offset) { | ||
| 1520 | return error.RelocationMisaligned; | ||
| 1521 | } | ||
| 1522 | const shifted_jump_offset: i64 = @shrExact(jump_offset, 2); | ||
| 1523 | switch (s) { | ||
| 1524 | .larch_b21 => { | ||
| 1525 | if ((shifted_jump_offset << (64 - 21)) >> (64 - 21) != shifted_jump_offset) { | ||
| 1526 | return error.RelocationOverflow; | ||
| 1527 | } | ||
| 1528 | const truncated: i21 = @intCast(shifted_jump_offset); | ||
| 1529 | const parts: packed struct { lo16: u16, hi5: u5 } = @bitCast(truncated); | ||
| 1530 | const inst: *align(1) link.loongarch.D5K16 = @ptrCast(dest_slice[0..4]); | ||
| 1531 | elf.targetStore(inst, .{ | ||
| 1532 | .d5 = parts.hi5, | ||
| 1533 | .b5_9 = elf.targetLoad(inst).b5_9, | ||
| 1534 | .k16 = parts.lo16, | ||
| 1535 | .b26_31 = elf.targetLoad(inst).b26_31, | ||
| 1536 | }); | ||
| 1537 | }, | ||
| 1538 | .larch_b26 => { | ||
| 1539 | if ((shifted_jump_offset << (64 - 26)) >> (64 - 26) != shifted_jump_offset) { | ||
| 1540 | return error.RelocationOverflow; | ||
| 1541 | } | ||
| 1542 | const truncated: i26 = @intCast(shifted_jump_offset); | ||
| 1543 | const parts: packed struct { lo16: u16, hi10: u10 } = @bitCast(truncated); | ||
| 1544 | const inst: *align(1) link.loongarch.D10K16 = @ptrCast(dest_slice[0..4]); | ||
| 1545 | elf.targetStore(inst, .{ | ||
| 1546 | .d10 = parts.hi10, | ||
| 1547 | .k16 = parts.lo16, | ||
| 1548 | .b26_31 = elf.targetLoad(inst).b26_31, | ||
| 1549 | }); | ||
| 1550 | }, | ||
| 1551 | .larch_call36 => { | ||
| 1552 | // The allowed range of destination addresses here is non-trivial: | ||
| 1553 | // [PC - 128 GiB - 0x20_000, PC + 128 GiB - 0x20_000 - 4] | ||
| 1554 | const gib = 1024 * 1024 * 1024; | ||
| 1555 | if (jump_offset < -128 * gib - 0x20_000 or | ||
| 1556 | jump_offset > 128 * gib - 0x20_000 - 4) | ||
| 1557 | { | ||
| 1558 | return error.RelocationOverflow; | ||
| 1559 | } | ||
| 1560 | // The values we write into the instructions are a little weird too: | ||
| 1561 | const hi: i20 = @intCast((shifted_jump_offset +% 0x8000) >> 16); | ||
| 1562 | const lo: i16 = @truncate(shifted_jump_offset); | ||
| 1563 | |||
| 1564 | const inst0: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | ||
| 1565 | const inst1: *align(1) link.loongarch.K16 = @ptrCast(dest_slice[4..8]); | ||
| 1566 | |||
| 1567 | const old0 = elf.targetLoad(inst0); | ||
| 1568 | elf.targetStore(inst0, .{ .b0_4 = old0.b0_4, .j20 = @bitCast(hi), .b25_31 = old0.b25_31 }); | ||
| 1569 | |||
| 1570 | const old1 = elf.targetLoad(inst1); | ||
| 1571 | elf.targetStore(inst1, .{ .b0_9 = old1.b0_9, .k16 = @bitCast(lo), .b26_31 = old1.b26_31 }); | ||
| 1572 | }, | ||
| 1573 | else => unreachable, | ||
| 1574 | } | ||
| 1575 | }, | ||
| 1576 | .sparc_le_hix22 => { | ||
| 1577 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; | ||
| 1578 | const tls_size: u64 = switch (elf.phdrSlice()) { | ||
| 1579 | inline else => |phdr| tls_size: { | ||
| 1580 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); | ||
| 1581 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); | ||
| 1582 | }, | ||
| 1583 | }; | ||
| 1584 | const dest_ptr: *align(1) packed struct(u32) { | ||
| 1585 | imm22: u22, | ||
| 1586 | b22_31: u10, | ||
| 1587 | } = @ptrCast(dest_slice); | ||
| 1588 | elf.targetStore(dest_ptr, .{ | ||
| 1589 | .imm22 = @truncate(~(target.value(elf) +% addend -% tls_size) >> 10), | ||
| 1590 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, | ||
| 1591 | }); | ||
| 1592 | }, | ||
| 1593 | } | ||
| 1594 | } | ||
| 1595 | }; | ||
| 1596 | |||
| 1597 | fn dependsOnTlsSize(t: SymbolReloc.Type, elf: *const Elf) bool { | ||
| 1598 | return switch (elf.targetTlsVariant()) { | ||
| 1599 | // In TLS variant I, the executable's TLS block starts at a fixed offset from the | ||
| 1600 | // thread pointer, so everything is fine... | ||
| 1601 | .I_original, .I_modified => false, | ||
| 1602 | // ...but in variant II, the executable's TLS block *ends* at a fixed offset from | ||
| 1603 | // the thread pointer, so the offset from the thread pointer to the *start* of the | ||
| 1604 | // TLS block depends on the size of the block, and we need that offset to resolve | ||
| 1605 | // 'tpoff' relocations. | ||
| 1606 | .II => switch (t.target) { | ||
| 1607 | .abs, | ||
| 1608 | .rel, | ||
| 1609 | .pltabs, | ||
| 1610 | .pltrel, | ||
| 1611 | .dtpoff, | ||
| 1612 | .size, | ||
| 1613 | => false, | ||
| 1614 | |||
| 1615 | .tpoff => true, | ||
| 1616 | |||
| 1617 | .special => switch (t.action.special) { | ||
| 1618 | .sparc_le_hix22, | ||
| 1619 | => true, | ||
| 1620 | |||
| 1621 | .larch_pcala_hi20, | ||
| 1622 | .larch_pcala64_lo20, | ||
| 1623 | .larch_pcala64_hi12, | ||
| 1624 | .larch_b21, | ||
| 1625 | .larch_b26, | ||
| 1626 | .larch_call36, | ||
| 1627 | => false, | ||
| 1628 | }, | ||
| 1629 | }, | ||
| 1630 | }; | ||
| 1631 | } | ||
| 1632 | }; | ||
| 1633 | |||
| 1634 | const Index = enum(u32) { | ||
| 1635 | none = std.math.maxInt(u32), | ||
| 1636 | _, | ||
| 1637 | |||
| 1638 | fn get(index: SymbolReloc.Index, elf: *Elf) *SymbolReloc { | ||
| 1639 | return &elf.symbol_relocs.items[@backingInt(index)]; | ||
| 1640 | } | ||
| 1641 | }; | ||
| 1642 | |||
| 1643 | fn flushMovedNode(reloc: *SymbolReloc, elf: *Elf, node_vaddr: u64) void { | ||
| 1644 | if (reloc.rela_index.unwrap()) |rela_index| { | ||
| 1645 | // The node has moved, so the offset of the relocation within the section might have | ||
| 1646 | // changed, so update the `offset` field of the `ElfN.Rela` entry. | ||
| 1647 | reloc.relaSection(elf).relaSetOffset(elf, rela_index, node_vaddr + reloc.offset); | ||
| 1648 | } | ||
| 1649 | // This is not just the inverse of the above condition, because if `reloc` is relative | ||
| 1650 | // to the base of this DSO, then `rela_index` is an `R_*_RELATIVE` relocation, but we | ||
| 1651 | // still need to call `SymbolReloc.apply` to update that relocation's addend. | ||
| 1652 | if (elf.ehdrType() != .REL) { | ||
| 1653 | reloc.apply(elf); | ||
| 1654 | } | ||
| 1655 | } | ||
| 1656 | |||
| 1657 | fn apply(reloc: *SymbolReloc, elf: *Elf) void { | ||
| 1658 | assert(elf.ehdrType() != .REL); | ||
| 1659 | const node = reloc.node.unwrap() orelse return; // deleted | ||
| 1660 | if (node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) { | ||
| 1661 | // There's no point applying the relocation now, because it will be re-applied by | ||
| 1662 | // `flushMoved` at some point anyway. | ||
| 1663 | return; | ||
| 1664 | } | ||
| 1665 | switch (reloc.result) { | ||
| 1666 | .ok => {}, | ||
| 987 | .overflowed => elf.overflowed_reloc_count -= 1, | 1667 | .overflowed => elf.overflowed_reloc_count -= 1, |
| 988 | .misaligned => elf.misaligned_reloc_count -= 1, | 1668 | .misaligned => elf.misaligned_reloc_count -= 1, |
| 989 | } | 1669 | } |
| ... | @@ -999,543 +1679,361 @@ const GotReloc = struct { | ... | @@ -999,543 +1679,361 @@ const GotReloc = struct { |
| 999 | reloc.result = .misaligned; | 1679 | reloc.result = .misaligned; |
| 1000 | elf.misaligned_reloc_count += 1; | 1680 | elf.misaligned_reloc_count += 1; |
| 1001 | }, | 1681 | }, |
| 1002 | } | 1682 | } |
| 1003 | } | ||
| 1004 | fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { | ||
| 1005 | const node = reloc.node.unwrap().?; | ||
| 1006 | const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset; | ||
| 1007 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; | ||
| 1008 | |||
| 1009 | const got_vaddr = elf.shndx.got.vaddr(elf); | ||
| 1010 | const got_index: u64 = elf.got.getIndex(reloc.target).?; | ||
| 1011 | const got_offset: u64 = switch (elf.identClass()) { | ||
| 1012 | .NONE, _ => unreachable, | ||
| 1013 | inline else => |class| @sizeOf(class.ElfN().Addr) * got_index, | ||
| 1014 | }; | ||
| 1015 | const addend: u64 = @bitCast(reloc.addend); | ||
| 1016 | |||
| 1017 | const target_val: u64 = switch (reloc.type.target) { | ||
| 1018 | .abs => got_vaddr +% got_offset +% addend, | ||
| 1019 | .rel => got_vaddr +% got_offset +% addend -% dest_vaddr, | ||
| 1020 | .offset => got_offset +% addend, | ||
| 1021 | .special => return reloc.type.action.special.applyInner( | ||
| 1022 | elf, | ||
| 1023 | got_vaddr, | ||
| 1024 | got_offset, | ||
| 1025 | addend, | ||
| 1026 | dest_vaddr, | ||
| 1027 | dest_slice, | ||
| 1028 | ), | ||
| 1029 | }; | ||
| 1030 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | fn delete(reloc: *GotReloc, elf: *Elf) void { | ||
| 1034 | switch (reloc.result) { | ||
| 1035 | .ok => {}, | ||
| 1036 | .overflowed => elf.overflowed_reloc_count -= 1, | ||
| 1037 | .misaligned => elf.misaligned_reloc_count -= 1, | ||
| 1038 | } | ||
| 1039 | reloc.* = .{ | ||
| 1040 | .node = .none, | ||
| 1041 | .offset = undefined, | ||
| 1042 | .target = undefined, | ||
| 1043 | .addend = undefined, | ||
| 1044 | .type = undefined, | ||
| 1045 | .result = undefined, | ||
| 1046 | }; | ||
| 1047 | } | ||
| 1048 | }; | ||
| 1049 | |||
| 1050 | pub const MachineRelocType = union { | ||
| 1051 | AARCH64: std.elf.R_AARCH64, | ||
| 1052 | LARCH: std.elf.R_LARCH, | ||
| 1053 | PPC64: std.elf.R_PPC64, | ||
| 1054 | RISCV: std.elf.R_RISCV, | ||
| 1055 | SPARC: std.elf.R_SPARC, | ||
| 1056 | X86_64: std.elf.R_X86_64, | ||
| 1057 | |||
| 1058 | pub const Format = struct { | ||
| 1059 | rt: MachineRelocType, | ||
| 1060 | elf: *const Elf, | ||
| 1061 | |||
| 1062 | pub fn format(f: Format, w: *Io.Writer) Io.Writer.Error!void { | ||
| 1063 | switch (f.elf.ehdrMachine()) { | ||
| 1064 | .AARCH64 => try w.print("R_AARCH64_{t}", .{f.rt.AARCH64}), | ||
| 1065 | .LOONGARCH => try w.print("R_LARCH_{t}", .{f.rt.LARCH}), | ||
| 1066 | .PPC64 => try w.print("R_PPC64_{t}", .{f.rt.PPC64}), | ||
| 1067 | .RISCV => try w.print("R_RISCV_{t}", .{f.rt.RISCV}), | ||
| 1068 | .SPARCV9 => try w.print("R_SPARC_{t}", .{f.rt.SPARC}), | ||
| 1069 | .X86_64 => try w.print("R_X86_64_{t}", .{f.rt.X86_64}), | ||
| 1070 | } | ||
| 1071 | } | ||
| 1072 | }; | ||
| 1073 | |||
| 1074 | pub fn fmt(rt: MachineRelocType, elf: *const Elf) Format { | ||
| 1075 | return .{ .rt = rt, .elf = elf }; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | pub fn none(elf: *const Elf) MachineRelocType { | ||
| 1079 | return switch (elf.ehdrMachine()) { | ||
| 1080 | .AARCH64 => .{ .AARCH64 = .NONE }, | ||
| 1081 | .LOONGARCH => .{ .LARCH = .NONE }, | ||
| 1082 | .PPC64 => .{ .PPC64 = .NONE }, | ||
| 1083 | .RISCV => .{ .RISCV = .NONE }, | ||
| 1084 | .SPARCV9 => .{ .SPARC = .NONE }, | ||
| 1085 | .X86_64 => .{ .X86_64 = .NONE }, | ||
| 1086 | }; | ||
| 1087 | } | ||
| 1088 | pub fn copy(elf: *const Elf) MachineRelocType { | ||
| 1089 | return switch (elf.ehdrMachine()) { | ||
| 1090 | .AARCH64 => .{ .AARCH64 = .COPY }, | ||
| 1091 | .LOONGARCH => .{ .LARCH = .COPY }, | ||
| 1092 | .PPC64 => .{ .PPC64 = .COPY }, | ||
| 1093 | .RISCV => .{ .RISCV = .COPY }, | ||
| 1094 | .SPARCV9 => .{ .SPARC = .COPY }, | ||
| 1095 | .X86_64 => .{ .X86_64 = .COPY }, | ||
| 1096 | }; | ||
| 1097 | } | ||
| 1098 | pub fn relative(elf: *const Elf) MachineRelocType { | ||
| 1099 | return switch (elf.ehdrMachine()) { | ||
| 1100 | .AARCH64 => .{ .AARCH64 = .RELATIVE }, | ||
| 1101 | .LOONGARCH => .{ .LARCH = .RELATIVE }, | ||
| 1102 | .PPC64 => .{ .PPC64 = .RELATIVE }, | ||
| 1103 | .RISCV => .{ .RISCV = .RELATIVE }, | ||
| 1104 | .SPARCV9 => .{ .SPARC = .RELATIVE }, | ||
| 1105 | .X86_64 => .{ .X86_64 = .RELATIVE }, | ||
| 1106 | }; | ||
| 1107 | } | ||
| 1108 | pub fn jumpSlot(elf: *const Elf) MachineRelocType { | ||
| 1109 | return switch (elf.ehdrMachine()) { | ||
| 1110 | .AARCH64 => .{ .AARCH64 = .JUMP_SLOT }, | ||
| 1111 | .LOONGARCH => .{ .LARCH = .JUMP_SLOT }, | ||
| 1112 | .PPC64 => .{ .PPC64 = .JMP_SLOT }, | ||
| 1113 | .RISCV => .{ .RISCV = .JUMP_SLOT }, | ||
| 1114 | .SPARCV9 => .{ .SPARC = .JMP_SLOT }, | ||
| 1115 | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, | ||
| 1116 | }; | ||
| 1117 | } | ||
| 1118 | pub fn globDat(elf: *const Elf) MachineRelocType { | ||
| 1119 | return switch (elf.ehdrMachine()) { | ||
| 1120 | .AARCH64 => .{ .AARCH64 = .GLOB_DAT }, | ||
| 1121 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | ||
| 1122 | .PPC64 => .{ .PPC64 = .GLOB_DAT }, | ||
| 1123 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | ||
| 1124 | .SPARCV9 => .{ .SPARC = .GLOB_DAT }, | ||
| 1125 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, | ||
| 1126 | }; | ||
| 1127 | } | ||
| 1128 | pub fn dtpMod(elf: *const Elf) MachineRelocType { | ||
| 1129 | return switch (elf.ehdrMachine()) { | ||
| 1130 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .TLS_DTPMOD else .P32_TLS_DTPMOD }, | ||
| 1131 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | ||
| 1132 | .PPC64 => .{ .PPC64 = .DTPMOD64 }, | ||
| 1133 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | ||
| 1134 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | ||
| 1135 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, | ||
| 1136 | }; | ||
| 1137 | } | ||
| 1138 | pub fn dtpOff(elf: *const Elf) MachineRelocType { | ||
| 1139 | return switch (elf.ehdrMachine()) { | ||
| 1140 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .TLS_DTPREL else .P32_TLS_DTPREL }, | ||
| 1141 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, | ||
| 1142 | .PPC64 => .{ .PPC64 = .DTPREL64 }, | ||
| 1143 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, | ||
| 1144 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPOFF64 else .TLS_DTPOFF32 }, | ||
| 1145 | .X86_64 => .{ .X86_64 = .DTPOFF64 }, | ||
| 1146 | }; | ||
| 1147 | } | ||
| 1148 | pub fn tpOff(elf: *const Elf) MachineRelocType { | ||
| 1149 | return switch (elf.ehdrMachine()) { | ||
| 1150 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .TLS_TPREL else .P32_TLS_TPREL }, | ||
| 1151 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 }, | ||
| 1152 | .PPC64 => .{ .PPC64 = .TPREL64 }, | ||
| 1153 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 }, | ||
| 1154 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_TPOFF64 else .TLS_TPOFF32 }, | ||
| 1155 | .X86_64 => .{ .X86_64 = .TPOFF64 }, | ||
| 1156 | }; | ||
| 1157 | } | ||
| 1158 | pub fn absAddr(elf: *const Elf) MachineRelocType { | ||
| 1159 | return switch (elf.ehdrMachine()) { | ||
| 1160 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .ABS64 else .P32_ABS32 }, | ||
| 1161 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | ||
| 1162 | .PPC64 => .{ .PPC64 = .ADDR64 }, | ||
| 1163 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | ||
| 1164 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | ||
| 1165 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | ||
| 1166 | }; | ||
| 1167 | } | 1683 | } |
| 1168 | pub fn size32(elf: *const Elf) ?MachineRelocType { | 1684 | fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { |
| 1169 | return switch (elf.ehdrMachine()) { | 1685 | const node = reloc.node.unwrap().?; |
| 1170 | .AARCH64, | 1686 | const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset; |
| 1171 | .LOONGARCH, | 1687 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| 1172 | .PPC64, | ||
| 1173 | .RISCV, | ||
| 1174 | => null, | ||
| 1175 | 1688 | ||
| 1176 | .SPARCV9 => .{ .SPARC = .SIZE32 }, | 1689 | const addend: u64 = @bitCast(reloc.addend); |
| 1177 | .X86_64 => .{ .X86_64 = .SIZE32 }, | 1690 | const target_val: u64 = type: switch (reloc.type.target) { |
| 1691 | .abs => reloc.target.value(elf) +% addend, | ||
| 1692 | .rel => reloc.target.value(elf) +% addend -% dest_vaddr, | ||
| 1693 | .pltabs => { | ||
| 1694 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .abs; | ||
| 1695 | break :type plt_entry_addr +% addend; | ||
| 1696 | }, | ||
| 1697 | .pltrel => { | ||
| 1698 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .rel; | ||
| 1699 | break :type plt_entry_addr +% addend -% dest_vaddr; | ||
| 1700 | }, | ||
| 1701 | .dtpoff => reloc.target.value(elf) +% addend, | ||
| 1702 | .tpoff => switch (elf.targetTlsVariant()) { | ||
| 1703 | .I_original => |tls| tls.tcb_size +% reloc.target.value(elf) +% addend, | ||
| 1704 | .I_modified => |tls| 0 -% tls.tp_off +% reloc.target.value(elf) +% addend, | ||
| 1705 | .II => { | ||
| 1706 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; | ||
| 1707 | const tls_size: u64 = switch (elf.phdrSlice()) { | ||
| 1708 | inline else => |phdr| tls_size: { | ||
| 1709 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); | ||
| 1710 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); | ||
| 1711 | }, | ||
| 1712 | }; | ||
| 1713 | break :type reloc.target.value(elf) +% addend -% tls_size; | ||
| 1714 | }, | ||
| 1715 | }, | ||
| 1716 | .size => switch (elf.symPtr(reloc.target.index(elf))) { | ||
| 1717 | inline else => |sym| elf.targetLoad(&sym.size), | ||
| 1718 | }, | ||
| 1719 | .special => return reloc.type.action.special.applyInner( | ||
| 1720 | elf, | ||
| 1721 | reloc.target, | ||
| 1722 | addend, | ||
| 1723 | dest_vaddr, | ||
| 1724 | dest_slice, | ||
| 1725 | ), | ||
| 1178 | }; | 1726 | }; |
| 1179 | } | ||
| 1180 | pub fn size64(elf: *const Elf) ?MachineRelocType { | ||
| 1181 | return switch (elf.ehdrMachine()) { | ||
| 1182 | .AARCH64, | ||
| 1183 | .LOONGARCH, | ||
| 1184 | .PPC64, | ||
| 1185 | .RISCV, | ||
| 1186 | => null, | ||
| 1187 | 1727 | ||
| 1188 | .SPARCV9 => .{ .SPARC = .SIZE64 }, | 1728 | // Check for the `R_*_RELATIVE` case now, because it is possible only when no shift or cast |
| 1189 | .X86_64 => .{ .X86_64 = .SIZE64 }, | 1729 | // is required, meaning we can handle it now and return early. |
| 1730 | if (reloc.rela_index.unwrap()) |rela_index| switch (elf.classifySymbolValue(reloc.target)) { | ||
| 1731 | .static => unreachable, | ||
| 1732 | .dynamic => return, // the relocation happens at runtime | ||
| 1733 | .static_relative => { | ||
| 1734 | // We have emitted an R_*_RELATIVE relocation to help lower an absolute-address | ||
| 1735 | // relocation. The value computed above is valid, but instead of writing it to the | ||
| 1736 | // destination slice, we actually want to write it to the runtime relocation entry. | ||
| 1737 | switch (elf.identClass()) { | ||
| 1738 | .NONE, _ => unreachable, | ||
| 1739 | .@"32" => assert(reloc.type.action.simple.dest == .@"32"), | ||
| 1740 | .@"64" => assert(reloc.type.action.simple.dest == .@"64"), | ||
| 1741 | } | ||
| 1742 | assert(reloc.type.action.simple.cast == .unsigned); | ||
| 1743 | assert(reloc.type.action.simple.shift == .@"0"); | ||
| 1744 | elf.shndx.rela_dyn.relaSetAddend(elf, rela_index, target_val); | ||
| 1745 | return; | ||
| 1746 | }, | ||
| 1190 | }; | 1747 | }; |
| 1748 | |||
| 1749 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | ||
| 1191 | } | 1750 | } |
| 1192 | 1751 | ||
| 1193 | pub fn wrap(int: u32, elf: *const Elf) MachineRelocType { | 1752 | fn delete(reloc: *SymbolReloc, elf: *Elf, index: SymbolReloc.Index) void { |
| 1194 | return switch (elf.ehdrMachine()) { | 1753 | assert(index.get(elf) == reloc); |
| 1195 | .AARCH64 => .{ .AARCH64 = @fromBackingInt(int) }, | 1754 | |
| 1196 | .LOONGARCH => .{ .LARCH = @fromBackingInt(int) }, | 1755 | reloc.deleteOutputRel(elf); |
| 1197 | .PPC64 => .{ .PPC64 = @fromBackingInt(int) }, | 1756 | if (reloc.type.dependsOnTlsSize(elf)) { |
| 1198 | .RISCV => .{ .RISCV = @fromBackingInt(int) }, | 1757 | assert(elf.tls_size_symbol_relocs.swapRemove(index)); |
| 1199 | .SPARCV9 => .{ .SPARC = @fromBackingInt(int) }, | 1758 | } |
| 1200 | .X86_64 => .{ .X86_64 = @fromBackingInt(int) }, | 1759 | |
| 1201 | }; | 1760 | switch (reloc.prev) { |
| 1761 | .none => { | ||
| 1762 | const first_target_reloc = &reloc.target.index(elf).ptr(elf).first_target_reloc; | ||
| 1763 | assert(first_target_reloc.* == index); | ||
| 1764 | first_target_reloc.* = reloc.next; | ||
| 1765 | }, | ||
| 1766 | else => |prev| prev.get(elf).next = reloc.next, | ||
| 1767 | } | ||
| 1768 | switch (reloc.next) { | ||
| 1769 | .none => {}, | ||
| 1770 | else => |next| next.get(elf).prev = reloc.prev, | ||
| 1771 | } | ||
| 1772 | switch (reloc.result) { | ||
| 1773 | .ok => {}, | ||
| 1774 | .overflowed => elf.overflowed_reloc_count -= 1, | ||
| 1775 | .misaligned => elf.misaligned_reloc_count -= 1, | ||
| 1776 | } | ||
| 1777 | |||
| 1778 | reloc.* = undefined; | ||
| 1779 | reloc.node = .none; | ||
| 1202 | } | 1780 | } |
| 1203 | pub fn unwrap(rt: MachineRelocType, elf: *const Elf) u32 { | 1781 | |
| 1204 | return switch (elf.ehdrMachine()) { | 1782 | /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation, updating |
| 1205 | .AARCH64 => @backingInt(rt.AARCH64), | 1783 | /// `elf.textrel_count` if necessary. |
| 1206 | .LOONGARCH => @backingInt(rt.LARCH), | 1784 | fn deleteOutputRel(reloc: *SymbolReloc, elf: *Elf) void { |
| 1207 | .PPC64 => @backingInt(rt.PPC64), | 1785 | const rela_index = reloc.rela_index.unwrap() orelse return; |
| 1208 | .RISCV => @backingInt(rt.RISCV), | 1786 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); |
| 1209 | .SPARCV9 => @backingInt(rt.SPARC), | 1787 | switch (elf.ehdrType()) { |
| 1210 | .X86_64 => @backingInt(rt.X86_64), | 1788 | .REL => {}, |
| 1211 | }; | 1789 | .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node.unwrap().?)) { |
| 1790 | .no => unreachable, // there *was* a dynamic relocation! | ||
| 1791 | .yes => {}, | ||
| 1792 | .yes_textrel => elf.textrel_count -= 1, | ||
| 1793 | }, | ||
| 1794 | } | ||
| 1795 | reloc.rela_index = .none; | ||
| 1212 | } | 1796 | } |
| 1213 | }; | 1797 | }; |
| 1214 | 1798 | ||
| 1215 | /// A relocation targeting an arbitrary symbol with a fixed addend. | 1799 | /// A relocation targeting an arbitrary node (within a section) with a fixed addend. |
| 1216 | const SymbolReloc = struct { | 1800 | /// This represents a symbol reloc against the section symbol containing the node |
| 1217 | /// The node containing this relocation. Possible values are: | 1801 | /// with a variable addend that changes when the target node moves. |
| 1218 | /// * An input section | 1802 | const NodeReloc = struct { |
| 1219 | /// * A section | 1803 | node: MappedFile.Node.Index.Optional, |
| 1220 | /// * A NAV, UAV, or lazy code/data | ||
| 1221 | node: MappedFile.Node.Index, | ||
| 1222 | /// The offset of the relocation inside of `node`. | ||
| 1223 | offset: u64, | 1804 | offset: u64, |
| 1224 | /// A symbol used to compute the relocated value. Precise meaning depends on `@"type"`. | 1805 | target: MappedFile.Node.Index, |
| 1225 | target: Symbol.Id, | ||
| 1226 | /// A signed constant used to compute the relocated value. Precise meaning depends on `@"type"`. | ||
| 1227 | addend: i64, | 1806 | addend: i64, |
| 1228 | /// Specifies how to apply the relocation. | 1807 | type: NodeReloc.Type, |
| 1229 | /// | 1808 | next: NodeReloc.Index, |
| 1230 | /// When emitting a relocatable, this field is `undefined`. | 1809 | prev: NodeReloc.Index, |
| 1231 | type: SymbolReloc.Type, | ||
| 1232 | /// Forms a linked list of all symbol relocations with the same `target`. This list exists so | ||
| 1233 | /// that all relocations targeting a particular symbol can be re-applied if that symbol moves. | ||
| 1234 | /// Doubly-linked so that relocations can be removed. | ||
| 1235 | next: SymbolReloc.Index, | ||
| 1236 | /// Back-reference in a doubly-linked list---see `next`. | ||
| 1237 | prev: SymbolReloc.Index, | ||
| 1238 | /// If this relocation has a corresponding output relocation, this is its index within the | ||
| 1239 | /// appropriate SHT_RELA section (see `relaSection`). If there is no output relocation | ||
| 1240 | /// corresponding to this relocation, this is `.none`. | ||
| 1241 | /// | ||
| 1242 | /// If we are producing a relocatable, this field is always populated, because all relocations | ||
| 1243 | /// are emitted as output relocations. | ||
| 1244 | /// | ||
| 1245 | /// If we are producing a DSO, this field is populated if this relocation requires a runtime | ||
| 1246 | /// relocation entry. The entry will be removed if we discover a definition which allows us to | ||
| 1247 | /// statically resolve the relocation. | ||
| 1248 | rela_index: Section.RelaIndex.Optional, | 1810 | rela_index: Section.RelaIndex.Optional, |
| 1249 | result: enum(u8) { ok, overflowed, misaligned }, | 1811 | result: enum(u8) { ok, overflowed, misaligned }, |
| 1250 | 1812 | ||
| 1251 | /// Determines the section in which this relocation will be placed if it is outstanding. | 1813 | const Type = enum { abs32, abs64 }; |
| 1252 | /// | ||
| 1253 | /// When producing a relocatable (ET_REL), the relocation section is `Section.rela.shndx` for | ||
| 1254 | /// the section of `node`, and this function asserts that the aforementioned `rela.shndx` field | ||
| 1255 | /// is populated. | ||
| 1256 | /// | ||
| 1257 | /// When producing a DSO, the relocation section is always `.rela.dyn`. It is not `.rela.plt` | ||
| 1258 | /// because relocations in the GOTPLT are handled specially, without `SymbolReloc` entries. | ||
| 1259 | fn relaSection(sr: *const SymbolReloc, elf: *Elf) Section.Index { | ||
| 1260 | const shndx = switch (elf.ehdrType()) { | ||
| 1261 | .REL => elf.getNodeShndx(sr.node).get(elf).rela.shndx, | ||
| 1262 | .EXEC, .DYN => elf.shndx.rela_dyn, | ||
| 1263 | }; | ||
| 1264 | assert(shndx != .UNDEF); | ||
| 1265 | return shndx; | ||
| 1266 | } | ||
| 1267 | 1814 | ||
| 1268 | const Index = enum(u32) { | 1815 | const Index = enum(u32) { |
| 1269 | none = std.math.maxInt(u32), | 1816 | none = std.math.maxInt(u32), |
| 1270 | _, | 1817 | _, |
| 1271 | 1818 | ||
| 1272 | fn get(index: SymbolReloc.Index, elf: *Elf) *SymbolReloc { | 1819 | fn get(index: NodeReloc.Index, elf: *Elf) *NodeReloc { |
| 1273 | return &elf.symbol_relocs.items[@backingInt(index)]; | 1820 | return &elf.node_relocs.items[@backingInt(index)]; |
| 1274 | } | 1821 | } |
| 1275 | }; | 1822 | }; |
| 1276 | |||
| 1277 | /// Instead of using the ELF relocation enums, we have our own internal representation for | ||
| 1278 | /// relocation types. This representation is more compact (requiring only 16 bits), and allows | ||
| 1279 | /// sharing a lot of relocation handling between multiple relocs and target architectures. | ||
| 1280 | /// | ||
| 1281 | /// A relocation type can be "simple" or "special". | ||
| 1282 | /// | ||
| 1283 | /// "Simple" relocations are designed to cover the majority of cases. They can represent most | ||
| 1284 | /// relocations which either write 8-bit, 16-bit, 32-bit, or 64-bit integers, or which write one | ||
| 1285 | /// contiguous bit-field within such an integer (e.g. an instruction operand). For more details, | ||
| 1286 | /// see `Simple`. | ||
| 1287 | /// | ||
| 1288 | /// "Special" relocations handle anything which does not fit into the above category, such as | ||
| 1289 | /// relocations which write multiple sequences of bits or which need to do unusual arithmetic on | ||
| 1290 | /// a symbol value. The representation is simply a big enum containing all of these exceptional | ||
| 1291 | /// cases---see `Special`. This representation is in use when `Type.target == .special`. | ||
| 1292 | const Type = packed struct(u16) { | ||
| 1293 | /// Helper function for constructing a "simple" relocation type. This mainly exists to | ||
| 1294 | /// improve readability in the relocation lowering logic in `addRelocAssumeCapacity`. | ||
| 1295 | fn simple(target: Target, action: Simple) SymbolReloc.Type { | ||
| 1296 | assert(target != .special); | ||
| 1297 | return .{ .target = target, .action = .{ .simple = action } }; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | /// Helper function for constructing a "special" relocation type. This mainly exists to | ||
| 1301 | /// improve readability in the relocation lowering logic in `addRelocAssumeCapacity`. | ||
| 1302 | fn special(s: Special) SymbolReloc.Type { | ||
| 1303 | return .{ .target = .special, .action = .{ .special = s } }; | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | /// See doc comment on `Target`. | ||
| 1307 | target: Target, | ||
| 1308 | /// If `target == .special`, the `special` field is used. | ||
| 1309 | /// | ||
| 1310 | /// Otherwise, the `.simple` field is used. | ||
| 1311 | action: packed union { | ||
| 1312 | simple: Simple, | ||
| 1313 | special: Special, | ||
| 1314 | }, | ||
| 1315 | |||
| 1316 | /// If a relocation is "special", indicates that using the value `.@"special"`. | ||
| 1317 | /// | ||
| 1318 | /// Otherwise (for "simple" relocations), `Target` indicates the first step in computing the | ||
| 1319 | /// relocation---whether we care about the target symbol's absolute address, its PC-relative | ||
| 1320 | /// address, its PLT entry, etc. | ||
| 1321 | const Target = enum(u3) { | ||
| 1322 | /// This is a "special" relocation whose specific type is in the `action.special` field. | ||
| 1323 | special, | ||
| 1324 | |||
| 1325 | /// Absolute value of the target symbol. | ||
| 1326 | abs, | ||
| 1327 | /// Offset from the relocation itself to the target symbol ("PC-relative"). | ||
| 1328 | rel, | ||
| 1329 | /// Address of the target symbol's PLT entry. | ||
| 1330 | /// | ||
| 1331 | /// If the target symbol does not have a PLT entry, equivalent to `.abs`. | ||
| 1332 | pltabs, | ||
| 1333 | /// Offset from the relocation itself to the target symbol's PLT entry ("PC-relative"). | ||
| 1334 | /// | ||
| 1335 | /// If the target symbol does not have a PLT entry, equivalent to `.rel`. | ||
| 1336 | pltrel, | ||
| 1337 | /// Offset of the target TLS symbol from the base of this DSO's own TLS region. | ||
| 1338 | dtpoff, | ||
| 1339 | /// Offset of the target TLS symbol from the raw thread pointer. | ||
| 1340 | tpoff, | ||
| 1341 | /// Size of the target symbol. | ||
| 1342 | size, | ||
| 1343 | }; | ||
| 1344 | 1823 | ||
| 1345 | /// For a "simple" relocation, after the initial value is computed according to `Target`, a | 1824 | fn flushMovedNode(reloc: *NodeReloc, elf: *Elf, node_vaddr: u64) void { |
| 1346 | /// `Simple` value communicates how to shift, truncate, and store that value into memory. | 1825 | if (reloc.rela_index.unwrap()) |rela_index| { |
| 1347 | const Simple = packed struct(u13) { | 1826 | assert(elf.ehdrType() == .REL); |
| 1348 | /// The field being written to, represented as a sequence of bits in a backing integer | 1827 | // The node has moved, so the offset of the relocation within the section might have |
| 1349 | /// of 8, 16, 32, or 64 bits. | 1828 | // changed, so update the `offset` field of the `ElfN.Rela` entry. |
| 1350 | /// | 1829 | elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaSetOffset(elf, rela_index, node_vaddr + reloc.offset); |
| 1351 | /// The `.@"8"`, `.@"16"`, `.@"32"`, and `.@"64"` fields simply write to all bits of the | 1830 | } else { |
| 1352 | /// backing integer; i.e. the existing value is entirely overwritten. | 1831 | assert(elf.ehdrType() != .REL); |
| 1353 | /// | 1832 | reloc.apply(elf); |
| 1354 | /// Other fields are named like "B[H:L]", where "B" is the backing integer type, and | 1833 | } |
| 1355 | /// "H" and "L" are the indices of the highest and lowest bits in the bit field (in | 1834 | } |
| 1356 | /// other words, an inclusive bit range). This notation was chosen because it seems to | ||
| 1357 | /// be one of the more common ways that bit relocations are written in ABIs. | ||
| 1358 | /// | ||
| 1359 | /// e.g. 8[6:3] writes the relocated value to this 4-bit field in an 8-bit integer: | ||
| 1360 | /// | ||
| 1361 | /// MSB ___ ### ### ### ### ___ ___ ___ LSB | ||
| 1362 | /// 7 6 5 4 3 2 1 0 | ||
| 1363 | /// bit index | ||
| 1364 | /// | ||
| 1365 | /// This enum is not intended to be able to represent every possible bit field in the | ||
| 1366 | /// backing integer types. Instead, to keep `SymbolReloc.Type` compact, fields are added | ||
| 1367 | /// to this enum only as needed. If the enum ever becomes full, some lesser-used tags | ||
| 1368 | /// can have their handling moved into `Special` to free up space. | ||
| 1369 | dest: enum(u6) { | ||
| 1370 | @"8", | ||
| 1371 | @"16", | ||
| 1372 | @"32", | ||
| 1373 | @"64", | ||
| 1374 | 1835 | ||
| 1375 | @"32[4:0]", | 1836 | fn flushMovedTarget(reloc: *NodeReloc, elf: *Elf, target_section_offset: u64) void { |
| 1376 | @"32[5:0]", | 1837 | if (reloc.rela_index.unwrap()) |rela_index| { |
| 1377 | @"32[6:0]", | 1838 | assert(elf.ehdrType() == .REL); |
| 1378 | @"32[9:0]", | 1839 | // The target has moved, so the `addend` field of the `ElfN.Rela` entry needs to be updated. |
| 1379 | @"32[10:0]", | 1840 | elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaSetAddend(elf, rela_index, target_section_offset +% @as(u64, @bitCast(reloc.addend))); |
| 1380 | @"32[11:0]", | 1841 | } else { |
| 1381 | @"32[12:0]", | 1842 | assert(elf.ehdrType() != .REL); |
| 1382 | @"32[21:0]", | 1843 | reloc.apply(elf); |
| 1383 | @"32[21:10]", | 1844 | } |
| 1384 | @"32[24:5]", | 1845 | } |
| 1385 | @"32[25:10]", | ||
| 1386 | @"32[29:0]", | ||
| 1387 | 1846 | ||
| 1388 | /// Returns `true` iff `dest` writes a full address for the target. | 1847 | fn apply(reloc: *NodeReloc, elf: *Elf) void { |
| 1389 | /// | 1848 | const node = reloc.node.unwrap() orelse return; // deleted |
| 1390 | /// i.e. checks for `.@"32"` on 32-bit targets; for `.@"64"` on 64-bit targets. | 1849 | if (reloc.rela_index.unwrap()) |rela_index| { |
| 1391 | fn isAddr(dest: @This(), elf: *const Elf) bool { | 1850 | assert(elf.ehdrType() == .REL); |
| 1392 | return switch (elf.identClass()) { | 1851 | _ = rela_index; |
| 1393 | .NONE, _ => unreachable, | 1852 | } else { |
| 1394 | .@"32" => dest == .@"32", | 1853 | assert(elf.ehdrType() != .REL); |
| 1395 | .@"64" => dest == .@"64", | 1854 | if (node.hasMoved(&elf.mf) or reloc.target.hasMoved(&elf.mf)) { |
| 1396 | }; | 1855 | // There's no point applying the relocation now, because it will be re-applied by |
| 1397 | } | 1856 | // `flushMoved` at some point anyway. |
| 1398 | }, | 1857 | return; |
| 1858 | } | ||
| 1859 | switch (reloc.result) { | ||
| 1860 | .ok => {}, | ||
| 1861 | .overflowed => elf.overflowed_reloc_count -= 1, | ||
| 1862 | .misaligned => elf.misaligned_reloc_count -= 1, | ||
| 1863 | } | ||
| 1864 | if (reloc.applyInner(elf)) { | ||
| 1865 | @branchHint(.likely); | ||
| 1866 | reloc.result = .ok; | ||
| 1867 | } else |err| switch (err) { | ||
| 1868 | error.RelocationOverflow => { | ||
| 1869 | reloc.result = .overflowed; | ||
| 1870 | elf.overflowed_reloc_count += 1; | ||
| 1871 | }, | ||
| 1872 | error.RelocationMisaligned => { | ||
| 1873 | reloc.result = .misaligned; | ||
| 1874 | elf.misaligned_reloc_count += 1; | ||
| 1875 | }, | ||
| 1876 | } | ||
| 1877 | } | ||
| 1878 | } | ||
| 1879 | fn applyInner(reloc: *const NodeReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { | ||
| 1880 | const simple: SymbolReloc.Type.Simple = .{ .dest = switch (reloc.type) { | ||
| 1881 | .abs32 => .@"32", | ||
| 1882 | .abs64 => .@"64", | ||
| 1883 | }, .cast = .unsigned, .shift = .@"0" }; | ||
| 1884 | const addend: u64 = @bitCast(reloc.addend); | ||
| 1885 | const target_val = elf.getNodeVAddr(reloc.target) +% addend; | ||
| 1886 | const dest_slice = reloc.node.unwrap().?.slice(&elf.mf)[@intCast(reloc.offset)..]; | ||
| 1887 | try simple.write(target_val, dest_slice, elf.targetEndian()); | ||
| 1888 | } | ||
| 1399 | 1889 | ||
| 1400 | /// After the relocation value is shifted (see `shift`), it is truncated to the size of | 1890 | fn delete(reloc: *NodeReloc, elf: *Elf) void { |
| 1401 | /// the bit field (see `dest`). This field specifies whether the linker will check for, | 1891 | reloc.deleteOutputRel(elf); |
| 1402 | /// and error in the case of, truncated bits (in other words, relocation overflow). | ||
| 1403 | cast: enum(u2) { | ||
| 1404 | /// Do not perform any check when truncating unused bits. | ||
| 1405 | trunc, | ||
| 1406 | /// Error if the truncated value cannot be zero-extended back to the original value, | ||
| 1407 | /// i.e. if the truncated value is different when interpreted as unsigned. | ||
| 1408 | unsigned, | ||
| 1409 | /// Error if the truncated value cannot be sign-extended back to the original value. | ||
| 1410 | /// i.e. if the truncated value is different when interpreted as signed. | ||
| 1411 | signed, | ||
| 1412 | }, | ||
| 1413 | 1892 | ||
| 1414 | /// The relocation value (computed based on the `Target`) gets shifted to the right by | 1893 | switch (reloc.prev) { |
| 1415 | /// this amount. By default, the shifted-out bits can be anything, but tags ending in | 1894 | .none => { |
| 1416 | /// "_exact" introduce a check that the shifted-out bits are all zeroes (an error is | 1895 | const first_target_reloc = switch (elf.getNode(reloc.target)) { |
| 1417 | /// emitted if not), similar to the behavior of `@shrExact`. | 1896 | else => unreachable, |
| 1418 | shift: enum(u5) { | 1897 | .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc, |
| 1419 | @"0", | 1898 | .unit_frame_cie => |ui| &elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc, |
| 1420 | @"2_exact", | 1899 | .unit_debug_info_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_target_reloc, |
| 1421 | @"10", | 1900 | .unit_debug_line_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_target_reloc, |
| 1422 | @"12", | 1901 | .unit_debug_rnglists => |ui| &elf.dwarf_units[@backingInt(ui)].debug_rnglists_first_target_reloc, |
| 1423 | @"22", | 1902 | .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc, |
| 1424 | @"32", | 1903 | .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc, |
| 1425 | @"52", | 1904 | .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc, |
| 1905 | .decl_debug_info => |di| &elf.dwarf_decls.getPtr(di).?.debug_info_first_target_reloc, | ||
| 1906 | }; | ||
| 1907 | first_target_reloc.* = reloc.next; | ||
| 1426 | }, | 1908 | }, |
| 1909 | else => |prev| prev.get(elf).next = reloc.next, | ||
| 1910 | } | ||
| 1911 | switch (reloc.next) { | ||
| 1912 | .none => {}, | ||
| 1913 | else => |next| next.get(elf).prev = reloc.prev, | ||
| 1914 | } | ||
| 1915 | switch (reloc.result) { | ||
| 1916 | .ok => {}, | ||
| 1917 | .overflowed => elf.overflowed_reloc_count -= 1, | ||
| 1918 | .misaligned => elf.misaligned_reloc_count -= 1, | ||
| 1919 | } | ||
| 1427 | 1920 | ||
| 1428 | /// Given a value (computed based on the `Target`), applies the shift and truncation | 1921 | reloc.* = undefined; |
| 1429 | /// operations specified by `s`, then writes the result to the start of `dest_slice` as | 1922 | reloc.node = .none; |
| 1430 | /// specified by `s.dest`. | 1923 | } |
| 1431 | fn write( | ||
| 1432 | s: Simple, | ||
| 1433 | val: u64, | ||
| 1434 | dest_slice: []u8, | ||
| 1435 | target_endian: std.lang.Endian, | ||
| 1436 | ) error{ RelocationMisaligned, RelocationOverflow }!void { | ||
| 1437 | const shift: u6, const shift_exact: bool = switch (s.shift) { | ||
| 1438 | .@"0" => .{ 0, false }, | ||
| 1439 | .@"2_exact" => .{ 2, true }, | ||
| 1440 | .@"10" => .{ 10, false }, | ||
| 1441 | .@"12" => .{ 12, false }, | ||
| 1442 | .@"22" => .{ 22, false }, | ||
| 1443 | .@"32" => .{ 32, false }, | ||
| 1444 | .@"52" => .{ 52, false }, | ||
| 1445 | }; | ||
| 1446 | 1924 | ||
| 1447 | if (shift_exact and (val >> shift) << shift != val) { | 1925 | /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation. |
| 1448 | return error.RelocationMisaligned; | 1926 | fn deleteOutputRel(reloc: *NodeReloc, elf: *Elf) void { |
| 1449 | } | 1927 | const rela_index = reloc.rela_index.unwrap() orelse return; |
| 1928 | assert(elf.ehdrType() == .REL); | ||
| 1929 | elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaDeleteOne(elf, rela_index); | ||
| 1930 | reloc.rela_index = .none; | ||
| 1931 | } | ||
| 1932 | }; | ||
| 1450 | 1933 | ||
| 1451 | const dest_word_bits: u8, const dest_high_bit: u6, const dest_low_bit: u6 = switch (s.dest) { | 1934 | /// Identifies a single entry in the GOT. |
| 1452 | // zig fmt: off | 1935 | const GotKey = union(enum) { |
| 1453 | .@"8" => .{ 8, 7, 0 }, | 1936 | /// The entry is a reserved word, initialized to zero. `initHeaders` will add as many of these |
| 1454 | .@"16" => .{ 16, 15, 0 }, | 1937 | /// as the target machine ABI requires. |
| 1455 | .@"32" => .{ 32, 31, 0 }, | 1938 | /// |
| 1456 | .@"64" => .{ 64, 63, 0 }, | 1939 | /// This `u32` value exists to allow reserving multiple words with distinct keys. |
| 1457 | .@"32[4:0]" => .{ 32, 4, 0 }, | 1940 | reserved: u32, |
| 1458 | .@"32[5:0]" => .{ 32, 5, 0 }, | ||
| 1459 | .@"32[6:0]" => .{ 32, 6, 0 }, | ||
| 1460 | .@"32[9:0]" => .{ 32, 9, 0 }, | ||
| 1461 | .@"32[10:0]" => .{ 32, 10, 0 }, | ||
| 1462 | .@"32[11:0]" => .{ 32, 11, 0 }, | ||
| 1463 | .@"32[12:0]" => .{ 32, 12, 0 }, | ||
| 1464 | .@"32[21:0]" => .{ 32, 21, 0 }, | ||
| 1465 | .@"32[21:10]" => .{ 32, 21, 10 }, | ||
| 1466 | .@"32[24:5]" => .{ 32, 24, 5 }, | ||
| 1467 | .@"32[25:10]" => .{ 32, 25, 10 }, | ||
| 1468 | .@"32[29:0]" => .{ 32, 29, 0 }, | ||
| 1469 | // zig fmt: on | ||
| 1470 | }; | ||
| 1471 | 1941 | ||
| 1472 | // The number of bits we are truncating from the full 64-bit relocation value. | 1942 | /// Value is the address of the given symbol. |
| 1473 | const trunc_bits: u6 = 63 - dest_high_bit + dest_low_bit; | 1943 | symbol: Symbol.Id, |
| 1474 | 1944 | ||
| 1475 | // When we shift, whether we do an arithmetic or logical shift depends on what cast | 1945 | /// Value is the signed offset of the given symbol from the TLS pointer. |
| 1476 | // behavior we are going to use. If we'll be doing a signed int cast, we must shift | 1946 | tpoff: Symbol.Id, |
| 1477 | // in sign bits so that we don't incorrectly cause a failure, and vice versa for an | ||
| 1478 | // unsigned int cast. Either is fine when truncating (here we pick logical shift). | ||
| 1479 | const shifted_val: u64 = switch (s.cast) { | ||
| 1480 | .trunc => val >> shift, | ||
| 1481 | inline else => |cast| shifted: { | ||
| 1482 | const ShiftInt = if (cast == .signed) i64 else u64; | ||
| 1483 | const x: ShiftInt = @bitCast(val); | ||
| 1484 | const shifted: ShiftInt = x >> shift; | ||
| 1485 | 1947 | ||
| 1486 | if ((shifted << trunc_bits) >> trunc_bits != shifted) { | 1948 | /// Value is the TLS module ID of the DSO we are creating. |
| 1487 | return error.RelocationOverflow; | 1949 | /// |
| 1488 | } | 1950 | /// Used for the first of the two GOT entries generated by a TLSLD relocation. |
| 1951 | tlsld0, | ||
| 1952 | /// Value is always 0. | ||
| 1953 | /// | ||
| 1954 | /// Used for the second of the two GOT entries generated by a TLSLD relocation. | ||
| 1955 | tlsld1, | ||
| 1489 | 1956 | ||
| 1490 | break :shifted @bitCast(shifted); | 1957 | /// Value is the TLS module ID for the given STT_TLS symbol. |
| 1491 | }, | 1958 | /// |
| 1492 | }; | 1959 | /// Used for the first of the two GOT entries generated by a TLSGD relocation. |
| 1960 | tlsgd0: Symbol.Id, | ||
| 1961 | /// Value is the offset of the given STT_TLS symbol from the base of the per-module TLS area. | ||
| 1962 | /// | ||
| 1963 | /// Used for the second of the two GOT entries generated by a TLSGD relocation. | ||
| 1964 | tlsgd1: Symbol.Id, | ||
| 1965 | }; | ||
| 1493 | 1966 | ||
| 1494 | // Create a bit-mask for the field being populated, e.g. 8[3:1] -> 0b00001110 | 1967 | /// A relocation targeting a particular GOT entry. |
| 1495 | const field_mask = (~@as(u64, 0) >> trunc_bits) << dest_low_bit; | 1968 | const GotReloc = struct { |
| 1969 | /// The node containing this relocation. Possible values are: | ||
| 1970 | /// * An input section | ||
| 1971 | /// * A section | ||
| 1972 | /// * A NAV, UAV, or lazy code/data | ||
| 1973 | /// * `.none`, if this relocation was deleted (in which case it should be ignored) | ||
| 1974 | node: MappedFile.Node.Index.Optional, | ||
| 1975 | /// The offset of the relocation inside of `node`. | ||
| 1976 | offset: u64, | ||
| 1977 | target: GotKey, | ||
| 1978 | addend: i64, | ||
| 1979 | type: GotReloc.Type, | ||
| 1980 | result: enum(u8) { ok, overflowed, misaligned }, | ||
| 1496 | 1981 | ||
| 1497 | // Shift and mask the value to be in the correct bits, leaving the others zeroed. | 1982 | /// `GotReloc.Type` has the same structure as `SymbolReloc.Type`, just with different `Target` |
| 1498 | const masked_field: u64 = (shifted_val << dest_low_bit) & field_mask; | 1983 | /// and `Special` enums---consult doc comments on `SymbolReloc.Type` for an overview. |
| 1984 | const Type = packed struct(u16) { | ||
| 1985 | fn simple(target: Target, action: Simple) GotReloc.Type { | ||
| 1986 | assert(target != .special); | ||
| 1987 | return .{ .target = target, .action = .{ .simple = action } }; | ||
| 1988 | } | ||
| 1499 | 1989 | ||
| 1500 | // Now we just need to actually apply the relocation by loading a word, replacing | 1990 | fn special(s: Special) GotReloc.Type { |
| 1501 | // the field bits with those in `masked_field`, and storing the result back. | 1991 | return .{ .target = .special, .action = .{ .special = s } }; |
| 1502 | switch (dest_word_bits) { | 1992 | } |
| 1503 | inline 8, 16, 32, 64 => |bits| { | 1993 | |
| 1504 | const word_slice = dest_slice[0..@divExact(bits, 8)]; | 1994 | target: Target, |
| 1505 | const Int = @Int(.unsigned, bits); | 1995 | action: packed union { |
| 1506 | const old: u64 = std.mem.readInt(Int, word_slice, target_endian); | 1996 | simple: Simple, |
| 1507 | const new: u64 = (old & ~field_mask) | masked_field; | 1997 | special: Special, |
| 1508 | std.mem.writeInt(Int, word_slice, @intCast(new), target_endian); | 1998 | }, |
| 1509 | }, | 1999 | |
| 1510 | else => unreachable, | 2000 | /// Like `SymbolReloc.Target`, but for GOT relocations. There are fewer tags because there |
| 1511 | } | 2001 | /// are fewer different kinds of GOT relocation. |
| 1512 | } | 2002 | const Target = enum(u3) { |
| 2003 | /// This is a "special" relocation whose specific type is in the `action.special` field. | ||
| 2004 | special, | ||
| 2005 | |||
| 2006 | /// Absolute address of the GOT entry. | ||
| 2007 | abs, | ||
| 2008 | /// Offset from the relocation itself to the GOT entry ("PC-relative"). | ||
| 2009 | rel, | ||
| 2010 | /// Offset from the base of the GOT to the GOT entry. | ||
| 2011 | offset, | ||
| 1513 | }; | 2012 | }; |
| 1514 | 2013 | ||
| 1515 | /// Enum representing "special" relocation types, i.e. those which cannot be represented | 2014 | const Simple = SymbolReloc.Type.Simple; |
| 1516 | /// just with `Target` and `Simple`. These relocations have completely custom handling in | 2015 | |
| 1517 | /// the `Special.applyInner` function. | 2016 | /// Like `SymbolReloc.Special`, but for GOT relocations. |
| 1518 | const Special = enum(u13) { | 2017 | const Special = enum(u13) { |
| 1519 | larch_pcala_hi20, | 2018 | larch_pcala_hi20, |
| 1520 | larch_pcala64_lo20, | 2019 | larch_pcala64_lo20, |
| 1521 | larch_pcala64_hi12, | 2020 | larch_pcala64_hi12, |
| 1522 | larch_b21, | ||
| 1523 | larch_b26, | ||
| 1524 | larch_call36, | ||
| 1525 | 2021 | ||
| 1526 | sparc_le_hix22, | 2022 | sparc_op_lox10, |
| 2023 | sparc_op_hix22, | ||
| 1527 | 2024 | ||
| 1528 | fn applyInner( | 2025 | fn applyInner( |
| 1529 | s: Special, | 2026 | s: Special, |
| 1530 | elf: *Elf, | 2027 | elf: *Elf, |
| 1531 | target: Symbol.Id, | 2028 | got_vaddr: u64, |
| 2029 | got_offset: u64, | ||
| 1532 | addend: u64, | 2030 | addend: u64, |
| 1533 | dest_vaddr: u64, | 2031 | dest_vaddr: u64, |
| 1534 | dest_slice: []u8, | 2032 | dest_slice: []u8, |
| 1535 | ) error{ RelocationMisaligned, RelocationOverflow }!void { | 2033 | ) error{ RelocationMisaligned, RelocationOverflow }!void { |
| 1536 | switch (s) { | 2034 | switch (s) { |
| 1537 | .larch_pcala_hi20 => { | 2035 | .larch_pcala_hi20 => { |
| 1538 | const val = target.value(elf) +% addend; | 2036 | const val = got_vaddr +% got_offset +% addend; |
| 1539 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | 2037 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| 1540 | elf.targetStore(inst, .{ | 2038 | elf.targetStore(inst, .{ |
| 1541 | .b0_4 = elf.targetLoad(inst).b0_4, | 2039 | .b0_4 = elf.targetLoad(inst).b0_4, |
| ... | @@ -1544,7 +2042,7 @@ const SymbolReloc = struct { | ... | @@ -1544,7 +2042,7 @@ const SymbolReloc = struct { |
| 1544 | }); | 2042 | }); |
| 1545 | }, | 2043 | }, |
| 1546 | .larch_pcala64_lo20 => { | 2044 | .larch_pcala64_lo20 => { |
| 1547 | const val = target.value(elf) +% addend; | 2045 | const val = got_vaddr +% got_offset +% addend; |
| 1548 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | 2046 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| 1549 | elf.targetStore(inst, .{ | 2047 | elf.targetStore(inst, .{ |
| 1550 | .b0_4 = elf.targetLoad(inst).b0_4, | 2048 | .b0_4 = elf.targetLoad(inst).b0_4, |
| ... | @@ -1553,7 +2051,7 @@ const SymbolReloc = struct { | ... | @@ -1553,7 +2051,7 @@ const SymbolReloc = struct { |
| 1553 | }); | 2051 | }); |
| 1554 | }, | 2052 | }, |
| 1555 | .larch_pcala64_hi12 => { | 2053 | .larch_pcala64_hi12 => { |
| 1556 | const val = target.value(elf) +% addend; | 2054 | const val = got_vaddr +% got_offset +% addend; |
| 1557 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); | 2055 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); |
| 1558 | elf.targetStore(inst, .{ | 2056 | elf.targetStore(inst, .{ |
| 1559 | .b0_9 = elf.targetLoad(inst).b0_9, | 2057 | .b0_9 = elf.targetLoad(inst).b0_9, |
| ... | @@ -1561,127 +2059,44 @@ const SymbolReloc = struct { | ... | @@ -1561,127 +2059,44 @@ const SymbolReloc = struct { |
| 1561 | .b22_31 = elf.targetLoad(inst).b22_31, | 2059 | .b22_31 = elf.targetLoad(inst).b22_31, |
| 1562 | }); | 2060 | }); |
| 1563 | }, | 2061 | }, |
| 1564 | .larch_b21, .larch_b26, .larch_call36 => { | 2062 | .sparc_op_lox10 => { |
| 1565 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target) orelse target.value(elf); | 2063 | const dest_ptr: *align(1) packed struct(u32) { |
| 1566 | const jump_offset: i64 = @bitCast(target_vaddr +% addend -% dest_vaddr); | 2064 | imm13: u13, |
| 1567 | if ((jump_offset >> 2) << 2 != jump_offset) { | 2065 | b13_31: u19, |
| 1568 | return error.RelocationMisaligned; | 2066 | } = @ptrCast(dest_slice); |
| 1569 | } | 2067 | elf.targetStore(dest_ptr, .{ |
| 1570 | const shifted_jump_offset: i64 = @shrExact(jump_offset, 2); | 2068 | .imm13 = @as(u10, @truncate(got_offset)), |
| 1571 | switch (s) { | 2069 | .b13_31 = elf.targetLoad(dest_ptr).b13_31, |
| 1572 | .larch_b21 => { | 2070 | }); |
| 1573 | if ((shifted_jump_offset << (64 - 21)) >> (64 - 21) != shifted_jump_offset) { | ||
| 1574 | return error.RelocationOverflow; | ||
| 1575 | } | ||
| 1576 | const truncated: i21 = @intCast(shifted_jump_offset); | ||
| 1577 | const parts: packed struct { lo16: u16, hi5: u5 } = @bitCast(truncated); | ||
| 1578 | const inst: *align(1) link.loongarch.D5K16 = @ptrCast(dest_slice[0..4]); | ||
| 1579 | elf.targetStore(inst, .{ | ||
| 1580 | .d5 = parts.hi5, | ||
| 1581 | .b5_9 = elf.targetLoad(inst).b5_9, | ||
| 1582 | .k16 = parts.lo16, | ||
| 1583 | .b26_31 = elf.targetLoad(inst).b26_31, | ||
| 1584 | }); | ||
| 1585 | }, | ||
| 1586 | .larch_b26 => { | ||
| 1587 | if ((shifted_jump_offset << (64 - 26)) >> (64 - 26) != shifted_jump_offset) { | ||
| 1588 | return error.RelocationOverflow; | ||
| 1589 | } | ||
| 1590 | const truncated: i26 = @intCast(shifted_jump_offset); | ||
| 1591 | const parts: packed struct { lo16: u16, hi10: u10 } = @bitCast(truncated); | ||
| 1592 | const inst: *align(1) link.loongarch.D10K16 = @ptrCast(dest_slice[0..4]); | ||
| 1593 | elf.targetStore(inst, .{ | ||
| 1594 | .d10 = parts.hi10, | ||
| 1595 | .k16 = parts.lo16, | ||
| 1596 | .b26_31 = elf.targetLoad(inst).b26_31, | ||
| 1597 | }); | ||
| 1598 | }, | ||
| 1599 | .larch_call36 => { | ||
| 1600 | // The allowed range of destination addresses here is non-trivial: | ||
| 1601 | // [PC - 128 GiB - 0x20_000, PC + 128 GiB - 0x20_000 - 4] | ||
| 1602 | const gib = 1024 * 1024 * 1024; | ||
| 1603 | if (jump_offset < -128 * gib - 0x20_000 or | ||
| 1604 | jump_offset > 128 * gib - 0x20_000 - 4) | ||
| 1605 | { | ||
| 1606 | return error.RelocationOverflow; | ||
| 1607 | } | ||
| 1608 | // The values we write into the instructions are a little weird too: | ||
| 1609 | const hi: i20 = @intCast((shifted_jump_offset +% 0x8000) >> 16); | ||
| 1610 | const lo: i16 = @truncate(shifted_jump_offset); | ||
| 1611 | |||
| 1612 | const inst0: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | ||
| 1613 | const inst1: *align(1) link.loongarch.K16 = @ptrCast(dest_slice[4..8]); | ||
| 1614 | |||
| 1615 | const old0 = elf.targetLoad(inst0); | ||
| 1616 | elf.targetStore(inst0, .{ .b0_4 = old0.b0_4, .j20 = @bitCast(hi), .b25_31 = old0.b25_31 }); | ||
| 1617 | |||
| 1618 | const old1 = elf.targetLoad(inst1); | ||
| 1619 | elf.targetStore(inst1, .{ .b0_9 = old1.b0_9, .k16 = @bitCast(lo), .b26_31 = old1.b26_31 }); | ||
| 1620 | }, | ||
| 1621 | else => unreachable, | ||
| 1622 | } | ||
| 1623 | }, | 2071 | }, |
| 1624 | .sparc_le_hix22 => { | 2072 | .sparc_op_hix22 => { |
| 1625 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; | ||
| 1626 | const tls_size: u64 = switch (elf.phdrSlice()) { | ||
| 1627 | inline else => |phdr| tls_size: { | ||
| 1628 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); | ||
| 1629 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); | ||
| 1630 | }, | ||
| 1631 | }; | ||
| 1632 | const dest_ptr: *align(1) packed struct(u32) { | 2073 | const dest_ptr: *align(1) packed struct(u32) { |
| 1633 | imm22: u22, | 2074 | imm22: u22, |
| 1634 | b22_31: u10, | 2075 | b22_31: u10, |
| 1635 | } = @ptrCast(dest_slice); | 2076 | } = @ptrCast(dest_slice); |
| 1636 | elf.targetStore(dest_ptr, .{ | 2077 | elf.targetStore(dest_ptr, .{ |
| 1637 | .imm22 = @truncate(~(target.value(elf) +% addend -% tls_size) >> 10), | 2078 | .imm22 = @truncate(got_offset >> 10), |
| 1638 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, | 2079 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, |
| 1639 | }); | 2080 | }); |
| 1640 | }, | 2081 | }, |
| 1641 | } | 2082 | } |
| 1642 | } | 2083 | } |
| 1643 | }; | 2084 | }; |
| 2085 | }; | ||
| 1644 | 2086 | ||
| 1645 | fn dependsOnTlsSize(t: SymbolReloc.Type, elf: *const Elf) bool { | 2087 | const Index = enum(u32) { |
| 1646 | return switch (elf.targetTlsVariant()) { | 2088 | none = std.math.maxInt(u32), |
| 1647 | // In TLS variant I, the executable's TLS block starts at a fixed offset from the | 2089 | _, |
| 1648 | // thread pointer, so everything is fine... | ||
| 1649 | .I_original, .I_modified => false, | ||
| 1650 | // ...but in variant II, the executable's TLS block *ends* at a fixed offset from | ||
| 1651 | // the thread pointer, so the offset from the thread pointer to the *start* of the | ||
| 1652 | // TLS block depends on the size of the block, and we need that offset to resolve | ||
| 1653 | // 'tpoff' relocations. | ||
| 1654 | .II => switch (t.target) { | ||
| 1655 | .abs, | ||
| 1656 | .rel, | ||
| 1657 | .pltabs, | ||
| 1658 | .pltrel, | ||
| 1659 | .dtpoff, | ||
| 1660 | .size, | ||
| 1661 | => false, | ||
| 1662 | |||
| 1663 | .tpoff => true, | ||
| 1664 | |||
| 1665 | .special => switch (t.action.special) { | ||
| 1666 | .sparc_le_hix22, | ||
| 1667 | => true, | ||
| 1668 | 2090 | ||
| 1669 | .larch_pcala_hi20, | 2091 | fn get(index: GotReloc.Index, elf: *Elf) *GotReloc { |
| 1670 | .larch_pcala64_lo20, | 2092 | return &elf.got_relocs.items[@backingInt(index)]; |
| 1671 | .larch_pcala64_hi12, | ||
| 1672 | .larch_b21, | ||
| 1673 | .larch_b26, | ||
| 1674 | .larch_call36, | ||
| 1675 | => false, | ||
| 1676 | }, | ||
| 1677 | }, | ||
| 1678 | }; | ||
| 1679 | } | 2093 | } |
| 1680 | }; | 2094 | }; |
| 1681 | 2095 | ||
| 1682 | fn apply(reloc: *SymbolReloc, elf: *Elf) void { | 2096 | fn apply(reloc: *GotReloc, elf: *Elf) void { |
| 1683 | assert(elf.ehdrType() != .REL); | 2097 | assert(elf.ehdrType() != .REL); |
| 1684 | if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) { | 2098 | const node = reloc.node.unwrap() orelse return; // deleted |
| 2099 | if (node.hasMoved(&elf.mf) or elf.shndx.got.get(elf).ni.hasMoved(&elf.mf)) { | ||
| 1685 | // There's no point applying the relocation now, because it will be re-applied by | 2100 | // There's no point applying the relocation now, because it will be re-applied by |
| 1686 | // `flushMoved` at some point anyway. | 2101 | // `flushMoved` at some point anyway. |
| 1687 | return; | 2102 | return; |
| ... | @@ -1705,118 +2120,99 @@ const SymbolReloc = struct { | ... | @@ -1705,118 +2120,99 @@ const SymbolReloc = struct { |
| 1705 | }, | 2120 | }, |
| 1706 | } | 2121 | } |
| 1707 | } | 2122 | } |
| 1708 | fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { | 2123 | fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { |
| 1709 | const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset; | 2124 | const node = reloc.node.unwrap().?; |
| 1710 | const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; | 2125 | const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset; |
| 2126 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; | ||
| 1711 | 2127 | ||
| 2128 | const got_vaddr = elf.shndx.got.vaddr(elf); | ||
| 2129 | const got_index: u64 = elf.got.getIndex(reloc.target).?; | ||
| 2130 | const got_offset: u64 = switch (elf.identClass()) { | ||
| 2131 | .NONE, _ => unreachable, | ||
| 2132 | inline else => |class| @sizeOf(class.ElfN().Addr) * got_index, | ||
| 2133 | }; | ||
| 1712 | const addend: u64 = @bitCast(reloc.addend); | 2134 | const addend: u64 = @bitCast(reloc.addend); |
| 1713 | const target_val: u64 = type: switch (reloc.type.target) { | 2135 | |
| 1714 | .abs => reloc.target.value(elf) +% addend, | 2136 | const target_val: u64 = switch (reloc.type.target) { |
| 1715 | .rel => reloc.target.value(elf) +% addend -% dest_vaddr, | 2137 | .abs => got_vaddr +% got_offset +% addend, |
| 1716 | .pltabs => { | 2138 | .rel => got_vaddr +% got_offset +% addend -% dest_vaddr, |
| 1717 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .abs; | 2139 | .offset => got_offset +% addend, |
| 1718 | break :type plt_entry_addr +% addend; | ||
| 1719 | }, | ||
| 1720 | .pltrel => { | ||
| 1721 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .rel; | ||
| 1722 | break :type plt_entry_addr +% addend -% dest_vaddr; | ||
| 1723 | }, | ||
| 1724 | .dtpoff => reloc.target.value(elf) +% addend, | ||
| 1725 | .tpoff => switch (elf.targetTlsVariant()) { | ||
| 1726 | .I_original => |tls| tls.tcb_size +% reloc.target.value(elf) +% addend, | ||
| 1727 | .I_modified => |tls| 0 -% tls.tp_off +% reloc.target.value(elf) +% addend, | ||
| 1728 | .II => { | ||
| 1729 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; | ||
| 1730 | const tls_size: u64 = switch (elf.phdrSlice()) { | ||
| 1731 | inline else => |phdr| tls_size: { | ||
| 1732 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); | ||
| 1733 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); | ||
| 1734 | }, | ||
| 1735 | }; | ||
| 1736 | break :type reloc.target.value(elf) +% addend -% tls_size; | ||
| 1737 | }, | ||
| 1738 | }, | ||
| 1739 | .size => switch (elf.symPtr(reloc.target.index(elf))) { | ||
| 1740 | inline else => |sym| elf.targetLoad(&sym.size), | ||
| 1741 | }, | ||
| 1742 | .special => return reloc.type.action.special.applyInner( | 2140 | .special => return reloc.type.action.special.applyInner( |
| 1743 | elf, | 2141 | elf, |
| 1744 | reloc.target, | 2142 | got_vaddr, |
| 2143 | got_offset, | ||
| 1745 | addend, | 2144 | addend, |
| 1746 | dest_vaddr, | 2145 | dest_vaddr, |
| 1747 | dest_slice, | 2146 | dest_slice, |
| 1748 | ), | 2147 | ), |
| 1749 | }; | 2148 | }; |
| 2149 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | ||
| 2150 | } | ||
| 1750 | 2151 | ||
| 1751 | // Check for the `R_*_RELATIVE` case now, because it is possible only when no shift or cast | 2152 | fn delete(reloc: *GotReloc, elf: *Elf) void { |
| 1752 | // is required, meaning we can handle it now and return early. | 2153 | switch (reloc.result) { |
| 1753 | if (reloc.rela_index.unwrap()) |rela_index| switch (elf.classifySymbolValue(reloc.target)) { | 2154 | .ok => {}, |
| 1754 | .static => unreachable, | 2155 | .overflowed => elf.overflowed_reloc_count -= 1, |
| 1755 | .dynamic => return, // the relocation happens at runtime | 2156 | .misaligned => elf.misaligned_reloc_count -= 1, |
| 1756 | .static_relative => { | 2157 | } |
| 1757 | // We have emitted an R_*_RELATIVE relocation to help lower an absolute-address | 2158 | reloc.* = .{ |
| 1758 | // relocation. The value computed above is valid, but instead of writing it to the | 2159 | .node = .none, |
| 1759 | // destination slice, we actually want to write it to the runtime relocation entry. | 2160 | .offset = undefined, |
| 1760 | switch (elf.identClass()) { | 2161 | .target = undefined, |
| 1761 | .NONE, _ => unreachable, | 2162 | .addend = undefined, |
| 1762 | .@"32" => assert(reloc.type.action.simple.dest == .@"32"), | 2163 | .type = undefined, |
| 1763 | .@"64" => assert(reloc.type.action.simple.dest == .@"64"), | 2164 | .result = undefined, |
| 1764 | } | 2165 | }; |
| 1765 | assert(reloc.type.action.simple.cast == .unsigned); | 2166 | } |
| 1766 | assert(reloc.type.action.simple.shift == .@"0"); | 2167 | }; |
| 1767 | elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, target_val); | 2168 | |
| 1768 | return; | 2169 | fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void { |
| 1769 | }, | 2170 | const gpa = elf.base.comp.gpa; |
| 2171 | |||
| 2172 | try elf.symtab.ensureUnusedCapacity(gpa, len); | ||
| 2173 | |||
| 2174 | // If adding locals, we may need to move one global out of the way for each local. If adding | ||
| 2175 | // globals, they could all get demoted to STB_LOCAL, meaning we have to move N other globals | ||
| 2176 | // around to keep `.dynsym` compact. Either way, the maximum is N. | ||
| 2177 | try elf.changed_symtab_index.ensureUnusedCapacity(gpa, len); | ||
| 2178 | |||
| 2179 | { | ||
| 2180 | // Ensure the symtab section's node is big enough | ||
| 2181 | const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) { | ||
| 2182 | inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym), | ||
| 1770 | }; | 2183 | }; |
| 1771 | 2184 | try Section.Index.symtab.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_node_size); | |
| 1772 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | ||
| 1773 | } | 2185 | } |
| 1774 | 2186 | ||
| 1775 | fn delete(reloc: *SymbolReloc, elf: *Elf, index: SymbolReloc.Index) void { | 2187 | switch (kind) { |
| 1776 | assert(index.get(elf) == reloc); | 2188 | .all_local => {}, |
| 2189 | .maybe_global => { | ||
| 2190 | try elf.globals.strong_def.ensureUnusedCapacity(gpa, len); | ||
| 2191 | try elf.globals.weak_def.ensureUnusedCapacity(gpa, len); | ||
| 2192 | try elf.globals.strong_undef.ensureUnusedCapacity(gpa, len); | ||
| 2193 | try elf.globals.weak_undef.ensureUnusedCapacity(gpa, len); | ||
| 1777 | 2194 | ||
| 1778 | reloc.deleteOutputRel(elf); | 2195 | try elf.node_global_symbols.ensureUnusedCapacity(gpa, len); |
| 1779 | if (reloc.type.dependsOnTlsSize(elf)) { | ||
| 1780 | assert(elf.tls_size_symbol_relocs.swapRemove(index)); | ||
| 1781 | } | ||
| 1782 | 2196 | ||
| 1783 | switch (reloc.prev) { | 2197 | if (elf.shndx.dynsym != .UNDEF) { |
| 1784 | .none => { | 2198 | const dynsym_cur_size: u64, const dynsym_ent_size: u32 = switch (elf.shdrPtr(elf.shndx.dynsym)) { |
| 1785 | const target_ptr = reloc.target.index(elf).ptr(elf); | 2199 | inline else => |shdr, class| .{ |
| 1786 | assert(target_ptr.first_target_reloc == index); | 2200 | elf.targetLoad(&shdr.size), |
| 1787 | target_ptr.first_target_reloc = reloc.next; | 2201 | @sizeOf(class.ElfN().Sym), |
| 1788 | }, | 2202 | }, |
| 1789 | else => |prev| prev.get(elf).next = reloc.next, | 2203 | }; |
| 1790 | } | 2204 | const dynsym_cur_len: u32 = @intCast(@divExact(dynsym_cur_size, dynsym_ent_size)); |
| 1791 | switch (reloc.next) { | ||
| 1792 | .none => {}, | ||
| 1793 | else => |next| next.get(elf).prev = reloc.prev, | ||
| 1794 | } | ||
| 1795 | switch (reloc.result) { | ||
| 1796 | .ok => {}, | ||
| 1797 | .overflowed => elf.overflowed_reloc_count -= 1, | ||
| 1798 | .misaligned => elf.misaligned_reloc_count -= 1, | ||
| 1799 | } | ||
| 1800 | 2205 | ||
| 1801 | reloc.* = undefined; | 2206 | const dynsym_need_size: u64 = (dynsym_cur_len + len) * dynsym_ent_size; |
| 1802 | } | 2207 | try elf.shndx.dynsym.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, dynsym_need_size); |
| 1803 | 2208 | ||
| 1804 | /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation, updating | 2209 | try elf.ensureDynsymHashCapacity(dynsym_cur_len + len); |
| 1805 | /// `elf.textrel_count` if necessary. | 2210 | |
| 1806 | fn deleteOutputRel(reloc: *SymbolReloc, elf: *Elf) void { | 2211 | try elf.ensureUnusedPltCapacity(len); |
| 1807 | const rela_index = reloc.rela_index.unwrap() orelse return; | 2212 | } |
| 1808 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); | 2213 | }, |
| 1809 | switch (elf.ehdrType()) { | ||
| 1810 | .REL => {}, | ||
| 1811 | .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node)) { | ||
| 1812 | .no => unreachable, // there *was* a dynamic relocation! | ||
| 1813 | .yes => {}, | ||
| 1814 | .yes_textrel => elf.textrel_count -= 1, | ||
| 1815 | }, | ||
| 1816 | } | ||
| 1817 | reloc.rela_index = .none; | ||
| 1818 | } | 2214 | } |
| 1819 | }; | 2215 | } |
| 1820 | 2216 | ||
| 1821 | fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { | 2217 | fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { |
| 1822 | const gpa = elf.base.comp.gpa; | 2218 | const gpa = elf.base.comp.gpa; |
| ... | @@ -1841,7 +2237,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { | ... | @@ -1841,7 +2237,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { |
| 1841 | // We don't need to add any buckets, but we still need to make sure the section is large | 2237 | // We don't need to add any buckets, but we still need to make sure the section is large |
| 1842 | // enough to fit `max_dynsym_count` chains. | 2238 | // enough to fit `max_dynsym_count` chains. |
| 1843 | const need_size = @sizeOf(info.Header()) + (nbucket + max_dynsym_count) * 4; | 2239 | const need_size = @sizeOf(info.Header()) + (nbucket + max_dynsym_count) * 4; |
| 1844 | try elf.shndx.hash.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size); | 2240 | try elf.shndx.hash.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size); |
| 1845 | return; | 2241 | return; |
| 1846 | } | 2242 | } |
| 1847 | // We need more buckets, so we'll have to rebuild the hash table. | 2243 | // We need more buckets, so we'll have to rebuild the hash table. |
| ... | @@ -1853,7 +2249,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { | ... | @@ -1853,7 +2249,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { |
| 1853 | 2249 | ||
| 1854 | { | 2250 | { |
| 1855 | const need_size = @sizeOf(info.Header()) + (new_nbucket + max_dynsym_count) * 4; | 2251 | const need_size = @sizeOf(info.Header()) + (new_nbucket + max_dynsym_count) * 4; |
| 1856 | try elf.shndx.hash.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size); | 2252 | try elf.shndx.hash.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size); |
| 1857 | } | 2253 | } |
| 1858 | 2254 | ||
| 1859 | elf.mf.nodes_lock.lock(); | 2255 | elf.mf.nodes_lock.lock(); |
| ... | @@ -1984,53 +2380,6 @@ fn clearDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { | ... | @@ -1984,53 +2380,6 @@ fn clearDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { |
| 1984 | } | 2380 | } |
| 1985 | } | 2381 | } |
| 1986 | 2382 | ||
| 1987 | fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void { | ||
| 1988 | const gpa = elf.base.comp.gpa; | ||
| 1989 | |||
| 1990 | try elf.symtab.ensureUnusedCapacity(gpa, len); | ||
| 1991 | |||
| 1992 | // If adding locals, we may need to move one global out of the way for each local. If adding | ||
| 1993 | // globals, they could all get demoted to STB_LOCAL, meaning we have to move N other globals | ||
| 1994 | // around to keep `.dynsym` compact. Either way, the maximum is N. | ||
| 1995 | try elf.changed_symtab_index.ensureUnusedCapacity(gpa, len); | ||
| 1996 | |||
| 1997 | { | ||
| 1998 | // Ensure the symtab section's node is big enough | ||
| 1999 | const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) { | ||
| 2000 | inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym), | ||
| 2001 | }; | ||
| 2002 | try Section.Index.symtab.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_node_size); | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | switch (kind) { | ||
| 2006 | .all_local => {}, | ||
| 2007 | .maybe_global => { | ||
| 2008 | try elf.globals.strong_def.ensureUnusedCapacity(gpa, len); | ||
| 2009 | try elf.globals.weak_def.ensureUnusedCapacity(gpa, len); | ||
| 2010 | try elf.globals.strong_undef.ensureUnusedCapacity(gpa, len); | ||
| 2011 | try elf.globals.weak_undef.ensureUnusedCapacity(gpa, len); | ||
| 2012 | |||
| 2013 | try elf.node_global_symbols.ensureUnusedCapacity(gpa, len); | ||
| 2014 | |||
| 2015 | if (elf.shndx.dynsym != .UNDEF) { | ||
| 2016 | const dynsym_cur_size: u64, const dynsym_ent_size: u32 = switch (elf.shdrPtr(elf.shndx.dynsym)) { | ||
| 2017 | inline else => |shdr, class| .{ | ||
| 2018 | elf.targetLoad(&shdr.size), | ||
| 2019 | @sizeOf(class.ElfN().Sym), | ||
| 2020 | }, | ||
| 2021 | }; | ||
| 2022 | const dynsym_cur_len: u32 = @intCast(@divExact(dynsym_cur_size, dynsym_ent_size)); | ||
| 2023 | |||
| 2024 | const dynsym_need_size: u64 = (dynsym_cur_len + len) * dynsym_ent_size; | ||
| 2025 | try elf.shndx.dynsym.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, dynsym_need_size); | ||
| 2026 | |||
| 2027 | try elf.ensureDynsymHashCapacity(dynsym_cur_len + len); | ||
| 2028 | |||
| 2029 | try elf.ensureUnusedPltCapacity(len); | ||
| 2030 | } | ||
| 2031 | }, | ||
| 2032 | } | ||
| 2033 | } | ||
| 2034 | fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { | 2383 | fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 2035 | const gpa = elf.base.comp.gpa; | 2384 | const gpa = elf.base.comp.gpa; |
| 2036 | 2385 | ||
| ... | @@ -2044,19 +2393,19 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { | ... | @@ -2044,19 +2393,19 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 2044 | // Ensure the `.plt` section's node is big enough: | 2393 | // Ensure the `.plt` section's node is big enough: |
| 2045 | { | 2394 | { |
| 2046 | const need_size: usize = plt.entry_size * (1 + need_plt_count); | 2395 | const need_size: usize = plt.entry_size * (1 + need_plt_count); |
| 2047 | try elf.shndx.plt.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size); | 2396 | try elf.shndx.plt.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size); |
| 2048 | } | 2397 | } |
| 2049 | 2398 | ||
| 2050 | // If there is a `.got.plt` section, ensure its node is big enough | 2399 | // If there is a `.got.plt` section, ensure its node is big enough |
| 2051 | if (plt.got_plt) |got_plt| { | 2400 | if (plt.got_plt) |got_plt| { |
| 2052 | const need_size: usize = elf.targetPtrSize() * (got_plt.header_entries + need_plt_count); | 2401 | const need_size: usize = elf.targetPtrSize() * (got_plt.header_entries + need_plt_count); |
| 2053 | try elf.shndx.got_plt.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size); | 2402 | try elf.shndx.got_plt.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size); |
| 2054 | } | 2403 | } |
| 2055 | 2404 | ||
| 2056 | // If there is a `.plt.sec` section, ensure its node is big enough | 2405 | // If there is a `.plt.sec` section, ensure its node is big enough |
| 2057 | if (plt.plt_sec) |plt_sec| { | 2406 | if (plt.plt_sec) |plt_sec| { |
| 2058 | const need_size: usize = plt_sec.entry_size * need_plt_count; | 2407 | const need_size: usize = plt_sec.entry_size * need_plt_count; |
| 2059 | try elf.shndx.plt_sec.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size); | 2408 | try elf.shndx.plt_sec.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size); |
| 2060 | } | 2409 | } |
| 2061 | } | 2410 | } |
| 2062 | /// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at | 2411 | /// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at |
| ... | @@ -2138,7 +2487,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L | ... | @@ -2138,7 +2487,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L |
| 2138 | .other = .{ .visibility = .DEFAULT }, | 2487 | .other = .{ .visibility = .DEFAULT }, |
| 2139 | .shndx = opts.shndx.toSection().?, | 2488 | .shndx = opts.shndx.toSection().?, |
| 2140 | }; | 2489 | }; |
| 2141 | if (elf.targetEndian() != native_endian) { | 2490 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 2142 | std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym); | 2491 | std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym); |
| 2143 | } | 2492 | } |
| 2144 | 2493 | ||
| ... | @@ -2323,7 +2672,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ | ... | @@ -2323,7 +2672,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ |
| 2323 | .other = .{ .visibility = opts.visibility }, | 2672 | .other = .{ .visibility = opts.visibility }, |
| 2324 | .shndx = opts.shndx.toSection().?, | 2673 | .shndx = opts.shndx.toSection().?, |
| 2325 | }; | 2674 | }; |
| 2326 | if (elf.targetEndian() != native_endian) { | 2675 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 2327 | std.mem.byteSwapAllFields(Sym, sym); | 2676 | std.mem.byteSwapAllFields(Sym, sym); |
| 2328 | } | 2677 | } |
| 2329 | }, | 2678 | }, |
| ... | @@ -2359,7 +2708,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ | ... | @@ -2359,7 +2708,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ |
| 2359 | .other = .{ .visibility = opts.visibility }, | 2708 | .other = .{ .visibility = opts.visibility }, |
| 2360 | .shndx = opts.shndx.toSection().?, | 2709 | .shndx = opts.shndx.toSection().?, |
| 2361 | }; | 2710 | }; |
| 2362 | if (elf.targetEndian() != native_endian) { | 2711 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 2363 | std.mem.byteSwapAllFields(Sym, sym); | 2712 | std.mem.byteSwapAllFields(Sym, sym); |
| 2364 | } | 2713 | } |
| 2365 | elf.appendDynsymHashEntry(dynsym_index); | 2714 | elf.appendDynsymHashEntry(dynsym_index); |
| ... | @@ -2869,7 +3218,8 @@ const Symbol = struct { | ... | @@ -2869,7 +3218,8 @@ const Symbol = struct { |
| 2869 | .abs, .pltabs => {}, | 3218 | .abs, .pltabs => {}, |
| 2870 | } | 3219 | } |
| 2871 | if (!reloc.type.action.simple.dest.isAddr(elf)) continue; | 3220 | if (!reloc.type.action.simple.dest.isAddr(elf)) continue; |
| 2872 | switch (elf.nodeWantsDsoRelocation(reloc.node)) { | 3221 | const node = reloc.node.unwrap().?; |
| 3222 | switch (elf.nodeWantsDsoRelocation(node)) { | ||
| 2873 | .no => continue, | 3223 | .no => continue, |
| 2874 | .yes_textrel => elf.textrel_count += 1, | 3224 | .yes_textrel => elf.textrel_count += 1, |
| 2875 | .yes => {}, | 3225 | .yes => {}, |
| ... | @@ -2877,7 +3227,7 @@ const Symbol = struct { | ... | @@ -2877,7 +3227,7 @@ const Symbol = struct { |
| 2877 | // There is capacity for a relocation because we just deleted one earlier. | 3227 | // There is capacity for a relocation because we just deleted one earlier. |
| 2878 | reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{ | 3228 | reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{ |
| 2879 | .type = .relative(elf), | 3229 | .type = .relative(elf), |
| 2880 | .offset = elf.getNodeVAddr(reloc.node) + reloc.offset, | 3230 | .offset = elf.getNodeVAddr(node) + reloc.offset, |
| 2881 | .raw_sym_index = 0, | 3231 | .raw_sym_index = 0, |
| 2882 | .addend = 0, | 3232 | .addend = 0, |
| 2883 | }).toOptional(); | 3233 | }).toOptional(); |
| ... | @@ -2982,6 +3332,7 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum { | ... | @@ -2982,6 +3332,7 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum { |
| 2982 | 3332 | ||
| 2983 | pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { | 3333 | pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { |
| 2984 | const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) { | 3334 | const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) { |
| 3335 | .deleted, | ||
| 2985 | .archive, | 3336 | .archive, |
| 2986 | .archive_header, | 3337 | .archive_header, |
| 2987 | .archive_input_member, | 3338 | .archive_input_member, |
| ... | @@ -2991,10 +3342,27 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { | ... | @@ -2991,10 +3342,27 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { |
| 2991 | .shdr, | 3342 | .shdr, |
| 2992 | .segment, | 3343 | .segment, |
| 2993 | .section, | 3344 | .section, |
| 3345 | .section_manual_size, | ||
| 2994 | .input_section, | 3346 | .input_section, |
| 2995 | .copied_global, | 3347 | .copied_global, |
| 3348 | .debug_shared, | ||
| 3349 | .eh_frame_footer, | ||
| 3350 | .unit_padding, | ||
| 3351 | .unit_frame, | ||
| 3352 | .unit_frame_cie, | ||
| 3353 | .unit_debug_info, | ||
| 3354 | .unit_debug_info_header, | ||
| 3355 | .unit_debug_info_footer, | ||
| 3356 | .unit_debug_line, | ||
| 3357 | .unit_debug_line_header, | ||
| 3358 | .unit_debug_rnglists, | ||
| 3359 | .const_debug_info, | ||
| 3360 | .global_debug_info, | ||
| 3361 | .func_frame_fde, | ||
| 3362 | .func_debug_info, | ||
| 3363 | .func_debug_line, | ||
| 3364 | .decl_debug_info, | ||
| 2996 | => unreachable, | 3365 | => unreachable, |
| 2997 | |||
| 2998 | inline .nav, | 3366 | inline .nav, |
| 2999 | .uav, | 3367 | .uav, |
| 3000 | .lazy_code, | 3368 | .lazy_code, |
| ... | @@ -3005,10 +3373,9 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { | ... | @@ -3005,10 +3373,9 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { |
| 3005 | return s.toTypeErased(); | 3373 | return s.toTypeErased(); |
| 3006 | } | 3374 | } |
| 3007 | pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) link.Error!link.File.SymbolId { | 3375 | pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) link.Error!link.File.SymbolId { |
| 3008 | const diags = &elf.base.comp.link_diags; | ||
| 3009 | return elf.lazySymbolInner(lazy) catch |err| switch (err) { | 3376 | return elf.lazySymbolInner(lazy) catch |err| switch (err) { |
| 3010 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3011 | else => |e| return e, | 3377 | else => |e| return e, |
| 3378 | error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3012 | }; | 3379 | }; |
| 3013 | } | 3380 | } |
| 3014 | fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.SymbolId { | 3381 | fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.SymbolId { |
| ... | @@ -3024,13 +3391,16 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol | ... | @@ -3024,13 +3391,16 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol |
| 3024 | .code => .{ .text, .FUNC }, | 3391 | .code => .{ .text, .FUNC }, |
| 3025 | .const_data => .{ .rodata, .OBJECT }, | 3392 | .const_data => .{ .rodata, .OBJECT }, |
| 3026 | }; | 3393 | }; |
| 3027 | const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}); | 3394 | const node = elf.addNodeAssumeCapacity( |
| 3028 | var name_buf: [64]u8 = undefined; | 3395 | try shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), |
| 3029 | const name = std.mem.print( | 3396 | switch (lazy.kind) { |
| 3030 | &name_buf, | 3397 | .code => .{ .lazy_code = @fromBackingInt(@intCast(gop.index)) }, |
| 3031 | "__lazy_{t}_{d}", | 3398 | .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(gop.index)) }, |
| 3032 | .{ lazy.kind, @backingInt(lazy.ty) }, | 3399 | }, |
| 3033 | ) catch unreachable; | 3400 | ); |
| 3401 | var name_buf: [std.fmt.count("__lazy_const_data_{d}", .{std.math.maxInt(u32)})]u8 = undefined; | ||
| 3402 | const name = std.mem.print(&name_buf, "__lazy_{t}_{d}", .{ lazy.kind, gop.index }) catch | ||
| 3403 | unreachable; | ||
| 3034 | gop.value_ptr.* = .{ | 3404 | gop.value_ptr.* = .{ |
| 3035 | .lsi = elf.addLocalSymbolAssumeCapacity(.{ | 3405 | .lsi = elf.addLocalSymbolAssumeCapacity(.{ |
| 3036 | .node = .wrap(node), | 3406 | .node = .wrap(node), |
| ... | @@ -3043,11 +3413,7 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol | ... | @@ -3043,11 +3413,7 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol |
| 3043 | .first_symbol_reloc = .none, | 3413 | .first_symbol_reloc = .none, |
| 3044 | .first_got_reloc = .none, | 3414 | .first_got_reloc = .none, |
| 3045 | }; | 3415 | }; |
| 3046 | elf.nodes.appendAssumeCapacity(switch (lazy.kind) { | 3416 | elf.base.comp.link_prog_node.increaseEstimatedTotalItems(1); |
| 3047 | .code => .{ .lazy_code = @fromBackingInt(@intCast(gop.index)) }, | ||
| 3048 | .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(gop.index)) }, | ||
| 3049 | }); | ||
| 3050 | elf.synth_prog_node.increaseEstimatedTotalItems(1); | ||
| 3051 | } | 3417 | } |
| 3052 | const s: Symbol.Id = .local(gop.value_ptr.lsi); | 3418 | const s: Symbol.Id = .local(gop.value_ptr.lsi); |
| 3053 | return s.toTypeErased(); | 3419 | return s.toTypeErased(); |
| ... | @@ -3062,8 +3428,8 @@ pub const ExternSymbolOpts = struct { | ... | @@ -3062,8 +3428,8 @@ pub const ExternSymbolOpts = struct { |
| 3062 | pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId { | 3428 | pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId { |
| 3063 | const diags = &elf.base.comp.link_diags; | 3429 | const diags = &elf.base.comp.link_diags; |
| 3064 | return (elf.externSymbolInner(opts) catch |err| switch (err) { | 3430 | return (elf.externSymbolInner(opts) catch |err| switch (err) { |
| 3065 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3066 | else => |e| return e, | 3431 | else => |e| return e, |
| 3432 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3067 | }).toTypeErased(); | 3433 | }).toTypeErased(); |
| 3068 | } | 3434 | } |
| 3069 | fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!Symbol.Id { | 3435 | fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!Symbol.Id { |
| ... | @@ -3103,15 +3469,33 @@ pub fn addReloc( | ... | @@ -3103,15 +3469,33 @@ pub fn addReloc( |
| 3103 | const node: MappedFile.Node.Index = Node.fromAtom(atom); | 3469 | const node: MappedFile.Node.Index = Node.fromAtom(atom); |
| 3104 | const diags = &elf.base.comp.link_diags; | 3470 | const diags = &elf.base.comp.link_diags; |
| 3105 | elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) { | 3471 | elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) { |
| 3106 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3107 | else => |e| return e, | 3472 | else => |e| return e, |
| 3473 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3108 | }; | 3474 | }; |
| 3109 | elf.addRelocAssumeCapacity(node, offset, .fromTypeErased(target), addend, @"type") catch |err| switch (err) { | 3475 | elf.addRelocAssumeCapacity(node, offset, .fromTypeErased(target), addend, @"type") catch |err| switch (err) { |
| 3476 | else => |e| return e, | ||
| 3110 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | 3477 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), |
| 3111 | error.UnknownRelocation => unreachable, // codegen bug | 3478 | error.UnknownRelocation => unreachable, // codegen bug |
| 3112 | error.NonStaticRelocation => unreachable, // codegen bug | 3479 | error.NonStaticRelocation => unreachable, // codegen bug |
| 3113 | error.UnimplementedRelocation => unreachable, // codegen bug (asking Elf2 for a relocation it does not support) | 3480 | error.UnimplementedRelocation => unreachable, // codegen bug (asking Elf2 for a relocation it does not support) |
| 3481 | }; | ||
| 3482 | } | ||
| 3483 | pub fn addNodeReloc( | ||
| 3484 | elf: *Elf, | ||
| 3485 | node: MappedFile.Node.Index, | ||
| 3486 | offset: u64, | ||
| 3487 | target: MappedFile.Node.Index, | ||
| 3488 | addend: i64, | ||
| 3489 | @"type": NodeReloc.Type, | ||
| 3490 | ) link.Error!void { | ||
| 3491 | const diags = &elf.base.comp.link_diags; | ||
| 3492 | elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) { | ||
| 3493 | else => |e| return e, | ||
| 3494 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3495 | }; | ||
| 3496 | elf.addNodeRelocAssumeCapacity(node, offset, target, addend, @"type") catch |err| switch (err) { | ||
| 3114 | else => |e| return e, | 3497 | else => |e| return e, |
| 3498 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3115 | }; | 3499 | }; |
| 3116 | } | 3500 | } |
| 3117 | pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId { | 3501 | pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId { |
| ... | @@ -3129,8 +3513,8 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil | ... | @@ -3129,8 +3513,8 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil |
| 3129 | }); | 3513 | }); |
| 3130 | } | 3514 | } |
| 3131 | const nmi = elf.navMapIndex(zcu, nav_index) catch |err| switch (err) { | 3515 | const nmi = elf.navMapIndex(zcu, nav_index) catch |err| switch (err) { |
| 3132 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3133 | else => |e| return e, | 3516 | else => |e| return e, |
| 3517 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3134 | }; | 3518 | }; |
| 3135 | const s: Symbol.Id = .local(nmi.symbol(elf)); | 3519 | const s: Symbol.Id = .local(nmi.symbol(elf)); |
| 3136 | return s.toTypeErased(); | 3520 | return s.toTypeErased(); |
| ... | @@ -3142,8 +3526,8 @@ pub fn uavSymbol( | ... | @@ -3142,8 +3526,8 @@ pub fn uavSymbol( |
| 3142 | ) link.Error!link.File.SymbolId { | 3526 | ) link.Error!link.File.SymbolId { |
| 3143 | const diags = &elf.base.comp.link_diags; | 3527 | const diags = &elf.base.comp.link_diags; |
| 3144 | const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) { | 3528 | const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) { |
| 3145 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3146 | else => |e| return e, | 3529 | else => |e| return e, |
| 3530 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3147 | }; | 3531 | }; |
| 3148 | const s: Symbol.Id = .local(umi.symbol(elf)); | 3532 | const s: Symbol.Id = .local(umi.symbol(elf)); |
| 3149 | return s.toTypeErased(); | 3533 | return s.toTypeErased(); |
| ... | @@ -3166,7 +3550,11 @@ pub fn getUavVAddr( | ... | @@ -3166,7 +3550,11 @@ pub fn getUavVAddr( |
| 3166 | } | 3550 | } |
| 3167 | pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) link.Error!u64 { | 3551 | pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) link.Error!u64 { |
| 3168 | try elf.addReloc( | 3552 | try elf.addReloc( |
| 3169 | reloc_info.parent.atom_index, | 3553 | switch (reloc_info.parent) { |
| 3554 | .none => unreachable, | ||
| 3555 | .atom_index => |atom_id| atom_id, | ||
| 3556 | .debug_output => |debug_output| Node.toAtom(debug_output.dwarf2.info_writer.ni), | ||
| 3557 | }, | ||
| 3170 | reloc_info.offset, | 3558 | reloc_info.offset, |
| 3171 | target, | 3559 | target, |
| 3172 | reloc_info.addend, | 3560 | reloc_info.addend, |
| ... | @@ -3183,8 +3571,8 @@ pub fn lowerUav( | ... | @@ -3183,8 +3571,8 @@ pub fn lowerUav( |
| 3183 | _ = pt; | 3571 | _ = pt; |
| 3184 | const diags = &elf.base.comp.link_diags; | 3572 | const diags = &elf.base.comp.link_diags; |
| 3185 | const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) { | 3573 | const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) { |
| 3186 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3187 | else => |e| return e, | 3574 | else => |e| return e, |
| 3575 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 3188 | }; | 3576 | }; |
| 3189 | const s: Symbol.Id = .local(umi.symbol(elf)); | 3577 | const s: Symbol.Id = .local(umi.symbol(elf)); |
| 3190 | return s.toTypeErased(); | 3578 | return s.toTypeErased(); |
| ... | @@ -3283,7 +3671,7 @@ const StringTable = struct { | ... | @@ -3283,7 +3671,7 @@ const StringTable = struct { |
| 3283 | break :size .{ old_size, new_size }; | 3671 | break :size .{ old_size, new_size }; |
| 3284 | }, | 3672 | }, |
| 3285 | }; | 3673 | }; |
| 3286 | try ni.ensureMinimumSize(&elf.mf, gpa, new_size); | 3674 | try ni.ensureMinimumSize(gpa, &elf.mf, new_size); |
| 3287 | const slice = ni.slice(&elf.mf)[old_size..]; | 3675 | const slice = ni.slice(&elf.mf)[old_size..]; |
| 3288 | @memcpy(slice[0..key.len], key); | 3676 | @memcpy(slice[0..key.len], key); |
| 3289 | slice[key.len] = 0; | 3677 | slice[key.len] = 0; |
| ... | @@ -3393,6 +3781,7 @@ fn create( | ... | @@ -3393,6 +3781,7 @@ fn create( |
| 3393 | .data = undefined, | 3781 | .data = undefined, |
| 3394 | .data_rel_ro = undefined, | 3782 | .data_rel_ro = undefined, |
| 3395 | .tls = .none, | 3783 | .tls = .none, |
| 3784 | .gnu_eh_frame = .none, | ||
| 3396 | }, | 3785 | }, |
| 3397 | .archive = null, | 3786 | .archive = null, |
| 3398 | .nodes = .empty, | 3787 | .nodes = .empty, |
| ... | @@ -3410,6 +3799,16 @@ fn create( | ... | @@ -3410,6 +3799,16 @@ fn create( |
| 3410 | .tdata = .UNDEF, | 3799 | .tdata = .UNDEF, |
| 3411 | .rela_dyn = .UNDEF, | 3800 | .rela_dyn = .UNDEF, |
| 3412 | .rela_plt = .UNDEF, | 3801 | .rela_plt = .UNDEF, |
| 3802 | .debug_abbrev = .UNDEF, | ||
| 3803 | .eh_frame_hdr = .UNDEF, | ||
| 3804 | .eh_frame = .UNDEF, | ||
| 3805 | .debug_frame = .UNDEF, | ||
| 3806 | .debug_info = .UNDEF, | ||
| 3807 | .debug_line = .UNDEF, | ||
| 3808 | .debug_line_str = .UNDEF, | ||
| 3809 | .debug_rnglists = .UNDEF, | ||
| 3810 | .debug_str = .UNDEF, | ||
| 3811 | .debug_str_offsets = .UNDEF, | ||
| 3413 | .init_array = .UNDEF, | 3812 | .init_array = .UNDEF, |
| 3414 | .fini_array = .UNDEF, | 3813 | .fini_array = .UNDEF, |
| 3415 | .preinit_array = .UNDEF, | 3814 | .preinit_array = .UNDEF, |
| ... | @@ -3437,6 +3836,7 @@ fn create( | ... | @@ -3437,6 +3836,7 @@ fn create( |
| 3437 | .got = .empty, | 3836 | .got = .empty, |
| 3438 | .plt = .empty, | 3837 | .plt = .empty, |
| 3439 | .plt_first_symbol_reloc = .none, | 3838 | .plt_first_symbol_reloc = .none, |
| 3839 | .eh_frame_hdr_first_symbol_reloc = .none, | ||
| 3440 | .needed = .empty, | 3840 | .needed = .empty, |
| 3441 | .inputs = .empty, | 3841 | .inputs = .empty, |
| 3442 | .input_pending_index = 0, | 3842 | .input_pending_index = 0, |
| ... | @@ -3451,15 +3851,31 @@ fn create( | ... | @@ -3451,15 +3851,31 @@ fn create( |
| 3451 | }), | 3851 | }), |
| 3452 | .pending_uavs = .empty, | 3852 | .pending_uavs = .empty, |
| 3453 | .symbol_relocs = .empty, | 3853 | .symbol_relocs = .empty, |
| 3854 | .node_relocs = .empty, | ||
| 3454 | .got_relocs = .empty, | 3855 | .got_relocs = .empty, |
| 3455 | .tls_size_symbol_relocs = .empty, | 3856 | .tls_size_symbol_relocs = .empty, |
| 3456 | .section_by_name = .empty, | 3857 | .section_by_name = .empty, |
| 3457 | .changed_symtab_index = .empty, | 3858 | .changed_symtab_index = .empty, |
| 3458 | .textrel_count = 0, | 3859 | .textrel_count = 0, |
| 3860 | |||
| 3861 | .dwarf = .init(&elf.base, switch (comp.config.debug_format) { | ||
| 3862 | .strip => .@"32", // for .eh_frame | ||
| 3863 | .dwarf => |v| v, | ||
| 3864 | .code_view => unreachable, | ||
| 3865 | }), | ||
| 3866 | .dwarf_shared = comptime .initFill(.{ | ||
| 3867 | .first_target_reloc = .none, | ||
| 3868 | }), | ||
| 3869 | .dwarf_units = &.{}, | ||
| 3870 | .dwarf_consts = .empty, | ||
| 3871 | .dwarf_globals = .empty, | ||
| 3872 | .dwarf_funcs = .empty, | ||
| 3873 | .dwarf_decls = .empty, | ||
| 3874 | |||
| 3459 | .overflowed_reloc_count = 0, | 3875 | .overflowed_reloc_count = 0, |
| 3460 | .misaligned_reloc_count = 0, | 3876 | .misaligned_reloc_count = 0, |
| 3877 | |||
| 3461 | .const_prog_node = .none, | 3878 | .const_prog_node = .none, |
| 3462 | .synth_prog_node = .none, | ||
| 3463 | .input_prog_node = .none, | 3879 | .input_prog_node = .none, |
| 3464 | }; | 3880 | }; |
| 3465 | errdefer elf.deinit(); | 3881 | errdefer elf.deinit(); |
| ... | @@ -3498,10 +3914,20 @@ pub fn deinit(elf: *Elf) void { | ... | @@ -3498,10 +3914,20 @@ pub fn deinit(elf: *Elf) void { |
| 3498 | for (&elf.lazy.values) |*lazy| lazy.map.deinit(gpa); | 3914 | for (&elf.lazy.values) |*lazy| lazy.map.deinit(gpa); |
| 3499 | elf.pending_uavs.deinit(gpa); | 3915 | elf.pending_uavs.deinit(gpa); |
| 3500 | elf.symbol_relocs.deinit(gpa); | 3916 | elf.symbol_relocs.deinit(gpa); |
| 3917 | elf.node_relocs.deinit(gpa); | ||
| 3501 | elf.got_relocs.deinit(gpa); | 3918 | elf.got_relocs.deinit(gpa); |
| 3502 | elf.tls_size_symbol_relocs.deinit(gpa); | 3919 | elf.tls_size_symbol_relocs.deinit(gpa); |
| 3503 | elf.section_by_name.deinit(gpa); | 3920 | elf.section_by_name.deinit(gpa); |
| 3504 | elf.changed_symtab_index.deinit(gpa); | 3921 | elf.changed_symtab_index.deinit(gpa); |
| 3922 | |||
| 3923 | elf.dwarf.deinit(); | ||
| 3924 | for (elf.dwarf_units) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa); | ||
| 3925 | gpa.free(elf.dwarf_units); | ||
| 3926 | elf.dwarf_consts.deinit(gpa); | ||
| 3927 | elf.dwarf_globals.deinit(gpa); | ||
| 3928 | elf.dwarf_funcs.deinit(gpa); | ||
| 3929 | elf.dwarf_decls.deinit(gpa); | ||
| 3930 | |||
| 3505 | elf.* = undefined; | 3931 | elf.* = undefined; |
| 3506 | } | 3932 | } |
| 3507 | 3933 | ||
| ... | @@ -3518,11 +3944,17 @@ fn initHeaders( | ... | @@ -3518,11 +3944,17 @@ fn initHeaders( |
| 3518 | const gpa = comp.gpa; | 3944 | const gpa = comp.gpa; |
| 3519 | 3945 | ||
| 3520 | const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static; | 3946 | const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static; |
| 3521 | const have_dynamic_section = switch (@"type") { | 3947 | const have_dynamic = switch (@"type") { |
| 3522 | .REL => false, | 3948 | .REL => false, |
| 3523 | .EXEC => comp.config.link_mode == .dynamic, | 3949 | .EXEC => comp.config.link_mode == .dynamic, |
| 3524 | .DYN => true, | 3950 | .DYN => true, |
| 3525 | }; | 3951 | }; |
| 3952 | const have_eh_frame = machine == .X86_64 and comp.config.any_unwind_tables; | ||
| 3953 | const have_debug_frame = machine == .X86_64 and switch (comp.config.debug_format) { | ||
| 3954 | .strip => false, | ||
| 3955 | .dwarf => !comp.config.any_unwind_tables, | ||
| 3956 | .code_view => unreachable, | ||
| 3957 | }; | ||
| 3526 | const addr_align: Alignment = switch (class) { | 3958 | const addr_align: Alignment = switch (class) { |
| 3527 | .NONE, _ => unreachable, | 3959 | .NONE, _ => unreachable, |
| 3528 | .@"32" => .@"4", | 3960 | .@"32" => .@"4", |
| ... | @@ -3537,7 +3969,7 @@ fn initHeaders( | ... | @@ -3537,7 +3969,7 @@ fn initHeaders( |
| 3537 | // | 3969 | // |
| 3538 | // It can be handy to temporarily set this to `.@"1"` when working on the linker, because it | 3970 | // It can be handy to temporarily set this to `.@"1"` when working on the linker, because it |
| 3539 | // prevents alignment bugs from being hidden by your filesystem's block alignment. | 3971 | // prevents alignment bugs from being hidden by your filesystem's block alignment. |
| 3540 | const node_block_align: Alignment = elf.mf.flags.block_size; | 3972 | const node_block_align = elf.mf.flags.block_size; |
| 3541 | 3973 | ||
| 3542 | const plt: PltInfo = .fromMachine(machine); | 3974 | const plt: PltInfo = .fromMachine(machine); |
| 3543 | 3975 | ||
| ... | @@ -3552,7 +3984,7 @@ fn initHeaders( | ... | @@ -3552,7 +3984,7 @@ fn initHeaders( |
| 3552 | shnum += 1; // .data | 3984 | shnum += 1; // .data |
| 3553 | shnum += @intFromBool(comp.config.any_non_single_threaded); // .tdata | 3985 | shnum += @intFromBool(comp.config.any_non_single_threaded); // .tdata |
| 3554 | shnum += 1; // .data.rel.ro | 3986 | shnum += 1; // .data.rel.ro |
| 3555 | if (have_dynamic_section) { | 3987 | if (have_dynamic) { |
| 3556 | shnum += 1; // .dynamic | 3988 | shnum += 1; // .dynamic |
| 3557 | shnum += 1; // .dynstr | 3989 | shnum += 1; // .dynstr |
| 3558 | shnum += 1; // .dynsym | 3990 | shnum += 1; // .dynsym |
| ... | @@ -3560,6 +3992,24 @@ fn initHeaders( | ... | @@ -3560,6 +3992,24 @@ fn initHeaders( |
| 3560 | shnum += 1; // .rela.dyn | 3992 | shnum += 1; // .rela.dyn |
| 3561 | shnum += 1; // .rela.plt | 3993 | shnum += 1; // .rela.plt |
| 3562 | } | 3994 | } |
| 3995 | if (have_eh_frame) { | ||
| 3996 | shnum += @intFromBool(@"type" != .REL); // .eh_frame_hdr | ||
| 3997 | shnum += 1; // .eh_frame | ||
| 3998 | } | ||
| 3999 | switch (comp.config.debug_format) { | ||
| 4000 | .strip => {}, | ||
| 4001 | .dwarf => { | ||
| 4002 | shnum += 1; // .debug_abbrev | ||
| 4003 | shnum += @intFromBool(have_debug_frame); // .debug_frame | ||
| 4004 | shnum += 1; // .debug_info | ||
| 4005 | shnum += 1; // .debug_line | ||
| 4006 | shnum += 1; // .debug_line_str | ||
| 4007 | shnum += 1; // .debug_rnglists | ||
| 4008 | shnum += 1; // .debug_str | ||
| 4009 | shnum += 1; // .debug_str_offsets | ||
| 4010 | }, | ||
| 4011 | .code_view => unreachable, | ||
| 4012 | } | ||
| 3563 | if (@"type" != .REL) { | 4013 | if (@"type" != .REL) { |
| 3564 | shnum += 1; // .got | 4014 | shnum += 1; // .got |
| 3565 | shnum += @intFromBool(plt.got_plt != null); // .got.plt | 4015 | shnum += @intFromBool(plt.got_plt != null); // .got.plt |
| ... | @@ -3574,14 +4024,15 @@ fn initHeaders( | ... | @@ -3574,14 +4024,15 @@ fn initHeaders( |
| 3574 | interp: u32, | 4024 | interp: u32, |
| 3575 | rodata: u32, | 4025 | rodata: u32, |
| 3576 | text: u32, | 4026 | text: u32, |
| 3577 | data: u32, | ||
| 3578 | /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write | 4027 | /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write |
| 3579 | /// directly to the PLT, we place the PLT in its own segment in order to avoid making the | 4028 | /// directly to the PLT, we place the PLT in its own segment in order to avoid making the |
| 3580 | /// general data segment RWX. | 4029 | /// general data segment RWX. |
| 3581 | plt: u32, | 4030 | plt: u32, |
| 4031 | data: u32, | ||
| 3582 | tls: u32, | 4032 | tls: u32, |
| 3583 | dynamic: u32, | 4033 | dynamic: u32, |
| 3584 | relro: u32, | 4034 | relro: u32, |
| 4035 | gnu_eh_frame: u32, | ||
| 3585 | gnu_stack: u32, | 4036 | gnu_stack: u32, |
| 3586 | }, const phnum: u32 = ph: { | 4037 | }, const phnum: u32 = ph: { |
| 3587 | switch (@"type") { | 4038 | switch (@"type") { |
| ... | @@ -3622,7 +4073,7 @@ fn initHeaders( | ... | @@ -3622,7 +4073,7 @@ fn initHeaders( |
| 3622 | defer phnum += 1; | 4073 | defer phnum += 1; |
| 3623 | break :phndx phnum; | 4074 | break :phndx phnum; |
| 3624 | } else undefined, | 4075 | } else undefined, |
| 3625 | .dynamic = if (have_dynamic_section) phndx: { | 4076 | .dynamic = if (have_dynamic) phndx: { |
| 3626 | defer phnum += 1; | 4077 | defer phnum += 1; |
| 3627 | break :phndx phnum; | 4078 | break :phndx phnum; |
| 3628 | } else undefined, | 4079 | } else undefined, |
| ... | @@ -3630,6 +4081,10 @@ fn initHeaders( | ... | @@ -3630,6 +4081,10 @@ fn initHeaders( |
| 3630 | defer phnum += 1; | 4081 | defer phnum += 1; |
| 3631 | break :phndx phnum; | 4082 | break :phndx phnum; |
| 3632 | }, | 4083 | }, |
| 4084 | .gnu_eh_frame = if (have_eh_frame) phndx: { | ||
| 4085 | defer phnum += 1; | ||
| 4086 | break :phndx phnum; | ||
| 4087 | } else undefined, | ||
| 3633 | .gnu_stack = phndx: { | 4088 | .gnu_stack = phndx: { |
| 3634 | defer phnum += 1; | 4089 | defer phnum += 1; |
| 3635 | break :phndx phnum; | 4090 | break :phndx phnum; |
| ... | @@ -3643,7 +4098,8 @@ fn initHeaders( | ... | @@ -3643,7 +4098,8 @@ fn initHeaders( |
| 3643 | const expected_nodes_len = @as(usize, if (is_archive) 3 else 0) + // .archive, .archive_header, .archive_elf_member_header | 4098 | const expected_nodes_len = @as(usize, if (is_archive) 3 else 0) + // .archive, .archive_header, .archive_elf_member_header |
| 3644 | 3 + // `.elf`, `.ehdr`, and `.shdr` nodes | 4099 | 3 + // `.elf`, `.ehdr`, and `.shdr` nodes |
| 3645 | (shnum - 1) + // -1 because the SHN_UNDEF shdr does not have a `.section` node | 4100 | (shnum - 1) + // -1 because the SHN_UNDEF shdr does not have a `.section` node |
| 3646 | (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node | 4101 | (phnum -| 1) + // -1 because the GNU_STACK phdr does not have a `.segment` node |
| 4102 | @intFromBool(have_eh_frame and @"type" != .REL); // eh_frame_footer | ||
| 3647 | 4103 | ||
| 3648 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); | 4104 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 3649 | try elf.shdrs.ensureTotalCapacity(gpa, shnum - 1); // -1 to exclude SHN_UNDEF | 4105 | try elf.shdrs.ensureTotalCapacity(gpa, shnum - 1); // -1 to exclude SHN_UNDEF |
| ... | @@ -3652,21 +4108,21 @@ fn initHeaders( | ... | @@ -3652,21 +4108,21 @@ fn initHeaders( |
| 3652 | try elf.symtab.ensureTotalCapacity(gpa, 1); | 4108 | try elf.symtab.ensureTotalCapacity(gpa, 1); |
| 3653 | 4109 | ||
| 3654 | if (is_archive) { | 4110 | if (is_archive) { |
| 3655 | elf.nodes.appendAssumeCapacity(.archive); | 4111 | const archive_ni = elf.addNodeAssumeCapacity(.root, .archive); |
| 3656 | 4112 | ||
| 3657 | const archive_ni: MappedFile.Node.Index = .root; | 4113 | const archive_header_ni = elf.addNodeAssumeCapacity( |
| 3658 | 4114 | try archive_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ | |
| 3659 | const archive_header_ni = try archive_ni.addOnlyHeaderChild(&elf.mf, gpa, .{ | 4115 | // We intentionally do not set `.alignment = .@"2"` here, because the string table data |
| 3660 | // We intentionally do not set `.alignment = .@"2"` here, because the string table data | 4116 | // in this node does not need to have an aligned length. (This node's offset is aligned |
| 3661 | // in this node does not need to have an aligned length. (This node's offset is aligned | 4117 | // regardless by virtue of it being a header.) |
| 3662 | // regardless by virtue of it being a header.) | 4118 | .size = std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr), |
| 3663 | .size = std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr), | 4119 | // The archive header uses 'next_moved' events to resize the "//" member, so that it |
| 3664 | // The archive header uses 'next_moved' events to resize the "//" member, so that it | 4120 | // absorbs all padding between `archive_header_ni` and the actual object file members. |
| 3665 | // absorbs all padding between `archive_header_ni` and the actual object file members. | 4121 | .enable_next_moved = true, |
| 3666 | .enable_next_moved = true, | 4122 | .next_moved = true, |
| 3667 | .next_moved = true, | 4123 | }), |
| 3668 | }); | 4124 | .archive_header, |
| 3669 | elf.nodes.appendAssumeCapacity(.archive_header); | 4125 | ); |
| 3670 | const archive_header_slice = archive_header_ni.slice(&elf.mf); | 4126 | const archive_header_slice = archive_header_ni.slice(&elf.mf); |
| 3671 | @memcpy(archive_header_slice[0..std.elf.ARMAG.len], std.elf.ARMAG); | 4127 | @memcpy(archive_header_slice[0..std.elf.ARMAG.len], std.elf.ARMAG); |
| 3672 | const strtab_ar_hdr: *std.elf.ar_hdr = @ptrCast(archive_header_slice[std.elf.ARMAG.len..]); | 4128 | const strtab_ar_hdr: *std.elf.ar_hdr = @ptrCast(archive_header_slice[std.elf.ARMAG.len..]); |
| ... | @@ -3680,18 +4136,19 @@ fn initHeaders( | ... | @@ -3680,18 +4136,19 @@ fn initHeaders( |
| 3680 | .ar_fmag = std.elf.ARFMAG.*, | 4136 | .ar_fmag = std.elf.ARFMAG.*, |
| 3681 | }; | 4137 | }; |
| 3682 | 4138 | ||
| 3683 | elf.ni.elf = try archive_ni.addOnlyFooterChild(&elf.mf, gpa, .{ | 4139 | elf.ni.elf = elf.addNodeAssumeCapacity(try archive_ni.addOnlyFooterChild(gpa, &elf.mf, .{ |
| 3684 | .alignment = node_block_align.max(.@"2"), | 4140 | .alignment = node_block_align.max(.@"2"), |
| 3685 | .bubbles_moved = false, | 4141 | .bubbles_moved = false, |
| 3686 | .resized = true, // ensure that this node's `ar_hdr.ar_size` is updated at least once | 4142 | .resized = true, // ensure that this node's `ar_hdr.ar_size` is updated at least once |
| 3687 | }); | 4143 | }), .elf); |
| 3688 | elf.nodes.appendAssumeCapacity(.elf); | ||
| 3689 | 4144 | ||
| 3690 | const elf_ar_hdr_ni = try archive_ni.addFooterChildBefore(&elf.mf, gpa, .wrap(elf.ni.elf), .{ | 4145 | const elf_ar_hdr_ni = elf.addNodeAssumeCapacity( |
| 3691 | .alignment = .@"2", | 4146 | try archive_ni.addFooterChildBefore(gpa, &elf.mf, .wrap(elf.ni.elf), .{ |
| 3692 | .size = @sizeOf(std.elf.ar_hdr), | 4147 | .alignment = .@"2", |
| 3693 | }); | 4148 | .size = @sizeOf(std.elf.ar_hdr), |
| 3694 | elf.nodes.appendAssumeCapacity(.archive_elf_member_header); | 4149 | }), |
| 4150 | .archive_elf_member_header, | ||
| 4151 | ); | ||
| 3695 | 4152 | ||
| 3696 | // Must be populated before we call `populateArchiveMemberName` below. | 4153 | // Must be populated before we call `populateArchiveMemberName` below. |
| 3697 | elf.archive = .{ | 4154 | elf.archive = .{ |
| ... | @@ -3717,10 +4174,7 @@ fn initHeaders( | ... | @@ -3717,10 +4174,7 @@ fn initHeaders( |
| 3717 | defer gpa.free(zcu_member_name); | 4174 | defer gpa.free(zcu_member_name); |
| 3718 | // After this call returns, `elf_ar_hdr` is invalidated. | 4175 | // After this call returns, `elf_ar_hdr` is invalidated. |
| 3719 | try elf.populateArchiveMemberName(elf_ar_hdr, zcu_member_name); | 4176 | try elf.populateArchiveMemberName(elf_ar_hdr, zcu_member_name); |
| 3720 | } else { | 4177 | } else elf.ni.elf = elf.addNodeAssumeCapacity(.root, .elf); |
| 3721 | elf.ni.elf = .root; | ||
| 3722 | elf.nodes.appendAssumeCapacity(.elf); | ||
| 3723 | } | ||
| 3724 | 4178 | ||
| 3725 | const entsize: struct { ph: u32, sh: u32 } = switch (class) { | 4179 | const entsize: struct { ph: u32, sh: u32 } = switch (class) { |
| 3726 | .NONE, _ => unreachable, | 4180 | .NONE, _ => unreachable, |
| ... | @@ -3736,69 +4190,65 @@ fn initHeaders( | ... | @@ -3736,69 +4190,65 @@ fn initHeaders( |
| 3736 | if (@"type" != .REL) { | 4190 | if (@"type" != .REL) { |
| 3737 | // This node will contain the ehdr, which must be at the start of the ELF file, so this | 4191 | // This node will contain the ehdr, which must be at the start of the ELF file, so this |
| 3738 | // node must itself be a header of the `.elf` node. | 4192 | // node must itself be a header of the `.elf` node. |
| 3739 | elf.ni.rodata = try elf.ni.elf.addOnlyHeaderChild(&elf.mf, gpa, .{ | 4193 | elf.ni.rodata = elf.addNodeAssumeCapacity(try elf.ni.elf.addOnlyHeaderChild(gpa, &elf.mf, .{ |
| 3740 | // Must be at least `addr_align` for `elf.ni.phdr` to be placed inside this node | 4194 | // Must be at least `addr_align` for `elf.ni.phdr` to be placed inside this node |
| 3741 | .alignment = node_block_align.max(addr_align), | 4195 | .alignment = node_block_align.max(addr_align), |
| 3742 | .moved = true, | 4196 | .moved = true, |
| 3743 | .bubbles_moved = false, | 4197 | .bubbles_moved = false, |
| 3744 | }); | 4198 | }), .{ .segment = phndx.rodata }); |
| 3745 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata }); | ||
| 3746 | elf.phdrs.items[phndx.rodata] = .wrap(elf.ni.rodata); | 4199 | elf.phdrs.items[phndx.rodata] = .wrap(elf.ni.rodata); |
| 3747 | 4200 | ||
| 3748 | elf.ni.phdr = try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{ | 4201 | elf.ni.phdr = elf.addNodeAssumeCapacity(try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{ |
| 3749 | .size = @as(u64, phnum) * entsize.ph, | 4202 | .size = @as(u64, phnum) * entsize.ph, |
| 3750 | .alignment = addr_align, // keep in sync with `elf.ni.rodata` alignment above | 4203 | .alignment = addr_align, // keep in sync with `elf.ni.rodata` alignment above |
| 3751 | .moved = true, | 4204 | .moved = true, |
| 3752 | .resized = true, | 4205 | .resized = true, |
| 3753 | .bubbles_moved = false, | 4206 | .bubbles_moved = false, |
| 3754 | }); | 4207 | }), .{ .segment = phndx.phdr }); |
| 3755 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr }); | ||
| 3756 | elf.phdrs.items[phndx.phdr] = .wrap(elf.ni.phdr); | 4208 | elf.phdrs.items[phndx.phdr] = .wrap(elf.ni.phdr); |
| 3757 | 4209 | ||
| 3758 | elf.ni.text = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{ | 4210 | elf.ni.text = elf.addNodeAssumeCapacity(try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{ |
| 3759 | .alignment = node_block_align, | 4211 | .alignment = node_block_align, |
| 3760 | .moved = true, | 4212 | .moved = true, |
| 3761 | .bubbles_moved = false, | 4213 | .bubbles_moved = false, |
| 3762 | }); | 4214 | }), .{ .segment = phndx.text }); |
| 3763 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text }); | ||
| 3764 | elf.phdrs.items[phndx.text] = .wrap(elf.ni.text); | 4215 | elf.phdrs.items[phndx.text] = .wrap(elf.ni.text); |
| 3765 | 4216 | ||
| 3766 | elf.ni.data = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{ | 4217 | elf.ni.data = elf.addNodeAssumeCapacity(try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{ |
| 3767 | // Must be at least `addr_align` for `elf.ni.data_rel_ro` to be placed inside this node | 4218 | // Must be at least `addr_align` for `elf.ni.data_rel_ro` to be placed inside this node |
| 3768 | .alignment = node_block_align.max(addr_align), | 4219 | .alignment = node_block_align.max(addr_align), |
| 3769 | .moved = true, | 4220 | .moved = true, |
| 3770 | .bubbles_moved = false, | 4221 | .bubbles_moved = false, |
| 3771 | }); | 4222 | }), .{ .segment = phndx.data }); |
| 3772 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data }); | ||
| 3773 | elf.phdrs.items[phndx.data] = .wrap(elf.ni.data); | 4223 | elf.phdrs.items[phndx.data] = .wrap(elf.ni.data); |
| 3774 | 4224 | ||
| 3775 | if (plt.got_plt == null) { | 4225 | if (plt.got_plt == null) elf.phdrs.items[phndx.plt] = .wrap(elf.addNodeAssumeCapacity( |
| 3776 | const plt_ni = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{ | 4226 | try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{ |
| 3777 | .alignment = node_block_align, | 4227 | .alignment = node_block_align, |
| 3778 | .moved = true, | 4228 | .moved = true, |
| 3779 | .bubbles_moved = false, | 4229 | .bubbles_moved = false, |
| 3780 | }); | 4230 | }), |
| 3781 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.plt }); | 4231 | .{ .segment = phndx.plt }, |
| 3782 | elf.phdrs.items[phndx.plt] = .wrap(plt_ni); | 4232 | )); |
| 3783 | } | ||
| 3784 | 4233 | ||
| 3785 | elf.ni.data_rel_ro = try elf.ni.data.addFloatingChild(&elf.mf, gpa, .{ | 4234 | elf.ni.data_rel_ro = elf.addNodeAssumeCapacity(try elf.ni.data.addFloatingChild(gpa, &elf.mf, .{ |
| 3786 | // Must be at least `addr_align` for the `PT_DYNAMIC` node to be placed inside this one | 4235 | // Must be at least `addr_align` for the `PT_DYNAMIC` node to be placed inside this one |
| 3787 | // later (if `have_dynamic_section`). Keep in sync with `elf.ni.data` alignment above. | 4236 | // later (if `have_dynamic_section`). Keep in sync with `elf.ni.data` alignment above. |
| 3788 | .alignment = node_block_align.max(addr_align), | 4237 | .alignment = node_block_align.max(addr_align), |
| 3789 | .moved = true, | 4238 | .moved = true, |
| 3790 | .bubbles_moved = false, | 4239 | .bubbles_moved = false, |
| 3791 | }); | 4240 | }), .{ .segment = phndx.relro }); |
| 3792 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro }); | ||
| 3793 | elf.phdrs.items[phndx.relro] = .wrap(elf.ni.data_rel_ro); | 4241 | elf.phdrs.items[phndx.relro] = .wrap(elf.ni.data_rel_ro); |
| 3794 | 4242 | ||
| 3795 | if (comp.config.any_non_single_threaded) { | 4243 | if (comp.config.any_non_single_threaded) { |
| 3796 | elf.ni.tls = .wrap(try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{ | 4244 | elf.ni.tls = .wrap(elf.addNodeAssumeCapacity( |
| 3797 | .alignment = node_block_align, | 4245 | try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{ |
| 3798 | .moved = true, | 4246 | .alignment = node_block_align, |
| 3799 | .bubbles_moved = false, | 4247 | .moved = true, |
| 3800 | })); | 4248 | .bubbles_moved = false, |
| 3801 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.tls }); | 4249 | }), |
| 4250 | .{ .segment = phndx.tls }, | ||
| 4251 | )); | ||
| 3802 | elf.phdrs.items[phndx.tls] = elf.ni.tls; | 4252 | elf.phdrs.items[phndx.tls] = elf.ni.tls; |
| 3803 | } | 4253 | } |
| 3804 | 4254 | ||
| ... | @@ -3822,11 +4272,10 @@ fn initHeaders( | ... | @@ -3822,11 +4272,10 @@ fn initHeaders( |
| 3822 | .REL => elf.ni.elf, | 4272 | .REL => elf.ni.elf, |
| 3823 | .DYN, .EXEC => elf.ni.rodata, | 4273 | .DYN, .EXEC => elf.ni.rodata, |
| 3824 | }; | 4274 | }; |
| 3825 | elf.ni.ehdr = try parent_ni.addOnlyHeaderChild(&elf.mf, gpa, .{ | 4275 | elf.ni.ehdr = elf.addNodeAssumeCapacity(try parent_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ |
| 3826 | .size = @sizeOf(ElfN.Ehdr), | 4276 | .size = @sizeOf(ElfN.Ehdr), |
| 3827 | .alignment = addr_align, | 4277 | .alignment = addr_align, |
| 3828 | }); | 4278 | }), .ehdr); |
| 3829 | elf.nodes.appendAssumeCapacity(.ehdr); | ||
| 3830 | 4279 | ||
| 3831 | const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf))); | 4280 | const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf))); |
| 3832 | ehdr.ident = .{ | 4281 | ehdr.ident = .{ |
| ... | @@ -3872,17 +4321,16 @@ fn initHeaders( | ... | @@ -3872,17 +4321,16 @@ fn initHeaders( |
| 3872 | ehdr.shentsize = @sizeOf(ElfN.Shdr); | 4321 | ehdr.shentsize = @sizeOf(ElfN.Shdr); |
| 3873 | ehdr.shnum = 1; // Only the SHN_UNDEF shdr initially---will be incremented by `addSection` | 4322 | ehdr.shnum = 1; // Only the SHN_UNDEF shdr initially---will be incremented by `addSection` |
| 3874 | ehdr.shstrndx = std.elf.SHN_UNDEF; | 4323 | ehdr.shstrndx = std.elf.SHN_UNDEF; |
| 3875 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); | 4324 | if (elf.targetEndian() != std.lang.Endian.native) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); |
| 3876 | }, | 4325 | }, |
| 3877 | } | 4326 | } |
| 3878 | 4327 | ||
| 3879 | elf.ni.shdr = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{ | 4328 | elf.ni.shdr = elf.addNodeAssumeCapacity(try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{ |
| 3880 | .size = node_block_align.forward(1 * entsize.sh), // as above, only the SHN_UNDEF initially | 4329 | .size = 1 * entsize.sh, // as above, only the null shdr initially |
| 3881 | .alignment = addr_align.max(node_block_align), | 4330 | .alignment = addr_align, |
| 3882 | .moved = true, | 4331 | .moved = true, |
| 3883 | .resized = true, | 4332 | .resized = true, |
| 3884 | }); | 4333 | }), .shdr); |
| 3885 | elf.nodes.appendAssumeCapacity(.shdr); | ||
| 3886 | 4334 | ||
| 3887 | switch (class) { | 4335 | switch (class) { |
| 3888 | .NONE, _ => unreachable, | 4336 | .NONE, _ => unreachable, |
| ... | @@ -3925,8 +4373,7 @@ fn initHeaders( | ... | @@ -3925,8 +4373,7 @@ fn initHeaders( |
| 3925 | elf.ni.phdr.slice(&elf.mf)[0 .. phnum * @sizeOf(ElfN.Phdr)], | 4373 | elf.ni.phdr.slice(&elf.mf)[0 .. phnum * @sizeOf(ElfN.Phdr)], |
| 3926 | )); | 4374 | )); |
| 3927 | 4375 | ||
| 3928 | const ph_phdr = &phdr[phndx.phdr]; | 4376 | phdr[phndx.phdr] = .{ |
| 3929 | ph_phdr.* = .{ | ||
| 3930 | .type = .PHDR, | 4377 | .type = .PHDR, |
| 3931 | .offset = 0, | 4378 | .offset = 0, |
| 3932 | .vaddr = 0, | 4379 | .vaddr = 0, |
| ... | @@ -3937,22 +4384,18 @@ fn initHeaders( | ... | @@ -3937,22 +4384,18 @@ fn initHeaders( |
| 3937 | .@"align" = @intCast(elf.ni.phdr.alignment(&elf.mf).toByteUnits()), | 4384 | .@"align" = @intCast(elf.ni.phdr.alignment(&elf.mf).toByteUnits()), |
| 3938 | }; | 4385 | }; |
| 3939 | 4386 | ||
| 3940 | if (maybe_interp) |_| { | 4387 | if (maybe_interp) |_| phdr[phndx.interp] = .{ |
| 3941 | const ph_interp = &phdr[phndx.interp]; | 4388 | .type = .INTERP, |
| 3942 | ph_interp.* = .{ | 4389 | .offset = 0, |
| 3943 | .type = .INTERP, | 4390 | .vaddr = 0, |
| 3944 | .offset = 0, | 4391 | .paddr = 0, |
| 3945 | .vaddr = 0, | 4392 | .filesz = 0, |
| 3946 | .paddr = 0, | 4393 | .memsz = 0, |
| 3947 | .filesz = 0, | 4394 | .flags = .{ .R = true }, |
| 3948 | .memsz = 0, | 4395 | .@"align" = 1, |
| 3949 | .flags = .{ .R = true }, | 4396 | }; |
| 3950 | .@"align" = 1, | ||
| 3951 | }; | ||
| 3952 | } | ||
| 3953 | 4397 | ||
| 3954 | const ph_rodata = &phdr[phndx.rodata]; | 4398 | phdr[phndx.rodata] = .{ |
| 3955 | ph_rodata.* = .{ | ||
| 3956 | .type = .NULL, | 4399 | .type = .NULL, |
| 3957 | .offset = 0, | 4400 | .offset = 0, |
| 3958 | .vaddr = @intCast(base_vaddr), | 4401 | .vaddr = @intCast(base_vaddr), |
| ... | @@ -3963,8 +4406,7 @@ fn initHeaders( | ... | @@ -3963,8 +4406,7 @@ fn initHeaders( |
| 3963 | .@"align" = @intCast(page_align.toByteUnits()), | 4406 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3964 | }; | 4407 | }; |
| 3965 | 4408 | ||
| 3966 | const ph_text = &phdr[phndx.text]; | 4409 | phdr[phndx.text] = .{ |
| 3967 | ph_text.* = .{ | ||
| 3968 | .type = .NULL, | 4410 | .type = .NULL, |
| 3969 | .offset = 0, | 4411 | .offset = 0, |
| 3970 | .vaddr = @intCast(base_vaddr), | 4412 | .vaddr = @intCast(base_vaddr), |
| ... | @@ -3975,8 +4417,7 @@ fn initHeaders( | ... | @@ -3975,8 +4417,7 @@ fn initHeaders( |
| 3975 | .@"align" = @intCast(page_align.toByteUnits()), | 4417 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3976 | }; | 4418 | }; |
| 3977 | 4419 | ||
| 3978 | const ph_data = &phdr[phndx.data]; | 4420 | phdr[phndx.data] = .{ |
| 3979 | ph_data.* = .{ | ||
| 3980 | .type = .NULL, | 4421 | .type = .NULL, |
| 3981 | .offset = 0, | 4422 | .offset = 0, |
| 3982 | .vaddr = @intCast(base_vaddr), | 4423 | .vaddr = @intCast(base_vaddr), |
| ... | @@ -3987,50 +4428,40 @@ fn initHeaders( | ... | @@ -3987,50 +4428,40 @@ fn initHeaders( |
| 3987 | .@"align" = @intCast(page_align.toByteUnits()), | 4428 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3988 | }; | 4429 | }; |
| 3989 | 4430 | ||
| 3990 | if (plt.got_plt == null) { | 4431 | if (plt.got_plt == null) phdr[phndx.plt] = .{ |
| 3991 | const ph_plt = &phdr[phndx.plt]; | 4432 | .type = .NULL, |
| 3992 | ph_plt.* = .{ | 4433 | .offset = 0, |
| 3993 | .type = .NULL, | 4434 | .vaddr = @intCast(base_vaddr), |
| 3994 | .offset = 0, | 4435 | .paddr = @intCast(base_vaddr), |
| 3995 | .vaddr = @intCast(base_vaddr), | 4436 | .filesz = 0, |
| 3996 | .paddr = @intCast(base_vaddr), | 4437 | .memsz = 0, |
| 3997 | .filesz = 0, | 4438 | .flags = .{ .R = true, .W = true, .X = true }, |
| 3998 | .memsz = 0, | 4439 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3999 | .flags = .{ .R = true, .W = true, .X = true }, | 4440 | }; |
| 4000 | .@"align" = @intCast(page_align.toByteUnits()), | ||
| 4001 | }; | ||
| 4002 | } | ||
| 4003 | 4441 | ||
| 4004 | if (elf.ni.tls.unwrap()) |tls_segment_ni| { | 4442 | if (elf.ni.tls.unwrap()) |tls_segment_ni| phdr[phndx.tls] = .{ |
| 4005 | const ph_tls = &phdr[phndx.tls]; | 4443 | .type = .TLS, |
| 4006 | ph_tls.* = .{ | 4444 | .offset = 0, |
| 4007 | .type = .TLS, | 4445 | .vaddr = 0, |
| 4008 | .offset = 0, | 4446 | .paddr = 0, |
| 4009 | .vaddr = 0, | 4447 | .filesz = 0, |
| 4010 | .paddr = 0, | 4448 | .memsz = 0, |
| 4011 | .filesz = 0, | 4449 | .flags = .{ .R = true }, |
| 4012 | .memsz = 0, | 4450 | .@"align" = @intCast(tls_segment_ni.alignment(&elf.mf).toByteUnits()), |
| 4013 | .flags = .{ .R = true }, | 4451 | }; |
| 4014 | .@"align" = @intCast(tls_segment_ni.alignment(&elf.mf).toByteUnits()), | ||
| 4015 | }; | ||
| 4016 | } | ||
| 4017 | 4452 | ||
| 4018 | if (have_dynamic_section) { | 4453 | if (have_dynamic) phdr[phndx.dynamic] = .{ |
| 4019 | const ph_dynamic = &phdr[phndx.dynamic]; | 4454 | .type = .DYNAMIC, |
| 4020 | ph_dynamic.* = .{ | 4455 | .offset = 0, |
| 4021 | .type = .DYNAMIC, | 4456 | .vaddr = 0, |
| 4022 | .offset = 0, | 4457 | .paddr = 0, |
| 4023 | .vaddr = 0, | 4458 | .filesz = 0, |
| 4024 | .paddr = 0, | 4459 | .memsz = 0, |
| 4025 | .filesz = 0, | 4460 | .flags = .{ .R = true, .W = true }, |
| 4026 | .memsz = 0, | 4461 | .@"align" = @intCast(addr_align.toByteUnits()), |
| 4027 | .flags = .{ .R = true, .W = true }, | 4462 | }; |
| 4028 | .@"align" = @intCast(addr_align.toByteUnits()), | ||
| 4029 | }; | ||
| 4030 | } | ||
| 4031 | 4463 | ||
| 4032 | const ph_relro = &phdr[phndx.relro]; | 4464 | phdr[phndx.relro] = .{ |
| 4033 | ph_relro.* = .{ | ||
| 4034 | .type = .GNU_RELRO, | 4465 | .type = .GNU_RELRO, |
| 4035 | .offset = 0, | 4466 | .offset = 0, |
| 4036 | .vaddr = 0, | 4467 | .vaddr = 0, |
| ... | @@ -4041,8 +4472,18 @@ fn initHeaders( | ... | @@ -4041,8 +4472,18 @@ fn initHeaders( |
| 4041 | .@"align" = @intCast(elf.ni.data_rel_ro.alignment(&elf.mf).toByteUnits()), | 4472 | .@"align" = @intCast(elf.ni.data_rel_ro.alignment(&elf.mf).toByteUnits()), |
| 4042 | }; | 4473 | }; |
| 4043 | 4474 | ||
| 4044 | const ph_gnu_stack = &phdr[phndx.gnu_stack]; | 4475 | if (have_eh_frame) phdr[phndx.gnu_eh_frame] = .{ |
| 4045 | ph_gnu_stack.* = .{ | 4476 | .type = .GNU_EH_FRAME, |
| 4477 | .offset = 0, | ||
| 4478 | .vaddr = 0, | ||
| 4479 | .paddr = 0, | ||
| 4480 | .filesz = @sizeOf(Dwarf.EhFrameHdr), | ||
| 4481 | .memsz = @sizeOf(Dwarf.EhFrameHdr), | ||
| 4482 | .flags = .{ .R = true }, | ||
| 4483 | .@"align" = 4, | ||
| 4484 | }; | ||
| 4485 | |||
| 4486 | phdr[phndx.gnu_stack] = .{ | ||
| 4046 | .type = .GNU_STACK, | 4487 | .type = .GNU_STACK, |
| 4047 | .offset = 0, | 4488 | .offset = 0, |
| 4048 | .vaddr = 0, | 4489 | .vaddr = 0, |
| ... | @@ -4071,7 +4512,7 @@ fn initHeaders( | ... | @@ -4071,7 +4512,7 @@ fn initHeaders( |
| 4071 | .addralign = 0, | 4512 | .addralign = 0, |
| 4072 | .entsize = 0, | 4513 | .entsize = 0, |
| 4073 | }; | 4514 | }; |
| 4074 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef); | 4515 | if (target_endian != std.lang.Endian.native) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef); |
| 4075 | 4516 | ||
| 4076 | elf.symtab.addOneAssumeCapacity().* = .{ | 4517 | elf.symtab.addOneAssumeCapacity().* = .{ |
| 4077 | .node = .none, | 4518 | .node = .none, |
| ... | @@ -4084,6 +4525,7 @@ fn initHeaders( | ... | @@ -4084,6 +4525,7 @@ fn initHeaders( |
| 4084 | .entsize = @sizeOf(ElfN.Sym), | 4525 | .entsize = @sizeOf(ElfN.Sym), |
| 4085 | .node_align = node_block_align, | 4526 | .node_align = node_block_align, |
| 4086 | .info = 1, // index of first non-local symbol | 4527 | .info = 1, // index of first non-local symbol |
| 4528 | .manual_size = true, | ||
| 4087 | })); | 4529 | })); |
| 4088 | const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class)); | 4530 | const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class)); |
| 4089 | symtab_null.* = .{ | 4531 | symtab_null.* = .{ |
| ... | @@ -4094,7 +4536,7 @@ fn initHeaders( | ... | @@ -4094,7 +4536,7 @@ fn initHeaders( |
| 4094 | .other = .{ .visibility = .DEFAULT }, | 4536 | .other = .{ .visibility = .DEFAULT }, |
| 4095 | .shndx = std.elf.SHN_UNDEF, | 4537 | .shndx = std.elf.SHN_UNDEF, |
| 4096 | }; | 4538 | }; |
| 4097 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null); | 4539 | if (target_endian != std.lang.Endian.native) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null); |
| 4098 | 4540 | ||
| 4099 | const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class)); | 4541 | const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class)); |
| 4100 | ehdr.shstrndx = ehdr.shnum; | 4542 | ehdr.shstrndx = ehdr.shnum; |
| ... | @@ -4105,6 +4547,7 @@ fn initHeaders( | ... | @@ -4105,6 +4547,7 @@ fn initHeaders( |
| 4105 | .size = 1, | 4547 | .size = 1, |
| 4106 | .entsize = 1, | 4548 | .entsize = 1, |
| 4107 | .node_align = node_block_align, | 4549 | .node_align = node_block_align, |
| 4550 | .manual_size = true, | ||
| 4108 | })); | 4551 | })); |
| 4109 | Section.Index.get(.shstrtab, elf).ni.slice(&elf.mf)[0] = 0; | 4552 | Section.Index.get(.shstrtab, elf).ni.slice(&elf.mf)[0] = 0; |
| 4110 | 4553 | ||
| ... | @@ -4117,6 +4560,7 @@ fn initHeaders( | ... | @@ -4117,6 +4560,7 @@ fn initHeaders( |
| 4117 | .size = 1, | 4560 | .size = 1, |
| 4118 | .entsize = 1, | 4561 | .entsize = 1, |
| 4119 | .node_align = node_block_align, | 4562 | .node_align = node_block_align, |
| 4563 | .manual_size = true, | ||
| 4120 | })); | 4564 | })); |
| 4121 | Section.Index.get(.strtab, elf).ni.slice(&elf.mf)[0] = 0; | 4565 | Section.Index.get(.strtab, elf).ni.slice(&elf.mf)[0] = 0; |
| 4122 | switch (elf.shdrPtr(.symtab)) { | 4566 | switch (elf.shdrPtr(.symtab)) { |
| ... | @@ -4156,6 +4600,7 @@ fn initHeaders( | ... | @@ -4156,6 +4600,7 @@ fn initHeaders( |
| 4156 | .flags = .{ .WRITE = true, .ALLOC = true }, | 4600 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 4157 | .addralign = addr_align, | 4601 | .addralign = addr_align, |
| 4158 | .entsize = @intCast(addr_align.toByteUnits()), | 4602 | .entsize = @intCast(addr_align.toByteUnits()), |
| 4603 | .manual_size = true, | ||
| 4159 | }); | 4604 | }); |
| 4160 | { | 4605 | { |
| 4161 | const init_plt_size = plt.entry_size * plt.header_entries; | 4606 | const init_plt_size = plt.entry_size * plt.header_entries; |
| ... | @@ -4168,6 +4613,7 @@ fn initHeaders( | ... | @@ -4168,6 +4613,7 @@ fn initHeaders( |
| 4168 | .size = got_plt.header_entries * elf.targetPtrSize(), | 4613 | .size = got_plt.header_entries * elf.targetPtrSize(), |
| 4169 | .addralign = addr_align, | 4614 | .addralign = addr_align, |
| 4170 | .entsize = @intCast(addr_align.toByteUnits()), | 4615 | .entsize = @intCast(addr_align.toByteUnits()), |
| 4616 | .manual_size = true, | ||
| 4171 | }); | 4617 | }); |
| 4172 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ | 4618 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ |
| 4173 | .name = ".plt", | 4619 | .name = ".plt", |
| ... | @@ -4176,6 +4622,7 @@ fn initHeaders( | ... | @@ -4176,6 +4622,7 @@ fn initHeaders( |
| 4176 | .size = plt.@"align".forward(init_plt_size), | 4622 | .size = plt.@"align".forward(init_plt_size), |
| 4177 | .addralign = plt.@"align", | 4623 | .addralign = plt.@"align", |
| 4178 | .node_align = node_block_align, | 4624 | .node_align = node_block_align, |
| 4625 | .manual_size = true, | ||
| 4179 | }); | 4626 | }); |
| 4180 | } else { | 4627 | } else { |
| 4181 | elf.shndx.plt = try elf.addSection(elf.phdrs.items[phndx.plt].unwrap().?, .{ | 4628 | elf.shndx.plt = try elf.addSection(elf.phdrs.items[phndx.plt].unwrap().?, .{ |
| ... | @@ -4185,6 +4632,7 @@ fn initHeaders( | ... | @@ -4185,6 +4632,7 @@ fn initHeaders( |
| 4185 | .size = plt.@"align".forward(init_plt_size), | 4632 | .size = plt.@"align".forward(init_plt_size), |
| 4186 | .addralign = plt.@"align", | 4633 | .addralign = plt.@"align", |
| 4187 | .node_align = node_block_align, | 4634 | .node_align = node_block_align, |
| 4635 | .manual_size = true, | ||
| 4188 | }); | 4636 | }); |
| 4189 | } | 4637 | } |
| 4190 | // And the award for most annoying PLT requirement goes to SPARC, which decided that the | 4638 | // And the award for most annoying PLT requirement goes to SPARC, which decided that the |
| ... | @@ -4203,13 +4651,15 @@ fn initHeaders( | ... | @@ -4203,13 +4651,15 @@ fn initHeaders( |
| 4203 | .node_align = node_block_align, | 4651 | .node_align = node_block_align, |
| 4204 | }); | 4652 | }); |
| 4205 | if (maybe_interp) |interp| { | 4653 | if (maybe_interp) |interp| { |
| 4206 | const interp_ni = try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{ | 4654 | const interp_ni = elf.addNodeAssumeCapacity( |
| 4207 | .size = interp.len + 1, | 4655 | try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{ |
| 4208 | .moved = true, | 4656 | .size = interp.len + 1, |
| 4209 | .resized = true, | 4657 | .moved = true, |
| 4210 | .bubbles_moved = false, | 4658 | .resized = true, |
| 4211 | }); | 4659 | .bubbles_moved = false, |
| 4212 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.interp }); | 4660 | }), |
| 4661 | .{ .segment = phndx.interp }, | ||
| 4662 | ); | ||
| 4213 | elf.phdrs.items[phndx.interp] = .wrap(interp_ni); | 4663 | elf.phdrs.items[phndx.interp] = .wrap(interp_ni); |
| 4214 | 4664 | ||
| 4215 | const sec_interp_shndx = try elf.addSection(interp_ni, .{ | 4665 | const sec_interp_shndx = try elf.addSection(interp_ni, .{ |
| ... | @@ -4222,14 +4672,16 @@ fn initHeaders( | ... | @@ -4222,14 +4672,16 @@ fn initHeaders( |
| 4222 | @memcpy(sec_interp[0..interp.len], interp); | 4672 | @memcpy(sec_interp[0..interp.len], interp); |
| 4223 | sec_interp[interp.len] = 0; | 4673 | sec_interp[interp.len] = 0; |
| 4224 | } | 4674 | } |
| 4225 | if (have_dynamic_section) { | 4675 | if (have_dynamic) { |
| 4226 | assert(elf.ni.data_rel_ro.alignment(&elf.mf).compare(.gte, addr_align)); | 4676 | assert(elf.ni.data_rel_ro.alignment(&elf.mf).compare(.gte, addr_align)); |
| 4227 | const dynamic_ni = try elf.ni.data_rel_ro.addFloatingChild(&elf.mf, gpa, .{ | 4677 | const dynamic_ni = elf.addNodeAssumeCapacity( |
| 4228 | .alignment = addr_align, | 4678 | try elf.ni.data_rel_ro.addFloatingChild(gpa, &elf.mf, .{ |
| 4229 | .moved = true, | 4679 | .alignment = addr_align, |
| 4230 | .bubbles_moved = false, | 4680 | .moved = true, |
| 4231 | }); | 4681 | .bubbles_moved = false, |
| 4232 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.dynamic }); | 4682 | }), |
| 4683 | .{ .segment = phndx.dynamic }, | ||
| 4684 | ); | ||
| 4233 | elf.phdrs.items[phndx.dynamic] = .wrap(dynamic_ni); | 4685 | elf.phdrs.items[phndx.dynamic] = .wrap(dynamic_ni); |
| 4234 | 4686 | ||
| 4235 | const dynstr_shndx = try elf.addSection(elf.ni.rodata, .{ | 4687 | const dynstr_shndx = try elf.addSection(elf.ni.rodata, .{ |
| ... | @@ -4239,6 +4691,7 @@ fn initHeaders( | ... | @@ -4239,6 +4691,7 @@ fn initHeaders( |
| 4239 | .size = 1, | 4691 | .size = 1, |
| 4240 | .entsize = 1, | 4692 | .entsize = 1, |
| 4241 | .node_align = node_block_align, | 4693 | .node_align = node_block_align, |
| 4694 | .manual_size = true, | ||
| 4242 | }); | 4695 | }); |
| 4243 | dynstr_shndx.get(elf).ni.slice(&elf.mf)[0] = 0; | 4696 | dynstr_shndx.get(elf).ni.slice(&elf.mf)[0] = 0; |
| 4244 | elf.shndx.dynstr = dynstr_shndx; | 4697 | elf.shndx.dynstr = dynstr_shndx; |
| ... | @@ -4257,6 +4710,7 @@ fn initHeaders( | ... | @@ -4257,6 +4710,7 @@ fn initHeaders( |
| 4257 | .addralign = addr_align, | 4710 | .addralign = addr_align, |
| 4258 | .entsize = @sizeOf(Sym), | 4711 | .entsize = @sizeOf(Sym), |
| 4259 | .node_align = node_block_align, | 4712 | .node_align = node_block_align, |
| 4713 | .manual_size = true, | ||
| 4260 | }); | 4714 | }); |
| 4261 | const dynsym_null = @field(elf.dynsymPtr(0), @tagName(ct_class)); | 4715 | const dynsym_null = @field(elf.dynsymPtr(0), @tagName(ct_class)); |
| 4262 | dynsym_null.* = .{ | 4716 | dynsym_null.* = .{ |
| ... | @@ -4267,7 +4721,7 @@ fn initHeaders( | ... | @@ -4267,7 +4721,7 @@ fn initHeaders( |
| 4267 | .other = .{ .visibility = .DEFAULT }, | 4721 | .other = .{ .visibility = .DEFAULT }, |
| 4268 | .shndx = std.elf.SHN_UNDEF, | 4722 | .shndx = std.elf.SHN_UNDEF, |
| 4269 | }; | 4723 | }; |
| 4270 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields( | 4724 | if (elf.targetEndian() != std.lang.Endian.native) std.mem.byteSwapAllFields( |
| 4271 | Sym, | 4725 | Sym, |
| 4272 | dynsym_null, | 4726 | dynsym_null, |
| 4273 | ); | 4727 | ); |
| ... | @@ -4285,6 +4739,7 @@ fn initHeaders( | ... | @@ -4285,6 +4739,7 @@ fn initHeaders( |
| 4285 | .addralign = addr_align, | 4739 | .addralign = addr_align, |
| 4286 | .entsize = rela_size, | 4740 | .entsize = rela_size, |
| 4287 | .node_align = node_block_align, | 4741 | .node_align = node_block_align, |
| 4742 | .manual_size = true, | ||
| 4288 | }); | 4743 | }); |
| 4289 | elf.shndx.rela_plt = try elf.addSection(elf.ni.rodata, .{ | 4744 | elf.shndx.rela_plt = try elf.addSection(elf.ni.rodata, .{ |
| 4290 | .name = ".rela.plt", | 4745 | .name = ".rela.plt", |
| ... | @@ -4295,6 +4750,7 @@ fn initHeaders( | ... | @@ -4295,6 +4750,7 @@ fn initHeaders( |
| 4295 | .addralign = addr_align, | 4750 | .addralign = addr_align, |
| 4296 | .entsize = rela_size, | 4751 | .entsize = rela_size, |
| 4297 | .node_align = node_block_align, | 4752 | .node_align = node_block_align, |
| 4753 | .manual_size = true, | ||
| 4298 | }); | 4754 | }); |
| 4299 | elf.shndx.dynamic = try elf.addSection(dynamic_ni, .{ | 4755 | elf.shndx.dynamic = try elf.addSection(dynamic_ni, .{ |
| 4300 | .name = ".dynamic", | 4756 | .name = ".dynamic", |
| ... | @@ -4303,6 +4759,7 @@ fn initHeaders( | ... | @@ -4303,6 +4759,7 @@ fn initHeaders( |
| 4303 | .link = dynstr_shndx.toSection().?, | 4759 | .link = dynstr_shndx.toSection().?, |
| 4304 | .entsize = @intCast(addr_align.toByteUnits() * 2), | 4760 | .entsize = @intCast(addr_align.toByteUnits() * 2), |
| 4305 | .addralign = addr_align, | 4761 | .addralign = addr_align, |
| 4762 | .manual_size = true, | ||
| 4306 | }); | 4763 | }); |
| 4307 | switch (elf.targetDynsymHashInfo()) { | 4764 | switch (elf.targetDynsymHashInfo()) { |
| 4308 | inline else => |info| { | 4765 | inline else => |info| { |
| ... | @@ -4318,6 +4775,7 @@ fn initHeaders( | ... | @@ -4318,6 +4775,7 @@ fn initHeaders( |
| 4318 | .addralign = .fromByteUnits(@sizeOf(info.Int())), | 4775 | .addralign = .fromByteUnits(@sizeOf(info.Int())), |
| 4319 | // initially: nbucket = 8 + nchain = 1 | 4776 | // initially: nbucket = 8 + nchain = 1 |
| 4320 | .size = @sizeOf(info.Header()) + @sizeOf(info.Int()) * (8 + 1), | 4777 | .size = @sizeOf(info.Header()) + @sizeOf(info.Int()) * (8 + 1), |
| 4778 | .manual_size = true, | ||
| 4321 | }); | 4779 | }); |
| 4322 | const hash_slice: []align(@sizeOf(info.Int())) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); | 4780 | const hash_slice: []align(@sizeOf(info.Int())) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| 4323 | const header: *info.Header() = @ptrCast(hash_slice[0..@sizeOf(info.Header())]); | 4781 | const header: *info.Header() = @ptrCast(hash_slice[0..@sizeOf(info.Header())]); |
| ... | @@ -4386,34 +4844,78 @@ fn initHeaders( | ... | @@ -4386,34 +4844,78 @@ fn initHeaders( |
| 4386 | elf.plt_first_symbol_reloc = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | 4844 | elf.plt_first_symbol_reloc = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| 4387 | try elf.ensureUnusedRelocCapacity(plt_ni, 3); | 4845 | try elf.ensureUnusedRelocCapacity(plt_ni, 3); |
| 4388 | elf.addRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .{ .LARCH = .PCALA_HI20 }) catch |err| switch (err) { | 4846 | elf.addRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .{ .LARCH = .PCALA_HI20 }) catch |err| switch (err) { |
| 4847 | else => |e| return e, | ||
| 4389 | error.UnknownRelocation => unreachable, | 4848 | error.UnknownRelocation => unreachable, |
| 4390 | error.NonStaticRelocation => unreachable, | 4849 | error.NonStaticRelocation => unreachable, |
| 4391 | error.UnimplementedRelocation => unreachable, | 4850 | error.UnimplementedRelocation => unreachable, |
| 4392 | else => |e| return e, | ||
| 4393 | }; | 4851 | }; |
| 4394 | elf.addRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .{ .LARCH = .PCALA_LO12 }) catch |err| switch (err) { | 4852 | elf.addRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .{ .LARCH = .PCALA_LO12 }) catch |err| switch (err) { |
| 4853 | else => |e| return e, | ||
| 4395 | error.UnknownRelocation => unreachable, | 4854 | error.UnknownRelocation => unreachable, |
| 4396 | error.NonStaticRelocation => unreachable, | 4855 | error.NonStaticRelocation => unreachable, |
| 4397 | error.UnimplementedRelocation => unreachable, | 4856 | error.UnimplementedRelocation => unreachable, |
| 4398 | else => |e| return e, | ||
| 4399 | }; | 4857 | }; |
| 4400 | elf.addRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .{ .LARCH = .PCALA_LO12 }) catch |err| switch (err) { | 4858 | elf.addRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .{ .LARCH = .PCALA_LO12 }) catch |err| switch (err) { |
| 4859 | else => |e| return e, | ||
| 4401 | error.UnknownRelocation => unreachable, | 4860 | error.UnknownRelocation => unreachable, |
| 4402 | error.NonStaticRelocation => unreachable, | 4861 | error.NonStaticRelocation => unreachable, |
| 4403 | error.UnimplementedRelocation => unreachable, | 4862 | error.UnimplementedRelocation => unreachable, |
| 4404 | else => |e| return e, | ||
| 4405 | }; | 4863 | }; |
| 4406 | }, | 4864 | }, |
| 4407 | .SPARCV9 => {}, | 4865 | .SPARCV9 => {}, |
| 4408 | } | 4866 | } |
| 4409 | } | 4867 | } |
| 4868 | if (have_eh_frame) { | ||
| 4869 | const gnu_eh_frame = elf.addNodeAssumeCapacity( | ||
| 4870 | try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{ | ||
| 4871 | .size = @sizeOf(Dwarf.EhFrameHdr), | ||
| 4872 | .alignment = .@"4", | ||
| 4873 | .moved = true, | ||
| 4874 | .bubbles_moved = false, | ||
| 4875 | }), | ||
| 4876 | .{ .segment = phndx.gnu_eh_frame }, | ||
| 4877 | ); | ||
| 4878 | elf.ni.gnu_eh_frame = .wrap(gnu_eh_frame); | ||
| 4879 | elf.phdrs.items[phndx.gnu_eh_frame] = elf.ni.gnu_eh_frame; | ||
| 4880 | |||
| 4881 | elf.shndx.eh_frame_hdr = try elf.addSection(gnu_eh_frame, .{ | ||
| 4882 | .name = ".eh_frame_hdr", | ||
| 4883 | .type = .PROGBITS, | ||
| 4884 | .flags = .{ .ALLOC = true }, | ||
| 4885 | .size = @sizeOf(Dwarf.EhFrameHdr), | ||
| 4886 | .addralign = .@"4", | ||
| 4887 | }); | ||
| 4888 | elf.shndx.eh_frame = try elf.addSection(elf.ni.rodata, .{ | ||
| 4889 | .name = ".eh_frame", | ||
| 4890 | .flags = .{ .ALLOC = true }, | ||
| 4891 | .addralign = addr_align, | ||
| 4892 | .node_align = elf.mf.flags.block_size, | ||
| 4893 | .manual_size = true, | ||
| 4894 | }); | ||
| 4895 | |||
| 4896 | const eh_frame_hdr_ni = elf.shndx.eh_frame_hdr.get(elf).ni; | ||
| 4897 | elf.eh_frame_hdr_first_symbol_reloc = | ||
| 4898 | @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | ||
| 4899 | try elf.dwarf.genEhFrameHdr( | ||
| 4900 | Node.toAtom(eh_frame_hdr_ni), | ||
| 4901 | @ptrCast(@alignCast(eh_frame_hdr_ni.slice(&elf.mf))), | ||
| 4902 | Symbol.Id.local(elf.shndx.eh_frame.get(elf).lsi).toTypeErased(), | ||
| 4903 | ); | ||
| 4904 | _ = elf.addNodeAssumeCapacity( | ||
| 4905 | try elf.shndx.eh_frame.get(elf).ni.addOnlyFooterChild(gpa, &elf.mf, .{ | ||
| 4906 | .size = addr_align.forward(4), | ||
| 4907 | .alignment = addr_align, | ||
| 4908 | }), | ||
| 4909 | .eh_frame_footer, | ||
| 4910 | ); | ||
| 4911 | } | ||
| 4410 | 4912 | ||
| 4411 | // Populate reserved GOT words. | 4913 | // Populate reserved GOT words. |
| 4412 | switch (machine) { | 4914 | switch (machine) { |
| 4413 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), | 4915 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), |
| 4414 | .X86_64 => { | 4916 | .X86_64 => { |
| 4415 | try elf.got.ensureUnusedCapacity(gpa, 3); | 4917 | try elf.got.ensureUnusedCapacity(gpa, 3); |
| 4416 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { | 4918 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic) { |
| 4417 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, | 4919 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, |
| 4418 | false => .{ .reserved = 0 }, | 4920 | false => .{ .reserved = 0 }, |
| 4419 | }, .none); | 4921 | }, .none); |
| ... | @@ -4422,7 +4924,7 @@ fn initHeaders( | ... | @@ -4422,7 +4924,7 @@ fn initHeaders( |
| 4422 | }, | 4924 | }, |
| 4423 | .LOONGARCH, .SPARCV9 => { | 4925 | .LOONGARCH, .SPARCV9 => { |
| 4424 | try elf.got.ensureUnusedCapacity(gpa, 1); | 4926 | try elf.got.ensureUnusedCapacity(gpa, 1); |
| 4425 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { | 4927 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic) { |
| 4426 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, | 4928 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, |
| 4427 | false => .{ .reserved = 0 }, | 4929 | false => .{ .reserved = 0 }, |
| 4428 | }, .none); | 4930 | }, .none); |
| ... | @@ -4567,7 +5069,7 @@ fn initHeaders( | ... | @@ -4567,7 +5069,7 @@ fn initHeaders( |
| 4567 | }) catch |err| switch (err) { | 5069 | }) catch |err| switch (err) { |
| 4568 | error.MultipleDefinitions => unreachable, // no inputs are processed yet | 5070 | error.MultipleDefinitions => unreachable, // no inputs are processed yet |
| 4569 | }; | 5071 | }; |
| 4570 | if (have_dynamic_section) { | 5072 | if (have_dynamic) { |
| 4571 | _ = elf.addGlobalSymbolAssumeCapacity(.{ | 5073 | _ = elf.addGlobalSymbolAssumeCapacity(.{ |
| 4572 | .node = .wrap(elf.shndx.dynamic.get(elf).ni), | 5074 | .node = .wrap(elf.shndx.dynamic.get(elf).ni), |
| 4573 | .name = try .string(elf, "_DYNAMIC"), | 5075 | .name = try .string(elf, "_DYNAMIC"), |
| ... | @@ -4583,13 +5085,57 @@ fn initHeaders( | ... | @@ -4583,13 +5085,57 @@ fn initHeaders( |
| 4583 | } | 5085 | } |
| 4584 | } else { | 5086 | } else { |
| 4585 | assert(maybe_interp == null); | 5087 | assert(maybe_interp == null); |
| 4586 | assert(!have_dynamic_section); | 5088 | assert(!have_dynamic); |
| 5089 | if (have_eh_frame) elf.shndx.eh_frame = try elf.addSection(elf.ni.rodata, .{ | ||
| 5090 | .name = ".eh_frame", | ||
| 5091 | .type = if (machine == .X86_64) .X86_64_UNWIND else .NULL, | ||
| 5092 | .flags = .{ .ALLOC = true }, | ||
| 5093 | .addralign = addr_align, | ||
| 5094 | .node_align = elf.mf.flags.block_size, | ||
| 5095 | .manual_size = true, | ||
| 5096 | }); | ||
| 4587 | } | 5097 | } |
| 4588 | if (elf.ni.tls.unwrap()) |tls_segment_ni| elf.shndx.tdata = try elf.addSection(tls_segment_ni, .{ | 5098 | if (elf.ni.tls.unwrap()) |tls_segment_ni| elf.shndx.tdata = try elf.addSection(tls_segment_ni, .{ |
| 4589 | .name = ".tdata", | 5099 | .name = ".tdata", |
| 4590 | .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, | 5100 | .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, |
| 4591 | .node_align = node_block_align, | 5101 | .node_align = node_block_align, |
| 4592 | }); | 5102 | }); |
| 5103 | switch (comp.config.debug_format) { | ||
| 5104 | .strip => {}, | ||
| 5105 | .dwarf => { | ||
| 5106 | elf.shndx.debug_abbrev = try elf.addSection(elf.ni.elf, .{ .name = ".debug_abbrev" }); | ||
| 5107 | if (have_debug_frame) elf.shndx.debug_frame = try elf.addSection(elf.ni.elf, .{ | ||
| 5108 | .name = ".debug_frame", | ||
| 5109 | .addralign = addr_align, | ||
| 5110 | .node_align = elf.mf.flags.block_size, | ||
| 5111 | .manual_size = true, | ||
| 5112 | }); | ||
| 5113 | elf.shndx.debug_info = try elf.addSection(elf.ni.elf, .{ | ||
| 5114 | .name = ".debug_info", | ||
| 5115 | .node_align = elf.mf.flags.block_size, | ||
| 5116 | }); | ||
| 5117 | elf.shndx.debug_line = try elf.addSection(elf.ni.elf, .{ | ||
| 5118 | .name = ".debug_line", | ||
| 5119 | .node_align = elf.mf.flags.block_size, | ||
| 5120 | }); | ||
| 5121 | elf.shndx.debug_line_str = try elf.addSection(elf.ni.elf, .{ | ||
| 5122 | .name = ".debug_line_str", | ||
| 5123 | .flags = .{ .MERGE = true, .STRINGS = true }, | ||
| 5124 | }); | ||
| 5125 | elf.shndx.debug_rnglists = try elf.addSection(elf.ni.elf, .{ | ||
| 5126 | .name = ".debug_rnglists", | ||
| 5127 | .node_align = elf.mf.flags.block_size, | ||
| 5128 | }); | ||
| 5129 | elf.shndx.debug_str = try elf.addSection(elf.ni.elf, .{ | ||
| 5130 | .name = ".debug_str", | ||
| 5131 | .flags = .{ .MERGE = true, .STRINGS = true }, | ||
| 5132 | }); | ||
| 5133 | elf.shndx.debug_str_offsets = try elf.addSection(elf.ni.elf, .{ | ||
| 5134 | .name = ".debug_str_offsets", | ||
| 5135 | }); | ||
| 5136 | }, | ||
| 5137 | .code_view => unreachable, | ||
| 5138 | } | ||
| 4593 | 5139 | ||
| 4594 | assert(elf.nodes.len == expected_nodes_len); | 5140 | assert(elf.nodes.len == expected_nodes_len); |
| 4595 | assert(elf.shdrs.items.len == shnum - 1); // -1 to exclude SHN_UNDEF | 5141 | assert(elf.shdrs.items.len == shnum - 1); // -1 to exclude SHN_UNDEF |
| ... | @@ -4599,7 +5145,7 @@ fn initHeaders( | ... | @@ -4599,7 +5145,7 @@ fn initHeaders( |
| 4599 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); | 5145 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); |
| 4600 | } | 5146 | } |
| 4601 | 5147 | ||
| 4602 | if (have_dynamic_section) elf.dynamic = .{ | 5148 | if (have_dynamic) elf.dynamic = .{ |
| 4603 | .flags = if (elf.options.z_now) std.elf.DF_BIND_NOW else 0, | 5149 | .flags = if (elf.options.z_now) std.elf.DF_BIND_NOW else 0, |
| 4604 | .flags_1 = f: { | 5150 | .flags_1 = f: { |
| 4605 | var f: u32 = 0; | 5151 | var f: u32 = 0; |
| ... | @@ -4642,11 +5188,6 @@ fn initHeaders( | ... | @@ -4642,11 +5188,6 @@ fn initHeaders( |
| 4642 | pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void { | 5188 | pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void { |
| 4643 | prog_node.increaseEstimatedTotalItems(4); | 5189 | prog_node.increaseEstimatedTotalItems(4); |
| 4644 | elf.const_prog_node = prog_node.start("Constants", elf.pending_uavs.items.len); | 5190 | elf.const_prog_node = prog_node.start("Constants", elf.pending_uavs.items.len); |
| 4645 | elf.synth_prog_node = prog_node.start("Synthetics", count: { | ||
| 4646 | var count: usize = 0; | ||
| 4647 | for (&elf.lazy.values) |*lazy| count += lazy.map.count() - lazy.pending_index; | ||
| 4648 | break :count count; | ||
| 4649 | }); | ||
| 4650 | elf.mf.update_prog_node = prog_node.start("Relocations", elf.mf.updates.items.len); | 5191 | elf.mf.update_prog_node = prog_node.start("Relocations", elf.mf.updates.items.len); |
| 4651 | elf.input_prog_node = prog_node.start("Inputs", (elf.inputs.items.len - elf.input_pending_index) + | 5192 | elf.input_prog_node = prog_node.start("Inputs", (elf.inputs.items.len - elf.input_pending_index) + |
| 4652 | (elf.input_sections.items.len - elf.input_section_pending_index)); | 5193 | (elf.input_sections.items.len - elf.input_section_pending_index)); |
| ... | @@ -4657,8 +5198,6 @@ pub fn endProgress(elf: *Elf) void { | ... | @@ -4657,8 +5198,6 @@ pub fn endProgress(elf: *Elf) void { |
| 4657 | elf.input_prog_node = .none; | 5198 | elf.input_prog_node = .none; |
| 4658 | elf.mf.update_prog_node.end(); | 5199 | elf.mf.update_prog_node.end(); |
| 4659 | elf.mf.update_prog_node = .none; | 5200 | elf.mf.update_prog_node = .none; |
| 4660 | elf.synth_prog_node.end(); | ||
| 4661 | elf.synth_prog_node = .none; | ||
| 4662 | elf.const_prog_node.end(); | 5201 | elf.const_prog_node.end(); |
| 4663 | elf.const_prog_node = .none; | 5202 | elf.const_prog_node = .none; |
| 4664 | } | 5203 | } |
| ... | @@ -4669,6 +5208,7 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { | ... | @@ -4669,6 +5208,7 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { |
| 4669 | /// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data. | 5208 | /// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data. |
| 4670 | fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { | 5209 | fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { |
| 4671 | return switch (elf.getNode(ni)) { | 5210 | return switch (elf.getNode(ni)) { |
| 5211 | .deleted, | ||
| 4672 | .archive, | 5212 | .archive, |
| 4673 | .archive_header, | 5213 | .archive_header, |
| 4674 | .archive_input_member, | 5214 | .archive_input_member, |
| ... | @@ -4678,18 +5218,43 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { | ... | @@ -4678,18 +5218,43 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { |
| 4678 | .shdr, | 5218 | .shdr, |
| 4679 | .segment, | 5219 | .segment, |
| 4680 | => unreachable, | 5220 | => unreachable, |
| 4681 | .section => |shndx| shndx, | 5221 | .section, .section_manual_size => |shndx| shndx, |
| 4682 | .input_section, | 5222 | .input_section, |
| 4683 | .copied_global, | 5223 | .copied_global, |
| 4684 | .nav, | 5224 | .nav, |
| 4685 | .uav, | 5225 | .uav, |
| 4686 | .lazy_code, | 5226 | .lazy_code, |
| 4687 | .lazy_const_data, | 5227 | .lazy_const_data, |
| 4688 | => elf.getNode(ni.parent(&elf.mf).unwrap().?).section, | 5228 | .debug_shared, |
| 5229 | .eh_frame_footer, | ||
| 5230 | .unit_padding, | ||
| 5231 | .unit_frame, | ||
| 5232 | .unit_debug_info, | ||
| 5233 | .unit_debug_line, | ||
| 5234 | .unit_debug_rnglists, | ||
| 5235 | => switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) { | ||
| 5236 | else => unreachable, | ||
| 5237 | .section, .section_manual_size => |shndx| shndx, | ||
| 5238 | }, | ||
| 5239 | .unit_frame_cie, | ||
| 5240 | .unit_debug_info_header, | ||
| 5241 | .unit_debug_info_footer, | ||
| 5242 | .unit_debug_line_header, | ||
| 5243 | .const_debug_info, | ||
| 5244 | .global_debug_info, | ||
| 5245 | .func_frame_fde, | ||
| 5246 | .func_debug_info, | ||
| 5247 | .func_debug_line, | ||
| 5248 | .decl_debug_info, | ||
| 5249 | => switch (elf.getNode(ni.parent(&elf.mf).unwrap().?.parent(&elf.mf).unwrap().?)) { | ||
| 5250 | else => unreachable, | ||
| 5251 | .section, .section_manual_size => |shndx| shndx, | ||
| 5252 | }, | ||
| 4689 | }; | 5253 | }; |
| 4690 | } | 5254 | } |
| 4691 | fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 5255 | fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4692 | return switch (elf.getNode(ni)) { | 5256 | return switch (elf.getNode(ni)) { |
| 5257 | .deleted, | ||
| 4693 | .archive, | 5258 | .archive, |
| 4694 | .archive_header, | 5259 | .archive_header, |
| 4695 | .archive_input_member, | 5260 | .archive_input_member, |
| ... | @@ -4700,17 +5265,37 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ... | @@ -4700,17 +5265,37 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4700 | .segment, | 5265 | .segment, |
| 4701 | .copied_global, | 5266 | .copied_global, |
| 4702 | => unreachable, | 5267 | => unreachable, |
| 4703 | .section => |shndx| shndx.vaddr(elf), | 5268 | .section, .section_manual_size => |shndx| shndx.vaddr(elf), |
| 4704 | .input_section => |isi| isi.ptrConst(elf).vaddr, | 5269 | .input_section => |isi| isi.ptrConst(elf).vaddr, |
| 4705 | inline .nav, | 5270 | inline .nav, |
| 4706 | .uav, | 5271 | .uav, |
| 4707 | .lazy_code, | 5272 | .lazy_code, |
| 4708 | .lazy_const_data, | 5273 | .lazy_const_data, |
| 4709 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | 5274 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), |
| 5275 | .debug_shared, | ||
| 5276 | .eh_frame_footer, | ||
| 5277 | .unit_padding, | ||
| 5278 | .unit_frame, | ||
| 5279 | .unit_frame_cie, | ||
| 5280 | .unit_debug_info, | ||
| 5281 | .unit_debug_info_header, | ||
| 5282 | .unit_debug_info_footer, | ||
| 5283 | .unit_debug_line, | ||
| 5284 | .unit_debug_line_header, | ||
| 5285 | .unit_debug_rnglists, | ||
| 5286 | .const_debug_info, | ||
| 5287 | .global_debug_info, | ||
| 5288 | .func_frame_fde, | ||
| 5289 | .func_debug_info, | ||
| 5290 | .func_debug_line, | ||
| 5291 | .decl_debug_info, | ||
| 5292 | => elf.computeNodeVAddr(ni), | ||
| 4710 | }; | 5293 | }; |
| 4711 | } | 5294 | } |
| 4712 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 5295 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4713 | const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) { | 5296 | const parent_ni = ni.parent(&elf.mf).unwrap().?; |
| 5297 | const parent_vaddr = parent_vaddr: switch (elf.getNode(parent_ni)) { | ||
| 5298 | .deleted, | ||
| 4714 | .archive, | 5299 | .archive, |
| 4715 | .archive_header, | 5300 | .archive_header, |
| 4716 | .archive_input_member, | 5301 | .archive_input_member, |
| ... | @@ -4721,14 +5306,72 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ... | @@ -4721,14 +5306,72 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4721 | .segment => |phndx| switch (elf.phdrSlice()) { | 5306 | .segment => |phndx| switch (elf.phdrSlice()) { |
| 4722 | inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr), | 5307 | inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr), |
| 4723 | }, | 5308 | }, |
| 4724 | .section => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf), | 5309 | .section, .section_manual_size => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf), |
| 4725 | .input_section, .copied_global => unreachable, | 5310 | .input_section, .copied_global => unreachable, |
| 4726 | inline .nav, .uav, .lazy_code, .lazy_const_data => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | 5311 | inline .nav, |
| 5312 | .uav, | ||
| 5313 | .lazy_code, | ||
| 5314 | .lazy_const_data, | ||
| 5315 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | ||
| 5316 | .debug_shared, .eh_frame_footer, .unit_padding => unreachable, | ||
| 5317 | .unit_frame, .unit_debug_info, .unit_debug_line => { | ||
| 5318 | const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); | ||
| 5319 | break :parent_vaddr elf.getNodeShndx(parent_ni).vaddr(elf) + section_offset; | ||
| 5320 | }, | ||
| 5321 | .unit_frame_cie, | ||
| 5322 | .unit_debug_info_header, | ||
| 5323 | .unit_debug_info_footer, | ||
| 5324 | .unit_debug_line_header, | ||
| 5325 | .unit_debug_rnglists, | ||
| 5326 | .const_debug_info, | ||
| 5327 | .global_debug_info, | ||
| 5328 | .func_frame_fde, | ||
| 5329 | .func_debug_info, | ||
| 5330 | .func_debug_line, | ||
| 5331 | .decl_debug_info, | ||
| 5332 | => unreachable, | ||
| 4727 | }; | 5333 | }; |
| 4728 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); | 5334 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); |
| 4729 | return parent_vaddr + offset; | 5335 | return parent_vaddr + offset; |
| 4730 | } | 5336 | } |
| 4731 | fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 5337 | fn computeNodeSectionOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 5338 | const parent_ni = ni.parent(&elf.mf).unwrap().?; | ||
| 5339 | const parent_section_offset = parent_section_offset: switch (elf.getNode(parent_ni)) { | ||
| 5340 | .deleted, | ||
| 5341 | .archive, | ||
| 5342 | .archive_header, | ||
| 5343 | .archive_input_member, | ||
| 5344 | .archive_elf_member_header, | ||
| 5345 | .elf, | ||
| 5346 | .ehdr, | ||
| 5347 | .shdr, | ||
| 5348 | .segment, | ||
| 5349 | => unreachable, | ||
| 5350 | .section, .section_manual_size => 0, | ||
| 5351 | .input_section, .copied_global => unreachable, | ||
| 5352 | .nav, .uav, .lazy_code, .lazy_const_data => unreachable, | ||
| 5353 | .debug_shared, .eh_frame_footer, .unit_padding => unreachable, | ||
| 5354 | .unit_frame, .unit_debug_info, .unit_debug_line => { | ||
| 5355 | const parent_section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); | ||
| 5356 | break :parent_section_offset parent_section_offset; | ||
| 5357 | }, | ||
| 5358 | .unit_frame_cie, | ||
| 5359 | .unit_debug_info_header, | ||
| 5360 | .unit_debug_info_footer, | ||
| 5361 | .unit_debug_line_header, | ||
| 5362 | .unit_debug_rnglists, | ||
| 5363 | .const_debug_info, | ||
| 5364 | .global_debug_info, | ||
| 5365 | .func_frame_fde, | ||
| 5366 | .func_debug_info, | ||
| 5367 | .func_debug_line, | ||
| 5368 | .decl_debug_info, | ||
| 5369 | => unreachable, | ||
| 5370 | }; | ||
| 5371 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); | ||
| 5372 | return parent_section_offset + offset; | ||
| 5373 | } | ||
| 5374 | fn computeNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ||
| 4732 | return ni.fileLocation(&elf.mf, false).offset - elf.ni.elf.fileLocation(&elf.mf, false).offset; | 5375 | return ni.fileLocation(&elf.mf, false).offset - elf.ni.elf.fileLocation(&elf.mf, false).offset; |
| 4733 | } | 5376 | } |
| 4734 | 5377 | ||
| ... | @@ -4736,9 +5379,16 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ... | @@ -4736,9 +5379,16 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4736 | /// sequence of relocations, so that the caller may append the node's updated relocations. | 5379 | /// sequence of relocations, so that the caller may append the node's updated relocations. |
| 4737 | /// | 5380 | /// |
| 4738 | /// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support | 5381 | /// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support |
| 4739 | /// the special-case sections '.plt' and '.dynamic'. | 5382 | /// the special-case sections '.plt', '.dynamic', and '.eh_frame_hdr'. |
| 4740 | fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | 5383 | pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4741 | const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { | 5384 | const opts: struct { |
| 5385 | first_symbol_reloc: ?*SymbolReloc.Index = null, | ||
| 5386 | skip_symbol_relocs: MappedFile.Node.Index.Optional = .none, | ||
| 5387 | first_node_reloc: ?*NodeReloc.Index = null, | ||
| 5388 | skip_node_relocs: MappedFile.Node.Index.Optional = .none, | ||
| 5389 | first_got_reloc: ?*GotReloc.Index = null, | ||
| 5390 | } = switch (elf.getNode(ni)) { | ||
| 5391 | .deleted, | ||
| 4742 | .archive, | 5392 | .archive, |
| 4743 | .archive_header, | 5393 | .archive_header, |
| 4744 | .archive_input_member, | 5394 | .archive_input_member, |
| ... | @@ -4748,41 +5398,106 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -4748,41 +5398,106 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4748 | .shdr, | 5398 | .shdr, |
| 4749 | .segment, | 5399 | .segment, |
| 4750 | .copied_global, | 5400 | .copied_global, |
| 5401 | .debug_shared, | ||
| 5402 | .eh_frame_footer, | ||
| 5403 | .unit_padding, | ||
| 5404 | .unit_frame, | ||
| 5405 | .unit_frame_cie, | ||
| 5406 | .unit_debug_info, | ||
| 5407 | .unit_debug_line, | ||
| 4751 | => unreachable, // cannot contain relocs | 5408 | => unreachable, // cannot contain relocs |
| 4752 | .section => unreachable, // cannot contain relocs (.plt and .dynamic unsupported) | 5409 | .section, |
| 5410 | .section_manual_size, | ||
| 5411 | => unreachable, // cannot contain relocs (.plt, .dynamic, and .eh_frame_hdr unsupported) | ||
| 4753 | .input_section => |isi| .{ | 5412 | .input_section => |isi| .{ |
| 4754 | &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, | 5413 | .first_symbol_reloc = &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, |
| 4755 | &elf.input_sections.items[@backingInt(isi)].first_got_reloc, | 5414 | .first_got_reloc = &elf.input_sections.items[@backingInt(isi)].first_got_reloc, |
| 4756 | }, | 5415 | }, |
| 4757 | .nav => |nmi| .{ | 5416 | .nav => |nmi| .{ |
| 4758 | &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc, | 5417 | .first_symbol_reloc = &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc, |
| 4759 | &elf.navs.values()[@backingInt(nmi)].first_got_reloc, | 5418 | .first_got_reloc = &elf.navs.values()[@backingInt(nmi)].first_got_reloc, |
| 4760 | }, | 5419 | }, |
| 4761 | .uav => |umi| .{ | 5420 | .uav => |umi| .{ |
| 4762 | &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc, | 5421 | .first_symbol_reloc = &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc, |
| 4763 | null, | ||
| 4764 | }, | 5422 | }, |
| 4765 | inline .lazy_code, .lazy_const_data => |lmi| .{ | 5423 | inline .lazy_code, .lazy_const_data => |lmi| .{ |
| 4766 | &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc, | 5424 | .first_symbol_reloc = &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc, |
| 4767 | &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc, | 5425 | .first_got_reloc = &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc, |
| 5426 | }, | ||
| 5427 | .unit_debug_info_header => |ui| .{ | ||
| 5428 | .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_node_reloc, | ||
| 5429 | }, | ||
| 5430 | .unit_debug_info_footer => unreachable, // cannot contain relocs | ||
| 5431 | .unit_debug_line_header => |ui| .{ | ||
| 5432 | .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_node_reloc, | ||
| 5433 | }, | ||
| 5434 | .unit_debug_rnglists => unreachable, // cannot contain relocs | ||
| 5435 | .const_debug_info => |cpi| .{ | ||
| 5436 | .first_symbol_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_symbol_reloc, | ||
| 5437 | .first_node_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_node_reloc, | ||
| 5438 | }, | ||
| 5439 | .global_debug_info => |gi| .{ | ||
| 5440 | .first_symbol_reloc = &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_symbol_reloc, | ||
| 5441 | .first_node_reloc = &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_node_reloc, | ||
| 5442 | }, | ||
| 5443 | .func_frame_fde => |fi| .{ | ||
| 5444 | .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].frame_fde_first_symbol_reloc, | ||
| 5445 | .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].frame_fde_first_node_reloc, | ||
| 5446 | }, | ||
| 5447 | .func_debug_info => |fi| .{ | ||
| 5448 | .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_symbol_reloc, | ||
| 5449 | .skip_symbol_relocs = if (elf.navs.getPtr(fi.nav(&elf.dwarf))) |nav| | ||
| 5450 | nav.lsi.index().ptr(elf).node | ||
| 5451 | else | ||
| 5452 | .none, | ||
| 5453 | .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_node_reloc, | ||
| 5454 | .skip_node_relocs = fi.get(&elf.dwarf).debug_line_ni, | ||
| 5455 | }, | ||
| 5456 | .func_debug_line => |fi| .{ | ||
| 5457 | .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_line_first_symbol_reloc, | ||
| 5458 | .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_line_first_node_reloc, | ||
| 5459 | .skip_node_relocs = fi.get(&elf.dwarf).debug_info_ni, | ||
| 5460 | }, | ||
| 5461 | .decl_debug_info => |di| .{ | ||
| 5462 | .first_node_reloc = &elf.dwarf_decls.getPtr(di).?.debug_info_first_node_reloc, | ||
| 4768 | }, | 5463 | }, |
| 4769 | }; | 5464 | }; |
| 4770 | 5465 | ||
| 4771 | if (symbol_relocs.* != .none) { | 5466 | if (opts.first_symbol_reloc) |ptr| { |
| 4772 | for ( | 5467 | if (ptr.* != .none) { |
| 4773 | elf.symbol_relocs.items[@backingInt(symbol_relocs.*)..], | 5468 | for (elf.symbol_relocs.items[@backingInt(ptr.*)..], @backingInt(ptr.*)..) |*reloc, index| { |
| 4774 | @backingInt(symbol_relocs.*).., | 5469 | if (reloc.node != ni.toOptional()) { |
| 4775 | ) |*reloc, index| { | 5470 | if (reloc.node == .none) continue; |
| 4776 | if (reloc.node != ni) break; | 5471 | if (reloc.node == opts.skip_symbol_relocs) continue; |
| 4777 | reloc.delete(elf, @fromBackingInt(@intCast(index))); | 5472 | break; |
| 5473 | } | ||
| 5474 | reloc.delete(elf, @fromBackingInt(@intCast(index))); | ||
| 5475 | } | ||
| 5476 | } | ||
| 5477 | ptr.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | ||
| 5478 | } | ||
| 5479 | |||
| 5480 | if (opts.first_node_reloc) |ptr| { | ||
| 5481 | if (ptr.* != .none) { | ||
| 5482 | for (elf.node_relocs.items[@backingInt(ptr.*)..]) |*reloc| { | ||
| 5483 | if (reloc.node != ni.toOptional()) { | ||
| 5484 | if (reloc.node == .none) continue; | ||
| 5485 | if (reloc.node == opts.skip_node_relocs) continue; | ||
| 5486 | break; | ||
| 5487 | } | ||
| 5488 | reloc.delete(elf); | ||
| 5489 | } | ||
| 4778 | } | 5490 | } |
| 5491 | ptr.* = @fromBackingInt(@intCast(elf.node_relocs.items.len)); | ||
| 4779 | } | 5492 | } |
| 4780 | symbol_relocs.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | ||
| 4781 | 5493 | ||
| 4782 | if (got_relocs) |ptr| { | 5494 | if (opts.first_got_reloc) |ptr| { |
| 4783 | if (ptr.* != .none) { | 5495 | if (ptr.* != .none) { |
| 4784 | for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| { | 5496 | for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| { |
| 4785 | if (reloc.node != ni.toOptional()) break; | 5497 | if (reloc.node != ni.toOptional()) { |
| 5498 | if (reloc.node == .none) continue; | ||
| 5499 | break; | ||
| 5500 | } | ||
| 4786 | reloc.delete(elf); | 5501 | reloc.delete(elf); |
| 4787 | } | 5502 | } |
| 4788 | } | 5503 | } |
| ... | @@ -4796,29 +5511,42 @@ fn flushMovedNodeRelocs( | ... | @@ -4796,29 +5511,42 @@ fn flushMovedNodeRelocs( |
| 4796 | elf: *Elf, | 5511 | elf: *Elf, |
| 4797 | node: MappedFile.Node.Index, | 5512 | node: MappedFile.Node.Index, |
| 4798 | node_vaddr: u64, | 5513 | node_vaddr: u64, |
| 4799 | first_symbol_reloc: SymbolReloc.Index, | 5514 | opts: struct { |
| 4800 | first_got_reloc: GotReloc.Index, | 5515 | first_symbol_reloc: SymbolReloc.Index = .none, |
| 5516 | skip_symbol_relocs: MappedFile.Node.Index.Optional = .none, | ||
| 5517 | first_node_reloc: NodeReloc.Index = .none, | ||
| 5518 | skip_node_relocs: MappedFile.Node.Index.Optional = .none, | ||
| 5519 | first_got_reloc: GotReloc.Index = .none, | ||
| 5520 | }, | ||
| 4801 | ) void { | 5521 | ) void { |
| 4802 | if (first_symbol_reloc != .none) { | 5522 | if (opts.first_symbol_reloc != .none) { |
| 4803 | for (elf.symbol_relocs.items[@backingInt(first_symbol_reloc)..]) |*reloc| { | 5523 | for (elf.symbol_relocs.items[@backingInt(opts.first_symbol_reloc)..]) |*reloc| { |
| 4804 | if (reloc.node != node) break; | 5524 | if (reloc.node != node.toOptional()) { |
| 4805 | if (reloc.rela_index.unwrap()) |rela_index| { | 5525 | if (reloc.node == .none) continue; |
| 4806 | // The node has moved, so the offset of the relocation within the section might have | 5526 | if (reloc.node == opts.skip_symbol_relocs) continue; |
| 4807 | // changed, so update the `offset` field of the `ElfN.Rela` entry. | 5527 | break; |
| 4808 | reloc.relaSection(elf).relaSetOffset(elf, rela_index, node_vaddr + reloc.offset); | 5528 | } |
| 4809 | } | 5529 | reloc.flushMovedNode(elf, node_vaddr); |
| 4810 | // This is not just the inverse of the above condition, because if `reloc` is relative | 5530 | } |
| 4811 | // to the base of this DSO, then `rela_index` is an `R_*_RELATIVE` relocation, but we | 5531 | } |
| 4812 | // still need to call `SymbolReloc.apply` to update that relocation's addend. | 5532 | |
| 4813 | if (elf.ehdrType() != .REL) { | 5533 | if (opts.first_node_reloc != .none) { |
| 4814 | reloc.apply(elf); | 5534 | for (elf.node_relocs.items[@backingInt(opts.first_node_reloc)..]) |*reloc| { |
| 5535 | if (reloc.node != node.toOptional()) { | ||
| 5536 | if (reloc.node == .none) continue; | ||
| 5537 | if (reloc.node == opts.skip_node_relocs) continue; | ||
| 5538 | break; | ||
| 4815 | } | 5539 | } |
| 5540 | reloc.flushMovedNode(elf, node_vaddr); | ||
| 4816 | } | 5541 | } |
| 4817 | } | 5542 | } |
| 4818 | 5543 | ||
| 4819 | if (first_got_reloc != .none) { | 5544 | if (opts.first_got_reloc != .none) { |
| 4820 | for (elf.got_relocs.items[@backingInt(first_got_reloc)..]) |*reloc| { | 5545 | for (elf.got_relocs.items[@backingInt(opts.first_got_reloc)..]) |*reloc| { |
| 4821 | if (reloc.node != node.toOptional()) break; | 5546 | if (reloc.node != node.toOptional()) { |
| 5547 | if (reloc.node == .none) continue; | ||
| 5548 | break; | ||
| 5549 | } | ||
| 4822 | reloc.apply(elf); | 5550 | reloc.apply(elf); |
| 4823 | } | 5551 | } |
| 4824 | } | 5552 | } |
| ... | @@ -5088,13 +5816,12 @@ const ShdrPtr = union(std.elf.CLASS) { | ... | @@ -5088,13 +5816,12 @@ const ShdrPtr = union(std.elf.CLASS) { |
| 5088 | @"64": *std.elf.Elf64.Shdr, | 5816 | @"64": *std.elf.Elf64.Shdr, |
| 5089 | }; | 5817 | }; |
| 5090 | fn shdrPtr(elf: *Elf, shndx: Section.Index) ShdrPtr { | 5818 | fn shdrPtr(elf: *Elf, shndx: Section.Index) ShdrPtr { |
| 5091 | const raw_slice = elf.ni.shdr.slice(&elf.mf); | 5819 | const slice = elf.ni.shdr.slice(&elf.mf); |
| 5092 | switch (elf.identClass()) { | 5820 | switch (elf.identClass()) { |
| 5093 | .NONE, _ => unreachable, | 5821 | .NONE, _ => unreachable, |
| 5094 | inline else => |class| { | 5822 | inline else => |class| { |
| 5095 | const shdrs_len = elf.shdrs.items.len + 1; // +1 for SHN_UNDEF | ||
| 5096 | const shdr_slice: []class.ElfN().Shdr = @ptrCast(@alignCast( | 5823 | const shdr_slice: []class.ElfN().Shdr = @ptrCast(@alignCast( |
| 5097 | raw_slice[0 .. shdrs_len * @sizeOf(class.ElfN().Shdr)], | 5824 | slice[0 .. @sizeOf(class.ElfN().Shdr) * (1 + elf.shdrs.items.len)], |
| 5098 | )); | 5825 | )); |
| 5099 | const shdr_ptr = &shdr_slice[@backingInt(shndx)]; | 5826 | const shdr_ptr = &shdr_slice[@backingInt(shndx)]; |
| 5100 | return @unionInit(ShdrPtr, @tagName(class), shdr_ptr); | 5827 | return @unionInit(ShdrPtr, @tagName(class), shdr_ptr); |
| ... | @@ -5226,7 +5953,7 @@ fn mapInputSection(elf: *Elf, opts: struct { | ... | @@ -5226,7 +5953,7 @@ fn mapInputSection(elf: *Elf, opts: struct { |
| 5226 | } | 5953 | } |
| 5227 | 5954 | ||
| 5228 | switch (elf.targetLoad(&shdr.type)) { | 5955 | switch (elf.targetLoad(&shdr.type)) { |
| 5229 | .NULL, .PROGBITS => {}, | 5956 | .NULL, .PROGBITS, .X86_64_UNWIND => {}, |
| 5230 | else => return error.SectionTypeConflict, | 5957 | else => return error.SectionTypeConflict, |
| 5231 | } | 5958 | } |
| 5232 | 5959 | ||
| ... | @@ -5270,6 +5997,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node | ... | @@ -5270,6 +5997,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node |
| 5270 | })) |shndx| { | 5997 | })) |shndx| { |
| 5271 | break :section shndx; | 5998 | break :section shndx; |
| 5272 | } else |err| switch (err) { | 5999 | } else |err| switch (err) { |
| 6000 | else => |e| return e, | ||
| 5273 | error.StripSection, | 6001 | error.StripSection, |
| 5274 | error.TlsSectionUnavailable, | 6002 | error.TlsSectionUnavailable, |
| 5275 | error.UnsupportedSectionFlags, | 6003 | error.UnsupportedSectionFlags, |
| ... | @@ -5277,7 +6005,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node | ... | @@ -5277,7 +6005,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node |
| 5277 | error.SectionFlagsConflict, | 6005 | error.SectionFlagsConflict, |
| 5278 | => {}, // fall back to default behavior below | 6006 | => {}, // fall back to default behavior below |
| 5279 | 6007 | ||
| 5280 | else => |e| return e, | ||
| 5281 | } | 6008 | } |
| 5282 | } | 6009 | } |
| 5283 | if (elf.base.comp.config.any_non_single_threaded and nav.resolved.?.@"threadlocal") { | 6010 | if (elf.base.comp.config.any_non_single_threaded and nav.resolved.?.@"threadlocal") { |
| ... | @@ -5294,15 +6021,11 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node | ... | @@ -5294,15 +6021,11 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node |
| 5294 | .@"fn" => a: { | 6021 | .@"fn" => a: { |
| 5295 | const mod = zcu.navFileScope(nav_index).mod.?; | 6022 | const mod = zcu.navFileScope(nav_index).mod.?; |
| 5296 | const target = &mod.resolved_target.result; | 6023 | const target = &mod.resolved_target.result; |
| 5297 | const min = target_util.minFunctionAlignment(target); | ||
| 5298 | break :a .fromIp(switch (nav.resolved.?.@"align") { | 6024 | break :a .fromIp(switch (nav.resolved.?.@"align") { |
| 5299 | else => |a| a.maxStrict(min), | 6025 | else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), |
| 5300 | .none => switch (mod.optimize_mode) { | 6026 | .none => switch (mod.optimize_mode) { |
| 5301 | .debug, | 6027 | .debug, .safe, .fast => target_util.defaultFunctionAlignment(target), |
| 5302 | .safe, | 6028 | .small => target_util.minFunctionAlignment(target), |
| 5303 | .fast, | ||
| 5304 | => target_util.defaultFunctionAlignment(target), | ||
| 5305 | .small => min, | ||
| 5306 | }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)), | 6029 | }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)), |
| 5307 | }); | 6030 | }); |
| 5308 | }, | 6031 | }, |
| ... | @@ -5312,9 +6035,9 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node | ... | @@ -5312,9 +6035,9 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node |
| 5312 | }, | 6035 | }, |
| 5313 | }; | 6036 | }; |
| 5314 | try shndx.ensureAligned(elf, alignment); | 6037 | try shndx.ensureAligned(elf, alignment); |
| 5315 | const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{ | 6038 | const node = elf.addNodeAssumeCapacity(try shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ |
| 5316 | .alignment = alignment, | 6039 | .alignment = alignment, |
| 5317 | }); | 6040 | }), .{ .nav = nmi }); |
| 5318 | nav_gop.value_ptr.* = .{ | 6041 | nav_gop.value_ptr.* = .{ |
| 5319 | .lsi = elf.addLocalSymbolAssumeCapacity(.{ | 6042 | .lsi = elf.addLocalSymbolAssumeCapacity(.{ |
| 5320 | .node = .wrap(node), | 6043 | .node = .wrap(node), |
| ... | @@ -5327,7 +6050,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node | ... | @@ -5327,7 +6050,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node |
| 5327 | .first_symbol_reloc = .none, | 6050 | .first_symbol_reloc = .none, |
| 5328 | .first_got_reloc = .none, | 6051 | .first_got_reloc = .none, |
| 5329 | }; | 6052 | }; |
| 5330 | elf.nodes.appendAssumeCapacity(.{ .nav = nmi }); | ||
| 5331 | } | 6053 | } |
| 5332 | return nmi; | 6054 | return nmi; |
| 5333 | } | 6055 | } |
| ... | @@ -5356,16 +6078,12 @@ fn uavMapIndex( | ... | @@ -5356,16 +6078,12 @@ fn uavMapIndex( |
| 5356 | if (!uav_gop.found_existing) { | 6078 | if (!uav_gop.found_existing) { |
| 5357 | const shndx: Section.Index = .data_rel_ro; // TODO: it would be better to use `.rodata` if the UAV value doesn't have relocs | 6079 | const shndx: Section.Index = .data_rel_ro; // TODO: it would be better to use `.rodata` if the UAV value doesn't have relocs |
| 5358 | try shndx.ensureAligned(elf, resolved_align); | 6080 | try shndx.ensureAligned(elf, resolved_align); |
| 5359 | const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{ | 6081 | const node = elf.addNodeAssumeCapacity(try shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ |
| 5360 | .moved = true, // see assert at end of `genUav` | 6082 | .moved = true, // see assert at end of `genUav` |
| 5361 | .alignment = resolved_align, | 6083 | .alignment = resolved_align, |
| 5362 | }); | 6084 | }), .{ .uav = umi }); |
| 5363 | var name_buf: [32]u8 = undefined; | 6085 | var name_buf: [std.fmt.count("__anon_{d}", .{std.math.maxInt(u32)})]u8 = undefined; |
| 5364 | const name = std.mem.print( | 6086 | const name = std.mem.print(&name_buf, "__anon_{d}", .{umi}) catch unreachable; |
| 5365 | &name_buf, | ||
| 5366 | "__anon_{d}", | ||
| 5367 | .{@backingInt(uav_val)}, | ||
| 5368 | ) catch unreachable; | ||
| 5369 | uav_gop.value_ptr.* = .{ | 6087 | uav_gop.value_ptr.* = .{ |
| 5370 | .lsi = elf.addLocalSymbolAssumeCapacity(.{ | 6088 | .lsi = elf.addLocalSymbolAssumeCapacity(.{ |
| 5371 | .node = .wrap(node), | 6089 | .node = .wrap(node), |
| ... | @@ -5377,15 +6095,14 @@ fn uavMapIndex( | ... | @@ -5377,15 +6095,14 @@ fn uavMapIndex( |
| 5377 | }), | 6095 | }), |
| 5378 | .first_symbol_reloc = .none, | 6096 | .first_symbol_reloc = .none, |
| 5379 | }; | 6097 | }; |
| 5380 | elf.nodes.appendAssumeCapacity(.{ .uav = umi }); | ||
| 5381 | elf.const_prog_node.increaseEstimatedTotalItems(1); | 6098 | elf.const_prog_node.increaseEstimatedTotalItems(1); |
| 5382 | elf.pending_uavs.appendAssumeCapacity(umi); | 6099 | elf.pending_uavs.appendAssumeCapacity(umi); |
| 5383 | } else { | 6100 | } else { |
| 5384 | const node = uav_gop.value_ptr.lsi.index().ptr(elf).node.unwrap().?; | 6101 | const node = uav_gop.value_ptr.lsi.index().ptr(elf).node.unwrap().?; |
| 5385 | const shndx = elf.getNode(node.parent(&elf.mf).unwrap().?).section; | 6102 | const shndx = elf.getNodeShndx(node); |
| 5386 | try shndx.ensureAligned(elf, resolved_align); | 6103 | try shndx.ensureAligned(elf, resolved_align); |
| 5387 | if (resolved_align.order(node.alignment(&elf.mf)).compare(.gt)) { | 6104 | if (resolved_align.order(node.alignment(&elf.mf)).compare(.gt)) { |
| 5388 | try node.realign(&elf.mf, gpa, resolved_align); | 6105 | try node.realign(gpa, &elf.mf, resolved_align); |
| 5389 | } | 6106 | } |
| 5390 | } | 6107 | } |
| 5391 | return umi; | 6108 | return umi; |
| ... | @@ -5518,9 +6235,9 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load | ... | @@ -5518,9 +6235,9 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load |
| 5518 | return error.BadMagic; | 6235 | return error.BadMagic; |
| 5519 | } | 6236 | } |
| 5520 | } | 6237 | } |
| 5521 | var strtab: std.Io.Writer.Allocating = .init(gpa); | 6238 | var strtab: Io.Writer.Allocating = .init(gpa); |
| 5522 | defer strtab.deinit(); | 6239 | defer strtab.deinit(); |
| 5523 | while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| { | 6240 | while (r.takeStruct(std.elf.ar_hdr, .native)) |header| { |
| 5524 | if (!std.mem.eql(u8, &header.ar_fmag, std.elf.ARFMAG)) | 6241 | if (!std.mem.eql(u8, &header.ar_fmag, std.elf.ARFMAG)) |
| 5525 | return diags.failParse(path, "bad file magic", .{}); | 6242 | return diags.failParse(path, "bad file magic", .{}); |
| 5526 | const offset = fr.logicalPos(); | 6243 | const offset = fr.logicalPos(); |
| ... | @@ -5530,8 +6247,8 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load | ... | @@ -5530,8 +6247,8 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load |
| 5530 | strtab.clearRetainingCapacity(); | 6247 | strtab.clearRetainingCapacity(); |
| 5531 | try strtab.ensureTotalCapacityPrecise(size); | 6248 | try strtab.ensureTotalCapacityPrecise(size); |
| 5532 | r.streamExact(&strtab.writer, size) catch |err| switch (err) { | 6249 | r.streamExact(&strtab.writer, size) catch |err| switch (err) { |
| 5533 | error.WriteFailed => return error.OutOfMemory, | ||
| 5534 | else => |e| return e, | 6250 | else => |e| return e, |
| 6251 | error.WriteFailed => return error.OutOfMemory, | ||
| 5535 | }; | 6252 | }; |
| 5536 | continue; | 6253 | continue; |
| 5537 | } | 6254 | } |
| ... | @@ -5562,14 +6279,14 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load | ... | @@ -5562,14 +6279,14 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load |
| 5562 | } | 6279 | } |
| 5563 | try fr.seekTo(std.mem.alignForward(u64, offset + size, 2)); | 6280 | try fr.seekTo(std.mem.alignForward(u64, offset + size, 2)); |
| 5564 | } else |err| switch (err) { | 6281 | } else |err| switch (err) { |
| 5565 | error.EndOfStream => if (!fr.atEnd()) return error.EndOfStream, | ||
| 5566 | else => |e| return e, | 6282 | else => |e| return e, |
| 6283 | error.EndOfStream => if (!fr.atEnd()) return error.EndOfStream, | ||
| 5567 | } | 6284 | } |
| 5568 | } | 6285 | } |
| 5569 | fn fmtMemberString(member: ?[]const u8) std.fmt.Alt(?[]const u8, memberStringEscape) { | 6286 | fn fmtMemberString(member: ?[]const u8) std.fmt.Alt(?[]const u8, memberStringEscape) { |
| 5570 | return .{ .data = member }; | 6287 | return .{ .data = member }; |
| 5571 | } | 6288 | } |
| 5572 | fn memberStringEscape(member: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void { | 6289 | fn memberStringEscape(member: ?[]const u8, w: *Io.Writer) Io.Writer.Error!void { |
| 5573 | try w.print("({f})", .{std.zig.fmtString(member orelse return)}); | 6290 | try w.print("({f})", .{std.zig.fmtString(member orelse return)}); |
| 5574 | } | 6291 | } |
| 5575 | fn loadObject( | 6292 | fn loadObject( |
| ... | @@ -5614,11 +6331,13 @@ fn loadObject( | ... | @@ -5614,11 +6331,13 @@ fn loadObject( |
| 5614 | }; | 6331 | }; |
| 5615 | 6332 | ||
| 5616 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | 6333 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 5617 | const new_member_ni = try archive.ni.addFooterChildBefore(&elf.mf, gpa, first_member_oni, .{ | 6334 | const new_member_ni = elf.addNodeAssumeCapacity( |
| 5618 | .size = Alignment.@"2".forward(@sizeOf(std.elf.ar_hdr) + fl.size), | 6335 | try archive.ni.addFooterChildBefore(gpa, &elf.mf, first_member_oni, .{ |
| 5619 | .alignment = .@"2", | 6336 | .size = Alignment.@"2".forward(@sizeOf(std.elf.ar_hdr) + fl.size), |
| 5620 | }); | 6337 | .alignment = .@"2", |
| 5621 | elf.nodes.appendAssumeCapacity(.{ .archive_input_member = input_index }); | 6338 | }), |
| 6339 | .{ .archive_input_member = input_index }, | ||
| 6340 | ); | ||
| 5622 | input.extra = .{ .node = new_member_ni }; | 6341 | input.extra = .{ .node = new_member_ni }; |
| 5623 | elf.input_prog_node.increaseEstimatedTotalItems(1); | 6342 | elf.input_prog_node.increaseEstimatedTotalItems(1); |
| 5624 | 6343 | ||
| ... | @@ -5717,18 +6436,19 @@ fn loadObject( | ... | @@ -5717,18 +6436,19 @@ fn loadObject( |
| 5717 | for (sections[1..]) |*section| { | 6436 | for (sections[1..]) |*section| { |
| 5718 | if (section.shdr.name >= shstrtab.len) continue; | 6437 | if (section.shdr.name >= shstrtab.len) continue; |
| 5719 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); | 6438 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); |
| 6439 | if (!comp.config.any_unwind_tables and std.mem.eql(u8, name, ".eh_frame")) continue; | ||
| 5720 | const opts: struct { | 6440 | const opts: struct { |
| 5721 | shndx: Section.Index, | 6441 | shndx: Section.Index, |
| 5722 | has_file_bits: bool, | ||
| 5723 | node_fixed: bool, | 6442 | node_fixed: bool, |
| 5724 | } = switch (section.shdr.type) { | 6443 | } = switch (section.shdr.type) { |
| 5725 | else => continue, | 6444 | else => continue, |
| 5726 | .PROGBITS, .NOBITS => opts: { | 6445 | .PROGBITS, .NOBITS, .X86_64_UNWIND => opts: { |
| 5727 | const shndx = elf.mapInputSection(.{ | 6446 | const shndx = elf.mapInputSection(.{ |
| 5728 | .name = name, | 6447 | .name = name, |
| 5729 | .flags = section.shdr.flags.shf, | 6448 | .flags = section.shdr.flags.shf, |
| 5730 | .entsize = section.shdr.entsize, | 6449 | .entsize = section.shdr.entsize, |
| 5731 | }) catch |err| switch (err) { | 6450 | }) catch |err| switch (err) { |
| 6451 | else => |e| return e, | ||
| 5732 | error.StripSection => continue, | 6452 | error.StripSection => continue, |
| 5733 | error.TlsSectionUnavailable => return diags.failParse( | 6453 | error.TlsSectionUnavailable => return diags.failParse( |
| 5734 | path, | 6454 | path, |
| ... | @@ -5759,7 +6479,6 @@ fn loadObject( | ... | @@ -5759,7 +6479,6 @@ fn loadObject( |
| 5759 | "flags of section '{s}' conflict with other inputs", | 6479 | "flags of section '{s}' conflict with other inputs", |
| 5760 | .{name}, | 6480 | .{name}, |
| 5761 | ), | 6481 | ), |
| 5762 | else => |e| return e, | ||
| 5763 | }; | 6482 | }; |
| 5764 | if (section.shdr.flags.shf.COMPRESSED) { | 6483 | if (section.shdr.flags.shf.COMPRESSED) { |
| 5765 | // SHF_COMPRESSED is only allowed on non-alloc sections. | 6484 | // SHF_COMPRESSED is only allowed on non-alloc sections. |
| ... | @@ -5776,7 +6495,6 @@ fn loadObject( | ... | @@ -5776,7 +6495,6 @@ fn loadObject( |
| 5776 | } | 6495 | } |
| 5777 | break :opts .{ | 6496 | break :opts .{ |
| 5778 | .shndx = shndx, | 6497 | .shndx = shndx, |
| 5779 | .has_file_bits = section.shdr.type == .PROGBITS, | ||
| 5780 | // For well-known sections, we know that it's fine to have e.g. random | 6498 | // For well-known sections, we know that it's fine to have e.g. random |
| 5781 | // padding, so there's no need to make the sections fixed. For custom | 6499 | // padding, so there's no need to make the sections fixed. For custom |
| 5782 | // sections, however, we do want fixed nodes to avoid padding. | 6500 | // sections, however, we do want fixed nodes to avoid padding. |
| ... | @@ -5819,7 +6537,6 @@ fn loadObject( | ... | @@ -5819,7 +6537,6 @@ fn loadObject( |
| 5819 | } | 6537 | } |
| 5820 | break :shndx shndx.*; | 6538 | break :shndx shndx.*; |
| 5821 | }, | 6539 | }, |
| 5822 | .has_file_bits = true, | ||
| 5823 | // This node must be fixed to prevent padding from being added between different | 6540 | // This node must be fixed to prevent padding from being added between different |
| 5824 | // INIT_ARRAY/FINI_ARRAY/PREINIT_ARRAY input sections. | 6541 | // INIT_ARRAY/FINI_ARRAY/PREINIT_ARRAY input sections. |
| 5825 | .node_fixed = true, | 6542 | .node_fixed = true, |
| ... | @@ -5834,28 +6551,26 @@ fn loadObject( | ... | @@ -5834,28 +6551,26 @@ fn loadObject( |
| 5834 | .alignment = need_align, | 6551 | .alignment = need_align, |
| 5835 | .moved = true, // see assert at end of `flushInputSection` | 6552 | .moved = true, // see assert at end of `flushInputSection` |
| 5836 | }; | 6553 | }; |
| 5837 | const ni = if (opts.node_fixed) ni: { | 6554 | const ni = elf.addNodeAssumeCapacity( |
| 5838 | const shndx_ni = opts.shndx.get(elf).ni; | 6555 | if (opts.node_fixed) ni: { |
| 5839 | const after_oni: MappedFile.Node.Index.Optional = after: { | 6556 | const shndx_ni = opts.shndx.get(elf).ni; |
| 5840 | const last_ni = shndx_ni.last(&elf.mf).unwrap() orelse break :after .none; | 6557 | const after_oni: MappedFile.Node.Index.Optional = after: { |
| 5841 | break :after switch (last_ni.position(&elf.mf)) { | 6558 | const last_ni = shndx_ni.last(&elf.mf).unwrap() orelse break :after .none; |
| 5842 | .header => .wrap(last_ni), | 6559 | break :after switch (last_ni.position(&elf.mf)) { |
| 5843 | .footer, .floating => .none, | 6560 | .header => .wrap(last_ni), |
| 6561 | .footer, .floating => .none, | ||
| 6562 | }; | ||
| 5844 | }; | 6563 | }; |
| 5845 | }; | 6564 | break :ni try shndx_ni.addHeaderChildAfter(gpa, &elf.mf, after_oni, add_node_opts); |
| 5846 | break :ni try shndx_ni.addHeaderChildAfter(&elf.mf, gpa, after_oni, add_node_opts); | 6565 | } else try opts.shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, add_node_opts), |
| 5847 | } else ni: { | 6566 | .{ .input_section = @fromBackingInt(@intCast(elf.input_sections.items.len)) }, |
| 5848 | break :ni try opts.shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, add_node_opts); | 6567 | ); |
| 5849 | }; | ||
| 5850 | elf.nodes.appendAssumeCapacity(.{ | ||
| 5851 | .input_section = @fromBackingInt(@intCast(elf.input_sections.items.len)), | ||
| 5852 | }); | ||
| 5853 | section.isi = @fromBackingInt(@intCast(elf.input_sections.items.len)); | 6568 | section.isi = @fromBackingInt(@intCast(elf.input_sections.items.len)); |
| 5854 | elf.input_sections.addOneAssumeCapacity().* = .{ | 6569 | elf.input_sections.addOneAssumeCapacity().* = .{ |
| 5855 | .input = input_index, | 6570 | .input = input_index, |
| 5856 | .file_location = .{ | 6571 | .file_location = .{ |
| 5857 | .offset = fl.offset + section.shdr.offset, | 6572 | .offset = fl.offset + section.shdr.offset, |
| 5858 | .size = if (opts.has_file_bits) section.shdr.size else 0, | 6573 | .size = if (section.shdr.type == .NOBITS) 0 else section.shdr.size, |
| 5859 | }, | 6574 | }, |
| 5860 | // The section vaddr is initially 0, because the symbol addresses are | 6575 | // The section vaddr is initially 0, because the symbol addresses are |
| 5861 | // zero-based. This will eventually be updated by `flushMoved`. | 6576 | // zero-based. This will eventually be updated by `flushMoved`. |
| ... | @@ -6043,6 +6758,7 @@ fn loadObject( | ... | @@ -6043,6 +6758,7 @@ fn loadObject( |
| 6043 | rel.addend, | 6758 | rel.addend, |
| 6044 | rt, | 6759 | rt, |
| 6045 | ) catch |err| switch (err) { | 6760 | ) catch |err| switch (err) { |
| 6761 | else => |e| return e, | ||
| 6046 | error.UnknownRelocation => diags.addParseError( | 6762 | error.UnknownRelocation => diags.addParseError( |
| 6047 | path, | 6763 | path, |
| 6048 | "unknown relocation type '{f}'", | 6764 | "unknown relocation type '{f}'", |
| ... | @@ -6058,7 +6774,6 @@ fn loadObject( | ... | @@ -6058,7 +6774,6 @@ fn loadObject( |
| 6058 | "TODO(Elf2): unimplemented relocation type '{f}'", | 6774 | "TODO(Elf2): unimplemented relocation type '{f}'", |
| 6059 | .{rt.fmt(elf)}, | 6775 | .{rt.fmt(elf)}, |
| 6060 | ), | 6776 | ), |
| 6061 | else => |e| return e, | ||
| 6062 | }; | 6777 | }; |
| 6063 | } | 6778 | } |
| 6064 | }, | 6779 | }, |
| ... | @@ -6102,7 +6817,7 @@ fn populateArchiveMemberName(elf: *Elf, member_ar_hdr: *std.elf.ar_hdr, member_n | ... | @@ -6102,7 +6817,7 @@ fn populateArchiveMemberName(elf: *Elf, member_ar_hdr: *std.elf.ar_hdr, member_n |
| 6102 | // We set the size of the archive header node exactly, because we want padding bytes to go into | 6817 | // We set the size of the archive header node exactly, because we want padding bytes to go into |
| 6103 | // the root `.archive` node. That way, those bytes could still be used to grow the string table | 6818 | // the root `.archive` node. That way, those bytes could still be used to grow the string table |
| 6104 | // if necessary, but they could also be used for new archive members. | 6819 | // if necessary, but they could also be used for new archive members. |
| 6105 | try archive_header_ni.resizeLeaf(&elf.mf, gpa, old_archive_header_size + member_name.len + 2); | 6820 | try archive_header_ni.resizeLeaf(gpa, &elf.mf, old_archive_header_size + member_name.len + 2); |
| 6106 | 6821 | ||
| 6107 | const dest_slice = archive_header_ni.slice(&elf.mf)[@intCast(old_archive_header_size)..]; | 6822 | const dest_slice = archive_header_ni.slice(&elf.mf)[@intCast(old_archive_header_size)..]; |
| 6108 | @memcpy(dest_slice[0 .. dest_slice.len - 2], member_name); | 6823 | @memcpy(dest_slice[0 .. dest_slice.len - 2], member_name); |
| ... | @@ -6254,8 +6969,12 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars | ... | @@ -6254,8 +6969,12 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars |
| 6254 | // We have a copy relocation for this global, but the amount of space we | 6969 | // We have a copy relocation for this global, but the amount of space we |
| 6255 | // reserved for it could be too small or underaligned! | 6970 | // reserved for it could be too small or underaligned! |
| 6256 | try Section.Index.data.ensureAligned(elf, gop.value_ptr.alignment); | 6971 | try Section.Index.data.ensureAligned(elf, gop.value_ptr.alignment); |
| 6257 | try copied_global.node.resizeLeaf(&elf.mf, gpa, gop.value_ptr.alignment.forward(gop.value_ptr.size)); | 6972 | try copied_global.node.resizeLeaf( |
| 6258 | try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment); | 6973 | gpa, |
| 6974 | &elf.mf, | ||
| 6975 | gop.value_ptr.alignment.forward(gop.value_ptr.size), | ||
| 6976 | ); | ||
| 6977 | try copied_global.node.realign(gpa, &elf.mf, gop.value_ptr.alignment); | ||
| 6259 | const global_ptr = elf.globalByName(name).?; | 6978 | const global_ptr = elf.globalByName(name).?; |
| 6260 | switch (elf.symPtr(global_ptr.symtab_index)) { | 6979 | switch (elf.symPtr(global_ptr.symtab_index)) { |
| 6261 | inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)), | 6980 | inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)), |
| ... | @@ -6407,6 +7126,7 @@ fn createInitFiniArraySection( | ... | @@ -6407,6 +7126,7 @@ fn createInitFiniArraySection( |
| 6407 | .type = @"type", | 7126 | .type = @"type", |
| 6408 | .flags = .{ .WRITE = true, .ALLOC = true }, | 7127 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 6409 | .node_align = addr_align, | 7128 | .node_align = addr_align, |
| 7129 | .manual_size = true, | ||
| 6410 | }); | 7130 | }); |
| 6411 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); | 7131 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); |
| 6412 | try elf.ensureUnusedSymbolCapacity(2, .maybe_global); | 7132 | try elf.ensureUnusedSymbolCapacity(2, .maybe_global); |
| ... | @@ -6454,8 +7174,9 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void { | ... | @@ -6454,8 +7174,9 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void { |
| 6454 | fn prelinkInner(elf: *Elf) Error!void { | 7174 | fn prelinkInner(elf: *Elf) Error!void { |
| 6455 | const comp = elf.base.comp; | 7175 | const comp = elf.base.comp; |
| 6456 | const gpa = comp.gpa; | 7176 | const gpa = comp.gpa; |
| 7177 | if (comp.zcu) |_| self_hosted_codegen: { | ||
| 7178 | if (comp.config.use_llvm) break :self_hosted_codegen; | ||
| 6457 | 7179 | ||
| 6458 | if (comp.zcu != null and !comp.config.use_llvm and elf.ni.elf == .root) { | ||
| 6459 | // We're using self-hosted codegen---add an input representing the Zig "object". | 7180 | // We're using self-hosted codegen---add an input representing the Zig "object". |
| 6460 | try elf.ensureUnusedSymbolCapacity(1, .all_local); | 7181 | try elf.ensureUnusedSymbolCapacity(1, .all_local); |
| 6461 | try elf.inputs.ensureUnusedCapacity(gpa, 1); | 7182 | try elf.inputs.ensureUnusedCapacity(gpa, 1); |
| ... | @@ -6475,7 +7196,226 @@ fn prelinkInner(elf: *Elf) Error!void { | ... | @@ -6475,7 +7196,226 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 6475 | .extra = .{ .file_symbol = zcu_file_symbol }, | 7196 | .extra = .{ .file_symbol = zcu_file_symbol }, |
| 6476 | }; | 7197 | }; |
| 6477 | elf.input_pending_index += 1; | 7198 | elf.input_pending_index += 1; |
| 7199 | |||
| 7200 | try elf.nodes.ensureUnusedCapacity(gpa, 5 + 4); | ||
| 7201 | |||
| 7202 | switch (elf.shndx.debug_abbrev) { | ||
| 7203 | .UNDEF => {}, | ||
| 7204 | else => |debug_abbrev_shndx| elf.dwarf.debug_abbrev.ni = .wrap(elf.addNodeAssumeCapacity( | ||
| 7205 | try debug_abbrev_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), | ||
| 7206 | .{ .debug_shared = .debug_abbrev }, | ||
| 7207 | )), | ||
| 7208 | } | ||
| 7209 | switch (elf.shndx.debug_line_str) { | ||
| 7210 | .UNDEF => {}, | ||
| 7211 | else => |debug_line_str_shndx| elf.dwarf.debug_line_str.ni = | ||
| 7212 | .wrap(elf.addNodeAssumeCapacity( | ||
| 7213 | try debug_line_str_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), | ||
| 7214 | .{ .debug_shared = .debug_line_str }, | ||
| 7215 | )), | ||
| 7216 | } | ||
| 7217 | switch (elf.shndx.debug_str) { | ||
| 7218 | .UNDEF => {}, | ||
| 7219 | else => |debug_str_shndx| elf.dwarf.debug_str.ni = .wrap(elf.addNodeAssumeCapacity( | ||
| 7220 | try debug_str_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), | ||
| 7221 | .{ .debug_shared = .debug_str }, | ||
| 7222 | )), | ||
| 7223 | } | ||
| 7224 | switch (elf.shndx.debug_str_offsets) { | ||
| 7225 | .UNDEF => {}, | ||
| 7226 | else => |debug_str_offsets_shndx| elf.dwarf.debug_str_offsets.ni = | ||
| 7227 | .wrap(elf.addNodeAssumeCapacity( | ||
| 7228 | try debug_str_offsets_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}), | ||
| 7229 | .{ .debug_shared = .debug_str_offsets }, | ||
| 7230 | )), | ||
| 7231 | } | ||
| 7232 | |||
| 7233 | for ([5]Section.Index{ | ||
| 7234 | elf.shndx.eh_frame, | ||
| 7235 | elf.shndx.debug_frame, | ||
| 7236 | elf.shndx.debug_info, | ||
| 7237 | elf.shndx.debug_line, | ||
| 7238 | elf.shndx.debug_rnglists, | ||
| 7239 | }) |debug_shndx| { | ||
| 7240 | if (debug_shndx == .UNDEF) continue; | ||
| 7241 | const debug_ni = debug_shndx.get(elf).ni; | ||
| 7242 | const frame_format = debug_shndx.debugFrameFormat(elf); | ||
| 7243 | const unit_padding_ni = elf.addNodeAssumeCapacity( | ||
| 7244 | try debug_ni.addHeaderChildAfter(gpa, &elf.mf, last_header_oni: { | ||
| 7245 | var last_header_oni = debug_ni.last(&elf.mf); | ||
| 7246 | while (last_header_oni.unwrap()) |last_header_ni| | ||
| 7247 | switch (last_header_ni.position(&elf.mf)) { | ||
| 7248 | .header => break, | ||
| 7249 | .footer => last_header_oni = last_header_ni.prev(&elf.mf), | ||
| 7250 | .floating => unreachable, | ||
| 7251 | }; | ||
| 7252 | break :last_header_oni last_header_oni; | ||
| 7253 | }, .{ | ||
| 7254 | .alignment = if (frame_format) |_| switch (elf.identClass()) { | ||
| 7255 | .NONE, _ => unreachable, | ||
| 7256 | .@"32" => .@"4", | ||
| 7257 | .@"64" => .@"8", | ||
| 7258 | } else .@"1", | ||
| 7259 | .next_moved = true, | ||
| 7260 | .enable_next_moved = true, | ||
| 7261 | }), | ||
| 7262 | .unit_padding, | ||
| 7263 | ); | ||
| 7264 | var debug_nw: MappedFile.Node.Writer = undefined; | ||
| 7265 | unit_padding_ni.writer(gpa, &elf.mf, &debug_nw); | ||
| 7266 | defer debug_nw.deinit(); | ||
| 7267 | (if (frame_format) |format| | ||
| 7268 | elf.dwarf.genDebugFrameCie(&debug_nw.interface, null, format) | ||
| 7269 | else | ||
| 7270 | elf.dwarf.genUnitPadding(&debug_nw.interface)) catch |err| switch (err) { | ||
| 7271 | error.WriteFailed => return debug_nw.err.?, | ||
| 7272 | }; | ||
| 7273 | } | ||
| 7274 | } | ||
| 7275 | } | ||
| 7276 | |||
| 7277 | pub fn zcuFilesReady(elf: *Elf, zcu: *Zcu) link.Error!void { | ||
| 7278 | elf.zcuFilesReadyInner(zcu) catch |err| switch (err) { | ||
| 7279 | else => |e| return e, | ||
| 7280 | error.MappedFileIo => return elf.base.comp.link_diags.fail( | ||
| 7281 | "failed to write output file: {t}", | ||
| 7282 | .{elf.mf.io_err.?}, | ||
| 7283 | ), | ||
| 7284 | }; | ||
| 7285 | } | ||
| 7286 | fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void { | ||
| 7287 | const gpa = zcu.gpa; | ||
| 7288 | const units_len = zcu.module_roots.count(); | ||
| 7289 | if (elf.dwarf_units.len == 0) { | ||
| 7290 | @branchHint(.unlikely); | ||
| 7291 | try elf.dwarf.initUnits(gpa, units_len); | ||
| 7292 | elf.dwarf_units = try gpa.alloc(dwarf_relocs.Unit, zcu.module_roots.count()); | ||
| 7293 | @memset(elf.dwarf_units, .{ | ||
| 7294 | .frame_cie_first_target_reloc = .none, | ||
| 7295 | .debug_info_header_first_target_reloc = .none, | ||
| 7296 | .debug_info_header_first_node_reloc = .none, | ||
| 7297 | .debug_line_header_first_target_reloc = .none, | ||
| 7298 | .debug_line_header_first_node_reloc = .none, | ||
| 7299 | .debug_rnglists_first_target_reloc = .none, | ||
| 7300 | .debug_rnglists_symbol_relocs = .empty, | ||
| 7301 | }); | ||
| 7302 | } | ||
| 7303 | if (!try elf.dwarf.updateUnits(zcu)) return; | ||
| 7304 | try elf.nodes.ensureUnusedCapacity(gpa, 5 * units_len); | ||
| 7305 | for (0..units_len) |unit_index| { | ||
| 7306 | const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index)); | ||
| 7307 | const unit = ui.get(&elf.dwarf); | ||
| 7308 | if (!unit.alive) continue; | ||
| 7309 | switch (elf.shndx.debug_info) { | ||
| 7310 | .UNDEF => {}, | ||
| 7311 | else => |debug_info_shndx| { | ||
| 7312 | const debug_info_ni = unit.debug_info_ni.unwrap() orelse debug_info_ni: { | ||
| 7313 | const debug_info_ni = elf.addNodeAssumeCapacity( | ||
| 7314 | try debug_info_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ | ||
| 7315 | .alignment = elf.mf.flags.block_size, | ||
| 7316 | .enable_next_moved = true, | ||
| 7317 | }), | ||
| 7318 | .{ .unit_debug_info = ui }, | ||
| 7319 | ); | ||
| 7320 | unit.debug_info_ni = .wrap(debug_info_ni); | ||
| 7321 | break :debug_info_ni debug_info_ni; | ||
| 7322 | }; | ||
| 7323 | if (unit.debug_info_header_ni == .none) unit.debug_info_header_ni = .wrap( | ||
| 7324 | elf.addNodeAssumeCapacity(try debug_info_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ | ||
| 7325 | .next_moved = true, | ||
| 7326 | .enable_next_moved = true, | ||
| 7327 | }), .{ .unit_debug_info_header = ui }), | ||
| 7328 | ); | ||
| 7329 | if (unit.debug_info_footer_ni == .none) unit.debug_info_footer_ni = .wrap( | ||
| 7330 | elf.addNodeAssumeCapacity(try debug_info_ni.addOnlyFooterChild(gpa, &elf.mf, .{ | ||
| 7331 | .size = comptime Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) * 2, | ||
| 7332 | }), .{ .unit_debug_info_footer = ui }), | ||
| 7333 | ); | ||
| 7334 | }, | ||
| 7335 | } | ||
| 7336 | switch (elf.shndx.debug_line) { | ||
| 7337 | .UNDEF => {}, | ||
| 7338 | else => |debug_line_shndx| { | ||
| 7339 | const debug_line_ni = unit.debug_line_ni.unwrap() orelse debug_line_ni: { | ||
| 7340 | const debug_line_ni = elf.addNodeAssumeCapacity( | ||
| 7341 | try debug_line_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ | ||
| 7342 | .alignment = elf.mf.flags.block_size, | ||
| 7343 | .enable_next_moved = true, | ||
| 7344 | }), | ||
| 7345 | .{ .unit_debug_line = ui }, | ||
| 7346 | ); | ||
| 7347 | unit.debug_line_ni = .wrap(debug_line_ni); | ||
| 7348 | break :debug_line_ni debug_line_ni; | ||
| 7349 | }; | ||
| 7350 | if (unit.debug_line_header_ni == .none) unit.debug_line_header_ni = .wrap( | ||
| 7351 | elf.addNodeAssumeCapacity(try debug_line_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ | ||
| 7352 | // Idle tasks are going to try to keep this up to date before we are able to | ||
| 7353 | // write out the full header, so just reserve space for them to do so. | ||
| 7354 | .size = elf.dwarf.unitLengthSize(), | ||
| 7355 | .enable_next_moved = true, | ||
| 7356 | }), .{ .unit_debug_line_header = ui }), | ||
| 7357 | ); | ||
| 7358 | }, | ||
| 7359 | } | ||
| 7360 | switch (elf.shndx.debug_rnglists) { | ||
| 7361 | .UNDEF => {}, | ||
| 7362 | else => |debug_rnglists_shndx| { | ||
| 7363 | const debug_rnglists_ni = unit.debug_rnglists_ni.unwrap() orelse debug_rnglists_ni: { | ||
| 7364 | const debug_rnglists_ni = elf.addNodeAssumeCapacity( | ||
| 7365 | try debug_rnglists_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ | ||
| 7366 | .next_moved = true, | ||
| 7367 | .enable_next_moved = true, | ||
| 7368 | }), | ||
| 7369 | .{ .unit_debug_rnglists = ui }, | ||
| 7370 | ); | ||
| 7371 | unit.debug_rnglists_ni = .wrap(debug_rnglists_ni); | ||
| 7372 | break :debug_rnglists_ni debug_rnglists_ni; | ||
| 7373 | }; | ||
| 7374 | |||
| 7375 | var drh_nw: MappedFile.Node.Writer = undefined; | ||
| 7376 | debug_rnglists_ni.writer(gpa, &elf.mf, &drh_nw); | ||
| 7377 | defer drh_nw.deinit(); | ||
| 7378 | elf.dwarf.genDebugRnglistsHeader(unit, &drh_nw) catch |err| switch (err) { | ||
| 7379 | else => |e| return e, | ||
| 7380 | error.WriteFailed => return drh_nw.err.?, | ||
| 7381 | }; | ||
| 7382 | }, | ||
| 7383 | } | ||
| 6478 | } | 7384 | } |
| 7385 | for (0..units_len) |unit_index| { | ||
| 7386 | const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index)); | ||
| 7387 | const unit = ui.get(&elf.dwarf); | ||
| 7388 | if (unit.debug_info_header_ni == .none) continue; | ||
| 7389 | var dih_nw: MappedFile.Node.Writer = undefined; | ||
| 7390 | const debug_info_header_ni = unit.debug_info_header_ni.unwrap().?; | ||
| 7391 | debug_info_header_ni.writer(gpa, &elf.mf, &dih_nw); | ||
| 7392 | defer dih_nw.deinit(); | ||
| 7393 | elf.resetNodeRelocs(debug_info_header_ni); | ||
| 7394 | elf.dwarf.genDebugInfoHeader(zcu, ui.mod(&elf.dwarf), unit, &dih_nw) catch |err| switch (err) { | ||
| 7395 | else => |e| return e, | ||
| 7396 | error.WriteFailed => return dih_nw.err.?, | ||
| 7397 | }; | ||
| 7398 | } | ||
| 7399 | } | ||
| 7400 | |||
| 7401 | fn flushFiles(elf: *Elf) Error!void { | ||
| 7402 | const gpa = elf.base.comp.gpa; | ||
| 7403 | if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units) |*unit| { | ||
| 7404 | if (!unit.cleanDebugLineHeaderChanged()) continue; | ||
| 7405 | assert(unit.alive); | ||
| 7406 | const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?; | ||
| 7407 | try debug_line_header_ni.parent(&elf.mf).unwrap().?.nextMoved(gpa, &elf.mf); | ||
| 7408 | try debug_line_header_ni.moved(gpa, &elf.mf); | ||
| 7409 | try debug_line_header_ni.nextMoved(gpa, &elf.mf); | ||
| 7410 | var dlh_nw: MappedFile.Node.Writer = undefined; | ||
| 7411 | debug_line_header_ni.writer(gpa, &elf.mf, &dlh_nw); | ||
| 7412 | defer dlh_nw.deinit(); | ||
| 7413 | elf.resetNodeRelocs(debug_line_header_ni); | ||
| 7414 | elf.dwarf.genDebugLineHeader(unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) { | ||
| 7415 | else => |e| return e, | ||
| 7416 | error.WriteFailed => return dlh_nw.err.?, | ||
| 7417 | }; | ||
| 7418 | }; | ||
| 6479 | } | 7419 | } |
| 6480 | 7420 | ||
| 6481 | fn prepareDynamic(elf: *Elf) Error!void { | 7421 | fn prepareDynamic(elf: *Elf) Error!void { |
| ... | @@ -6500,7 +7440,7 @@ fn prepareDynamic(elf: *Elf) Error!void { | ... | @@ -6500,7 +7440,7 @@ fn prepareDynamic(elf: *Elf) Error!void { |
| 6500 | 7440 | ||
| 6501 | const dynamic_size = dynamic_len * 2 * elf.targetPtrSize(); | 7441 | const dynamic_size = dynamic_len * 2 * elf.targetPtrSize(); |
| 6502 | 7442 | ||
| 6503 | try elf.shndx.dynamic.get(elf).ni.resizeLeaf(&elf.mf, comp.gpa, dynamic_size); | 7443 | try elf.shndx.dynamic.get(elf).ni.resizeLeaf(comp.gpa, &elf.mf, dynamic_size); |
| 6504 | switch (elf.shdrPtr(elf.shndx.dynamic)) { | 7444 | switch (elf.shdrPtr(elf.shndx.dynamic)) { |
| 6505 | inline else => |shdr| elf.targetStore(&shdr.size, @intCast(dynamic_size)), | 7445 | inline else => |shdr| elf.targetStore(&shdr.size, @intCast(dynamic_size)), |
| 6506 | } | 7446 | } |
| ... | @@ -6610,7 +7550,7 @@ fn flushDynamic(elf: *Elf) void { | ... | @@ -6610,7 +7550,7 @@ fn flushDynamic(elf: *Elf) void { |
| 6610 | dynamic_index += 9; | 7550 | dynamic_index += 9; |
| 6611 | 7551 | ||
| 6612 | assert(dynamic_index == dynamic_entries.len); | 7552 | assert(dynamic_index == dynamic_entries.len); |
| 6613 | if (elf.targetEndian() != native_endian) for (dynamic_entries) |*dynamic_entry| | 7553 | if (elf.targetEndian() != std.lang.Endian.native) for (dynamic_entries) |*dynamic_entry| |
| 6614 | std.mem.byteSwapAllFields(@TypeOf(dynamic_entry.*), dynamic_entry); | 7554 | std.mem.byteSwapAllFields(@TypeOf(dynamic_entry.*), dynamic_entry); |
| 6615 | }, | 7555 | }, |
| 6616 | } | 7556 | } |
| ... | @@ -6626,6 +7566,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6626,6 +7566,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6626 | addralign: Alignment = .@"1", | 7566 | addralign: Alignment = .@"1", |
| 6627 | entsize: std.elf.Word = 0, | 7567 | entsize: std.elf.Word = 0, |
| 6628 | node_align: Alignment = .@"1", | 7568 | node_align: Alignment = .@"1", |
| 7569 | manual_size: bool = false, | ||
| 6629 | }) Error!Section.Index { | 7570 | }) Error!Section.Index { |
| 6630 | switch (opts.type) { | 7571 | switch (opts.type) { |
| 6631 | .NULL => assert(opts.size == 0), | 7572 | .NULL => assert(opts.size == 0), |
| ... | @@ -6639,7 +7580,11 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6639,7 +7580,11 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6639 | const gpa = elf.base.comp.gpa; | 7580 | const gpa = elf.base.comp.gpa; |
| 6640 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | 7581 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 6641 | try elf.shdrs.ensureUnusedCapacity(gpa, 1); | 7582 | try elf.shdrs.ensureUnusedCapacity(gpa, 1); |
| 6642 | if (opts.flags.ALLOC) try elf.ensureUnusedSymbolCapacity(1, .all_local); | 7583 | const want_symbol = opts.flags.ALLOC or switch (opts.type) { |
| 7584 | .NULL, .PROGBITS, .NOBITS, .X86_64_UNWIND => elf.ehdrType() == .REL, | ||
| 7585 | else => false, | ||
| 7586 | }; | ||
| 7587 | if (want_symbol) try elf.ensureUnusedSymbolCapacity(1, .all_local); | ||
| 6643 | 7588 | ||
| 6644 | const shstrtab_entry = try elf.string(.shstrtab, opts.name); | 7589 | const shstrtab_entry = try elf.string(.shstrtab, opts.name); |
| 6645 | const shndx: Section.Index, const new_shdr_size = shndx: switch (elf.ehdrPtr()) { | 7590 | const shndx: Section.Index, const new_shdr_size = shndx: switch (elf.ehdrPtr()) { |
| ... | @@ -6669,32 +7614,38 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6669,32 +7614,38 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6669 | break :shndx .{ @fromBackingInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) }; | 7614 | break :shndx .{ @fromBackingInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) }; |
| 6670 | }, | 7615 | }, |
| 6671 | }; | 7616 | }; |
| 6672 | try elf.ni.shdr.ensureMinimumSize(&elf.mf, gpa, new_shdr_size); | 7617 | try elf.ni.shdr.ensureMinimumSize(gpa, &elf.mf, new_shdr_size); |
| 6673 | const parent_ni = switch (elf.ehdrType()) { | 7618 | const parent_ni = switch (elf.ehdrType()) { |
| 6674 | .REL => elf.ni.elf, | 7619 | .REL => elf.ni.elf, |
| 6675 | .EXEC, .DYN => segment_ni, | 7620 | .EXEC, .DYN => segment_ni, |
| 6676 | }; | 7621 | }; |
| 6677 | assert(opts.addralign.check(opts.size)); | 7622 | assert(opts.addralign.check(opts.size)); |
| 6678 | const ni = try parent_ni.addFloatingChild(&elf.mf, gpa, .{ | 7623 | const ni = elf.addNodeAssumeCapacity(try parent_ni.addFloatingChild(gpa, &elf.mf, .{ |
| 6679 | .size = opts.node_align.forward(opts.size), | 7624 | .size = opts.node_align.forward(opts.size), |
| 6680 | .alignment = opts.addralign.max(opts.node_align), | 7625 | .alignment = opts.addralign.max(opts.node_align), |
| 6681 | .resized = opts.size > 0, | 7626 | .resized = opts.size > 0, |
| 7627 | .bubbles_moved = opts.flags.ALLOC, | ||
| 7628 | }), switch (opts.manual_size) { | ||
| 7629 | false => .{ .section = shndx }, | ||
| 7630 | true => .{ .section_manual_size = shndx }, | ||
| 6682 | }); | 7631 | }); |
| 6683 | const addr = elf.computeNodeVAddr(ni); | 7632 | const addr = elf.computeNodeVAddr(ni); |
| 6684 | const lsi: Symbol.LocalIndex = if (opts.flags.ALLOC) elf.addLocalSymbolAssumeCapacity(.{ | 7633 | elf.shdrs.appendAssumeCapacity(.{ |
| 6685 | .node = .wrap(ni), | 7634 | .lsi = if (want_symbol) elf.addLocalSymbolAssumeCapacity(.{ |
| 6686 | .name = .empty, | 7635 | .node = ni.toOptional(), |
| 6687 | .value = addr, | 7636 | .name = .empty, |
| 6688 | .size = 0, | 7637 | .value = addr, |
| 6689 | .type = .SECTION, | 7638 | .size = 0, |
| 6690 | .shndx = shndx, | 7639 | .type = .SECTION, |
| 6691 | }) else .null; | 7640 | .shndx = shndx, |
| 6692 | elf.shdrs.appendAssumeCapacity(.{ .lsi = lsi, .ni = ni, .rela = switch (opts.type) { | 7641 | }) else .null, |
| 6693 | .REL => unreachable, | 7642 | .ni = ni, |
| 6694 | .RELA => .{ .free_head = .none }, | 7643 | .rela = switch (opts.type) { |
| 6695 | else => .{ .shndx = .UNDEF }, | 7644 | .REL => unreachable, |
| 6696 | } }); | 7645 | .RELA => .{ .free_head = .none }, |
| 6697 | elf.nodes.appendAssumeCapacity(.{ .section = shndx }); | 7646 | else => .{ .shndx = .UNDEF }, |
| 7647 | }, | ||
| 7648 | }); | ||
| 6698 | switch (elf.shdrPtr(shndx)) { | 7649 | switch (elf.shdrPtr(shndx)) { |
| 6699 | inline else => |shdr, class| { | 7650 | inline else => |shdr, class| { |
| 6700 | shdr.* = .{ | 7651 | shdr.* = .{ |
| ... | @@ -6702,14 +7653,14 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6702,14 +7653,14 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6702 | .type = opts.type, | 7653 | .type = opts.type, |
| 6703 | .flags = .{ .shf = opts.flags }, | 7654 | .flags = .{ .shf = opts.flags }, |
| 6704 | .addr = @intCast(addr), | 7655 | .addr = @intCast(addr), |
| 6705 | .offset = @intCast(elf.getNodeElfOffset(ni)), | 7656 | .offset = @intCast(elf.computeNodeElfOffset(ni)), |
| 6706 | .size = @intCast(opts.size), | 7657 | .size = @intCast(opts.size), |
| 6707 | .link = opts.link, | 7658 | .link = opts.link, |
| 6708 | .info = opts.info, | 7659 | .info = opts.info, |
| 6709 | .addralign = @intCast(opts.addralign.toByteUnits()), | 7660 | .addralign = @intCast(opts.addralign.toByteUnits()), |
| 6710 | .entsize = opts.entsize, | 7661 | .entsize = opts.entsize, |
| 6711 | }; | 7662 | }; |
| 6712 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(class.ElfN().Shdr, shdr); | 7663 | if (elf.targetEndian() != std.lang.Endian.native) std.mem.byteSwapAllFields(class.ElfN().Shdr, shdr); |
| 6713 | }, | 7664 | }, |
| 6714 | } | 7665 | } |
| 6715 | return shndx; | 7666 | return shndx; |
| ... | @@ -6719,6 +7670,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) | ... | @@ -6719,6 +7670,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 6719 | if (len == 0) return; | 7670 | if (len == 0) return; |
| 6720 | const gpa = elf.base.comp.gpa; | 7671 | const gpa = elf.base.comp.gpa; |
| 6721 | try elf.symbol_relocs.ensureUnusedCapacity(gpa, len); | 7672 | try elf.symbol_relocs.ensureUnusedCapacity(gpa, len); |
| 7673 | try elf.node_relocs.ensureUnusedCapacity(gpa, len); | ||
| 6722 | try elf.got_relocs.ensureUnusedCapacity(gpa, len); | 7674 | try elf.got_relocs.ensureUnusedCapacity(gpa, len); |
| 6723 | const class = elf.identClass(); | 7675 | const class = elf.identClass(); |
| 6724 | switch (elf.ehdrType()) { | 7676 | switch (elf.ehdrType()) { |
| ... | @@ -6749,6 +7701,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) | ... | @@ -6749,6 +7701,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 6749 | inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela), | 7701 | inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela), |
| 6750 | }, | 7702 | }, |
| 6751 | .node_align = elf.mf.flags.block_size, | 7703 | .node_align = elf.mf.flags.block_size, |
| 7704 | .manual_size = true, | ||
| 6752 | }); | 7705 | }); |
| 6753 | elf.section_by_name.putAssumeCapacityNoClobber(rela_shndx.name(elf), {}); | 7706 | elf.section_by_name.putAssumeCapacityNoClobber(rela_shndx.name(elf), {}); |
| 6754 | shndx.get(elf).rela.shndx = rela_shndx; | 7707 | shndx.get(elf).rela.shndx = rela_shndx; |
| ... | @@ -6763,7 +7716,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) | ... | @@ -6763,7 +7716,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 6763 | .NONE, _ => unreachable, | 7716 | .NONE, _ => unreachable, |
| 6764 | inline else => |ct_class| (elf.got.count() + new_got_entries) * @sizeOf(ct_class.ElfN().Addr), | 7717 | inline else => |ct_class| (elf.got.count() + new_got_entries) * @sizeOf(ct_class.ElfN().Addr), |
| 6765 | }; | 7718 | }; |
| 6766 | try elf.shndx.got.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_got_size); | 7719 | try elf.shndx.got.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_got_size); |
| 6767 | 7720 | ||
| 6768 | if (elf.shndx.dynamic != .UNDEF) { | 7721 | if (elf.shndx.dynamic != .UNDEF) { |
| 6769 | try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, new_got_entries); | 7722 | try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, new_got_entries); |
| ... | @@ -6795,17 +7748,12 @@ fn addRelocAssumeCapacity( | ... | @@ -6795,17 +7748,12 @@ fn addRelocAssumeCapacity( |
| 6795 | .addend = addend, | 7748 | .addend = addend, |
| 6796 | }); | 7749 | }); |
| 6797 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | 7750 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| 6798 | const next: SymbolReloc.Index = next: { | 7751 | const first_target_reloc = &target.index(elf).ptr(elf).first_target_reloc; |
| 6799 | const target_ptr = target.index(elf).ptr(elf); | 7752 | const next = first_target_reloc.*; |
| 6800 | const next = target_ptr.first_target_reloc; | 7753 | first_target_reloc.* = ri; |
| 6801 | target_ptr.first_target_reloc = ri; | 7754 | if (next != .none) next.get(elf).prev = ri; |
| 6802 | break :next next; | ||
| 6803 | }; | ||
| 6804 | if (next != .none) { | ||
| 6805 | next.get(elf).prev = ri; | ||
| 6806 | } | ||
| 6807 | elf.symbol_relocs.appendAssumeCapacity(.{ | 7755 | elf.symbol_relocs.appendAssumeCapacity(.{ |
| 6808 | .node = node, | 7756 | .node = node.toOptional(), |
| 6809 | .offset = offset, | 7757 | .offset = offset, |
| 6810 | .type = undefined, | 7758 | .type = undefined, |
| 6811 | .target = target, | 7759 | .target = target, |
| ... | @@ -6816,7 +7764,6 @@ fn addRelocAssumeCapacity( | ... | @@ -6816,7 +7764,6 @@ fn addRelocAssumeCapacity( |
| 6816 | .result = .ok, | 7764 | .result = .ok, |
| 6817 | }); | 7765 | }); |
| 6818 | }, | 7766 | }, |
| 6819 | |||
| 6820 | .DYN, .EXEC => switch (elf.ehdrMachine()) { | 7767 | .DYN, .EXEC => switch (elf.ehdrMachine()) { |
| 6821 | .AARCH64 => switch (@"type".AARCH64) { | 7768 | .AARCH64 => switch (@"type".AARCH64) { |
| 6822 | .NONE => {}, | 7769 | .NONE => {}, |
| ... | @@ -7239,14 +8186,12 @@ fn addSymbolRelocAssumeCapacity( | ... | @@ -7239,14 +8186,12 @@ fn addSymbolRelocAssumeCapacity( |
| 7239 | }; | 8186 | }; |
| 7240 | 8187 | ||
| 7241 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | 8188 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| 7242 | const target_ptr = target.index(elf).ptr(elf); | 8189 | const first_target_reloc = &target.index(elf).ptr(elf).first_target_reloc; |
| 7243 | const next = target_ptr.first_target_reloc; | 8190 | const next = first_target_reloc.*; |
| 7244 | target_ptr.first_target_reloc = ri; | 8191 | first_target_reloc.* = ri; |
| 7245 | if (next != .none) { | 8192 | if (next != .none) next.get(elf).prev = ri; |
| 7246 | next.get(elf).prev = ri; | ||
| 7247 | } | ||
| 7248 | elf.symbol_relocs.appendAssumeCapacity(.{ | 8193 | elf.symbol_relocs.appendAssumeCapacity(.{ |
| 7249 | .node = node, | 8194 | .node = node.toOptional(), |
| 7250 | .offset = offset, | 8195 | .offset = offset, |
| 7251 | .target = target, | 8196 | .target = target, |
| 7252 | .addend = addend, | 8197 | .addend = addend, |
| ... | @@ -7263,6 +8208,103 @@ fn addSymbolRelocAssumeCapacity( | ... | @@ -7263,6 +8208,103 @@ fn addSymbolRelocAssumeCapacity( |
| 7263 | // Actually apply the new relocation! | 8208 | // Actually apply the new relocation! |
| 7264 | ri.get(elf).apply(elf); | 8209 | ri.get(elf).apply(elf); |
| 7265 | } | 8210 | } |
| 8211 | fn addNodeRelocAssumeCapacity( | ||
| 8212 | elf: *Elf, | ||
| 8213 | node: MappedFile.Node.Index, | ||
| 8214 | offset: u64, | ||
| 8215 | target: MappedFile.Node.Index, | ||
| 8216 | addend: i64, | ||
| 8217 | @"type": NodeReloc.Type, | ||
| 8218 | ) Error!void { | ||
| 8219 | const shndx = elf.getNodeShndx(target); | ||
| 8220 | assert(!shndx.flags(elf).ALLOC); // not yet needed so not implemented | ||
| 8221 | const first_target_reloc = switch (elf.getNode(target)) { | ||
| 8222 | else => unreachable, | ||
| 8223 | .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc, | ||
| 8224 | .unit_frame_cie => |ui| &elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc, | ||
| 8225 | .unit_debug_info_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_target_reloc, | ||
| 8226 | .unit_debug_line_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_target_reloc, | ||
| 8227 | .unit_debug_rnglists => |ui| &elf.dwarf_units[@backingInt(ui)].debug_rnglists_first_target_reloc, | ||
| 8228 | .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc, | ||
| 8229 | .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc, | ||
| 8230 | .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc, | ||
| 8231 | .decl_debug_info => |di| &elf.dwarf_decls.getPtr(di).?.debug_info_first_target_reloc, | ||
| 8232 | }; | ||
| 8233 | const next = first_target_reloc.*; | ||
| 8234 | const ri: NodeReloc.Index = @fromBackingInt(@intCast(elf.node_relocs.items.len)); | ||
| 8235 | first_target_reloc.* = ri; | ||
| 8236 | if (next != .none) next.get(elf).prev = ri; | ||
| 8237 | switch (elf.ehdrType()) { | ||
| 8238 | .REL => { | ||
| 8239 | const rela_shndx = elf.getNodeShndx(node).get(elf).rela.shndx; | ||
| 8240 | const rela_index = rela_shndx.relaAddOneAssumeCapacity(elf, .{ | ||
| 8241 | .type = switch (elf.ehdrMachine()) { | ||
| 8242 | .AARCH64 => .{ .AARCH64 = switch (@"type") { | ||
| 8243 | .abs32 => .ABS32, | ||
| 8244 | .abs64 => .ABS64, | ||
| 8245 | } }, | ||
| 8246 | .LOONGARCH => .{ .LARCH = switch (@"type") { | ||
| 8247 | .abs32 => .@"32", | ||
| 8248 | .abs64 => .@"64", | ||
| 8249 | } }, | ||
| 8250 | .PPC64 => .{ .PPC64 = switch (@"type") { | ||
| 8251 | .abs32 => .ADDR32, | ||
| 8252 | .abs64 => .ADDR64, | ||
| 8253 | } }, | ||
| 8254 | .RISCV => .{ .RISCV = switch (@"type") { | ||
| 8255 | .abs32 => .@"32", | ||
| 8256 | .abs64 => .@"64", | ||
| 8257 | } }, | ||
| 8258 | .SPARCV9 => .{ .SPARC = switch (@"type") { | ||
| 8259 | .abs32 => .UA32, | ||
| 8260 | .abs64 => .UA64, | ||
| 8261 | } }, | ||
| 8262 | .X86_64 => .{ .X86_64 = switch (@"type") { | ||
| 8263 | .abs32 => .@"32", | ||
| 8264 | .abs64 => .@"64", | ||
| 8265 | } }, | ||
| 8266 | }, | ||
| 8267 | // This field needs to equal the offset into the section, which is *not* necessarily | ||
| 8268 | // the same thing as our `offset`, which is the offset into `node`. We could compute | ||
| 8269 | // the section offset now, but there's no point, because `flushMovedNodeRelocs` will | ||
| 8270 | // eventually do it for us anyway, so just init to 0. | ||
| 8271 | .offset = 0, | ||
| 8272 | .raw_sym_index = @backingInt(switch (shndx.get(elf).lsi) { | ||
| 8273 | .null => unreachable, | ||
| 8274 | else => |lsi| lsi.index(), | ||
| 8275 | }), | ||
| 8276 | .addend = 0, | ||
| 8277 | }); | ||
| 8278 | elf.node_relocs.appendAssumeCapacity(.{ | ||
| 8279 | .node = node.toOptional(), | ||
| 8280 | .offset = offset, | ||
| 8281 | .type = undefined, | ||
| 8282 | .target = target, | ||
| 8283 | .addend = addend, | ||
| 8284 | .next = next, | ||
| 8285 | .prev = .none, | ||
| 8286 | .rela_index = rela_index.toOptional(), | ||
| 8287 | .result = .ok, | ||
| 8288 | }); | ||
| 8289 | }, | ||
| 8290 | .DYN, .EXEC => { | ||
| 8291 | elf.node_relocs.appendAssumeCapacity(.{ | ||
| 8292 | .node = node.toOptional(), | ||
| 8293 | .offset = offset, | ||
| 8294 | .target = target, | ||
| 8295 | .addend = addend, | ||
| 8296 | .type = @"type", | ||
| 8297 | .next = next, | ||
| 8298 | .prev = .none, | ||
| 8299 | .rela_index = .none, | ||
| 8300 | .result = .ok, | ||
| 8301 | }); | ||
| 8302 | |||
| 8303 | // Actually apply the new relocation! | ||
| 8304 | ri.get(elf).apply(elf); | ||
| 8305 | }, | ||
| 8306 | } | ||
| 8307 | } | ||
| 7266 | fn addGotRelocAssumeCapacity( | 8308 | fn addGotRelocAssumeCapacity( |
| 7267 | elf: *Elf, | 8309 | elf: *Elf, |
| 7268 | node: MappedFile.Node.Index, | 8310 | node: MappedFile.Node.Index, |
| ... | @@ -7273,6 +8315,7 @@ fn addGotRelocAssumeCapacity( | ... | @@ -7273,6 +8315,7 @@ fn addGotRelocAssumeCapacity( |
| 7273 | ) void { | 8315 | ) void { |
| 7274 | assert(elf.ehdrType() != .REL); | 8316 | assert(elf.ehdrType() != .REL); |
| 7275 | switch (elf.getNode(node)) { | 8317 | switch (elf.getNode(node)) { |
| 8318 | .deleted, | ||
| 7276 | .archive, | 8319 | .archive, |
| 7277 | .archive_header, | 8320 | .archive_header, |
| 7278 | .archive_input_member, | 8321 | .archive_input_member, |
| ... | @@ -7282,8 +8325,26 @@ fn addGotRelocAssumeCapacity( | ... | @@ -7282,8 +8325,26 @@ fn addGotRelocAssumeCapacity( |
| 7282 | .shdr, | 8325 | .shdr, |
| 7283 | .segment, | 8326 | .segment, |
| 7284 | .copied_global, | 8327 | .copied_global, |
| 8328 | .debug_shared, | ||
| 8329 | .eh_frame_footer, | ||
| 8330 | .unit_padding, | ||
| 8331 | .unit_frame, | ||
| 8332 | .unit_frame_cie, | ||
| 8333 | .unit_debug_info, | ||
| 8334 | .unit_debug_info_header, | ||
| 8335 | .unit_debug_info_footer, | ||
| 8336 | .unit_debug_line, | ||
| 8337 | .unit_debug_line_header, | ||
| 8338 | .unit_debug_rnglists, | ||
| 8339 | .const_debug_info, | ||
| 8340 | .global_debug_info, | ||
| 8341 | .func_frame_fde, | ||
| 8342 | .func_debug_info, | ||
| 8343 | .func_debug_line, | ||
| 8344 | .decl_debug_info, | ||
| 7285 | => unreachable, // cannot contain relocs, | 8345 | => unreachable, // cannot contain relocs, |
| 7286 | .section, | 8346 | .section, |
| 8347 | .section_manual_size, | ||
| 7287 | .uav, | 8348 | .uav, |
| 7288 | => unreachable, // cannot contain GOT relocs | 8349 | => unreachable, // cannot contain GOT relocs |
| 7289 | .input_section, | 8350 | .input_section, |
| ... | @@ -7519,14 +8580,13 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool { | ... | @@ -7519,14 +8580,13 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool { |
| 7519 | try Section.Index.data.ensureAligned(elf, dso_global.alignment); | 8580 | try Section.Index.data.ensureAligned(elf, dso_global.alignment); |
| 7520 | 8581 | ||
| 7521 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | 8582 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 7522 | const node = try Section.Index.data.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{ | 8583 | const node = try Section.Index.data.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ |
| 7523 | .size = dso_global.alignment.forward(dso_global.size), | 8584 | .size = dso_global.alignment.forward(dso_global.size), |
| 7524 | .alignment = dso_global.alignment, | 8585 | .alignment = dso_global.alignment, |
| 7525 | }); | 8586 | }); |
| 7526 | errdefer comptime unreachable; | 8587 | errdefer comptime unreachable; |
| 7527 | 8588 | ||
| 7528 | const vaddr = elf.computeNodeVAddr(node); | 8589 | const vaddr = elf.computeNodeVAddr(node); |
| 7529 | elf.nodes.appendAssumeCapacity(.{ .copied_global = global_name }); | ||
| 7530 | const rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{ | 8590 | const rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{ |
| 7531 | .type = .copy(elf), | 8591 | .type = .copy(elf), |
| 7532 | .offset = vaddr, | 8592 | .offset = vaddr, |
| ... | @@ -7555,10 +8615,12 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool { | ... | @@ -7555,10 +8615,12 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool { |
| 7555 | } | 8615 | } |
| 7556 | 8616 | ||
| 7557 | pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void { | 8617 | pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void { |
| 7558 | const diags = &elf.base.comp.link_diags; | ||
| 7559 | elf.updateNavInner(pt, nav_index) catch |err| switch (err) { | 8618 | elf.updateNavInner(pt, nav_index) catch |err| switch (err) { |
| 7560 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 7561 | else => |e| return e, | 8619 | else => |e| return e, |
| 8620 | error.MappedFileIo => return elf.base.comp.link_diags.fail( | ||
| 8621 | "failed to write output file: {t}", | ||
| 8622 | .{elf.mf.io_err.?}, | ||
| 8623 | ), | ||
| 7562 | }; | 8624 | }; |
| 7563 | } | 8625 | } |
| 7564 | fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void { | 8626 | fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void { |
| ... | @@ -7568,11 +8630,14 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) | ... | @@ -7568,11 +8630,14 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 7568 | 8630 | ||
| 7569 | const nav = ip.getNav(nav_index); | 8631 | const nav = ip.getNav(nav_index); |
| 7570 | if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return; | 8632 | if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return; |
| 7571 | if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return; | 8633 | if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) { |
| 8634 | if (elf.ehdrMachine() != .X86_64) return; | ||
| 8635 | const mod = zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?; | ||
| 8636 | return if (!mod.strip) elf.dwarf.updateComptimeNav(pt, nav_index); | ||
| 8637 | } | ||
| 7572 | 8638 | ||
| 7573 | const nmi = try elf.navMapIndex(zcu, nav_index); | 8639 | const nmi = try elf.navMapIndex(zcu, nav_index); |
| 7574 | const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; | 8640 | const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; |
| 7575 | elf.resetNodeRelocs(ni); | ||
| 7576 | 8641 | ||
| 7577 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be | 8642 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be |
| 7578 | // called to apply the NAV's new relocations. | 8643 | // called to apply the NAV's new relocations. |
| ... | @@ -7580,8 +8645,9 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) | ... | @@ -7580,8 +8645,9 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 7580 | 8645 | ||
| 7581 | { | 8646 | { |
| 7582 | var nw: MappedFile.Node.Writer = undefined; | 8647 | var nw: MappedFile.Node.Writer = undefined; |
| 7583 | ni.writer(&elf.mf, gpa, &nw); | 8648 | ni.writer(gpa, &elf.mf, &nw); |
| 7584 | defer nw.deinit(); | 8649 | defer nw.deinit(); |
| 8650 | elf.resetNodeRelocs(ni); | ||
| 7585 | codegen.generateSymbol( | 8651 | codegen.generateSymbol( |
| 7586 | &elf.base, | 8652 | &elf.base, |
| 7587 | pt, | 8653 | pt, |
| ... | @@ -7589,16 +8655,153 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) | ... | @@ -7589,16 +8655,153 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 7589 | &nw.interface, | 8655 | &nw.interface, |
| 7590 | .{ .atom_index = Node.toAtom(ni) }, | 8656 | .{ .atom_index = Node.toAtom(ni) }, |
| 7591 | ) catch |err| switch (err) { | 8657 | ) catch |err| switch (err) { |
| 7592 | error.WriteFailed => return nw.err.?, | ||
| 7593 | else => |e| return e, | 8658 | else => |e| return e, |
| 8659 | error.WriteFailed => return nw.err.?, | ||
| 7594 | }; | 8660 | }; |
| 7595 | switch (elf.symPtr(nmi.symbol(elf).index())) { | 8661 | switch (elf.symPtr(nmi.symbol(elf).index())) { |
| 7596 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 8662 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), |
| 7597 | } | 8663 | } |
| 7598 | } | 8664 | } |
| 7599 | 8665 | ||
| 7600 | // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs. | 8666 | // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs. |
| 7601 | try elf.genPending(pt); | 8667 | try elf.genPending(pt); |
| 8668 | try elf.dwarf.const_pool.flushPending(pt, .{ .elf2 = elf }); | ||
| 8669 | } | ||
| 8670 | |||
| 8671 | pub fn updateContainerType( | ||
| 8672 | elf: *Elf, | ||
| 8673 | pt: Zcu.PerThread, | ||
| 8674 | ty: InternPool.Index, | ||
| 8675 | success: bool, | ||
| 8676 | ) link.Error!void { | ||
| 8677 | elf.updateContainerTypeInner(pt, ty, success) catch |err| switch (err) { | ||
| 8678 | else => |e| return e, | ||
| 8679 | error.MappedFileIo => return elf.base.comp.link_diags.fail( | ||
| 8680 | "failed to write output file: {t}", | ||
| 8681 | .{elf.mf.io_err.?}, | ||
| 8682 | ), | ||
| 8683 | }; | ||
| 8684 | } | ||
| 8685 | pub fn updateContainerTypeInner( | ||
| 8686 | elf: *Elf, | ||
| 8687 | pt: Zcu.PerThread, | ||
| 8688 | ty: InternPool.Index, | ||
| 8689 | success: bool, | ||
| 8690 | ) Error!void { | ||
| 8691 | switch (elf.base.comp.config.debug_format) { | ||
| 8692 | .strip => {}, | ||
| 8693 | .dwarf => { | ||
| 8694 | try elf.dwarf.const_pool.updateContainerType(pt, .{ .elf2 = elf }, ty, success); | ||
| 8695 | try elf.dwarf.const_pool.flushPending(pt, .{ .elf2 = elf }); | ||
| 8696 | }, | ||
| 8697 | .code_view => unreachable, | ||
| 8698 | } | ||
| 8699 | if (!success) return; | ||
| 8700 | var lazy_it = elf.lazy.iterator(); | ||
| 8701 | while (lazy_it.next()) |lazy| if (lazy.value.map.getIndex(ty)) |lmi| { | ||
| 8702 | if (lazy.value.pending_index <= lmi) continue; | ||
| 8703 | // This type has changed on this incremental update, so update the lazy code/data. | ||
| 8704 | try elf.genLazy(pt, .{ .kind = lazy.key, .index = @intCast(lmi) }); | ||
| 8705 | }; | ||
| 8706 | } | ||
| 8707 | |||
| 8708 | pub fn addConst( | ||
| 8709 | elf: *Elf, | ||
| 8710 | _: Zcu.PerThread, | ||
| 8711 | cpi: link.ConstPool.Index, | ||
| 8712 | val: InternPool.Index, | ||
| 8713 | ) link.Error!void { | ||
| 8714 | switch (elf.base.comp.config.debug_format) { | ||
| 8715 | .strip => {}, | ||
| 8716 | .dwarf => { | ||
| 8717 | const gpa = elf.base.comp.gpa; | ||
| 8718 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | ||
| 8719 | try elf.dwarf.consts.ensureUnusedCapacity(gpa, 1); | ||
| 8720 | try elf.dwarf_consts.ensureUnusedCapacity(gpa, 1); | ||
| 8721 | try elf.dwarf.addConst(cpi, val, &addConstNode); | ||
| 8722 | }, | ||
| 8723 | .code_view => unreachable, | ||
| 8724 | } | ||
| 8725 | } | ||
| 8726 | fn addConstNode(lf: *link.File, ui: Dwarf.Unit.Index, cpi: link.ConstPool.Index) link.Error!MappedFile.Node.Index { | ||
| 8727 | const elf = lf.cast(.elf2).?; | ||
| 8728 | const unit = ui.get(&elf.dwarf); | ||
| 8729 | const debug_info_ni = elf.addNodeAssumeCapacity( | ||
| 8730 | unit.debug_info_ni.unwrap().?.addFloatingChild(lf.comp.gpa, &elf.mf, .{ | ||
| 8731 | .enable_next_moved = true, | ||
| 8732 | }) catch |err| switch (err) { | ||
| 8733 | else => |e| return e, | ||
| 8734 | error.MappedFileIo => return lf.comp.link_diags.fail("failed to write output file: {t}", .{ | ||
| 8735 | elf.mf.io_err.?, | ||
| 8736 | }), | ||
| 8737 | }, | ||
| 8738 | .{ .const_debug_info = cpi }, | ||
| 8739 | ); | ||
| 8740 | elf.dwarf_consts.putAssumeCapacityNoClobber(cpi, .{ | ||
| 8741 | .debug_info_first_target_reloc = .none, | ||
| 8742 | .debug_info_first_symbol_reloc = .none, | ||
| 8743 | .debug_info_first_node_reloc = .none, | ||
| 8744 | }); | ||
| 8745 | return debug_info_ni; | ||
| 8746 | } | ||
| 8747 | |||
| 8748 | pub fn updateConst( | ||
| 8749 | elf: *Elf, | ||
| 8750 | pt: Zcu.PerThread, | ||
| 8751 | cpi: link.ConstPool.Index, | ||
| 8752 | val: InternPool.Index, | ||
| 8753 | ) link.Error!void { | ||
| 8754 | switch (val) { | ||
| 8755 | .anyerror_type => {}, // handled in `updateErrorData` instead | ||
| 8756 | else => try elf.updateConstInner(pt, cpi, val, .complete), | ||
| 8757 | } | ||
| 8758 | } | ||
| 8759 | fn updateConstInner( | ||
| 8760 | elf: *Elf, | ||
| 8761 | pt: Zcu.PerThread, | ||
| 8762 | cpi: link.ConstPool.Index, | ||
| 8763 | val: InternPool.Index, | ||
| 8764 | complete: enum { incomplete, complete }, | ||
| 8765 | ) link.Error!void { | ||
| 8766 | switch (elf.base.comp.config.debug_format) { | ||
| 8767 | .strip => {}, | ||
| 8768 | .dwarf => { | ||
| 8769 | { | ||
| 8770 | switch (pt.zcu.intern_pool.indexToKey(val)) { | ||
| 8771 | else => {}, | ||
| 8772 | .func => |func| { | ||
| 8773 | const fi = try elf.dwarf.getFunc(func.owner_nav); | ||
| 8774 | switch (fi.get(&elf.dwarf).state) { | ||
| 8775 | .unresolved => {}, | ||
| 8776 | .resolved => return, | ||
| 8777 | } | ||
| 8778 | }, | ||
| 8779 | } | ||
| 8780 | const gpa = elf.base.comp.gpa; | ||
| 8781 | const debug_info_ni = Dwarf.Const.get(cpi, &elf.dwarf).debug_info_ni.unwrap().?; | ||
| 8782 | try debug_info_ni.moved(gpa, &elf.mf); | ||
| 8783 | var di_nw: MappedFile.Node.Writer = undefined; | ||
| 8784 | debug_info_ni.writer(gpa, &elf.mf, &di_nw); | ||
| 8785 | defer di_nw.deinit(); | ||
| 8786 | elf.resetNodeRelocs(debug_info_ni); | ||
| 8787 | switch (complete) { | ||
| 8788 | .incomplete => try elf.dwarf.updateConstIncomplete(pt, &di_nw, val), | ||
| 8789 | .complete => try elf.dwarf.updateConst(pt, &di_nw, val), | ||
| 8790 | } | ||
| 8791 | } | ||
| 8792 | try elf.genPending(pt); | ||
| 8793 | }, | ||
| 8794 | .code_view => unreachable, | ||
| 8795 | } | ||
| 8796 | } | ||
| 8797 | |||
| 8798 | pub fn updateConstIncomplete( | ||
| 8799 | elf: *Elf, | ||
| 8800 | pt: Zcu.PerThread, | ||
| 8801 | cpi: link.ConstPool.Index, | ||
| 8802 | val: InternPool.Index, | ||
| 8803 | ) link.Error!void { | ||
| 8804 | return elf.updateConstInner(pt, cpi, val, .incomplete); | ||
| 7602 | } | 8805 | } |
| 7603 | 8806 | ||
| 7604 | pub fn updateFunc( | 8807 | pub fn updateFunc( |
| ... | @@ -7607,10 +8810,12 @@ pub fn updateFunc( | ... | @@ -7607,10 +8810,12 @@ pub fn updateFunc( |
| 7607 | func_index: InternPool.Index, | 8810 | func_index: InternPool.Index, |
| 7608 | mir: *const codegen.AnyMir, | 8811 | mir: *const codegen.AnyMir, |
| 7609 | ) link.Error!void { | 8812 | ) link.Error!void { |
| 7610 | const diags = &elf.base.comp.link_diags; | ||
| 7611 | elf.updateFuncInner(pt, func_index, mir) catch |err| switch (err) { | 8813 | elf.updateFuncInner(pt, func_index, mir) catch |err| switch (err) { |
| 7612 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 7613 | else => |e| return e, | 8814 | else => |e| return e, |
| 8815 | error.MappedFileIo => return elf.base.comp.link_diags.fail( | ||
| 8816 | "failed to write output file: {t}", | ||
| 8817 | .{elf.mf.io_err.?}, | ||
| 8818 | ), | ||
| 7614 | }; | 8819 | }; |
| 7615 | } | 8820 | } |
| 7616 | fn updateFuncInner( | 8821 | fn updateFuncInner( |
| ... | @@ -7627,8 +8832,8 @@ fn updateFuncInner( | ... | @@ -7627,8 +8832,8 @@ fn updateFuncInner( |
| 7627 | 8832 | ||
| 7628 | const nmi = try elf.navMapIndex(zcu, func.owner_nav); | 8833 | const nmi = try elf.navMapIndex(zcu, func.owner_nav); |
| 7629 | log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), nmi.symbol(elf) }); | 8834 | log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), nmi.symbol(elf) }); |
| 7630 | const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; | 8835 | const lsi = nmi.symbol(elf); |
| 7631 | elf.resetNodeRelocs(ni); | 8836 | const ni = lsi.index().ptr(elf).node.unwrap().?; |
| 7632 | 8837 | ||
| 7633 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be | 8838 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be |
| 7634 | // called to apply the NAV's new relocations. | 8839 | // called to apply the NAV's new relocations. |
| ... | @@ -7636,8 +8841,145 @@ fn updateFuncInner( | ... | @@ -7636,8 +8841,145 @@ fn updateFuncInner( |
| 7636 | 8841 | ||
| 7637 | { | 8842 | { |
| 7638 | var nw: MappedFile.Node.Writer = undefined; | 8843 | var nw: MappedFile.Node.Writer = undefined; |
| 7639 | ni.writer(&elf.mf, gpa, &nw); | 8844 | ni.writer(gpa, &elf.mf, &nw); |
| 7640 | defer nw.deinit(); | 8845 | defer nw.deinit(); |
| 8846 | var debug_output_buf: Dwarf.WipNav.Debug = undefined; | ||
| 8847 | const debug_output: link.File.DebugInfoOutput, const dwarf_func = debug_output: { | ||
| 8848 | if (elf.ehdrMachine() != .X86_64) break :debug_output .{ .none, undefined }; | ||
| 8849 | const dwarf = &elf.dwarf; | ||
| 8850 | const src_inst = nav.srcInst(ip); | ||
| 8851 | const mod = zcu.fileByIndex(src_inst.resolveFile(ip)).mod.?; | ||
| 8852 | if (mod.strip and mod.unwind_tables == .none) break :debug_output .{ .none, undefined }; | ||
| 8853 | |||
| 8854 | try elf.nodes.ensureUnusedCapacity(gpa, 4); | ||
| 8855 | const dwarf_fi = try dwarf.getFunc(func.owner_nav); | ||
| 8856 | |||
| 8857 | const wip_nav = &debug_output_buf.wip_nav; | ||
| 8858 | wip_nav.* = .{ | ||
| 8859 | .dwarf = dwarf, | ||
| 8860 | .unit = dwarf.getUnit(mod), | ||
| 8861 | .func = func_index, | ||
| 8862 | .func_si = Symbol.Id.local(lsi).toTypeErased(), | ||
| 8863 | .cfi = .{ | ||
| 8864 | .loc = 0, | ||
| 8865 | .cfa = dwarf.frame.header.initial_instructions[0].def_cfa, | ||
| 8866 | }, | ||
| 8867 | .frame_format = switch (mod.unwind_tables) { | ||
| 8868 | .none => .debug_frame, | ||
| 8869 | .sync, .async => .eh_frame, | ||
| 8870 | }, | ||
| 8871 | .fde_writer = undefined, | ||
| 8872 | .frame_func_length = undefined, | ||
| 8873 | }; | ||
| 8874 | const unit = wip_nav.unit.get(dwarf); | ||
| 8875 | |||
| 8876 | const frame_align: Alignment = switch (elf.identClass()) { | ||
| 8877 | .NONE, _ => unreachable, | ||
| 8878 | .@"32" => .@"4", | ||
| 8879 | .@"64" => .@"8", | ||
| 8880 | }; | ||
| 8881 | const frame_ni = unit.frame_ni.unwrap() orelse frame_ni: { | ||
| 8882 | const frame_ni = elf.addNodeAssumeCapacity(try switch (wip_nav.frame_format) { | ||
| 8883 | .debug_frame => elf.shndx.debug_frame, | ||
| 8884 | .eh_frame => elf.shndx.eh_frame, | ||
| 8885 | }.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ | ||
| 8886 | .alignment = frame_align.max(elf.mf.flags.block_size), | ||
| 8887 | .enable_next_moved = true, | ||
| 8888 | }), .{ .unit_frame = wip_nav.unit }); | ||
| 8889 | unit.frame_ni = .wrap(frame_ni); | ||
| 8890 | break :frame_ni frame_ni; | ||
| 8891 | }; | ||
| 8892 | if (unit.cie_ni == .none) { | ||
| 8893 | const cie_ni = elf.addNodeAssumeCapacity( | ||
| 8894 | try frame_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ | ||
| 8895 | .alignment = frame_align, | ||
| 8896 | .next_moved = true, | ||
| 8897 | .enable_next_moved = true, | ||
| 8898 | }), | ||
| 8899 | .{ .unit_frame_cie = wip_nav.unit }, | ||
| 8900 | ); | ||
| 8901 | unit.cie_ni = .wrap(cie_ni); | ||
| 8902 | var cie_nw: MappedFile.Node.Writer = undefined; | ||
| 8903 | cie_ni.writer(gpa, &elf.mf, &cie_nw); | ||
| 8904 | defer cie_nw.deinit(); | ||
| 8905 | dwarf.genDebugFrameCie(&cie_nw.interface, switch (elf.ehdrMachine()) { | ||
| 8906 | else => unreachable, | ||
| 8907 | .X86_64 => .x86_64, | ||
| 8908 | }, wip_nav.frame_format) catch |err| switch (err) { | ||
| 8909 | error.WriteFailed => return cie_nw.err.?, | ||
| 8910 | }; | ||
| 8911 | } | ||
| 8912 | const dwarf_func = dwarf_fi.get(dwarf); | ||
| 8913 | const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: { | ||
| 8914 | try fde_ni.moved(gpa, &elf.mf); | ||
| 8915 | try fde_ni.nextMoved(gpa, &elf.mf); | ||
| 8916 | break :fde_ni fde_ni; | ||
| 8917 | } else fde_ni: { | ||
| 8918 | const fde_ni = elf.addNodeAssumeCapacity(try frame_ni.addFloatingChild(gpa, &elf.mf, .{ | ||
| 8919 | .alignment = frame_align, | ||
| 8920 | .moved = true, | ||
| 8921 | .next_moved = true, | ||
| 8922 | .enable_next_moved = true, | ||
| 8923 | }), .{ .func_frame_fde = dwarf_fi }); | ||
| 8924 | dwarf_func.fde_ni = .wrap(fde_ni); | ||
| 8925 | break :fde_ni fde_ni; | ||
| 8926 | }; | ||
| 8927 | fde_ni.writer(gpa, &elf.mf, &wip_nav.fde_writer); | ||
| 8928 | |||
| 8929 | if (mod.strip) break :debug_output .{ .{ .eh_frame = wip_nav }, dwarf_func }; | ||
| 8930 | |||
| 8931 | const debug = &debug_output_buf; | ||
| 8932 | debug.pt = pt; | ||
| 8933 | debug.any_children = false; | ||
| 8934 | debug.blocks = .empty; | ||
| 8935 | dwarf_func.state = .resolved; | ||
| 8936 | |||
| 8937 | const debug_info_ni = dwarf_func.debug_info_ni.unwrap().?; | ||
| 8938 | try dwarf.decls.put(zcu.comp.gpa, src_inst, .{ | ||
| 8939 | .debug_info_ni = debug_info_ni.toOptional(), | ||
| 8940 | }); | ||
| 8941 | try debug_info_ni.moved(gpa, &elf.mf); | ||
| 8942 | try debug_info_ni.nextMoved(gpa, &elf.mf); | ||
| 8943 | debug_info_ni.writer(gpa, &elf.mf, &debug.info_writer); | ||
| 8944 | |||
| 8945 | const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: { | ||
| 8946 | const debug_line_ni = elf.addNodeAssumeCapacity( | ||
| 8947 | try unit.debug_line_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{ | ||
| 8948 | .moved = true, | ||
| 8949 | .next_moved = true, | ||
| 8950 | .enable_next_moved = true, | ||
| 8951 | }), | ||
| 8952 | .{ .func_debug_line = dwarf_fi }, | ||
| 8953 | ); | ||
| 8954 | dwarf_func.debug_line_ni = .wrap(debug_line_ni); | ||
| 8955 | break :debug_line_ni debug_line_ni; | ||
| 8956 | }; | ||
| 8957 | debug_line_ni.writer(gpa, &elf.mf, &debug.line_writer); | ||
| 8958 | |||
| 8959 | break :debug_output .{ .{ .dwarf2 = debug }, dwarf_func }; | ||
| 8960 | }; | ||
| 8961 | defer switch (debug_output) { | ||
| 8962 | .dwarf => unreachable, | ||
| 8963 | inline .eh_frame, .dwarf2 => |dwarf| dwarf.deinit(), | ||
| 8964 | .none => {}, | ||
| 8965 | }; | ||
| 8966 | switch (debug_output) { | ||
| 8967 | .dwarf => unreachable, | ||
| 8968 | .eh_frame => |wip_nav| { | ||
| 8969 | elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?); | ||
| 8970 | try wip_nav.genDebugFrameHeader(); | ||
| 8971 | }, | ||
| 8972 | .dwarf2 => |debug| { | ||
| 8973 | elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?); | ||
| 8974 | try debug.wip_nav.genDebugFrameHeader(); | ||
| 8975 | elf.resetNodeRelocs(dwarf_func.debug_line_ni.unwrap().?); | ||
| 8976 | try debug.startDebugLine(); | ||
| 8977 | elf.resetNodeRelocs(dwarf_func.debug_info_ni.unwrap().?); | ||
| 8978 | try debug.startFuncDebugInfo(); | ||
| 8979 | }, | ||
| 8980 | .none => {}, | ||
| 8981 | } | ||
| 8982 | elf.resetNodeRelocs(ni); | ||
| 7641 | codegen.emitFunction( | 8983 | codegen.emitFunction( |
| 7642 | &elf.base, | 8984 | &elf.base, |
| 7643 | pt, | 8985 | pt, |
| ... | @@ -7645,29 +8987,101 @@ fn updateFuncInner( | ... | @@ -7645,29 +8987,101 @@ fn updateFuncInner( |
| 7645 | Node.toAtom(ni), | 8987 | Node.toAtom(ni), |
| 7646 | mir, | 8988 | mir, |
| 7647 | &nw.interface, | 8989 | &nw.interface, |
| 7648 | .none, | 8990 | debug_output, |
| 7649 | ) catch |err| switch (err) { | 8991 | ) catch |err| switch (err) { |
| 7650 | error.WriteFailed => return nw.err.?, | ||
| 7651 | else => |e| return e, | 8992 | else => |e| return e, |
| 8993 | error.WriteFailed => if (nw.err) |e| return e, | ||
| 7652 | }; | 8994 | }; |
| 8995 | const func_length = nw.interface.end; | ||
| 7653 | switch (elf.symPtr(nmi.symbol(elf).index())) { | 8996 | switch (elf.symPtr(nmi.symbol(elf).index())) { |
| 7654 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 8997 | inline else => |sym| elf.targetStore(&sym.size, @intCast(func_length)), |
| 8998 | } | ||
| 8999 | switch (debug_output) { | ||
| 9000 | .dwarf => unreachable, | ||
| 9001 | .eh_frame => |wip_nav| wip_nav.finishDebugFrameFde(func_length), | ||
| 9002 | .dwarf2 => |debug| { | ||
| 9003 | try debug.finishFunc(func_length); | ||
| 9004 | const unit = debug.wip_nav.unit.get(debug.wip_nav.dwarf); | ||
| 9005 | { | ||
| 9006 | var dr_nw: MappedFile.Node.Writer = undefined; | ||
| 9007 | unit.debug_rnglists_ni.unwrap().?.writer(gpa, &elf.mf, &dr_nw); | ||
| 9008 | defer dr_nw.deinit(); | ||
| 9009 | const first_symbol_reloc = elf.symbol_relocs.items.len; | ||
| 9010 | debug.wip_nav.dwarf.genDebugRnglists( | ||
| 9011 | unit, | ||
| 9012 | &dr_nw, | ||
| 9013 | debug.wip_nav.func_si, | ||
| 9014 | func_length, | ||
| 9015 | ) catch |err| switch (err) { | ||
| 9016 | else => |e| return e, | ||
| 9017 | error.WriteFailed => return dr_nw.err.?, | ||
| 9018 | }; | ||
| 9019 | const symbol_relocs = &elf.dwarf_units[@backingInt(debug.wip_nav.unit)] | ||
| 9020 | .debug_rnglists_symbol_relocs; | ||
| 9021 | try symbol_relocs.ensureUnusedCapacity(gpa, elf.symbol_relocs.items.len - | ||
| 9022 | first_symbol_reloc); | ||
| 9023 | for (first_symbol_reloc..elf.symbol_relocs.items.len) |symbol_ri| | ||
| 9024 | symbol_relocs.putAssumeCapacityNoClobber( | ||
| 9025 | @fromBackingInt(@intCast(symbol_ri)), | ||
| 9026 | {}, | ||
| 9027 | ); | ||
| 9028 | } | ||
| 9029 | debug.wip_nav.finishDebugFrameFde(func_length); | ||
| 9030 | if (func.analysisUnordered(ip).inferred_error_set) { | ||
| 9031 | const ies = ip.getIfExists(.{ .inferred_error_set_type = func_index }).?; | ||
| 9032 | if (elf.dwarf.const_pool.getIfExists(ies)) |cpi| | ||
| 9033 | try elf.updateConstInner(pt, cpi, ies, .complete); | ||
| 9034 | } | ||
| 9035 | }, | ||
| 9036 | .none => {}, | ||
| 7655 | } | 9037 | } |
| 7656 | } | 9038 | } |
| 7657 | 9039 | ||
| 7658 | // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs. | 9040 | // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs. |
| 7659 | try elf.genPending(pt); | 9041 | try elf.genPending(pt); |
| 9042 | try elf.dwarf.const_pool.flushPending(pt, .{ .elf2 = elf }); | ||
| 7660 | } | 9043 | } |
| 7661 | 9044 | ||
| 7662 | pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void { | 9045 | pub fn updateLineNumber( |
| 7663 | const diags = &elf.base.comp.link_diags; | 9046 | elf: *Elf, |
| 7664 | elf.genLazy(pt, .{ | 9047 | _: Zcu.PerThread, |
| 7665 | .kind = .const_data, | 9048 | inst: InternPool.TrackedInst.Index, |
| 7666 | .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return), | 9049 | line: u32, |
| 7667 | }) catch |err| switch (err) { | 9050 | ) void { |
| 7668 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | 9051 | elf.dwarf.updateLineNumber(&elf.mf, inst, line); |
| 9052 | } | ||
| 9053 | |||
| 9054 | pub fn lostTracking( | ||
| 9055 | elf: *Elf, | ||
| 9056 | _: Zcu.PerThread, | ||
| 9057 | inst: InternPool.TrackedInst.Index, | ||
| 9058 | ) link.Error!void { | ||
| 9059 | const di = elf.dwarf.getDeclIfExists(inst) orelse return; | ||
| 9060 | const decl_ni = di.get(&elf.dwarf).debug_info_ni.unwrap() orelse return; | ||
| 9061 | const comp = elf.base.comp; | ||
| 9062 | var di_nw: MappedFile.Node.Writer = undefined; | ||
| 9063 | decl_ni.writer(comp.gpa, &elf.mf, &di_nw); | ||
| 9064 | defer di_nw.deinit(); | ||
| 9065 | elf.resetNodeRelocs(decl_ni); | ||
| 9066 | elf.dwarf.lostTracking(&di_nw) catch |err| switch (err) { | ||
| 7669 | else => |e| return e, | 9067 | else => |e| return e, |
| 9068 | error.WriteFailed => unreachable, | ||
| 7670 | }; | 9069 | }; |
| 9070 | decl_ni.resizeLeaf(comp.gpa, &elf.mf, di_nw.interface.end) catch |err| switch (err) { | ||
| 9071 | else => |e| return e, | ||
| 9072 | error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{ | ||
| 9073 | elf.mf.io_err.?, | ||
| 9074 | }), | ||
| 9075 | }; | ||
| 9076 | } | ||
| 9077 | |||
| 9078 | pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void { | ||
| 9079 | if (elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type)) |lmi| try elf.genLazyInner(pt, .{ | ||
| 9080 | .kind = .const_data, | ||
| 9081 | .index = @intCast(lmi), | ||
| 9082 | }); | ||
| 9083 | if (elf.dwarf.const_pool.getIfExists(.anyerror_type)) |cpi| | ||
| 9084 | try elf.updateConstInner(pt, cpi, .anyerror_type, .complete); | ||
| 7671 | } | 9085 | } |
| 7672 | 9086 | ||
| 7673 | pub fn flush( | 9087 | pub fn flush( |
| ... | @@ -7677,8 +9091,11 @@ pub fn flush( | ... | @@ -7677,8 +9091,11 @@ pub fn flush( |
| 7677 | prog_node: std.Progress.Node, | 9091 | prog_node: std.Progress.Node, |
| 7678 | ) link.Error!void { | 9092 | ) link.Error!void { |
| 7679 | elf.flushInner(arena, tid, prog_node) catch |err| switch (err) { | 9093 | elf.flushInner(arena, tid, prog_node) catch |err| switch (err) { |
| 7680 | error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 7681 | else => |e| return e, | 9094 | else => |e| return e, |
| 9095 | error.MappedFileIo => return elf.base.comp.link_diags.fail( | ||
| 9096 | "failed to write output file: {t}", | ||
| 9097 | .{elf.mf.io_err.?}, | ||
| 9098 | ), | ||
| 7682 | }; | 9099 | }; |
| 7683 | } | 9100 | } |
| 7684 | fn flushInner( | 9101 | fn flushInner( |
| ... | @@ -7694,6 +9111,8 @@ fn flushInner( | ... | @@ -7694,6 +9111,8 @@ fn flushInner( |
| 7694 | const sub_prog_node = prog_node.start("ELF Flush", 0); | 9111 | const sub_prog_node = prog_node.start("ELF Flush", 0); |
| 7695 | defer sub_prog_node.end(); | 9112 | defer sub_prog_node.end(); |
| 7696 | 9113 | ||
| 9114 | try elf.flushFiles(); | ||
| 9115 | |||
| 7697 | if (comp.config.output_mode == .Exe) { | 9116 | if (comp.config.output_mode == .Exe) { |
| 7698 | var any_undef = false; | 9117 | var any_undef = false; |
| 7699 | for (elf.globals.strong_undef.keys()) |name| { | 9118 | for (elf.globals.strong_undef.keys()) |name| { |
| ... | @@ -7708,8 +9127,13 @@ fn flushInner( | ... | @@ -7708,8 +9127,13 @@ fn flushInner( |
| 7708 | 9127 | ||
| 7709 | while (try elf.idle(tid)) {} | 9128 | while (try elf.idle(tid)) {} |
| 7710 | 9129 | ||
| 9130 | assert(elf.pending_uavs.items.len == 0); | ||
| 9131 | assert(elf.dwarf.const_pool.pending.items.len == 0); | ||
| 9132 | |||
| 7711 | // We've done the final `idle` loop, so everything is at its final place in the file. We have a | 9133 | // We've done the final `idle` loop, so everything is at its final place in the file. We have a |
| 7712 | // few more things to check and write now that addresses and offsets are finalized. | 9134 | // few more things to check and write now that addresses and offsets are finalized. |
| 9135 | elf.mf.nodes_lock.lock(); | ||
| 9136 | defer elf.mf.nodes_lock.unlock(); | ||
| 7713 | 9137 | ||
| 7714 | if (elf.overflowed_reloc_count > 0) { | 9138 | if (elf.overflowed_reloc_count > 0) { |
| 7715 | diags.addError("failed to apply {d} relocations: overflow", .{elf.overflowed_reloc_count}); | 9139 | diags.addError("failed to apply {d} relocations: overflow", .{elf.overflowed_reloc_count}); |
| ... | @@ -7753,20 +9177,19 @@ fn flushInner( | ... | @@ -7753,20 +9177,19 @@ fn flushInner( |
| 7753 | 9177 | ||
| 7754 | if (elf.options.enable_link_snapshots) | 9178 | if (elf.options.enable_link_snapshots) |
| 7755 | elf.dumpStderr(tid) catch |err| | 9179 | elf.dumpStderr(tid) catch |err| |
| 7756 | return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); | 9180 | return diags.fail("dumping link snapshot failed: {t}", .{err}); |
| 7757 | } | 9181 | } |
| 7758 | 9182 | ||
| 7759 | pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { | 9183 | pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { |
| 7760 | const comp = elf.base.comp; | 9184 | // This function is called non-deterministically, and so must not affect the layout of any nodes. |
| 7761 | const diags = &comp.link_diags; | ||
| 7762 | |||
| 7763 | elf.mf.nodes_lock.lock(); | 9185 | elf.mf.nodes_lock.lock(); |
| 7764 | defer elf.mf.nodes_lock.unlock(); | 9186 | defer elf.mf.nodes_lock.unlock(); |
| 7765 | 9187 | ||
| 9188 | const comp = elf.base.comp; | ||
| 9189 | const diags = &comp.link_diags; | ||
| 9190 | |||
| 7766 | assert(elf.pending_uavs.items.len == 0); | 9191 | assert(elf.pending_uavs.items.len == 0); |
| 7767 | for (&elf.lazy.values) |*lazy| { | 9192 | assert(elf.dwarf.const_pool.pending.items.len == 0); |
| 7768 | assert(lazy.pending_index == lazy.map.count()); | ||
| 7769 | } | ||
| 7770 | 9193 | ||
| 7771 | task: { | 9194 | task: { |
| 7772 | if (elf.input_pending_index < elf.inputs.items.len) { | 9195 | if (elf.input_pending_index < elf.inputs.items.len) { |
| ... | @@ -7775,8 +9198,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { | ... | @@ -7775,8 +9198,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { |
| 7775 | const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(ii.node(elf))); | 9198 | const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(ii.node(elf))); |
| 7776 | defer sub_prog_node.end(); | 9199 | defer sub_prog_node.end(); |
| 7777 | elf.flushInput(ii) catch |err| switch (err) { | 9200 | elf.flushInput(ii) catch |err| switch (err) { |
| 7778 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 7779 | else => |e| return e, | 9201 | else => |e| return e, |
| 9202 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 7780 | }; | 9203 | }; |
| 7781 | break :task; | 9204 | break :task; |
| 7782 | } | 9205 | } |
| ... | @@ -7786,8 +9209,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { | ... | @@ -7786,8 +9209,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { |
| 7786 | const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf))); | 9209 | const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf))); |
| 7787 | defer sub_prog_node.end(); | 9210 | defer sub_prog_node.end(); |
| 7788 | elf.flushInputSection(isi) catch |err| switch (err) { | 9211 | elf.flushInputSection(isi) catch |err| switch (err) { |
| 7789 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 7790 | else => |e| return e, | 9212 | else => |e| return e, |
| 9213 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 7791 | }; | 9214 | }; |
| 7792 | break :task; | 9215 | break :task; |
| 7793 | } | 9216 | } |
| ... | @@ -7885,18 +9308,18 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { | ... | @@ -7885,18 +9308,18 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { |
| 7885 | 9308 | ||
| 7886 | break :task; | 9309 | break :task; |
| 7887 | } | 9310 | } |
| 7888 | while (elf.mf.updates.pop()) |ni| { | 9311 | while (elf.mf.updates.pop()) |ni| : (elf.mf.update_prog_node.completeOne()) { |
| 9312 | if (ni.pendingDelete(&elf.mf)) continue; | ||
| 7889 | const clean_moved = ni.cleanMoved(&elf.mf); | 9313 | const clean_moved = ni.cleanMoved(&elf.mf); |
| 7890 | const clean_resized = ni.cleanResized(&elf.mf); | 9314 | const clean_resized = ni.cleanResized(&elf.mf); |
| 7891 | const clean_next_moved = ni.cleanNextMoved(&elf.mf); | 9315 | const clean_next_moved = ni.cleanNextMoved(&elf.mf); |
| 7892 | if (clean_moved or clean_resized or clean_next_moved) { | 9316 | if (!clean_moved and !clean_resized and !clean_next_moved) continue; |
| 7893 | const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni)); | 9317 | const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni)); |
| 7894 | defer sub_prog_node.end(); | 9318 | defer sub_prog_node.end(); |
| 7895 | if (clean_moved) try elf.flushMoved(ni); | 9319 | if (clean_moved) try elf.flushMoved(ni); |
| 7896 | if (clean_resized) try elf.flushResized(ni); | 9320 | if (clean_resized) try elf.flushResized(ni); |
| 7897 | if (clean_next_moved) try elf.flushNextMoved(ni); | 9321 | if (clean_moved or clean_resized or clean_next_moved) try elf.flushPadding(ni); |
| 7898 | break :task; | 9322 | break :task; |
| 7899 | } else elf.mf.update_prog_node.completeOne(); | ||
| 7900 | } | 9323 | } |
| 7901 | } | 9324 | } |
| 7902 | if (elf.input_sections.items.len > elf.input_section_pending_index) return true; | 9325 | if (elf.input_sections.items.len > elf.input_section_pending_index) return true; |
| ... | @@ -7915,62 +9338,119 @@ fn idleProgNode( | ... | @@ -7915,62 +9338,119 @@ fn idleProgNode( |
| 7915 | var name: [std.Progress.Node.max_name_len]u8 = undefined; | 9338 | var name: [std.Progress.Node.max_name_len]u8 = undefined; |
| 7916 | return prog_node.start(name: switch (node) { | 9339 | return prog_node.start(name: switch (node) { |
| 7917 | else => |tag| @tagName(tag), | 9340 | else => |tag| @tagName(tag), |
| 7918 | .section => |shndx| shndx.name(elf).slice(elf), | ||
| 7919 | .archive_input_member => |ii| std.mem.print(&name, "{f}{f}", .{ | 9341 | .archive_input_member => |ii| std.mem.print(&name, "{f}{f}", .{ |
| 7920 | ii.path(elf).fmtEscapeString(), | 9342 | ii.path(elf).fmtEscapeString(), |
| 7921 | fmtMemberString(ii.member(elf)), | 9343 | fmtMemberString(ii.member(elf)), |
| 7922 | }) catch &name, | 9344 | }) catch &name, |
| 9345 | .section, .section_manual_size => |shndx| shndx.name(elf).slice(elf), | ||
| 7923 | .input_section => |isi| { | 9346 | .input_section => |isi| { |
| 7924 | const ii = isi.input(elf); | 9347 | const ii = isi.input(elf); |
| 7925 | break :name std.mem.print(&name, "{f}{f} {s}", .{ | 9348 | break :name std.mem.print(&name, "{f}{f} {s}", .{ |
| 7926 | ii.path(elf).fmtEscapeString(), | 9349 | ii.path(elf).fmtEscapeString(), |
| 7927 | fmtMemberString(ii.member(elf)), | 9350 | fmtMemberString(ii.member(elf)), |
| 7928 | elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf), | 9351 | elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf), |
| 7929 | }) catch &name; | 9352 | }) catch &name; |
| 7930 | }, | 9353 | }, |
| 7931 | .nav => |nmi| { | 9354 | .nav => |nmi| { |
| 7932 | const ip = &elf.base.comp.zcu.?.intern_pool; | 9355 | const ip = &elf.base.comp.zcu.?.intern_pool; |
| 7933 | break :name ip.getNav(nmi.navIndex(elf)).fqn.toSlice(ip); | 9356 | break :name ip.getNav(nmi.nav(elf)).fqn.toSlice(ip); |
| 7934 | }, | 9357 | }, |
| 7935 | .uav => |umi| std.mem.print(&name, "{f}", .{ | 9358 | .uav => |umi| std.mem.print(&name, "{f}", .{ |
| 7936 | Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), | 9359 | Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), |
| 7937 | }) catch &name, | 9360 | }) catch &name, |
| 9361 | .debug_shared => |ss| switch (ss) { | ||
| 9362 | .debug_abbrev => "debug info abbrevs", | ||
| 9363 | .debug_str, .debug_str_offsets => "debug info strings", | ||
| 9364 | .debug_line_str => "line info strings", | ||
| 9365 | }, | ||
| 9366 | .unit_frame, | ||
| 9367 | .unit_frame_cie, | ||
| 9368 | .unit_debug_info, | ||
| 9369 | .unit_debug_info_header, | ||
| 9370 | .unit_debug_info_footer, | ||
| 9371 | .unit_debug_line, | ||
| 9372 | .unit_debug_line_header, | ||
| 9373 | .unit_debug_rnglists, | ||
| 9374 | => |ui, tag| std.mem.print(&name, "{s} info for {s}", .{ | ||
| 9375 | switch (tag) { | ||
| 9376 | else => unreachable, | ||
| 9377 | .unit_frame, .unit_frame_cie => "unwind", | ||
| 9378 | .unit_debug_info, | ||
| 9379 | .unit_debug_info_header, | ||
| 9380 | .unit_debug_info_footer, | ||
| 9381 | .unit_debug_rnglists, | ||
| 9382 | => "debug", | ||
| 9383 | .unit_debug_line, .unit_debug_line_header => "line", | ||
| 9384 | }, | ||
| 9385 | ui.mod(&elf.dwarf).fully_qualified_name, | ||
| 9386 | }) catch &name, | ||
| 9387 | .const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) { | ||
| 9388 | .generic_poison_type => "anytype", | ||
| 9389 | else => |val| std.mem.print(&name, "debug info for {f}", .{ | ||
| 9390 | Value.fromInterned(val).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), | ||
| 9391 | }) catch &name, | ||
| 9392 | }, | ||
| 9393 | .global_debug_info => |gi| { | ||
| 9394 | const ip = &elf.base.comp.zcu.?.intern_pool; | ||
| 9395 | break :name std.mem.print(&name, "debug info for {f}", .{ | ||
| 9396 | ip.getNav(gi.nav(&elf.dwarf)).fqn.fmt(ip), | ||
| 9397 | }) catch &name; | ||
| 9398 | }, | ||
| 9399 | .func_frame_fde, .func_debug_info, .func_debug_line => |fi, tag| { | ||
| 9400 | const ip = &elf.base.comp.zcu.?.intern_pool; | ||
| 9401 | break :name std.mem.print(&name, "{s} info for {f}", .{ | ||
| 9402 | switch (tag) { | ||
| 9403 | else => unreachable, | ||
| 9404 | .func_frame_fde => "unwind", | ||
| 9405 | .func_debug_info => "debug", | ||
| 9406 | .func_debug_line => "line", | ||
| 9407 | }, | ||
| 9408 | ip.getNav(fi.nav(&elf.dwarf)).fqn.fmt(ip), | ||
| 9409 | }) catch &name; | ||
| 9410 | }, | ||
| 9411 | .decl_debug_info => |di| { | ||
| 9412 | const comp = elf.base.comp; | ||
| 9413 | const zcu = comp.zcu.?; | ||
| 9414 | break :name std.mem.print(&name, "debug info for {f}", .{ | ||
| 9415 | zcu.fileByIndex(di.srcInst(&elf.dwarf).resolveFile(&zcu.intern_pool)).path.fmt(comp), | ||
| 9416 | }) catch &name; | ||
| 9417 | }, | ||
| 7938 | }, 0); | 9418 | }, 0); |
| 7939 | } | 9419 | } |
| 7940 | 9420 | ||
| 7941 | fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void { | 9421 | fn genPending(elf: *Elf, pt: Zcu.PerThread) link.Error!void { |
| 7942 | const zcu = elf.base.comp.zcu.?; | 9422 | while (elf.pending_uavs.pop()) |umi| { |
| 7943 | pending: while (true) { | 9423 | var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined; |
| 7944 | if (elf.pending_uavs.pop()) |umi| { | 9424 | const prog_name = std.mem.print(&prog_name_buf, "{f}", .{ |
| 7945 | var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined; | 9425 | Value.fromInterned(umi.uavValue(elf)).fmtValue(pt), |
| 7946 | const prog_name = std.mem.print(&prog_name_buf, "{f}", .{ | 9426 | }) catch &prog_name_buf; |
| 7947 | Value.fromInterned(umi.uavValue(elf)).fmtValue(pt), | 9427 | const prog_node = elf.const_prog_node.start(prog_name, 0); |
| 7948 | }) catch &prog_name_buf; | 9428 | defer prog_node.end(); |
| 7949 | const prog_node = elf.const_prog_node.start(prog_name, 0); | 9429 | try elf.genUav(pt, umi); |
| 7950 | defer prog_node.end(); | 9430 | } |
| 7951 | try elf.genUav(pt, umi); | 9431 | var lazy_it = elf.lazy.iterator(); |
| 7952 | continue :pending; | 9432 | while (lazy_it.next()) |lazy| while (lazy.value.pending_index < lazy.value.map.count()) { |
| 7953 | } | 9433 | try elf.genLazy(pt, .{ .kind = lazy.key, .index = lazy.value.pending_index }); |
| 7954 | var lazy_it = elf.lazy.iterator(); | 9434 | lazy.value.pending_index += 1; |
| 7955 | while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) { | 9435 | }; |
| 7956 | const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index }; | 9436 | switch (elf.base.comp.config.debug_format) { |
| 7957 | lazy.value.pending_index += 1; | 9437 | .strip => {}, |
| 7958 | const lazy_ty: Type = .fromInterned(lmr.lazySymbol(elf).ty); | 9438 | .dwarf => { |
| 7959 | var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined; | 9439 | const gpa = elf.base.comp.gpa; |
| 7960 | const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(zcu)) { | 9440 | while (true) { |
| 7961 | .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf, | 9441 | const pending = elf.dwarf.pending_decl; |
| 7962 | .error_set => switch (lmr.kind) { | 9442 | if (pending.instance_val == .none) break; |
| 7963 | .code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf, | 9443 | elf.dwarf.pending_decl = .{ .di = undefined, .instance_val = .none }; |
| 7964 | .const_data => "@errorName", | 9444 | const debug_info_ni = pending.di.get(&elf.dwarf).debug_info_ni.unwrap().?; |
| 7965 | }, | 9445 | try debug_info_ni.moved(gpa, &elf.mf); |
| 7966 | else => unreachable, | 9446 | var di_nw: MappedFile.Node.Writer = undefined; |
| 7967 | }; | 9447 | debug_info_ni.writer(gpa, &elf.mf, &di_nw); |
| 7968 | const prog_node = elf.synth_prog_node.start(prog_name, 0); | 9448 | defer di_nw.deinit(); |
| 7969 | defer prog_node.end(); | 9449 | elf.resetNodeRelocs(debug_info_ni); |
| 7970 | try elf.genLazy(pt, lmr); | 9450 | try elf.dwarf.genDecl(pt, &di_nw, pending.instance_val); |
| 7971 | continue :pending; | 9451 | } |
| 7972 | }; | 9452 | }, |
| 7973 | break; | 9453 | .code_view => unreachable, |
| 7974 | } | 9454 | } |
| 7975 | } | 9455 | } |
| 7976 | 9456 | ||
| ... | @@ -7978,17 +9458,17 @@ fn genUav( | ... | @@ -7978,17 +9458,17 @@ fn genUav( |
| 7978 | elf: *Elf, | 9458 | elf: *Elf, |
| 7979 | pt: Zcu.PerThread, | 9459 | pt: Zcu.PerThread, |
| 7980 | umi: Node.UavMapIndex, | 9460 | umi: Node.UavMapIndex, |
| 7981 | ) Error!void { | 9461 | ) link.Error!void { |
| 7982 | const comp = elf.base.comp; | 9462 | const comp = elf.base.comp; |
| 7983 | const gpa = comp.gpa; | 9463 | const gpa = comp.gpa; |
| 7984 | 9464 | ||
| 7985 | const uav_val = umi.uavValue(elf); | 9465 | const uav_val = umi.uavValue(elf); |
| 7986 | const ni = umi.symbol(elf).index().ptr(elf).node.unwrap().?; | 9466 | const ni = umi.symbol(elf).index().ptr(elf).node.unwrap().?; |
| 7987 | elf.resetNodeRelocs(ni); | ||
| 7988 | 9467 | ||
| 7989 | var nw: MappedFile.Node.Writer = undefined; | 9468 | var nw: MappedFile.Node.Writer = undefined; |
| 7990 | ni.writer(&elf.mf, gpa, &nw); | 9469 | ni.writer(gpa, &elf.mf, &nw); |
| 7991 | defer nw.deinit(); | 9470 | defer nw.deinit(); |
| 9471 | elf.resetNodeRelocs(ni); | ||
| 7992 | codegen.generateSymbol( | 9472 | codegen.generateSymbol( |
| 7993 | &elf.base, | 9473 | &elf.base, |
| 7994 | pt, | 9474 | pt, |
| ... | @@ -7996,8 +9476,11 @@ fn genUav( | ... | @@ -7996,8 +9476,11 @@ fn genUav( |
| 7996 | &nw.interface, | 9476 | &nw.interface, |
| 7997 | .{ .atom_index = Node.toAtom(ni) }, | 9477 | .{ .atom_index = Node.toAtom(ni) }, |
| 7998 | ) catch |err| switch (err) { | 9478 | ) catch |err| switch (err) { |
| 7999 | error.WriteFailed => return nw.err.?, | ||
| 8000 | else => |e| return e, | 9479 | else => |e| return e, |
| 9480 | error.WriteFailed => switch (nw.err.?) { | ||
| 9481 | else => |e| return e, | ||
| 9482 | error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | ||
| 9483 | }, | ||
| 8001 | }; | 9484 | }; |
| 8002 | switch (elf.symPtr(umi.symbol(elf).index())) { | 9485 | switch (elf.symPtr(umi.symbol(elf).index())) { |
| 8003 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 9486 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), |
| ... | @@ -8007,13 +9490,29 @@ fn genUav( | ... | @@ -8007,13 +9490,29 @@ fn genUav( |
| 8007 | assert(ni.hasMoved(&elf.mf)); | 9490 | assert(ni.hasMoved(&elf.mf)); |
| 8008 | } | 9491 | } |
| 8009 | 9492 | ||
| 8010 | fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { | 9493 | fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) link.Error!void { |
| 9494 | const lazy = lmr.lazySymbol(elf); | ||
| 9495 | if (lazy.ty == .anyerror_type) return; | ||
| 9496 | const lazy_ty: Type = .fromInterned(lazy.ty); | ||
| 9497 | var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined; | ||
| 9498 | const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(pt.zcu)) { | ||
| 9499 | .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf, | ||
| 9500 | .error_set => switch (lmr.kind) { | ||
| 9501 | .code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf, | ||
| 9502 | .const_data => "@errorName(anyerror)", | ||
| 9503 | }, | ||
| 9504 | else => unreachable, | ||
| 9505 | }; | ||
| 9506 | const prog_node = elf.base.comp.link_prog_node.start(prog_name, 0); | ||
| 9507 | defer prog_node.end(); | ||
| 9508 | try elf.genLazyInner(pt, lmr); | ||
| 9509 | } | ||
| 9510 | fn genLazyInner(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) link.Error!void { | ||
| 8011 | const zcu = pt.zcu; | 9511 | const zcu = pt.zcu; |
| 8012 | const gpa = zcu.gpa; | 9512 | const gpa = zcu.gpa; |
| 8013 | 9513 | ||
| 8014 | const lazy = lmr.lazySymbol(elf); | 9514 | const lazy = lmr.lazySymbol(elf); |
| 8015 | const ni = lmr.symbol(elf).index().ptr(elf).node.unwrap().?; | 9515 | const ni = lmr.symbol(elf).index().ptr(elf).node.unwrap().?; |
| 8016 | elf.resetNodeRelocs(ni); | ||
| 8017 | 9516 | ||
| 8018 | // Ensure the lazy node is marked as moved so that once we're done, `flushMoved` will eventually | 9517 | // Ensure the lazy node is marked as moved so that once we're done, `flushMoved` will eventually |
| 8019 | // be called to apply the lazy node's new relocations. | 9518 | // be called to apply the lazy node's new relocations. |
| ... | @@ -8021,8 +9520,9 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { | ... | @@ -8021,8 +9520,9 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { |
| 8021 | 9520 | ||
| 8022 | var required_alignment: InternPool.Alignment = .none; | 9521 | var required_alignment: InternPool.Alignment = .none; |
| 8023 | var nw: MappedFile.Node.Writer = undefined; | 9522 | var nw: MappedFile.Node.Writer = undefined; |
| 8024 | ni.writer(&elf.mf, gpa, &nw); | 9523 | ni.writer(gpa, &elf.mf, &nw); |
| 8025 | defer nw.deinit(); | 9524 | defer nw.deinit(); |
| 9525 | elf.resetNodeRelocs(ni); | ||
| 8026 | codegen.generateLazySymbol( | 9526 | codegen.generateLazySymbol( |
| 8027 | &elf.base, | 9527 | &elf.base, |
| 8028 | pt, | 9528 | pt, |
| ... | @@ -8032,8 +9532,14 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { | ... | @@ -8032,8 +9532,14 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { |
| 8032 | .none, | 9532 | .none, |
| 8033 | .{ .atom_index = Node.toAtom(ni) }, | 9533 | .{ .atom_index = Node.toAtom(ni) }, |
| 8034 | ) catch |err| switch (err) { | 9534 | ) catch |err| switch (err) { |
| 8035 | error.WriteFailed => return nw.err.?, | ||
| 8036 | else => |e| return e, | 9535 | else => |e| return e, |
| 9536 | error.WriteFailed => return switch (nw.err.?) { | ||
| 9537 | else => |e| return e, | ||
| 9538 | error.MappedFileIo => return elf.base.comp.link_diags.fail( | ||
| 9539 | "failed to write output file: {t}", | ||
| 9540 | .{elf.mf.io_err.?}, | ||
| 9541 | ), | ||
| 9542 | }, | ||
| 8037 | }; | 9543 | }; |
| 8038 | switch (elf.symPtr(lmr.symbol(elf).index())) { | 9544 | switch (elf.symPtr(lmr.symbol(elf).index())) { |
| 8039 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 9545 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), |
| ... | @@ -8104,18 +9610,18 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { | ... | @@ -8104,18 +9610,18 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { |
| 8104 | fr.seekTo(file_loc.offset) catch |err| switch (err) { | 9610 | fr.seekTo(file_loc.offset) catch |err| switch (err) { |
| 8105 | error.Canceled => |e| return e, | 9611 | error.Canceled => |e| return e, |
| 8106 | else => |e| return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{ | 9612 | else => |e| return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{ |
| 8107 | elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf), | 9613 | elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf), |
| 8108 | path.fmtEscapeString(), | 9614 | path.fmtEscapeString(), |
| 8109 | fmtMemberString(ii.member(elf)), | 9615 | fmtMemberString(ii.member(elf)), |
| 8110 | e, | 9616 | e, |
| 8111 | }), | 9617 | }), |
| 8112 | }; | 9618 | }; |
| 8113 | var nw: MappedFile.Node.Writer = undefined; | 9619 | var nw: MappedFile.Node.Writer = undefined; |
| 8114 | isi.node(elf).writer(&elf.mf, gpa, &nw); | 9620 | isi.node(elf).writer(gpa, &elf.mf, &nw); |
| 8115 | defer nw.deinit(); | 9621 | defer nw.deinit(); |
| 8116 | const n_bytes = nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) catch |err| switch (err) { | 9622 | const n_bytes = nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) catch |err| switch (err) { |
| 8117 | error.ReadFailed => return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{ | 9623 | error.ReadFailed => return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{ |
| 8118 | elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf), | 9624 | elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf), |
| 8119 | path.fmtEscapeString(), | 9625 | path.fmtEscapeString(), |
| 8120 | fmtMemberString(ii.member(elf)), | 9626 | fmtMemberString(ii.member(elf)), |
| 8121 | fr.err orelse (fr.seek_err orelse fr.size_err.?), | 9627 | fr.err orelse (fr.seek_err orelse fr.size_err.?), |
| ... | @@ -8123,7 +9629,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { | ... | @@ -8123,7 +9629,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { |
| 8123 | error.WriteFailed => return nw.err.?, | 9629 | error.WriteFailed => return nw.err.?, |
| 8124 | }; | 9630 | }; |
| 8125 | if (n_bytes != file_loc.size) return diags.fail("failed to read input section '{s}' from \"{f}{f}\": unexpected eof", .{ | 9631 | if (n_bytes != file_loc.size) return diags.fail("failed to read input section '{s}' from \"{f}{f}\": unexpected eof", .{ |
| 8126 | elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf), | 9632 | elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf), |
| 8127 | path.fmtEscapeString(), | 9633 | path.fmtEscapeString(), |
| 8128 | fmtMemberString(ii.member(elf)), | 9634 | fmtMemberString(ii.member(elf)), |
| 8129 | }); | 9635 | }); |
| ... | @@ -8133,7 +9639,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { | ... | @@ -8133,7 +9639,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { |
| 8133 | } | 9639 | } |
| 8134 | 9640 | ||
| 8135 | fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { | 9641 | fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 8136 | const elf_offset = elf.getNodeElfOffset(ni); | 9642 | const elf_offset = elf.computeNodeElfOffset(ni); |
| 8137 | switch (elf.getNode(ni)) { | 9643 | switch (elf.getNode(ni)) { |
| 8138 | else => unreachable, | 9644 | else => unreachable, |
| 8139 | .ehdr => assert(elf_offset == 0), | 9645 | .ehdr => assert(elf_offset == 0), |
| ... | @@ -8155,7 +9661,7 @@ fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -8155,7 +9661,7 @@ fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 8155 | elf.flushElfOffset(child_ni); | 9661 | elf.flushElfOffset(child_ni); |
| 8156 | } | 9662 | } |
| 8157 | }, | 9663 | }, |
| 8158 | .section => |shndx| switch (elf.shdrPtr(shndx)) { | 9664 | .section, .section_manual_size => |shndx| switch (elf.shdrPtr(shndx)) { |
| 8159 | inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)), | 9665 | inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)), |
| 8160 | }, | 9666 | }, |
| 8161 | } | 9667 | } |
| ... | @@ -8166,17 +9672,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8166,17 +9672,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8166 | defer trace.end(); | 9672 | defer trace.end(); |
| 8167 | 9673 | ||
| 8168 | switch (elf.getNode(ni)) { | 9674 | switch (elf.getNode(ni)) { |
| 8169 | .archive => unreachable, | 9675 | .deleted => unreachable, |
| 8170 | .archive_header => unreachable, | 9676 | .archive, .archive_header => unreachable, |
| 8171 | 9677 | .archive_input_member, .archive_elf_member_header, .elf => { | |
| 8172 | .archive_input_member, | ||
| 8173 | .archive_elf_member_header, | ||
| 8174 | .elf, | ||
| 8175 | => { | ||
| 8176 | assert(elf.archive != null); | 9678 | assert(elf.archive != null); |
| 8177 | return; | 9679 | return; |
| 8178 | }, | 9680 | }, |
| 8179 | |||
| 8180 | .ehdr, .shdr => elf.flushElfOffset(ni), | 9681 | .ehdr, .shdr => elf.flushElfOffset(ni), |
| 8181 | .segment => |phndx| { | 9682 | .segment => |phndx| { |
| 8182 | elf.flushElfOffset(ni); | 9683 | elf.flushElfOffset(ni); |
| ... | @@ -8194,6 +9695,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8194,6 +9695,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8194 | .INTERP, | 9695 | .INTERP, |
| 8195 | .PHDR, | 9696 | .PHDR, |
| 8196 | .TLS, | 9697 | .TLS, |
| 9698 | .GNU_EH_FRAME, | ||
| 8197 | .GNU_RELRO, | 9699 | .GNU_RELRO, |
| 8198 | => { | 9700 | => { |
| 8199 | const new_vaddr = elf.computeNodeVAddr(ni); | 9701 | const new_vaddr = elf.computeNodeVAddr(ni); |
| ... | @@ -8204,14 +9706,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8204,14 +9706,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8204 | }, | 9706 | }, |
| 8205 | } | 9707 | } |
| 8206 | }, | 9708 | }, |
| 8207 | .section => |shndx| { | 9709 | .section, .section_manual_size => |shndx| { |
| 8208 | elf.flushElfOffset(ni); | 9710 | elf.flushElfOffset(ni); |
| 8209 | const addr = elf.computeNodeVAddr(ni); | 9711 | const addr = elf.computeNodeVAddr(ni); |
| 8210 | const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) { | 9712 | const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) { |
| 8211 | inline else => |shdr| .{ | 9713 | inline else => |shdr| .{ elf.targetLoad(&shdr.addr), elf.targetLoad(&shdr.flags).shf }, |
| 8212 | elf.targetLoad(&shdr.addr), | ||
| 8213 | elf.targetLoad(&shdr.flags).shf, | ||
| 8214 | }, | ||
| 8215 | }; | 9714 | }; |
| 8216 | 9715 | ||
| 8217 | if (flags.ALLOC) { | 9716 | if (flags.ALLOC) { |
| ... | @@ -8225,10 +9724,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8225,10 +9724,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8225 | var name = first_name; | 9724 | var name = first_name; |
| 8226 | while (name != .empty) { | 9725 | while (name != .empty) { |
| 8227 | const old_sym_addr = Symbol.Id.global(name).value(elf); | 9726 | const old_sym_addr = Symbol.Id.global(name).value(elf); |
| 8228 | Symbol.Id.global(name).flushMoved( | 9727 | Symbol.Id.global(name).flushMoved(elf, old_sym_addr - old_addr + addr); |
| 8229 | elf, | ||
| 8230 | old_sym_addr - old_addr + addr, | ||
| 8231 | ); | ||
| 8232 | name = elf.globalByName(name).?.next_in_node; | 9728 | name = elf.globalByName(name).?.next_in_node; |
| 8233 | } | 9729 | } |
| 8234 | } | 9730 | } |
| ... | @@ -8246,12 +9742,18 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8246,12 +9742,18 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8246 | reloc.apply(elf); | 9742 | reloc.apply(elf); |
| 8247 | } | 9743 | } |
| 8248 | } else if (shndx == elf.shndx.plt) { | 9744 | } else if (shndx == elf.shndx.plt) { |
| 8249 | elf.flushMovedNodeRelocs(ni, addr, elf.plt_first_symbol_reloc, .none); | 9745 | elf.flushMovedNodeRelocs(ni, addr, .{ |
| 9746 | .first_symbol_reloc = elf.plt_first_symbol_reloc, | ||
| 9747 | }); | ||
| 8250 | elf.flushMovedPltSection(.plt, old_addr, addr); | 9748 | elf.flushMovedPltSection(.plt, old_addr, addr); |
| 8251 | } else if (shndx == elf.shndx.got_plt) { | 9749 | } else if (shndx == elf.shndx.got_plt) { |
| 8252 | elf.flushMovedPltSection(.got_plt, old_addr, addr); | 9750 | elf.flushMovedPltSection(.got_plt, old_addr, addr); |
| 8253 | } else if (shndx == elf.shndx.plt_sec) { | 9751 | } else if (shndx == elf.shndx.plt_sec) { |
| 8254 | elf.flushMovedPltSection(.plt_sec, old_addr, addr); | 9752 | elf.flushMovedPltSection(.plt_sec, old_addr, addr); |
| 9753 | } else if (shndx == elf.shndx.eh_frame_hdr) { | ||
| 9754 | elf.flushMovedNodeRelocs(ni, addr, .{ | ||
| 9755 | .first_symbol_reloc = elf.eh_frame_hdr_first_symbol_reloc, | ||
| 9756 | }); | ||
| 8255 | } | 9757 | } |
| 8256 | }, | 9758 | }, |
| 8257 | .input_section => |isi| { | 9759 | .input_section => |isi| { |
| ... | @@ -8298,12 +9800,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8298,12 +9800,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8298 | } | 9800 | } |
| 8299 | } | 9801 | } |
| 8300 | 9802 | ||
| 8301 | elf.flushMovedNodeRelocs( | 9803 | elf.flushMovedNodeRelocs(ni, new_section_addr, .{ |
| 8302 | ni, | 9804 | .first_symbol_reloc = isi.ptrConst(elf).first_symbol_reloc, |
| 8303 | new_section_addr, | 9805 | .first_got_reloc = isi.ptrConst(elf).first_got_reloc, |
| 8304 | isi.ptrConst(elf).first_symbol_reloc, | 9806 | }); |
| 8305 | isi.ptrConst(elf).first_got_reloc, | ||
| 8306 | ); | ||
| 8307 | }, | 9807 | }, |
| 8308 | .copied_global => |global_name| { | 9808 | .copied_global => |global_name| { |
| 8309 | const copied_global = elf.copied_globals.getPtr(global_name) orelse { | 9809 | const copied_global = elf.copied_globals.getPtr(global_name) orelse { |
| ... | @@ -8318,7 +9818,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8318,7 +9818,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8318 | 9818 | ||
| 8319 | Symbol.Id.global(global_name).flushMoved(elf, new_addr); | 9819 | Symbol.Id.global(global_name).flushMoved(elf, new_addr); |
| 8320 | }, | 9820 | }, |
| 8321 | inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| { | 9821 | inline .nav, .uav, .lazy_code, .lazy_const_data => |mi, tag| { |
| 8322 | const new_addr = elf.computeNodeVAddr(ni); | 9822 | const new_addr = elf.computeNodeVAddr(ni); |
| 8323 | Symbol.Id.local(mi.symbol(elf)).flushMoved(elf, new_addr); | 9823 | Symbol.Id.local(mi.symbol(elf)).flushMoved(elf, new_addr); |
| 8324 | if (elf.node_global_symbols.get(ni)) |first_name| { | 9824 | if (elf.node_global_symbols.get(ni)) |first_name| { |
| ... | @@ -8329,12 +9829,173 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8329,12 +9829,173 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8329 | name = elf.globalByName(name).?.next_in_node; | 9829 | name = elf.globalByName(name).?.next_in_node; |
| 8330 | } | 9830 | } |
| 8331 | } | 9831 | } |
| 8332 | elf.flushMovedNodeRelocs( | 9832 | elf.flushMovedNodeRelocs(ni, new_addr, .{ |
| 8333 | ni, | 9833 | .first_symbol_reloc = mi.firstSymbolReloc(elf), |
| 8334 | new_addr, | 9834 | .skip_symbol_relocs = switch (tag) { |
| 8335 | mi.firstSymbolReloc(elf), | 9835 | else => comptime unreachable, |
| 8336 | mi.firstGotReloc(elf), | 9836 | .nav => if (elf.dwarf.getFuncIfExists(mi.nav(elf))) |dwarf_fi| |
| 8337 | ); | 9837 | dwarf_fi.get(&elf.dwarf).debug_info_ni |
| 9838 | else | ||
| 9839 | .none, | ||
| 9840 | .uav, .lazy_code, .lazy_const_data => .none, | ||
| 9841 | }, | ||
| 9842 | .first_got_reloc = mi.firstGotReloc(elf), | ||
| 9843 | }); | ||
| 9844 | }, | ||
| 9845 | .debug_shared => |ss| { | ||
| 9846 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9847 | var target_ri = elf.dwarf_shared.getPtr(ss).first_target_reloc; | ||
| 9848 | while (target_ri != .none) { | ||
| 9849 | const target_reloc = target_ri.get(elf); | ||
| 9850 | assert(target_reloc.target == ni); | ||
| 9851 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9852 | target_ri = target_reloc.next; | ||
| 9853 | } | ||
| 9854 | }, | ||
| 9855 | .eh_frame_footer, .unit_padding, .unit_frame, .unit_debug_info, .unit_debug_line => {}, | ||
| 9856 | .unit_frame_cie => |ui| { | ||
| 9857 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9858 | var target_ri = elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc; | ||
| 9859 | while (target_ri != .none) { | ||
| 9860 | const target_reloc = target_ri.get(elf); | ||
| 9861 | assert(target_reloc.target == ni); | ||
| 9862 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9863 | target_ri = target_reloc.next; | ||
| 9864 | } | ||
| 9865 | }, | ||
| 9866 | .unit_debug_info_header => |ui| { | ||
| 9867 | const dwarf_unit = &elf.dwarf_units[@backingInt(ui)]; | ||
| 9868 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9869 | var target_ri = dwarf_unit.debug_info_header_first_target_reloc; | ||
| 9870 | while (target_ri != .none) { | ||
| 9871 | const target_reloc = target_ri.get(elf); | ||
| 9872 | assert(target_reloc.target == ni); | ||
| 9873 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9874 | target_ri = target_reloc.next; | ||
| 9875 | } | ||
| 9876 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9877 | .first_node_reloc = dwarf_unit.debug_info_header_first_node_reloc, | ||
| 9878 | }); | ||
| 9879 | }, | ||
| 9880 | .unit_debug_info_footer => {}, | ||
| 9881 | .unit_debug_line_header => |ui| { | ||
| 9882 | const dwarf_unit = &elf.dwarf_units[@backingInt(ui)]; | ||
| 9883 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9884 | var target_ri = dwarf_unit.debug_line_header_first_target_reloc; | ||
| 9885 | while (target_ri != .none) { | ||
| 9886 | const target_reloc = target_ri.get(elf); | ||
| 9887 | assert(target_reloc.target == ni); | ||
| 9888 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9889 | target_ri = target_reloc.next; | ||
| 9890 | } | ||
| 9891 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9892 | .first_node_reloc = dwarf_unit.debug_line_header_first_node_reloc, | ||
| 9893 | }); | ||
| 9894 | }, | ||
| 9895 | .unit_debug_rnglists => |ui| { | ||
| 9896 | const dwarf_unit = &elf.dwarf_units[@backingInt(ui)]; | ||
| 9897 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9898 | var target_ri = dwarf_unit.debug_rnglists_first_target_reloc; | ||
| 9899 | while (target_ri != .none) { | ||
| 9900 | const target_reloc = target_ri.get(elf); | ||
| 9901 | assert(target_reloc.target == ni); | ||
| 9902 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9903 | target_ri = target_reloc.next; | ||
| 9904 | } | ||
| 9905 | const node_vaddr = elf.computeNodeVAddr(ni); | ||
| 9906 | for (dwarf_unit.debug_rnglists_symbol_relocs.keys()) |symbol_ri| { | ||
| 9907 | const symbol_reloc = symbol_ri.get(elf); | ||
| 9908 | assert(symbol_reloc.node.unwrap().? == ni); | ||
| 9909 | symbol_reloc.flushMovedNode(elf, node_vaddr); | ||
| 9910 | } | ||
| 9911 | }, | ||
| 9912 | .const_debug_info => |cpi| { | ||
| 9913 | const dwarf_const = &elf.dwarf_consts.get(cpi).?; | ||
| 9914 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9915 | var target_ri = dwarf_const.debug_info_first_target_reloc; | ||
| 9916 | while (target_ri != .none) { | ||
| 9917 | const target_reloc = target_ri.get(elf); | ||
| 9918 | assert(target_reloc.target == ni); | ||
| 9919 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9920 | target_ri = target_reloc.next; | ||
| 9921 | } | ||
| 9922 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9923 | .first_symbol_reloc = dwarf_const.debug_info_first_symbol_reloc, | ||
| 9924 | .first_node_reloc = dwarf_const.debug_info_first_node_reloc, | ||
| 9925 | }); | ||
| 9926 | }, | ||
| 9927 | .global_debug_info => |gi| { | ||
| 9928 | const dwarf_global = &elf.dwarf_globals.items[@backingInt(gi)]; | ||
| 9929 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9930 | var target_ri = dwarf_global.debug_info_first_target_reloc; | ||
| 9931 | while (target_ri != .none) { | ||
| 9932 | const target_reloc = target_ri.get(elf); | ||
| 9933 | assert(target_reloc.target == ni); | ||
| 9934 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9935 | target_ri = target_reloc.next; | ||
| 9936 | } | ||
| 9937 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9938 | .first_symbol_reloc = dwarf_global.debug_info_first_symbol_reloc, | ||
| 9939 | .first_node_reloc = dwarf_global.debug_info_first_node_reloc, | ||
| 9940 | }); | ||
| 9941 | }, | ||
| 9942 | .func_frame_fde => |fi| { | ||
| 9943 | const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)]; | ||
| 9944 | const zcu = elf.base.comp.zcu.?; | ||
| 9945 | const mod = zcu.navFileScope(fi.nav(&elf.dwarf)).mod.?; | ||
| 9946 | switch (mod.unwind_tables) { | ||
| 9947 | .none => {}, | ||
| 9948 | .sync, .async => { | ||
| 9949 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); | ||
| 9950 | elf.dwarf.updateEhFrameFde(ni.slice(&elf.mf), offset); | ||
| 9951 | }, | ||
| 9952 | } | ||
| 9953 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9954 | .first_symbol_reloc = dwarf_func.frame_fde_first_symbol_reloc, | ||
| 9955 | .first_node_reloc = dwarf_func.frame_fde_first_node_reloc, | ||
| 9956 | }); | ||
| 9957 | }, | ||
| 9958 | .func_debug_info => |fi| { | ||
| 9959 | const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)]; | ||
| 9960 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9961 | var target_ri = dwarf_func.debug_info_first_target_reloc; | ||
| 9962 | while (target_ri != .none) { | ||
| 9963 | const target_reloc = target_ri.get(elf); | ||
| 9964 | assert(target_reloc.target == ni); | ||
| 9965 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9966 | target_ri = target_reloc.next; | ||
| 9967 | } | ||
| 9968 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9969 | .first_symbol_reloc = dwarf_func.debug_info_first_symbol_reloc, | ||
| 9970 | .skip_symbol_relocs = if (elf.navs.getPtr(fi.nav(&elf.dwarf))) |nav| | ||
| 9971 | nav.lsi.index().ptr(elf).node | ||
| 9972 | else | ||
| 9973 | .none, | ||
| 9974 | .first_node_reloc = dwarf_func.debug_info_first_node_reloc, | ||
| 9975 | .skip_node_relocs = fi.get(&elf.dwarf).debug_line_ni, | ||
| 9976 | }); | ||
| 9977 | }, | ||
| 9978 | .func_debug_line => |fi| { | ||
| 9979 | const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)]; | ||
| 9980 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9981 | .first_symbol_reloc = dwarf_func.debug_line_first_symbol_reloc, | ||
| 9982 | .first_node_reloc = dwarf_func.debug_line_first_node_reloc, | ||
| 9983 | .skip_node_relocs = fi.get(&elf.dwarf).debug_info_ni, | ||
| 9984 | }); | ||
| 9985 | }, | ||
| 9986 | .decl_debug_info => |di| { | ||
| 9987 | const dwarf_decl = &elf.dwarf_decls.get(di).?; | ||
| 9988 | const target_section_offset = elf.computeNodeSectionOffset(ni); | ||
| 9989 | var target_ri = dwarf_decl.debug_info_first_target_reloc; | ||
| 9990 | while (target_ri != .none) { | ||
| 9991 | const target_reloc = target_ri.get(elf); | ||
| 9992 | assert(target_reloc.target == ni); | ||
| 9993 | target_reloc.flushMovedTarget(elf, target_section_offset); | ||
| 9994 | target_ri = target_reloc.next; | ||
| 9995 | } | ||
| 9996 | elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{ | ||
| 9997 | .first_node_reloc = dwarf_decl.debug_info_first_node_reloc, | ||
| 9998 | }); | ||
| 8338 | }, | 9999 | }, |
| 8339 | } | 10000 | } |
| 8340 | try ni.childrenMoved(elf.base.comp.gpa, &elf.mf); | 10001 | try ni.childrenMoved(elf.base.comp.gpa, &elf.mf); |
| ... | @@ -8496,6 +10157,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -8496,6 +10157,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 8496 | 10157 | ||
| 8497 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); | 10158 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); |
| 8498 | switch (elf.getNode(ni)) { | 10159 | switch (elf.getNode(ni)) { |
| 10160 | .deleted => unreachable, | ||
| 8499 | .archive, .archive_header => {}, | 10161 | .archive, .archive_header => {}, |
| 8500 | .archive_input_member => unreachable, | 10162 | .archive_input_member => unreachable, |
| 8501 | .archive_elf_member_header => unreachable, | 10163 | .archive_elf_member_header => unreachable, |
| ... | @@ -8523,7 +10185,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -8523,7 +10185,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 8523 | elf.targetStore(&ph.type, if (size > 0) .LOAD else .NULL); | 10185 | elf.targetStore(&ph.type, if (size > 0) .LOAD else .NULL); |
| 8524 | try elf.allocateSegmentLoadAddress(phndx); | 10186 | try elf.allocateSegmentLoadAddress(phndx); |
| 8525 | }, | 10187 | }, |
| 8526 | .DYNAMIC, .INTERP, .PHDR, std.elf.PT.GNU_RELRO => { | 10188 | .DYNAMIC, .INTERP, .PHDR, .GNU_EH_FRAME, .GNU_RELRO => { |
| 8527 | elf.targetStore(&ph.memsz, @intCast(size)); | 10189 | elf.targetStore(&ph.memsz, @intCast(size)); |
| 8528 | }, | 10190 | }, |
| 8529 | .TLS => { | 10191 | .TLS => { |
| ... | @@ -8558,39 +10220,47 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -8558,39 +10220,47 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 8558 | inline else => |shdr| { | 10220 | inline else => |shdr| { |
| 8559 | switch (elf.targetLoad(&shdr.type)) { | 10221 | switch (elf.targetLoad(&shdr.type)) { |
| 8560 | else => unreachable, | 10222 | else => unreachable, |
| 8561 | |||
| 8562 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), | 10223 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), |
| 8563 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), | 10224 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), |
| 8564 | 10225 | .X86_64_UNWIND => {}, | |
| 8565 | .INIT_ARRAY, | ||
| 8566 | .FINI_ARRAY, | ||
| 8567 | .PREINIT_ARRAY, | ||
| 8568 | .STRTAB, | ||
| 8569 | .SYMTAB, | ||
| 8570 | .DYNAMIC, | ||
| 8571 | .REL, | ||
| 8572 | .RELA, | ||
| 8573 | .DYNSYM, | ||
| 8574 | .HASH, | ||
| 8575 | => return, | ||
| 8576 | } | ||
| 8577 | if (shndx != elf.shndx.plt and | ||
| 8578 | shndx != elf.shndx.got and | ||
| 8579 | shndx != elf.shndx.got_plt) | ||
| 8580 | { | ||
| 8581 | elf.targetStore(&shdr.size, @intCast(size)); | ||
| 8582 | } | 10226 | } |
| 10227 | elf.targetStore(&shdr.size, @intCast(size)); | ||
| 8583 | }, | 10228 | }, |
| 8584 | }, | 10229 | }, |
| 8585 | .input_section, .copied_global, .nav, .uav, .lazy_code, .lazy_const_data => {}, | 10230 | .section_manual_size, |
| 10231 | .input_section, | ||
| 10232 | .copied_global, | ||
| 10233 | .nav, | ||
| 10234 | .uav, | ||
| 10235 | .lazy_code, | ||
| 10236 | .lazy_const_data, | ||
| 10237 | .debug_shared, | ||
| 10238 | .eh_frame_footer, | ||
| 10239 | .unit_padding, | ||
| 10240 | .unit_frame, | ||
| 10241 | .unit_frame_cie, | ||
| 10242 | .unit_debug_info, | ||
| 10243 | .unit_debug_info_header, | ||
| 10244 | .unit_debug_info_footer, | ||
| 10245 | .unit_debug_line, | ||
| 10246 | .unit_debug_line_header, | ||
| 10247 | .unit_debug_rnglists, | ||
| 10248 | .const_debug_info, | ||
| 10249 | .global_debug_info, | ||
| 10250 | .func_frame_fde, | ||
| 10251 | .func_debug_info, | ||
| 10252 | .func_debug_line, | ||
| 10253 | .decl_debug_info, | ||
| 10254 | => {}, | ||
| 8586 | } | 10255 | } |
| 8587 | } | 10256 | } |
| 8588 | 10257 | ||
| 8589 | fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { | 10258 | fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 8590 | const trace = tracy.trace(@src()); | 10259 | const trace = tracy.trace(@src()); |
| 8591 | defer trace.end(); | 10260 | defer trace.end(); |
| 8592 | 10261 | ||
| 8593 | switch (elf.getNode(ni)) { | 10262 | switch (elf.getNode(ni)) { |
| 10263 | .deleted => unreachable, | ||
| 8594 | .archive, | 10264 | .archive, |
| 8595 | .archive_input_member, | 10265 | .archive_input_member, |
| 8596 | .archive_elf_member_header, | 10266 | .archive_elf_member_header, |
| ... | @@ -8599,13 +10269,17 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! | ... | @@ -8599,13 +10269,17 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! |
| 8599 | .shdr, | 10269 | .shdr, |
| 8600 | .segment, | 10270 | .segment, |
| 8601 | .section, | 10271 | .section, |
| 10272 | .section_manual_size, | ||
| 8602 | .input_section, | 10273 | .input_section, |
| 8603 | .copied_global, | 10274 | .copied_global, |
| 8604 | .nav, | 10275 | .nav, |
| 8605 | .uav, | 10276 | .uav, |
| 8606 | .lazy_code, | 10277 | .lazy_code, |
| 8607 | .lazy_const_data, | 10278 | .lazy_const_data, |
| 8608 | => unreachable, | 10279 | .debug_shared, |
| 10280 | .eh_frame_footer, | ||
| 10281 | .unit_debug_info_footer, | ||
| 10282 | => {}, | ||
| 8609 | 10283 | ||
| 8610 | .archive_header => { | 10284 | .archive_header => { |
| 8611 | const archive = &elf.archive.?; | 10285 | const archive = &elf.archive.?; |
| ... | @@ -8633,6 +10307,190 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! | ... | @@ -8633,6 +10307,190 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! |
| 8633 | error.NoSpaceLeft => archive.strtab_member_too_big = true, | 10307 | error.NoSpaceLeft => archive.strtab_member_too_big = true, |
| 8634 | } | 10308 | } |
| 8635 | }, | 10309 | }, |
| 10310 | .unit_padding, | ||
| 10311 | .unit_frame_cie, | ||
| 10312 | .unit_debug_info_header, | ||
| 10313 | .unit_debug_line_header, | ||
| 10314 | .unit_debug_rnglists, | ||
| 10315 | .const_debug_info, | ||
| 10316 | .global_debug_info, | ||
| 10317 | .func_frame_fde, | ||
| 10318 | .func_debug_info, | ||
| 10319 | .func_debug_line, | ||
| 10320 | .decl_debug_info, | ||
| 10321 | => |_, tag| { | ||
| 10322 | const offset, const size = ni.location(&elf.mf).resolve(&elf.mf); | ||
| 10323 | const parent_ni = ni.parent(&elf.mf).unwrap().?; | ||
| 10324 | const slice = slice: { | ||
| 10325 | if (ni.next(&elf.mf).unwrap()) |next_ni| switch (next_ni.position(&elf.mf)) { | ||
| 10326 | .header => unreachable, | ||
| 10327 | .footer => {}, | ||
| 10328 | .floating => { | ||
| 10329 | const parent_slice = parent_ni.slicePadding(&elf.mf); | ||
| 10330 | const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf); | ||
| 10331 | break :slice parent_slice[@intCast(offset)..@intCast(next_offset)]; | ||
| 10332 | }, | ||
| 10333 | }; | ||
| 10334 | switch (tag) { | ||
| 10335 | else => unreachable, | ||
| 10336 | .unit_padding, .unit_debug_rnglists => { | ||
| 10337 | const parent_slice = parent_ni.slicePadding(&elf.mf); | ||
| 10338 | const frame_shndx = elf.getNodeShndx(parent_ni); | ||
| 10339 | const frame_format = frame_shndx.debugFrameFormat(elf) orelse | ||
| 10340 | break :slice parent_slice[@intCast(offset)..]; | ||
| 10341 | const footer_size = elf.debugFrameFooterSize(frame_format); | ||
| 10342 | @memset(parent_slice[@intCast(offset + size)..][0..footer_size], 0); | ||
| 10343 | frame_shndx.setSize(elf, offset + size + footer_size); | ||
| 10344 | break :slice parent_slice[@intCast(offset)..][0..@intCast(size)]; | ||
| 10345 | }, | ||
| 10346 | .unit_frame_cie, .func_frame_fde => { | ||
| 10347 | const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); | ||
| 10348 | const frame_ni = parent_ni.parent(&elf.mf).unwrap().?; | ||
| 10349 | const frame_slice = frame_ni.slicePadding(&elf.mf); | ||
| 10350 | const frame_shndx = elf.getNode(frame_ni).section_manual_size; | ||
| 10351 | const frame_format = frame_shndx.debugFrameFormat(elf).?; | ||
| 10352 | if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| { | ||
| 10353 | switch (parent_next_ni.position(&elf.mf)) { | ||
| 10354 | .header => unreachable, | ||
| 10355 | .footer => {}, | ||
| 10356 | .floating => { | ||
| 10357 | const parent_next_offset, _ = | ||
| 10358 | parent_next_ni.location(&elf.mf).resolve(&elf.mf); | ||
| 10359 | const slice = frame_slice[@intCast( | ||
| 10360 | parent_offset + offset, | ||
| 10361 | )..@intCast(parent_next_offset)]; | ||
| 10362 | var fw: Io.Writer = .fixed(slice[@intCast(size)..]); | ||
| 10363 | elf.dwarf.genDebugFrameCie( | ||
| 10364 | &fw, | ||
| 10365 | null, | ||
| 10366 | frame_format, | ||
| 10367 | ) catch |err| switch (err) { | ||
| 10368 | error.WriteFailed => break :slice slice, | ||
| 10369 | }; | ||
| 10370 | elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len); | ||
| 10371 | break :slice slice[0..@intCast(size)]; | ||
| 10372 | }, | ||
| 10373 | } | ||
| 10374 | } | ||
| 10375 | const footer_size = elf.debugFrameFooterSize(frame_format); | ||
| 10376 | @memset( | ||
| 10377 | frame_slice[@intCast(parent_offset + offset + size)..][0..footer_size], | ||
| 10378 | 0, | ||
| 10379 | ); | ||
| 10380 | frame_shndx.setSize(elf, parent_offset + offset + size + footer_size); | ||
| 10381 | break :slice frame_slice[@intCast(parent_offset + offset)..][0..@intCast(size)]; | ||
| 10382 | }, | ||
| 10383 | .unit_debug_info_header, | ||
| 10384 | .unit_debug_line_header, | ||
| 10385 | .const_debug_info, | ||
| 10386 | .global_debug_info, | ||
| 10387 | .func_debug_info, | ||
| 10388 | .func_debug_line, | ||
| 10389 | .decl_debug_info, | ||
| 10390 | => { | ||
| 10391 | const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); | ||
| 10392 | const debug_ni = parent_ni.parent(&elf.mf).unwrap().?; | ||
| 10393 | const debug_slice = debug_ni.slicePadding(&elf.mf); | ||
| 10394 | var fw: Io.Writer = .fixed(buffer: { | ||
| 10395 | if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| { | ||
| 10396 | switch (parent_next_ni.position(&elf.mf)) { | ||
| 10397 | .header => unreachable, | ||
| 10398 | .footer => {}, | ||
| 10399 | .floating => { | ||
| 10400 | const parent_next_offset, _ = | ||
| 10401 | parent_next_ni.location(&elf.mf).resolve(&elf.mf); | ||
| 10402 | break :buffer debug_slice[@intCast( | ||
| 10403 | parent_offset, | ||
| 10404 | )..@intCast(parent_next_offset)]; | ||
| 10405 | }, | ||
| 10406 | } | ||
| 10407 | } | ||
| 10408 | break :buffer debug_slice[@intCast(parent_offset)..]; | ||
| 10409 | }); | ||
| 10410 | fw.end = @intCast(offset + size); | ||
| 10411 | switch (tag) { | ||
| 10412 | else => unreachable, | ||
| 10413 | .unit_debug_info_header, | ||
| 10414 | .const_debug_info, | ||
| 10415 | .global_debug_info, | ||
| 10416 | .func_debug_info, | ||
| 10417 | .decl_debug_info, | ||
| 10418 | => for (0..2) |_| fw.writeUleb128(@backingInt(Dwarf.AbbrevCode.null)) catch | ||
| 10419 | unreachable, | ||
| 10420 | .unit_debug_line_header, .func_debug_line => {}, | ||
| 10421 | } | ||
| 10422 | const unit_padding_offset = fw.end; | ||
| 10423 | const unit_padding = fw.unusedCapacitySlice(); | ||
| 10424 | elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) { | ||
| 10425 | error.WriteFailed => { | ||
| 10426 | fw.end = unit_padding_offset; | ||
| 10427 | elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len); | ||
| 10428 | switch (tag) { | ||
| 10429 | else => unreachable, | ||
| 10430 | .unit_debug_info_header, | ||
| 10431 | .const_debug_info, | ||
| 10432 | .global_debug_info, | ||
| 10433 | .func_debug_info, | ||
| 10434 | .decl_debug_info, | ||
| 10435 | => { | ||
| 10436 | comptime assert( | ||
| 10437 | Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) == 1, | ||
| 10438 | ); | ||
| 10439 | @memset( | ||
| 10440 | fw.unusedCapacitySlice(), | ||
| 10441 | @backingInt(Dwarf.AbbrevCode.null), | ||
| 10442 | ); | ||
| 10443 | }, | ||
| 10444 | .unit_debug_line_header, | ||
| 10445 | .func_debug_line, | ||
| 10446 | => Dwarf.genDebugLinePadding(&fw, fw.unusedCapacityLen()) catch | ||
| 10447 | unreachable, | ||
| 10448 | } | ||
| 10449 | return; | ||
| 10450 | }, | ||
| 10451 | }; | ||
| 10452 | elf.dwarf.updateUnitLength(fw.buffer, unit_padding_offset); | ||
| 10453 | elf.dwarf.updateUnitLength(unit_padding, unit_padding.len); | ||
| 10454 | return; | ||
| 10455 | }, | ||
| 10456 | } | ||
| 10457 | }; | ||
| 10458 | var fw: Io.Writer = .fixed(slice[@intCast(size)..]); | ||
| 10459 | switch (tag) { | ||
| 10460 | else => unreachable, | ||
| 10461 | .unit_padding => elf.dwarf.updateUnitLength(slice, slice.len), | ||
| 10462 | .unit_frame_cie, .func_frame_fde => { | ||
| 10463 | elf.dwarf.updateUnitLength(slice, slice.len); | ||
| 10464 | @memset(fw.buffer, std.dwarf.CFA.nop); | ||
| 10465 | }, | ||
| 10466 | .unit_debug_info_header, | ||
| 10467 | .const_debug_info, | ||
| 10468 | .global_debug_info, | ||
| 10469 | .func_debug_info, | ||
| 10470 | .decl_debug_info, | ||
| 10471 | => elf.dwarf.genDebugInfoPadding(&fw, fw.buffer.len) catch unreachable, | ||
| 10472 | .unit_debug_line_header, | ||
| 10473 | .func_debug_line, | ||
| 10474 | => Dwarf.genDebugLinePadding(&fw, fw.buffer.len) catch unreachable, | ||
| 10475 | .unit_debug_rnglists => { | ||
| 10476 | elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) { | ||
| 10477 | error.WriteFailed => { | ||
| 10478 | elf.dwarf.updateUnitLength(slice, slice.len); | ||
| 10479 | @memset(fw.buffer, std.dwarf.RLE.end_of_list); | ||
| 10480 | return; | ||
| 10481 | }, | ||
| 10482 | }; | ||
| 10483 | elf.dwarf.updateUnitLength(slice, size); | ||
| 10484 | elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len); | ||
| 10485 | }, | ||
| 10486 | } | ||
| 10487 | }, | ||
| 10488 | .unit_frame, .unit_debug_info, .unit_debug_line => { | ||
| 10489 | var last_ni = ni.last(&elf.mf).unwrap() orelse return; | ||
| 10490 | while (last_ni.position(&elf.mf) == .footer) | ||
| 10491 | last_ni = last_ni.prev(&elf.mf).unwrap() orelse return; | ||
| 10492 | try last_ni.nextMoved(elf.base.comp.gpa, &elf.mf); | ||
| 10493 | }, | ||
| 8636 | } | 10494 | } |
| 8637 | } | 10495 | } |
| 8638 | 10496 | ||
| ... | @@ -8987,11 +10845,10 @@ pub fn updateExports( | ... | @@ -8987,11 +10845,10 @@ pub fn updateExports( |
| 8987 | pt: Zcu.PerThread, | 10845 | pt: Zcu.PerThread, |
| 8988 | export_indices: []const Zcu.Export.Index, | 10846 | export_indices: []const Zcu.Export.Index, |
| 8989 | ) link.Error!void { | 10847 | ) link.Error!void { |
| 8990 | const diags = &elf.base.comp.link_diags; | ||
| 8991 | for (export_indices) |export_index| { | 10848 | for (export_indices) |export_index| { |
| 8992 | elf.updateExportInner(pt, export_index) catch |err| switch (err) { | 10849 | elf.updateExportInner(pt, export_index) catch |err| switch (err) { |
| 8993 | else => |e| return e, | 10850 | else => |e| return e, |
| 8994 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | 10851 | error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), |
| 8995 | }; | 10852 | }; |
| 8996 | } | 10853 | } |
| 8997 | } | 10854 | } |
| ... | @@ -9068,17 +10925,19 @@ fn updateExportInner( | ... | @@ -9068,17 +10925,19 @@ fn updateExportInner( |
| 9068 | }; | 10925 | }; |
| 9069 | } | 10926 | } |
| 9070 | 10927 | ||
| 9071 | fn dumpStderr(elf: *Elf, tid: Zcu.PerThread.Id) !void { | 10928 | fn dumpStderr(elf: *Elf, tid: Zcu.PerThread.Id) Io.File.Writer.Error!void { |
| 9072 | const comp = elf.base.comp; | 10929 | const comp = elf.base.comp; |
| 9073 | const io = comp.io; | 10930 | const io = comp.io; |
| 9074 | var buffer: [512]u8 = undefined; | 10931 | var buffer: [512]u8 = undefined; |
| 9075 | const stderr = try io.lockStderr(&buffer, null); | 10932 | const stderr = try io.lockStderr(&buffer, null); |
| 9076 | defer io.unlockStderr(); | 10933 | defer io.unlockStderr(); |
| 9077 | const w = &stderr.file_writer.interface; | 10934 | const w = &stderr.file_writer.interface; |
| 9078 | _ = try elf.dump(w, tid); | 10935 | _ = elf.dump(w, tid) catch |err| switch (err) { |
| 10936 | error.WriteFailed => return stderr.file_writer.err.?, | ||
| 10937 | }; | ||
| 9079 | } | 10938 | } |
| 9080 | 10939 | ||
| 9081 | pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult { | 10940 | pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) Io.Writer.Error!link.File.DumpResult { |
| 9082 | if (elf.options.enable_link_snapshots) { | 10941 | if (elf.options.enable_link_snapshots) { |
| 9083 | try elf.printNode(tid, w, .root, 0); | 10942 | try elf.printNode(tid, w, .root, 0); |
| 9084 | return .enabled; | 10943 | return .enabled; |
| ... | @@ -9118,22 +10977,22 @@ pub fn printNode( | ... | @@ -9118,22 +10977,22 @@ pub fn printNode( |
| 9118 | try w.writeByte(')'); | 10977 | try w.writeByte(')'); |
| 9119 | }, | 10978 | }, |
| 9120 | }, | 10979 | }, |
| 9121 | .section => |shndx| try w.print("({s})", .{shndx.name(elf).slice(elf)}), | 10980 | .section, .section_manual_size => |shndx| try w.print("({s})", .{shndx.name(elf).slice(elf)}), |
| 9122 | .input_section => |isi| { | 10981 | .input_section => |isi| { |
| 9123 | const ii = isi.input(elf); | 10982 | const ii = isi.input(elf); |
| 9124 | try w.print("({f}{f}, {s})", .{ | 10983 | try w.print("({f}{f}, {s})", .{ |
| 9125 | ii.path(elf).fmtEscapeString(), | 10984 | ii.path(elf).fmtEscapeString(), |
| 9126 | fmtMemberString(ii.member(elf)), | 10985 | fmtMemberString(ii.member(elf)), |
| 9127 | elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf), | 10986 | elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf), |
| 9128 | }); | 10987 | }); |
| 9129 | }, | 10988 | }, |
| 9130 | .copied_global => |name| try w.print("(copy:{s})", .{name.slice(elf)}), | 10989 | .copied_global => |name| try w.print("(copy:{s})", .{name.slice(elf)}), |
| 9131 | .nav => |nmi| { | 10990 | .nav => |nmi| { |
| 9132 | const zcu = elf.base.comp.zcu.?; | 10991 | const zcu = elf.base.comp.zcu.?; |
| 9133 | const ip = &zcu.intern_pool; | 10992 | const ip = &zcu.intern_pool; |
| 9134 | const nav = ip.getNav(nmi.navIndex(elf)); | 10993 | const nav = ip.getNav(nmi.nav(elf)); |
| 9135 | try w.print("({f}, {f})", .{ | 10994 | try w.print("({f}, {f})", .{ |
| 9136 | Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }), | 10995 | Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }), |
| 9137 | nav.fqn.fmt(ip), | 10996 | nav.fqn.fmt(ip), |
| 9138 | }); | 10997 | }); |
| 9139 | }, | 10998 | }, |
| ... | @@ -9151,19 +11010,66 @@ pub fn printNode( | ... | @@ -9151,19 +11010,66 @@ pub fn printNode( |
| 9151 | .tid = tid, | 11010 | .tid = tid, |
| 9152 | }), | 11011 | }), |
| 9153 | }), | 11012 | }), |
| 11013 | .debug_shared => |ss| try w.print("({})", .{ss}), | ||
| 11014 | .unit_frame, | ||
| 11015 | .unit_frame_cie, | ||
| 11016 | .unit_debug_info, | ||
| 11017 | .unit_debug_info_header, | ||
| 11018 | .unit_debug_info_footer, | ||
| 11019 | .unit_debug_line, | ||
| 11020 | .unit_debug_line_header, | ||
| 11021 | .unit_debug_rnglists, | ||
| 11022 | => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}), | ||
| 11023 | .const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) { | ||
| 11024 | .generic_poison_type => try w.writeAll("(anytype)"), | ||
| 11025 | else => |val| try w.print("({f})", .{ | ||
| 11026 | Value.fromInterned(val).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), | ||
| 11027 | }), | ||
| 11028 | }, | ||
| 11029 | .global_debug_info => |gi| { | ||
| 11030 | const zcu = elf.base.comp.zcu.?; | ||
| 11031 | const ip = &zcu.intern_pool; | ||
| 11032 | const nav = ip.getNav(gi.nav(&elf.dwarf)); | ||
| 11033 | try w.writeByte('('); | ||
| 11034 | if (nav.resolved) |resolved| try w.print("{f}, ", .{ | ||
| 11035 | Type.fromInterned(resolved.type).fmt(.{ .zcu = zcu, .tid = tid }), | ||
| 11036 | }); | ||
| 11037 | try w.print("{f})", .{nav.fqn.fmt(ip)}); | ||
| 11038 | }, | ||
| 11039 | .func_frame_fde, .func_debug_info, .func_debug_line => |fi| { | ||
| 11040 | const zcu = elf.base.comp.zcu.?; | ||
| 11041 | const ip = &zcu.intern_pool; | ||
| 11042 | const nav = ip.getNav(fi.nav(&elf.dwarf)); | ||
| 11043 | try w.writeByte('('); | ||
| 11044 | if (nav.resolved) |resolved| try w.print("{f}, ", .{ | ||
| 11045 | Type.fromInterned(resolved.type).fmt(.{ .zcu = zcu, .tid = tid }), | ||
| 11046 | }); | ||
| 11047 | try w.print("{f})", .{nav.fqn.fmt(ip)}); | ||
| 11048 | }, | ||
| 11049 | .decl_debug_info => |di| { | ||
| 11050 | const comp = elf.base.comp; | ||
| 11051 | const zcu = comp.zcu.?; | ||
| 11052 | const ip = &zcu.intern_pool; | ||
| 11053 | const src_inst = di.srcInst(&elf.dwarf); | ||
| 11054 | try w.print("({f}, ", .{zcu.fileByIndex(src_inst.resolveFile(ip)).path.fmt(comp)}); | ||
| 11055 | if (src_inst.resolve(ip)) |inst| try w.print("%{d}", .{inst}) else try w.writeAll("lost"); | ||
| 11056 | try w.writeByte(')'); | ||
| 11057 | }, | ||
| 9154 | } | 11058 | } |
| 9155 | { | 11059 | { |
| 9156 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; | 11060 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; |
| 9157 | const off, const size = mf_node.location().resolve(&elf.mf); | 11061 | const off, const size = mf_node.location().resolve(&elf.mf); |
| 9158 | try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x} {t}{s}{s}{s}{s}\n", .{ | 11062 | try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x} {t}{s}{s}{s}{s}{s}{s}\n", .{ |
| 9159 | @backingInt(ni), | 11063 | @backingInt(ni), |
| 9160 | off, | 11064 | off, |
| 9161 | size, | 11065 | size, |
| 9162 | mf_node.flags.alignment.toByteUnits(), | 11066 | mf_node.flags.alignment.toByteUnits(), |
| 9163 | mf_node.flags.position, | 11067 | mf_node.flags.position, |
| 9164 | if (mf_node.flags.moved) " moved" else "", | 11068 | if (mf_node.flags.bubbles_moved) " bubbles_moved" else "", |
| 9165 | if (mf_node.flags.next_moved) " next_moved" else "", | 11069 | if (mf_node.flags.resized) " moved" else "", |
| 9166 | if (mf_node.flags.resized) " resized" else "", | 11070 | if (mf_node.flags.resized) " resized" else "", |
| 11071 | if (mf_node.flags.enable_next_moved) " enable_next_moved" else "", | ||
| 11072 | if (mf_node.flags.next_moved) " next_moved" else "", | ||
| 9167 | if (mf_node.flags.has_content) " has_content" else "", | 11073 | if (mf_node.flags.has_content) " has_content" else "", |
| 9168 | }); | 11074 | }); |
| 9169 | } | 11075 | } |
| ... | @@ -9176,26 +11082,30 @@ pub fn printNode( | ... | @@ -9176,26 +11082,30 @@ pub fn printNode( |
| 9176 | } | 11082 | } |
| 9177 | return; | 11083 | return; |
| 9178 | } | 11084 | } |
| 9179 | const file_loc = ni.fileLocation(&elf.mf, false); | 11085 | const start_address: usize, const end_address: usize = file_loc: { |
| 9180 | var address = file_loc.offset; | 11086 | const file_loc = ni.fileLocation(&elf.mf, false); |
| 9181 | if (file_loc.size == 0) { | 11087 | break :file_loc .{ @intCast(file_loc.offset), @intCast(file_loc.offset + file_loc.size) }; |
| 9182 | try w.splatByteAll(' ', indent + 1); | 11088 | }; |
| 9183 | try w.print("{x:0>8}\n", .{address}); | 11089 | var address = start_address; |
| 9184 | return; | ||
| 9185 | } | ||
| 9186 | const line_len = 0x10; | 11090 | const line_len = 0x10; |
| 9187 | var line_it = std.mem.window( | 11091 | while (true) : (address = @min(std.mem.alignForward(usize, address + 1, line_len), end_address)) { |
| 9188 | u8, | ||
| 9189 | elf.mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)], | ||
| 9190 | line_len, | ||
| 9191 | line_len, | ||
| 9192 | ); | ||
| 9193 | while (line_it.next()) |line_bytes| : (address += line_len) { | ||
| 9194 | try w.splatByteAll(' ', indent + 1); | 11092 | try w.splatByteAll(' ', indent + 1); |
| 9195 | try w.print("{x:0>8} ", .{address}); | 11093 | try w.print("{x:0>8}", .{address}); |
| 9196 | for (line_bytes) |byte| try w.print("{x:0>2} ", .{byte}); | 11094 | if (address == end_address) break try w.writeByte('\n'); |
| 9197 | try w.splatByteAll(' ', 3 * (line_len - line_bytes.len) + 1); | 11095 | try w.splatByteAll(' ', 2); |
| 9198 | for (line_bytes) |byte| try w.writeByte(if (std.ascii.isPrint(byte)) byte else '.'); | 11096 | const start_byte_address = std.mem.alignBackward(usize, address, line_len); |
| 11097 | const end_byte_address = start_byte_address + line_len; | ||
| 11098 | for (start_byte_address..end_byte_address) |byte_address| | ||
| 11099 | if (byte_address < start_address or byte_address >= end_address) | ||
| 11100 | try w.splatByteAll(' ', 3) | ||
| 11101 | else | ||
| 11102 | try w.print("{x:0>2} ", .{elf.mf.memory_map.memory[byte_address]}); | ||
| 11103 | try w.writeByte(' '); | ||
| 11104 | for (start_byte_address..@min(end_address, end_byte_address)) |byte_address| | ||
| 11105 | try w.writeByte(if (byte_address < start_address or byte_address >= end_address) ' ' else char: { | ||
| 11106 | const byte = elf.mf.memory_map.memory[byte_address]; | ||
| 11107 | break :char if (std.ascii.isPrint(byte)) byte else '.'; | ||
| 11108 | }); | ||
| 9199 | try w.writeByte('\n'); | 11109 | try w.writeByte('\n'); |
| 9200 | } | 11110 | } |
| 9201 | } | 11111 | } |
| ... | @@ -9209,7 +11119,7 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error | ... | @@ -9209,7 +11119,7 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error |
| 9209 | // Align the actual node | 11119 | // Align the actual node |
| 9210 | const seg_ni = elf.phdrs.items[phndx].unwrap().?; | 11120 | const seg_ni = elf.phdrs.items[phndx].unwrap().?; |
| 9211 | if (min_align.compare(.gt, seg_ni.alignment(&elf.mf))) { | 11121 | if (min_align.compare(.gt, seg_ni.alignment(&elf.mf))) { |
| 9212 | try seg_ni.realign(&elf.mf, gpa, min_align); | 11122 | try seg_ni.realign(gpa, &elf.mf, min_align); |
| 9213 | } | 11123 | } |
| 9214 | // Update the phdr `@"align"` field if necessary | 11124 | // Update the phdr `@"align"` field if necessary |
| 9215 | switch (elf.phdrSlice()) { | 11125 | switch (elf.phdrSlice()) { |
| ... | @@ -9240,6 +11150,21 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error | ... | @@ -9240,6 +11150,21 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error |
| 9240 | } | 11150 | } |
| 9241 | } | 11151 | } |
| 9242 | 11152 | ||
| 11153 | pub fn addNodeAssumeCapacity(elf: *Elf, ni: MappedFile.Node.Index, node: Node) MappedFile.Node.Index { | ||
| 11154 | if (elf.nodes.len - @backingInt(ni) > 0) { | ||
| 11155 | assert(elf.getNode(ni) == .deleted); | ||
| 11156 | elf.nodes.set(@backingInt(ni), node); | ||
| 11157 | } else elf.nodes.appendAssumeCapacity(node); | ||
| 11158 | return ni; | ||
| 11159 | } | ||
| 11160 | |||
| 11161 | fn deleteNode(elf: *Elf, node: *MappedFile.Node.Index.Optional) std.mem.Allocator.Error!void { | ||
| 11162 | const ni = node.unwrap().?; | ||
| 11163 | try ni.delete(elf.base.comp.gpa, &elf.mf); | ||
| 11164 | elf.nodes.set(@backingInt(ni), .deleted); | ||
| 11165 | node.* = .none; | ||
| 11166 | } | ||
| 11167 | |||
| 9243 | /// If `sym` has a PLT entry, returns the address of that entry (specifically, the address which a | 11168 | /// If `sym` has a PLT entry, returns the address of that entry (specifically, the address which a |
| 9244 | /// branch to the PLT should target). If `sym` does not have a PLT entry, returns `null`. | 11169 | /// branch to the PLT should target). If `sym` does not have a PLT entry, returns `null`. |
| 9245 | fn pltEntryTargetAddr(elf: *Elf, sym: Symbol.Id) ?u64 { | 11170 | fn pltEntryTargetAddr(elf: *Elf, sym: Symbol.Id) ?u64 { |
src/link/MachO.zig+2-3| ... | @@ -3095,8 +3095,8 @@ pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin | ... | @@ -3095,8 +3095,8 @@ pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin |
| 3095 | return self.getZigObject().?.updateNav(self, pt, nav); | 3095 | return self.getZigObject().?.updateNav(self, pt, nav); |
| 3096 | } | 3096 | } |
| 3097 | 3097 | ||
| 3098 | pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void { | 3098 | pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, inst: InternPool.TrackedInst.Index, line: u32) link.Error!void { |
| 3099 | return self.getZigObject().?.updateLineNumber(pt, ti_id); | 3099 | return self.getZigObject().?.updateLineNumber(pt, inst, line); |
| 3100 | } | 3100 | } |
| 3101 | 3101 | ||
| 3102 | pub fn updateExports( | 3102 | pub fn updateExports( |
| ... | @@ -5503,4 +5503,3 @@ const Value = @import("../Value.zig"); | ... | @@ -5503,4 +5503,3 @@ const Value = @import("../Value.zig"); |
| 5503 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); | 5503 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); |
| 5504 | const WeakBind = bind.WeakBind; | 5504 | const WeakBind = bind.WeakBind; |
| 5505 | const ZigObject = @import("MachO/ZigObject.zig"); | 5505 | const ZigObject = @import("MachO/ZigObject.zig"); |
| 5506 | const dev = @import("../dev.zig"); |
src/link/MachO/Atom.zig+2-2| ... | @@ -853,7 +853,7 @@ fn resolveRelocInner( | ... | @@ -853,7 +853,7 @@ fn resolveRelocInner( |
| 853 | 853 | ||
| 854 | const x86_64 = struct { | 854 | const x86_64 = struct { |
| 855 | fn relaxGotLoad(self: Atom, code: []u8, rel: Relocation, macho_file: *MachO) ResolveError!void { | 855 | fn relaxGotLoad(self: Atom, code: []u8, rel: Relocation, macho_file: *MachO) ResolveError!void { |
| 856 | dev.check(.x86_64_backend); | 856 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 857 | const t = &macho_file.base.comp.root_mod.resolved_target.result; | 857 | const t = &macho_file.base.comp.root_mod.resolved_target.result; |
| 858 | const diags = &macho_file.base.comp.link_diags; | 858 | const diags = &macho_file.base.comp.link_diags; |
| 859 | const old_inst = disassemble(code) orelse return error.RelaxFail; | 859 | const old_inst = disassemble(code) orelse return error.RelaxFail; |
| ... | @@ -879,7 +879,7 @@ const x86_64 = struct { | ... | @@ -879,7 +879,7 @@ const x86_64 = struct { |
| 879 | } | 879 | } |
| 880 | 880 | ||
| 881 | fn relaxTlv(code: []u8, t: *const std.Target) error{RelaxFail}!void { | 881 | fn relaxTlv(code: []u8, t: *const std.Target) error{RelaxFail}!void { |
| 882 | dev.check(.x86_64_backend); | 882 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); |
| 883 | const old_inst = disassemble(code) orelse return error.RelaxFail; | 883 | const old_inst = disassemble(code) orelse return error.RelaxFail; |
| 884 | switch (old_inst.encoding.mnemonic) { | 884 | switch (old_inst.encoding.mnemonic) { |
| 885 | .mov => { | 885 | .mov => { |
src/link/MachO/Object.zig+5| ... | @@ -3,6 +3,7 @@ const Object = @This(); | ... | @@ -3,6 +3,7 @@ const Object = @This(); |
| 3 | const trace = @import("../../tracy.zig").trace; | 3 | const trace = @import("../../tracy.zig").trace; |
| 4 | const Archive = @import("Archive.zig"); | 4 | const Archive = @import("Archive.zig"); |
| 5 | const Atom = @import("Atom.zig"); | 5 | const Atom = @import("Atom.zig"); |
| 6 | const dev = @import("../../dev.zig"); | ||
| 6 | const Dwarf = @import("Dwarf.zig"); | 7 | const Dwarf = @import("Dwarf.zig"); |
| 7 | const File = @import("file.zig").File; | 8 | const File = @import("file.zig").File; |
| 8 | const MachO = @import("../MachO.zig"); | 9 | const MachO = @import("../MachO.zig"); |
| ... | @@ -2826,6 +2827,7 @@ const x86_64 = struct { | ... | @@ -2826,6 +2827,7 @@ const x86_64 = struct { |
| 2826 | handle: File.Handle, | 2827 | handle: File.Handle, |
| 2827 | macho_file: *MachO, | 2828 | macho_file: *MachO, |
| 2828 | ) !void { | 2829 | ) !void { |
| 2830 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 2829 | const comp = macho_file.base.comp; | 2831 | const comp = macho_file.base.comp; |
| 2830 | const io = comp.io; | 2832 | const io = comp.io; |
| 2831 | const gpa = comp.gpa; | 2833 | const gpa = comp.gpa; |
| ... | @@ -2938,6 +2940,7 @@ const x86_64 = struct { | ... | @@ -2938,6 +2940,7 @@ const x86_64 = struct { |
| 2938 | } | 2940 | } |
| 2939 | 2941 | ||
| 2940 | fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_x86_64, is_extern: bool) !Relocation.Type { | 2942 | fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_x86_64, is_extern: bool) !Relocation.Type { |
| 2943 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 2941 | switch (rel_type) { | 2944 | switch (rel_type) { |
| 2942 | .X86_64_RELOC_UNSIGNED => { | 2945 | .X86_64_RELOC_UNSIGNED => { |
| 2943 | if (rel.r_pcrel == 1) return error.Pcrel; | 2946 | if (rel.r_pcrel == 1) return error.Pcrel; |
| ... | @@ -2995,6 +2998,7 @@ const aarch64 = struct { | ... | @@ -2995,6 +2998,7 @@ const aarch64 = struct { |
| 2995 | handle: File.Handle, | 2998 | handle: File.Handle, |
| 2996 | macho_file: *MachO, | 2999 | macho_file: *MachO, |
| 2997 | ) !void { | 3000 | ) !void { |
| 3001 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 2998 | const comp = macho_file.base.comp; | 3002 | const comp = macho_file.base.comp; |
| 2999 | const io = comp.io; | 3003 | const io = comp.io; |
| 3000 | const gpa = comp.gpa; | 3004 | const gpa = comp.gpa; |
| ... | @@ -3131,6 +3135,7 @@ const aarch64 = struct { | ... | @@ -3131,6 +3135,7 @@ const aarch64 = struct { |
| 3131 | } | 3135 | } |
| 3132 | 3136 | ||
| 3133 | fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_arm64, is_extern: bool) !Relocation.Type { | 3137 | fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_arm64, is_extern: bool) !Relocation.Type { |
| 3138 | dev.checkAny(&.{ .llvm_backend, .aarch64_backend }); | ||
| 3134 | switch (rel_type) { | 3139 | switch (rel_type) { |
| 3135 | .ARM64_RELOC_UNSIGNED => { | 3140 | .ARM64_RELOC_UNSIGNED => { |
| 3136 | if (rel.r_pcrel == 1) return error.Pcrel; | 3141 | if (rel.r_pcrel == 1) return error.Pcrel; |
src/link/MachO/ZigObject.zig+14-18| ... | @@ -647,14 +647,11 @@ pub fn getNavVAddr( | ... | @@ -647,14 +647,11 @@ pub fn getNavVAddr( |
| 647 | }, | 647 | }, |
| 648 | }); | 648 | }); |
| 649 | }, | 649 | }, |
| 650 | .debug_output => |debug_output| switch (debug_output) { | 650 | .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{ |
| 651 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 651 | .source_off = @intCast(reloc_info.offset), |
| 652 | .source_off = @intCast(reloc_info.offset), | 652 | .target_sym = @fromBackingInt(@intCast(sym_index)), |
| 653 | .target_sym = @fromBackingInt(@intCast(sym_index)), | 653 | .target_off = reloc_info.addend, |
| 654 | .target_off = reloc_info.addend, | 654 | }), |
| 655 | }), | ||
| 656 | .none => unreachable, | ||
| 657 | }, | ||
| 658 | } | 655 | } |
| 659 | return vaddr; | 656 | return vaddr; |
| 660 | } | 657 | } |
| ... | @@ -686,14 +683,11 @@ pub fn getUavVAddr( | ... | @@ -686,14 +683,11 @@ pub fn getUavVAddr( |
| 686 | }, | 683 | }, |
| 687 | }); | 684 | }); |
| 688 | }, | 685 | }, |
| 689 | .debug_output => |debug_output| switch (debug_output) { | 686 | .debug_output => |debug_output| try debug_output.dwarf.infoExternalReloc(.{ |
| 690 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 687 | .source_off = @intCast(reloc_info.offset), |
| 691 | .source_off = @intCast(reloc_info.offset), | 688 | .target_sym = @fromBackingInt(@intCast(sym_index)), |
| 692 | .target_sym = @fromBackingInt(@intCast(sym_index)), | 689 | .target_off = reloc_info.addend, |
| 693 | .target_off = reloc_info.addend, | 690 | }), |
| 694 | }), | ||
| 695 | .none => unreachable, | ||
| 696 | }, | ||
| 697 | } | 691 | } |
| 698 | return vaddr; | 692 | return vaddr; |
| 699 | } | 693 | } |
| ... | @@ -1418,11 +1412,11 @@ fn updateLazySymbol( | ... | @@ -1418,11 +1412,11 @@ fn updateLazySymbol( |
| 1418 | try macho_file.pwriteAll(code, file_offset); | 1412 | try macho_file.pwriteAll(code, file_offset); |
| 1419 | } | 1413 | } |
| 1420 | 1414 | ||
| 1421 | pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void { | 1415 | pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index, line: u32) link.Error!void { |
| 1422 | if (self.dwarf) |*dwarf| { | 1416 | if (self.dwarf) |*dwarf| { |
| 1423 | const comp = dwarf.bin_file.comp; | 1417 | const comp = dwarf.bin_file.comp; |
| 1424 | const diags = &comp.link_diags; | 1418 | const diags = &comp.link_diags; |
| 1425 | dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) { | 1419 | dwarf.updateLineNumber(pt.zcu, ti_id, line) catch |err| switch (err) { |
| 1426 | error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e, | 1420 | error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e, |
| 1427 | else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}), | 1421 | else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}), |
| 1428 | }; | 1422 | }; |
| ... | @@ -1750,6 +1744,7 @@ const TlvInitializerTable = std.array_hash_map.Auto(Atom.Index, TlvInitializer); | ... | @@ -1750,6 +1744,7 @@ const TlvInitializerTable = std.array_hash_map.Auto(Atom.Index, TlvInitializer); |
| 1750 | 1744 | ||
| 1751 | const x86_64 = struct { | 1745 | const x86_64 = struct { |
| 1752 | fn writeTrampolineCode(source_addr: u64, target_addr: u64, buf: *[max_trampoline_len]u8) ![]u8 { | 1746 | fn writeTrampolineCode(source_addr: u64, target_addr: u64, buf: *[max_trampoline_len]u8) ![]u8 { |
| 1747 | dev.checkAny(&.{ .llvm_backend, .x86_64_backend }); | ||
| 1753 | const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr)) - 5; | 1748 | const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr)) - 5; |
| 1754 | var bytes = [_]u8{ | 1749 | var bytes = [_]u8{ |
| 1755 | 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp rel32 | 1750 | 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp rel32 |
| ... | @@ -1764,6 +1759,7 @@ const x86_64 = struct { | ... | @@ -1764,6 +1759,7 @@ const x86_64 = struct { |
| 1764 | const assert = std.debug.assert; | 1759 | const assert = std.debug.assert; |
| 1765 | const builtin = @import("builtin"); | 1760 | const builtin = @import("builtin"); |
| 1766 | const codegen = @import("../../codegen.zig"); | 1761 | const codegen = @import("../../codegen.zig"); |
| 1762 | const dev = @import("../../dev.zig"); | ||
| 1767 | const link = @import("../../link.zig"); | 1763 | const link = @import("../../link.zig"); |
| 1768 | const log = std.log.scoped(.link); | 1764 | const log = std.log.scoped(.link); |
| 1769 | const macho = std.macho; | 1765 | const macho = std.macho; |
src/link/MappedFile.zig+73-57| ... | @@ -362,7 +362,7 @@ pub const Node = extern struct { | ... | @@ -362,7 +362,7 @@ pub const Node = extern struct { |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | /// Adds a floating child node to `parent_ni`. Returns the index of the new child. | 364 | /// Adds a floating child node to `parent_ni`. Returns the index of the new child. |
| 365 | pub fn addFloatingChild(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, opts: AddOptions) Error!Node.Index { | 365 | pub fn addFloatingChild(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, opts: AddOptions) Error!Node.Index { |
| 366 | return mf.addNode(gpa, .{ | 366 | return mf.addNode(gpa, .{ |
| 367 | .add_options = opts, | 367 | .add_options = opts, |
| 368 | .position = .floating, | 368 | .position = .floating, |
| ... | @@ -373,11 +373,11 @@ pub const Node = extern struct { | ... | @@ -373,11 +373,11 @@ pub const Node = extern struct { |
| 373 | /// Adds a header child node to `parent_ni`. Returns the index of the new child. | 373 | /// Adds a header child node to `parent_ni`. Returns the index of the new child. |
| 374 | /// | 374 | /// |
| 375 | /// Asserts that `parent_ni` has no existing header children. | 375 | /// Asserts that `parent_ni` has no existing header children. |
| 376 | pub fn addOnlyHeaderChild(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, opts: AddOptions) Error!Node.Index { | 376 | pub fn addOnlyHeaderChild(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, opts: AddOptions) Error!Node.Index { |
| 377 | if (parent_ni.first(mf).unwrap()) |first_ni| { | 377 | if (parent_ni.first(mf).unwrap()) |first_ni| { |
| 378 | assert(first_ni.position(mf) != .header); // `parent_ni` already has a header child | 378 | assert(first_ni.position(mf) != .header); // `parent_ni` already has a header child |
| 379 | } | 379 | } |
| 380 | return parent_ni.addHeaderChildAfter(mf, gpa, .none, opts); | 380 | return parent_ni.addHeaderChildAfter(gpa, mf, .none, opts); |
| 381 | } | 381 | } |
| 382 | /// Adds a header child node to `parent_ni`. Returns the index of the new child. | 382 | /// Adds a header child node to `parent_ni`. Returns the index of the new child. |
| 383 | /// | 383 | /// |
| ... | @@ -386,7 +386,7 @@ pub const Node = extern struct { | ... | @@ -386,7 +386,7 @@ pub const Node = extern struct { |
| 386 | /// | 386 | /// |
| 387 | /// Otherwise, asserts that `prev_oni` is a header node and a child of `parent_ni`, and | 387 | /// Otherwise, asserts that `prev_oni` is a header node and a child of `parent_ni`, and |
| 388 | /// places the new child node immediately after `prev_oni`. | 388 | /// places the new child node immediately after `prev_oni`. |
| 389 | pub fn addHeaderChildAfter(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, prev_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index { | 389 | pub fn addHeaderChildAfter(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, prev_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index { |
| 390 | return mf.addNode(gpa, .{ | 390 | return mf.addNode(gpa, .{ |
| 391 | .add_options = opts, | 391 | .add_options = opts, |
| 392 | .position = .header, | 392 | .position = .header, |
| ... | @@ -397,11 +397,11 @@ pub const Node = extern struct { | ... | @@ -397,11 +397,11 @@ pub const Node = extern struct { |
| 397 | /// Adds a footer child node to `parent_ni`. Returns the index of the new child. | 397 | /// Adds a footer child node to `parent_ni`. Returns the index of the new child. |
| 398 | /// | 398 | /// |
| 399 | /// Asserts that `parent_ni` has no existing footer children. | 399 | /// Asserts that `parent_ni` has no existing footer children. |
| 400 | pub fn addOnlyFooterChild(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, opts: AddOptions) Error!Node.Index { | 400 | pub fn addOnlyFooterChild(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, opts: AddOptions) Error!Node.Index { |
| 401 | if (parent_ni.last(mf).unwrap()) |last_ni| { | 401 | if (parent_ni.last(mf).unwrap()) |last_ni| { |
| 402 | assert(last_ni.position(mf) != .footer); // `parent_ni` already has a footer child | 402 | assert(last_ni.position(mf) != .footer); // `parent_ni` already has a footer child |
| 403 | } | 403 | } |
| 404 | return parent_ni.addFooterChildBefore(mf, gpa, .none, opts); | 404 | return parent_ni.addFooterChildBefore(gpa, mf, .none, opts); |
| 405 | } | 405 | } |
| 406 | /// Adds a footer child node to `parent_ni`. Returns the index of the new child. | 406 | /// Adds a footer child node to `parent_ni`. Returns the index of the new child. |
| 407 | /// | 407 | /// |
| ... | @@ -410,7 +410,7 @@ pub const Node = extern struct { | ... | @@ -410,7 +410,7 @@ pub const Node = extern struct { |
| 410 | /// | 410 | /// |
| 411 | /// Otherwise, asserts that `next_oni` is a footer node and a child of `parent_ni`, and | 411 | /// Otherwise, asserts that `next_oni` is a footer node and a child of `parent_ni`, and |
| 412 | /// places the new child node immediately before `next_oni`. | 412 | /// places the new child node immediately before `next_oni`. |
| 413 | pub fn addFooterChildBefore(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, next_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index { | 413 | pub fn addFooterChildBefore(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, next_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index { |
| 414 | const prev_oni: Node.Index.Optional = prev: { | 414 | const prev_oni: Node.Index.Optional = prev: { |
| 415 | const next_ni = next_oni.unwrap() orelse { | 415 | const next_ni = next_oni.unwrap() orelse { |
| 416 | break :prev parent_ni.last(mf); | 416 | break :prev parent_ni.last(mf); |
| ... | @@ -473,8 +473,8 @@ pub const Node = extern struct { | ... | @@ -473,8 +473,8 @@ pub const Node = extern struct { |
| 473 | fn setNext( | 473 | fn setNext( |
| 474 | ni: Node.Index, | 474 | ni: Node.Index, |
| 475 | gpa: Allocator, | 475 | gpa: Allocator, |
| 476 | next_ni: Node.Index.Optional, | ||
| 477 | mf: *MappedFile, | 476 | mf: *MappedFile, |
| 477 | next_ni: Node.Index.Optional, | ||
| 478 | ) Allocator.Error!void { | 478 | ) Allocator.Error!void { |
| 479 | const next_ptr = &ni.get(mf).next; | 479 | const next_ptr = &ni.get(mf).next; |
| 480 | if (next_ptr.* == next_ni) return; | 480 | if (next_ptr.* == next_ni) return; |
| ... | @@ -514,12 +514,10 @@ pub const Node = extern struct { | ... | @@ -514,12 +514,10 @@ pub const Node = extern struct { |
| 514 | return node_moved.*; | 514 | return node_moved.*; |
| 515 | } | 515 | } |
| 516 | pub fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void { | 516 | pub fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void { |
| 517 | if (ni.hasMoved(mf)) return; | ||
| 518 | const node = ni.get(mf); | 517 | const node = ni.get(mf); |
| 518 | if (node.prev.unwrap()) |prev_ni| prev_ni.nextMovedAssumeCapacity(mf); | ||
| 519 | if (ni.hasMoved(mf)) return; | ||
| 519 | node.flags.moved = true; | 520 | node.flags.moved = true; |
| 520 | if (node.prev.unwrap()) |prev_ni| { | ||
| 521 | prev_ni.nextMovedAssumeCapacity(mf); | ||
| 522 | } | ||
| 523 | if (node.flags.resized or node.flags.next_moved) return; | 521 | if (node.flags.resized or node.flags.next_moved) return; |
| 524 | mf.updates.appendAssumeCapacity(ni); | 522 | mf.updates.appendAssumeCapacity(ni); |
| 525 | mf.update_prog_node.increaseEstimatedTotalItems(1); | 523 | mf.update_prog_node.increaseEstimatedTotalItems(1); |
| ... | @@ -571,7 +569,7 @@ pub const Node = extern struct { | ... | @@ -571,7 +569,7 @@ pub const Node = extern struct { |
| 571 | return ni.get(mf).flags.alignment; | 569 | return ni.get(mf).flags.alignment; |
| 572 | } | 570 | } |
| 573 | 571 | ||
| 574 | fn setLocation(ni: Node.Index, mf: *MappedFile, gpa: Allocator, offset: u64, size: u64) Allocator.Error!void { | 572 | fn setLocation(ni: Node.Index, gpa: Allocator, mf: *MappedFile, offset: u64, size: u64) Allocator.Error!void { |
| 575 | try mf.large.ensureUnusedCapacity(gpa, 2); | 573 | try mf.large.ensureUnusedCapacity(gpa, 2); |
| 576 | try mf.updates.ensureUnusedCapacity(gpa, 2); | 574 | try mf.updates.ensureUnusedCapacity(gpa, 2); |
| 577 | const node = ni.get(mf); | 575 | const node = ni.get(mf); |
| ... | @@ -636,15 +634,38 @@ pub const Node = extern struct { | ... | @@ -636,15 +634,38 @@ pub const Node = extern struct { |
| 636 | return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; | 634 | return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; |
| 637 | } | 635 | } |
| 638 | 636 | ||
| 637 | pub fn slicePadding(ni: Node.Index, mf: *const MappedFile) []u8 { | ||
| 638 | const file_loc = ni.fileLocation(mf, false); | ||
| 639 | return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; | ||
| 640 | } | ||
| 641 | |||
| 639 | pub fn sliceConst(ni: Node.Index, mf: *const MappedFile) []const u8 { | 642 | pub fn sliceConst(ni: Node.Index, mf: *const MappedFile) []const u8 { |
| 640 | const file_loc = ni.fileLocation(mf, false); | 643 | const file_loc = ni.fileLocation(mf, false); |
| 641 | return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; | 644 | return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; |
| 642 | } | 645 | } |
| 643 | 646 | ||
| 647 | pub fn delete(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void { | ||
| 648 | const node = ni.get(mf); | ||
| 649 | assert(node.first == .none and node.last == .none); // has children | ||
| 650 | mf.removeNodesFromChildList(gpa, ni, ni); | ||
| 651 | const updated = node.flags.moved or node.flags.resized or node.flags.next_moved; | ||
| 652 | node.* = undefined; | ||
| 653 | node.next = ni.toOptional(); | ||
| 654 | if (!updated) assert(ni.pendingDelete(mf)); | ||
| 655 | } | ||
| 656 | |||
| 657 | pub fn pendingDelete(ni: Node.Index, mf: *MappedFile) bool { | ||
| 658 | const node = ni.get(mf); | ||
| 659 | if (node.next != ni.toOptional()) return false; | ||
| 660 | node.next = mf.free_ni; | ||
| 661 | mf.free_ni = ni.toOptional(); | ||
| 662 | return true; | ||
| 663 | } | ||
| 664 | |||
| 644 | /// Ensures that the size of `ni` is at least `min_size`. Valid for any node. | 665 | /// Ensures that the size of `ni` is at least `min_size`. Valid for any node. |
| 645 | /// | 666 | /// |
| 646 | /// Applies `growth_factor` if necessary (so the caller should *not* apply `growth_factor`). | 667 | /// Applies `growth_factor` if necessary (so the caller should *not* apply `growth_factor`). |
| 647 | pub fn ensureMinimumSize(ni: Node.Index, mf: *MappedFile, gpa: Allocator, min_size: u64) Error!void { | 668 | pub fn ensureMinimumSize(ni: Node.Index, gpa: Allocator, mf: *MappedFile, min_size: u64) Error!void { |
| 648 | _, const current_size = ni.location(mf).resolve(mf); | 669 | _, const current_size = ni.location(mf).resolve(mf); |
| 649 | if (current_size >= min_size) return; | 670 | if (current_size >= min_size) return; |
| 650 | const new_size = ni.alignment(mf).forward(min_size +| min_size / growth_factor); | 671 | const new_size = ni.alignment(mf).forward(min_size +| min_size / growth_factor); |
| ... | @@ -660,7 +681,7 @@ pub const Node = extern struct { | ... | @@ -660,7 +681,7 @@ pub const Node = extern struct { |
| 660 | /// Asserts that `ni` is a leaf node, i.e. has no children. | 681 | /// Asserts that `ni` is a leaf node, i.e. has no children. |
| 661 | /// | 682 | /// |
| 662 | /// Asserts that `size` is aligned to `ni.alignment(mf)`. | 683 | /// Asserts that `size` is aligned to `ni.alignment(mf)`. |
| 663 | pub fn resizeLeaf(ni: Node.Index, mf: *MappedFile, gpa: Allocator, size: u64) Error!void { | 684 | pub fn resizeLeaf(ni: Node.Index, gpa: Allocator, mf: *MappedFile, size: u64) Error!void { |
| 664 | assert(ni.first(mf) == .none); | 685 | assert(ni.first(mf) == .none); |
| 665 | // The alignment of `size` is asserted by `shrinkLeafNode` and `growNode`. | 686 | // The alignment of `size` is asserted by `shrinkLeafNode` and `growNode`. |
| 666 | _, const old_size = ni.location(mf).resolve(mf); | 687 | _, const old_size = ni.location(mf).resolve(mf); |
| ... | @@ -680,17 +701,12 @@ pub const Node = extern struct { | ... | @@ -680,17 +701,12 @@ pub const Node = extern struct { |
| 680 | /// If the node's current offset or size is not sufficiently aligned, it will be moved | 701 | /// If the node's current offset or size is not sufficiently aligned, it will be moved |
| 681 | /// and/or resized to match the new alignment. The node's size may be increased by any | 702 | /// and/or resized to match the new alignment. The node's size may be increased by any |
| 682 | /// amount, as if `ensureMinimumSize` were used. | 703 | /// amount, as if `ensureMinimumSize` were used. |
| 683 | pub fn realign( | 704 | pub fn realign(ni: Node.Index, gpa: Allocator, mf: *MappedFile, new_alignment: Alignment) Error!void { |
| 684 | ni: Node.Index, | ||
| 685 | mf: *MappedFile, | ||
| 686 | gpa: Allocator, | ||
| 687 | new_alignment: Alignment, | ||
| 688 | ) Error!void { | ||
| 689 | try mf.realignNode(gpa, ni, new_alignment); | 705 | try mf.realignNode(gpa, ni, new_alignment); |
| 690 | mf.updateWriters(); | 706 | mf.updateWriters(); |
| 691 | } | 707 | } |
| 692 | 708 | ||
| 693 | pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: Allocator, w: *Writer) void { | 709 | pub fn writer(ni: Node.Index, gpa: Allocator, mf: *MappedFile, w: *Writer) void { |
| 694 | w.* = .{ | 710 | w.* = .{ |
| 695 | .gpa = gpa, | 711 | .gpa = gpa, |
| 696 | .mf = mf, | 712 | .mf = mf, |
| ... | @@ -820,7 +836,7 @@ pub const Node = extern struct { | ... | @@ -820,7 +836,7 @@ pub const Node = extern struct { |
| 820 | ) Io.Writer.Error!void { | 836 | ) Io.Writer.Error!void { |
| 821 | _ = preserve; | 837 | _ = preserve; |
| 822 | const w: *Writer = @fieldParentPtr("interface", interface); | 838 | const w: *Writer = @fieldParentPtr("interface", interface); |
| 823 | w.ni.ensureMinimumSize(w.mf, w.gpa, interface.end + unused_capacity) catch |err| { | 839 | w.ni.ensureMinimumSize(w.gpa, w.mf, interface.end + unused_capacity) catch |err| { |
| 824 | w.err = err; | 840 | w.err = err; |
| 825 | return error.WriteFailed; | 841 | return error.WriteFailed; |
| 826 | }; | 842 | }; |
| ... | @@ -992,7 +1008,7 @@ fn shrinkLeafNode( | ... | @@ -992,7 +1008,7 @@ fn shrinkLeafNode( |
| 992 | }, | 1008 | }, |
| 993 | }; | 1009 | }; |
| 994 | try mf.ensureTotalCapacityPrecise(@intCast(new_size)); | 1010 | try mf.ensureTotalCapacityPrecise(@intCast(new_size)); |
| 995 | try ni.setLocation(mf, gpa, old_offset, new_size); | 1011 | try ni.setLocation(gpa, mf, old_offset, new_size); |
| 996 | return; | 1012 | return; |
| 997 | }; | 1013 | }; |
| 998 | 1014 | ||
| ... | @@ -1000,7 +1016,7 @@ fn shrinkLeafNode( | ... | @@ -1000,7 +1016,7 @@ fn shrinkLeafNode( |
| 1000 | .header => { | 1016 | .header => { |
| 1001 | const shift = old_size - new_size; | 1017 | const shift = old_size - new_size; |
| 1002 | 1018 | ||
| 1003 | try ni.setLocation(mf, gpa, old_offset, new_size); | 1019 | try ni.setLocation(gpa, mf, old_offset, new_size); |
| 1004 | 1020 | ||
| 1005 | // We need to shift backwards all header nodes following us. | 1021 | // We need to shift backwards all header nodes following us. |
| 1006 | const next_header_ni = ni.next(mf).unwrap() orelse return; | 1022 | const next_header_ni = ni.next(mf).unwrap() orelse return; |
| ... | @@ -1009,7 +1025,7 @@ fn shrinkLeafNode( | ... | @@ -1009,7 +1025,7 @@ fn shrinkLeafNode( |
| 1009 | var header_ni = next_header_ni; | 1025 | var header_ni = next_header_ni; |
| 1010 | while (true) { | 1026 | while (true) { |
| 1011 | const old_header_off, const old_header_size = header_ni.location(mf).resolve(mf); | 1027 | const old_header_off, const old_header_size = header_ni.location(mf).resolve(mf); |
| 1012 | try header_ni.setLocation(mf, gpa, old_header_off - shift, old_header_size); | 1028 | try header_ni.setLocation(gpa, mf, old_header_off - shift, old_header_size); |
| 1013 | 1029 | ||
| 1014 | const next_ni = header_ni.next(mf).unwrap() orelse break; | 1030 | const next_ni = header_ni.next(mf).unwrap() orelse break; |
| 1015 | if (next_ni.position(mf) != .header) break; | 1031 | if (next_ni.position(mf) != .header) break; |
| ... | @@ -1034,13 +1050,13 @@ fn shrinkLeafNode( | ... | @@ -1034,13 +1050,13 @@ fn shrinkLeafNode( |
| 1034 | ); | 1050 | ); |
| 1035 | }, | 1051 | }, |
| 1036 | .floating => { | 1052 | .floating => { |
| 1037 | try ni.setLocation(mf, gpa, old_offset, new_size); | 1053 | try ni.setLocation(gpa, mf, old_offset, new_size); |
| 1038 | }, | 1054 | }, |
| 1039 | .footer => { | 1055 | .footer => { |
| 1040 | const shift = old_size - new_size; | 1056 | const shift = old_size - new_size; |
| 1041 | 1057 | ||
| 1042 | const new_offset = old_offset + shift; | 1058 | const new_offset = old_offset + shift; |
| 1043 | try ni.setLocation(mf, gpa, new_offset, new_size); | 1059 | try ni.setLocation(gpa, mf, new_offset, new_size); |
| 1044 | 1060 | ||
| 1045 | const prev_footers_size = prev_footers_size: { | 1061 | const prev_footers_size = prev_footers_size: { |
| 1046 | // We need to shift forwards all footer nodes preceding us. | 1062 | // We need to shift forwards all footer nodes preceding us. |
| ... | @@ -1054,7 +1070,7 @@ fn shrinkLeafNode( | ... | @@ -1054,7 +1070,7 @@ fn shrinkLeafNode( |
| 1054 | var footer_ni = prev_footer_ni; | 1070 | var footer_ni = prev_footer_ni; |
| 1055 | while (true) { | 1071 | while (true) { |
| 1056 | const old_footer_off, const old_footer_size = footer_ni.location(mf).resolve(mf); | 1072 | const old_footer_off, const old_footer_size = footer_ni.location(mf).resolve(mf); |
| 1057 | try footer_ni.setLocation(mf, gpa, old_footer_off + shift, old_footer_size); | 1073 | try footer_ni.setLocation(gpa, mf, old_footer_off + shift, old_footer_size); |
| 1058 | 1074 | ||
| 1059 | const prev_ni = footer_ni.prev(mf).unwrap() orelse break; | 1075 | const prev_ni = footer_ni.prev(mf).unwrap() orelse break; |
| 1060 | if (prev_ni.position(mf) != .footer) break; | 1076 | if (prev_ni.position(mf) != .footer) break; |
| ... | @@ -1137,7 +1153,7 @@ fn growNode( | ... | @@ -1137,7 +1153,7 @@ fn growNode( |
| 1137 | }, | 1153 | }, |
| 1138 | }; | 1154 | }; |
| 1139 | try mf.ensureTotalCapacityPrecise(@intCast(new_size)); | 1155 | try mf.ensureTotalCapacityPrecise(@intCast(new_size)); |
| 1140 | try ni.setLocation(mf, gpa, old_offset, new_size); | 1156 | try ni.setLocation(gpa, mf, old_offset, new_size); |
| 1141 | if (grow_options.move_footers) { | 1157 | if (grow_options.move_footers) { |
| 1142 | // We need to move any footers to be at the *new* end of the file. | 1158 | // We need to move any footers to be at the *new* end of the file. |
| 1143 | if (ni.firstFooter(mf).unwrap()) |first_footer_ni| { | 1159 | if (ni.firstFooter(mf).unwrap()) |first_footer_ni| { |
| ... | @@ -1152,7 +1168,7 @@ fn growNode( | ... | @@ -1152,7 +1168,7 @@ fn growNode( |
| 1152 | var cur_ni = first_footer_ni; | 1168 | var cur_ni = first_footer_ni; |
| 1153 | while (true) { | 1169 | while (true) { |
| 1154 | const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf); | 1170 | const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf); |
| 1155 | try cur_ni.setLocation(mf, gpa, old_footer_offset + (new_size - old_size), footer_size); | 1171 | try cur_ni.setLocation(gpa, mf, old_footer_offset + (new_size - old_size), footer_size); |
| 1156 | cur_ni = cur_ni.next(mf).unwrap() orelse break; | 1172 | cur_ni = cur_ni.next(mf).unwrap() orelse break; |
| 1157 | } | 1173 | } |
| 1158 | } | 1174 | } |
| ... | @@ -1211,8 +1227,8 @@ fn growNode( | ... | @@ -1211,8 +1227,8 @@ fn growNode( |
| 1211 | while (true) { | 1227 | while (true) { |
| 1212 | const old_sub_footer_offset, const sub_footer_size = cur_ni.location(mf).resolve(mf); | 1228 | const old_sub_footer_offset, const sub_footer_size = cur_ni.location(mf).resolve(mf); |
| 1213 | try cur_ni.setLocation( | 1229 | try cur_ni.setLocation( |
| 1214 | mf, | ||
| 1215 | gpa, | 1230 | gpa, |
| 1231 | mf, | ||
| 1216 | old_sub_footer_offset + (new_size - old_size), | 1232 | old_sub_footer_offset + (new_size - old_size), |
| 1217 | sub_footer_size, | 1233 | sub_footer_size, |
| 1218 | ); | 1234 | ); |
| ... | @@ -1227,8 +1243,8 @@ fn growNode( | ... | @@ -1227,8 +1243,8 @@ fn growNode( |
| 1227 | assert(moved_header_ni.position(mf) == .header); | 1243 | assert(moved_header_ni.position(mf) == .header); |
| 1228 | const moved_header_offset, const moved_header_size = moved_header_ni.location(mf).resolve(mf); | 1244 | const moved_header_offset, const moved_header_size = moved_header_ni.location(mf).resolve(mf); |
| 1229 | try moved_header_ni.setLocation( | 1245 | try moved_header_ni.setLocation( |
| 1230 | mf, | ||
| 1231 | gpa, | 1246 | gpa, |
| 1247 | mf, | ||
| 1232 | moved_header_offset - old_size + new_size, | 1248 | moved_header_offset - old_size + new_size, |
| 1233 | moved_header_size, | 1249 | moved_header_size, |
| 1234 | ); | 1250 | ); |
| ... | @@ -1237,7 +1253,7 @@ fn growNode( | ... | @@ -1237,7 +1253,7 @@ fn growNode( |
| 1237 | } | 1253 | } |
| 1238 | 1254 | ||
| 1239 | // Finally, update our own size: | 1255 | // Finally, update our own size: |
| 1240 | try ni.setLocation(mf, gpa, old_offset, new_size); | 1256 | try ni.setLocation(gpa, mf, old_offset, new_size); |
| 1241 | return; | 1257 | return; |
| 1242 | }, | 1258 | }, |
| 1243 | .floating => { | 1259 | .floating => { |
| ... | @@ -1365,8 +1381,8 @@ fn growNode( | ... | @@ -1365,8 +1381,8 @@ fn growNode( |
| 1365 | 1381 | ||
| 1366 | // Update our own offset and size: | 1382 | // Update our own offset and size: |
| 1367 | try ni.setLocation( | 1383 | try ni.setLocation( |
| 1368 | mf, | ||
| 1369 | gpa, | 1384 | gpa, |
| 1385 | mf, | ||
| 1370 | node.location().resolve(mf)[0] - shift, | 1386 | node.location().resolve(mf)[0] - shift, |
| 1371 | new_size, | 1387 | new_size, |
| 1372 | ); | 1388 | ); |
| ... | @@ -1377,7 +1393,7 @@ fn growNode( | ... | @@ -1377,7 +1393,7 @@ fn growNode( |
| 1377 | var footer_oni = first_sub_footer_oni; | 1393 | var footer_oni = first_sub_footer_oni; |
| 1378 | while (footer_oni.unwrap()) |footer_ni| : (footer_oni = footer_ni.next(mf)) { | 1394 | while (footer_oni.unwrap()) |footer_ni| : (footer_oni = footer_ni.next(mf)) { |
| 1379 | const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf); | 1395 | const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf); |
| 1380 | try footer_ni.setLocation(mf, gpa, old_footer_offset + shift, footer_size); | 1396 | try footer_ni.setLocation(gpa, mf, old_footer_offset + shift, footer_size); |
| 1381 | } | 1397 | } |
| 1382 | } | 1398 | } |
| 1383 | 1399 | ||
| ... | @@ -1392,7 +1408,7 @@ fn growNode( | ... | @@ -1392,7 +1408,7 @@ fn growNode( |
| 1392 | while (footer_ni != ni) : (footer_ni = footer_ni.next(mf).unwrap().?) { | 1408 | while (footer_ni != ni) : (footer_ni = footer_ni.next(mf).unwrap().?) { |
| 1393 | moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content; | 1409 | moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content; |
| 1394 | const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf); | 1410 | const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf); |
| 1395 | try footer_ni.setLocation(mf, gpa, old_footer_offset - shift, footer_size); | 1411 | try footer_ni.setLocation(gpa, mf, old_footer_offset - shift, footer_size); |
| 1396 | } | 1412 | } |
| 1397 | } | 1413 | } |
| 1398 | 1414 | ||
| ... | @@ -1444,8 +1460,8 @@ fn growNode( | ... | @@ -1444,8 +1460,8 @@ fn growNode( |
| 1444 | } | 1460 | } |
| 1445 | 1461 | ||
| 1446 | try ni.setLocation( | 1462 | try ni.setLocation( |
| 1447 | mf, | ||
| 1448 | gpa, | 1463 | gpa, |
| 1464 | mf, | ||
| 1449 | node.location().resolve(mf)[0], | 1465 | node.location().resolve(mf)[0], |
| 1450 | actual_new_size, | 1466 | actual_new_size, |
| 1451 | ); | 1467 | ); |
| ... | @@ -1461,7 +1477,7 @@ fn growNode( | ... | @@ -1461,7 +1477,7 @@ fn growNode( |
| 1461 | assert(footer_ni.position(mf) == .footer); | 1477 | assert(footer_ni.position(mf) == .footer); |
| 1462 | moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content; | 1478 | moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content; |
| 1463 | const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf); | 1479 | const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf); |
| 1464 | try footer_ni.setLocation(mf, gpa, footer_old_offset + shift, footer_size); | 1480 | try footer_ni.setLocation(gpa, mf, footer_old_offset + shift, footer_size); |
| 1465 | } | 1481 | } |
| 1466 | } | 1482 | } |
| 1467 | 1483 | ||
| ... | @@ -1472,7 +1488,7 @@ fn growNode( | ... | @@ -1472,7 +1488,7 @@ fn growNode( |
| 1472 | assert(footer_ni.position(mf) == .footer); | 1488 | assert(footer_ni.position(mf) == .footer); |
| 1473 | moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content; | 1489 | moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content; |
| 1474 | const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf); | 1490 | const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf); |
| 1475 | try footer_ni.setLocation(mf, gpa, footer_old_offset + shift, footer_size); | 1491 | try footer_ni.setLocation(gpa, mf, footer_old_offset + shift, footer_size); |
| 1476 | } | 1492 | } |
| 1477 | } | 1493 | } |
| 1478 | 1494 | ||
| ... | @@ -1544,7 +1560,7 @@ fn growFloatingNodeWithAlignment( | ... | @@ -1544,7 +1560,7 @@ fn growFloatingNodeWithAlignment( |
| 1544 | break :grow_in_place; // the parent is not big enough | 1560 | break :grow_in_place; // the parent is not big enough |
| 1545 | } | 1561 | } |
| 1546 | // Great, we can grow this node without changing its offset or moving any siblings. | 1562 | // Great, we can grow this node without changing its offset or moving any siblings. |
| 1547 | try ni.setLocation(mf, gpa, old_offset, new_size); | 1563 | try ni.setLocation(gpa, mf, old_offset, new_size); |
| 1548 | if (grow_options.move_footers) { | 1564 | if (grow_options.move_footers) { |
| 1549 | // If we have any footers, we need to move them to the end of our new size, and update | 1565 | // If we have any footers, we need to move them to the end of our new size, and update |
| 1550 | // their offsets accordingly. | 1566 | // their offsets accordingly. |
| ... | @@ -1554,7 +1570,7 @@ fn growFloatingNodeWithAlignment( | ... | @@ -1554,7 +1570,7 @@ fn growFloatingNodeWithAlignment( |
| 1554 | while (true) { | 1570 | while (true) { |
| 1555 | footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content; | 1571 | footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content; |
| 1556 | const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf); | 1572 | const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf); |
| 1557 | try cur_ni.setLocation(mf, gpa, old_footer_offset + (new_size - old_size), footer_size); | 1573 | try cur_ni.setLocation(gpa, mf, old_footer_offset + (new_size - old_size), footer_size); |
| 1558 | cur_ni = cur_ni.next(mf).unwrap() orelse break; | 1574 | cur_ni = cur_ni.next(mf).unwrap() orelse break; |
| 1559 | } | 1575 | } |
| 1560 | if (footers_have_content) { | 1576 | if (footers_have_content) { |
| ... | @@ -1691,7 +1707,7 @@ fn growFloatingNodeWithAlignment( | ... | @@ -1691,7 +1707,7 @@ fn growFloatingNodeWithAlignment( |
| 1691 | footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content; | 1707 | footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content; |
| 1692 | const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf); | 1708 | const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf); |
| 1693 | // Our footers' offsets must change to be at the end of our new size. | 1709 | // Our footers' offsets must change to be at the end of our new size. |
| 1694 | try cur_ni.setLocation(mf, gpa, old_footer_offset + (new_size - old_size), footer_size); | 1710 | try cur_ni.setLocation(gpa, mf, old_footer_offset + (new_size - old_size), footer_size); |
| 1695 | cur_ni = cur_ni.next(mf).unwrap() orelse break; | 1711 | cur_ni = cur_ni.next(mf).unwrap() orelse break; |
| 1696 | } | 1712 | } |
| 1697 | 1713 | ||
| ... | @@ -1718,7 +1734,7 @@ fn growFloatingNodeWithAlignment( | ... | @@ -1718,7 +1734,7 @@ fn growFloatingNodeWithAlignment( |
| 1718 | assert(!footers_have_content); | 1734 | assert(!footers_have_content); |
| 1719 | } | 1735 | } |
| 1720 | 1736 | ||
| 1721 | try ni.setLocation(mf, gpa, new_loc.offset, new_size); | 1737 | try ni.setLocation(gpa, mf, new_loc.offset, new_size); |
| 1722 | 1738 | ||
| 1723 | if (new_loc.prev != ni.toOptional()) { | 1739 | if (new_loc.prev != ni.toOptional()) { |
| 1724 | // We're potentially in a different place in `parent_ni`'s child list, so remove and re-add ourselves. | 1740 | // We're potentially in a different place in `parent_ni`'s child list, so remove and re-add ourselves. |
| ... | @@ -1918,11 +1934,11 @@ fn growNodeViaInsertRange( | ... | @@ -1918,11 +1934,11 @@ fn growNodeViaInsertRange( |
| 1918 | if (cur_ni == .root) { | 1934 | if (cur_ni == .root) { |
| 1919 | try mf.ensureTotalCapacityPrecise(@intCast(this_old_size + range_size)); | 1935 | try mf.ensureTotalCapacityPrecise(@intCast(this_old_size + range_size)); |
| 1920 | } | 1936 | } |
| 1921 | try cur_ni.setLocation(mf, gpa, this_offset, this_old_size + range_size); | 1937 | try cur_ni.setLocation(gpa, mf, this_offset, this_old_size + range_size); |
| 1922 | 1938 | ||
| 1923 | while (cur_ni.next(mf).unwrap()) |next_ni| { | 1939 | while (cur_ni.next(mf).unwrap()) |next_ni| { |
| 1924 | const next_old_offset, const next_size = next_ni.location(mf).resolve(mf); | 1940 | const next_old_offset, const next_size = next_ni.location(mf).resolve(mf); |
| 1925 | try next_ni.setLocation(mf, gpa, next_old_offset + range_size, next_size); | 1941 | try next_ni.setLocation(gpa, mf, next_old_offset + range_size, next_size); |
| 1926 | cur_ni = next_ni; | 1942 | cur_ni = next_ni; |
| 1927 | } | 1943 | } |
| 1928 | 1944 | ||
| ... | @@ -1935,7 +1951,7 @@ fn growNodeViaInsertRange( | ... | @@ -1935,7 +1951,7 @@ fn growNodeViaInsertRange( |
| 1935 | var footer_ni = first_footer_ni; | 1951 | var footer_ni = first_footer_ni; |
| 1936 | while (true) { | 1952 | while (true) { |
| 1937 | const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf); | 1953 | const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf); |
| 1938 | try footer_ni.setLocation(mf, gpa, old_footer_offset + range_size, footer_size); | 1954 | try footer_ni.setLocation(gpa, mf, old_footer_offset + range_size, footer_size); |
| 1939 | footer_ni = footer_ni.next(mf).unwrap() orelse break; | 1955 | footer_ni = footer_ni.next(mf).unwrap() orelse break; |
| 1940 | } | 1956 | } |
| 1941 | } | 1957 | } |
| ... | @@ -2103,7 +2119,7 @@ fn ensureAdditionalHeaderCapacity( | ... | @@ -2103,7 +2119,7 @@ fn ensureAdditionalHeaderCapacity( |
| 2103 | const old_offset, const old_size = cur_ni.location(mf).resolve(mf); | 2119 | const old_offset, const old_size = cur_ni.location(mf).resolve(mf); |
| 2104 | const new_offset = old_offset - moving_offset + dest_offset; | 2120 | const new_offset = old_offset - moving_offset + dest_offset; |
| 2105 | assert(cur_ni.alignment(mf).check(new_offset)); | 2121 | assert(cur_ni.alignment(mf).check(new_offset)); |
| 2106 | try cur_ni.setLocation(mf, gpa, new_offset, old_size); | 2122 | try cur_ni.setLocation(gpa, mf, new_offset, old_size); |
| 2107 | if (cur_ni == last_moving_ni) break; | 2123 | if (cur_ni == last_moving_ni) break; |
| 2108 | cur_ni = cur_ni.next(mf).unwrap().?; | 2124 | cur_ni = cur_ni.next(mf).unwrap().?; |
| 2109 | } | 2125 | } |
| ... | @@ -2146,7 +2162,7 @@ fn removeNodesFromChildList( | ... | @@ -2146,7 +2162,7 @@ fn removeNodesFromChildList( |
| 2146 | 2162 | ||
| 2147 | if (prev_oni.unwrap()) |prev_ni| { | 2163 | if (prev_oni.unwrap()) |prev_ni| { |
| 2148 | assert(prev_ni.next(mf).unwrap().? == first_remove_ni); | 2164 | assert(prev_ni.next(mf).unwrap().? == first_remove_ni); |
| 2149 | try prev_ni.setNext(gpa, next_oni, mf); | 2165 | try prev_ni.setNext(gpa, mf, next_oni); |
| 2150 | } else { | 2166 | } else { |
| 2151 | assert(parent_ni.first(mf).unwrap().? == first_remove_ni); | 2167 | assert(parent_ni.first(mf).unwrap().? == first_remove_ni); |
| 2152 | parent_ni.get(mf).first = next_oni; | 2168 | parent_ni.get(mf).first = next_oni; |
| ... | @@ -2185,11 +2201,11 @@ fn addNodesToChildListBefore( | ... | @@ -2185,11 +2201,11 @@ fn addNodesToChildListBefore( |
| 2185 | }; | 2201 | }; |
| 2186 | 2202 | ||
| 2187 | first_add_ni.get(mf).prev = prev_oni; | 2203 | first_add_ni.get(mf).prev = prev_oni; |
| 2188 | try last_add_ni.setNext(gpa, next_oni, mf); | 2204 | try last_add_ni.setNext(gpa, mf, next_oni); |
| 2189 | 2205 | ||
| 2190 | if (prev_oni.unwrap()) |prev_ni| { | 2206 | if (prev_oni.unwrap()) |prev_ni| { |
| 2191 | assert(prev_ni.next(mf) == next_oni); | 2207 | assert(prev_ni.next(mf) == next_oni); |
| 2192 | try prev_ni.setNext(gpa, .wrap(first_add_ni), mf); | 2208 | try prev_ni.setNext(gpa, mf, .wrap(first_add_ni)); |
| 2193 | } else { | 2209 | } else { |
| 2194 | assert(parent_ni.first(mf) == next_oni); | 2210 | assert(parent_ni.first(mf) == next_oni); |
| 2195 | parent_ni.get(mf).first = .wrap(first_add_ni); | 2211 | parent_ni.get(mf).first = .wrap(first_add_ni); |
| ... | @@ -2630,7 +2646,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { | ... | @@ -2630,7 +2646,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { |
| 2630 | for (1..n) |_| cur_ni = cur_ni.next(&mf).unwrap().?; | 2646 | for (1..n) |_| cur_ni = cur_ni.next(&mf).unwrap().?; |
| 2631 | break :prev_oni .wrap(cur_ni); | 2647 | break :prev_oni .wrap(cur_ni); |
| 2632 | }; | 2648 | }; |
| 2633 | const new_ni = try parent_ni.addHeaderChildAfter(&mf, gpa, prev_oni, .{ | 2649 | const new_ni = try parent_ni.addHeaderChildAfter(gpa, &mf, prev_oni, .{ |
| 2634 | .size = size, | 2650 | .size = size, |
| 2635 | .alignment = alignment, | 2651 | .alignment = alignment, |
| 2636 | }); | 2652 | }); |
| ... | @@ -2638,7 +2654,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { | ... | @@ -2638,7 +2654,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { |
| 2638 | break :new_ni new_ni; | 2654 | break :new_ni new_ni; |
| 2639 | }, | 2655 | }, |
| 2640 | 2656 | ||
| 2641 | .floating => try parent_ni.addFloatingChild(&mf, gpa, .{ | 2657 | .floating => try parent_ni.addFloatingChild(gpa, &mf, .{ |
| 2642 | .size = size, | 2658 | .size = size, |
| 2643 | .alignment = alignment, | 2659 | .alignment = alignment, |
| 2644 | }), | 2660 | }), |
| ... | @@ -2652,7 +2668,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { | ... | @@ -2652,7 +2668,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { |
| 2652 | for (1..n) |_| cur_ni = cur_ni.prev(&mf).unwrap().?; | 2668 | for (1..n) |_| cur_ni = cur_ni.prev(&mf).unwrap().?; |
| 2653 | break :next_oni .wrap(cur_ni); | 2669 | break :next_oni .wrap(cur_ni); |
| 2654 | }; | 2670 | }; |
| 2655 | const new_ni = try parent_ni.addFooterChildBefore(&mf, gpa, next_oni, .{ | 2671 | const new_ni = try parent_ni.addFooterChildBefore(gpa, &mf, next_oni, .{ |
| 2656 | .size = size, | 2672 | .size = size, |
| 2657 | .alignment = alignment, | 2673 | .alignment = alignment, |
| 2658 | }); | 2674 | }); |
| ... | @@ -2686,13 +2702,13 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { | ... | @@ -2686,13 +2702,13 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { |
| 2686 | if (ni.first(&mf) == .none and smith.value(bool)) { | 2702 | if (ni.first(&mf) == .none and smith.value(bool)) { |
| 2687 | // Since this is a leaf node, we can use `resizeLeaf`. | 2703 | // Since this is a leaf node, we can use `resizeLeaf`. |
| 2688 | const new_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights)); | 2704 | const new_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights)); |
| 2689 | try ni.resizeLeaf(&mf, gpa, new_size); | 2705 | try ni.resizeLeaf(gpa, &mf, new_size); |
| 2690 | if (new_size == 0) { | 2706 | if (new_size == 0) { |
| 2691 | node_info.initialized = false; | 2707 | node_info.initialized = false; |
| 2692 | } | 2708 | } |
| 2693 | } else { | 2709 | } else { |
| 2694 | const min_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights)); | 2710 | const min_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights)); |
| 2695 | try ni.ensureMinimumSize(&mf, gpa, min_size); | 2711 | try ni.ensureMinimumSize(gpa, &mf, min_size); |
| 2696 | } | 2712 | } |
| 2697 | 2713 | ||
| 2698 | if (ni.first(&mf) == .none) { | 2714 | if (ni.first(&mf) == .none) { |
| ... | @@ -2718,7 +2734,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { | ... | @@ -2718,7 +2734,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void { |
| 2718 | const new_alignment = smith.valueWeighted(Alignment, alignment_weights); | 2734 | const new_alignment = smith.valueWeighted(Alignment, alignment_weights); |
| 2719 | if (new_alignment.compare(.gt, ni.alignment(&mf))) { | 2735 | if (new_alignment.compare(.gt, ni.alignment(&mf))) { |
| 2720 | _, const old_size = ni.location(&mf).resolve(&mf); | 2736 | _, const old_size = ni.location(&mf).resolve(&mf); |
| 2721 | try ni.realign(&mf, gpa, new_alignment); | 2737 | try ni.realign(gpa, &mf, new_alignment); |
| 2722 | if (ni.first(&mf) == .none and nodes.get(ni).?.initialized) { | 2738 | if (ni.first(&mf) == .none and nodes.get(ni).?.initialized) { |
| 2723 | const slice = ni.slice(&mf); | 2739 | const slice = ni.slice(&mf); |
| 2724 | @memmove(slice[slice.len - 4 ..][0..4], slice[old_size - 4 ..][0..4]); | 2740 | @memmove(slice[slice.len - 4 ..][0..4], slice[old_size - 4 ..][0..4]); |
src/link/Spork8.zig+3-4| ... | @@ -18,7 +18,6 @@ const Mir = @import("../codegen/spork8/Mir.zig"); | ... | @@ -18,7 +18,6 @@ const Mir = @import("../codegen/spork8/Mir.zig"); |
| 18 | const link = @import("../link.zig"); | 18 | const link = @import("../link.zig"); |
| 19 | const Compilation = @import("../Compilation.zig"); | 19 | const Compilation = @import("../Compilation.zig"); |
| 20 | const Liveness = @import("../Air/Liveness.zig"); | 20 | const Liveness = @import("../Air/Liveness.zig"); |
| 21 | const dev = @import("../dev.zig"); | ||
| 22 | const Value = @import("../Value.zig"); | 21 | const Value = @import("../Value.zig"); |
| 23 | 22 | ||
| 24 | base: link.File, | 23 | base: link.File, |
| ... | @@ -89,7 +88,6 @@ pub fn updateFunc( | ... | @@ -89,7 +88,6 @@ pub fn updateFunc( |
| 89 | func_index: InternPool.Index, | 88 | func_index: InternPool.Index, |
| 90 | any_mir: *const codegen.AnyMir, | 89 | any_mir: *const codegen.AnyMir, |
| 91 | ) !void { | 90 | ) !void { |
| 92 | dev.check(.spork8_backend); | ||
| 93 | // This linker implementation only works with `std.lang.CompilerBackend.zsf_spork8`. | 91 | // This linker implementation only works with `std.lang.CompilerBackend.zsf_spork8`. |
| 94 | const mir = &any_mir.spork8; | 92 | const mir = &any_mir.spork8; |
| 95 | const zcu = pt.zcu; | 93 | const zcu = pt.zcu; |
| ... | @@ -168,10 +166,11 @@ pub fn updateNav(spork8: *Spork8, pt: Zcu.PerThread, nav_index: InternPool.Nav.I | ... | @@ -168,10 +166,11 @@ pub fn updateNav(spork8: *Spork8, pt: Zcu.PerThread, nav_index: InternPool.Nav.I |
| 168 | log.debug("updateNav {f}", .{nav.fqn.fmt(ip)}); | 166 | log.debug("updateNav {f}", .{nav.fqn.fmt(ip)}); |
| 169 | } | 167 | } |
| 170 | 168 | ||
| 171 | pub fn updateLineNumber(spork8: *Spork8, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { | 169 | pub fn updateLineNumber(spork8: *Spork8, pt: Zcu.PerThread, inst: InternPool.TrackedInst.Index, line: u32) !void { |
| 172 | _ = spork8; | 170 | _ = spork8; |
| 173 | _ = pt; | 171 | _ = pt; |
| 174 | _ = ti_id; | 172 | _ = inst; |
| 173 | _ = line; | ||
| 175 | } | 174 | } |
| 176 | 175 | ||
| 177 | pub fn deleteExport( | 176 | pub fn deleteExport( |
src/link/Wasm.zig+4-15| ... | @@ -38,7 +38,6 @@ const Dwarf = @import("Dwarf.zig"); | ... | @@ -38,7 +38,6 @@ const Dwarf = @import("Dwarf.zig"); |
| 38 | const InternPool = @import("../InternPool.zig"); | 38 | const InternPool = @import("../InternPool.zig"); |
| 39 | const Zcu = @import("../Zcu.zig"); | 39 | const Zcu = @import("../Zcu.zig"); |
| 40 | const codegen = @import("../codegen.zig"); | 40 | const codegen = @import("../codegen.zig"); |
| 41 | const dev = @import("../dev.zig"); | ||
| 42 | const link = @import("../link.zig"); | 41 | const link = @import("../link.zig"); |
| 43 | const trace = @import("../tracy.zig").trace; | 42 | const trace = @import("../tracy.zig").trace; |
| 44 | const wasi_libc = @import("../libs/wasi_libc.zig"); | 43 | const wasi_libc = @import("../libs/wasi_libc.zig"); |
| ... | @@ -1374,11 +1373,7 @@ pub const GlobalImport = extern struct { | ... | @@ -1374,11 +1373,7 @@ pub const GlobalImport = extern struct { |
| 1374 | .__tls_base => @tagName(Unpacked.__tls_base), | 1373 | .__tls_base => @tagName(Unpacked.__tls_base), |
| 1375 | .__tls_size => @tagName(Unpacked.__tls_size), | 1374 | .__tls_size => @tagName(Unpacked.__tls_size), |
| 1376 | .object_global => |i| i.name(wasm).slice(wasm), | 1375 | .object_global => |i| i.name(wasm).slice(wasm), |
| 1377 | inline .uav_obj, .uav_exe => |i| std.mem.print( | 1376 | inline .uav_obj, .uav_exe => |i| std.mem.print(buf, "__anon_{d}", .{i}) catch unreachable, |
| 1378 | buf, | ||
| 1379 | "__anon_{d}", | ||
| 1380 | .{@backingInt(i.key(wasm).*)}, | ||
| 1381 | ) catch unreachable, | ||
| 1382 | .nav_obj => |i| i.name(wasm), | 1377 | .nav_obj => |i| i.name(wasm), |
| 1383 | .nav_exe => |i| i.name(wasm), | 1378 | .nav_exe => |i| i.name(wasm), |
| 1384 | }; | 1379 | }; |
| ... | @@ -1997,11 +1992,7 @@ pub const ObjectDataImport = extern struct { | ... | @@ -1997,11 +1992,7 @@ pub const ObjectDataImport = extern struct { |
| 1997 | .__heap_base => @tagName(.__heap_base), | 1992 | .__heap_base => @tagName(.__heap_base), |
| 1998 | .__heap_end => @tagName(.__heap_end), | 1993 | .__heap_end => @tagName(.__heap_end), |
| 1999 | .__wasm_first_page_end => @tagName(.__wasm_first_page_end), | 1994 | .__wasm_first_page_end => @tagName(.__wasm_first_page_end), |
| 2000 | inline .uav_exe, .uav_obj => |i| std.mem.print( | 1995 | inline .uav_exe, .uav_obj => |i| std.mem.print(buf, "__anon_{d}", .{i}) catch unreachable, |
| 2001 | buf, | ||
| 2002 | "__anon_{d}", | ||
| 2003 | .{@backingInt(i.key(wasm).*)}, | ||
| 2004 | ) catch unreachable, | ||
| 2005 | inline .nav_exe, .nav_obj => |i| i.name(wasm), | 1996 | inline .nav_exe, .nav_obj => |i| i.name(wasm), |
| 2006 | }; | 1997 | }; |
| 2007 | } | 1998 | } |
| ... | @@ -3583,8 +3574,6 @@ pub fn updateFunc( | ... | @@ -3583,8 +3574,6 @@ pub fn updateFunc( |
| 3583 | func_index: InternPool.Index, | 3574 | func_index: InternPool.Index, |
| 3584 | any_mir: *const codegen.AnyMir, | 3575 | any_mir: *const codegen.AnyMir, |
| 3585 | ) !void { | 3576 | ) !void { |
| 3586 | dev.check(.wasm_backend); | ||
| 3587 | |||
| 3588 | // This linker implementation only works with codegen backend `.stage2_wasm`. | 3577 | // This linker implementation only works with codegen backend `.stage2_wasm`. |
| 3589 | const mir = &any_mir.wasm; | 3578 | const mir = &any_mir.wasm; |
| 3590 | const zcu = pt.zcu; | 3579 | const zcu = pt.zcu; |
| ... | @@ -3736,11 +3725,11 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index | ... | @@ -3736,11 +3725,11 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 3736 | } | 3725 | } |
| 3737 | } | 3726 | } |
| 3738 | 3727 | ||
| 3739 | pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void { | 3728 | pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index, line: u32) link.Error!void { |
| 3740 | const comp = wasm.base.comp; | 3729 | const comp = wasm.base.comp; |
| 3741 | const diags = &comp.link_diags; | 3730 | const diags = &comp.link_diags; |
| 3742 | if (wasm.dwarf) |*dw| { | 3731 | if (wasm.dwarf) |*dw| { |
| 3743 | dw.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) { | 3732 | dw.updateLineNumber(pt.zcu, ti_id, line) catch |err| switch (err) { |
| 3744 | error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e, | 3733 | error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e, |
| 3745 | else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}), | 3734 | else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}), |
| 3746 | }; | 3735 | }; |
src/main.zig+1-1| ... | @@ -36,7 +36,7 @@ const Module = @import("Module.zig"); | ... | @@ -36,7 +36,7 @@ const Module = @import("Module.zig"); |
| 36 | 36 | ||
| 37 | test { | 37 | test { |
| 38 | _ = @import("codegen.zig"); | 38 | _ = @import("codegen.zig"); |
| 39 | _ = @import("link/MappedFile.zig"); | 39 | _ = link.MappedFile; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | const thread_stack_size = 60 << 20; | 42 | const thread_stack_size = 60 << 20; |
src/print_zir.zig+11-3| ... | @@ -1452,6 +1452,8 @@ const Writer = struct { | ... | @@ -1452,6 +1452,8 @@ const Writer = struct { |
| 1452 | self.parent_decl_node = struct_decl.src_node; | 1452 | self.parent_decl_node = struct_decl.src_node; |
| 1453 | defer self.parent_decl_node = prev_parent_decl_node; | 1453 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1454 | 1454 | ||
| 1455 | try stream.print(":{d}:{d} ", .{ struct_decl.src_line + 1, struct_decl.src_column + 1 }); | ||
| 1456 | |||
| 1455 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; | 1457 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; |
| 1456 | try stream.print("hash({x}) ", .{&fields_hash}); | 1458 | try stream.print("hash({x}) ", .{&fields_hash}); |
| 1457 | 1459 | ||
| ... | @@ -1514,6 +1516,8 @@ const Writer = struct { | ... | @@ -1514,6 +1516,8 @@ const Writer = struct { |
| 1514 | self.parent_decl_node = union_decl.src_node; | 1516 | self.parent_decl_node = union_decl.src_node; |
| 1515 | defer self.parent_decl_node = prev_parent_decl_node; | 1517 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1516 | 1518 | ||
| 1519 | try stream.print(":{d}:{d} ", .{ union_decl.src_line + 1, union_decl.src_column + 1 }); | ||
| 1520 | |||
| 1517 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; | 1521 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; |
| 1518 | try stream.print("hash({x}) ", .{&fields_hash}); | 1522 | try stream.print("hash({x}) ", .{&fields_hash}); |
| 1519 | 1523 | ||
| ... | @@ -1590,6 +1594,8 @@ const Writer = struct { | ... | @@ -1590,6 +1594,8 @@ const Writer = struct { |
| 1590 | self.parent_decl_node = enum_decl.src_node; | 1594 | self.parent_decl_node = enum_decl.src_node; |
| 1591 | defer self.parent_decl_node = prev_parent_decl_node; | 1595 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1592 | 1596 | ||
| 1597 | try stream.print(":{d}:{d} ", .{ enum_decl.src_line + 1, enum_decl.src_column + 1 }); | ||
| 1598 | |||
| 1593 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; | 1599 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; |
| 1594 | try stream.print("hash({x}) ", .{&fields_hash}); | 1600 | try stream.print("hash({x}) ", .{&fields_hash}); |
| 1595 | 1601 | ||
| ... | @@ -1637,6 +1643,8 @@ const Writer = struct { | ... | @@ -1637,6 +1643,8 @@ const Writer = struct { |
| 1637 | self.parent_decl_node = opaque_decl.src_node; | 1643 | self.parent_decl_node = opaque_decl.src_node; |
| 1638 | defer self.parent_decl_node = prev_parent_decl_node; | 1644 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1639 | 1645 | ||
| 1646 | try stream.print(":{d}:{d} ", .{ opaque_decl.src_line + 1, opaque_decl.src_column + 1 }); | ||
| 1647 | |||
| 1640 | try stream.print("{s}, ", .{@tagName(opaque_decl.name_strategy)}); | 1648 | try stream.print("{s}, ", .{@tagName(opaque_decl.name_strategy)}); |
| 1641 | try self.writeCaptures(stream, opaque_decl.captures, opaque_decl.capture_names); | 1649 | try self.writeCaptures(stream, opaque_decl.captures, opaque_decl.capture_names); |
| 1642 | try stream.writeAll(", "); | 1650 | try stream.writeAll(", "); |
| ... | @@ -2216,10 +2224,10 @@ const Writer = struct { | ... | @@ -2216,10 +2224,10 @@ const Writer = struct { |
| 2216 | try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) }); | 2224 | try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) }); |
| 2217 | }, | 2225 | }, |
| 2218 | } | 2226 | } |
| 2227 | try stream.print(":{d}:{d}", .{ decl.src_line + 1, decl.src_column + 1 }); | ||
| 2228 | |||
| 2219 | const src_hash = self.code.getAssociatedSrcHash(inst).?; | 2229 | const src_hash = self.code.getAssociatedSrcHash(inst).?; |
| 2220 | try stream.print(" line({d}) column({d}) hash({x})", .{ | 2230 | try stream.print(" hash({x})", .{&src_hash}); |
| 2221 | decl.src_line, decl.src_column, &src_hash, | ||
| 2222 | }); | ||
| 2223 | 2231 | ||
| 2224 | { | 2232 | { |
| 2225 | if (decl.type_body) |b| { | 2233 | if (decl.type_body) |b| { |
src/target.zig+5-1| ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); | ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | 4 | ||
| 5 | const dev = @import("dev.zig"); | ||
| 5 | const Type = @import("Type.zig"); | 6 | const Type = @import("Type.zig"); |
| 6 | const AddressSpace = std.lang.AddressSpace; | 7 | const AddressSpace = std.lang.AddressSpace; |
| 7 | const Alignment = @import("InternPool.zig").Alignment; | 8 | const Alignment = @import("InternPool.zig").Alignment; |
| ... | @@ -855,7 +856,10 @@ pub fn functionPointerMask(target: *const std.Target) ?u64 { | ... | @@ -855,7 +856,10 @@ pub fn functionPointerMask(target: *const std.Target) ?u64 { |
| 855 | 856 | ||
| 856 | pub fn supportsTailCall(target: *const std.Target, backend: std.lang.CompilerBackend) bool { | 857 | pub fn supportsTailCall(target: *const std.Target, backend: std.lang.CompilerBackend) bool { |
| 857 | switch (backend) { | 858 | switch (backend) { |
| 858 | .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target), | 859 | .stage2_llvm => { |
| 860 | dev.check(.llvm_backend); | ||
| 861 | return @import("codegen/llvm.zig").supportsTailCall(target); | ||
| 862 | }, | ||
| 859 | .stage2_c => return true, | 863 | .stage2_c => return true, |
| 860 | else => return false, | 864 | else => return false, |
| 861 | } | 865 | } |
test/incremental/change_reify_struct_field_type created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | fn getEnum(s: @Struct(.auto, null, &.{"field"}, &.{struct { tag: Enum }}, &.{.{}})) Enum { | ||
| 4 | return s.field.tag; | ||
| 5 | } | ||
| 6 | pub fn main(init: std.process.Init) !void { | ||
| 7 | try std.Io.File.stdout().writeStreamingAll(init.io, @tagName(getEnum(.{ .field = .{ .tag = .foo } }))); | ||
| 8 | } | ||
| 9 | const Enum = enum { foo, bar }; | ||
| 10 | const std = @import("std"); | ||
| 11 | #expect_stdout="foo" | ||
| 12 | #update=change field type | ||
| 13 | #file=main.zig | ||
| 14 | fn getEnum(s: @Struct(.auto, null, &.{"field"}, &.{Enum}, &.{.{}})) Enum { | ||
| 15 | return s.field; | ||
| 16 | } | ||
| 17 | pub fn main(init: std.process.Init) !void { | ||
| 18 | try std.Io.File.stdout().writeStreamingAll(init.io, @tagName(getEnum(.{ .field = .bar }))); | ||
| 19 | } | ||
| 20 | const Enum = enum { foo, bar }; | ||
| 21 | const std = @import("std"); | ||
| 22 | #expect_stdout="bar" | ||
test/incremental/no_change_preserves_tag_names deleted-18| ... | @@ -1,18 +0,0 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | const std = @import("std"); | ||
| 4 | var some_enum: enum { first, second } = .first; | ||
| 5 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 6 | pub fn main() !void { | ||
| 7 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | ||
| 8 | } | ||
| 9 | #expect_stdout="first" | ||
| 10 | #update=no change | ||
| 11 | #file=main.zig | ||
| 12 | const std = @import("std"); | ||
| 13 | var some_enum: enum { first, second } = .first; | ||
| 14 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 15 | pub fn main() !void { | ||
| 16 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | ||
| 17 | } | ||
| 18 | #expect_stdout="first" | ||
test/incremental/tag_name created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | const std = @import("std"); | ||
| 4 | var some_enum: enum { first, second } = .first; | ||
| 5 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 6 | pub fn main() !void { | ||
| 7 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | ||
| 8 | } | ||
| 9 | #expect_stdout="first" | ||
| 10 | #update=no change | ||
| 11 | #file=main.zig | ||
| 12 | const std = @import("std"); | ||
| 13 | var some_enum: enum { first, second } = .first; | ||
| 14 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 15 | pub fn main() !void { | ||
| 16 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | ||
| 17 | } | ||
| 18 | #expect_stdout="first" | ||
| 19 | #update=swap fields | ||
| 20 | #file=main.zig | ||
| 21 | const std = @import("std"); | ||
| 22 | var some_enum: enum { second, first } = .first; | ||
| 23 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 24 | pub fn main() !void { | ||
| 25 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | ||
| 26 | } | ||
| 27 | #expect_stdout="first" | ||
test/src/Debugger.zig+101-71| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | b: *std.Build, | 1 | b: *std.Build, |
| 2 | options: Options, | 2 | options: Options, |
| 3 | root_step: *std.Build.Step, | 3 | root_step: *std.Build.Step, |
| 4 | test_matrix: []const TestTarget, | ||
| 4 | 5 | ||
| 5 | pub const Options = struct { | 6 | pub const Options = struct { |
| 6 | test_filters: []const []const u8, | 7 | test_filters: []const []const u8, |
| ... | @@ -12,19 +13,20 @@ pub const Options = struct { | ... | @@ -12,19 +13,20 @@ pub const Options = struct { |
| 12 | skip_libc: bool, | 13 | skip_libc: bool, |
| 13 | }; | 14 | }; |
| 14 | 15 | ||
| 15 | pub const Target = struct { | 16 | pub const TestTarget = struct { |
| 16 | resolved: std.Build.ResolvedTarget, | 17 | target: std.Target.Query, |
| 17 | optimize_mode: std.builtin.Optimize = .debug, | 18 | optimize_mode: std.builtin.Optimize = .debug, |
| 18 | link_libc: ?bool = null, | 19 | link_libc: ?bool = null, |
| 19 | single_threaded: ?bool = null, | 20 | single_threaded: ?bool = null, |
| 20 | pic: ?bool = null, | 21 | pic: ?bool = null, |
| 21 | test_name_suffix: []const u8, | 22 | linker: LinkerImpl, |
| 22 | }; | 23 | }; |
| 23 | 24 | ||
| 24 | pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | 25 | pub const LinkerImpl = enum { default, old, new }; |
| 26 | |||
| 27 | pub fn addTests(db: *Debugger) void { | ||
| 25 | db.addLldbTest( | 28 | db.addLldbTest( |
| 26 | "basic", | 29 | "basic", |
| 27 | target, | ||
| 28 | &.{ | 30 | &.{ |
| 29 | .{ | 31 | .{ |
| 30 | .path = "basic.zig", | 32 | .path = "basic.zig", |
| ... | @@ -179,10 +181,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -179,10 +181,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 179 | \\(lldb) breakpoint delete --force 1 | 181 | \\(lldb) breakpoint delete --force 1 |
| 180 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 182 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 181 | }, | 183 | }, |
| 184 | .{}, | ||
| 182 | ); | 185 | ); |
| 183 | db.addLldbTest( | 186 | db.addLldbTest( |
| 184 | "identifiers", | 187 | "identifiers", |
| 185 | target, | ||
| 186 | &.{ | 188 | &.{ |
| 187 | .{ | 189 | .{ |
| 188 | .path = "identifiers.zig", | 190 | .path = "identifiers.zig", |
| ... | @@ -214,10 +216,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -214,10 +216,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 214 | \\(lldb) breakpoint delete --force 1 | 216 | \\(lldb) breakpoint delete --force 1 |
| 215 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 217 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 216 | }, | 218 | }, |
| 219 | .{}, | ||
| 217 | ); | 220 | ); |
| 218 | db.addLldbTest( | 221 | db.addLldbTest( |
| 219 | "types", | 222 | "types", |
| 220 | target, | ||
| 221 | &.{ | 223 | &.{ |
| 222 | .{ | 224 | .{ |
| 223 | .path = "types.zig", | 225 | .path = "types.zig", |
| ... | @@ -282,10 +284,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -282,10 +284,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 282 | \\(lldb) breakpoint delete --force 1 | 284 | \\(lldb) breakpoint delete --force 1 |
| 283 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 285 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 284 | }, | 286 | }, |
| 287 | .{}, | ||
| 285 | ); | 288 | ); |
| 286 | db.addLldbTest( | 289 | db.addLldbTest( |
| 287 | "pointers", | 290 | "pointers", |
| 288 | target, | ||
| 289 | &.{ | 291 | &.{ |
| 290 | .{ | 292 | .{ |
| 291 | .path = "pointers.zig", | 293 | .path = "pointers.zig", |
| ... | @@ -419,10 +421,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -419,10 +421,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 419 | \\(lldb) breakpoint delete --force 1 | 421 | \\(lldb) breakpoint delete --force 1 |
| 420 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 422 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 421 | }, | 423 | }, |
| 424 | .{}, | ||
| 422 | ); | 425 | ); |
| 423 | db.addLldbTest( | 426 | db.addLldbTest( |
| 424 | "strings", | 427 | "strings", |
| 425 | target, | ||
| 426 | &.{ | 428 | &.{ |
| 427 | .{ | 429 | .{ |
| 428 | .path = "strings.zig", | 430 | .path = "strings.zig", |
| ... | @@ -495,10 +497,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -495,10 +497,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 495 | \\(lldb) breakpoint delete --force 1 | 497 | \\(lldb) breakpoint delete --force 1 |
| 496 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 498 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 497 | }, | 499 | }, |
| 500 | .{}, | ||
| 498 | ); | 501 | ); |
| 499 | db.addLldbTest( | 502 | db.addLldbTest( |
| 500 | "enums", | 503 | "enums", |
| 501 | target, | ||
| 502 | &.{ | 504 | &.{ |
| 503 | .{ | 505 | .{ |
| 504 | .path = "enums.zig", | 506 | .path = "enums.zig", |
| ... | @@ -557,10 +559,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -557,10 +559,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 557 | \\(lldb) breakpoint delete --force 1 | 559 | \\(lldb) breakpoint delete --force 1 |
| 558 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 560 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 559 | }, | 561 | }, |
| 562 | .{ .skip_new_linker = true }, // passes, but prints errors | ||
| 560 | ); | 563 | ); |
| 561 | db.addLldbTest( | 564 | db.addLldbTest( |
| 562 | "errors", | 565 | "errors", |
| 563 | target, | ||
| 564 | &.{ | 566 | &.{ |
| 565 | .{ | 567 | .{ |
| 566 | .path = "errors.zig", | 568 | .path = "errors.zig", |
| ... | @@ -627,10 +629,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -627,10 +629,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 627 | \\(lldb) breakpoint delete --force 1 | 629 | \\(lldb) breakpoint delete --force 1 |
| 628 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 630 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 629 | }, | 631 | }, |
| 632 | .{ .skip_new_linker = true }, | ||
| 630 | ); | 633 | ); |
| 631 | db.addLldbTest( | 634 | db.addLldbTest( |
| 632 | "optionals", | 635 | "optionals", |
| 633 | target, | ||
| 634 | &.{ | 636 | &.{ |
| 635 | .{ | 637 | .{ |
| 636 | .path = "optionals.zig", | 638 | .path = "optionals.zig", |
| ... | @@ -681,10 +683,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -681,10 +683,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 681 | \\(lldb) breakpoint delete --force 2 | 683 | \\(lldb) breakpoint delete --force 2 |
| 682 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 684 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 683 | }, | 685 | }, |
| 686 | .{}, | ||
| 684 | ); | 687 | ); |
| 685 | db.addLldbTest( | 688 | db.addLldbTest( |
| 686 | "unions", | 689 | "unions", |
| 687 | target, | ||
| 688 | &.{ | 690 | &.{ |
| 689 | .{ | 691 | .{ |
| 690 | .path = "unions.zig", | 692 | .path = "unions.zig", |
| ... | @@ -766,10 +768,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -766,10 +768,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 766 | \\(lldb) breakpoint delete --force 1 | 768 | \\(lldb) breakpoint delete --force 1 |
| 767 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 769 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 768 | }, | 770 | }, |
| 771 | .{ .skip_new_linker = true }, // passes, but prints errors | ||
| 769 | ); | 772 | ); |
| 770 | db.addLldbTest( | 773 | db.addLldbTest( |
| 771 | "storage", | 774 | "storage", |
| 772 | target, | ||
| 773 | &.{ | 775 | &.{ |
| 774 | .{ | 776 | .{ |
| 775 | .path = "storage.zig", | 777 | .path = "storage.zig", |
| ... | @@ -866,10 +868,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -866,10 +868,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 866 | \\(lldb) breakpoint delete --force 1 | 868 | \\(lldb) breakpoint delete --force 1 |
| 867 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 869 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 868 | }, | 870 | }, |
| 871 | .{ .skip_new_linker = true }, | ||
| 869 | ); | 872 | ); |
| 870 | db.addLldbTest( | 873 | db.addLldbTest( |
| 871 | "if_blocks", | 874 | "if_blocks", |
| 872 | target, | ||
| 873 | &.{ | 875 | &.{ |
| 874 | .{ | 876 | .{ |
| 875 | .path = "if_blocks.zig", | 877 | .path = "if_blocks.zig", |
| ... | @@ -908,10 +910,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -908,10 +910,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 908 | \\(lldb) breakpoint delete --force 1 | 910 | \\(lldb) breakpoint delete --force 1 |
| 909 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 911 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 910 | }, | 912 | }, |
| 913 | .{}, | ||
| 911 | ); | 914 | ); |
| 912 | db.addLldbTest( | 915 | db.addLldbTest( |
| 913 | "switch_blocks", | 916 | "switch_blocks", |
| 914 | target, | ||
| 915 | &.{ | 917 | &.{ |
| 916 | .{ | 918 | .{ |
| 917 | .path = "switch_blocks.zig", | 919 | .path = "switch_blocks.zig", |
| ... | @@ -953,10 +955,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -953,10 +955,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 953 | \\(lldb) breakpoint delete --force 1 | 955 | \\(lldb) breakpoint delete --force 1 |
| 954 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 956 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 955 | }, | 957 | }, |
| 958 | .{}, | ||
| 956 | ); | 959 | ); |
| 957 | db.addLldbTest( | 960 | db.addLldbTest( |
| 958 | "step_single_stmt_loops", | 961 | "step_single_stmt_loops", |
| 959 | target, | ||
| 960 | &.{ | 962 | &.{ |
| 961 | .{ | 963 | .{ |
| 962 | .path = "step_single_stmt_loops.zig", | 964 | .path = "step_single_stmt_loops.zig", |
| ... | @@ -1371,10 +1373,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -1371,10 +1373,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 1371 | \\(lldb) frame variable --show-all-children x | 1373 | \\(lldb) frame variable --show-all-children x |
| 1372 | \\(u32) x = 12 | 1374 | \\(u32) x = 12 |
| 1373 | }, | 1375 | }, |
| 1376 | .{}, | ||
| 1374 | ); | 1377 | ); |
| 1375 | db.addLldbTest( | 1378 | db.addLldbTest( |
| 1376 | "inline_call", | 1379 | "inline_call", |
| 1377 | target, | ||
| 1378 | &.{ | 1380 | &.{ |
| 1379 | .{ | 1381 | .{ |
| 1380 | .path = "root0.zig", | 1382 | .path = "root0.zig", |
| ... | @@ -1944,10 +1946,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -1944,10 +1946,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 1944 | \\ frame #1: inline_call`m1pfi(m1pai=89) at mod1.zig:23:15 | 1946 | \\ frame #1: inline_call`m1pfi(m1pai=89) at mod1.zig:23:15 |
| 1945 | \\ frame #2: inline_call`root0.main at root0.zig:41:15 | 1947 | \\ frame #2: inline_call`root0.main at root0.zig:41:15 |
| 1946 | }, | 1948 | }, |
| 1949 | .{ .skip_new_linker = true }, | ||
| 1947 | ); | 1950 | ); |
| 1948 | db.addLldbTest( | 1951 | db.addLldbTest( |
| 1949 | "link_object", | 1952 | "link_object", |
| 1950 | target, | ||
| 1951 | &.{ | 1953 | &.{ |
| 1952 | .{ | 1954 | .{ |
| 1953 | .path = "main.zig", | 1955 | .path = "main.zig", |
| ... | @@ -1983,10 +1985,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -1983,10 +1985,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 1983 | \\(lldb) breakpoint delete --force 2 | 1985 | \\(lldb) breakpoint delete --force 2 |
| 1984 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 1986 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 1985 | }, | 1987 | }, |
| 1988 | .{}, | ||
| 1986 | ); | 1989 | ); |
| 1987 | db.addLldbTest( | 1990 | db.addLldbTest( |
| 1988 | "hash_map", | 1991 | "hash_map", |
| 1989 | target, | ||
| 1990 | &.{ | 1992 | &.{ |
| 1991 | .{ | 1993 | .{ |
| 1992 | .path = "main.zig", | 1994 | .path = "main.zig", |
| ... | @@ -2052,10 +2054,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -2052,10 +2054,10 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 2052 | \\(lldb) breakpoint delete --force 1 | 2054 | \\(lldb) breakpoint delete --force 1 |
| 2053 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 2055 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 2054 | }, | 2056 | }, |
| 2057 | .{ .skip_new_linker = true }, | ||
| 2055 | ); | 2058 | ); |
| 2056 | db.addLldbTest( | 2059 | db.addLldbTest( |
| 2057 | "multi_array_list", | 2060 | "multi_array_list", |
| 2058 | target, | ||
| 2059 | &.{ | 2061 | &.{ |
| 2060 | .{ | 2062 | .{ |
| 2061 | .path = "main.zig", | 2063 | .path = "main.zig", |
| ... | @@ -2306,22 +2308,26 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { | ... | @@ -2306,22 +2308,26 @@ pub fn addTestsForTarget(db: *Debugger, target: *const Target) void { |
| 2306 | \\(lldb) breakpoint delete --force 1 | 2308 | \\(lldb) breakpoint delete --force 1 |
| 2307 | \\1 breakpoints deleted; 0 breakpoint locations disabled. | 2309 | \\1 breakpoints deleted; 0 breakpoint locations disabled. |
| 2308 | }, | 2310 | }, |
| 2311 | .{ .skip_new_linker = true }, | ||
| 2309 | ); | 2312 | ); |
| 2310 | } | 2313 | } |
| 2311 | 2314 | ||
| 2312 | const File = struct { import: ?[]const u8 = null, path: []const u8, source: []const u8 }; | 2315 | const File = struct { import: ?[]const u8 = null, path: []const u8, source: []const u8 }; |
| 2313 | 2316 | ||
| 2317 | const TestOptions = struct { | ||
| 2318 | skip_new_linker: bool = false, | ||
| 2319 | }; | ||
| 2320 | |||
| 2314 | fn addGdbTest( | 2321 | fn addGdbTest( |
| 2315 | db: *Debugger, | 2322 | db: *Debugger, |
| 2316 | name: []const u8, | 2323 | name: []const u8, |
| 2317 | target: *const Target, | ||
| 2318 | files: []const File, | 2324 | files: []const File, |
| 2319 | commands: []const u8, | 2325 | commands: []const u8, |
| 2320 | expected_output: []const []const u8, | 2326 | expected_output: []const []const u8, |
| 2327 | options: TestOptions, | ||
| 2321 | ) void { | 2328 | ) void { |
| 2322 | db.addTest( | 2329 | db.addTest( |
| 2323 | name, | 2330 | name, |
| 2324 | target, | ||
| 2325 | files, | 2331 | files, |
| 2326 | &.{}, | 2332 | &.{}, |
| 2327 | &.{ | 2333 | &.{ |
| ... | @@ -2331,24 +2337,22 @@ fn addGdbTest( | ... | @@ -2331,24 +2337,22 @@ fn addGdbTest( |
| 2331 | }, | 2337 | }, |
| 2332 | "set remotetimeout 0", | 2338 | "set remotetimeout 0", |
| 2333 | commands, | 2339 | commands, |
| 2334 | &.{ | 2340 | &.{"--args"}, |
| 2335 | "--args", | ||
| 2336 | }, | ||
| 2337 | expected_output, | 2341 | expected_output, |
| 2342 | options, | ||
| 2338 | ); | 2343 | ); |
| 2339 | } | 2344 | } |
| 2340 | 2345 | ||
| 2341 | fn addLldbTest( | 2346 | fn addLldbTest( |
| 2342 | db: *Debugger, | 2347 | db: *Debugger, |
| 2343 | name: []const u8, | 2348 | name: []const u8, |
| 2344 | target: *const Target, | ||
| 2345 | files: []const File, | 2349 | files: []const File, |
| 2346 | commands: []const u8, | 2350 | commands: []const u8, |
| 2347 | expected_output: []const []const u8, | 2351 | expected_output: []const []const u8, |
| 2352 | options: TestOptions, | ||
| 2348 | ) void { | 2353 | ) void { |
| 2349 | db.addTest( | 2354 | db.addTest( |
| 2350 | name, | 2355 | name, |
| 2351 | target, | ||
| 2352 | files, | 2356 | files, |
| 2353 | &.{.{ "LANG", "C.UTF-8" }}, // affects output formatting | 2357 | &.{.{ "LANG", "C.UTF-8" }}, // affects output formatting |
| 2354 | &.{ | 2358 | &.{ |
| ... | @@ -2358,10 +2362,9 @@ fn addLldbTest( | ... | @@ -2358,10 +2362,9 @@ fn addLldbTest( |
| 2358 | }, | 2362 | }, |
| 2359 | "settings set plugin.process.gdb-remote.packet-timeout 0", | 2363 | "settings set plugin.process.gdb-remote.packet-timeout 0", |
| 2360 | commands, | 2364 | commands, |
| 2361 | &.{ | 2365 | &.{"--"}, |
| 2362 | "--", | ||
| 2363 | }, | ||
| 2364 | expected_output, | 2366 | expected_output, |
| 2367 | options, | ||
| 2365 | ); | 2368 | ); |
| 2366 | } | 2369 | } |
| 2367 | 2370 | ||
| ... | @@ -2373,7 +2376,6 @@ const success = 99; | ... | @@ -2373,7 +2376,6 @@ const success = 99; |
| 2373 | fn addTest( | 2376 | fn addTest( |
| 2374 | db: *Debugger, | 2377 | db: *Debugger, |
| 2375 | name: []const u8, | 2378 | name: []const u8, |
| 2376 | target: *const Target, | ||
| 2377 | files: []const File, | 2379 | files: []const File, |
| 2378 | env: []const struct { []const u8, []const u8 }, | 2380 | env: []const struct { []const u8, []const u8 }, |
| 2379 | db_argv1: []const []const u8, | 2381 | db_argv1: []const []const u8, |
| ... | @@ -2381,57 +2383,85 @@ fn addTest( | ... | @@ -2381,57 +2383,85 @@ fn addTest( |
| 2381 | commands: []const u8, | 2383 | commands: []const u8, |
| 2382 | db_argv2: []const []const u8, | 2384 | db_argv2: []const []const u8, |
| 2383 | expected_output: []const []const u8, | 2385 | expected_output: []const []const u8, |
| 2386 | options: TestOptions, | ||
| 2384 | ) void { | 2387 | ) void { |
| 2385 | if (db.options.test_filters.len > 0) { | 2388 | if (db.options.test_filters.len > 0) { |
| 2386 | for (db.options.test_filters) |test_filter| { | 2389 | for (db.options.test_filters) |test_filter| { |
| 2387 | if (std.mem.find(u8, name, test_filter) != null) break; | 2390 | if (std.mem.find(u8, name, test_filter) != null) break; |
| 2388 | } else return; | 2391 | } else return; |
| 2389 | } | 2392 | } |
| 2390 | if (db.options.test_target_filters.len > 0) { | ||
| 2391 | const triple_txt = target.resolved.query.zigTriple(db.b.allocator) catch @panic("OOM"); | ||
| 2392 | for (db.options.test_target_filters) |filter| { | ||
| 2393 | if (std.mem.find(u8, triple_txt, filter) != null) break; | ||
| 2394 | } else return; | ||
| 2395 | } | ||
| 2396 | const files_wf = db.b.addWriteFiles(); | ||
| 2397 | 2393 | ||
| 2398 | const mod = db.b.createModule(.{ | 2394 | const wf = db.b.addWriteFiles(); |
| 2399 | .target = target.resolved, | 2395 | const root_source_file = wf.add(files[0].path, files[0].source); |
| 2400 | .root_source_file = files_wf.add(files[0].path, files[0].source), | 2396 | var imports: std.array_hash_map.String(*std.Build.Module) = .empty; |
| 2401 | .optimize = target.optimize_mode, | ||
| 2402 | .link_libc = target.link_libc, | ||
| 2403 | .single_threaded = target.single_threaded, | ||
| 2404 | .pic = target.pic, | ||
| 2405 | .strip = false, | ||
| 2406 | }); | ||
| 2407 | for (files[1..]) |file| { | 2397 | for (files[1..]) |file| { |
| 2408 | const path = files_wf.add(file.path, file.source); | 2398 | const path = wf.add(file.path, file.source); |
| 2409 | if (file.import) |import| mod.addImport(import, db.b.createModule(.{ | 2399 | if (file.import) |import| imports.putNoClobber(db.b.allocator, import, db.b.createModule(.{ |
| 2410 | .root_source_file = path, | 2400 | .root_source_file = path, |
| 2411 | })); | 2401 | })) catch @panic("OOM"); |
| 2412 | } | 2402 | } |
| 2413 | 2403 | const commands_file = wf.add( | |
| 2414 | const exe = db.b.addExecutable(.{ | ||
| 2415 | .name = name, | ||
| 2416 | .root_module = mod, | ||
| 2417 | .use_llvm = false, | ||
| 2418 | .use_lld = false, | ||
| 2419 | }); | ||
| 2420 | |||
| 2421 | const commands_wf = db.b.addWriteFiles(); | ||
| 2422 | const run = std.Build.Step.Run.create(db.b, db.b.fmt("run {s} {s}", .{ name, target.test_name_suffix })); | ||
| 2423 | for (env) |env_var| run.setEnvironmentVariable(env_var[0], env_var[1]); | ||
| 2424 | run.addArgs(db_argv1); | ||
| 2425 | run.addFileArg(commands_wf.add( | ||
| 2426 | db.b.fmt("{s}.cmd", .{name}), | 2404 | db.b.fmt("{s}.cmd", .{name}), |
| 2427 | db.b.fmt("{s}\n\n{s}\n\nquit {d}\n", .{ db_commands, commands, success }), | 2405 | db.b.fmt("{s}\n\n{s}\n\nquit {d}\n", .{ db_commands, commands, success }), |
| 2428 | )); | 2406 | ); |
| 2429 | run.addArgs(db_argv2); | 2407 | |
| 2430 | run.addArtifactArg(exe); | 2408 | for (db.test_matrix) |test_target| { |
| 2431 | for (expected_output) |expected| run.addCheck(.{ .expect_stdout_match = db.b.fmt("{s}\n", .{expected}) }); | 2409 | if (options.skip_new_linker and test_target.linker == .new) continue; |
| 2432 | run.addCheck(.{ .expect_term = .{ .exited = success } }); | 2410 | |
| 2433 | run.setStdIn(.{ .bytes = "" }); | 2411 | const resolved_target = db.b.resolveTargetQuery(test_target.target); |
| 2434 | db.root_step.dependOn(&run.step); | 2412 | |
| 2413 | const target_str = db.b.fmt("{s}{s}{s}", .{ | ||
| 2414 | resolved_target.query.zigTriple(db.b.allocator) catch @panic("OOM"), | ||
| 2415 | switch (test_target.linker) { | ||
| 2416 | .default, .old => "", | ||
| 2417 | .new => "-new-linker", | ||
| 2418 | }, | ||
| 2419 | if (test_target.pic == true) "-pic" else "", | ||
| 2420 | }); | ||
| 2421 | |||
| 2422 | if (db.options.test_target_filters.len > 0) { | ||
| 2423 | for (db.options.test_target_filters) |filter| { | ||
| 2424 | if (std.mem.find(u8, target_str, filter) != null) break; | ||
| 2425 | } else continue; | ||
| 2426 | } | ||
| 2427 | |||
| 2428 | const mod = db.b.createModule(.{ | ||
| 2429 | .target = resolved_target, | ||
| 2430 | .root_source_file = root_source_file, | ||
| 2431 | .optimize = test_target.optimize_mode, | ||
| 2432 | .link_libc = test_target.link_libc, | ||
| 2433 | .single_threaded = test_target.single_threaded, | ||
| 2434 | .pic = test_target.pic, | ||
| 2435 | .strip = false, | ||
| 2436 | }); | ||
| 2437 | for (imports.keys(), imports.values()) |import_name, import_mod| | ||
| 2438 | mod.addImport(import_name, import_mod); | ||
| 2439 | |||
| 2440 | const exe = db.b.addExecutable(.{ | ||
| 2441 | .name = name, | ||
| 2442 | .root_module = mod, | ||
| 2443 | .use_llvm = false, | ||
| 2444 | .use_lld = false, | ||
| 2445 | }); | ||
| 2446 | exe.use_new_linker = switch (test_target.linker) { | ||
| 2447 | .default => null, | ||
| 2448 | .old => false, | ||
| 2449 | .new => true, | ||
| 2450 | }; | ||
| 2451 | |||
| 2452 | const run = std.Build.Step.Run.create(db.b, db.b.fmt("run {s} {s}", .{ name, target_str })); | ||
| 2453 | for (env) |env_var| run.setEnvironmentVariable(env_var[0], env_var[1]); | ||
| 2454 | run.addArgs(db_argv1); | ||
| 2455 | run.addFileArg(commands_file); | ||
| 2456 | run.addArgs(db_argv2); | ||
| 2457 | run.addArtifactArg(exe); | ||
| 2458 | for (expected_output) |expected| run.addCheck(.{ | ||
| 2459 | .expect_stdout_match = db.b.fmt("{s}\n", .{expected}), | ||
| 2460 | }); | ||
| 2461 | run.addCheck(.{ .expect_term = .{ .exited = success } }); | ||
| 2462 | run.setStdIn(.{ .bytes = "" }); | ||
| 2463 | db.root_step.dependOn(&run.step); | ||
| 2464 | } | ||
| 2435 | } | 2465 | } |
| 2436 | 2466 | ||
| 2437 | const Debugger = @This(); | 2467 | const Debugger = @This(); |
test/src/ErrorTrace.zig+29-5| ... | @@ -36,6 +36,7 @@ pub const CaseParameters = struct { | ... | @@ -36,6 +36,7 @@ pub const CaseParameters = struct { |
| 36 | optimize: OptimizeMode = .debug, | 36 | optimize: OptimizeMode = .debug, |
| 37 | use_llvm: ?bool = null, | 37 | use_llvm: ?bool = null, |
| 38 | use_lld: ?bool = null, | 38 | use_lld: ?bool = null, |
| 39 | use_new_linker: ?bool = null, | ||
| 39 | 40 | ||
| 40 | // This is intended for targets that, for any reason, shouldn't be run as part of a normal test | 41 | // This is intended for targets that, for any reason, shouldn't be run as part of a normal test |
| 41 | // invocation. This could be because of a slow backend, requiring a newer LLVM version, being | 42 | // invocation. This could be because of a slow backend, requiring a newer LLVM version, being |
| ... | @@ -256,6 +257,14 @@ pub const param_sets = [_]CaseParameters{ | ... | @@ -256,6 +257,14 @@ pub const param_sets = [_]CaseParameters{ |
| 256 | .abi = .none, | 257 | .abi = .none, |
| 257 | }, | 258 | }, |
| 258 | }, | 259 | }, |
| 260 | .{ | ||
| 261 | .target = .{ | ||
| 262 | .cpu_arch = .x86_64, | ||
| 263 | .os_tag = .linux, | ||
| 264 | .abi = .none, | ||
| 265 | }, | ||
| 266 | .use_new_linker = true, | ||
| 267 | }, | ||
| 259 | .{ | 268 | .{ |
| 260 | .target = .{ | 269 | .target = .{ |
| 261 | .cpu_arch = .x86_64, | 270 | .cpu_arch = .x86_64, |
| ... | @@ -265,6 +274,15 @@ pub const param_sets = [_]CaseParameters{ | ... | @@ -265,6 +274,15 @@ pub const param_sets = [_]CaseParameters{ |
| 265 | .use_llvm = true, | 274 | .use_llvm = true, |
| 266 | .use_lld = true, | 275 | .use_lld = true, |
| 267 | }, | 276 | }, |
| 277 | .{ | ||
| 278 | .target = .{ | ||
| 279 | .cpu_arch = .x86_64, | ||
| 280 | .os_tag = .linux, | ||
| 281 | .abi = .none, | ||
| 282 | }, | ||
| 283 | .use_llvm = true, | ||
| 284 | .use_new_linker = true, | ||
| 285 | }, | ||
| 268 | .{ | 286 | .{ |
| 269 | .target = .{ | 287 | .target = .{ |
| 270 | .cpu_arch = .x86_64, | 288 | .cpu_arch = .x86_64, |
| ... | @@ -439,18 +457,23 @@ pub fn addCase(self: *ErrorTrace, case: Case) void { | ... | @@ -439,18 +457,23 @@ pub fn addCase(self: *ErrorTrace, case: Case) void { |
| 439 | }; | 457 | }; |
| 440 | 458 | ||
| 441 | const backend_string = if (params.use_llvm == true) | 459 | const backend_string = if (params.use_llvm == true) |
| 442 | "-llvm" | 460 | " llvm" |
| 443 | else if (params.use_llvm == false) | 461 | else if (params.use_llvm == false) |
| 444 | "-selfhosted" | 462 | " selfhosted" |
| 445 | else | 463 | else |
| 446 | ""; | 464 | ""; |
| 447 | 465 | ||
| 448 | const annotated_case_name = b.fmt("check {s} ({s}{s}{t}{s})", .{ | 466 | const annotated_case_name = b.fmt("check {s} ({s} {t}{s}{s})", .{ |
| 449 | case.name, | 467 | case.name, |
| 450 | triple orelse "", | 468 | triple orelse "native", |
| 451 | if (triple != null) " " else "", | ||
| 452 | params.optimize, | 469 | params.optimize, |
| 453 | backend_string, | 470 | backend_string, |
| 471 | if (params.use_new_linker == true) | ||
| 472 | " new_linker" | ||
| 473 | else if (params.use_lld == true) | ||
| 474 | " lld" | ||
| 475 | else | ||
| 476 | "", | ||
| 454 | }); | 477 | }); |
| 455 | if (self.options.test_filters.len > 0) { | 478 | if (self.options.test_filters.len > 0) { |
| 456 | for (self.options.test_filters) |test_filter| { | 479 | for (self.options.test_filters) |test_filter| { |
| ... | @@ -472,6 +495,7 @@ pub fn addCase(self: *ErrorTrace, case: Case) void { | ... | @@ -472,6 +495,7 @@ pub fn addCase(self: *ErrorTrace, case: Case) void { |
| 472 | .use_llvm = params.use_llvm, | 495 | .use_llvm = params.use_llvm, |
| 473 | .use_lld = params.use_lld, | 496 | .use_lld = params.use_lld, |
| 474 | }); | 497 | }); |
| 498 | exe.use_new_linker = params.use_new_linker; | ||
| 475 | exe.bundle_ubsan_rt = false; | 499 | exe.bundle_ubsan_rt = false; |
| 476 | 500 | ||
| 477 | const run = b.addRunArtifact(exe); | 501 | const run = b.addRunArtifact(exe); |
test/src/StackTrace.zig+26-2| ... | @@ -38,6 +38,7 @@ pub const CaseParameters = struct { | ... | @@ -38,6 +38,7 @@ pub const CaseParameters = struct { |
| 38 | link_libc: ?bool = null, | 38 | link_libc: ?bool = null, |
| 39 | use_llvm: ?bool = null, | 39 | use_llvm: ?bool = null, |
| 40 | use_lld: ?bool = null, | 40 | use_lld: ?bool = null, |
| 41 | use_new_linker: ?bool = null, | ||
| 41 | pie: ?bool = null, | 42 | pie: ?bool = null, |
| 42 | /// To enable this coverage, one of two things needs to happen: | 43 | /// To enable this coverage, one of two things needs to happen: |
| 43 | /// * The compiler needs to gain the ability to strip only debug info (not symbols) | 44 | /// * The compiler needs to gain the ability to strip only debug info (not symbols) |
| ... | @@ -752,6 +753,14 @@ pub const param_sets = [_]CaseParameters{ | ... | @@ -752,6 +753,14 @@ pub const param_sets = [_]CaseParameters{ |
| 752 | .abi = .none, | 753 | .abi = .none, |
| 753 | }, | 754 | }, |
| 754 | }, | 755 | }, |
| 756 | .{ | ||
| 757 | .target = .{ | ||
| 758 | .cpu_arch = .x86_64, | ||
| 759 | .os_tag = .linux, | ||
| 760 | .abi = .none, | ||
| 761 | }, | ||
| 762 | .use_new_linker = true, | ||
| 763 | }, | ||
| 755 | .{ | 764 | .{ |
| 756 | .target = .{ | 765 | .target = .{ |
| 757 | .cpu_arch = .x86_64, | 766 | .cpu_arch = .x86_64, |
| ... | @@ -761,6 +770,15 @@ pub const param_sets = [_]CaseParameters{ | ... | @@ -761,6 +770,15 @@ pub const param_sets = [_]CaseParameters{ |
| 761 | .use_llvm = true, | 770 | .use_llvm = true, |
| 762 | .use_lld = true, | 771 | .use_lld = true, |
| 763 | }, | 772 | }, |
| 773 | .{ | ||
| 774 | .target = .{ | ||
| 775 | .cpu_arch = .x86_64, | ||
| 776 | .os_tag = .linux, | ||
| 777 | .abi = .none, | ||
| 778 | }, | ||
| 779 | .use_llvm = true, | ||
| 780 | .use_new_linker = true, | ||
| 781 | }, | ||
| 764 | .{ | 782 | .{ |
| 765 | .target = .{ | 783 | .target = .{ |
| 766 | .cpu_arch = .x86_64, | 784 | .cpu_arch = .x86_64, |
| ... | @@ -1175,9 +1193,14 @@ fn addCaseInstance( | ... | @@ -1175,9 +1193,14 @@ fn addCaseInstance( |
| 1175 | 1193 | ||
| 1176 | const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s}{s})", .{ | 1194 | const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s}{s})", .{ |
| 1177 | name, | 1195 | name, |
| 1178 | triple orelse "", | 1196 | triple orelse "native", |
| 1179 | if (triple != null) " " else "", | ||
| 1180 | backend_string, | 1197 | backend_string, |
| 1198 | if (params.use_new_linker == true) | ||
| 1199 | " new_linker" | ||
| 1200 | else if (params.use_lld == true) | ||
| 1201 | " lld" | ||
| 1202 | else | ||
| 1203 | "", | ||
| 1181 | if (params.pie == true) " pie" else "", | 1204 | if (params.pie == true) " pie" else "", |
| 1182 | if (params.link_libc == true) " libc" else "", | 1205 | if (params.link_libc == true) " libc" else "", |
| 1183 | if (params.linkage) |linkage| switch (linkage) { | 1206 | if (params.linkage) |linkage| switch (linkage) { |
| ... | @@ -1210,6 +1233,7 @@ fn addCaseInstance( | ... | @@ -1210,6 +1233,7 @@ fn addCaseInstance( |
| 1210 | .use_llvm = params.use_llvm, | 1233 | .use_llvm = params.use_llvm, |
| 1211 | .use_lld = params.use_lld, | 1234 | .use_lld = params.use_lld, |
| 1212 | }); | 1235 | }); |
| 1236 | exe.use_new_linker = params.use_new_linker; | ||
| 1213 | exe.linkage = params.linkage; | 1237 | exe.linkage = params.linkage; |
| 1214 | exe.pie = params.pie; | 1238 | exe.pie = params.pie; |
| 1215 | exe.bundle_ubsan_rt = false; | 1239 | exe.bundle_ubsan_rt = false; |
test/tests.zig+46-22| ... | @@ -2303,6 +2303,45 @@ const incremental_targets = &[_]IncrementalTarget{ | ... | @@ -2303,6 +2303,45 @@ const incremental_targets = &[_]IncrementalTarget{ |
| 2303 | }, | 2303 | }, |
| 2304 | }; | 2304 | }; |
| 2305 | 2305 | ||
| 2306 | const debugger_matrix: []const DebuggerContext.TestTarget = &.{ | ||
| 2307 | .{ | ||
| 2308 | .target = .{ | ||
| 2309 | .cpu_arch = .x86_64, | ||
| 2310 | .os_tag = .linux, | ||
| 2311 | .abi = .none, | ||
| 2312 | }, | ||
| 2313 | .pic = false, | ||
| 2314 | .linker = .old, | ||
| 2315 | }, | ||
| 2316 | .{ | ||
| 2317 | .target = .{ | ||
| 2318 | .cpu_arch = .x86_64, | ||
| 2319 | .os_tag = .linux, | ||
| 2320 | .abi = .none, | ||
| 2321 | }, | ||
| 2322 | .pic = true, | ||
| 2323 | .linker = .old, | ||
| 2324 | }, | ||
| 2325 | .{ | ||
| 2326 | .target = .{ | ||
| 2327 | .cpu_arch = .x86_64, | ||
| 2328 | .os_tag = .linux, | ||
| 2329 | .abi = .none, | ||
| 2330 | }, | ||
| 2331 | .pic = false, | ||
| 2332 | .linker = .new, | ||
| 2333 | }, | ||
| 2334 | .{ | ||
| 2335 | .target = .{ | ||
| 2336 | .cpu_arch = .x86_64, | ||
| 2337 | .os_tag = .linux, | ||
| 2338 | .abi = .none, | ||
| 2339 | }, | ||
| 2340 | .pic = true, | ||
| 2341 | .linker = .new, | ||
| 2342 | }, | ||
| 2343 | }; | ||
| 2344 | |||
| 2306 | fn compatible32bitArch(host: *const std.Target) ?std.Target.Cpu.Arch { | 2345 | fn compatible32bitArch(host: *const std.Target) ?std.Target.Cpu.Arch { |
| 2307 | return switch (host.os.tag) { | 2346 | return switch (host.os.tag) { |
| 2308 | .freebsd => switch (host.cpu.arch) { | 2347 | .freebsd => switch (host.cpu.arch) { |
| ... | @@ -3323,25 +3362,9 @@ pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step | ... | @@ -3323,25 +3362,9 @@ pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step |
| 3323 | .b = b, | 3362 | .b = b, |
| 3324 | .options = options, | 3363 | .options = options, |
| 3325 | .root_step = step, | 3364 | .root_step = step, |
| 3365 | .test_matrix = debugger_matrix, | ||
| 3326 | }; | 3366 | }; |
| 3327 | context.addTestsForTarget(&.{ | 3367 | context.addTests(); |
| 3328 | .resolved = b.resolveTargetQuery(.{ | ||
| 3329 | .cpu_arch = .x86_64, | ||
| 3330 | .os_tag = .linux, | ||
| 3331 | .abi = .none, | ||
| 3332 | }), | ||
| 3333 | .pic = false, | ||
| 3334 | .test_name_suffix = "x86_64-linux", | ||
| 3335 | }); | ||
| 3336 | context.addTestsForTarget(&.{ | ||
| 3337 | .resolved = b.resolveTargetQuery(.{ | ||
| 3338 | .cpu_arch = .x86_64, | ||
| 3339 | .os_tag = .linux, | ||
| 3340 | .abi = .none, | ||
| 3341 | }), | ||
| 3342 | .pic = true, | ||
| 3343 | .test_name_suffix = "x86_64-linux-pic", | ||
| 3344 | }); | ||
| 3345 | return step; | 3368 | return step; |
| 3346 | } | 3369 | } |
| 3347 | 3370 | ||
| ... | @@ -3416,16 +3439,17 @@ pub fn addIncrementalTests( | ... | @@ -3416,16 +3439,17 @@ pub fn addIncrementalTests( |
| 3416 | 3439 | ||
| 3417 | if (options.skip_llvm and test_target.backend == .llvm) continue; | 3440 | if (options.skip_llvm and test_target.backend == .llvm) continue; |
| 3418 | 3441 | ||
| 3419 | const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"); | 3442 | const target_str = b.fmt("{s}-{t}", .{ |
| 3443 | resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"), | ||
| 3444 | test_target.backend, | ||
| 3445 | }); | ||
| 3420 | 3446 | ||
| 3421 | if (options.test_target_filters.len > 0) { | 3447 | if (options.test_target_filters.len > 0) { |
| 3422 | for (options.test_target_filters) |filter| { | 3448 | for (options.test_target_filters) |filter| { |
| 3423 | if (std.mem.find(u8, triple_txt, filter) != null) break; | 3449 | if (std.mem.find(u8, target_str, filter) != null) break; |
| 3424 | } else continue; | 3450 | } else continue; |
| 3425 | } | 3451 | } |
| 3426 | 3452 | ||
| 3427 | const target_str = b.fmt("{s}-{t}", .{ triple_txt, test_target.backend }); | ||
| 3428 | |||
| 3429 | const run = b.addRunArtifact(incr_check); | 3453 | const run = b.addRunArtifact(incr_check); |
| 3430 | run.setName(b.fmt("incr-check {s} '{s}'", .{ target_str, entry.basename })); | 3454 | run.setName(b.fmt("incr-check {s} '{s}'", .{ target_str, entry.basename })); |
| 3431 | 3455 |
tools/incr-check.zig+7| ... | @@ -17,6 +17,7 @@ const usage = | ... | @@ -17,6 +17,7 @@ const usage = |
| 17 | \\Debug Options: | 17 | \\Debug Options: |
| 18 | \\ --preserve-tmp | 18 | \\ --preserve-tmp |
| 19 | \\ --debug-log foo | 19 | \\ --debug-log foo |
| 20 | \\ --debug-link-snapshot | ||
| 20 | ; | 21 | ; |
| 21 | 22 | ||
| 22 | pub const std_options: std.Options = .{ | 23 | pub const std_options: std.Options = .{ |
| ... | @@ -60,6 +61,7 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -60,6 +61,7 @@ pub fn main(init: std.process.Init) !void { |
| 60 | var quiet: bool = false; | 61 | var quiet: bool = false; |
| 61 | 62 | ||
| 62 | var debug_log_args: std.ArrayList([]const u8) = .empty; | 63 | var debug_log_args: std.ArrayList([]const u8) = .empty; |
| 64 | var debug_link_snapshot = false; | ||
| 63 | 65 | ||
| 64 | var arg_it = try init.minimal.args.iterateAllocator(arena); | 66 | var arg_it = try init.minimal.args.iterateAllocator(arena); |
| 65 | _ = arg_it.skip(); | 67 | _ = arg_it.skip(); |
| ... | @@ -77,6 +79,8 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -77,6 +79,8 @@ pub fn main(init: std.process.Init) !void { |
| 77 | arena, | 79 | arena, |
| 78 | arg_it.next() orelse badUsage("expected arg after --debug-log", .{}), | 80 | arg_it.next() orelse badUsage("expected arg after --debug-log", .{}), |
| 79 | ); | 81 | ); |
| 82 | } else if (std.mem.eql(u8, arg, "--debug-link-snapshot")) { | ||
| 83 | debug_link_snapshot = true; | ||
| 80 | } else if (std.mem.eql(u8, arg, "--preserve-tmp")) { | 84 | } else if (std.mem.eql(u8, arg, "--preserve-tmp")) { |
| 81 | preserve_tmp = true; | 85 | preserve_tmp = true; |
| 82 | } else if (std.mem.eql(u8, arg, "-fqemu")) { | 86 | } else if (std.mem.eql(u8, arg, "-fqemu")) { |
| ... | @@ -173,6 +177,9 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -173,6 +177,9 @@ pub fn main(init: std.process.Init) !void { |
| 173 | for (debug_log_args.items) |arg| { | 177 | for (debug_log_args.items) |arg| { |
| 174 | try child_args.appendSlice(arena, &.{ "--debug-log", arg }); | 178 | try child_args.appendSlice(arena, &.{ "--debug-log", arg }); |
| 175 | } | 179 | } |
| 180 | if (debug_link_snapshot) { | ||
| 181 | try child_args.append(arena, "--debug-link-snapshot"); | ||
| 182 | } | ||
| 176 | for (case.modules) |mod| { | 183 | for (case.modules) |mod| { |
| 177 | try child_args.appendSlice(arena, &.{ "--dep", mod.name }); | 184 | try child_args.appendSlice(arena, &.{ "--dep", mod.name }); |
| 178 | } | 185 | } |