From c69d88cc5c60aed7a68c37e12ce55667ad70acaf Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Fri, 26 Sep 2025 02:36:29 +0200 Subject: [PATCH 01/11] zig 0.15.1 --- build.zig | 46 ++++++++++++++++++++++++++---------------- src/module.zig | 54 ++++++++++++++++++++++++-------------------------- src/store.zig | 14 ++++++------- 3 files changed, 62 insertions(+), 52 deletions(-) diff --git a/build.zig b/build.zig index 4613799d..e1c8e46e 100644 --- a/build.zig +++ b/build.zig @@ -10,17 +10,19 @@ pub fn build(b: *Build) !void { try b.modules.put(b.dupe("zware"), zware_module); - const lib = b.addStaticLibrary(.{ - .name = "zware", + const main_mod = b.addModule("zware", .{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }); + const lib = b.addLibrary(.{ + .name = "zware", + .root_module = main_mod, + }); b.installArtifact(lib); const main_tests = b.addTest(.{ - .root_source_file = b.path("src/main.zig"), - .optimize = optimize, + .root_module = main_mod, }); const run_main_tests = b.addRunArtifact(main_tests); @@ -31,9 +33,11 @@ pub fn build(b: *Build) !void { const testrunner = b.addExecutable(.{ .name = "testrunner", - .root_source_file = b.path("test/testrunner/src/testrunner.zig"), - .target = target, - .optimize = optimize, + .root_module = b.addModule("testrunner", .{ + .root_source_file = b.path("test/testrunner/src/testrunner.zig"), + .target = target, + .optimize = optimize, + }), }); testrunner.root_module.addImport("zware", zware_module); @@ -61,9 +65,11 @@ pub fn build(b: *Build) !void { { const exe = b.addExecutable(.{ .name = "zware-run", - .root_source_file = b.path("tools/zware-run.zig"), - .target = target, - .optimize = optimize, + .root_module = b.addModule("zware-run", .{ + .root_source_file = b.path("tools/zware-run.zig"), + .target = target, + .optimize = optimize, + }), }); exe.root_module.addImport("zware", zware_module); const install = b.addInstallArtifact(exe, .{}); @@ -79,9 +85,11 @@ pub fn build(b: *Build) !void { { const exe = b.addExecutable(.{ .name = "zware-gen", - .root_source_file = b.path("tools/zware-gen.zig"), - .target = target, - .optimize = optimize, + .root_module = b.addModule("zware-gen", .{ + .root_source_file = b.path("tools/zware-gen.zig"), + .target = target, + .optimize = optimize, + }), }); exe.root_module.addImport("zware", zware_module); const install = b.addInstallArtifact(exe, .{}); @@ -116,10 +124,12 @@ fn addWast2Json(b: *Build) *Build.Step.Compile { .SIZEOF_SIZE_T = @sizeOf(usize), }); - const wabt_lib = b.addStaticLibrary(.{ + const wabt_lib = b.addLibrary(.{ .name = "wabt", - .target = b.graph.host, - .optimize = .Debug, + .root_module = b.createModule(.{ + .target = b.graph.host, + .optimize = .Debug, + }), }); wabt_lib.addConfigHeader(wabt_config_h); wabt_lib.addIncludePath(wabt_dep.path("include")); @@ -131,7 +141,9 @@ fn addWast2Json(b: *Build) *Build.Step.Compile { const wast2json = b.addExecutable(.{ .name = "wast2json", - .target = b.graph.host, + .root_module = b.createModule(.{ + .target = b.graph.host, + }), }); wast2json.addConfigHeader(wabt_config_h); wast2json.addIncludePath(wabt_dep.path("include")); diff --git a/src/module.zig b/src/module.zig index c6125343..d8719d04 100644 --- a/src/module.zig +++ b/src/module.zig @@ -41,22 +41,22 @@ pub const Module = struct { return Module{ .alloc = alloc, .wasm_bin = wasm_bin, - .customs = Section(Custom).init(alloc), - .types = Section(FuncType).init(alloc), - .imports = Section(Import).init(alloc), - .functions = Section(Function).init(alloc), - .tables = Section(TableType).init(alloc), - .memories = Section(MemType).init(alloc), - .globals = Section(GlobalType).init(alloc), - .exports = Section(Export).init(alloc), - .elements = Section(ElementSegment).init(alloc), - .codes = Section(Code).init(alloc), - .datas = Section(DataSegment).init(alloc), - .element_init_offsets = ArrayList(usize).init(alloc), - .parsed_code = ArrayList(Rr).init(alloc), - .local_types = ArrayList(LocalType).init(alloc), - .br_table_indices = ArrayList(u32).init(alloc), - .references = ArrayList(u32).init(alloc), + .customs = Section(Custom).empty, + .types = Section(FuncType).empty, + .imports = Section(Import).empty, + .functions = Section(Function).empty, + .tables = Section(TableType).empty, + .memories = Section(MemType).empty, + .globals = Section(GlobalType).empty, + .exports = Section(Export).empty, + .elements = Section(ElementSegment).empty, + .codes = Section(Code).empty, + .datas = Section(DataSegment).empty, + .element_init_offsets = ArrayList(usize).empty, + .parsed_code = ArrayList(Rr).empty, + .local_types = ArrayList(LocalType).empty, + .br_table_indices = ArrayList(u32).empty, + .references = ArrayList(u32).empty, }; } @@ -97,7 +97,7 @@ pub const Module = struct { // Push an initial return instruction so we don't have to // track the end of a function to use its return on invoke // See https://github.com/malcolmstill/zware/pull/133 - try self.parsed_code.append(.@"return"); + try self.parsed_code.append(self.alloc, .@"return"); var i: usize = 0; while (true) : (i += 1) { @@ -220,7 +220,7 @@ pub const Decoder = struct { results_valtype.ptr = @ptrCast(results.ptr); results_valtype.len = results.len; - try module.types.list.append(FuncType{ + try module.types.list.append(module.alloc, FuncType{ .params = params_valtype, .results = results_valtype, }); @@ -281,7 +281,7 @@ pub const Decoder = struct { module.function_index_start = module.functions.list.items.len; } - try module.functions.list.append(Function{ + try module.functions.list.append(module.alloc, Function{ .typeidx = typeidx, .import = import, }); @@ -311,7 +311,7 @@ pub const Decoder = struct { }, } }; - try module.tables.list.append(TableType{ + try module.tables.list.append(module.alloc, TableType{ .import = import, .reftype = reftype, .limits = Limit{ @@ -348,7 +348,7 @@ pub const Decoder = struct { }, } }; - try module.memories.list.append(MemType{ + try module.memories.list.append(module.alloc, MemType{ .import = import, .limits = Limit{ .min = min, @@ -773,7 +773,7 @@ pub const Decoder = struct { const data_length = try math.sub(usize, size, (self.fbs.pos - offset)); const data = try self.readSlice(data_length); - try module.customs.list.append(Custom{ + try module.customs.list.append(module.alloc, Custom{ .name = name, .data = data, }); @@ -809,7 +809,7 @@ pub const Decoder = struct { fn readLEB128(self: *Decoder, comptime T: type) !T { const readFn = switch (@typeInfo(T).int.signedness) { .signed => std.leb.readILEB128, - .unsigned => std.leb.readULEB128, + .unsigned => std.leb.readUleb128, }; return readFn(T, self.fbs.reader()); } @@ -831,11 +831,9 @@ fn Section(comptime T: type) type { const Self = @This(); - pub fn init(alloc: mem.Allocator) Self { - return Self{ - .list = ArrayList(T).init(alloc), - }; - } + pub const empty = Self{ + .list = ArrayList(T).empty, + }; pub fn deinit(self: *Self) void { self.list.deinit(); diff --git a/src/store.zig b/src/store.zig index d0fe7315..64a169a7 100644 --- a/src/store.zig +++ b/src/store.zig @@ -44,13 +44,13 @@ pub const ArrayListStore = struct { pub fn init(alloc: mem.Allocator) ArrayListStore { const store = ArrayListStore{ .alloc = alloc, - .functions = ArrayList(Function).init(alloc), - .memories = ArrayList(Memory).init(alloc), - .tables = ArrayList(Table).init(alloc), - .globals = ArrayList(Global).init(alloc), - .elems = ArrayList(Elem).init(alloc), - .datas = ArrayList(Data).init(alloc), - .imports = ArrayList(ImportExport).init(alloc), + .functions = ArrayList(Function).empty, + .memories = ArrayList(Memory).empty, + .tables = ArrayList(Table).empty, + .globals = ArrayList(Global).empty, + .elems = ArrayList(Elem).empty, + .datas = ArrayList(Data).empty, + .imports = ArrayList(ImportExport).empty, }; return store; From 396c57e1b7255a6907c2afc19177f0a684394128 Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Sat, 27 Sep 2025 12:10:39 +0200 Subject: [PATCH 02/11] more unmanaged structures --- src/instance.zig | 66 +++++++++--------- src/instance/vm.zig | 4 +- src/module.zig | 142 +++++++++++++++++++-------------------- src/module/parser.zig | 12 ++-- src/module/validator.zig | 14 ++-- src/store.zig | 40 +++++------ src/store/memory.zig | 6 +- src/store/table.zig | 8 +-- 8 files changed, 148 insertions(+), 144 deletions(-) diff --git a/src/instance.zig b/src/instance.zig index 8c7d778b..d252a5a3 100644 --- a/src/instance.zig +++ b/src/instance.zig @@ -33,6 +33,7 @@ const VirtualMachineOptions = struct { // - `tableaddrs`: as per `memaddrs` but for tables // - `globaladdrs`: as per `memaddrs` but for globals pub const Instance = struct { + alloc: mem.Allocator, module: Module, store: *Store, funcaddrs: ArrayList(usize), @@ -55,38 +56,39 @@ pub const Instance = struct { // a VirtualMachine swaps out its `inst` (instance) pointer as // it executes; an arbitrary `inst` will not contain the correct // data. - wasi_preopens: std.AutoHashMap(wasi.fd_t, WasiPreopen), + wasi_preopens: std.AutoHashMapUnmanaged(wasi.fd_t, WasiPreopen), wasi_args: std.ArrayList([:0]u8), - wasi_env: std.StringHashMap([]const u8), + wasi_env: std.StringHashMapUnmanaged([]const u8), pub fn init(alloc: mem.Allocator, store: *Store, module: Module) Instance { return Instance{ + .alloc = alloc, .module = module, .store = store, - .funcaddrs = ArrayList(usize).init(alloc), - .memaddrs = ArrayList(usize).init(alloc), - .tableaddrs = ArrayList(usize).init(alloc), - .globaladdrs = ArrayList(usize).init(alloc), - .elemaddrs = ArrayList(usize).init(alloc), - .dataaddrs = ArrayList(usize).init(alloc), - - .wasi_preopens = std.AutoHashMap(wasi.fd_t, WasiPreopen).init(alloc), - .wasi_args = ArrayList([:0]u8).init(alloc), - .wasi_env = std.StringHashMap([]const u8).init(alloc), + .funcaddrs = .empty, + .memaddrs = .empty, + .tableaddrs = .empty, + .globaladdrs = .empty, + .elemaddrs = .empty, + .dataaddrs = .empty, + + .wasi_preopens = .empty, + .wasi_args = .empty, + .wasi_env = .empty, }; } pub fn deinit(self: *Instance) void { - defer self.funcaddrs.deinit(); - defer self.memaddrs.deinit(); - defer self.tableaddrs.deinit(); - defer self.globaladdrs.deinit(); - defer self.elemaddrs.deinit(); - defer self.dataaddrs.deinit(); - - defer self.wasi_preopens.deinit(); - defer self.wasi_args.deinit(); - defer self.wasi_env.deinit(); + defer self.funcaddrs.deinit(self.alloc); + defer self.memaddrs.deinit(self.alloc); + defer self.tableaddrs.deinit(self.alloc); + defer self.globaladdrs.deinit(self.alloc); + defer self.elemaddrs.deinit(self.alloc); + defer self.dataaddrs.deinit(self.alloc); + + defer self.wasi_preopens.deinit(self.alloc); + defer self.wasi_args.deinit(self.alloc); + defer self.wasi_env.deinit(self.alloc); } pub fn getFunc(self: *Instance, funcidx: usize) !Function { @@ -161,10 +163,10 @@ pub const Instance = struct { error.ImportNotFound => return err.set(.{ .missing_import = import }), }; switch (import.desc_tag) { - .Func => try self.funcaddrs.append(import_handle), - .Mem => try self.memaddrs.append(import_handle), - .Table => try self.tableaddrs.append(import_handle), - .Global => try self.globaladdrs.append(import_handle), + .Func => try self.funcaddrs.append(self.alloc, import_handle), + .Mem => try self.memaddrs.append(self.alloc, import_handle), + .Table => try self.tableaddrs.append(self.alloc, import_handle), + .Global => try self.globaladdrs.append(self.alloc, import_handle), } } } @@ -208,7 +210,7 @@ pub const Instance = struct { }); // Need to do this regardless of if import or internal - try self.funcaddrs.append(handle); + try self.funcaddrs.append(self.alloc, handle); } } } @@ -226,7 +228,7 @@ pub const Instance = struct { .mutability = global_def.mutability, .valtype = global_def.valtype, }); - try self.globaladdrs.append(handle); + try self.globaladdrs.append(self.alloc, handle); } } } @@ -239,7 +241,7 @@ pub const Instance = struct { try memtype.limits.checkMatch(imported_mem.size(), imported_mem.max); } else { const handle = try self.store.addMemory(memtype.limits.min, memtype.limits.max); - try self.memaddrs.append(handle); + try self.memaddrs.append(self.alloc, handle); } } } @@ -252,7 +254,7 @@ pub const Instance = struct { try tabletype.limits.checkMatch(imported_table.min, imported_table.max); } else { const handle = try self.store.addTable(tabletype.reftype, tabletype.limits.min, tabletype.limits.max); - try self.tableaddrs.append(handle); + try self.tableaddrs.append(self.alloc, handle); } } } @@ -260,7 +262,7 @@ pub const Instance = struct { fn instantiateData(self: *Instance) !void { for (self.module.datas.list.items) |datatype| { const dataddr = try self.store.addData(datatype.count); - try self.dataaddrs.append(dataddr); + try self.dataaddrs.append(self.alloc, dataddr); var data = try self.store.data(dataddr); // TODO: Do we actually need to copy the data or just close over module bytes? @@ -285,7 +287,7 @@ pub const Instance = struct { fn instantiateElements(self: *Instance) !void { for (self.module.elements.list.items) |elemtype| { const elemaddr = try self.store.addElem(elemtype.reftype, elemtype.count); - try self.elemaddrs.append(elemaddr); + try self.elemaddrs.append(self.alloc, elemaddr); var elem = try self.store.elem(elemaddr); for (self.module.element_init_offsets.items[elemtype.init .. elemtype.init + elemtype.count], 0..) |expr, j| { diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 5105dd3d..bca164c6 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -52,9 +52,9 @@ pub const VirtualMachine = struct { // These fields match the types in Instance but are // instead pointers. These will point to the Instance // that initialises the VirtualMachine - wasi_preopens: *std.AutoHashMap(wasi.fd_t, WasiPreopen), + wasi_preopens: *std.AutoHashMapUnmanaged(wasi.fd_t, WasiPreopen), wasi_args: *std.ArrayList([:0]u8), - wasi_env: *std.StringHashMap([]const u8), + wasi_env: *std.StringHashMapUnmanaged([]const u8), pub const Frame = struct { locals: []u64 = undefined, // TODO: we're in trouble if we move our stacks in memory diff --git a/src/module.zig b/src/module.zig index d8719d04..f8bc5adf 100644 --- a/src/module.zig +++ b/src/module.zig @@ -41,43 +41,43 @@ pub const Module = struct { return Module{ .alloc = alloc, .wasm_bin = wasm_bin, - .customs = Section(Custom).empty, - .types = Section(FuncType).empty, - .imports = Section(Import).empty, - .functions = Section(Function).empty, - .tables = Section(TableType).empty, - .memories = Section(MemType).empty, - .globals = Section(GlobalType).empty, - .exports = Section(Export).empty, - .elements = Section(ElementSegment).empty, - .codes = Section(Code).empty, - .datas = Section(DataSegment).empty, - .element_init_offsets = ArrayList(usize).empty, - .parsed_code = ArrayList(Rr).empty, - .local_types = ArrayList(LocalType).empty, - .br_table_indices = ArrayList(u32).empty, - .references = ArrayList(u32).empty, + .customs = .empty, + .types = .empty, + .imports = .empty, + .functions = .empty, + .tables = .empty, + .memories = .empty, + .globals = .empty, + .exports = .empty, + .elements = .empty, + .codes = .empty, + .datas = .empty, + .element_init_offsets = .empty, + .parsed_code = .empty, + .local_types = .empty, + .br_table_indices = .empty, + .references = .empty, }; } pub fn deinit(self: *Module) void { - defer self.customs.deinit(); - defer self.types.deinit(); - defer self.imports.deinit(); - defer self.functions.deinit(); - defer self.tables.deinit(); - defer self.memories.deinit(); - defer self.globals.deinit(); - defer self.exports.deinit(); - defer self.elements.deinit(); - defer self.codes.deinit(); - defer self.datas.deinit(); - - defer self.element_init_offsets.deinit(); - defer self.parsed_code.deinit(); - defer self.local_types.deinit(); - defer self.br_table_indices.deinit(); - defer self.references.deinit(); + defer self.customs.deinit(self.alloc); + defer self.types.deinit(self.alloc); + defer self.imports.deinit(self.alloc); + defer self.functions.deinit(self.alloc); + defer self.tables.deinit(self.alloc); + defer self.memories.deinit(self.alloc); + defer self.globals.deinit(self.alloc); + defer self.exports.deinit(self.alloc); + defer self.elements.deinit(self.alloc); + defer self.codes.deinit(self.alloc); + defer self.datas.deinit(self.alloc); + + defer self.element_init_offsets.deinit(self.alloc); + defer self.parsed_code.deinit(self.alloc); + defer self.local_types.deinit(self.alloc); + defer self.br_table_indices.deinit(self.alloc); + defer self.references.deinit(self.alloc); } pub fn decode(self: *Module) !void { @@ -254,7 +254,7 @@ pub const Decoder = struct { .Global => try self.decodeGlobal(module, import_index), }; - try module.imports.list.append(Import{ + try module.imports.list.append(module.alloc, Import{ .module = module_name, .name = name, .desc_tag = tag, @@ -382,7 +382,7 @@ pub const Decoder = struct { if (parsed_code == null and import == null) return error.ExpectedOneOrTheOther; if (parsed_code != null and import != null) return error.ExpectedOneOrTheOther; - try module.globals.list.append(GlobalType{ + try module.globals.list.append(module.alloc, GlobalType{ .valtype = global_type, .mutability = mutability, .start = if (parsed_code) |pc| pc.start else null, @@ -411,14 +411,14 @@ pub const Decoder = struct { switch (tag) { .Func => { if (index >= module.functions.list.items.len) return error.ValidatorExportUnknownFunction; - try module.references.append(index); + try module.references.append(module.alloc, index); }, .Table => if (index >= module.tables.list.items.len) return error.ValidatorExportUnknownTable, .Mem => if (index >= module.memories.list.items.len) return error.ValidatorExportUnknownMemory, .Global => if (index >= module.globals.list.items.len) return error.ValidatorExportUnknownGlobal, } - try module.exports.list.append(Export{ + try module.exports.list.append(module.alloc, Export{ .name = name, .tag = tag, .index = index, @@ -463,15 +463,15 @@ pub const Decoder = struct { if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; - try module.references.append(funcidx); + try module.references.append(module.alloc, funcidx); const init_offset = module.parsed_code.items.len; - try module.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try module.parsed_code.append(Rr.@"return"); - try module.element_init_offsets.append(init_offset); + try module.parsed_code.append(module.alloc, Rr{ .@"ref.func" = funcidx }); + try module.parsed_code.append(module.alloc, Rr.@"return"); + try module.element_init_offsets.append(module.alloc, init_offset); } - try module.elements.list.append(ElementSegment{ + try module.elements.list.append(module.alloc, ElementSegment{ .reftype = .FuncRef, .init = first_init_offset, .count = data_length, @@ -494,15 +494,15 @@ pub const Decoder = struct { if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; - try module.references.append(funcidx); + try module.references.append(module.alloc, funcidx); const init_offset = module.parsed_code.items.len; - try module.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try module.parsed_code.append(Rr.@"return"); - try module.element_init_offsets.append(init_offset); + try module.parsed_code.append(module.alloc, Rr{ .@"ref.func" = funcidx }); + try module.parsed_code.append(module.alloc, Rr.@"return"); + try module.element_init_offsets.append(module.alloc, init_offset); } - try module.elements.list.append(ElementSegment{ + try module.elements.list.append(module.alloc, ElementSegment{ .reftype = .FuncRef, .init = first_init_offset, .count = data_length, @@ -527,15 +527,15 @@ pub const Decoder = struct { if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; - try module.references.append(funcidx); + try module.references.append(module.alloc, funcidx); const init_offset = module.parsed_code.items.len; - try module.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try module.parsed_code.append(Rr.@"return"); - try module.element_init_offsets.append(init_offset); + try module.parsed_code.append(module.alloc, Rr{ .@"ref.func" = funcidx }); + try module.parsed_code.append(module.alloc, Rr.@"return"); + try module.element_init_offsets.append(module.alloc, init_offset); } - try module.elements.list.append(ElementSegment{ + try module.elements.list.append(module.alloc, ElementSegment{ .reftype = .FuncRef, .init = first_init_offset, .count = data_length, @@ -557,15 +557,15 @@ pub const Decoder = struct { if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; - try module.references.append(funcidx); + try module.references.append(module.alloc, funcidx); const init_offset = module.parsed_code.items.len; - try module.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try module.parsed_code.append(Rr.@"return"); - try module.element_init_offsets.append(init_offset); + try module.parsed_code.append(module.alloc, Rr{ .@"ref.func" = funcidx }); + try module.parsed_code.append(module.alloc, Rr.@"return"); + try module.element_init_offsets.append(module.alloc, init_offset); } - try module.elements.list.append(ElementSegment{ + try module.elements.list.append(module.alloc, ElementSegment{ .reftype = .FuncRef, .init = first_init_offset, .count = data_length, @@ -585,10 +585,10 @@ pub const Decoder = struct { var j: usize = 0; while (j < init_expression_count) : (j += 1) { const parsed_init_code = try self.readConstantExpression(module, .FuncRef); - try module.element_init_offsets.append(parsed_init_code.start); + try module.element_init_offsets.append(module.alloc, parsed_init_code.start); } - try module.elements.list.append(ElementSegment{ + try module.elements.list.append(module.alloc, ElementSegment{ .reftype = .FuncRef, .init = first_init_offset, .count = init_expression_count, @@ -608,10 +608,10 @@ pub const Decoder = struct { while (j < expr_count) : (j += 1) { const init_offset = module.parsed_code.items.len; _ = try self.readConstantExpression(module, .FuncRef); - try module.element_init_offsets.append(init_offset); + try module.element_init_offsets.append(module.alloc, init_offset); } - try module.elements.list.append(ElementSegment{ + try module.elements.list.append(module.alloc, ElementSegment{ .reftype = reftype, .init = first_init_offset, .count = expr_count, @@ -627,10 +627,10 @@ pub const Decoder = struct { var j: usize = 0; while (j < expr_count) : (j += 1) { const parsed_init_code = try self.readConstantExpression(module, .FuncRef); - try module.element_init_offsets.append(parsed_init_code.start); + try module.element_init_offsets.append(module.alloc, parsed_init_code.start); } - try module.elements.list.append(ElementSegment{ + try module.elements.list.append(module.alloc, ElementSegment{ .reftype = reftype, .init = first_init_offset, .count = expr_count, @@ -653,7 +653,7 @@ pub const Decoder = struct { const count = try self.readLEB128(u32); module.codes.count = count; - try module.parsed_code.ensureTotalCapacity(count * 32); + try module.parsed_code.ensureTotalCapacity(module.alloc, count * 32); if (count == 0) return; @@ -676,7 +676,7 @@ pub const Decoder = struct { const local_type = try self.readEnum(ValType); locals_count += type_count; - try module.local_types.append(.{ .count = type_count, .valtype = local_type }); + try module.local_types.append(module.alloc, .{ .count = type_count, .valtype = local_type }); } if (locals_count >= 0x100000000) return error.TooManyLocals; @@ -685,7 +685,7 @@ pub const Decoder = struct { if (function_index_start + i >= module.functions.list.items.len) return error.FunctionCodeSectionsInconsistent; const parsed_code = try self.readFunction(module, locals, function_index_start + i); - try module.codes.list.append(Code{ + try module.codes.list.append(module.alloc, Code{ .locals_count = locals_count, .start = parsed_code.start, .required_stack_space = parsed_code.max_depth, @@ -717,7 +717,7 @@ pub const Decoder = struct { const data_length = try self.readLEB128(u32); const data = try self.readSlice(data_length); - try module.datas.list.append(DataSegment{ + try module.datas.list.append(module.alloc, DataSegment{ .count = data_length, .data = data, .mode = DataSegmentMode{ .Active = .{ @@ -730,7 +730,7 @@ pub const Decoder = struct { const data_length = try self.readLEB128(u32); const data = try self.readSlice(data_length); - try module.datas.list.append(DataSegment{ + try module.datas.list.append(module.alloc, DataSegment{ .count = data_length, .data = data, .mode = .Passive, @@ -746,7 +746,7 @@ pub const Decoder = struct { const data_length = try self.readLEB128(u32); const data = try self.readSlice(data_length); - try module.datas.list.append(DataSegment{ + try module.datas.list.append(module.alloc, DataSegment{ .count = data_length, .data = data, .mode = DataSegmentMode{ .Active = .{ @@ -835,8 +835,8 @@ fn Section(comptime T: type) type { .list = ArrayList(T).empty, }; - pub fn deinit(self: *Self) void { - self.list.deinit(); + pub fn deinit(self: *Self, alloc: mem.Allocator) void { + self.list.deinit(alloc); } pub fn itemsSlice(self: *Self) []T { diff --git a/src/module/parser.zig b/src/module/parser.zig index 9cde4c7e..6d957a67 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -61,7 +61,7 @@ pub const Parser = struct { try self.pushFunction(locals, funcidx); while (try self.next()) |instr| { - try self.module.parsed_code.append(instr); + try self.module.parsed_code.append(self.module.alloc, instr); } const bytes_read = self.bytesRead(); @@ -103,7 +103,7 @@ pub const Parser = struct { => {}, else => return error.ValidatorConstantExpressionRequired, } - try self.module.parsed_code.append(instr); + try self.module.parsed_code.append(self.module.alloc, instr); } const bytes_read = self.bytesRead(); @@ -350,7 +350,7 @@ pub const Parser = struct { var j: usize = 0; while (j < label_count) : (j += 1) { const tmp_label = try self.readLEB128Mem(u32); - try self.module.br_table_indices.append(tmp_label); + try self.module.br_table_indices.append(self.module.alloc, tmp_label); } const ln = try self.readLEB128Mem(u32); const l_star = self.module.br_table_indices.items[label_start .. label_start + j]; @@ -1028,7 +1028,7 @@ pub const Parser = struct { // Gather funcidx* from constant expressions if (self.is_constant) { - try self.module.references.append(funcidx); + try self.module.references.append(self.module.alloc, funcidx); } else { // For functions, check that the funcidx has already been referenced var in_references = false; @@ -1189,8 +1189,8 @@ pub const Parser = struct { var buf = std.io.fixedBufferStream(self.code); const readFn = switch (@typeInfo(T).int.signedness) { - .signed => std.leb.readILEB128, - .unsigned => std.leb.readULEB128, + .signed => std.leb.readIleb128, + .unsigned => std.leb.readUleb128, }; const value = try readFn(T, buf.reader()); diff --git a/src/module/validator.zig b/src/module/validator.zig index add2c75f..0962620e 100644 --- a/src/module/validator.zig +++ b/src/module/validator.zig @@ -11,6 +11,7 @@ const MiscOpcode = @import("../opcode.zig").MiscOpcode; const Module = @import("../module.zig").Module; pub const Validator = struct { + alloc: std.mem.Allocator, op_stack: OperandStack = undefined, ctrl_stack: ControlStack = undefined, max_depth: usize = 0, @@ -18,16 +19,17 @@ pub const Validator = struct { pub fn init(alloc: mem.Allocator, is_constant: bool) Validator { return Validator{ - .op_stack = OperandStack.init(alloc), - .ctrl_stack = ControlStack.init(alloc), + .alloc = alloc, + .op_stack = OperandStack.empty, + .ctrl_stack = ControlStack.empty, .is_constant = is_constant, }; } pub fn deinit(self: *Validator) void { // Static allocation? - self.op_stack.deinit(); - self.ctrl_stack.deinit(); + self.op_stack.deinit(self.alloc); + self.ctrl_stack.deinit(self.alloc); } pub fn validateBlock(v: *Validator, in_operands: []const ValType, out_operands: []const ValType) !void { @@ -550,7 +552,7 @@ pub const Validator = struct { pub fn pushOperand(v: *Validator, t: Type) !void { defer v.trackMaxDepth(); - try v.op_stack.append(t); + try v.op_stack.append(v.alloc, t); } fn popOperand(v: *Validator) !Type { @@ -600,7 +602,7 @@ pub const Validator = struct { .height = v.op_stack.items.len, .unreachable_flag = false, }; - try v.ctrl_stack.append(frame); + try v.ctrl_stack.append(v.alloc, frame); try v.pushOperands(in); } diff --git a/src/store.zig b/src/store.zig index 64a169a7..9d05bb0b 100644 --- a/src/store.zig +++ b/src/store.zig @@ -44,26 +44,26 @@ pub const ArrayListStore = struct { pub fn init(alloc: mem.Allocator) ArrayListStore { const store = ArrayListStore{ .alloc = alloc, - .functions = ArrayList(Function).empty, - .memories = ArrayList(Memory).empty, - .tables = ArrayList(Table).empty, - .globals = ArrayList(Global).empty, - .elems = ArrayList(Elem).empty, - .datas = ArrayList(Data).empty, - .imports = ArrayList(ImportExport).empty, + .functions = .empty, + .memories = .empty, + .tables = .empty, + .globals = .empty, + .elems = .empty, + .datas = .empty, + .imports = .empty, }; return store; } pub fn deinit(self: *ArrayListStore) void { - defer self.functions.deinit(); - defer self.memories.deinit(); - defer self.tables.deinit(); - defer self.globals.deinit(); - defer self.elems.deinit(); - defer self.datas.deinit(); - defer self.imports.deinit(); + defer self.functions.deinit(self.alloc); + defer self.memories.deinit(self.alloc); + defer self.tables.deinit(self.alloc); + defer self.globals.deinit(self.alloc); + defer self.elems.deinit(self.alloc); + defer self.datas.deinit(self.alloc); + defer self.imports.deinit(self.alloc); for (self.memories.items) |*m| { m.deinit(); @@ -114,7 +114,7 @@ pub const ArrayListStore = struct { } pub fn addFunction(self: *ArrayListStore, func: Function) !usize { - const fun_ptr = try self.functions.addOne(); + const fun_ptr = try self.functions.addOne(self.alloc); fun_ptr.* = func; return self.functions.items.len - 1; } @@ -128,7 +128,7 @@ pub const ArrayListStore = struct { /// Allocate a new Memory with min / max size and add to store. pub fn addMemory(self: *ArrayListStore, min: u32, max: ?u32) !usize { - const mem_ptr = try self.memories.addOne(); + const mem_ptr = try self.memories.addOne(self.alloc); mem_ptr.* = Memory.init(self.alloc, min, max); _ = try mem_ptr.grow(min); return self.memories.items.len - 1; @@ -142,7 +142,7 @@ pub const ArrayListStore = struct { } pub fn addTable(self: *ArrayListStore, reftype: RefType, entries: u32, max: ?u32) !usize { - const tbl_ptr = try self.tables.addOne(); + const tbl_ptr = try self.tables.addOne(self.alloc); tbl_ptr.* = try Table.init(self.alloc, reftype, entries, max); return self.tables.items.len - 1; } @@ -156,7 +156,7 @@ pub const ArrayListStore = struct { /// Add a Global to the store and return its globaladdr pub fn addGlobal(self: *ArrayListStore, value: Global) !usize { - const glbl_ptr = try self.globals.addOne(); + const glbl_ptr = try self.globals.addOne(self.alloc); glbl_ptr.* = value; return self.globals.items.len - 1; @@ -170,7 +170,7 @@ pub const ArrayListStore = struct { } pub fn addElem(self: *ArrayListStore, reftype: RefType, count: u32) !usize { - const elem_ptr = try self.elems.addOne(); + const elem_ptr = try self.elems.addOne(self.alloc); elem_ptr.* = try Elem.init(self.alloc, reftype, count); return self.elems.items.len - 1; } @@ -183,7 +183,7 @@ pub const ArrayListStore = struct { } pub fn addData(self: *ArrayListStore, count: u32) !usize { - const data_ptr = try self.datas.addOne(); + const data_ptr = try self.datas.addOne(self.alloc); data_ptr.* = try Data.init(self.alloc, count); return self.datas.items.len - 1; } diff --git a/src/store/memory.zig b/src/store/memory.zig index 4750b426..a186503c 100644 --- a/src/store/memory.zig +++ b/src/store/memory.zig @@ -14,14 +14,14 @@ pub const Memory = struct { pub fn init(alloc: mem.Allocator, min: u32, max: ?u32) Memory { return Memory{ .alloc = alloc, - .data = ArrayList(u8).init(alloc), + .data = .empty, .min = min, .max = max, }; } pub fn deinit(self: *Memory) void { - self.data.deinit(); + self.data.deinit(self.alloc); } // Return the size of the memory (in pages) @@ -41,7 +41,7 @@ pub const Memory = struct { const old_size_in_bytes = self.data.items.len; const old_size_in_pages = self.size(); - _ = try self.data.resize(self.data.items.len + PAGE_SIZE * num_pages); + _ = try self.data.resize(self.alloc, self.data.items.len + PAGE_SIZE * num_pages); // Zero memory. FIXME: I don't think this is required (maybe do this only in debug build) @memset(self.data.items[old_size_in_bytes .. old_size_in_bytes + PAGE_SIZE * num_pages], 0); diff --git a/src/store/table.zig b/src/store/table.zig index 805f5c90..82fce941 100644 --- a/src/store/table.zig +++ b/src/store/table.zig @@ -12,8 +12,8 @@ pub const Table = struct { reftype: RefType, pub fn init(alloc: mem.Allocator, reftype: RefType, min: u32, max: ?u32) !Table { - var data = ArrayList(?usize).init(alloc); - try data.appendNTimes(null, min); + var data: ArrayList(?usize) = .empty; + try data.appendNTimes(alloc, null, min); return Table{ .alloc = alloc, @@ -25,7 +25,7 @@ pub const Table = struct { } pub fn deinit(self: *Table) void { - self.data.deinit(); + self.data.deinit(self.alloc); } pub fn lookup(self: *Table, index: u32) !usize { @@ -57,7 +57,7 @@ pub const Table = struct { const old_size = math.cast(u32, self.data.items.len) orelse return error.TableGrowToolarge; - try self.data.appendNTimes(null, n); + try self.data.appendNTimes(self.alloc, null, n); return old_size; } From 35fba559628182c1793a5c0f213265edd6c75787 Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Sat, 27 Sep 2025 13:16:05 +0200 Subject: [PATCH 03/11] upgrade ci --- .github/workflows/test.yaml | 20 ++++++++++---------- README.md | 2 +- build.zig.zon | 2 +- src/error.zig | 6 +----- src/module.zig | 2 +- src/module/parser.zig | 8 ++++---- src/store.zig | 2 +- tools/zware-gen.zig | 9 +++++---- tools/zware-run.zig | 26 ++++++++++++++++---------- 9 files changed, 40 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 30211fb8..151158df 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -14,9 +14,9 @@ jobs: runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v2 - - uses: mlugg/setup-zig@v1.2.1 + - uses: mlugg/setup-zig@v2.0.5 with: - version: 0.14.0 + version: 0.15.1 - run: zig build unittest testsuite: strategy: @@ -25,18 +25,18 @@ jobs: runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v2 - - uses: mlugg/setup-zig@v1.2.1 + - uses: mlugg/setup-zig@v2.0.5 with: - version: 0.14.0 + version: 0.15.1 - name: Run testsuite run: zig build testsuite lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: mlugg/setup-zig@v1.2.1 + - uses: mlugg/setup-zig@v2.0.5 with: - version: 0.14.0 + version: 0.15.1 - run: zig fmt --check src/*.zig fib: strategy: @@ -45,9 +45,9 @@ jobs: runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v2 - - uses: mlugg/setup-zig@v1.2.1 + - uses: mlugg/setup-zig@v2.0.5 with: - version: 0.14.0 + version: 0.15.1 - name: Build fib working-directory: ./examples/fib run: zig build @@ -58,8 +58,8 @@ jobs: runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v2 - - uses: mlugg/setup-zig@v1.2.1 + - uses: mlugg/setup-zig@v2.0.5 with: - version: 0.14.0 + version: 0.15.1 - name: Build zware-gen, zware-run and libzware.a run: zig build diff --git a/README.md b/README.md index f147c2a4..5491fe7a 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ pub fn main() !void { ### Compile-time -- Zig 0.12 (master) +- Zig 0.15.1 (master) ### Run-time diff --git a/build.zig.zon b/build.zig.zon index 9e5cd669..6ce79c19 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -2,7 +2,7 @@ .name = .zware, .version = "0.0.1", .fingerprint = 0xea6cb8e2e9e30e64, - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.15.1", .dependencies = .{ .wabt = .{ .url = "https://github.com/WebAssembly/wabt/archive/39f85a791cbbad91a253a851841a29777efdc2cd.tar.gz", diff --git a/src/error.zig b/src/error.zig index 628da38f..639ef5d7 100644 --- a/src/error.zig +++ b/src/error.zig @@ -27,12 +27,8 @@ pub const Error = union(enum) { } pub fn format( self: Error, - comptime fmt: []const u8, - options: std.fmt.FormatOptions, - writer: anytype, + writer: *std.Io.Writer, ) !void { - _ = fmt; - _ = options; switch (self) { .missing_import => |import| try writer.print( "missing {s} import '{s}' from module '{s}'", diff --git a/src/module.zig b/src/module.zig index f8bc5adf..fd91bb19 100644 --- a/src/module.zig +++ b/src/module.zig @@ -148,7 +148,7 @@ pub const Module = struct { }; pub const Decoder = struct { - fbs: std.io.FixedBufferStream([]const u8), + fbs: std.Io.FixedBufferStream([]const u8), pub fn decodeSection(self: *Decoder, module: *Module) !void { const id: SectionType = self.readEnum(SectionType) catch |err| switch (err) { diff --git a/src/module/parser.zig b/src/module/parser.zig index 6d957a67..5656330e 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -1186,7 +1186,7 @@ pub const Parser = struct { } pub fn readLEB128Mem(self: *Parser, comptime T: type) !T { - var buf = std.io.fixedBufferStream(self.code); + var buf = std.Io.fixedBufferStream(self.code); const readFn = switch (@typeInfo(T).int.signedness) { .signed => std.leb.readIleb128, @@ -1213,7 +1213,7 @@ pub const Parser = struct { } pub fn readU32(self: *Parser) !u32 { - var buf = std.io.fixedBufferStream(self.code); + var buf = std.Io.fixedBufferStream(self.code); const rd = buf.reader(); const value = try rd.readInt(u32, .little); @@ -1223,7 +1223,7 @@ pub const Parser = struct { } pub fn readU64(self: *Parser) !u64 { - var buf = std.io.fixedBufferStream(self.code); + var buf = std.Io.fixedBufferStream(self.code); const rd = buf.reader(); const value = try rd.readInt(u64, .little); @@ -1233,7 +1233,7 @@ pub const Parser = struct { } pub fn readByte(self: *Parser) !u8 { - var buf = std.io.fixedBufferStream(self.code); + var buf = std.Io.fixedBufferStream(self.code); const rd = buf.reader(); const value = try rd.readByte(); diff --git a/src/store.zig b/src/store.zig index 9d05bb0b..3b69c33e 100644 --- a/src/store.zig +++ b/src/store.zig @@ -96,7 +96,7 @@ pub const ArrayListStore = struct { } pub fn @"export"(self: *ArrayListStore, module: []const u8, name: []const u8, tag: Tag, handle: usize) !void { - try self.imports.append(ImportExport{ + try self.imports.append(self.alloc, ImportExport{ .import = Import{ .module = module, .name = name, diff --git a/tools/zware-gen.zig b/tools/zware-gen.zig index 1273bfd9..8fffb8b8 100644 --- a/tools/zware-gen.zig +++ b/tools/zware-gen.zig @@ -27,9 +27,10 @@ pub fn main() !void { defer module.deinit(); try module.decode(); - const stdout_file = std.io.getStdOut().writer(); - var bw = std.io.bufferedWriter(stdout_file); - const stdout = bw.writer(); + const stdout_fd = std.fs.File.stdout(); + var stdout_buf: [4096]u8 = undefined; + var stdout_writer = stdout_fd.writer(&stdout_buf); + const stdout = &stdout_writer.interface; try stdout.print("const std = @import(\"std\");\n", .{}); try stdout.print("const zware = @import(\"zware\");\n\n", .{}); @@ -222,7 +223,7 @@ pub fn main() !void { } try stdout.print("}};\n\n", .{}); - try bw.flush(); + try stdout.flush(); } fn zigType(v: zware.ValType) []const u8 { diff --git a/tools/zware-run.zig b/tools/zware-run.zig index 94310397..4fae1afb 100644 --- a/tools/zware-run.zig +++ b/tools/zware-run.zig @@ -35,8 +35,14 @@ fn main2() !void { const full_cmdline = try std.process.argsAlloc(global.alloc); defer std.process.argsFree(global.alloc, full_cmdline); + if (full_cmdline.len <= 1) { - try std.io.getStdErr().writer().writeAll("Usage: zware-run FILE.wasm FUNCTION\n"); + const stderr_fd = std.fs.File.stderr(); + var stderr_buf: [4096]u8 = undefined; + var stderr_writer = stderr_fd.writer(&stderr_buf); + const stderr = &stderr_writer.interface; + try stderr.writeAll("Usage: zware-run FILE.wasm FUNCTION\n"); + try stderr.flush(); std.process.exit(0xff); } @@ -81,7 +87,7 @@ fn main2() !void { var zware_error: zware.Error = undefined; instance.instantiateWithError(&zware_error) catch |err| switch (err) { error.SeeContext => { - std.log.err("failed to instantiate the module: {}", .{zware_error}); + std.log.err("failed to instantiate the module: {f}", .{zware_error}); std.process.exit(0xff); }, else => |e| return e, @@ -94,14 +100,17 @@ fn main2() !void { try instance.invoke(wasm_func_name, &in, out_args, .{}); std.log.info("{} output(s)", .{out_args.len}); for (out_args, 0..) |out_arg, out_index| { - std.log.info("output {} {}", .{ out_index, fmtValue(export_functype.results[out_index], out_arg) }); + std.log.info("output {} {f}", .{ out_index, fmtValue(export_functype.results[out_index], out_arg) }); } } fn getExportFunction(module: *const zware.Module, func_name: []const u8) !usize { return module.getExport(.Func, func_name) catch |err| switch (err) { error.ExportNotFound => { - const stderr = std.io.getStdErr().writer(); + const stderr_fd = std.fs.File.stderr(); + var stderr_buf: [4096]u8 = undefined; + var stderr_writer = stderr_fd.writer(&stderr_buf); + const stderr = &stderr_writer.interface; var export_func_count: usize = 0; for (module.exports.list.items) |exp| { if (exp.tag == .Func) { @@ -121,6 +130,7 @@ fn getExportFunction(module: *const zware.Module, func_name: []const u8) !usize } } } + try stderr.flush(); std.process.exit(0xff); }, }; @@ -176,10 +186,10 @@ fn onMissingImport(vm: *zware.VirtualMachine, context: usize) zware.WasmError!vo std.log.info("import function '{s}.{s}' called", .{ stub.module, stub.name }); for (stub.type.params, 0..) |param_type, i| { const value = vm.popAnyOperand(); - std.log.info(" param {} {}", .{ i, fmtValue(param_type, value) }); + std.log.info(" param {} {f}", .{ i, fmtValue(param_type, value) }); } for (stub.type.results, 0..) |result_type, i| { - std.log.info(" result {} {}", .{ i, fmtValue(result_type, 0) }); + std.log.info(" result {} {f}", .{ i, fmtValue(result_type, 0) }); try vm.pushOperand(u64, 0); } } @@ -216,12 +226,8 @@ const FmtValue = struct { value: u64, pub fn format( self: FmtValue, - comptime fmt: []const u8, - options: std.fmt.FormatOptions, writer: anytype, ) !void { - _ = fmt; - _ = options; switch (self.type) { inline else => |t2| try writer.print("({s}) {}", .{ @tagName(t2), cast(t2, self.value) }), } From 3cb920c028b502753a59c4b235cb948be7f1120f Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Sat, 27 Sep 2025 12:23:20 +0200 Subject: [PATCH 04/11] switch tail calls to auto to avoid error with zig x86 backend --- src/instance/vm.zig | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index bca164c6..c4eb289a 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const builtin = @import("builtin"); const os = std.os; const posix = std.posix; const mem = std.mem; @@ -125,7 +126,10 @@ pub const VirtualMachine = struct { inline fn dispatch(self: *VirtualMachine, next_ip: usize, code: []Rr) WasmError!void { const next_instr = code[next_ip]; - return try @call(.always_tail, lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }); + switch (builtin.zig_backend) { + .stage2_x86_64 => return @call(.auto, lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), + else => return @call(.always_tail, lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), + } } pub const REF_NULL: u64 = 0xFFFF_FFFF_FFFF_FFFF; @@ -2111,7 +2115,10 @@ pub const VirtualMachine = struct { inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, code: []Rr) WasmError!void { const next_instr = code[next_ip].misc; - return try @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }); + switch (builtin.zig_backend) { + .stage2_x86_64 => return @call(.auto, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), + else => return @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), + } } fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { From 26811b4ace2da008692a50c57890c947fe3471a0 Mon Sep 17 00:00:00 2001 From: Tobias Simetsreiter Date: Sun, 28 Sep 2025 10:50:03 +0200 Subject: [PATCH 05/11] upgrade fib example build.zig --- examples/fib/build.zig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/fib/build.zig b/examples/fib/build.zig index ba990bb0..db6061b8 100644 --- a/examples/fib/build.zig +++ b/examples/fib/build.zig @@ -6,9 +6,11 @@ pub fn build(b: *Build) void { const exe = b.addExecutable(.{ .name = "fib", - .root_source_file = b.path("src/fib.zig"), - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .root_source_file = b.path("src/fib.zig"), + .target = target, + .optimize = optimize, + }), }); exe.root_module.addAnonymousImport("zware", .{ .root_source_file = b.path("../../src/main.zig"), From 189017dfccc6b6d13550aebadfd54a1d4a0badff Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 28 Sep 2025 13:25:54 +0100 Subject: [PATCH 06/11] Reduce integer size for line number when parsing .wast files The testsuite was failing with: ``` zig-aarch64-macos-0.15.1/lib/std/json/static.zig:572:44: error: type 'f64' cannot represent integer value '18446744073709551615' if (f > std.math.maxInt(T)) return error.Overflow; ``` Interestingly in an example .wast (e.g. test-token's token.wast) the line numbers are 4 and 8: ``` {"source_filename": "/Users/malcolm/.cache/zig/p/N-V-__8AAKtbtgBFkB_BMIKSUqC-temKvHmuqBSvjBlf4hD6/token.wast", "commands": [ {"type": "assert_malformed", "line": 4, "filename": "token.0.wat", "text": "unknown operator", "module_type": "text"}, {"type": "assert_malformed", "line": 8, "filename": "token.1.wat", "text": "unknown operator", "module_type": "text"}]} ``` which is hinting at maybe the json parser code running on uninitialised data? Not sure. Anyway, usize is way larger than we need anyway so dropping down to u32 (say) is totally fine. --- test/testrunner/src/testrunner.zig | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/testrunner/src/testrunner.zig b/test/testrunner/src/testrunner.zig index f8db3f19..8a1fa782 100644 --- a/test/testrunner/src/testrunner.zig +++ b/test/testrunner/src/testrunner.zig @@ -819,21 +819,21 @@ const Command = union(enum) { const CommandModule = struct { // type: "module" - line: usize, + line: u32, name: ?[]const u8 = null, filename: []const u8, }; const CommandAssertReturn = struct { // type: "assert_return" - line: usize, + line: u32, action: Action, expected: []const Value, }; const CommandAssertTrap = struct { // type: "assert_trap" - line: usize, + line: u32, action: Action, text: []const u8, expected: []const ValueTrap, @@ -841,7 +841,7 @@ const CommandAssertTrap = struct { const CommandAssertMalformed = struct { // type: "assert_malformed" - line: usize, + line: u32, filename: []const u8, text: []const u8, module_type: []const u8, @@ -849,7 +849,7 @@ const CommandAssertMalformed = struct { const CommandAssertInvalid = struct { // type: "assert_invalid" - line: usize, + line: u32, filename: []const u8, text: []const u8, module_type: []const u8, @@ -857,7 +857,7 @@ const CommandAssertInvalid = struct { const CommandAssertExhaustion = struct { // type: "assert_exhaustion" - line: usize, + line: u32, action: Action, text: []const u8, expected: []const ValueTrap, @@ -865,7 +865,7 @@ const CommandAssertExhaustion = struct { const CommandAssertUnlinkable = struct { // type: "assert_unlinkable" - line: usize, + line: u32, filename: []const u8, text: []const u8, module_type: []const u8, @@ -873,7 +873,7 @@ const CommandAssertUnlinkable = struct { const CommandAssertUninstantiable = struct { // type: "assert_uninstantiable" - line: usize, + line: u32, filename: []const u8, text: []const u8, module_type: []const u8, @@ -881,14 +881,14 @@ const CommandAssertUninstantiable = struct { const CommandAction = struct { // type: "action" - line: usize, + line: u32, action: Action, expected: []const ValueTrap, }; const CommandRegister = struct { // type: "register" - line: usize, + line: u32, name: ?[]const u8 = null, as: []const u8, }; From 496e535377d3003d8fb399a8c4116b55f465476d Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 28 Sep 2025 16:20:09 +0100 Subject: [PATCH 07/11] Use llvm backend for testrunner debug builds --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index e1c8e46e..974992df 100644 --- a/build.zig +++ b/build.zig @@ -38,6 +38,7 @@ pub fn build(b: *Build) !void { .target = target, .optimize = optimize, }), + .use_llvm = true, }); testrunner.root_module.addImport("zware", zware_module); From 653ad089b0bcb2a7496d0ceb4d5dd5a73212be45 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 6 Oct 2025 10:16:07 -0400 Subject: [PATCH 08/11] compileError on .stage2_x86_64 backend --- build.zig | 1 + src/instance/vm.zig | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/build.zig b/build.zig index 974992df..5c4e333d 100644 --- a/build.zig +++ b/build.zig @@ -71,6 +71,7 @@ pub fn build(b: *Build) !void { .target = target, .optimize = optimize, }), + .use_llvm = true, }); exe.root_module.addImport("zware", zware_module); const install = b.addInstallArtifact(exe, .{}); diff --git a/src/instance/vm.zig b/src/instance/vm.zig index c4eb289a..4286d544 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -126,10 +126,11 @@ pub const VirtualMachine = struct { inline fn dispatch(self: *VirtualMachine, next_ip: usize, code: []Rr) WasmError!void { const next_instr = code[next_ip]; - switch (builtin.zig_backend) { - .stage2_x86_64 => return @call(.auto, lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), - else => return @call(.always_tail, lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), + if (builtin.zig_backend == .stage2_x86_64) { + @compileError("zware currently requires the LLVM backend for `.always_tail`. See https://github.com/ziglang/zig/issues/24044"); } + + return @call(.always_tail, lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }); } pub const REF_NULL: u64 = 0xFFFF_FFFF_FFFF_FFFF; @@ -2115,10 +2116,11 @@ pub const VirtualMachine = struct { inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, code: []Rr) WasmError!void { const next_instr = code[next_ip].misc; - switch (builtin.zig_backend) { - .stage2_x86_64 => return @call(.auto, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), - else => return @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }), + if (builtin.zig_backend == .stage2_x86_64) { + @compileError("zware currently requires the LLVM backend for `.always_tail`. See https://github.com/ziglang/zig/issues/24044"); } + + return @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }); } fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { From 069cc3ca41da3c6df51edd32cd49935a1af8c4ea Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 6 Oct 2025 13:39:03 -0400 Subject: [PATCH 09/11] remove explicit zig version from CI workflow --- .github/workflows/test.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 151158df..d978ec36 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -15,8 +15,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: mlugg/setup-zig@v2.0.5 - with: - version: 0.15.1 - run: zig build unittest testsuite: strategy: @@ -26,8 +24,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: mlugg/setup-zig@v2.0.5 - with: - version: 0.15.1 - name: Run testsuite run: zig build testsuite lint: @@ -35,8 +31,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: mlugg/setup-zig@v2.0.5 - with: - version: 0.15.1 - run: zig fmt --check src/*.zig fib: strategy: @@ -46,8 +40,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: mlugg/setup-zig@v2.0.5 - with: - version: 0.15.1 - name: Build fib working-directory: ./examples/fib run: zig build @@ -59,7 +51,5 @@ jobs: steps: - uses: actions/checkout@v2 - uses: mlugg/setup-zig@v2.0.5 - with: - version: 0.15.1 - name: Build zware-gen, zware-run and libzware.a run: zig build From 089da5915be2162cd0966ec87bd92d1c58a3ea97 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 6 Oct 2025 13:41:06 -0400 Subject: [PATCH 10/11] fib uses llvm --- examples/fib/build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/fib/build.zig b/examples/fib/build.zig index db6061b8..d5145bd9 100644 --- a/examples/fib/build.zig +++ b/examples/fib/build.zig @@ -11,6 +11,7 @@ pub fn build(b: *Build) void { .target = target, .optimize = optimize, }), + .use_llvm = true, }); exe.root_module.addAnonymousImport("zware", .{ .root_source_file = b.path("../../src/main.zig"), From 8b499f75460a56893d9512e3831a1a59e1185e25 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 6 Oct 2025 13:43:34 -0400 Subject: [PATCH 11/11] unittest uses llvm --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index 5c4e333d..8d58a9f5 100644 --- a/build.zig +++ b/build.zig @@ -23,6 +23,7 @@ pub fn build(b: *Build) !void { const main_tests = b.addTest(.{ .root_module = main_mod, + .use_llvm = true, }); const run_main_tests = b.addRunArtifact(main_tests);