mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 02:44:43 +01:00
wasm linker: fix crashes when parsing compiler_rt
This commit is contained in:
parent
4b9dc2922f
commit
1a4c5837fe
10 changed files with 526 additions and 381 deletions
|
|
@ -97,15 +97,12 @@ pub const Diags = struct {
|
|||
err_msg.msg = try std.fmt.allocPrint(gpa, format, args);
|
||||
}
|
||||
|
||||
pub fn addNote(
|
||||
err: *ErrorWithNotes,
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) error{OutOfMemory}!void {
|
||||
pub fn addNote(err: *ErrorWithNotes, comptime format: []const u8, args: anytype) void {
|
||||
const gpa = err.diags.gpa;
|
||||
const msg = std.fmt.allocPrint(gpa, format, args) catch return err.diags.setAllocFailure();
|
||||
const err_msg = &err.diags.msgs.items[err.index];
|
||||
assert(err.note_slot < err_msg.notes.len);
|
||||
err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) };
|
||||
err_msg.notes[err.note_slot] = .{ .msg = msg };
|
||||
err.note_slot += 1;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3394,7 +3394,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
|
|||
// TODO verify `getMaxNumberOfPhdrs()` is accurate and convert this into no-op
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("fatal linker error: not enough space reserved for EHDR and PHDR table", .{});
|
||||
try err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space });
|
||||
err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space });
|
||||
}
|
||||
|
||||
phdr_table_load.p_filesz = needed_size + ehsize;
|
||||
|
|
@ -4545,12 +4545,12 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
|
|||
for (refs.items[0..nrefs]) |ref| {
|
||||
const atom_ptr = self.atom(ref).?;
|
||||
const file_ptr = atom_ptr.file(self).?;
|
||||
try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
|
||||
err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
|
||||
}
|
||||
|
||||
if (refs.items.len > max_notes) {
|
||||
const remaining = refs.items.len - max_notes;
|
||||
try err.addNote("referenced {d} more times", .{remaining});
|
||||
err.addNote("referenced {d} more times", .{remaining});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4567,17 +4567,17 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor
|
|||
|
||||
var err = try diags.addErrorWithNotes(nnotes + 1);
|
||||
try err.addMsg("duplicate symbol definition: {s}", .{sym.name(self)});
|
||||
try err.addNote("defined by {}", .{sym.file(self).?.fmtPath()});
|
||||
err.addNote("defined by {}", .{sym.file(self).?.fmtPath()});
|
||||
|
||||
var inote: usize = 0;
|
||||
while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
|
||||
const file_ptr = self.file(notes.items[inote]).?;
|
||||
try err.addNote("defined by {}", .{file_ptr.fmtPath()});
|
||||
err.addNote("defined by {}", .{file_ptr.fmtPath()});
|
||||
}
|
||||
|
||||
if (notes.items.len > max_notes) {
|
||||
const remaining = notes.items.len - max_notes;
|
||||
try err.addNote("defined {d} more times", .{remaining});
|
||||
err.addNote("defined {d} more times", .{remaining});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4601,7 +4601,7 @@ pub fn addFileError(
|
|||
const diags = &self.base.comp.link_diags;
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg(format, args);
|
||||
try err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()});
|
||||
err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()});
|
||||
}
|
||||
|
||||
pub fn failFile(
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) Re
|
|||
relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
|
||||
rel.r_offset,
|
||||
});
|
||||
try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
return error.RelocFailure;
|
||||
}
|
||||
|
||||
|
|
@ -539,7 +539,7 @@ fn reportTextRelocError(
|
|||
rel.r_offset,
|
||||
symbol.name(elf_file),
|
||||
});
|
||||
try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
return error.RelocFailure;
|
||||
}
|
||||
|
||||
|
|
@ -555,8 +555,8 @@ fn reportPicError(
|
|||
rel.r_offset,
|
||||
symbol.name(elf_file),
|
||||
});
|
||||
try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
try err.addNote("recompile with -fPIC", .{});
|
||||
err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
err.addNote("recompile with -fPIC", .{});
|
||||
return error.RelocFailure;
|
||||
}
|
||||
|
||||
|
|
@ -572,8 +572,8 @@ fn reportNoPicError(
|
|||
rel.r_offset,
|
||||
symbol.name(elf_file),
|
||||
});
|
||||
try err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
try err.addNote("recompile with -fno-PIC", .{});
|
||||
err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
|
||||
err.addNote("recompile with -fno-PIC", .{});
|
||||
return error.RelocFailure;
|
||||
}
|
||||
|
||||
|
|
@ -1187,7 +1187,7 @@ const x86_64 = struct {
|
|||
x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..]) catch {
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("could not relax {s}", .{@tagName(r_type)});
|
||||
try err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
atom.file(elf_file).?.fmtPath(),
|
||||
atom.name(elf_file),
|
||||
rel.r_offset,
|
||||
|
|
@ -1332,7 +1332,7 @@ const x86_64 = struct {
|
|||
relocation.fmtRelocType(rels[0].r_type(), .x86_64),
|
||||
relocation.fmtRelocType(rels[1].r_type(), .x86_64),
|
||||
});
|
||||
try err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
self.file(elf_file).?.fmtPath(),
|
||||
self.name(elf_file),
|
||||
rels[0].r_offset,
|
||||
|
|
@ -1388,7 +1388,7 @@ const x86_64 = struct {
|
|||
relocation.fmtRelocType(rels[0].r_type(), .x86_64),
|
||||
relocation.fmtRelocType(rels[1].r_type(), .x86_64),
|
||||
});
|
||||
try err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
self.file(elf_file).?.fmtPath(),
|
||||
self.name(elf_file),
|
||||
rels[0].r_offset,
|
||||
|
|
@ -1485,7 +1485,7 @@ const x86_64 = struct {
|
|||
relocation.fmtRelocType(rels[0].r_type(), .x86_64),
|
||||
relocation.fmtRelocType(rels[1].r_type(), .x86_64),
|
||||
});
|
||||
try err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
self.file(elf_file).?.fmtPath(),
|
||||
self.name(elf_file),
|
||||
rels[0].r_offset,
|
||||
|
|
@ -1672,7 +1672,7 @@ const aarch64 = struct {
|
|||
// TODO: relax
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("TODO: relax ADR_GOT_PAGE", .{});
|
||||
try err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
atom.file(elf_file).?.fmtPath(),
|
||||
atom.name(elf_file),
|
||||
r_offset,
|
||||
|
|
@ -1959,7 +1959,7 @@ const riscv = struct {
|
|||
// TODO: implement searching forward
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("TODO: find HI20 paired reloc scanning forward", .{});
|
||||
try err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
atom.file(elf_file).?.fmtPath(),
|
||||
atom.name(elf_file),
|
||||
rel.r_offset,
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
|
|||
if (!isNull(data[end .. end + sh_entsize])) {
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("string not null terminated", .{});
|
||||
try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
|
||||
err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
|
||||
return error.LinkFailure;
|
||||
}
|
||||
end += sh_entsize;
|
||||
|
|
@ -812,7 +812,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
|
|||
if (shdr.sh_size % sh_entsize != 0) {
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("size not a multiple of sh_entsize", .{});
|
||||
try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
|
||||
err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
|
||||
return error.LinkFailure;
|
||||
}
|
||||
|
||||
|
|
@ -889,8 +889,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
|
|||
const res = imsec.findSubsection(@intCast(esym.st_value)) orelse {
|
||||
var err = try diags.addErrorWithNotes(2);
|
||||
try err.addMsg("invalid symbol value: {x}", .{esym.st_value});
|
||||
try err.addNote("for symbol {s}", .{sym.name(elf_file)});
|
||||
try err.addNote("in {}", .{self.fmtPath()});
|
||||
err.addNote("for symbol {s}", .{sym.name(elf_file)});
|
||||
err.addNote("in {}", .{self.fmtPath()});
|
||||
return error.LinkFailure;
|
||||
};
|
||||
|
||||
|
|
@ -915,7 +915,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
|
|||
const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse {
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});
|
||||
try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
|
||||
err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
|
||||
return error.LinkFailure;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -611,7 +611,7 @@ fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void {
|
|||
relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
|
||||
rel.r_offset,
|
||||
});
|
||||
try err.addNote("in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});
|
||||
err.addNote("in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});
|
||||
return error.RelocFailure;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1572,21 +1572,21 @@ fn reportUndefs(self: *MachO) !void {
|
|||
try err.addMsg("undefined symbol: {s}", .{undef_sym.getName(self)});
|
||||
|
||||
switch (notes) {
|
||||
.force_undefined => try err.addNote("referenced with linker flag -u", .{}),
|
||||
.entry => try err.addNote("referenced with linker flag -e", .{}),
|
||||
.dyld_stub_binder, .objc_msgsend => try err.addNote("referenced implicitly", .{}),
|
||||
.force_undefined => err.addNote("referenced with linker flag -u", .{}),
|
||||
.entry => err.addNote("referenced with linker flag -e", .{}),
|
||||
.dyld_stub_binder, .objc_msgsend => err.addNote("referenced implicitly", .{}),
|
||||
.refs => |refs| {
|
||||
var inote: usize = 0;
|
||||
while (inote < @min(refs.items.len, max_notes)) : (inote += 1) {
|
||||
const ref = refs.items[inote];
|
||||
const file = self.getFile(ref.file).?;
|
||||
const atom = ref.getAtom(self).?;
|
||||
try err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) });
|
||||
err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) });
|
||||
}
|
||||
|
||||
if (refs.items.len > max_notes) {
|
||||
const remaining = refs.items.len - max_notes;
|
||||
try err.addNote("referenced {d} more times", .{remaining});
|
||||
err.addNote("referenced {d} more times", .{remaining});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -3473,8 +3473,8 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo
|
|||
seg_id,
|
||||
seg.segName(),
|
||||
});
|
||||
try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{});
|
||||
try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
|
||||
err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{});
|
||||
err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
|
||||
}
|
||||
|
||||
seg.vmsize = needed_size;
|
||||
|
|
@ -3776,7 +3776,7 @@ pub fn reportParseError2(
|
|||
const diags = &self.base.comp.link_diags;
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg(format, args);
|
||||
try err.addNote("while parsing {}", .{self.getFile(file_index).?.fmtPath()});
|
||||
err.addNote("while parsing {}", .{self.getFile(file_index).?.fmtPath()});
|
||||
}
|
||||
|
||||
fn reportMissingDependencyError(
|
||||
|
|
@ -3790,10 +3790,10 @@ fn reportMissingDependencyError(
|
|||
const diags = &self.base.comp.link_diags;
|
||||
var err = try diags.addErrorWithNotes(2 + checked_paths.len);
|
||||
try err.addMsg(format, args);
|
||||
try err.addNote("while resolving {s}", .{path});
|
||||
try err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});
|
||||
err.addNote("while resolving {s}", .{path});
|
||||
err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});
|
||||
for (checked_paths) |p| {
|
||||
try err.addNote("tried {s}", .{p});
|
||||
err.addNote("tried {s}", .{p});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3807,8 +3807,8 @@ fn reportDependencyError(
|
|||
const diags = &self.base.comp.link_diags;
|
||||
var err = try diags.addErrorWithNotes(2);
|
||||
try err.addMsg(format, args);
|
||||
try err.addNote("while parsing {s}", .{path});
|
||||
try err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});
|
||||
err.addNote("while parsing {s}", .{path});
|
||||
err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});
|
||||
}
|
||||
|
||||
fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
|
||||
|
|
@ -3838,17 +3838,17 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
|
|||
|
||||
var err = try diags.addErrorWithNotes(nnotes + 1);
|
||||
try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)});
|
||||
try err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()});
|
||||
err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()});
|
||||
|
||||
var inote: usize = 0;
|
||||
while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
|
||||
const file = self.getFile(notes.items[inote]).?;
|
||||
try err.addNote("defined by {}", .{file.fmtPath()});
|
||||
err.addNote("defined by {}", .{file.fmtPath()});
|
||||
}
|
||||
|
||||
if (notes.items.len > max_notes) {
|
||||
const remaining = notes.items.len - max_notes;
|
||||
try err.addNote("defined {d} more times", .{remaining});
|
||||
err.addNote("defined {d} more times", .{remaining});
|
||||
}
|
||||
}
|
||||
return error.HasDuplicates;
|
||||
|
|
|
|||
|
|
@ -909,8 +909,8 @@ const x86_64 = struct {
|
|||
rel.offset,
|
||||
rel.fmtPretty(.x86_64),
|
||||
});
|
||||
try err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)});
|
||||
try err.addNote("while parsing {}", .{self.getFile(macho_file).fmtPath()});
|
||||
err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)});
|
||||
err.addNote("while parsing {}", .{self.getFile(macho_file).fmtPath()});
|
||||
return error.RelaxFailUnexpectedInstruction;
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ object_tables: std.ArrayListUnmanaged(Table) = .empty,
|
|||
/// All memory imports for all objects.
|
||||
object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty,
|
||||
/// All parsed memory sections for all objects.
|
||||
object_memories: std.ArrayListUnmanaged(std.wasm.Memory) = .empty,
|
||||
object_memories: std.ArrayListUnmanaged(ObjectMemory) = .empty,
|
||||
|
||||
/// All relocations from all objects concatenated. `relocs_start` marks the end
|
||||
/// point of object relocations and start point of Zcu relocations.
|
||||
|
|
@ -119,8 +119,13 @@ object_relocations: std.MultiArrayList(ObjectRelocation) = .empty,
|
|||
/// by the (synthetic) __wasm_call_ctors function.
|
||||
object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty,
|
||||
|
||||
/// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations.
|
||||
object_data_segments: std.ArrayListUnmanaged(DataSegment) = .empty,
|
||||
/// The data section of an object has many segments. Each segment corresponds
|
||||
/// logically to an object file's .data section, or .rodata section. In
|
||||
/// the case of `-fdata-sections` there will be one segment per data symbol.
|
||||
object_data_segments: std.ArrayListUnmanaged(ObjectDataSegment) = .empty,
|
||||
/// Each segment has many data symbols. These correspond logically to global
|
||||
/// constants.
|
||||
object_datas: std.ArrayListUnmanaged(ObjectData) = .empty,
|
||||
/// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations.
|
||||
object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, CustomSegment) = .empty,
|
||||
|
||||
|
|
@ -457,6 +462,21 @@ pub const SourceLocation = enum(u32) {
|
|||
.source_location_index => @panic("TODO"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addNote(
|
||||
sl: SourceLocation,
|
||||
wasm: *Wasm,
|
||||
err: *link.Diags.ErrorWithNotes,
|
||||
comptime f: []const u8,
|
||||
args: anytype,
|
||||
) void {
|
||||
switch (sl.unpack(wasm)) {
|
||||
.none => err.addNote(f, args),
|
||||
.zig_object_nofile => err.addNote("zig compilation unit: " ++ f, args),
|
||||
.object_index => |i| err.addNote("{}: " ++ f, .{i.ptr(wasm).path} ++ args),
|
||||
.source_location_index => @panic("TODO"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// The lower bits of this ABI-match the flags here:
|
||||
|
|
@ -687,13 +707,13 @@ pub const UavsExeIndex = enum(u32) {
|
|||
|
||||
/// Used when emitting a relocatable object.
|
||||
pub const ZcuDataObj = extern struct {
|
||||
code: DataSegment.Payload,
|
||||
code: DataPayload,
|
||||
relocs: OutReloc.Slice,
|
||||
};
|
||||
|
||||
/// Used when not emitting a relocatable object.
|
||||
pub const ZcuDataExe = extern struct {
|
||||
code: DataSegment.Payload,
|
||||
code: DataPayload,
|
||||
/// Tracks how many references there are for the purposes of sorting data segments.
|
||||
count: u32,
|
||||
};
|
||||
|
|
@ -917,6 +937,10 @@ pub const FunctionImport = extern struct {
|
|||
return pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.getIndex(ip_index).?) });
|
||||
}
|
||||
|
||||
pub fn fromObjectFunction(wasm: *const Wasm, object_function: ObjectFunctionIndex) Resolution {
|
||||
return pack(wasm, .{ .object_function = object_function });
|
||||
}
|
||||
|
||||
pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool {
|
||||
return switch (r.unpack(wasm)) {
|
||||
.unresolved, .zcu_func => true,
|
||||
|
|
@ -988,7 +1012,7 @@ pub const Function = extern struct {
|
|||
section_index: ObjectSectionIndex,
|
||||
source_location: SourceLocation,
|
||||
|
||||
pub const Code = DataSegment.Payload;
|
||||
pub const Code = DataPayload;
|
||||
};
|
||||
|
||||
pub const GlobalImport = extern struct {
|
||||
|
|
@ -1283,12 +1307,30 @@ pub const ObjectGlobalIndex = enum(u32) {
|
|||
}
|
||||
};
|
||||
|
||||
/// Index into `Wasm.object_memories`.
|
||||
pub const ObjectMemoryIndex = enum(u32) {
|
||||
_,
|
||||
pub const ObjectMemory = extern struct {
|
||||
flags: SymbolFlags,
|
||||
name: OptionalString,
|
||||
limits_min: u32,
|
||||
limits_max: u32,
|
||||
|
||||
pub fn ptr(index: ObjectMemoryIndex, wasm: *const Wasm) *std.wasm.Memory {
|
||||
return &wasm.object_memories.items[@intFromEnum(index)];
|
||||
/// Index into `Wasm.object_memories`.
|
||||
pub const Index = enum(u32) {
|
||||
_,
|
||||
|
||||
pub fn ptr(index: Index, wasm: *const Wasm) *ObjectMemory {
|
||||
return &wasm.object_memories.items[@intFromEnum(index)];
|
||||
}
|
||||
};
|
||||
|
||||
pub fn limits(om: *const ObjectMemory) std.wasm.Limits {
|
||||
return .{
|
||||
.flags = .{
|
||||
.has_max = om.limits_has_max,
|
||||
.is_shared = om.limits_is_shared,
|
||||
},
|
||||
.min = om.limits_min,
|
||||
.max = om.limits_max,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1318,14 +1360,74 @@ pub const OptionalObjectFunctionIndex = enum(u32) {
|
|||
}
|
||||
};
|
||||
|
||||
pub const DataSegment = extern struct {
|
||||
pub const ObjectDataSegment = extern struct {
|
||||
/// `none` if segment info custom subsection is missing.
|
||||
name: OptionalString,
|
||||
flags: SymbolFlags,
|
||||
payload: DataPayload,
|
||||
|
||||
/// Index into `Wasm.object_data_segments`.
|
||||
pub const Index = enum(u32) {
|
||||
_,
|
||||
|
||||
pub fn ptr(i: Index, wasm: *const Wasm) *ObjectDataSegment {
|
||||
return &wasm.object_data_segments.items[@intFromEnum(i)];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/// A local or exported global const from an object file.
|
||||
pub const ObjectData = extern struct {
|
||||
segment: ObjectDataSegment.Index,
|
||||
/// Index into the object segment payload. Must be <= the segment's size.
|
||||
offset: u32,
|
||||
/// May be zero. `offset + size` must be <= the segment's size.
|
||||
size: u32,
|
||||
/// `none` if no symbol describes it.
|
||||
name: OptionalString,
|
||||
flags: SymbolFlags,
|
||||
payload: Payload,
|
||||
/// From the data segment start to the first byte of payload.
|
||||
segment_offset: u32,
|
||||
section_index: ObjectSectionIndex,
|
||||
|
||||
/// Index into `Wasm.object_datas`.
|
||||
pub const Index = enum(u32) {
|
||||
_,
|
||||
|
||||
pub fn ptr(i: Index, wasm: *const Wasm) *ObjectData {
|
||||
return &wasm.object_datas.items[@intFromEnum(i)];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
pub const DataPayload = extern struct {
|
||||
off: Off,
|
||||
/// The size in bytes of the data representing the segment within the section.
|
||||
len: u32,
|
||||
|
||||
pub const Off = enum(u32) {
|
||||
/// The payload is all zeroes (bss section).
|
||||
none = std.math.maxInt(u32),
|
||||
/// Points into string_bytes. No corresponding string_table entry.
|
||||
_,
|
||||
|
||||
pub fn unwrap(off: Off) ?u32 {
|
||||
return if (off == .none) null else @intFromEnum(off);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn slice(p: DataPayload, wasm: *const Wasm) []const u8 {
|
||||
return wasm.string_bytes.items[p.off.unwrap().?..][0..p.len];
|
||||
}
|
||||
};
|
||||
|
||||
/// A reference to a local or exported global const.
|
||||
pub const DataId = enum(u32) {
|
||||
__zig_error_names,
|
||||
__zig_error_name_table,
|
||||
/// First, an `ObjectDataSegment.Index`.
|
||||
/// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
|
||||
/// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
|
||||
_,
|
||||
|
||||
const first_object = @intFromEnum(DataId.__zig_error_name_table) + 1;
|
||||
|
||||
pub const Category = enum {
|
||||
/// Thread-local variables.
|
||||
|
|
@ -1337,221 +1439,180 @@ pub const DataSegment = extern struct {
|
|||
zero,
|
||||
};
|
||||
|
||||
pub const Payload = extern struct {
|
||||
off: Off,
|
||||
/// The size in bytes of the data representing the segment within the section.
|
||||
len: u32,
|
||||
|
||||
pub const Off = enum(u32) {
|
||||
/// The payload is all zeroes (bss section).
|
||||
none = std.math.maxInt(u32),
|
||||
/// Points into string_bytes. No corresponding string_table entry.
|
||||
_,
|
||||
|
||||
pub fn unwrap(off: Off) ?u32 {
|
||||
return if (off == .none) null else @intFromEnum(off);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn slice(p: DataSegment.Payload, wasm: *const Wasm) []const u8 {
|
||||
return wasm.string_bytes.items[p.off.unwrap().?..][0..p.len];
|
||||
}
|
||||
};
|
||||
|
||||
pub const Id = enum(u32) {
|
||||
pub const Unpacked = union(enum) {
|
||||
__zig_error_names,
|
||||
__zig_error_name_table,
|
||||
/// First, an `ObjectDataSegmentIndex`.
|
||||
/// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
|
||||
/// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
|
||||
_,
|
||||
|
||||
const first_object = @intFromEnum(Id.__zig_error_name_table) + 1;
|
||||
|
||||
pub const Unpacked = union(enum) {
|
||||
__zig_error_names,
|
||||
__zig_error_name_table,
|
||||
object: ObjectDataSegmentIndex,
|
||||
uav_exe: UavsExeIndex,
|
||||
uav_obj: UavsObjIndex,
|
||||
nav_exe: NavsExeIndex,
|
||||
nav_obj: NavsObjIndex,
|
||||
};
|
||||
|
||||
pub fn pack(wasm: *const Wasm, unpacked: Unpacked) Id {
|
||||
return switch (unpacked) {
|
||||
.__zig_error_names => .__zig_error_names,
|
||||
.__zig_error_name_table => .__zig_error_name_table,
|
||||
.object => |i| @enumFromInt(first_object + @intFromEnum(i)),
|
||||
inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)),
|
||||
.nav_exe => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @intFromEnum(i)),
|
||||
.nav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_obj.entries.len + @intFromEnum(i)),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unpack(id: Id, wasm: *const Wasm) Unpacked {
|
||||
return switch (id) {
|
||||
.__zig_error_names => .__zig_error_names,
|
||||
.__zig_error_name_table => .__zig_error_name_table,
|
||||
_ => {
|
||||
const object_index = @intFromEnum(id) - first_object;
|
||||
|
||||
const uav_index = if (object_index < wasm.object_data_segments.items.len)
|
||||
return .{ .object = @enumFromInt(object_index) }
|
||||
else
|
||||
object_index - wasm.object_data_segments.items.len;
|
||||
|
||||
const comp = wasm.base.comp;
|
||||
const is_obj = comp.config.output_mode == .Obj;
|
||||
if (is_obj) {
|
||||
const nav_index = if (uav_index < wasm.uavs_obj.entries.len)
|
||||
return .{ .uav_obj = @enumFromInt(uav_index) }
|
||||
else
|
||||
uav_index - wasm.uavs_obj.entries.len;
|
||||
|
||||
return .{ .nav_obj = @enumFromInt(nav_index) };
|
||||
} else {
|
||||
const nav_index = if (uav_index < wasm.uavs_exe.entries.len)
|
||||
return .{ .uav_exe = @enumFromInt(uav_index) }
|
||||
else
|
||||
uav_index - wasm.uavs_exe.entries.len;
|
||||
|
||||
return .{ .nav_exe = @enumFromInt(nav_index) };
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn category(id: Id, wasm: *const Wasm) Category {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => .data,
|
||||
.object => |i| {
|
||||
const ptr = i.ptr(wasm);
|
||||
if (ptr.flags.tls) return .tls;
|
||||
if (wasm.isBss(ptr.name)) return .zero;
|
||||
return .data;
|
||||
},
|
||||
inline .uav_exe, .uav_obj => |i| if (i.value(wasm).code.off == .none) .zero else .data,
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
if (nav.isThreadLocal(ip)) return .tls;
|
||||
const code = i.value(wasm).code;
|
||||
return if (code.off == .none) .zero else .data;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isTls(id: Id, wasm: *const Wasm) bool {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => false,
|
||||
.object => |i| i.ptr(wasm).flags.tls,
|
||||
.uav_exe, .uav_obj => false,
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
return nav.isThreadLocal(ip);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isBss(id: Id, wasm: *const Wasm) bool {
|
||||
return id.category(wasm) == .zero;
|
||||
}
|
||||
|
||||
pub fn name(id: Id, wasm: *const Wasm) []const u8 {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj => ".data",
|
||||
.object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
return nav.status.resolved.@"linksection".toSlice(ip) orelse ".data";
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn alignment(id: Id, wasm: *const Wasm) Alignment {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names => .@"1",
|
||||
.__zig_error_name_table => wasm.pointerAlignment(),
|
||||
.object => |i| i.ptr(wasm).flags.alignment,
|
||||
inline .uav_exe, .uav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const ip_index = i.key(wasm).*;
|
||||
const ty: ZcuType = .fromInterned(ip.typeOf(ip_index));
|
||||
const result = ty.abiAlignment(zcu);
|
||||
assert(result != .none);
|
||||
return result;
|
||||
},
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
const explicit = nav.status.resolved.alignment;
|
||||
if (explicit != .none) return explicit;
|
||||
const ty: ZcuType = .fromInterned(nav.typeOf(ip));
|
||||
const result = ty.abiAlignment(zcu);
|
||||
assert(result != .none);
|
||||
return result;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn refCount(id: Id, wasm: *const Wasm) u32 {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names => @intCast(wasm.error_name_offs.items.len),
|
||||
.__zig_error_name_table => wasm.error_name_table_ref_count,
|
||||
.object, .uav_obj, .nav_obj => 0,
|
||||
inline .uav_exe, .nav_exe => |i| i.value(wasm).count,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isPassive(id: Id, wasm: *const Wasm) bool {
|
||||
const comp = wasm.base.comp;
|
||||
if (comp.config.import_memory and !id.isBss(wasm)) return true;
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => false,
|
||||
.object => |i| i.ptr(wasm).flags.is_passive,
|
||||
.uav_exe, .uav_obj, .nav_exe, .nav_obj => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isEmpty(id: Id, wasm: *const Wasm) bool {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => false,
|
||||
.object => |i| i.ptr(wasm).payload.off == .none,
|
||||
inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn size(id: Id, wasm: *const Wasm) u32 {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names => @intCast(wasm.error_name_bytes.items.len),
|
||||
.__zig_error_name_table => {
|
||||
const comp = wasm.base.comp;
|
||||
const zcu = comp.zcu.?;
|
||||
const errors_len = wasm.error_name_offs.items.len;
|
||||
const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu);
|
||||
return @intCast(errors_len * elem_size);
|
||||
},
|
||||
.object => |i| i.ptr(wasm).payload.len,
|
||||
inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len,
|
||||
};
|
||||
}
|
||||
object: ObjectDataSegment.Index,
|
||||
uav_exe: UavsExeIndex,
|
||||
uav_obj: UavsObjIndex,
|
||||
nav_exe: NavsExeIndex,
|
||||
nav_obj: NavsObjIndex,
|
||||
};
|
||||
};
|
||||
|
||||
/// Index into `Wasm.object_data_segments`.
|
||||
pub const ObjectDataSegmentIndex = enum(u32) {
|
||||
_,
|
||||
pub fn pack(wasm: *const Wasm, unpacked: Unpacked) DataId {
|
||||
return switch (unpacked) {
|
||||
.__zig_error_names => .__zig_error_names,
|
||||
.__zig_error_name_table => .__zig_error_name_table,
|
||||
.object => |i| @enumFromInt(first_object + @intFromEnum(i)),
|
||||
inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)),
|
||||
.nav_exe => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @intFromEnum(i)),
|
||||
.nav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_obj.entries.len + @intFromEnum(i)),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn ptr(i: ObjectDataSegmentIndex, wasm: *const Wasm) *DataSegment {
|
||||
return &wasm.object_data_segments.items[@intFromEnum(i)];
|
||||
pub fn unpack(id: DataId, wasm: *const Wasm) Unpacked {
|
||||
return switch (id) {
|
||||
.__zig_error_names => .__zig_error_names,
|
||||
.__zig_error_name_table => .__zig_error_name_table,
|
||||
_ => {
|
||||
const object_index = @intFromEnum(id) - first_object;
|
||||
|
||||
const uav_index = if (object_index < wasm.object_data_segments.items.len)
|
||||
return .{ .object = @enumFromInt(object_index) }
|
||||
else
|
||||
object_index - wasm.object_data_segments.items.len;
|
||||
|
||||
const comp = wasm.base.comp;
|
||||
const is_obj = comp.config.output_mode == .Obj;
|
||||
if (is_obj) {
|
||||
const nav_index = if (uav_index < wasm.uavs_obj.entries.len)
|
||||
return .{ .uav_obj = @enumFromInt(uav_index) }
|
||||
else
|
||||
uav_index - wasm.uavs_obj.entries.len;
|
||||
|
||||
return .{ .nav_obj = @enumFromInt(nav_index) };
|
||||
} else {
|
||||
const nav_index = if (uav_index < wasm.uavs_exe.entries.len)
|
||||
return .{ .uav_exe = @enumFromInt(uav_index) }
|
||||
else
|
||||
uav_index - wasm.uavs_exe.entries.len;
|
||||
|
||||
return .{ .nav_exe = @enumFromInt(nav_index) };
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn category(id: DataId, wasm: *const Wasm) Category {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => .data,
|
||||
.object => |i| {
|
||||
const ptr = i.ptr(wasm);
|
||||
if (ptr.flags.tls) return .tls;
|
||||
if (wasm.isBss(ptr.name)) return .zero;
|
||||
return .data;
|
||||
},
|
||||
inline .uav_exe, .uav_obj => |i| if (i.value(wasm).code.off == .none) .zero else .data,
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
if (nav.isThreadLocal(ip)) return .tls;
|
||||
const code = i.value(wasm).code;
|
||||
return if (code.off == .none) .zero else .data;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isTls(id: DataId, wasm: *const Wasm) bool {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => false,
|
||||
.object => |i| i.ptr(wasm).flags.tls,
|
||||
.uav_exe, .uav_obj => false,
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
return nav.isThreadLocal(ip);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isBss(id: DataId, wasm: *const Wasm) bool {
|
||||
return id.category(wasm) == .zero;
|
||||
}
|
||||
|
||||
pub fn name(id: DataId, wasm: *const Wasm) []const u8 {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj => ".data",
|
||||
.object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
return nav.status.resolved.@"linksection".toSlice(ip) orelse ".data";
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn alignment(id: DataId, wasm: *const Wasm) Alignment {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names => .@"1",
|
||||
.__zig_error_name_table => wasm.pointerAlignment(),
|
||||
.object => |i| i.ptr(wasm).flags.alignment,
|
||||
inline .uav_exe, .uav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const ip_index = i.key(wasm).*;
|
||||
const ty: ZcuType = .fromInterned(ip.typeOf(ip_index));
|
||||
const result = ty.abiAlignment(zcu);
|
||||
assert(result != .none);
|
||||
return result;
|
||||
},
|
||||
inline .nav_exe, .nav_obj => |i| {
|
||||
const zcu = wasm.base.comp.zcu.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = ip.getNav(i.key(wasm).*);
|
||||
const explicit = nav.status.resolved.alignment;
|
||||
if (explicit != .none) return explicit;
|
||||
const ty: ZcuType = .fromInterned(nav.typeOf(ip));
|
||||
const result = ty.abiAlignment(zcu);
|
||||
assert(result != .none);
|
||||
return result;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn refCount(id: DataId, wasm: *const Wasm) u32 {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names => @intCast(wasm.error_name_offs.items.len),
|
||||
.__zig_error_name_table => wasm.error_name_table_ref_count,
|
||||
.object, .uav_obj, .nav_obj => 0,
|
||||
inline .uav_exe, .nav_exe => |i| i.value(wasm).count,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isPassive(id: DataId, wasm: *const Wasm) bool {
|
||||
const comp = wasm.base.comp;
|
||||
if (comp.config.import_memory and !id.isBss(wasm)) return true;
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => false,
|
||||
.object => |i| i.ptr(wasm).flags.is_passive,
|
||||
.uav_exe, .uav_obj, .nav_exe, .nav_obj => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isEmpty(id: DataId, wasm: *const Wasm) bool {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names, .__zig_error_name_table => false,
|
||||
.object => |i| i.ptr(wasm).payload.off == .none,
|
||||
inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn size(id: DataId, wasm: *const Wasm) u32 {
|
||||
return switch (unpack(id, wasm)) {
|
||||
.__zig_error_names => @intCast(wasm.error_name_bytes.items.len),
|
||||
.__zig_error_name_table => {
|
||||
const comp = wasm.base.comp;
|
||||
const zcu = comp.zcu.?;
|
||||
const errors_len = wasm.error_name_offs.items.len;
|
||||
const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu);
|
||||
return @intCast(errors_len * elem_size);
|
||||
},
|
||||
.object => |i| i.ptr(wasm).payload.len,
|
||||
inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1565,7 +1626,7 @@ pub const CustomSegment = extern struct {
|
|||
flags: SymbolFlags,
|
||||
section_name: String,
|
||||
|
||||
pub const Payload = DataSegment.Payload;
|
||||
pub const Payload = DataPayload;
|
||||
};
|
||||
|
||||
/// An index into string_bytes where a wasm expression is found.
|
||||
|
|
@ -1591,9 +1652,13 @@ pub const FunctionType = extern struct {
|
|||
pub const Index = enum(u32) {
|
||||
_,
|
||||
|
||||
pub fn ptr(i: FunctionType.Index, wasm: *const Wasm) *FunctionType {
|
||||
pub fn ptr(i: Index, wasm: *const Wasm) *FunctionType {
|
||||
return &wasm.func_types.keys()[@intFromEnum(i)];
|
||||
}
|
||||
|
||||
pub fn fmt(i: Index, wasm: *const Wasm) Formatter {
|
||||
return i.ptr(wasm).fmt(wasm);
|
||||
}
|
||||
};
|
||||
|
||||
pub const format = @compileError("can't format without *Wasm reference");
|
||||
|
|
@ -1601,6 +1666,46 @@ pub const FunctionType = extern struct {
|
|||
pub fn eql(a: FunctionType, b: FunctionType) bool {
|
||||
return a.params == b.params and a.returns == b.returns;
|
||||
}
|
||||
|
||||
pub fn fmt(ft: FunctionType, wasm: *const Wasm) Formatter {
|
||||
return .{ .wasm = wasm, .ft = ft };
|
||||
}
|
||||
|
||||
const Formatter = struct {
|
||||
wasm: *const Wasm,
|
||||
ft: FunctionType,
|
||||
|
||||
pub fn format(
|
||||
self: Formatter,
|
||||
comptime format_string: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) !void {
|
||||
if (format_string.len != 0) std.fmt.invalidFmtError(format_string, self);
|
||||
_ = options;
|
||||
const params = self.ft.params.slice(self.wasm);
|
||||
const returns = self.ft.returns.slice(self.wasm);
|
||||
|
||||
try writer.writeByte('(');
|
||||
for (params, 0..) |param, i| {
|
||||
try writer.print("{s}", .{@tagName(param)});
|
||||
if (i + 1 != params.len) {
|
||||
try writer.writeAll(", ");
|
||||
}
|
||||
}
|
||||
try writer.writeAll(") -> ");
|
||||
if (returns.len == 0) {
|
||||
try writer.writeAll("nil");
|
||||
} else {
|
||||
for (returns, 0..) |return_ty, i| {
|
||||
try writer.print("{s}", .{@tagName(return_ty)});
|
||||
if (i + 1 != returns.len) {
|
||||
try writer.writeAll(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/// Represents a function entry, holding the index to its type
|
||||
|
|
@ -1955,7 +2060,7 @@ pub const ObjectRelocation = struct {
|
|||
symbol_name: String,
|
||||
type_index: FunctionType.Index,
|
||||
section: ObjectSectionIndex,
|
||||
data_segment: ObjectDataSegmentIndex,
|
||||
data: ObjectData.Index,
|
||||
function: Wasm.ObjectFunctionIndex,
|
||||
};
|
||||
|
||||
|
|
@ -2096,6 +2201,8 @@ pub const Feature = packed struct(u8) {
|
|||
/// Type of the feature, must be unique in the sequence of features.
|
||||
tag: Tag,
|
||||
|
||||
pub const sentinel: Feature = @bitCast(@as(u8, 0));
|
||||
|
||||
/// Stored identically to `String`. The bytes are reinterpreted as `Feature`
|
||||
/// elements. Elements must be sorted before string-interning.
|
||||
pub const Set = enum(u32) {
|
||||
|
|
@ -2104,6 +2211,14 @@ pub const Feature = packed struct(u8) {
|
|||
pub fn fromString(s: String) Set {
|
||||
return @enumFromInt(@intFromEnum(s));
|
||||
}
|
||||
|
||||
pub fn string(s: Set) String {
|
||||
return @enumFromInt(@intFromEnum(s));
|
||||
}
|
||||
|
||||
pub fn slice(s: Set, wasm: *const Wasm) [:sentinel]const Feature {
|
||||
return @ptrCast(string(s).slice(wasm));
|
||||
}
|
||||
};
|
||||
|
||||
/// Unlike `std.Target.wasm.Feature` this also contains linker-features such as shared-mem.
|
||||
|
|
@ -2129,6 +2244,13 @@ pub const Feature = packed struct(u8) {
|
|||
return @enumFromInt(@intFromEnum(feature));
|
||||
}
|
||||
|
||||
pub fn toCpuFeature(tag: Tag) ?std.Target.wasm.Feature {
|
||||
return if (@intFromEnum(tag) < @typeInfo(std.Target.wasm.Feature).@"enum".fields.len)
|
||||
@enumFromInt(@intFromEnum(tag))
|
||||
else
|
||||
null;
|
||||
}
|
||||
|
||||
pub const format = @compileError("use @tagName instead");
|
||||
};
|
||||
|
||||
|
|
@ -2136,15 +2258,14 @@ pub const Feature = packed struct(u8) {
|
|||
pub const Prefix = enum(u2) {
|
||||
/// Reserved so that a 0-byte Feature is invalid and therefore can be a sentinel.
|
||||
invalid,
|
||||
/// '0x2b': Object uses this feature, and the link fails if feature is
|
||||
/// not in the allowed set.
|
||||
/// Object uses this feature, and the link fails if feature is not in
|
||||
/// the allowed set.
|
||||
@"+",
|
||||
/// '0x2d': Object does not use this feature, and the link fails if
|
||||
/// this feature is in the allowed set.
|
||||
/// Object does not use this feature, and the link fails if this
|
||||
/// feature is in the allowed set.
|
||||
@"-",
|
||||
/// '0x3d': Object uses this feature, and the link fails if this
|
||||
/// feature is not in the allowed set, or if any object does not use
|
||||
/// this feature.
|
||||
/// Object uses this feature, and the link fails if this feature is not
|
||||
/// in the allowed set, or if any object does not use this feature.
|
||||
@"=",
|
||||
};
|
||||
|
||||
|
|
@ -2390,6 +2511,7 @@ pub fn deinit(wasm: *Wasm) void {
|
|||
wasm.object_memories.deinit(gpa);
|
||||
wasm.object_relocations.deinit(gpa);
|
||||
wasm.object_data_segments.deinit(gpa);
|
||||
wasm.object_datas.deinit(gpa);
|
||||
wasm.object_custom_segments.deinit(gpa);
|
||||
wasm.object_init_funcs.deinit(gpa);
|
||||
wasm.object_comdats.deinit(gpa);
|
||||
|
|
@ -3412,7 +3534,7 @@ pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr {
|
|||
return @enumFromInt(wasm.string_bytes.items.len - bytes.len);
|
||||
}
|
||||
|
||||
pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error!DataSegment.Payload {
|
||||
pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error!DataPayload {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
try wasm.string_bytes.appendSlice(gpa, bytes);
|
||||
return .{
|
||||
|
|
@ -3546,7 +3668,7 @@ pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {
|
|||
assert(wasm.flush_buffer.memory_layout_finished);
|
||||
const comp = wasm.base.comp;
|
||||
assert(comp.config.output_mode != .Obj);
|
||||
const ds_id: DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_index });
|
||||
const ds_id: DataId = .pack(wasm, .{ .uav_exe = uav_index });
|
||||
return wasm.flush_buffer.data_segments.get(ds_id).?;
|
||||
}
|
||||
|
||||
|
|
@ -3557,7 +3679,7 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
|
|||
assert(comp.config.output_mode != .Obj);
|
||||
const navs_exe_index: NavsExeIndex = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?);
|
||||
log.debug("navAddr {s} {}", .{ navs_exe_index.name(wasm), nav_index });
|
||||
const ds_id: DataSegment.Id = .pack(wasm, .{ .nav_exe = navs_exe_index });
|
||||
const ds_id: DataId = .pack(wasm, .{ .nav_exe = navs_exe_index });
|
||||
return wasm.flush_buffer.data_segments.get(ds_id).?;
|
||||
}
|
||||
|
||||
|
|
@ -3646,14 +3768,14 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu
|
|||
const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start);
|
||||
wasm.string_bytes_lock.unlock();
|
||||
|
||||
const naive_code: DataSegment.Payload = .{
|
||||
const naive_code: DataPayload = .{
|
||||
.off = @enumFromInt(code_start),
|
||||
.len = code_len,
|
||||
};
|
||||
|
||||
// Only nonzero init values need to take up space in the output.
|
||||
const all_zeroes = std.mem.allEqual(u8, naive_code.slice(wasm), 0);
|
||||
const code: DataSegment.Payload = if (!all_zeroes) naive_code else c: {
|
||||
const code: DataPayload = if (!all_zeroes) naive_code else c: {
|
||||
wasm.string_bytes.shrinkRetainingCapacity(code_start);
|
||||
// Indicate empty by making off and len the same value, however, still
|
||||
// transmit the data size by using the size as that value.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const assert = std.debug.assert;
|
|||
/// Ordered list of data segments that will appear in the final binary.
|
||||
/// When sorted, to-be-merged segments will be made adjacent.
|
||||
/// Values are virtual address.
|
||||
data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataSegment.Id, u32) = .empty,
|
||||
data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataId, u32) = .empty,
|
||||
/// Each time a `data_segment` offset equals zero it indicates a new group, and
|
||||
/// the next element in this array will contain the total merged segment size.
|
||||
/// Value is the virtual memory address of the end of the segment.
|
||||
|
|
@ -120,7 +120,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
|
|||
if (wasm.entry_resolution == .unresolved) {
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("entry symbol '{s}' missing", .{name.slice(wasm)});
|
||||
try err.addNote("'-fno-entry' suppresses this error", .{});
|
||||
err.addNote("'-fno-entry' suppresses this error", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -176,10 +176,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
|
|||
}), @as(u32, undefined));
|
||||
for (wasm.object_data_segments.items, 0..) |*ds, i| {
|
||||
if (!ds.flags.alive) continue;
|
||||
const data_segment_index: Wasm.ObjectDataSegmentIndex = @enumFromInt(i);
|
||||
const obj_seg_index: Wasm.ObjectDataSegment.Index = @enumFromInt(i);
|
||||
any_passive_inits = any_passive_inits or ds.flags.is_passive or (import_memory and !wasm.isBss(ds.name));
|
||||
_ = f.data_segments.putAssumeCapacityNoClobber(.pack(wasm, .{
|
||||
.object = data_segment_index,
|
||||
.object = obj_seg_index,
|
||||
}), @as(u32, undefined));
|
||||
}
|
||||
if (wasm.error_name_table_ref_count > 0) {
|
||||
|
|
@ -229,7 +229,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
|
|||
// For the purposes of sorting, they are implicitly all named ".data".
|
||||
const Sort = struct {
|
||||
wasm: *const Wasm,
|
||||
segments: []const Wasm.DataSegment.Id,
|
||||
segments: []const Wasm.DataId,
|
||||
pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool {
|
||||
const lhs_segment = ctx.segments[lhs];
|
||||
const rhs_segment = ctx.segments[rhs];
|
||||
|
|
@ -312,7 +312,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
|
|||
const data_vaddr: u32 = @intCast(memory_ptr);
|
||||
{
|
||||
var seen_tls: enum { before, during, after } = .before;
|
||||
var category: Wasm.DataSegment.Category = undefined;
|
||||
var category: Wasm.DataId.Category = undefined;
|
||||
for (segment_ids, segment_vaddrs, 0..) |segment_id, *segment_vaddr, i| {
|
||||
const alignment = segment_id.alignment(wasm);
|
||||
category = segment_id.category(wasm);
|
||||
|
|
@ -707,7 +707,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
|
|||
|
||||
if (!is_obj) {
|
||||
for (wasm.uav_fixups.items) |uav_fixup| {
|
||||
const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index });
|
||||
const ds_id: Wasm.DataId = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index });
|
||||
const vaddr = f.data_segments.get(ds_id).?;
|
||||
if (!is64) {
|
||||
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 {
|
|||
}
|
||||
}
|
||||
for (wasm.nav_fixups.items) |nav_fixup| {
|
||||
const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });
|
||||
const ds_id: Wasm.DataId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });
|
||||
const vaddr = f.data_segments.get(ds_id).?;
|
||||
if (!is64) {
|
||||
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 {
|
|||
|
||||
fn emitNameSection(
|
||||
wasm: *Wasm,
|
||||
data_segments: *const std.AutoArrayHashMapUnmanaged(Wasm.DataSegment.Id, u32),
|
||||
data_segments: *const std.AutoArrayHashMapUnmanaged(Wasm.DataId, u32),
|
||||
binary_bytes: *std.ArrayListUnmanaged(u8),
|
||||
) !void {
|
||||
const f = &wasm.flush_buffer;
|
||||
|
|
@ -1137,9 +1137,9 @@ fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } {
|
|||
|
||||
fn wantSegmentMerge(
|
||||
wasm: *const Wasm,
|
||||
a_id: Wasm.DataSegment.Id,
|
||||
b_id: Wasm.DataSegment.Id,
|
||||
b_category: Wasm.DataSegment.Category,
|
||||
a_id: Wasm.DataId,
|
||||
b_id: Wasm.DataId,
|
||||
b_category: Wasm.DataId.Category,
|
||||
) bool {
|
||||
const a_category = a_id.category(wasm);
|
||||
if (a_category != b_category) return false;
|
||||
|
|
|
|||
|
|
@ -102,11 +102,7 @@ pub const Symbol = struct {
|
|||
const Pointee = union(enum) {
|
||||
function: Wasm.ObjectFunctionIndex,
|
||||
function_import: ScratchSpace.FuncImportIndex,
|
||||
data: struct {
|
||||
segment_index: Wasm.ObjectDataSegmentIndex,
|
||||
segment_offset: u32,
|
||||
size: u32,
|
||||
},
|
||||
data: Wasm.ObjectData.Index,
|
||||
data_import: void,
|
||||
global: Wasm.ObjectGlobalIndex,
|
||||
global_import: Wasm.GlobalImport.Index,
|
||||
|
|
@ -131,7 +127,7 @@ pub const ScratchSpace = struct {
|
|||
const Pointee = union(std.wasm.ExternalKind) {
|
||||
function: Wasm.ObjectFunctionIndex,
|
||||
table: Wasm.ObjectTableIndex,
|
||||
memory: Wasm.ObjectMemoryIndex,
|
||||
memory: Wasm.ObjectMemory.Index,
|
||||
global: Wasm.ObjectGlobalIndex,
|
||||
};
|
||||
};
|
||||
|
|
@ -184,8 +180,9 @@ pub fn parse(
|
|||
must_link: bool,
|
||||
gc_sections: bool,
|
||||
) anyerror!Object {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const diags = &wasm.base.comp.link_diags;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const diags = &comp.link_diags;
|
||||
|
||||
var pos: usize = 0;
|
||||
|
||||
|
|
@ -334,12 +331,16 @@ pub fn parse(
|
|||
const segment_index, pos = readLeb(u32, bytes, pos);
|
||||
const segment_offset, pos = readLeb(u32, bytes, pos);
|
||||
const size, pos = readLeb(u32, bytes, pos);
|
||||
|
||||
symbol.pointee = .{ .data = .{
|
||||
.segment_index = @enumFromInt(data_segment_start + segment_index),
|
||||
.segment_offset = segment_offset,
|
||||
try wasm.object_datas.append(gpa, .{
|
||||
.segment = @enumFromInt(data_segment_start + segment_index),
|
||||
.offset = segment_offset,
|
||||
.size = size,
|
||||
} };
|
||||
.name = symbol.name,
|
||||
.flags = symbol.flags,
|
||||
});
|
||||
symbol.pointee = .{
|
||||
.data = @enumFromInt(wasm.object_datas.items.len - 1),
|
||||
};
|
||||
}
|
||||
},
|
||||
.section => {
|
||||
|
|
@ -405,7 +406,6 @@ pub fn parse(
|
|||
return error.UnrecognizedSymbolType;
|
||||
},
|
||||
}
|
||||
log.debug("found symbol: {}", .{symbol});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -450,22 +450,10 @@ pub fn parse(
|
|||
.MEMORY_ADDR_TLS_SLEB64,
|
||||
=> {
|
||||
const addend: i32, pos = readLeb(i32, bytes, pos);
|
||||
const sym_section = ss.symbol_table.items[index].pointee.data;
|
||||
if (sym_section.segment_offset != 0) {
|
||||
return diags.failParse(path, "data symbol {d} has nonzero offset {d}", .{
|
||||
index, sym_section.segment_offset,
|
||||
});
|
||||
}
|
||||
const seg_size = sym_section.segment_index.ptr(wasm).payload.len;
|
||||
if (sym_section.size != seg_size) {
|
||||
return diags.failParse(path, "data symbol {d} has size {d}, inequal to corresponding data segment {d} size {d}", .{
|
||||
index, sym_section.size, @intFromEnum(sym_section.segment_index), seg_size,
|
||||
});
|
||||
}
|
||||
wasm.object_relocations.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.offset = offset,
|
||||
.pointee = .{ .data_segment = sym_section.segment_index },
|
||||
.pointee = .{ .data = ss.symbol_table.items[index].pointee.data },
|
||||
.addend = addend,
|
||||
});
|
||||
},
|
||||
|
|
@ -651,7 +639,15 @@ pub fn parse(
|
|||
const memories_len, pos = readLeb(u32, bytes, pos);
|
||||
for (try wasm.object_memories.addManyAsSlice(gpa, memories_len)) |*memory| {
|
||||
const limits, pos = readLimits(bytes, pos);
|
||||
memory.* = .{ .limits = limits };
|
||||
memory.* = .{
|
||||
.name = .none,
|
||||
.flags = .{
|
||||
.limits_has_max = limits.flags.has_max,
|
||||
.limits_is_shared = limits.flags.is_shared,
|
||||
},
|
||||
.limits_min = limits.min,
|
||||
.limits_max = limits.max,
|
||||
};
|
||||
}
|
||||
},
|
||||
.global => {
|
||||
|
|
@ -722,7 +718,6 @@ pub fn parse(
|
|||
}
|
||||
},
|
||||
.data => {
|
||||
const start = pos;
|
||||
const count, pos = readLeb(u32, bytes, pos);
|
||||
for (try wasm.object_data_segments.addManyAsSlice(gpa, count)) |*elem| {
|
||||
const flags, pos = readEnum(DataSegmentFlags, bytes, pos);
|
||||
|
|
@ -733,13 +728,10 @@ pub fn parse(
|
|||
//const expr, pos = if (flags != .passive) try readInit(wasm, bytes, pos) else .{ .none, pos };
|
||||
if (flags != .passive) pos = try skipInit(bytes, pos);
|
||||
const data_len, pos = readLeb(u32, bytes, pos);
|
||||
const segment_offset: u32 = @intCast(pos - start);
|
||||
const payload = try wasm.addRelocatableDataPayload(bytes[pos..][0..data_len]);
|
||||
pos += data_len;
|
||||
elem.* = .{
|
||||
.payload = payload,
|
||||
.segment_offset = segment_offset,
|
||||
.section_index = section_index,
|
||||
.name = .none, // Populated from symbol table
|
||||
.flags = .{}, // Populated from symbol table and segment_info
|
||||
};
|
||||
|
|
@ -751,20 +743,56 @@ pub fn parse(
|
|||
}
|
||||
if (!saw_linking_section) return error.MissingLinkingSection;
|
||||
|
||||
const target_features = comp.root_mod.resolved_target.result.cpu.features;
|
||||
|
||||
if (has_tls) {
|
||||
const cpu_features = wasm.base.comp.root_mod.resolved_target.result.cpu.features;
|
||||
if (!std.Target.wasm.featureSetHas(cpu_features, .atomics))
|
||||
if (!std.Target.wasm.featureSetHas(target_features, .atomics))
|
||||
return diags.failParse(path, "object has TLS segment but target CPU feature atomics is disabled", .{});
|
||||
if (!std.Target.wasm.featureSetHas(cpu_features, .bulk_memory))
|
||||
if (!std.Target.wasm.featureSetHas(target_features, .bulk_memory))
|
||||
return diags.failParse(path, "object has TLS segment but target CPU feature bulk_memory is disabled", .{});
|
||||
}
|
||||
|
||||
const features = opt_features orelse return error.MissingFeatures;
|
||||
if (true) @panic("iterate features, match against target features");
|
||||
for (features.slice(wasm)) |feat| {
|
||||
log.debug("feature: {s}{s}", .{ @tagName(feat.prefix), @tagName(feat.tag) });
|
||||
switch (feat.prefix) {
|
||||
.invalid => unreachable,
|
||||
.@"-" => switch (feat.tag) {
|
||||
.@"shared-mem" => if (comp.config.shared_memory) {
|
||||
return diags.failParse(path, "object forbids shared-mem but compilation enables it", .{});
|
||||
},
|
||||
else => {
|
||||
const f = feat.tag.toCpuFeature().?;
|
||||
if (std.Target.wasm.featureSetHas(target_features, f)) {
|
||||
return diags.failParse(
|
||||
path,
|
||||
"object forbids {s} but specified target features include {s}",
|
||||
.{ @tagName(feat.tag), @tagName(f) },
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
.@"+", .@"=" => switch (feat.tag) {
|
||||
.@"shared-mem" => if (!comp.config.shared_memory) {
|
||||
return diags.failParse(path, "object requires shared-mem but compilation disables it", .{});
|
||||
},
|
||||
else => {
|
||||
const f = feat.tag.toCpuFeature().?;
|
||||
if (!std.Target.wasm.featureSetHas(target_features, f)) {
|
||||
return diags.failParse(
|
||||
path,
|
||||
"object requires {s} but specified target features exclude {s}",
|
||||
.{ @tagName(feat.tag), @tagName(f) },
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Apply function type information.
|
||||
for (ss.func_types.items, wasm.object_functions.items[functions_start..]) |func_type, *func| {
|
||||
func.type_index = func_type;
|
||||
for (ss.func_type_indexes.items, wasm.object_functions.items[functions_start..]) |func_type, *func| {
|
||||
func.type_index = func_type.ptr(ss).*;
|
||||
}
|
||||
|
||||
// Apply symbol table information.
|
||||
|
|
@ -782,15 +810,21 @@ pub fn parse(
|
|||
if (gop.value_ptr.type != fn_ty_index) {
|
||||
var err = try diags.addErrorWithNotes(2);
|
||||
try err.addMsg("symbol '{s}' mismatching function signatures", .{name.slice(wasm)});
|
||||
try err.addSrcNote(gop.value_ptr.source_location, "imported as {} here", .{gop.value_ptr.type.fmt(wasm)});
|
||||
try err.addSrcNote(source_location, "imported as {} here", .{fn_ty_index.fmt(wasm)});
|
||||
gop.value_ptr.source_location.addNote(wasm, &err, "imported as {} here", .{
|
||||
gop.value_ptr.type.fmt(wasm),
|
||||
});
|
||||
source_location.addNote(wasm, &err, "imported as {} here", .{fn_ty_index.fmt(wasm)});
|
||||
continue;
|
||||
}
|
||||
if (gop.value_ptr.module_name != ptr.module_name) {
|
||||
if (gop.value_ptr.module_name != ptr.module_name.toOptional()) {
|
||||
var err = try diags.addErrorWithNotes(2);
|
||||
try err.addMsg("symbol '{s}' mismatching module names", .{name.slice(wasm)});
|
||||
try err.addSrcNote(gop.value_ptr.source_location, "module '{s}' here", .{gop.value_ptr.module_name.slice(wasm)});
|
||||
try err.addSrcNote(source_location, "module '{s}' here", .{ptr.module_name.slice(wasm)});
|
||||
if (gop.value_ptr.module_name.slice(wasm)) |module_name| {
|
||||
gop.value_ptr.source_location.addNote(wasm, &err, "module '{s}' here", .{module_name});
|
||||
} else {
|
||||
gop.value_ptr.source_location.addNote(wasm, &err, "no module here", .{});
|
||||
}
|
||||
source_location.addNote(wasm, &err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
|
||||
continue;
|
||||
}
|
||||
if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong;
|
||||
|
|
@ -799,7 +833,7 @@ pub fn parse(
|
|||
} else {
|
||||
gop.value_ptr.* = .{
|
||||
.flags = symbol.flags,
|
||||
.module_name = ptr.module_name,
|
||||
.module_name = ptr.module_name.toOptional(),
|
||||
.source_location = source_location,
|
||||
.resolution = .unresolved,
|
||||
.type = fn_ty_index,
|
||||
|
|
@ -808,7 +842,7 @@ pub fn parse(
|
|||
},
|
||||
.function => |index| {
|
||||
assert(!symbol.flags.undefined);
|
||||
const ptr = index.ptr();
|
||||
const ptr = index.ptr(wasm);
|
||||
ptr.name = symbol.name;
|
||||
ptr.flags = symbol.flags;
|
||||
if (symbol.flags.binding == .local) continue; // No participation in symbol resolution.
|
||||
|
|
@ -818,35 +852,46 @@ pub fn parse(
|
|||
if (gop.value_ptr.type != ptr.type_index) {
|
||||
var err = try diags.addErrorWithNotes(2);
|
||||
try err.addMsg("function signature mismatch: {s}", .{name.slice(wasm)});
|
||||
try err.addSrcNote(gop.value_ptr.source_location, "exported as {} here", .{ptr.type_index.fmt(wasm)});
|
||||
const word = if (gop.value_ptr.resolution == .none) "imported" else "exported";
|
||||
try err.addSrcNote(source_location, "{s} as {} here", .{ word, gop.value_ptr.type.fmt(wasm) });
|
||||
gop.value_ptr.source_location.addNote(wasm, &err, "exported as {} here", .{
|
||||
ptr.type_index.fmt(wasm),
|
||||
});
|
||||
const word = if (gop.value_ptr.resolution == .unresolved) "imported" else "exported";
|
||||
source_location.addNote(wasm, &err, "{s} as {} here", .{ word, gop.value_ptr.type.fmt(wasm) });
|
||||
continue;
|
||||
}
|
||||
if (gop.value_ptr.resolution == .none or gop.value_ptr.flags.binding == .weak) {
|
||||
if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) {
|
||||
// Intentional: if they're both weak, take the last one.
|
||||
gop.value_ptr.source_location = source_location;
|
||||
gop.value_ptr.module_name = host_name;
|
||||
gop.value_ptr.resolution = .fromObjectFunction(index);
|
||||
gop.value_ptr.resolution = .fromObjectFunction(wasm, index);
|
||||
continue;
|
||||
}
|
||||
var err = try diags.addErrorWithNotes(2);
|
||||
try err.addMsg("symbol collision: {s}", .{name.slice(wasm)});
|
||||
try err.addSrcNote(gop.value_ptr.source_location, "exported as {} here", .{ptr.type_index.fmt(wasm)});
|
||||
try err.addSrcNote(source_location, "exported as {} here", .{gop.value_ptr.type.fmt(wasm)});
|
||||
gop.value_ptr.source_location.addNote(wasm, &err, "exported as {} here", .{ptr.type_index.fmt(wasm)});
|
||||
source_location.addNote(wasm, &err, "exported as {} here", .{gop.value_ptr.type.fmt(wasm)});
|
||||
continue;
|
||||
} else {
|
||||
gop.value_ptr.* = .{
|
||||
.flags = symbol.flags,
|
||||
.module_name = host_name,
|
||||
.source_location = source_location,
|
||||
.resolution = .fromObjectFunction(index),
|
||||
.resolution = .fromObjectFunction(wasm, index),
|
||||
.type = ptr.type_index,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
inline .global, .global_import, .table, .table_import => |i| {
|
||||
inline .global_import, .table_import => |i| {
|
||||
const ptr = i.value(wasm);
|
||||
assert(i.key(wasm).toOptional() == symbol.name); // TODO
|
||||
ptr.flags = symbol.flags;
|
||||
if (symbol.flags.undefined and symbol.flags.binding == .local) {
|
||||
const name = i.key(wasm).slice(wasm);
|
||||
diags.addParseError(path, "local symbol '{s}' references import", .{name});
|
||||
}
|
||||
},
|
||||
inline .global, .table => |i| {
|
||||
const ptr = i.ptr(wasm);
|
||||
ptr.name = symbol.name;
|
||||
ptr.flags = symbol.flags;
|
||||
|
|
@ -857,10 +902,11 @@ pub fn parse(
|
|||
},
|
||||
.section => |i| {
|
||||
// Name is provided by the section directly; symbol table does not have it.
|
||||
const ptr = i.ptr(wasm);
|
||||
ptr.flags = symbol.flags;
|
||||
//const ptr = i.ptr(wasm);
|
||||
//ptr.flags = symbol.flags;
|
||||
_ = i;
|
||||
if (symbol.flags.undefined and symbol.flags.binding == .local) {
|
||||
const name = ptr.name.slice(wasm);
|
||||
const name = symbol.name.slice(wasm).?;
|
||||
diags.addParseError(path, "local symbol '{s}' references import", .{name});
|
||||
}
|
||||
},
|
||||
|
|
@ -868,15 +914,7 @@ pub fn parse(
|
|||
const name = symbol.name.unwrap().?;
|
||||
log.warn("TODO data import '{s}'", .{name.slice(wasm)});
|
||||
},
|
||||
.data => |data| {
|
||||
const ptr = data.ptr(wasm);
|
||||
const is_passive = ptr.flags.is_passive;
|
||||
ptr.name = symbol.name;
|
||||
ptr.flags = symbol.flags;
|
||||
ptr.flags.is_passive = is_passive;
|
||||
ptr.offset = data.segment_offset;
|
||||
ptr.size = data.size;
|
||||
},
|
||||
.data => continue, // `wasm.object_datas` has already been populated.
|
||||
};
|
||||
|
||||
// Apply export section info. This is done after the symbol table above so
|
||||
|
|
@ -957,18 +995,6 @@ pub fn parse(
|
|||
.off = functions_start,
|
||||
.len = @intCast(wasm.object_functions.items.len - functions_start),
|
||||
},
|
||||
.globals = .{
|
||||
.off = globals_start,
|
||||
.len = @intCast(wasm.object_globals.items.len - globals_start),
|
||||
},
|
||||
.tables = .{
|
||||
.off = tables_start,
|
||||
.len = @intCast(wasm.object_tables.items.len - tables_start),
|
||||
},
|
||||
.memories = .{
|
||||
.off = memories_start,
|
||||
.len = @intCast(wasm.object_memories.items.len - memories_start),
|
||||
},
|
||||
.function_imports = .{
|
||||
.off = function_imports_start,
|
||||
.len = @intCast(wasm.object_function_imports.entries.len - function_imports_start),
|
||||
|
|
@ -979,7 +1005,7 @@ pub fn parse(
|
|||
},
|
||||
.table_imports = .{
|
||||
.off = table_imports_start,
|
||||
.len = @intCast(wasm.object_table_imports.items.len - table_imports_start),
|
||||
.len = @intCast(wasm.object_table_imports.entries.len - table_imports_start),
|
||||
},
|
||||
.init_funcs = .{
|
||||
.off = init_funcs_start,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue