authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-07-17 20:22:25+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-07-19 17:22:46+02:00
log1a3304ed236b60cd31c790bae929a78c58c9d33e
treef0cee69c44e49054a0641f6a6152578e46ffd2b6
parent3fd6e93f4f6f34658d5e198064f54e1dad09e241
signaturelock-open Commit is signed but in an unrecognized format.

test/link: add shared-memory test for WebAssembly


4 files changed, 100 insertions(+), 3 deletions(-)

lib/std/Build/Step/CheckObject.zig+14-3
...@@ -1012,6 +1012,10 @@ const WasmDumper = struct {...@@ -1012,6 +1012,10 @@ const WasmDumper = struct {
1012 const start = try std.leb.readULEB128(u32, reader);1012 const start = try std.leb.readULEB128(u32, reader);
1013 try writer.print("\nstart {d}\n", .{start});1013 try writer.print("\nstart {d}\n", .{start});
1014 },1014 },
1015 .data_count => {
1016 const count = try std.leb.readULEB128(u32, reader);
1017 try writer.print("\ncount {d}\n", .{count});
1018 },
1015 else => {}, // skip unknown sections1019 else => {}, // skip unknown sections
1016 }1020 }
1017 }1021 }
...@@ -1143,9 +1147,16 @@ const WasmDumper = struct {...@@ -1143,9 +1147,16 @@ const WasmDumper = struct {
1143 .data => {1147 .data => {
1144 var i: u32 = 0;1148 var i: u32 = 0;
1145 while (i < entries) : (i += 1) {1149 while (i < entries) : (i += 1) {
1146 const index = try std.leb.readULEB128(u32, reader);1150 const flags = try std.leb.readULEB128(u32, reader);
1151 const index = if (flags & 0x02 != 0)
1152 try std.leb.readULEB128(u32, reader)
1153 else
1154 0;
1147 try writer.print("memory index 0x{x}\n", .{index});1155 try writer.print("memory index 0x{x}\n", .{index});
1148 try parseDumpInit(step, reader, writer);1156 if (flags == 0) {
1157 try parseDumpInit(step, reader, writer);
1158 }
1159
1149 const size = try std.leb.readULEB128(u32, reader);1160 const size = try std.leb.readULEB128(u32, reader);
1150 try writer.print("size {d}\n", .{size});1161 try writer.print("size {d}\n", .{size});
1151 try reader.skipBytes(size, .{}); // we do not care about the content of the segments1162 try reader.skipBytes(size, .{}); // we do not care about the content of the segments
...@@ -1174,7 +1185,7 @@ const WasmDumper = struct {...@@ -1174,7 +1185,7 @@ const WasmDumper = struct {
1174 }1185 }
11751186
1176 fn parseDumpInit(step: *Step, reader: anytype, writer: anytype) !void {1187 fn parseDumpInit(step: *Step, reader: anytype, writer: anytype) !void {
1177 const byte = try std.leb.readULEB128(u8, reader);1188 const byte = try reader.readByte();
1178 const opcode = std.meta.intToEnum(std.wasm.Opcode, byte) catch {1189 const opcode = std.meta.intToEnum(std.wasm.Opcode, byte) catch {
1179 return step.fail("invalid wasm opcode '{d}'", .{byte});1190 return step.fail("invalid wasm opcode '{d}'", .{byte});
1180 };1191 };
lib/std/Build/Step/Compile.zig+4
...@@ -65,6 +65,7 @@ sanitize_thread: bool,...@@ -65,6 +65,7 @@ sanitize_thread: bool,
65rdynamic: bool,65rdynamic: bool,
66dwarf_format: ?std.dwarf.Format = null,66dwarf_format: ?std.dwarf.Format = null,
67import_memory: bool = false,67import_memory: bool = false,
68export_memory: bool = false,
68/// For WebAssembly targets, this will allow for undefined symbols to69/// For WebAssembly targets, this will allow for undefined symbols to
69/// be imported from the host environment.70/// be imported from the host environment.
70import_symbols: bool = false,71import_symbols: bool = false,
...@@ -1662,6 +1663,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1662,6 +1663,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1662 if (self.import_memory) {1663 if (self.import_memory) {
1663 try zig_args.append("--import-memory");1664 try zig_args.append("--import-memory");
1664 }1665 }
1666 if (self.export_memory) {
1667 try zig_args.append("--export-memory");
1668 }
1665 if (self.import_symbols) {1669 if (self.import_symbols) {
1666 try zig_args.append("--import-symbols");1670 try zig_args.append("--import-symbols");
1667 }1671 }
test/link/wasm/shared-memory/build.zig created+77
...@@ -0,0 +1,77 @@
1const std = @import("std");
2
3pub fn build(b: *std.Build) void {
4 const test_step = b.step("test", "Test");
5 b.default_step = test_step;
6
7 add(b, test_step, .Debug);
8
9 // Enable the following build modes once garbage-collection is implemented properly.
10 // add(b, test_step, .ReleaseFast);
11 // add(b, test_step, .ReleaseSmall);
12 // add(b, test_step, .ReleaseSafe);
13}
14
15fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode) void {
16 {
17 const lib = b.addSharedLibrary(.{
18 .name = "lib",
19 .root_source_file = .{ .path = "lib.zig" },
20 .target = .{
21 .cpu_arch = .wasm32,
22 .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
23 .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }),
24 .os_tag = .freestanding,
25 },
26 .optimize = optimize_mode,
27 });
28 lib.use_lld = false;
29 lib.strip = false;
30 lib.import_memory = true;
31 lib.export_memory = true;
32 lib.shared_memory = true;
33 lib.max_memory = 67108864;
34 lib.single_threaded = false;
35 lib.export_symbol_names = &.{"foo"};
36
37 const check_lib = lib.checkObject();
38
39 check_lib.checkStart("Section import");
40 check_lib.checkNext("entries 1");
41 check_lib.checkNext("module env");
42 check_lib.checkNext("name memory"); // ensure we are importing memory
43
44 check_lib.checkStart("Section export");
45 check_lib.checkNext("entries 2");
46 check_lib.checkNext("name memory"); // ensure we also export memory again
47
48 // This section *must* be emit as the start function is set to the index
49 // of __wasm_init_memory
50 check_lib.checkStart("Section start");
51
52 // This section is only and *must* be emit when shared-memory is enabled
53 check_lib.checkStart("Section data_count");
54 check_lib.checkNext("count 3");
55
56 check_lib.checkStart("Section custom");
57 check_lib.checkNext("name name");
58 check_lib.checkNext("type function");
59 check_lib.checkNext("name __wasm_init_memory");
60 check_lib.checkNext("name __wasm_init_tls");
61 check_lib.checkNext("type global");
62 check_lib.checkNext("name __tls_size");
63 check_lib.checkNext("name __tls_align");
64 check_lib.checkNext("name __tls_base");
65
66 check_lib.checkNext("type data_segment");
67 check_lib.checkNext("names 3");
68 check_lib.checkNext("index 0");
69 check_lib.checkNext("name .rodata");
70 check_lib.checkNext("index 1");
71 check_lib.checkNext("name .bss");
72 check_lib.checkNext("index 2");
73 check_lib.checkNext("name .tdata");
74
75 test_step.dependOn(&check_lib.step);
76 }
77}
test/link/wasm/shared-memory/lib.zig created+5
...@@ -0,0 +1,5 @@
1threadlocal var some_tls_global: u32 = 1;
2
3export fn foo() void {
4 some_tls_global = 2;
5}