Commit d6b42e585b
Changed files (4)
src
src/link/Wasm/Flush.zig
@@ -52,7 +52,7 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {
f.* = undefined;
}
-pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
+pub fn finish(f: *Flush, wasm: *Wasm) !void {
const comp = wasm.base.comp;
const shared_memory = comp.config.shared_memory;
const diags = &comp.link_diags;
@@ -685,7 +685,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
// try wasm.emitDataRelocations(binary_bytes, data_index, symbol_table);
//}
} else if (comp.config.debug_format != .strip) {
- try emitNameSection(wasm, binary_bytes, arena);
+ try emitNameSection(wasm, &f.data_segments, binary_bytes);
}
if (comp.config.debug_format != .strip) {
@@ -732,117 +732,77 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
try file.setEndPos(binary_bytes.items.len);
}
-fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), arena: Allocator) !void {
- if (true) {
- std.log.warn("TODO emit name section", .{});
- return;
- }
+fn emitNameSection(
+ wasm: *Wasm,
+ data_segments: *const std.AutoArrayHashMapUnmanaged(Wasm.DataSegment.Index, u32),
+ binary_bytes: *std.ArrayListUnmanaged(u8),
+) !void {
const comp = wasm.base.comp;
const gpa = comp.gpa;
- const import_memory = comp.config.import_memory;
- // Deduplicate symbols that point to the same function.
- var funcs: std.AutoArrayHashMapUnmanaged(u32, String) = .empty;
- try funcs.ensureUnusedCapacityPrecise(arena, wasm.functions.count() + wasm.function_imports.items.len);
+ const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
+ defer writeCustomSectionHeader(binary_bytes, header_offset);
- const NamedIndex = struct {
- index: u32,
- name: String,
- };
+ const name_name = "name";
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, name_name.len));
+ try binary_bytes.appendSlice(gpa, name_name);
- var globals: std.MultiArrayList(NamedIndex) = .empty;
- try globals.ensureTotalCapacityPrecise(arena, wasm.globals.items.len + wasm.global_imports.items.len);
-
- var segments: std.MultiArrayList(NamedIndex) = .empty;
- try segments.ensureTotalCapacityPrecise(arena, wasm.data_segments.count());
-
- for (wasm.resolved_symbols.keys()) |sym_loc| {
- const symbol = wasm.finalSymbolByLoc(sym_loc).*;
- if (!symbol.flags.alive) continue;
- const name = wasm.finalSymbolByLoc(sym_loc).name;
- switch (symbol.tag) {
- .function => {
- const index = if (symbol.flags.undefined)
- @intFromEnum(symbol.pointee.function_import)
- else
- wasm.function_imports.items.len + @intFromEnum(symbol.pointee.function);
- const gop = funcs.getOrPutAssumeCapacity(index);
- if (gop.found_existing) {
- assert(gop.value_ptr.* == name);
- } else {
- gop.value_ptr.* = name;
- }
- },
- .global => {
- globals.appendAssumeCapacity(.{
- .index = if (symbol.flags.undefined)
- @intFromEnum(symbol.pointee.global_import)
- else
- @intFromEnum(symbol.pointee.global),
- .name = name,
- });
- },
- else => {},
+ {
+ const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
+ defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.function));
+
+ const total_functions: u32 = @intCast(wasm.function_imports.entries.len + wasm.functions.entries.len);
+ try leb.writeUleb128(binary_bytes.writer(gpa), total_functions);
+
+ for (wasm.function_imports.keys(), 0..) |name_index, function_index| {
+ const name = name_index.slice(wasm);
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(function_index)));
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
+ }
+ for (wasm.functions.keys(), wasm.function_imports.entries.len..) |resolution, function_index| {
+ const name = resolution.name(wasm).?;
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(function_index)));
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
}
}
- for (wasm.data_segments.keys(), 0..) |key, index| {
- // bss section is not emitted when this condition holds true, so we also
- // do not output a name for it.
- if (!import_memory and mem.eql(u8, key, ".bss")) continue;
- segments.appendAssumeCapacity(.{ .index = @intCast(index), .name = key });
- }
+ {
+ const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
+ defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.global));
- const Sort = struct {
- indexes: []const u32,
- pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool {
- return ctx.indexes[lhs] < ctx.indexes[rhs];
+ const total_globals: u32 = @intCast(wasm.global_imports.entries.len + wasm.globals.entries.len);
+ try leb.writeUleb128(binary_bytes.writer(gpa), total_globals);
+
+ for (wasm.global_imports.keys(), 0..) |name_index, global_index| {
+ const name = name_index.slice(wasm);
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(global_index)));
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
}
- };
- funcs.entries.sortUnstable(@as(Sort, .{ .indexes = funcs.keys() }));
- globals.sortUnstable(@as(Sort, .{ .indexes = globals.items(.index) }));
- // Data segments are already ordered.
+ for (wasm.globals.keys(), wasm.global_imports.entries.len..) |resolution, global_index| {
+ const name = resolution.name(wasm).?;
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(global_index)));
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
+ }
+ }
- const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
- defer writeCustomSectionHeader(binary_bytes, header_offset);
+ {
+ const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
+ defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.data_segment));
- const writer = binary_bytes.writer(gpa);
- try leb.writeUleb128(writer, @as(u32, @intCast("name".len)));
- try writer.writeAll("name");
+ const total_globals: u32 = @intCast(wasm.global_imports.entries.len + wasm.globals.entries.len);
+ try leb.writeUleb128(binary_bytes.writer(gpa), total_globals);
- try emitNameSubsection(wasm, binary_bytes, .function, funcs.keys(), funcs.values());
- try emitNameSubsection(wasm, binary_bytes, .global, globals.items(.index), globals.items(.name));
- try emitNameSubsection(wasm, binary_bytes, .data_segment, segments.items(.index), segments.items(.name));
-}
-
-fn emitNameSubsection(
- wasm: *const Wasm,
- binary_bytes: *std.ArrayListUnmanaged(u8),
- section_id: std.wasm.NameSubsection,
- indexes: []const u32,
- names: []const String,
-) !void {
- assert(indexes.len == names.len);
- const gpa = wasm.base.comp.gpa;
- // We must emit subsection size, so first write to a temporary list
- var section_list: std.ArrayListUnmanaged(u8) = .empty;
- defer section_list.deinit(gpa);
- const sub_writer = section_list.writer(gpa);
-
- try leb.writeUleb128(sub_writer, @as(u32, @intCast(names.len)));
- for (indexes, names) |index, name_index| {
- const name = name_index.slice(wasm);
- log.debug("emit symbol '{s}' type({s})", .{ name, @tagName(section_id) });
- try leb.writeUleb128(sub_writer, index);
- try leb.writeUleb128(sub_writer, @as(u32, @intCast(name.len)));
- try sub_writer.writeAll(name);
+ for (data_segments.keys(), 0..) |ds, i| {
+ const name = ds.ptr(wasm).name.slice(wasm).?;
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(i)));
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
+ }
}
-
- // From now, write to the actual writer
- const writer = binary_bytes.writer(gpa);
- try leb.writeUleb128(writer, @intFromEnum(section_id));
- try leb.writeUleb128(writer, @as(u32, @intCast(section_list.items.len)));
- try binary_bytes.appendSlice(gpa, section_list.items);
}
fn emitFeaturesSection(
@@ -1094,11 +1054,15 @@ fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)
}
fn writeCustomSectionHeader(bytes: *std.ArrayListUnmanaged(u8), offset: u32) void {
+ return replaceHeader(bytes, offset, 0); // 0 = 'custom' section
+}
+
+fn replaceHeader(bytes: *std.ArrayListUnmanaged(u8), offset: u32, tag: u8) void {
const size: u32 = @intCast(bytes.items.len - offset - section_header_size);
var buf: [section_header_size]u8 = undefined;
var fbw = std.io.fixedBufferStream(&buf);
const w = fbw.writer();
- w.writeByte(0) catch unreachable; // 0 = 'custom' section
+ w.writeByte(tag) catch unreachable;
leb.writeUleb128(w, size) catch unreachable;
bytes.replaceRangeAssumeCapacity(offset, section_header_size, fbw.getWritten());
}
src/link/Wasm.zig
@@ -550,7 +550,7 @@ pub const NavObj = extern struct {
/// Empty if not emitting an object.
relocs: OutReloc.Slice,
- /// Index into `navs`.
+ /// Index into `Wasm.navs_obj`.
/// Note that swapRemove is sometimes performed on `navs`.
pub const Index = enum(u32) {
_,
@@ -562,13 +562,20 @@ pub const NavObj = extern struct {
pub fn value(i: @This(), wasm: *const Wasm) *NavObj {
return &wasm.navs_obj.values()[@intFromEnum(i)];
}
+
+ pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 {
+ const zcu = wasm.base.comp.zcu.?;
+ const ip = &zcu.intern_pool;
+ const nav = ip.getNav(i.key(wasm).*);
+ return nav.fqn.toSlice(ip);
+ }
};
};
pub const NavExe = extern struct {
code: DataSegment.Payload,
- /// Index into `navs`.
+ /// Index into `Wasm.navs_exe`.
/// Note that swapRemove is sometimes performed on `navs`.
pub const Index = enum(u32) {
_,
@@ -580,6 +587,13 @@ pub const NavExe = extern struct {
pub fn value(i: @This(), wasm: *const Wasm) *NavExe {
return &wasm.navs_exe.values()[@intFromEnum(i)];
}
+
+ pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 {
+ const zcu = wasm.base.comp.zcu.?;
+ const ip = &zcu.intern_pool;
+ const nav = ip.getNav(i.key(wasm).*);
+ return nav.fqn.toSlice(ip);
+ }
};
};
@@ -598,6 +612,14 @@ pub const ZcuFunc = extern struct {
pub fn value(i: @This(), wasm: *const Wasm) *ZcuFunc {
return &wasm.zcu_funcs.values()[@intFromEnum(i)];
}
+
+ pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 {
+ const zcu = wasm.base.comp.zcu.?;
+ const ip = &zcu.intern_pool;
+ const func = ip.toFunc(i.key(wasm).*);
+ const nav = ip.getNav(func.owner_nav);
+ return nav.fqn.toSlice(ip);
+ }
};
};
@@ -720,6 +742,19 @@ pub const FunctionImport = extern struct {
.zcu_func => @panic("TODO"),
};
}
+
+ pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 {
+ return switch (unpack(r, wasm)) {
+ .unresolved => unreachable,
+ .__wasm_apply_global_tls_relocs => @tagName(Unpacked.__wasm_apply_global_tls_relocs),
+ .__wasm_call_ctors => @tagName(Unpacked.__wasm_call_ctors),
+ .__wasm_init_memory => @tagName(Unpacked.__wasm_init_memory),
+ .__wasm_init_tls => @tagName(Unpacked.__wasm_init_tls),
+ .__zig_error_names => @tagName(Unpacked.__zig_error_names),
+ .object_function => |i| i.ptr(wasm).name.slice(wasm),
+ .zcu_func => |i| i.name(wasm),
+ };
+ }
};
/// Index into `object_function_imports`.
@@ -851,6 +886,22 @@ pub const GlobalImport = extern struct {
.nav_exe = @enumFromInt(wasm.navs_exe.getIndex(ip_nav).?),
});
}
+
+ pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 {
+ return switch (unpack(r, wasm)) {
+ .unresolved => unreachable,
+ .__heap_base => @tagName(Unpacked.__heap_base),
+ .__heap_end => @tagName(Unpacked.__heap_end),
+ .__stack_pointer => @tagName(Unpacked.__stack_pointer),
+ .__tls_align => @tagName(Unpacked.__tls_align),
+ .__tls_base => @tagName(Unpacked.__tls_base),
+ .__tls_size => @tagName(Unpacked.__tls_size),
+ .__zig_error_name_table => @tagName(Unpacked.__zig_error_name_table),
+ .object_global => |i| i.name(wasm).slice(wasm),
+ .nav_obj => |i| i.name(wasm),
+ .nav_exe => |i| i.name(wasm),
+ };
+ }
};
/// Index into `Wasm.object_global_imports`.
@@ -1038,6 +1089,10 @@ pub const ObjectGlobalIndex = enum(u32) {
pub fn ptr(index: ObjectGlobalIndex, wasm: *const Wasm) *Global {
return &wasm.object_globals.items[@intFromEnum(index)];
}
+
+ pub fn name(index: ObjectGlobalIndex, wasm: *const Wasm) OptionalString {
+ return index.ptr(wasm).name;
+ }
};
/// Index into `Wasm.object_memories`.
@@ -1049,7 +1104,7 @@ pub const ObjectMemoryIndex = enum(u32) {
}
};
-/// Index into `object_functions`.
+/// Index into `Wasm.object_functions`.
pub const ObjectFunctionIndex = enum(u32) {
_,
@@ -2397,7 +2452,7 @@ pub fn flushModule(
defer sub_prog_node.end();
wasm.flush_buffer.clear();
- return wasm.flush_buffer.finish(wasm, arena) catch |err| switch (err) {
+ return wasm.flush_buffer.finish(wasm) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.LinkFailure => return error.LinkFailure,
else => |e| return diags.fail("failed to flush wasm: {s}", .{@errorName(e)}),
src/InternPool.zig
@@ -11801,6 +11801,10 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
return @enumFromInt(ip.indexToKey(int).int.storage.u64);
}
+pub fn toFunc(ip: *const InternPool, i: Index) Key.Func {
+ return ip.indexToKey(i).func;
+}
+
pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
return switch (ip.indexToKey(ty)) {
.struct_type => ip.loadStructType(ty).field_types.len,
src/Zcu.zig
@@ -3483,7 +3483,7 @@ pub fn iesFuncIndex(zcu: *const Zcu, ies_index: InternPool.Index) InternPool.Ind
}
pub fn funcInfo(zcu: *const Zcu, func_index: InternPool.Index) InternPool.Key.Func {
- return zcu.intern_pool.indexToKey(func_index).func;
+ return zcu.intern_pool.toFunc(func_index);
}
pub fn toEnum(zcu: *const Zcu, comptime E: type, val: Value) E {