| author | |
| committer | |
| log | 1a4c5837fedcad57f6c81301672e6246e0f0a8c1 |
| tree | 97b7b1b10d130d96cb93d7b28c88ad00971e0e1d |
| parent | 4b9dc2922ff0c5d873971f6f6f25db709df21cc0 |
10 files changed, 514 insertions(+), 369 deletions(-)
src/link.zig+3-6| ... | @@ -97,15 +97,12 @@ pub const Diags = struct { | ... | @@ -97,15 +97,12 @@ pub const Diags = struct { |
| 97 | err_msg.msg = try std.fmt.allocPrint(gpa, format, args); | 97 | err_msg.msg = try std.fmt.allocPrint(gpa, format, args); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | pub fn addNote( | 100 | pub fn addNote(err: *ErrorWithNotes, comptime format: []const u8, args: anytype) void { |
| 101 | err: *ErrorWithNotes, | ||
| 102 | comptime format: []const u8, | ||
| 103 | args: anytype, | ||
| 104 | ) error{OutOfMemory}!void { | ||
| 105 | const gpa = err.diags.gpa; | 101 | const gpa = err.diags.gpa; |
| 102 | const msg = std.fmt.allocPrint(gpa, format, args) catch return err.diags.setAllocFailure(); | ||
| 106 | const err_msg = &err.diags.msgs.items[err.index]; | 103 | const err_msg = &err.diags.msgs.items[err.index]; |
| 107 | assert(err.note_slot < err_msg.notes.len); | 104 | assert(err.note_slot < err_msg.notes.len); |
| 108 | err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) }; | 105 | err_msg.notes[err.note_slot] = .{ .msg = msg }; |
| 109 | err.note_slot += 1; | 106 | err.note_slot += 1; |
| 110 | } | 107 | } |
| 111 | }; | 108 | }; |
src/link/Elf.zig+7-7| ... | @@ -3394,7 +3394,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { | ... | @@ -3394,7 +3394,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { |
| 3394 | // TODO verify `getMaxNumberOfPhdrs()` is accurate and convert this into no-op | 3394 | // TODO verify `getMaxNumberOfPhdrs()` is accurate and convert this into no-op |
| 3395 | var err = try diags.addErrorWithNotes(1); | 3395 | var err = try diags.addErrorWithNotes(1); |
| 3396 | try err.addMsg("fatal linker error: not enough space reserved for EHDR and PHDR table", .{}); | 3396 | try err.addMsg("fatal linker error: not enough space reserved for EHDR and PHDR table", .{}); |
| 3397 | try err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space }); | 3397 | err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space }); |
| 3398 | } | 3398 | } |
| 3399 | 3399 | ||
| 3400 | phdr_table_load.p_filesz = needed_size + ehsize; | 3400 | phdr_table_load.p_filesz = needed_size + ehsize; |
| ... | @@ -4545,12 +4545,12 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { | ... | @@ -4545,12 +4545,12 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 4545 | for (refs.items[0..nrefs]) |ref| { | 4545 | for (refs.items[0..nrefs]) |ref| { |
| 4546 | const atom_ptr = self.atom(ref).?; | 4546 | const atom_ptr = self.atom(ref).?; |
| 4547 | const file_ptr = atom_ptr.file(self).?; | 4547 | const file_ptr = atom_ptr.file(self).?; |
| 4548 | try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) }); | 4548 | err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) }); |
| 4549 | } | 4549 | } |
| 4550 | 4550 | ||
| 4551 | if (refs.items.len > max_notes) { | 4551 | if (refs.items.len > max_notes) { |
| 4552 | const remaining = refs.items.len - max_notes; | 4552 | const remaining = refs.items.len - max_notes; |
| 4553 | try err.addNote("referenced {d} more times", .{remaining}); | 4553 | err.addNote("referenced {d} more times", .{remaining}); |
| 4554 | } | 4554 | } |
| 4555 | } | 4555 | } |
| 4556 | } | 4556 | } |
| ... | @@ -4567,17 +4567,17 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor | ... | @@ -4567,17 +4567,17 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor |
| 4567 | 4567 | ||
| 4568 | var err = try diags.addErrorWithNotes(nnotes + 1); | 4568 | var err = try diags.addErrorWithNotes(nnotes + 1); |
| 4569 | try err.addMsg("duplicate symbol definition: {s}", .{sym.name(self)}); | 4569 | try err.addMsg("duplicate symbol definition: {s}", .{sym.name(self)}); |
| 4570 | try err.addNote("defined by {}", .{sym.file(self).?.fmtPath()}); | 4570 | err.addNote("defined by {}", .{sym.file(self).?.fmtPath()}); |
| 4571 | 4571 | ||
| 4572 | var inote: usize = 0; | 4572 | var inote: usize = 0; |
| 4573 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { | 4573 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { |
| 4574 | const file_ptr = self.file(notes.items[inote]).?; | 4574 | const file_ptr = self.file(notes.items[inote]).?; |
| 4575 | try err.addNote("defined by {}", .{file_ptr.fmtPath()}); | 4575 | err.addNote("defined by {}", .{file_ptr.fmtPath()}); |
| 4576 | } | 4576 | } |
| 4577 | 4577 | ||
| 4578 | if (notes.items.len > max_notes) { | 4578 | if (notes.items.len > max_notes) { |
| 4579 | const remaining = notes.items.len - max_notes; | 4579 | const remaining = notes.items.len - max_notes; |
| 4580 | try err.addNote("defined {d} more times", .{remaining}); | 4580 | err.addNote("defined {d} more times", .{remaining}); |
| 4581 | } | 4581 | } |
| 4582 | } | 4582 | } |
| 4583 | 4583 | ||
| ... | @@ -4601,7 +4601,7 @@ pub fn addFileError( | ... | @@ -4601,7 +4601,7 @@ pub fn addFileError( |
| 4601 | const diags = &self.base.comp.link_diags; | 4601 | const diags = &self.base.comp.link_diags; |
| 4602 | var err = try diags.addErrorWithNotes(1); | 4602 | var err = try diags.addErrorWithNotes(1); |
| 4603 | try err.addMsg(format, args); | 4603 | try err.addMsg(format, args); |
| 4604 | try err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()}); | 4604 | err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()}); |
| 4605 | } | 4605 | } |
| 4606 | 4606 | ||
| 4607 | pub fn failFile( | 4607 | pub fn failFile( |
src/link/Elf/Atom.zig+12-12| ... | @@ -523,7 +523,7 @@ fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) Re | ... | @@ -523,7 +523,7 @@ fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) Re |
| 523 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), | 523 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), |
| 524 | rel.r_offset, | 524 | rel.r_offset, |
| 525 | }); | 525 | }); |
| 526 | try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); | 526 | err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); |
| 527 | return error.RelocFailure; | 527 | return error.RelocFailure; |
| 528 | } | 528 | } |
| 529 | 529 | ||
| ... | @@ -539,7 +539,7 @@ fn reportTextRelocError( | ... | @@ -539,7 +539,7 @@ fn reportTextRelocError( |
| 539 | rel.r_offset, | 539 | rel.r_offset, |
| 540 | symbol.name(elf_file), | 540 | symbol.name(elf_file), |
| 541 | }); | 541 | }); |
| 542 | try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); | 542 | err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); |
| 543 | return error.RelocFailure; | 543 | return error.RelocFailure; |
| 544 | } | 544 | } |
| 545 | 545 | ||
| ... | @@ -555,8 +555,8 @@ fn reportPicError( | ... | @@ -555,8 +555,8 @@ fn reportPicError( |
| 555 | rel.r_offset, | 555 | rel.r_offset, |
| 556 | symbol.name(elf_file), | 556 | symbol.name(elf_file), |
| 557 | }); | 557 | }); |
| 558 | try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); | 558 | err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); |
| 559 | try err.addNote("recompile with -fPIC", .{}); | 559 | err.addNote("recompile with -fPIC", .{}); |
| 560 | return error.RelocFailure; | 560 | return error.RelocFailure; |
| 561 | } | 561 | } |
| 562 | 562 | ||
| ... | @@ -572,8 +572,8 @@ fn reportNoPicError( | ... | @@ -572,8 +572,8 @@ fn reportNoPicError( |
| 572 | rel.r_offset, | 572 | rel.r_offset, |
| 573 | symbol.name(elf_file), | 573 | symbol.name(elf_file), |
| 574 | }); | 574 | }); |
| 575 | try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); | 575 | err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) }); |
| 576 | try err.addNote("recompile with -fno-PIC", .{}); | 576 | err.addNote("recompile with -fno-PIC", .{}); |
| 577 | return error.RelocFailure; | 577 | return error.RelocFailure; |
| 578 | } | 578 | } |
| 579 | 579 | ||
| ... | @@ -1187,7 +1187,7 @@ const x86_64 = struct { | ... | @@ -1187,7 +1187,7 @@ const x86_64 = struct { |
| 1187 | x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..]) catch { | 1187 | x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..]) catch { |
| 1188 | var err = try diags.addErrorWithNotes(1); | 1188 | var err = try diags.addErrorWithNotes(1); |
| 1189 | try err.addMsg("could not relax {s}", .{@tagName(r_type)}); | 1189 | try err.addMsg("could not relax {s}", .{@tagName(r_type)}); |
| 1190 | try err.addNote("in {}:{s} at offset 0x{x}", .{ | 1190 | err.addNote("in {}:{s} at offset 0x{x}", .{ |
| 1191 | atom.file(elf_file).?.fmtPath(), | 1191 | atom.file(elf_file).?.fmtPath(), |
| 1192 | atom.name(elf_file), | 1192 | atom.name(elf_file), |
| 1193 | rel.r_offset, | 1193 | rel.r_offset, |
| ... | @@ -1332,7 +1332,7 @@ const x86_64 = struct { | ... | @@ -1332,7 +1332,7 @@ const x86_64 = struct { |
| 1332 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), | 1332 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1333 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), | 1333 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), |
| 1334 | }); | 1334 | }); |
| 1335 | try err.addNote("in {}:{s} at offset 0x{x}", .{ | 1335 | err.addNote("in {}:{s} at offset 0x{x}", .{ |
| 1336 | self.file(elf_file).?.fmtPath(), | 1336 | self.file(elf_file).?.fmtPath(), |
| 1337 | self.name(elf_file), | 1337 | self.name(elf_file), |
| 1338 | rels[0].r_offset, | 1338 | rels[0].r_offset, |
| ... | @@ -1388,7 +1388,7 @@ const x86_64 = struct { | ... | @@ -1388,7 +1388,7 @@ const x86_64 = struct { |
| 1388 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), | 1388 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1389 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), | 1389 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), |
| 1390 | }); | 1390 | }); |
| 1391 | try err.addNote("in {}:{s} at offset 0x{x}", .{ | 1391 | err.addNote("in {}:{s} at offset 0x{x}", .{ |
| 1392 | self.file(elf_file).?.fmtPath(), | 1392 | self.file(elf_file).?.fmtPath(), |
| 1393 | self.name(elf_file), | 1393 | self.name(elf_file), |
| 1394 | rels[0].r_offset, | 1394 | rels[0].r_offset, |
| ... | @@ -1485,7 +1485,7 @@ const x86_64 = struct { | ... | @@ -1485,7 +1485,7 @@ const x86_64 = struct { |
| 1485 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), | 1485 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1486 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), | 1486 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), |
| 1487 | }); | 1487 | }); |
| 1488 | try err.addNote("in {}:{s} at offset 0x{x}", .{ | 1488 | err.addNote("in {}:{s} at offset 0x{x}", .{ |
| 1489 | self.file(elf_file).?.fmtPath(), | 1489 | self.file(elf_file).?.fmtPath(), |
| 1490 | self.name(elf_file), | 1490 | self.name(elf_file), |
| 1491 | rels[0].r_offset, | 1491 | rels[0].r_offset, |
| ... | @@ -1672,7 +1672,7 @@ const aarch64 = struct { | ... | @@ -1672,7 +1672,7 @@ const aarch64 = struct { |
| 1672 | // TODO: relax | 1672 | // TODO: relax |
| 1673 | var err = try diags.addErrorWithNotes(1); | 1673 | var err = try diags.addErrorWithNotes(1); |
| 1674 | try err.addMsg("TODO: relax ADR_GOT_PAGE", .{}); | 1674 | try err.addMsg("TODO: relax ADR_GOT_PAGE", .{}); |
| 1675 | try err.addNote("in {}:{s} at offset 0x{x}", .{ | 1675 | err.addNote("in {}:{s} at offset 0x{x}", .{ |
| 1676 | atom.file(elf_file).?.fmtPath(), | 1676 | atom.file(elf_file).?.fmtPath(), |
| 1677 | atom.name(elf_file), | 1677 | atom.name(elf_file), |
| 1678 | r_offset, | 1678 | r_offset, |
| ... | @@ -1959,7 +1959,7 @@ const riscv = struct { | ... | @@ -1959,7 +1959,7 @@ const riscv = struct { |
| 1959 | // TODO: implement searching forward | 1959 | // TODO: implement searching forward |
| 1960 | var err = try diags.addErrorWithNotes(1); | 1960 | var err = try diags.addErrorWithNotes(1); |
| 1961 | try err.addMsg("TODO: find HI20 paired reloc scanning forward", .{}); | 1961 | try err.addMsg("TODO: find HI20 paired reloc scanning forward", .{}); |
| 1962 | try err.addNote("in {}:{s} at offset 0x{x}", .{ | 1962 | err.addNote("in {}:{s} at offset 0x{x}", .{ |
| 1963 | atom.file(elf_file).?.fmtPath(), | 1963 | atom.file(elf_file).?.fmtPath(), |
| 1964 | atom.name(elf_file), | 1964 | atom.name(elf_file), |
| 1965 | rel.r_offset, | 1965 | rel.r_offset, |
src/link/Elf/Object.zig+5-5| ... | @@ -797,7 +797,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -797,7 +797,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { |
| 797 | if (!isNull(data[end .. end + sh_entsize])) { | 797 | if (!isNull(data[end .. end + sh_entsize])) { |
| 798 | var err = try diags.addErrorWithNotes(1); | 798 | var err = try diags.addErrorWithNotes(1); |
| 799 | try err.addMsg("string not null terminated", .{}); | 799 | try err.addMsg("string not null terminated", .{}); |
| 800 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | 800 | err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 801 | return error.LinkFailure; | 801 | return error.LinkFailure; |
| 802 | } | 802 | } |
| 803 | end += sh_entsize; | 803 | end += sh_entsize; |
| ... | @@ -812,7 +812,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -812,7 +812,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { |
| 812 | if (shdr.sh_size % sh_entsize != 0) { | 812 | if (shdr.sh_size % sh_entsize != 0) { |
| 813 | var err = try diags.addErrorWithNotes(1); | 813 | var err = try diags.addErrorWithNotes(1); |
| 814 | try err.addMsg("size not a multiple of sh_entsize", .{}); | 814 | try err.addMsg("size not a multiple of sh_entsize", .{}); |
| 815 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | 815 | err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 816 | return error.LinkFailure; | 816 | return error.LinkFailure; |
| 817 | } | 817 | } |
| 818 | 818 | ||
| ... | @@ -889,8 +889,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{ | ... | @@ -889,8 +889,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{ |
| 889 | const res = imsec.findSubsection(@intCast(esym.st_value)) orelse { | 889 | const res = imsec.findSubsection(@intCast(esym.st_value)) orelse { |
| 890 | var err = try diags.addErrorWithNotes(2); | 890 | var err = try diags.addErrorWithNotes(2); |
| 891 | try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); | 891 | try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); |
| 892 | try err.addNote("for symbol {s}", .{sym.name(elf_file)}); | 892 | err.addNote("for symbol {s}", .{sym.name(elf_file)}); |
| 893 | try err.addNote("in {}", .{self.fmtPath()}); | 893 | err.addNote("in {}", .{self.fmtPath()}); |
| 894 | return error.LinkFailure; | 894 | return error.LinkFailure; |
| 895 | }; | 895 | }; |
| 896 | 896 | ||
| ... | @@ -915,7 +915,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{ | ... | @@ -915,7 +915,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{ |
| 915 | const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { | 915 | const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { |
| 916 | var err = try diags.addErrorWithNotes(1); | 916 | var err = try diags.addErrorWithNotes(1); |
| 917 | try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset}); | 917 | try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset}); |
| 918 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | 918 | err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 919 | return error.LinkFailure; | 919 | return error.LinkFailure; |
| 920 | }; | 920 | }; |
| 921 | 921 |
src/link/Elf/eh_frame.zig+1-1| ... | @@ -611,7 +611,7 @@ fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void { | ... | @@ -611,7 +611,7 @@ fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void { |
| 611 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), | 611 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), |
| 612 | rel.r_offset, | 612 | rel.r_offset, |
| 613 | }); | 613 | }); |
| 614 | try err.addNote("in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()}); | 614 | err.addNote("in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()}); |
| 615 | return error.RelocFailure; | 615 | return error.RelocFailure; |
| 616 | } | 616 | } |
| 617 | 617 |
src/link/MachO.zig+16-16| ... | @@ -1572,21 +1572,21 @@ fn reportUndefs(self: *MachO) !void { | ... | @@ -1572,21 +1572,21 @@ fn reportUndefs(self: *MachO) !void { |
| 1572 | try err.addMsg("undefined symbol: {s}", .{undef_sym.getName(self)}); | 1572 | try err.addMsg("undefined symbol: {s}", .{undef_sym.getName(self)}); |
| 1573 | 1573 | ||
| 1574 | switch (notes) { | 1574 | switch (notes) { |
| 1575 | .force_undefined => try err.addNote("referenced with linker flag -u", .{}), | 1575 | .force_undefined => err.addNote("referenced with linker flag -u", .{}), |
| 1576 | .entry => try err.addNote("referenced with linker flag -e", .{}), | 1576 | .entry => err.addNote("referenced with linker flag -e", .{}), |
| 1577 | .dyld_stub_binder, .objc_msgsend => try err.addNote("referenced implicitly", .{}), | 1577 | .dyld_stub_binder, .objc_msgsend => err.addNote("referenced implicitly", .{}), |
| 1578 | .refs => |refs| { | 1578 | .refs => |refs| { |
| 1579 | var inote: usize = 0; | 1579 | var inote: usize = 0; |
| 1580 | while (inote < @min(refs.items.len, max_notes)) : (inote += 1) { | 1580 | while (inote < @min(refs.items.len, max_notes)) : (inote += 1) { |
| 1581 | const ref = refs.items[inote]; | 1581 | const ref = refs.items[inote]; |
| 1582 | const file = self.getFile(ref.file).?; | 1582 | const file = self.getFile(ref.file).?; |
| 1583 | const atom = ref.getAtom(self).?; | 1583 | const atom = ref.getAtom(self).?; |
| 1584 | try err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) }); | 1584 | err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) }); |
| 1585 | } | 1585 | } |
| 1586 | 1586 | ||
| 1587 | if (refs.items.len > max_notes) { | 1587 | if (refs.items.len > max_notes) { |
| 1588 | const remaining = refs.items.len - max_notes; | 1588 | const remaining = refs.items.len - max_notes; |
| 1589 | try err.addNote("referenced {d} more times", .{remaining}); | 1589 | err.addNote("referenced {d} more times", .{remaining}); |
| 1590 | } | 1590 | } |
| 1591 | }, | 1591 | }, |
| 1592 | } | 1592 | } |
| ... | @@ -3473,8 +3473,8 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo | ... | @@ -3473,8 +3473,8 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo |
| 3473 | seg_id, | 3473 | seg_id, |
| 3474 | seg.segName(), | 3474 | seg.segName(), |
| 3475 | }); | 3475 | }); |
| 3476 | try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{}); | 3476 | err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{}); |
| 3477 | try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); | 3477 | err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); |
| 3478 | } | 3478 | } |
| 3479 | 3479 | ||
| 3480 | seg.vmsize = needed_size; | 3480 | seg.vmsize = needed_size; |
| ... | @@ -3776,7 +3776,7 @@ pub fn reportParseError2( | ... | @@ -3776,7 +3776,7 @@ pub fn reportParseError2( |
| 3776 | const diags = &self.base.comp.link_diags; | 3776 | const diags = &self.base.comp.link_diags; |
| 3777 | var err = try diags.addErrorWithNotes(1); | 3777 | var err = try diags.addErrorWithNotes(1); |
| 3778 | try err.addMsg(format, args); | 3778 | try err.addMsg(format, args); |
| 3779 | try err.addNote("while parsing {}", .{self.getFile(file_index).?.fmtPath()}); | 3779 | err.addNote("while parsing {}", .{self.getFile(file_index).?.fmtPath()}); |
| 3780 | } | 3780 | } |
| 3781 | 3781 | ||
| 3782 | fn reportMissingDependencyError( | 3782 | fn reportMissingDependencyError( |
| ... | @@ -3790,10 +3790,10 @@ fn reportMissingDependencyError( | ... | @@ -3790,10 +3790,10 @@ fn reportMissingDependencyError( |
| 3790 | const diags = &self.base.comp.link_diags; | 3790 | const diags = &self.base.comp.link_diags; |
| 3791 | var err = try diags.addErrorWithNotes(2 + checked_paths.len); | 3791 | var err = try diags.addErrorWithNotes(2 + checked_paths.len); |
| 3792 | try err.addMsg(format, args); | 3792 | try err.addMsg(format, args); |
| 3793 | try err.addNote("while resolving {s}", .{path}); | 3793 | err.addNote("while resolving {s}", .{path}); |
| 3794 | try err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()}); | 3794 | err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()}); |
| 3795 | for (checked_paths) |p| { | 3795 | for (checked_paths) |p| { |
| 3796 | try err.addNote("tried {s}", .{p}); | 3796 | err.addNote("tried {s}", .{p}); |
| 3797 | } | 3797 | } |
| 3798 | } | 3798 | } |
| 3799 | 3799 | ||
| ... | @@ -3807,8 +3807,8 @@ fn reportDependencyError( | ... | @@ -3807,8 +3807,8 @@ fn reportDependencyError( |
| 3807 | const diags = &self.base.comp.link_diags; | 3807 | const diags = &self.base.comp.link_diags; |
| 3808 | var err = try diags.addErrorWithNotes(2); | 3808 | var err = try diags.addErrorWithNotes(2); |
| 3809 | try err.addMsg(format, args); | 3809 | try err.addMsg(format, args); |
| 3810 | try err.addNote("while parsing {s}", .{path}); | 3810 | err.addNote("while parsing {s}", .{path}); |
| 3811 | try err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()}); | 3811 | err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()}); |
| 3812 | } | 3812 | } |
| 3813 | 3813 | ||
| 3814 | fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void { | 3814 | fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void { |
| ... | @@ -3838,17 +3838,17 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void { | ... | @@ -3838,17 +3838,17 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void { |
| 3838 | 3838 | ||
| 3839 | var err = try diags.addErrorWithNotes(nnotes + 1); | 3839 | var err = try diags.addErrorWithNotes(nnotes + 1); |
| 3840 | try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)}); | 3840 | try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)}); |
| 3841 | try err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()}); | 3841 | err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()}); |
| 3842 | 3842 | ||
| 3843 | var inote: usize = 0; | 3843 | var inote: usize = 0; |
| 3844 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { | 3844 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { |
| 3845 | const file = self.getFile(notes.items[inote]).?; | 3845 | const file = self.getFile(notes.items[inote]).?; |
| 3846 | try err.addNote("defined by {}", .{file.fmtPath()}); | 3846 | err.addNote("defined by {}", .{file.fmtPath()}); |
| 3847 | } | 3847 | } |
| 3848 | 3848 | ||
| 3849 | if (notes.items.len > max_notes) { | 3849 | if (notes.items.len > max_notes) { |
| 3850 | const remaining = notes.items.len - max_notes; | 3850 | const remaining = notes.items.len - max_notes; |
| 3851 | try err.addNote("defined {d} more times", .{remaining}); | 3851 | err.addNote("defined {d} more times", .{remaining}); |
| 3852 | } | 3852 | } |
| 3853 | } | 3853 | } |
| 3854 | return error.HasDuplicates; | 3854 | return error.HasDuplicates; |
src/link/MachO/Atom.zig+2-2| ... | @@ -909,8 +909,8 @@ const x86_64 = struct { | ... | @@ -909,8 +909,8 @@ const x86_64 = struct { |
| 909 | rel.offset, | 909 | rel.offset, |
| 910 | rel.fmtPretty(.x86_64), | 910 | rel.fmtPretty(.x86_64), |
| 911 | }); | 911 | }); |
| 912 | try err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)}); | 912 | err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)}); |
| 913 | try err.addNote("while parsing {}", .{self.getFile(macho_file).fmtPath()}); | 913 | err.addNote("while parsing {}", .{self.getFile(macho_file).fmtPath()}); |
| 914 | return error.RelaxFailUnexpectedInstruction; | 914 | return error.RelaxFailUnexpectedInstruction; |
| 915 | }, | 915 | }, |
| 916 | } | 916 | } |
src/link/Wasm.zig+351-229| ... | @@ -109,7 +109,7 @@ object_tables: std.ArrayListUnmanaged(Table) = .empty, | ... | @@ -109,7 +109,7 @@ object_tables: std.ArrayListUnmanaged(Table) = .empty, |
| 109 | /// All memory imports for all objects. | 109 | /// All memory imports for all objects. |
| 110 | object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty, | 110 | object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty, |
| 111 | /// All parsed memory sections for all objects. | 111 | /// All parsed memory sections for all objects. |
| 112 | object_memories: std.ArrayListUnmanaged(std.wasm.Memory) = .empty, | 112 | object_memories: std.ArrayListUnmanaged(ObjectMemory) = .empty, |
| 113 | 113 | ||
| 114 | /// All relocations from all objects concatenated. `relocs_start` marks the end | 114 | /// All relocations from all objects concatenated. `relocs_start` marks the end |
| 115 | /// point of object relocations and start point of Zcu relocations. | 115 | /// point of object relocations and start point of Zcu relocations. |
| ... | @@ -119,8 +119,13 @@ object_relocations: std.MultiArrayList(ObjectRelocation) = .empty, | ... | @@ -119,8 +119,13 @@ object_relocations: std.MultiArrayList(ObjectRelocation) = .empty, |
| 119 | /// by the (synthetic) __wasm_call_ctors function. | 119 | /// by the (synthetic) __wasm_call_ctors function. |
| 120 | object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty, | 120 | object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty, |
| 121 | 121 | ||
| 122 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. | 122 | /// The data section of an object has many segments. Each segment corresponds |
| 123 | object_data_segments: std.ArrayListUnmanaged(DataSegment) = .empty, | 123 | /// logically to an object file's .data section, or .rodata section. In |
| 124 | /// the case of `-fdata-sections` there will be one segment per data symbol. | ||
| 125 | object_data_segments: std.ArrayListUnmanaged(ObjectDataSegment) = .empty, | ||
| 126 | /// Each segment has many data symbols. These correspond logically to global | ||
| 127 | /// constants. | ||
| 128 | object_datas: std.ArrayListUnmanaged(ObjectData) = .empty, | ||
| 124 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. | 129 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. |
| 125 | object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, CustomSegment) = .empty, | 130 | object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, CustomSegment) = .empty, |
| 126 | 131 | ||
| ... | @@ -457,6 +462,21 @@ pub const SourceLocation = enum(u32) { | ... | @@ -457,6 +462,21 @@ pub const SourceLocation = enum(u32) { |
| 457 | .source_location_index => @panic("TODO"), | 462 | .source_location_index => @panic("TODO"), |
| 458 | } | 463 | } |
| 459 | } | 464 | } |
| 465 | |||
| 466 | pub fn addNote( | ||
| 467 | sl: SourceLocation, | ||
| 468 | wasm: *Wasm, | ||
| 469 | err: *link.Diags.ErrorWithNotes, | ||
| 470 | comptime f: []const u8, | ||
| 471 | args: anytype, | ||
| 472 | ) void { | ||
| 473 | switch (sl.unpack(wasm)) { | ||
| 474 | .none => err.addNote(f, args), | ||
| 475 | .zig_object_nofile => err.addNote("zig compilation unit: " ++ f, args), | ||
| 476 | .object_index => |i| err.addNote("{}: " ++ f, .{i.ptr(wasm).path} ++ args), | ||
| 477 | .source_location_index => @panic("TODO"), | ||
| 478 | } | ||
| 479 | } | ||
| 460 | }; | 480 | }; |
| 461 | 481 | ||
| 462 | /// The lower bits of this ABI-match the flags here: | 482 | /// The lower bits of this ABI-match the flags here: |
| ... | @@ -687,13 +707,13 @@ pub const UavsExeIndex = enum(u32) { | ... | @@ -687,13 +707,13 @@ pub const UavsExeIndex = enum(u32) { |
| 687 | 707 | ||
| 688 | /// Used when emitting a relocatable object. | 708 | /// Used when emitting a relocatable object. |
| 689 | pub const ZcuDataObj = extern struct { | 709 | pub const ZcuDataObj = extern struct { |
| 690 | code: DataSegment.Payload, | 710 | code: DataPayload, |
| 691 | relocs: OutReloc.Slice, | 711 | relocs: OutReloc.Slice, |
| 692 | }; | 712 | }; |
| 693 | 713 | ||
| 694 | /// Used when not emitting a relocatable object. | 714 | /// Used when not emitting a relocatable object. |
| 695 | pub const ZcuDataExe = extern struct { | 715 | pub const ZcuDataExe = extern struct { |
| 696 | code: DataSegment.Payload, | 716 | code: DataPayload, |
| 697 | /// Tracks how many references there are for the purposes of sorting data segments. | 717 | /// Tracks how many references there are for the purposes of sorting data segments. |
| 698 | count: u32, | 718 | count: u32, |
| 699 | }; | 719 | }; |
| ... | @@ -917,6 +937,10 @@ pub const FunctionImport = extern struct { | ... | @@ -917,6 +937,10 @@ pub const FunctionImport = extern struct { |
| 917 | return pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.getIndex(ip_index).?) }); | 937 | return pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.getIndex(ip_index).?) }); |
| 918 | } | 938 | } |
| 919 | 939 | ||
| 940 | pub fn fromObjectFunction(wasm: *const Wasm, object_function: ObjectFunctionIndex) Resolution { | ||
| 941 | return pack(wasm, .{ .object_function = object_function }); | ||
| 942 | } | ||
| 943 | |||
| 920 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { | 944 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { |
| 921 | return switch (r.unpack(wasm)) { | 945 | return switch (r.unpack(wasm)) { |
| 922 | .unresolved, .zcu_func => true, | 946 | .unresolved, .zcu_func => true, |
| ... | @@ -988,7 +1012,7 @@ pub const Function = extern struct { | ... | @@ -988,7 +1012,7 @@ pub const Function = extern struct { |
| 988 | section_index: ObjectSectionIndex, | 1012 | section_index: ObjectSectionIndex, |
| 989 | source_location: SourceLocation, | 1013 | source_location: SourceLocation, |
| 990 | 1014 | ||
| 991 | pub const Code = DataSegment.Payload; | 1015 | pub const Code = DataPayload; |
| 992 | }; | 1016 | }; |
| 993 | 1017 | ||
| 994 | pub const GlobalImport = extern struct { | 1018 | pub const GlobalImport = extern struct { |
| ... | @@ -1283,12 +1307,30 @@ pub const ObjectGlobalIndex = enum(u32) { | ... | @@ -1283,12 +1307,30 @@ pub const ObjectGlobalIndex = enum(u32) { |
| 1283 | } | 1307 | } |
| 1284 | }; | 1308 | }; |
| 1285 | 1309 | ||
| 1286 | /// Index into `Wasm.object_memories`. | 1310 | pub const ObjectMemory = extern struct { |
| 1287 | pub const ObjectMemoryIndex = enum(u32) { | 1311 | flags: SymbolFlags, |
| 1288 | _, | 1312 | name: OptionalString, |
| 1313 | limits_min: u32, | ||
| 1314 | limits_max: u32, | ||
| 1289 | 1315 | ||
| 1290 | pub fn ptr(index: ObjectMemoryIndex, wasm: *const Wasm) *std.wasm.Memory { | 1316 | /// Index into `Wasm.object_memories`. |
| 1291 | return &wasm.object_memories.items[@intFromEnum(index)]; | 1317 | pub const Index = enum(u32) { |
| 1318 | _, | ||
| 1319 | |||
| 1320 | pub fn ptr(index: Index, wasm: *const Wasm) *ObjectMemory { | ||
| 1321 | return &wasm.object_memories.items[@intFromEnum(index)]; | ||
| 1322 | } | ||
| 1323 | }; | ||
| 1324 | |||
| 1325 | pub fn limits(om: *const ObjectMemory) std.wasm.Limits { | ||
| 1326 | return .{ | ||
| 1327 | .flags = .{ | ||
| 1328 | .has_max = om.limits_has_max, | ||
| 1329 | .is_shared = om.limits_is_shared, | ||
| 1330 | }, | ||
| 1331 | .min = om.limits_min, | ||
| 1332 | .max = om.limits_max, | ||
| 1333 | }; | ||
| 1292 | } | 1334 | } |
| 1293 | }; | 1335 | }; |
| 1294 | 1336 | ||
| ... | @@ -1318,14 +1360,74 @@ pub const OptionalObjectFunctionIndex = enum(u32) { | ... | @@ -1318,14 +1360,74 @@ pub const OptionalObjectFunctionIndex = enum(u32) { |
| 1318 | } | 1360 | } |
| 1319 | }; | 1361 | }; |
| 1320 | 1362 | ||
| 1321 | pub const DataSegment = extern struct { | 1363 | pub const ObjectDataSegment = extern struct { |
| 1364 | /// `none` if segment info custom subsection is missing. | ||
| 1365 | name: OptionalString, | ||
| 1366 | flags: SymbolFlags, | ||
| 1367 | payload: DataPayload, | ||
| 1368 | |||
| 1369 | /// Index into `Wasm.object_data_segments`. | ||
| 1370 | pub const Index = enum(u32) { | ||
| 1371 | _, | ||
| 1372 | |||
| 1373 | pub fn ptr(i: Index, wasm: *const Wasm) *ObjectDataSegment { | ||
| 1374 | return &wasm.object_data_segments.items[@intFromEnum(i)]; | ||
| 1375 | } | ||
| 1376 | }; | ||
| 1377 | }; | ||
| 1378 | |||
| 1379 | /// A local or exported global const from an object file. | ||
| 1380 | pub const ObjectData = extern struct { | ||
| 1381 | segment: ObjectDataSegment.Index, | ||
| 1382 | /// Index into the object segment payload. Must be <= the segment's size. | ||
| 1383 | offset: u32, | ||
| 1384 | /// May be zero. `offset + size` must be <= the segment's size. | ||
| 1385 | size: u32, | ||
| 1322 | /// `none` if no symbol describes it. | 1386 | /// `none` if no symbol describes it. |
| 1323 | name: OptionalString, | 1387 | name: OptionalString, |
| 1324 | flags: SymbolFlags, | 1388 | flags: SymbolFlags, |
| 1325 | payload: Payload, | 1389 | |
| 1326 | /// From the data segment start to the first byte of payload. | 1390 | /// Index into `Wasm.object_datas`. |
| 1327 | segment_offset: u32, | 1391 | pub const Index = enum(u32) { |
| 1328 | section_index: ObjectSectionIndex, | 1392 | _, |
| 1393 | |||
| 1394 | pub fn ptr(i: Index, wasm: *const Wasm) *ObjectData { | ||
| 1395 | return &wasm.object_datas.items[@intFromEnum(i)]; | ||
| 1396 | } | ||
| 1397 | }; | ||
| 1398 | }; | ||
| 1399 | |||
| 1400 | pub const DataPayload = extern struct { | ||
| 1401 | off: Off, | ||
| 1402 | /// The size in bytes of the data representing the segment within the section. | ||
| 1403 | len: u32, | ||
| 1404 | |||
| 1405 | pub const Off = enum(u32) { | ||
| 1406 | /// The payload is all zeroes (bss section). | ||
| 1407 | none = std.math.maxInt(u32), | ||
| 1408 | /// Points into string_bytes. No corresponding string_table entry. | ||
| 1409 | _, | ||
| 1410 | |||
| 1411 | pub fn unwrap(off: Off) ?u32 { | ||
| 1412 | return if (off == .none) null else @intFromEnum(off); | ||
| 1413 | } | ||
| 1414 | }; | ||
| 1415 | |||
| 1416 | pub fn slice(p: DataPayload, wasm: *const Wasm) []const u8 { | ||
| 1417 | return wasm.string_bytes.items[p.off.unwrap().?..][0..p.len]; | ||
| 1418 | } | ||
| 1419 | }; | ||
| 1420 | |||
| 1421 | /// A reference to a local or exported global const. | ||
| 1422 | pub const DataId = enum(u32) { | ||
| 1423 | __zig_error_names, | ||
| 1424 | __zig_error_name_table, | ||
| 1425 | /// First, an `ObjectDataSegment.Index`. | ||
| 1426 | /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. | ||
| 1427 | /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. | ||
| 1428 | _, | ||
| 1429 | |||
| 1430 | const first_object = @intFromEnum(DataId.__zig_error_name_table) + 1; | ||
| 1329 | 1431 | ||
| 1330 | pub const Category = enum { | 1432 | pub const Category = enum { |
| 1331 | /// Thread-local variables. | 1433 | /// Thread-local variables. |
| ... | @@ -1337,221 +1439,180 @@ pub const DataSegment = extern struct { | ... | @@ -1337,221 +1439,180 @@ pub const DataSegment = extern struct { |
| 1337 | zero, | 1439 | zero, |
| 1338 | }; | 1440 | }; |
| 1339 | 1441 | ||
| 1340 | pub const Payload = extern struct { | 1442 | pub const Unpacked = union(enum) { |
| 1341 | off: Off, | ||
| 1342 | /// The size in bytes of the data representing the segment within the section. | ||
| 1343 | len: u32, | ||
| 1344 | |||
| 1345 | pub const Off = enum(u32) { | ||
| 1346 | /// The payload is all zeroes (bss section). | ||
| 1347 | none = std.math.maxInt(u32), | ||
| 1348 | /// Points into string_bytes. No corresponding string_table entry. | ||
| 1349 | _, | ||
| 1350 | |||
| 1351 | pub fn unwrap(off: Off) ?u32 { | ||
| 1352 | return if (off == .none) null else @intFromEnum(off); | ||
| 1353 | } | ||
| 1354 | }; | ||
| 1355 | |||
| 1356 | pub fn slice(p: DataSegment.Payload, wasm: *const Wasm) []const u8 { | ||
| 1357 | return wasm.string_bytes.items[p.off.unwrap().?..][0..p.len]; | ||
| 1358 | } | ||
| 1359 | }; | ||
| 1360 | |||
| 1361 | pub const Id = enum(u32) { | ||
| 1362 | __zig_error_names, | 1443 | __zig_error_names, |
| 1363 | __zig_error_name_table, | 1444 | __zig_error_name_table, |
| 1364 | /// First, an `ObjectDataSegmentIndex`. | 1445 | object: ObjectDataSegment.Index, |
| 1365 | /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. | 1446 | uav_exe: UavsExeIndex, |
| 1366 | /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. | 1447 | uav_obj: UavsObjIndex, |
| 1367 | _, | 1448 | nav_exe: NavsExeIndex, |
| 1368 | 1449 | nav_obj: NavsObjIndex, | |
| 1369 | const first_object = @intFromEnum(Id.__zig_error_name_table) + 1; | 1450 | }; |
| 1370 | 1451 | ||
| 1371 | pub const Unpacked = union(enum) { | 1452 | pub fn pack(wasm: *const Wasm, unpacked: Unpacked) DataId { |
| 1372 | __zig_error_names, | 1453 | return switch (unpacked) { |
| 1373 | __zig_error_name_table, | 1454 | .__zig_error_names => .__zig_error_names, |
| 1374 | object: ObjectDataSegmentIndex, | 1455 | .__zig_error_name_table => .__zig_error_name_table, |
| 1375 | uav_exe: UavsExeIndex, | 1456 | .object => |i| @enumFromInt(first_object + @intFromEnum(i)), |
| 1376 | uav_obj: UavsObjIndex, | 1457 | inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)), |
| 1377 | nav_exe: NavsExeIndex, | 1458 | .nav_exe => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @intFromEnum(i)), |
| 1378 | nav_obj: NavsObjIndex, | 1459 | .nav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_obj.entries.len + @intFromEnum(i)), |
| 1379 | }; | 1460 | }; |
| 1461 | } | ||
| 1380 | 1462 | ||
| 1381 | pub fn pack(wasm: *const Wasm, unpacked: Unpacked) Id { | 1463 | pub fn unpack(id: DataId, wasm: *const Wasm) Unpacked { |
| 1382 | return switch (unpacked) { | 1464 | return switch (id) { |
| 1383 | .__zig_error_names => .__zig_error_names, | 1465 | .__zig_error_names => .__zig_error_names, |
| 1384 | .__zig_error_name_table => .__zig_error_name_table, | 1466 | .__zig_error_name_table => .__zig_error_name_table, |
| 1385 | .object => |i| @enumFromInt(first_object + @intFromEnum(i)), | 1467 | _ => { |
| 1386 | inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)), | 1468 | const object_index = @intFromEnum(id) - first_object; |
| 1387 | .nav_exe => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @intFromEnum(i)), | 1469 | |
| 1388 | .nav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_obj.entries.len + @intFromEnum(i)), | 1470 | const uav_index = if (object_index < wasm.object_data_segments.items.len) |
| 1389 | }; | 1471 | return .{ .object = @enumFromInt(object_index) } |
| 1390 | } | 1472 | else |
| 1391 | 1473 | object_index - wasm.object_data_segments.items.len; | |
| 1392 | pub fn unpack(id: Id, wasm: *const Wasm) Unpacked { | 1474 | |
| 1393 | return switch (id) { | 1475 | const comp = wasm.base.comp; |
| 1394 | .__zig_error_names => .__zig_error_names, | 1476 | const is_obj = comp.config.output_mode == .Obj; |
| 1395 | .__zig_error_name_table => .__zig_error_name_table, | 1477 | if (is_obj) { |
| 1396 | _ => { | 1478 | const nav_index = if (uav_index < wasm.uavs_obj.entries.len) |
| 1397 | const object_index = @intFromEnum(id) - first_object; | 1479 | return .{ .uav_obj = @enumFromInt(uav_index) } |
| 1398 | |||
| 1399 | const uav_index = if (object_index < wasm.object_data_segments.items.len) | ||
| 1400 | return .{ .object = @enumFromInt(object_index) } | ||
| 1401 | else | 1480 | else |
| 1402 | object_index - wasm.object_data_segments.items.len; | 1481 | uav_index - wasm.uavs_obj.entries.len; |
| 1403 | |||
| 1404 | const comp = wasm.base.comp; | ||
| 1405 | const is_obj = comp.config.output_mode == .Obj; | ||
| 1406 | if (is_obj) { | ||
| 1407 | const nav_index = if (uav_index < wasm.uavs_obj.entries.len) | ||
| 1408 | return .{ .uav_obj = @enumFromInt(uav_index) } | ||
| 1409 | else | ||
| 1410 | uav_index - wasm.uavs_obj.entries.len; | ||
| 1411 | |||
| 1412 | return .{ .nav_obj = @enumFromInt(nav_index) }; | ||
| 1413 | } else { | ||
| 1414 | const nav_index = if (uav_index < wasm.uavs_exe.entries.len) | ||
| 1415 | return .{ .uav_exe = @enumFromInt(uav_index) } | ||
| 1416 | else | ||
| 1417 | uav_index - wasm.uavs_exe.entries.len; | ||
| 1418 | |||
| 1419 | return .{ .nav_exe = @enumFromInt(nav_index) }; | ||
| 1420 | } | ||
| 1421 | }, | ||
| 1422 | }; | ||
| 1423 | } | ||
| 1424 | 1482 | ||
| 1425 | pub fn category(id: Id, wasm: *const Wasm) Category { | 1483 | return .{ .nav_obj = @enumFromInt(nav_index) }; |
| 1426 | return switch (unpack(id, wasm)) { | 1484 | } else { |
| 1427 | .__zig_error_names, .__zig_error_name_table => .data, | 1485 | const nav_index = if (uav_index < wasm.uavs_exe.entries.len) |
| 1428 | .object => |i| { | 1486 | return .{ .uav_exe = @enumFromInt(uav_index) } |
| 1429 | const ptr = i.ptr(wasm); | 1487 | else |
| 1430 | if (ptr.flags.tls) return .tls; | 1488 | uav_index - wasm.uavs_exe.entries.len; |
| 1431 | if (wasm.isBss(ptr.name)) return .zero; | ||
| 1432 | return .data; | ||
| 1433 | }, | ||
| 1434 | inline .uav_exe, .uav_obj => |i| if (i.value(wasm).code.off == .none) .zero else .data, | ||
| 1435 | inline .nav_exe, .nav_obj => |i| { | ||
| 1436 | const zcu = wasm.base.comp.zcu.?; | ||
| 1437 | const ip = &zcu.intern_pool; | ||
| 1438 | const nav = ip.getNav(i.key(wasm).*); | ||
| 1439 | if (nav.isThreadLocal(ip)) return .tls; | ||
| 1440 | const code = i.value(wasm).code; | ||
| 1441 | return if (code.off == .none) .zero else .data; | ||
| 1442 | }, | ||
| 1443 | }; | ||
| 1444 | } | ||
| 1445 | 1489 | ||
| 1446 | pub fn isTls(id: Id, wasm: *const Wasm) bool { | 1490 | return .{ .nav_exe = @enumFromInt(nav_index) }; |
| 1447 | return switch (unpack(id, wasm)) { | 1491 | } |
| 1448 | .__zig_error_names, .__zig_error_name_table => false, | 1492 | }, |
| 1449 | .object => |i| i.ptr(wasm).flags.tls, | 1493 | }; |
| 1450 | .uav_exe, .uav_obj => false, | 1494 | } |
| 1451 | inline .nav_exe, .nav_obj => |i| { | ||
| 1452 | const zcu = wasm.base.comp.zcu.?; | ||
| 1453 | const ip = &zcu.intern_pool; | ||
| 1454 | const nav = ip.getNav(i.key(wasm).*); | ||
| 1455 | return nav.isThreadLocal(ip); | ||
| 1456 | }, | ||
| 1457 | }; | ||
| 1458 | } | ||
| 1459 | 1495 | ||
| 1460 | pub fn isBss(id: Id, wasm: *const Wasm) bool { | 1496 | pub fn category(id: DataId, wasm: *const Wasm) Category { |
| 1461 | return id.category(wasm) == .zero; | 1497 | return switch (unpack(id, wasm)) { |
| 1462 | } | 1498 | .__zig_error_names, .__zig_error_name_table => .data, |
| 1499 | .object => |i| { | ||
| 1500 | const ptr = i.ptr(wasm); | ||
| 1501 | if (ptr.flags.tls) return .tls; | ||
| 1502 | if (wasm.isBss(ptr.name)) return .zero; | ||
| 1503 | return .data; | ||
| 1504 | }, | ||
| 1505 | inline .uav_exe, .uav_obj => |i| if (i.value(wasm).code.off == .none) .zero else .data, | ||
| 1506 | inline .nav_exe, .nav_obj => |i| { | ||
| 1507 | const zcu = wasm.base.comp.zcu.?; | ||
| 1508 | const ip = &zcu.intern_pool; | ||
| 1509 | const nav = ip.getNav(i.key(wasm).*); | ||
| 1510 | if (nav.isThreadLocal(ip)) return .tls; | ||
| 1511 | const code = i.value(wasm).code; | ||
| 1512 | return if (code.off == .none) .zero else .data; | ||
| 1513 | }, | ||
| 1514 | }; | ||
| 1515 | } | ||
| 1463 | 1516 | ||
| 1464 | pub fn name(id: Id, wasm: *const Wasm) []const u8 { | 1517 | pub fn isTls(id: DataId, wasm: *const Wasm) bool { |
| 1465 | return switch (unpack(id, wasm)) { | 1518 | return switch (unpack(id, wasm)) { |
| 1466 | .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj => ".data", | 1519 | .__zig_error_names, .__zig_error_name_table => false, |
| 1467 | .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm), | 1520 | .object => |i| i.ptr(wasm).flags.tls, |
| 1468 | inline .nav_exe, .nav_obj => |i| { | 1521 | .uav_exe, .uav_obj => false, |
| 1469 | const zcu = wasm.base.comp.zcu.?; | 1522 | inline .nav_exe, .nav_obj => |i| { |
| 1470 | const ip = &zcu.intern_pool; | 1523 | const zcu = wasm.base.comp.zcu.?; |
| 1471 | const nav = ip.getNav(i.key(wasm).*); | 1524 | const ip = &zcu.intern_pool; |
| 1472 | return nav.status.resolved.@"linksection".toSlice(ip) orelse ".data"; | 1525 | const nav = ip.getNav(i.key(wasm).*); |
| 1473 | }, | 1526 | return nav.isThreadLocal(ip); |
| 1474 | }; | 1527 | }, |
| 1475 | } | 1528 | }; |
| 1529 | } | ||
| 1476 | 1530 | ||
| 1477 | pub fn alignment(id: Id, wasm: *const Wasm) Alignment { | 1531 | pub fn isBss(id: DataId, wasm: *const Wasm) bool { |
| 1478 | return switch (unpack(id, wasm)) { | 1532 | return id.category(wasm) == .zero; |
| 1479 | .__zig_error_names => .@"1", | 1533 | } |
| 1480 | .__zig_error_name_table => wasm.pointerAlignment(), | ||
| 1481 | .object => |i| i.ptr(wasm).flags.alignment, | ||
| 1482 | inline .uav_exe, .uav_obj => |i| { | ||
| 1483 | const zcu = wasm.base.comp.zcu.?; | ||
| 1484 | const ip = &zcu.intern_pool; | ||
| 1485 | const ip_index = i.key(wasm).*; | ||
| 1486 | const ty: ZcuType = .fromInterned(ip.typeOf(ip_index)); | ||
| 1487 | const result = ty.abiAlignment(zcu); | ||
| 1488 | assert(result != .none); | ||
| 1489 | return result; | ||
| 1490 | }, | ||
| 1491 | inline .nav_exe, .nav_obj => |i| { | ||
| 1492 | const zcu = wasm.base.comp.zcu.?; | ||
| 1493 | const ip = &zcu.intern_pool; | ||
| 1494 | const nav = ip.getNav(i.key(wasm).*); | ||
| 1495 | const explicit = nav.status.resolved.alignment; | ||
| 1496 | if (explicit != .none) return explicit; | ||
| 1497 | const ty: ZcuType = .fromInterned(nav.typeOf(ip)); | ||
| 1498 | const result = ty.abiAlignment(zcu); | ||
| 1499 | assert(result != .none); | ||
| 1500 | return result; | ||
| 1501 | }, | ||
| 1502 | }; | ||
| 1503 | } | ||
| 1504 | 1534 | ||
| 1505 | pub fn refCount(id: Id, wasm: *const Wasm) u32 { | 1535 | pub fn name(id: DataId, wasm: *const Wasm) []const u8 { |
| 1506 | return switch (unpack(id, wasm)) { | 1536 | return switch (unpack(id, wasm)) { |
| 1507 | .__zig_error_names => @intCast(wasm.error_name_offs.items.len), | 1537 | .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj => ".data", |
| 1508 | .__zig_error_name_table => wasm.error_name_table_ref_count, | 1538 | .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm), |
| 1509 | .object, .uav_obj, .nav_obj => 0, | 1539 | inline .nav_exe, .nav_obj => |i| { |
| 1510 | inline .uav_exe, .nav_exe => |i| i.value(wasm).count, | 1540 | const zcu = wasm.base.comp.zcu.?; |
| 1511 | }; | 1541 | const ip = &zcu.intern_pool; |
| 1512 | } | 1542 | const nav = ip.getNav(i.key(wasm).*); |
| 1543 | return nav.status.resolved.@"linksection".toSlice(ip) orelse ".data"; | ||
| 1544 | }, | ||
| 1545 | }; | ||
| 1546 | } | ||
| 1513 | 1547 | ||
| 1514 | pub fn isPassive(id: Id, wasm: *const Wasm) bool { | 1548 | pub fn alignment(id: DataId, wasm: *const Wasm) Alignment { |
| 1515 | const comp = wasm.base.comp; | 1549 | return switch (unpack(id, wasm)) { |
| 1516 | if (comp.config.import_memory and !id.isBss(wasm)) return true; | 1550 | .__zig_error_names => .@"1", |
| 1517 | return switch (unpack(id, wasm)) { | 1551 | .__zig_error_name_table => wasm.pointerAlignment(), |
| 1518 | .__zig_error_names, .__zig_error_name_table => false, | 1552 | .object => |i| i.ptr(wasm).flags.alignment, |
| 1519 | .object => |i| i.ptr(wasm).flags.is_passive, | 1553 | inline .uav_exe, .uav_obj => |i| { |
| 1520 | .uav_exe, .uav_obj, .nav_exe, .nav_obj => false, | 1554 | const zcu = wasm.base.comp.zcu.?; |
| 1521 | }; | 1555 | const ip = &zcu.intern_pool; |
| 1522 | } | 1556 | const ip_index = i.key(wasm).*; |
| 1557 | const ty: ZcuType = .fromInterned(ip.typeOf(ip_index)); | ||
| 1558 | const result = ty.abiAlignment(zcu); | ||
| 1559 | assert(result != .none); | ||
| 1560 | return result; | ||
| 1561 | }, | ||
| 1562 | inline .nav_exe, .nav_obj => |i| { | ||
| 1563 | const zcu = wasm.base.comp.zcu.?; | ||
| 1564 | const ip = &zcu.intern_pool; | ||
| 1565 | const nav = ip.getNav(i.key(wasm).*); | ||
| 1566 | const explicit = nav.status.resolved.alignment; | ||
| 1567 | if (explicit != .none) return explicit; | ||
| 1568 | const ty: ZcuType = .fromInterned(nav.typeOf(ip)); | ||
| 1569 | const result = ty.abiAlignment(zcu); | ||
| 1570 | assert(result != .none); | ||
| 1571 | return result; | ||
| 1572 | }, | ||
| 1573 | }; | ||
| 1574 | } | ||
| 1523 | 1575 | ||
| 1524 | pub fn isEmpty(id: Id, wasm: *const Wasm) bool { | 1576 | pub fn refCount(id: DataId, wasm: *const Wasm) u32 { |
| 1525 | return switch (unpack(id, wasm)) { | 1577 | return switch (unpack(id, wasm)) { |
| 1526 | .__zig_error_names, .__zig_error_name_table => false, | 1578 | .__zig_error_names => @intCast(wasm.error_name_offs.items.len), |
| 1527 | .object => |i| i.ptr(wasm).payload.off == .none, | 1579 | .__zig_error_name_table => wasm.error_name_table_ref_count, |
| 1528 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none, | 1580 | .object, .uav_obj, .nav_obj => 0, |
| 1529 | }; | 1581 | inline .uav_exe, .nav_exe => |i| i.value(wasm).count, |
| 1530 | } | 1582 | }; |
| 1583 | } | ||
| 1531 | 1584 | ||
| 1532 | pub fn size(id: Id, wasm: *const Wasm) u32 { | 1585 | pub fn isPassive(id: DataId, wasm: *const Wasm) bool { |
| 1533 | return switch (unpack(id, wasm)) { | 1586 | const comp = wasm.base.comp; |
| 1534 | .__zig_error_names => @intCast(wasm.error_name_bytes.items.len), | 1587 | if (comp.config.import_memory and !id.isBss(wasm)) return true; |
| 1535 | .__zig_error_name_table => { | 1588 | return switch (unpack(id, wasm)) { |
| 1536 | const comp = wasm.base.comp; | 1589 | .__zig_error_names, .__zig_error_name_table => false, |
| 1537 | const zcu = comp.zcu.?; | 1590 | .object => |i| i.ptr(wasm).flags.is_passive, |
| 1538 | const errors_len = wasm.error_name_offs.items.len; | 1591 | .uav_exe, .uav_obj, .nav_exe, .nav_obj => false, |
| 1539 | const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu); | 1592 | }; |
| 1540 | return @intCast(errors_len * elem_size); | 1593 | } |
| 1541 | }, | ||
| 1542 | .object => |i| i.ptr(wasm).payload.len, | ||
| 1543 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, | ||
| 1544 | }; | ||
| 1545 | } | ||
| 1546 | }; | ||
| 1547 | }; | ||
| 1548 | 1594 | ||
| 1549 | /// Index into `Wasm.object_data_segments`. | 1595 | pub fn isEmpty(id: DataId, wasm: *const Wasm) bool { |
| 1550 | pub const ObjectDataSegmentIndex = enum(u32) { | 1596 | return switch (unpack(id, wasm)) { |
| 1551 | _, | 1597 | .__zig_error_names, .__zig_error_name_table => false, |
| 1598 | .object => |i| i.ptr(wasm).payload.off == .none, | ||
| 1599 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none, | ||
| 1600 | }; | ||
| 1601 | } | ||
| 1552 | 1602 | ||
| 1553 | pub fn ptr(i: ObjectDataSegmentIndex, wasm: *const Wasm) *DataSegment { | 1603 | pub fn size(id: DataId, wasm: *const Wasm) u32 { |
| 1554 | return &wasm.object_data_segments.items[@intFromEnum(i)]; | 1604 | return switch (unpack(id, wasm)) { |
| 1605 | .__zig_error_names => @intCast(wasm.error_name_bytes.items.len), | ||
| 1606 | .__zig_error_name_table => { | ||
| 1607 | const comp = wasm.base.comp; | ||
| 1608 | const zcu = comp.zcu.?; | ||
| 1609 | const errors_len = wasm.error_name_offs.items.len; | ||
| 1610 | const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu); | ||
| 1611 | return @intCast(errors_len * elem_size); | ||
| 1612 | }, | ||
| 1613 | .object => |i| i.ptr(wasm).payload.len, | ||
| 1614 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, | ||
| 1615 | }; | ||
| 1555 | } | 1616 | } |
| 1556 | }; | 1617 | }; |
| 1557 | 1618 | ||
| ... | @@ -1565,7 +1626,7 @@ pub const CustomSegment = extern struct { | ... | @@ -1565,7 +1626,7 @@ pub const CustomSegment = extern struct { |
| 1565 | flags: SymbolFlags, | 1626 | flags: SymbolFlags, |
| 1566 | section_name: String, | 1627 | section_name: String, |
| 1567 | 1628 | ||
| 1568 | pub const Payload = DataSegment.Payload; | 1629 | pub const Payload = DataPayload; |
| 1569 | }; | 1630 | }; |
| 1570 | 1631 | ||
| 1571 | /// An index into string_bytes where a wasm expression is found. | 1632 | /// An index into string_bytes where a wasm expression is found. |
| ... | @@ -1591,9 +1652,13 @@ pub const FunctionType = extern struct { | ... | @@ -1591,9 +1652,13 @@ pub const FunctionType = extern struct { |
| 1591 | pub const Index = enum(u32) { | 1652 | pub const Index = enum(u32) { |
| 1592 | _, | 1653 | _, |
| 1593 | 1654 | ||
| 1594 | pub fn ptr(i: FunctionType.Index, wasm: *const Wasm) *FunctionType { | 1655 | pub fn ptr(i: Index, wasm: *const Wasm) *FunctionType { |
| 1595 | return &wasm.func_types.keys()[@intFromEnum(i)]; | 1656 | return &wasm.func_types.keys()[@intFromEnum(i)]; |
| 1596 | } | 1657 | } |
| 1658 | |||
| 1659 | pub fn fmt(i: Index, wasm: *const Wasm) Formatter { | ||
| 1660 | return i.ptr(wasm).fmt(wasm); | ||
| 1661 | } | ||
| 1597 | }; | 1662 | }; |
| 1598 | 1663 | ||
| 1599 | pub const format = @compileError("can't format without *Wasm reference"); | 1664 | pub const format = @compileError("can't format without *Wasm reference"); |
| ... | @@ -1601,6 +1666,46 @@ pub const FunctionType = extern struct { | ... | @@ -1601,6 +1666,46 @@ pub const FunctionType = extern struct { |
| 1601 | pub fn eql(a: FunctionType, b: FunctionType) bool { | 1666 | pub fn eql(a: FunctionType, b: FunctionType) bool { |
| 1602 | return a.params == b.params and a.returns == b.returns; | 1667 | return a.params == b.params and a.returns == b.returns; |
| 1603 | } | 1668 | } |
| 1669 | |||
| 1670 | pub fn fmt(ft: FunctionType, wasm: *const Wasm) Formatter { | ||
| 1671 | return .{ .wasm = wasm, .ft = ft }; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | const Formatter = struct { | ||
| 1675 | wasm: *const Wasm, | ||
| 1676 | ft: FunctionType, | ||
| 1677 | |||
| 1678 | pub fn format( | ||
| 1679 | self: Formatter, | ||
| 1680 | comptime format_string: []const u8, | ||
| 1681 | options: std.fmt.FormatOptions, | ||
| 1682 | writer: anytype, | ||
| 1683 | ) !void { | ||
| 1684 | if (format_string.len != 0) std.fmt.invalidFmtError(format_string, self); | ||
| 1685 | _ = options; | ||
| 1686 | const params = self.ft.params.slice(self.wasm); | ||
| 1687 | const returns = self.ft.returns.slice(self.wasm); | ||
| 1688 | |||
| 1689 | try writer.writeByte('('); | ||
| 1690 | for (params, 0..) |param, i| { | ||
| 1691 | try writer.print("{s}", .{@tagName(param)}); | ||
| 1692 | if (i + 1 != params.len) { | ||
| 1693 | try writer.writeAll(", "); | ||
| 1694 | } | ||
| 1695 | } | ||
| 1696 | try writer.writeAll(") -> "); | ||
| 1697 | if (returns.len == 0) { | ||
| 1698 | try writer.writeAll("nil"); | ||
| 1699 | } else { | ||
| 1700 | for (returns, 0..) |return_ty, i| { | ||
| 1701 | try writer.print("{s}", .{@tagName(return_ty)}); | ||
| 1702 | if (i + 1 != returns.len) { | ||
| 1703 | try writer.writeAll(", "); | ||
| 1704 | } | ||
| 1705 | } | ||
| 1706 | } | ||
| 1707 | } | ||
| 1708 | }; | ||
| 1604 | }; | 1709 | }; |
| 1605 | 1710 | ||
| 1606 | /// Represents a function entry, holding the index to its type | 1711 | /// Represents a function entry, holding the index to its type |
| ... | @@ -1955,7 +2060,7 @@ pub const ObjectRelocation = struct { | ... | @@ -1955,7 +2060,7 @@ pub const ObjectRelocation = struct { |
| 1955 | symbol_name: String, | 2060 | symbol_name: String, |
| 1956 | type_index: FunctionType.Index, | 2061 | type_index: FunctionType.Index, |
| 1957 | section: ObjectSectionIndex, | 2062 | section: ObjectSectionIndex, |
| 1958 | data_segment: ObjectDataSegmentIndex, | 2063 | data: ObjectData.Index, |
| 1959 | function: Wasm.ObjectFunctionIndex, | 2064 | function: Wasm.ObjectFunctionIndex, |
| 1960 | }; | 2065 | }; |
| 1961 | 2066 | ||
| ... | @@ -2096,6 +2201,8 @@ pub const Feature = packed struct(u8) { | ... | @@ -2096,6 +2201,8 @@ pub const Feature = packed struct(u8) { |
| 2096 | /// Type of the feature, must be unique in the sequence of features. | 2201 | /// Type of the feature, must be unique in the sequence of features. |
| 2097 | tag: Tag, | 2202 | tag: Tag, |
| 2098 | 2203 | ||
| 2204 | pub const sentinel: Feature = @bitCast(@as(u8, 0)); | ||
| 2205 | |||
| 2099 | /// Stored identically to `String`. The bytes are reinterpreted as `Feature` | 2206 | /// Stored identically to `String`. The bytes are reinterpreted as `Feature` |
| 2100 | /// elements. Elements must be sorted before string-interning. | 2207 | /// elements. Elements must be sorted before string-interning. |
| 2101 | pub const Set = enum(u32) { | 2208 | pub const Set = enum(u32) { |
| ... | @@ -2104,6 +2211,14 @@ pub const Feature = packed struct(u8) { | ... | @@ -2104,6 +2211,14 @@ pub const Feature = packed struct(u8) { |
| 2104 | pub fn fromString(s: String) Set { | 2211 | pub fn fromString(s: String) Set { |
| 2105 | return @enumFromInt(@intFromEnum(s)); | 2212 | return @enumFromInt(@intFromEnum(s)); |
| 2106 | } | 2213 | } |
| 2214 | |||
| 2215 | pub fn string(s: Set) String { | ||
| 2216 | return @enumFromInt(@intFromEnum(s)); | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | pub fn slice(s: Set, wasm: *const Wasm) [:sentinel]const Feature { | ||
| 2220 | return @ptrCast(string(s).slice(wasm)); | ||
| 2221 | } | ||
| 2107 | }; | 2222 | }; |
| 2108 | 2223 | ||
| 2109 | /// Unlike `std.Target.wasm.Feature` this also contains linker-features such as shared-mem. | 2224 | /// Unlike `std.Target.wasm.Feature` this also contains linker-features such as shared-mem. |
| ... | @@ -2129,6 +2244,13 @@ pub const Feature = packed struct(u8) { | ... | @@ -2129,6 +2244,13 @@ pub const Feature = packed struct(u8) { |
| 2129 | return @enumFromInt(@intFromEnum(feature)); | 2244 | return @enumFromInt(@intFromEnum(feature)); |
| 2130 | } | 2245 | } |
| 2131 | 2246 | ||
| 2247 | pub fn toCpuFeature(tag: Tag) ?std.Target.wasm.Feature { | ||
| 2248 | return if (@intFromEnum(tag) < @typeInfo(std.Target.wasm.Feature).@"enum".fields.len) | ||
| 2249 | @enumFromInt(@intFromEnum(tag)) | ||
| 2250 | else | ||
| 2251 | null; | ||
| 2252 | } | ||
| 2253 | |||
| 2132 | pub const format = @compileError("use @tagName instead"); | 2254 | pub const format = @compileError("use @tagName instead"); |
| 2133 | }; | 2255 | }; |
| 2134 | 2256 | ||
| ... | @@ -2136,15 +2258,14 @@ pub const Feature = packed struct(u8) { | ... | @@ -2136,15 +2258,14 @@ pub const Feature = packed struct(u8) { |
| 2136 | pub const Prefix = enum(u2) { | 2258 | pub const Prefix = enum(u2) { |
| 2137 | /// Reserved so that a 0-byte Feature is invalid and therefore can be a sentinel. | 2259 | /// Reserved so that a 0-byte Feature is invalid and therefore can be a sentinel. |
| 2138 | invalid, | 2260 | invalid, |
| 2139 | /// '0x2b': Object uses this feature, and the link fails if feature is | 2261 | /// Object uses this feature, and the link fails if feature is not in |
| 2140 | /// not in the allowed set. | 2262 | /// the allowed set. |
| 2141 | @"+", | 2263 | @"+", |
| 2142 | /// '0x2d': Object does not use this feature, and the link fails if | 2264 | /// Object does not use this feature, and the link fails if this |
| 2143 | /// this feature is in the allowed set. | 2265 | /// feature is in the allowed set. |
| 2144 | @"-", | 2266 | @"-", |
| 2145 | /// '0x3d': Object uses this feature, and the link fails if this | 2267 | /// Object uses this feature, and the link fails if this feature is not |
| 2146 | /// feature is not in the allowed set, or if any object does not use | 2268 | /// in the allowed set, or if any object does not use this feature. |
| 2147 | /// this feature. | ||
| 2148 | @"=", | 2269 | @"=", |
| 2149 | }; | 2270 | }; |
| 2150 | 2271 | ||
| ... | @@ -2390,6 +2511,7 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -2390,6 +2511,7 @@ pub fn deinit(wasm: *Wasm) void { |
| 2390 | wasm.object_memories.deinit(gpa); | 2511 | wasm.object_memories.deinit(gpa); |
| 2391 | wasm.object_relocations.deinit(gpa); | 2512 | wasm.object_relocations.deinit(gpa); |
| 2392 | wasm.object_data_segments.deinit(gpa); | 2513 | wasm.object_data_segments.deinit(gpa); |
| 2514 | wasm.object_datas.deinit(gpa); | ||
| 2393 | wasm.object_custom_segments.deinit(gpa); | 2515 | wasm.object_custom_segments.deinit(gpa); |
| 2394 | wasm.object_init_funcs.deinit(gpa); | 2516 | wasm.object_init_funcs.deinit(gpa); |
| 2395 | wasm.object_comdats.deinit(gpa); | 2517 | wasm.object_comdats.deinit(gpa); |
| ... | @@ -3412,7 +3534,7 @@ pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr { | ... | @@ -3412,7 +3534,7 @@ pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr { |
| 3412 | return @enumFromInt(wasm.string_bytes.items.len - bytes.len); | 3534 | return @enumFromInt(wasm.string_bytes.items.len - bytes.len); |
| 3413 | } | 3535 | } |
| 3414 | 3536 | ||
| 3415 | pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error!DataSegment.Payload { | 3537 | pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error!DataPayload { |
| 3416 | const gpa = wasm.base.comp.gpa; | 3538 | const gpa = wasm.base.comp.gpa; |
| 3417 | try wasm.string_bytes.appendSlice(gpa, bytes); | 3539 | try wasm.string_bytes.appendSlice(gpa, bytes); |
| 3418 | return .{ | 3540 | return .{ |
| ... | @@ -3546,7 +3668,7 @@ pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 { | ... | @@ -3546,7 +3668,7 @@ pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 { |
| 3546 | assert(wasm.flush_buffer.memory_layout_finished); | 3668 | assert(wasm.flush_buffer.memory_layout_finished); |
| 3547 | const comp = wasm.base.comp; | 3669 | const comp = wasm.base.comp; |
| 3548 | assert(comp.config.output_mode != .Obj); | 3670 | assert(comp.config.output_mode != .Obj); |
| 3549 | const ds_id: DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_index }); | 3671 | const ds_id: DataId = .pack(wasm, .{ .uav_exe = uav_index }); |
| 3550 | return wasm.flush_buffer.data_segments.get(ds_id).?; | 3672 | return wasm.flush_buffer.data_segments.get(ds_id).?; |
| 3551 | } | 3673 | } |
| 3552 | 3674 | ||
| ... | @@ -3557,7 +3679,7 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { | ... | @@ -3557,7 +3679,7 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { |
| 3557 | assert(comp.config.output_mode != .Obj); | 3679 | assert(comp.config.output_mode != .Obj); |
| 3558 | const navs_exe_index: NavsExeIndex = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?); | 3680 | const navs_exe_index: NavsExeIndex = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?); |
| 3559 | log.debug("navAddr {s} {}", .{ navs_exe_index.name(wasm), nav_index }); | 3681 | log.debug("navAddr {s} {}", .{ navs_exe_index.name(wasm), nav_index }); |
| 3560 | const ds_id: DataSegment.Id = .pack(wasm, .{ .nav_exe = navs_exe_index }); | 3682 | const ds_id: DataId = .pack(wasm, .{ .nav_exe = navs_exe_index }); |
| 3561 | return wasm.flush_buffer.data_segments.get(ds_id).?; | 3683 | return wasm.flush_buffer.data_segments.get(ds_id).?; |
| 3562 | } | 3684 | } |
| 3563 | 3685 | ||
| ... | @@ -3646,14 +3768,14 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu | ... | @@ -3646,14 +3768,14 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu |
| 3646 | const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start); | 3768 | const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start); |
| 3647 | wasm.string_bytes_lock.unlock(); | 3769 | wasm.string_bytes_lock.unlock(); |
| 3648 | 3770 | ||
| 3649 | const naive_code: DataSegment.Payload = .{ | 3771 | const naive_code: DataPayload = .{ |
| 3650 | .off = @enumFromInt(code_start), | 3772 | .off = @enumFromInt(code_start), |
| 3651 | .len = code_len, | 3773 | .len = code_len, |
| 3652 | }; | 3774 | }; |
| 3653 | 3775 | ||
| 3654 | // Only nonzero init values need to take up space in the output. | 3776 | // Only nonzero init values need to take up space in the output. |
| 3655 | const all_zeroes = std.mem.allEqual(u8, naive_code.slice(wasm), 0); | 3777 | const all_zeroes = std.mem.allEqual(u8, naive_code.slice(wasm), 0); |
| 3656 | const code: DataSegment.Payload = if (!all_zeroes) naive_code else c: { | 3778 | const code: DataPayload = if (!all_zeroes) naive_code else c: { |
| 3657 | wasm.string_bytes.shrinkRetainingCapacity(code_start); | 3779 | wasm.string_bytes.shrinkRetainingCapacity(code_start); |
| 3658 | // Indicate empty by making off and len the same value, however, still | 3780 | // Indicate empty by making off and len the same value, however, still |
| 3659 | // transmit the data size by using the size as that value. | 3781 | // transmit the data size by using the size as that value. |
src/link/Wasm/Flush.zig+12-12| ... | @@ -22,7 +22,7 @@ const assert = std.debug.assert; | ... | @@ -22,7 +22,7 @@ const assert = std.debug.assert; |
| 22 | /// Ordered list of data segments that will appear in the final binary. | 22 | /// Ordered list of data segments that will appear in the final binary. |
| 23 | /// When sorted, to-be-merged segments will be made adjacent. | 23 | /// When sorted, to-be-merged segments will be made adjacent. |
| 24 | /// Values are virtual address. | 24 | /// Values are virtual address. |
| 25 | data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataSegment.Id, u32) = .empty, | 25 | data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataId, u32) = .empty, |
| 26 | /// Each time a `data_segment` offset equals zero it indicates a new group, and | 26 | /// Each time a `data_segment` offset equals zero it indicates a new group, and |
| 27 | /// the next element in this array will contain the total merged segment size. | 27 | /// the next element in this array will contain the total merged segment size. |
| 28 | /// Value is the virtual memory address of the end of the segment. | 28 | /// Value is the virtual memory address of the end of the segment. |
| ... | @@ -120,7 +120,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -120,7 +120,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 120 | if (wasm.entry_resolution == .unresolved) { | 120 | if (wasm.entry_resolution == .unresolved) { |
| 121 | var err = try diags.addErrorWithNotes(1); | 121 | var err = try diags.addErrorWithNotes(1); |
| 122 | try err.addMsg("entry symbol '{s}' missing", .{name.slice(wasm)}); | 122 | try err.addMsg("entry symbol '{s}' missing", .{name.slice(wasm)}); |
| 123 | try err.addNote("'-fno-entry' suppresses this error", .{}); | 123 | err.addNote("'-fno-entry' suppresses this error", .{}); |
| 124 | } | 124 | } |
| 125 | } | 125 | } |
| 126 | } | 126 | } |
| ... | @@ -176,10 +176,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -176,10 +176,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 176 | }), @as(u32, undefined)); | 176 | }), @as(u32, undefined)); |
| 177 | for (wasm.object_data_segments.items, 0..) |*ds, i| { | 177 | for (wasm.object_data_segments.items, 0..) |*ds, i| { |
| 178 | if (!ds.flags.alive) continue; | 178 | if (!ds.flags.alive) continue; |
| 179 | const data_segment_index: Wasm.ObjectDataSegmentIndex = @enumFromInt(i); | 179 | const obj_seg_index: Wasm.ObjectDataSegment.Index = @enumFromInt(i); |
| 180 | any_passive_inits = any_passive_inits or ds.flags.is_passive or (import_memory and !wasm.isBss(ds.name)); | 180 | any_passive_inits = any_passive_inits or ds.flags.is_passive or (import_memory and !wasm.isBss(ds.name)); |
| 181 | _ = f.data_segments.putAssumeCapacityNoClobber(.pack(wasm, .{ | 181 | _ = f.data_segments.putAssumeCapacityNoClobber(.pack(wasm, .{ |
| 182 | .object = data_segment_index, | 182 | .object = obj_seg_index, |
| 183 | }), @as(u32, undefined)); | 183 | }), @as(u32, undefined)); |
| 184 | } | 184 | } |
| 185 | if (wasm.error_name_table_ref_count > 0) { | 185 | if (wasm.error_name_table_ref_count > 0) { |
| ... | @@ -229,7 +229,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -229,7 +229,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 229 | // For the purposes of sorting, they are implicitly all named ".data". | 229 | // For the purposes of sorting, they are implicitly all named ".data". |
| 230 | const Sort = struct { | 230 | const Sort = struct { |
| 231 | wasm: *const Wasm, | 231 | wasm: *const Wasm, |
| 232 | segments: []const Wasm.DataSegment.Id, | 232 | segments: []const Wasm.DataId, |
| 233 | pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool { | 233 | pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool { |
| 234 | const lhs_segment = ctx.segments[lhs]; | 234 | const lhs_segment = ctx.segments[lhs]; |
| 235 | const rhs_segment = ctx.segments[rhs]; | 235 | const rhs_segment = ctx.segments[rhs]; |
| ... | @@ -312,7 +312,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -312,7 +312,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 312 | const data_vaddr: u32 = @intCast(memory_ptr); | 312 | const data_vaddr: u32 = @intCast(memory_ptr); |
| 313 | { | 313 | { |
| 314 | var seen_tls: enum { before, during, after } = .before; | 314 | var seen_tls: enum { before, during, after } = .before; |
| 315 | var category: Wasm.DataSegment.Category = undefined; | 315 | var category: Wasm.DataId.Category = undefined; |
| 316 | for (segment_ids, segment_vaddrs, 0..) |segment_id, *segment_vaddr, i| { | 316 | for (segment_ids, segment_vaddrs, 0..) |segment_id, *segment_vaddr, i| { |
| 317 | const alignment = segment_id.alignment(wasm); | 317 | const alignment = segment_id.alignment(wasm); |
| 318 | category = segment_id.category(wasm); | 318 | category = segment_id.category(wasm); |
| ... | @@ -707,7 +707,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -707,7 +707,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 707 | 707 | ||
| 708 | if (!is_obj) { | 708 | if (!is_obj) { |
| 709 | for (wasm.uav_fixups.items) |uav_fixup| { | 709 | for (wasm.uav_fixups.items) |uav_fixup| { |
| 710 | const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index }); | 710 | const ds_id: Wasm.DataId = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index }); |
| 711 | const vaddr = f.data_segments.get(ds_id).?; | 711 | const vaddr = f.data_segments.get(ds_id).?; |
| 712 | if (!is64) { | 712 | if (!is64) { |
| 713 | mem.writeInt(u32, wasm.string_bytes.items[uav_fixup.offset..][0..4], vaddr, .little); | 713 | mem.writeInt(u32, wasm.string_bytes.items[uav_fixup.offset..][0..4], vaddr, .little); |
| ... | @@ -716,7 +716,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -716,7 +716,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 716 | } | 716 | } |
| 717 | } | 717 | } |
| 718 | for (wasm.nav_fixups.items) |nav_fixup| { | 718 | for (wasm.nav_fixups.items) |nav_fixup| { |
| 719 | const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index }); | 719 | const ds_id: Wasm.DataId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index }); |
| 720 | const vaddr = f.data_segments.get(ds_id).?; | 720 | const vaddr = f.data_segments.get(ds_id).?; |
| 721 | if (!is64) { | 721 | if (!is64) { |
| 722 | mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little); | 722 | mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little); |
| ... | @@ -862,7 +862,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -862,7 +862,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 862 | 862 | ||
| 863 | fn emitNameSection( | 863 | fn emitNameSection( |
| 864 | wasm: *Wasm, | 864 | wasm: *Wasm, |
| 865 | data_segments: *const std.AutoArrayHashMapUnmanaged(Wasm.DataSegment.Id, u32), | 865 | data_segments: *const std.AutoArrayHashMapUnmanaged(Wasm.DataId, u32), |
| 866 | binary_bytes: *std.ArrayListUnmanaged(u8), | 866 | binary_bytes: *std.ArrayListUnmanaged(u8), |
| 867 | ) !void { | 867 | ) !void { |
| 868 | const f = &wasm.flush_buffer; | 868 | const f = &wasm.flush_buffer; |
| ... | @@ -1137,9 +1137,9 @@ fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } { | ... | @@ -1137,9 +1137,9 @@ fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } { |
| 1137 | 1137 | ||
| 1138 | fn wantSegmentMerge( | 1138 | fn wantSegmentMerge( |
| 1139 | wasm: *const Wasm, | 1139 | wasm: *const Wasm, |
| 1140 | a_id: Wasm.DataSegment.Id, | 1140 | a_id: Wasm.DataId, |
| 1141 | b_id: Wasm.DataSegment.Id, | 1141 | b_id: Wasm.DataId, |
| 1142 | b_category: Wasm.DataSegment.Category, | 1142 | b_category: Wasm.DataId.Category, |
| 1143 | ) bool { | 1143 | ) bool { |
| 1144 | const a_category = a_id.category(wasm); | 1144 | const a_category = a_id.category(wasm); |
| 1145 | if (a_category != b_category) return false; | 1145 | if (a_category != b_category) return false; |
src/link/Wasm/Object.zig+105-79| ... | @@ -102,11 +102,7 @@ pub const Symbol = struct { | ... | @@ -102,11 +102,7 @@ pub const Symbol = struct { |
| 102 | const Pointee = union(enum) { | 102 | const Pointee = union(enum) { |
| 103 | function: Wasm.ObjectFunctionIndex, | 103 | function: Wasm.ObjectFunctionIndex, |
| 104 | function_import: ScratchSpace.FuncImportIndex, | 104 | function_import: ScratchSpace.FuncImportIndex, |
| 105 | data: struct { | 105 | data: Wasm.ObjectData.Index, |
| 106 | segment_index: Wasm.ObjectDataSegmentIndex, | ||
| 107 | segment_offset: u32, | ||
| 108 | size: u32, | ||
| 109 | }, | ||
| 110 | data_import: void, | 106 | data_import: void, |
| 111 | global: Wasm.ObjectGlobalIndex, | 107 | global: Wasm.ObjectGlobalIndex, |
| 112 | global_import: Wasm.GlobalImport.Index, | 108 | global_import: Wasm.GlobalImport.Index, |
| ... | @@ -131,7 +127,7 @@ pub const ScratchSpace = struct { | ... | @@ -131,7 +127,7 @@ pub const ScratchSpace = struct { |
| 131 | const Pointee = union(std.wasm.ExternalKind) { | 127 | const Pointee = union(std.wasm.ExternalKind) { |
| 132 | function: Wasm.ObjectFunctionIndex, | 128 | function: Wasm.ObjectFunctionIndex, |
| 133 | table: Wasm.ObjectTableIndex, | 129 | table: Wasm.ObjectTableIndex, |
| 134 | memory: Wasm.ObjectMemoryIndex, | 130 | memory: Wasm.ObjectMemory.Index, |
| 135 | global: Wasm.ObjectGlobalIndex, | 131 | global: Wasm.ObjectGlobalIndex, |
| 136 | }; | 132 | }; |
| 137 | }; | 133 | }; |
| ... | @@ -184,8 +180,9 @@ pub fn parse( | ... | @@ -184,8 +180,9 @@ pub fn parse( |
| 184 | must_link: bool, | 180 | must_link: bool, |
| 185 | gc_sections: bool, | 181 | gc_sections: bool, |
| 186 | ) anyerror!Object { | 182 | ) anyerror!Object { |
| 187 | const gpa = wasm.base.comp.gpa; | 183 | const comp = wasm.base.comp; |
| 188 | const diags = &wasm.base.comp.link_diags; | 184 | const gpa = comp.gpa; |
| 185 | const diags = &comp.link_diags; | ||
| 189 | 186 | ||
| 190 | var pos: usize = 0; | 187 | var pos: usize = 0; |
| 191 | 188 | ||
| ... | @@ -334,12 +331,16 @@ pub fn parse( | ... | @@ -334,12 +331,16 @@ pub fn parse( |
| 334 | const segment_index, pos = readLeb(u32, bytes, pos); | 331 | const segment_index, pos = readLeb(u32, bytes, pos); |
| 335 | const segment_offset, pos = readLeb(u32, bytes, pos); | 332 | const segment_offset, pos = readLeb(u32, bytes, pos); |
| 336 | const size, pos = readLeb(u32, bytes, pos); | 333 | const size, pos = readLeb(u32, bytes, pos); |
| 337 | 334 | try wasm.object_datas.append(gpa, .{ | |
| 338 | symbol.pointee = .{ .data = .{ | 335 | .segment = @enumFromInt(data_segment_start + segment_index), |
| 339 | .segment_index = @enumFromInt(data_segment_start + segment_index), | 336 | .offset = segment_offset, |
| 340 | .segment_offset = segment_offset, | ||
| 341 | .size = size, | 337 | .size = size, |
| 342 | } }; | 338 | .name = symbol.name, |
| 339 | .flags = symbol.flags, | ||
| 340 | }); | ||
| 341 | symbol.pointee = .{ | ||
| 342 | .data = @enumFromInt(wasm.object_datas.items.len - 1), | ||
| 343 | }; | ||
| 343 | } | 344 | } |
| 344 | }, | 345 | }, |
| 345 | .section => { | 346 | .section => { |
| ... | @@ -405,7 +406,6 @@ pub fn parse( | ... | @@ -405,7 +406,6 @@ pub fn parse( |
| 405 | return error.UnrecognizedSymbolType; | 406 | return error.UnrecognizedSymbolType; |
| 406 | }, | 407 | }, |
| 407 | } | 408 | } |
| 408 | log.debug("found symbol: {}", .{symbol}); | ||
| 409 | } | 409 | } |
| 410 | }, | 410 | }, |
| 411 | } | 411 | } |
| ... | @@ -450,22 +450,10 @@ pub fn parse( | ... | @@ -450,22 +450,10 @@ pub fn parse( |
| 450 | .MEMORY_ADDR_TLS_SLEB64, | 450 | .MEMORY_ADDR_TLS_SLEB64, |
| 451 | => { | 451 | => { |
| 452 | const addend: i32, pos = readLeb(i32, bytes, pos); | 452 | const addend: i32, pos = readLeb(i32, bytes, pos); |
| 453 | const sym_section = ss.symbol_table.items[index].pointee.data; | ||
| 454 | if (sym_section.segment_offset != 0) { | ||
| 455 | return diags.failParse(path, "data symbol {d} has nonzero offset {d}", .{ | ||
| 456 | index, sym_section.segment_offset, | ||
| 457 | }); | ||
| 458 | } | ||
| 459 | const seg_size = sym_section.segment_index.ptr(wasm).payload.len; | ||
| 460 | if (sym_section.size != seg_size) { | ||
| 461 | return diags.failParse(path, "data symbol {d} has size {d}, inequal to corresponding data segment {d} size {d}", .{ | ||
| 462 | index, sym_section.size, @intFromEnum(sym_section.segment_index), seg_size, | ||
| 463 | }); | ||
| 464 | } | ||
| 465 | wasm.object_relocations.appendAssumeCapacity(.{ | 453 | wasm.object_relocations.appendAssumeCapacity(.{ |
| 466 | .tag = tag, | 454 | .tag = tag, |
| 467 | .offset = offset, | 455 | .offset = offset, |
| 468 | .pointee = .{ .data_segment = sym_section.segment_index }, | 456 | .pointee = .{ .data = ss.symbol_table.items[index].pointee.data }, |
| 469 | .addend = addend, | 457 | .addend = addend, |
| 470 | }); | 458 | }); |
| 471 | }, | 459 | }, |
| ... | @@ -651,7 +639,15 @@ pub fn parse( | ... | @@ -651,7 +639,15 @@ pub fn parse( |
| 651 | const memories_len, pos = readLeb(u32, bytes, pos); | 639 | const memories_len, pos = readLeb(u32, bytes, pos); |
| 652 | for (try wasm.object_memories.addManyAsSlice(gpa, memories_len)) |*memory| { | 640 | for (try wasm.object_memories.addManyAsSlice(gpa, memories_len)) |*memory| { |
| 653 | const limits, pos = readLimits(bytes, pos); | 641 | const limits, pos = readLimits(bytes, pos); |
| 654 | memory.* = .{ .limits = limits }; | 642 | memory.* = .{ |
| 643 | .name = .none, | ||
| 644 | .flags = .{ | ||
| 645 | .limits_has_max = limits.flags.has_max, | ||
| 646 | .limits_is_shared = limits.flags.is_shared, | ||
| 647 | }, | ||
| 648 | .limits_min = limits.min, | ||
| 649 | .limits_max = limits.max, | ||
| 650 | }; | ||
| 655 | } | 651 | } |
| 656 | }, | 652 | }, |
| 657 | .global => { | 653 | .global => { |
| ... | @@ -722,7 +718,6 @@ pub fn parse( | ... | @@ -722,7 +718,6 @@ pub fn parse( |
| 722 | } | 718 | } |
| 723 | }, | 719 | }, |
| 724 | .data => { | 720 | .data => { |
| 725 | const start = pos; | ||
| 726 | const count, pos = readLeb(u32, bytes, pos); | 721 | const count, pos = readLeb(u32, bytes, pos); |
| 727 | for (try wasm.object_data_segments.addManyAsSlice(gpa, count)) |*elem| { | 722 | for (try wasm.object_data_segments.addManyAsSlice(gpa, count)) |*elem| { |
| 728 | const flags, pos = readEnum(DataSegmentFlags, bytes, pos); | 723 | const flags, pos = readEnum(DataSegmentFlags, bytes, pos); |
| ... | @@ -733,13 +728,10 @@ pub fn parse( | ... | @@ -733,13 +728,10 @@ pub fn parse( |
| 733 | //const expr, pos = if (flags != .passive) try readInit(wasm, bytes, pos) else .{ .none, pos }; | 728 | //const expr, pos = if (flags != .passive) try readInit(wasm, bytes, pos) else .{ .none, pos }; |
| 734 | if (flags != .passive) pos = try skipInit(bytes, pos); | 729 | if (flags != .passive) pos = try skipInit(bytes, pos); |
| 735 | const data_len, pos = readLeb(u32, bytes, pos); | 730 | const data_len, pos = readLeb(u32, bytes, pos); |
| 736 | const segment_offset: u32 = @intCast(pos - start); | ||
| 737 | const payload = try wasm.addRelocatableDataPayload(bytes[pos..][0..data_len]); | 731 | const payload = try wasm.addRelocatableDataPayload(bytes[pos..][0..data_len]); |
| 738 | pos += data_len; | 732 | pos += data_len; |
| 739 | elem.* = .{ | 733 | elem.* = .{ |
| 740 | .payload = payload, | 734 | .payload = payload, |
| 741 | .segment_offset = segment_offset, | ||
| 742 | .section_index = section_index, | ||
| 743 | .name = .none, // Populated from symbol table | 735 | .name = .none, // Populated from symbol table |
| 744 | .flags = .{}, // Populated from symbol table and segment_info | 736 | .flags = .{}, // Populated from symbol table and segment_info |
| 745 | }; | 737 | }; |
| ... | @@ -751,20 +743,56 @@ pub fn parse( | ... | @@ -751,20 +743,56 @@ pub fn parse( |
| 751 | } | 743 | } |
| 752 | if (!saw_linking_section) return error.MissingLinkingSection; | 744 | if (!saw_linking_section) return error.MissingLinkingSection; |
| 753 | 745 | ||
| 746 | const target_features = comp.root_mod.resolved_target.result.cpu.features; | ||
| 747 | |||
| 754 | if (has_tls) { | 748 | if (has_tls) { |
| 755 | const cpu_features = wasm.base.comp.root_mod.resolved_target.result.cpu.features; | 749 | if (!std.Target.wasm.featureSetHas(target_features, .atomics)) |
| 756 | if (!std.Target.wasm.featureSetHas(cpu_features, .atomics)) | ||
| 757 | return diags.failParse(path, "object has TLS segment but target CPU feature atomics is disabled", .{}); | 750 | return diags.failParse(path, "object has TLS segment but target CPU feature atomics is disabled", .{}); |
| 758 | if (!std.Target.wasm.featureSetHas(cpu_features, .bulk_memory)) | 751 | if (!std.Target.wasm.featureSetHas(target_features, .bulk_memory)) |
| 759 | return diags.failParse(path, "object has TLS segment but target CPU feature bulk_memory is disabled", .{}); | 752 | return diags.failParse(path, "object has TLS segment but target CPU feature bulk_memory is disabled", .{}); |
| 760 | } | 753 | } |
| 761 | 754 | ||
| 762 | const features = opt_features orelse return error.MissingFeatures; | 755 | const features = opt_features orelse return error.MissingFeatures; |
| 763 | if (true) @panic("iterate features, match against target features"); | 756 | for (features.slice(wasm)) |feat| { |
| 757 | log.debug("feature: {s}{s}", .{ @tagName(feat.prefix), @tagName(feat.tag) }); | ||
| 758 | switch (feat.prefix) { | ||
| 759 | .invalid => unreachable, | ||
| 760 | .@"-" => switch (feat.tag) { | ||
| 761 | .@"shared-mem" => if (comp.config.shared_memory) { | ||
| 762 | return diags.failParse(path, "object forbids shared-mem but compilation enables it", .{}); | ||
| 763 | }, | ||
| 764 | else => { | ||
| 765 | const f = feat.tag.toCpuFeature().?; | ||
| 766 | if (std.Target.wasm.featureSetHas(target_features, f)) { | ||
| 767 | return diags.failParse( | ||
| 768 | path, | ||
| 769 | "object forbids {s} but specified target features include {s}", | ||
| 770 | .{ @tagName(feat.tag), @tagName(f) }, | ||
| 771 | ); | ||
| 772 | } | ||
| 773 | }, | ||
| 774 | }, | ||
| 775 | .@"+", .@"=" => switch (feat.tag) { | ||
| 776 | .@"shared-mem" => if (!comp.config.shared_memory) { | ||
| 777 | return diags.failParse(path, "object requires shared-mem but compilation disables it", .{}); | ||
| 778 | }, | ||
| 779 | else => { | ||
| 780 | const f = feat.tag.toCpuFeature().?; | ||
| 781 | if (!std.Target.wasm.featureSetHas(target_features, f)) { | ||
| 782 | return diags.failParse( | ||
| 783 | path, | ||
| 784 | "object requires {s} but specified target features exclude {s}", | ||
| 785 | .{ @tagName(feat.tag), @tagName(f) }, | ||
| 786 | ); | ||
| 787 | } | ||
| 788 | }, | ||
| 789 | }, | ||
| 790 | } | ||
| 791 | } | ||
| 764 | 792 | ||
| 765 | // Apply function type information. | 793 | // Apply function type information. |
| 766 | for (ss.func_types.items, wasm.object_functions.items[functions_start..]) |func_type, *func| { | 794 | for (ss.func_type_indexes.items, wasm.object_functions.items[functions_start..]) |func_type, *func| { |
| 767 | func.type_index = func_type; | 795 | func.type_index = func_type.ptr(ss).*; |
| 768 | } | 796 | } |
| 769 | 797 | ||
| 770 | // Apply symbol table information. | 798 | // Apply symbol table information. |
| ... | @@ -782,15 +810,21 @@ pub fn parse( | ... | @@ -782,15 +810,21 @@ pub fn parse( |
| 782 | if (gop.value_ptr.type != fn_ty_index) { | 810 | if (gop.value_ptr.type != fn_ty_index) { |
| 783 | var err = try diags.addErrorWithNotes(2); | 811 | var err = try diags.addErrorWithNotes(2); |
| 784 | try err.addMsg("symbol '{s}' mismatching function signatures", .{name.slice(wasm)}); | 812 | try err.addMsg("symbol '{s}' mismatching function signatures", .{name.slice(wasm)}); |
| 785 | try err.addSrcNote(gop.value_ptr.source_location, "imported as {} here", .{gop.value_ptr.type.fmt(wasm)}); | 813 | gop.value_ptr.source_location.addNote(wasm, &err, "imported as {} here", .{ |
| 786 | try err.addSrcNote(source_location, "imported as {} here", .{fn_ty_index.fmt(wasm)}); | 814 | gop.value_ptr.type.fmt(wasm), |
| 815 | }); | ||
| 816 | source_location.addNote(wasm, &err, "imported as {} here", .{fn_ty_index.fmt(wasm)}); | ||
| 787 | continue; | 817 | continue; |
| 788 | } | 818 | } |
| 789 | if (gop.value_ptr.module_name != ptr.module_name) { | 819 | if (gop.value_ptr.module_name != ptr.module_name.toOptional()) { |
| 790 | var err = try diags.addErrorWithNotes(2); | 820 | var err = try diags.addErrorWithNotes(2); |
| 791 | try err.addMsg("symbol '{s}' mismatching module names", .{name.slice(wasm)}); | 821 | try err.addMsg("symbol '{s}' mismatching module names", .{name.slice(wasm)}); |
| 792 | try err.addSrcNote(gop.value_ptr.source_location, "module '{s}' here", .{gop.value_ptr.module_name.slice(wasm)}); | 822 | if (gop.value_ptr.module_name.slice(wasm)) |module_name| { |
| 793 | try err.addSrcNote(source_location, "module '{s}' here", .{ptr.module_name.slice(wasm)}); | 823 | gop.value_ptr.source_location.addNote(wasm, &err, "module '{s}' here", .{module_name}); |
| 824 | } else { | ||
| 825 | gop.value_ptr.source_location.addNote(wasm, &err, "no module here", .{}); | ||
| 826 | } | ||
| 827 | source_location.addNote(wasm, &err, "module '{s}' here", .{ptr.module_name.slice(wasm)}); | ||
| 794 | continue; | 828 | continue; |
| 795 | } | 829 | } |
| 796 | if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong; | 830 | if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong; |
| ... | @@ -799,7 +833,7 @@ pub fn parse( | ... | @@ -799,7 +833,7 @@ pub fn parse( |
| 799 | } else { | 833 | } else { |
| 800 | gop.value_ptr.* = .{ | 834 | gop.value_ptr.* = .{ |
| 801 | .flags = symbol.flags, | 835 | .flags = symbol.flags, |
| 802 | .module_name = ptr.module_name, | 836 | .module_name = ptr.module_name.toOptional(), |
| 803 | .source_location = source_location, | 837 | .source_location = source_location, |
| 804 | .resolution = .unresolved, | 838 | .resolution = .unresolved, |
| 805 | .type = fn_ty_index, | 839 | .type = fn_ty_index, |
| ... | @@ -808,7 +842,7 @@ pub fn parse( | ... | @@ -808,7 +842,7 @@ pub fn parse( |
| 808 | }, | 842 | }, |
| 809 | .function => |index| { | 843 | .function => |index| { |
| 810 | assert(!symbol.flags.undefined); | 844 | assert(!symbol.flags.undefined); |
| 811 | const ptr = index.ptr(); | 845 | const ptr = index.ptr(wasm); |
| 812 | ptr.name = symbol.name; | 846 | ptr.name = symbol.name; |
| 813 | ptr.flags = symbol.flags; | 847 | ptr.flags = symbol.flags; |
| 814 | if (symbol.flags.binding == .local) continue; // No participation in symbol resolution. | 848 | if (symbol.flags.binding == .local) continue; // No participation in symbol resolution. |
| ... | @@ -818,35 +852,46 @@ pub fn parse( | ... | @@ -818,35 +852,46 @@ pub fn parse( |
| 818 | if (gop.value_ptr.type != ptr.type_index) { | 852 | if (gop.value_ptr.type != ptr.type_index) { |
| 819 | var err = try diags.addErrorWithNotes(2); | 853 | var err = try diags.addErrorWithNotes(2); |
| 820 | try err.addMsg("function signature mismatch: {s}", .{name.slice(wasm)}); | 854 | try err.addMsg("function signature mismatch: {s}", .{name.slice(wasm)}); |
| 821 | try err.addSrcNote(gop.value_ptr.source_location, "exported as {} here", .{ptr.type_index.fmt(wasm)}); | 855 | gop.value_ptr.source_location.addNote(wasm, &err, "exported as {} here", .{ |
| 822 | const word = if (gop.value_ptr.resolution == .none) "imported" else "exported"; | 856 | ptr.type_index.fmt(wasm), |
| 823 | try err.addSrcNote(source_location, "{s} as {} here", .{ word, gop.value_ptr.type.fmt(wasm) }); | 857 | }); |
| 858 | const word = if (gop.value_ptr.resolution == .unresolved) "imported" else "exported"; | ||
| 859 | source_location.addNote(wasm, &err, "{s} as {} here", .{ word, gop.value_ptr.type.fmt(wasm) }); | ||
| 824 | continue; | 860 | continue; |
| 825 | } | 861 | } |
| 826 | if (gop.value_ptr.resolution == .none or gop.value_ptr.flags.binding == .weak) { | 862 | if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) { |
| 827 | // Intentional: if they're both weak, take the last one. | 863 | // Intentional: if they're both weak, take the last one. |
| 828 | gop.value_ptr.source_location = source_location; | 864 | gop.value_ptr.source_location = source_location; |
| 829 | gop.value_ptr.module_name = host_name; | 865 | gop.value_ptr.module_name = host_name; |
| 830 | gop.value_ptr.resolution = .fromObjectFunction(index); | 866 | gop.value_ptr.resolution = .fromObjectFunction(wasm, index); |
| 831 | continue; | 867 | continue; |
| 832 | } | 868 | } |
| 833 | var err = try diags.addErrorWithNotes(2); | 869 | var err = try diags.addErrorWithNotes(2); |
| 834 | try err.addMsg("symbol collision: {s}", .{name.slice(wasm)}); | 870 | try err.addMsg("symbol collision: {s}", .{name.slice(wasm)}); |
| 835 | try err.addSrcNote(gop.value_ptr.source_location, "exported as {} here", .{ptr.type_index.fmt(wasm)}); | 871 | gop.value_ptr.source_location.addNote(wasm, &err, "exported as {} here", .{ptr.type_index.fmt(wasm)}); |
| 836 | try err.addSrcNote(source_location, "exported as {} here", .{gop.value_ptr.type.fmt(wasm)}); | 872 | source_location.addNote(wasm, &err, "exported as {} here", .{gop.value_ptr.type.fmt(wasm)}); |
| 837 | continue; | 873 | continue; |
| 838 | } else { | 874 | } else { |
| 839 | gop.value_ptr.* = .{ | 875 | gop.value_ptr.* = .{ |
| 840 | .flags = symbol.flags, | 876 | .flags = symbol.flags, |
| 841 | .module_name = host_name, | 877 | .module_name = host_name, |
| 842 | .source_location = source_location, | 878 | .source_location = source_location, |
| 843 | .resolution = .fromObjectFunction(index), | 879 | .resolution = .fromObjectFunction(wasm, index), |
| 844 | .type = ptr.type_index, | 880 | .type = ptr.type_index, |
| 845 | }; | 881 | }; |
| 846 | } | 882 | } |
| 847 | }, | 883 | }, |
| 848 | 884 | ||
| 849 | inline .global, .global_import, .table, .table_import => |i| { | 885 | inline .global_import, .table_import => |i| { |
| 886 | const ptr = i.value(wasm); | ||
| 887 | assert(i.key(wasm).toOptional() == symbol.name); // TODO | ||
| 888 | ptr.flags = symbol.flags; | ||
| 889 | if (symbol.flags.undefined and symbol.flags.binding == .local) { | ||
| 890 | const name = i.key(wasm).slice(wasm); | ||
| 891 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); | ||
| 892 | } | ||
| 893 | }, | ||
| 894 | inline .global, .table => |i| { | ||
| 850 | const ptr = i.ptr(wasm); | 895 | const ptr = i.ptr(wasm); |
| 851 | ptr.name = symbol.name; | 896 | ptr.name = symbol.name; |
| 852 | ptr.flags = symbol.flags; | 897 | ptr.flags = symbol.flags; |
| ... | @@ -857,10 +902,11 @@ pub fn parse( | ... | @@ -857,10 +902,11 @@ pub fn parse( |
| 857 | }, | 902 | }, |
| 858 | .section => |i| { | 903 | .section => |i| { |
| 859 | // Name is provided by the section directly; symbol table does not have it. | 904 | // Name is provided by the section directly; symbol table does not have it. |
| 860 | const ptr = i.ptr(wasm); | 905 | //const ptr = i.ptr(wasm); |
| 861 | ptr.flags = symbol.flags; | 906 | //ptr.flags = symbol.flags; |
| 907 | _ = i; | ||
| 862 | if (symbol.flags.undefined and symbol.flags.binding == .local) { | 908 | if (symbol.flags.undefined and symbol.flags.binding == .local) { |
| 863 | const name = ptr.name.slice(wasm); | 909 | const name = symbol.name.slice(wasm).?; |
| 864 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); | 910 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); |
| 865 | } | 911 | } |
| 866 | }, | 912 | }, |
| ... | @@ -868,15 +914,7 @@ pub fn parse( | ... | @@ -868,15 +914,7 @@ pub fn parse( |
| 868 | const name = symbol.name.unwrap().?; | 914 | const name = symbol.name.unwrap().?; |
| 869 | log.warn("TODO data import '{s}'", .{name.slice(wasm)}); | 915 | log.warn("TODO data import '{s}'", .{name.slice(wasm)}); |
| 870 | }, | 916 | }, |
| 871 | .data => |data| { | 917 | .data => continue, // `wasm.object_datas` has already been populated. |
| 872 | const ptr = data.ptr(wasm); | ||
| 873 | const is_passive = ptr.flags.is_passive; | ||
| 874 | ptr.name = symbol.name; | ||
| 875 | ptr.flags = symbol.flags; | ||
| 876 | ptr.flags.is_passive = is_passive; | ||
| 877 | ptr.offset = data.segment_offset; | ||
| 878 | ptr.size = data.size; | ||
| 879 | }, | ||
| 880 | }; | 918 | }; |
| 881 | 919 | ||
| 882 | // Apply export section info. This is done after the symbol table above so | 920 | // Apply export section info. This is done after the symbol table above so |
| ... | @@ -957,18 +995,6 @@ pub fn parse( | ... | @@ -957,18 +995,6 @@ pub fn parse( |
| 957 | .off = functions_start, | 995 | .off = functions_start, |
| 958 | .len = @intCast(wasm.object_functions.items.len - functions_start), | 996 | .len = @intCast(wasm.object_functions.items.len - functions_start), |
| 959 | }, | 997 | }, |
| 960 | .globals = .{ | ||
| 961 | .off = globals_start, | ||
| 962 | .len = @intCast(wasm.object_globals.items.len - globals_start), | ||
| 963 | }, | ||
| 964 | .tables = .{ | ||
| 965 | .off = tables_start, | ||
| 966 | .len = @intCast(wasm.object_tables.items.len - tables_start), | ||
| 967 | }, | ||
| 968 | .memories = .{ | ||
| 969 | .off = memories_start, | ||
| 970 | .len = @intCast(wasm.object_memories.items.len - memories_start), | ||
| 971 | }, | ||
| 972 | .function_imports = .{ | 998 | .function_imports = .{ |
| 973 | .off = function_imports_start, | 999 | .off = function_imports_start, |
| 974 | .len = @intCast(wasm.object_function_imports.entries.len - function_imports_start), | 1000 | .len = @intCast(wasm.object_function_imports.entries.len - function_imports_start), |
| ... | @@ -979,7 +1005,7 @@ pub fn parse( | ... | @@ -979,7 +1005,7 @@ pub fn parse( |
| 979 | }, | 1005 | }, |
| 980 | .table_imports = .{ | 1006 | .table_imports = .{ |
| 981 | .off = table_imports_start, | 1007 | .off = table_imports_start, |
| 982 | .len = @intCast(wasm.object_table_imports.items.len - table_imports_start), | 1008 | .len = @intCast(wasm.object_table_imports.entries.len - table_imports_start), |
| 983 | }, | 1009 | }, |
| 984 | .init_funcs = .{ | 1010 | .init_funcs = .{ |
| 985 | .off = init_funcs_start, | 1011 | .off = init_funcs_start, |