authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-12-14 16:55:23+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-12-14 16:55:23+01:00
logf95549ddc71f75f3bf15f54f8d03a1a367d0db37
tree5d043b4c9df3a85a467f767d9542a4f5cc94ad3b
parent41199bba4bae4783634ee52ecd8d111f8f82fd4c
signaturelock-open Commit is signed but in an unrecognized format.

wasm-linker: Export data symbols as global

When a data symbol is required to be exported, we instead generate a global that will be exported. This global is immutable and contains the address of the data symbol.

2 files changed, 39 insertions(+), 4 deletions(-)

src/link/Wasm.zig+38-3
...@@ -112,6 +112,8 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},...@@ -112,6 +112,8 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
112functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, std.wasm.Func) = .{},112functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, std.wasm.Func) = .{},
113/// Output global section113/// Output global section
114wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},114wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
115/// Global symbols for exported data symbols
116address_globals: std.ArrayListUnmanaged(SymbolLoc) = .{},
115/// Memory section117/// Memory section
116memories: std.wasm.Memory = .{ .limits = .{ .min = 0, .max = null } },118memories: std.wasm.Memory = .{ .limits = .{ .min = 0, .max = null } },
117/// Output table section119/// Output table section
...@@ -839,6 +841,7 @@ pub fn deinit(wasm: *Wasm) void {...@@ -839,6 +841,7 @@ pub fn deinit(wasm: *Wasm) void {
839 wasm.func_types.deinit(gpa);841 wasm.func_types.deinit(gpa);
840 wasm.functions.deinit(gpa);842 wasm.functions.deinit(gpa);
841 wasm.wasm_globals.deinit(gpa);843 wasm.wasm_globals.deinit(gpa);
844 wasm.address_globals.deinit(gpa);
842 wasm.function_table.deinit(gpa);845 wasm.function_table.deinit(gpa);
843 wasm.tables.deinit(gpa);846 wasm.tables.deinit(gpa);
844 wasm.exports.deinit(gpa);847 wasm.exports.deinit(gpa);
...@@ -1804,7 +1807,15 @@ fn setupExports(wasm: *Wasm) !void {...@@ -1804,7 +1807,15 @@ fn setupExports(wasm: *Wasm) !void {
1804 if (sym_loc.file == null) break :blk symbol.name;1807 if (sym_loc.file == null) break :blk symbol.name;
1805 break :blk try wasm.string_table.put(wasm.base.allocator, sym_name);1808 break :blk try wasm.string_table.put(wasm.base.allocator, sym_name);
1806 };1809 };
1807 const exp: types.Export = .{1810 const exp: types.Export = if (symbol.tag == .data) exp: {
1811 const global_index = @intCast(u32, wasm.wasm_globals.items.len + wasm.address_globals.items.len);
1812 try wasm.address_globals.append(wasm.base.allocator, sym_loc);
1813 break :exp .{
1814 .name = export_name,
1815 .kind = .global,
1816 .index = global_index,
1817 };
1818 } else .{
1808 .name = export_name,1819 .name = export_name,
1809 .kind = symbol.tag.externalType(),1820 .kind = symbol.tag.externalType(),
1810 .index = symbol.index,1821 .index = symbol.index,
...@@ -2473,10 +2484,22 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l...@@ -2473,10 +2484,22 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
2473 if (wasm.wasm_globals.items.len > 0) {2484 if (wasm.wasm_globals.items.len > 0) {
2474 const header_offset = try reserveVecSectionHeader(&binary_bytes);2485 const header_offset = try reserveVecSectionHeader(&binary_bytes);
24752486
2487 var global_count: u32 = 0;
2476 for (wasm.wasm_globals.items) |global| {2488 for (wasm.wasm_globals.items) |global| {
2477 try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));2489 try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));
2478 try binary_writer.writeByte(@boolToInt(global.global_type.mutable));2490 try binary_writer.writeByte(@boolToInt(global.global_type.mutable));
2479 try emitInit(binary_writer, global.init);2491 try emitInit(binary_writer, global.init);
2492 global_count += 1;
2493 }
2494
2495 for (wasm.address_globals.items) |sym_loc| {
2496 const atom = wasm.symbol_atom.get(sym_loc).?;
2497 try binary_writer.writeByte(std.wasm.valtype(.i32));
2498 try binary_writer.writeByte(0); // immutable
2499 try emitInit(binary_writer, .{
2500 .i32_const = @bitCast(i32, atom.offset),
2501 });
2502 global_count += 1;
2480 }2503 }
24812504
2482 try writeVecSectionHeader(2505 try writeVecSectionHeader(
...@@ -2484,7 +2507,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l...@@ -2484,7 +2507,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
2484 header_offset,2507 header_offset,
2485 .global,2508 .global,
2486 @intCast(u32, binary_bytes.items.len - header_offset - header_size),2509 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
2487 @intCast(u32, wasm.wasm_globals.items.len),2510 @intCast(u32, global_count),
2488 );2511 );
2489 section_count += 1;2512 section_count += 1;
2490 }2513 }
...@@ -2990,10 +3013,22 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2990,10 +3013,22 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2990 if (wasm.wasm_globals.items.len > 0) {3013 if (wasm.wasm_globals.items.len > 0) {
2991 const header_offset = try reserveVecSectionHeader(&binary_bytes);3014 const header_offset = try reserveVecSectionHeader(&binary_bytes);
29923015
3016 var global_count: u32 = 0;
2993 for (wasm.wasm_globals.items) |global| {3017 for (wasm.wasm_globals.items) |global| {
2994 try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));3018 try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));
2995 try binary_writer.writeByte(@boolToInt(global.global_type.mutable));3019 try binary_writer.writeByte(@boolToInt(global.global_type.mutable));
2996 try emitInit(binary_writer, global.init);3020 try emitInit(binary_writer, global.init);
3021 global_count += 1;
3022 }
3023
3024 for (wasm.address_globals.items) |sym_loc| {
3025 const atom = wasm.symbol_atom.get(sym_loc).?;
3026 try binary_writer.writeByte(std.wasm.valtype(.i32));
3027 try binary_writer.writeByte(0); // immutable
3028 try emitInit(binary_writer, .{
3029 .i32_const = @bitCast(i32, atom.offset),
3030 });
3031 global_count += 1;
2997 }3032 }
29983033
2999 try writeVecSectionHeader(3034 try writeVecSectionHeader(
...@@ -3001,7 +3036,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -3001,7 +3036,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
3001 header_offset,3036 header_offset,
3002 .global,3037 .global,
3003 @intCast(u32, binary_bytes.items.len - header_offset - header_size),3038 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
3004 @intCast(u32, wasm.wasm_globals.items.len),3039 @intCast(u32, global_count),
3005 );3040 );
3006 section_count += 1;3041 section_count += 1;
3007 }3042 }
src/link/Wasm/Symbol.zig+1-1
...@@ -38,7 +38,7 @@ pub const Tag = enum {...@@ -38,7 +38,7 @@ pub const Tag = enum {
38 return switch (tag) {38 return switch (tag) {
39 .function => .function,39 .function => .function,
40 .global => .global,40 .global => .global,
41 .data => .memory,41 .data => unreachable, // Data symbols will generate a global
42 .section => unreachable, // Not an external type42 .section => unreachable, // Not an external type
43 .event => unreachable, // Not an external type43 .event => unreachable, // Not an external type
44 .dead => unreachable, // Dead symbols should not be referenced44 .dead => unreachable, // Dead symbols should not be referenced