aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-12-14 16:55:23 +0100
committerLuuk de Gram <luuk@degram.dev>2022-12-14 16:55:23 +0100
commitf95549ddc71f75f3bf15f54f8d03a1a367d0db37 (patch)
tree5d043b4c9df3a85a467f767d9542a4f5cc94ad3b /src
parent41199bba4bae4783634ee52ecd8d111f8f82fd4c (diff)
downloadzig-f95549ddc71f75f3bf15f54f8d03a1a367d0db37.tar.gz
zig-f95549ddc71f75f3bf15f54f8d03a1a367d0db37.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/link/Wasm.zig41
-rw-r--r--src/link/Wasm/Symbol.zig2
2 files changed, 39 insertions, 4 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index e5bce8bda6..e89422d0ae 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -112,6 +112,8 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, std.wasm.Func) = .{},
/// Output global section
wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
+/// Global symbols for exported data symbols
+address_globals: std.ArrayListUnmanaged(SymbolLoc) = .{},
/// Memory section
memories: std.wasm.Memory = .{ .limits = .{ .min = 0, .max = null } },
/// Output table section
@@ -839,6 +841,7 @@ pub fn deinit(wasm: *Wasm) void {
wasm.func_types.deinit(gpa);
wasm.functions.deinit(gpa);
wasm.wasm_globals.deinit(gpa);
+ wasm.address_globals.deinit(gpa);
wasm.function_table.deinit(gpa);
wasm.tables.deinit(gpa);
wasm.exports.deinit(gpa);
@@ -1804,7 +1807,15 @@ fn setupExports(wasm: *Wasm) !void {
if (sym_loc.file == null) break :blk symbol.name;
break :blk try wasm.string_table.put(wasm.base.allocator, sym_name);
};
- const exp: types.Export = .{
+ const exp: types.Export = if (symbol.tag == .data) exp: {
+ const global_index = @intCast(u32, wasm.wasm_globals.items.len + wasm.address_globals.items.len);
+ try wasm.address_globals.append(wasm.base.allocator, sym_loc);
+ break :exp .{
+ .name = export_name,
+ .kind = .global,
+ .index = global_index,
+ };
+ } else .{
.name = export_name,
.kind = symbol.tag.externalType(),
.index = symbol.index,
@@ -2473,10 +2484,22 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
if (wasm.wasm_globals.items.len > 0) {
const header_offset = try reserveVecSectionHeader(&binary_bytes);
+ var global_count: u32 = 0;
for (wasm.wasm_globals.items) |global| {
try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));
try binary_writer.writeByte(@boolToInt(global.global_type.mutable));
try emitInit(binary_writer, global.init);
+ global_count += 1;
+ }
+
+ for (wasm.address_globals.items) |sym_loc| {
+ const atom = wasm.symbol_atom.get(sym_loc).?;
+ try binary_writer.writeByte(std.wasm.valtype(.i32));
+ try binary_writer.writeByte(0); // immutable
+ try emitInit(binary_writer, .{
+ .i32_const = @bitCast(i32, atom.offset),
+ });
+ global_count += 1;
}
try writeVecSectionHeader(
@@ -2484,7 +2507,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
header_offset,
.global,
@intCast(u32, binary_bytes.items.len - header_offset - header_size),
- @intCast(u32, wasm.wasm_globals.items.len),
+ @intCast(u32, global_count),
);
section_count += 1;
}
@@ -2990,10 +3013,22 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
if (wasm.wasm_globals.items.len > 0) {
const header_offset = try reserveVecSectionHeader(&binary_bytes);
+ var global_count: u32 = 0;
for (wasm.wasm_globals.items) |global| {
try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));
try binary_writer.writeByte(@boolToInt(global.global_type.mutable));
try emitInit(binary_writer, global.init);
+ global_count += 1;
+ }
+
+ for (wasm.address_globals.items) |sym_loc| {
+ const atom = wasm.symbol_atom.get(sym_loc).?;
+ try binary_writer.writeByte(std.wasm.valtype(.i32));
+ try binary_writer.writeByte(0); // immutable
+ try emitInit(binary_writer, .{
+ .i32_const = @bitCast(i32, atom.offset),
+ });
+ global_count += 1;
}
try writeVecSectionHeader(
@@ -3001,7 +3036,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
header_offset,
.global,
@intCast(u32, binary_bytes.items.len - header_offset - header_size),
- @intCast(u32, wasm.wasm_globals.items.len),
+ @intCast(u32, global_count),
);
section_count += 1;
}
diff --git a/src/link/Wasm/Symbol.zig b/src/link/Wasm/Symbol.zig
index d857e6de44..365f4a2c0b 100644
--- a/src/link/Wasm/Symbol.zig
+++ b/src/link/Wasm/Symbol.zig
@@ -38,7 +38,7 @@ pub const Tag = enum {
return switch (tag) {
.function => .function,
.global => .global,
- .data => .memory,
+ .data => unreachable, // Data symbols will generate a global
.section => unreachable, // Not an external type
.event => unreachable, // Not an external type
.dead => unreachable, // Dead symbols should not be referenced