diff --git a/src/common.zig b/src/common.zig index a263bfd0..d3b74050 100644 --- a/src/common.zig +++ b/src/common.zig @@ -33,11 +33,27 @@ pub const Mutability = enum(u8) { Mutable, }; +pub const NumType = enum(u8) { + I32 = 0x7F, + I64 = 0x7E, + F32 = 0x7D, + F64 = 0x7C, + V128 = 0x7B, +}; + +pub const RefType = enum(u8) { + FuncRef = 0x70, + ExternRef = 0x6F, +}; + pub const ValueType = enum(u8) { I32 = 0x7F, I64 = 0x7E, F32 = 0x7D, F64 = 0x7C, + V128 = 0x7B, + FuncRef = 0x70, + ExternRef = 0x6F, }; pub fn valueTypeFromBlockType(block_type: i32) !ValueType { diff --git a/src/instruction.zig b/src/instruction.zig index 77981e72..9044057a 100644 --- a/src/instruction.zig +++ b/src/instruction.zig @@ -494,6 +494,9 @@ const I32_OUT = [1]ValueType{.I32} ** 1; const I64_OUT = [1]ValueType{.I64} ** 1; const F32_OUT = [1]ValueType{.F32} ** 1; const F64_OUT = [1]ValueType{.F64} ** 1; +const V128_OUT = [1]ValueType{.V128} ** 1; +const FUNCREF_OUT = [1]ValueType{.FuncRef} ** 1; +const EXTERNREF_OUT = [1]ValueType{.ExternRef} ** 1; pub const ParseIterator = struct { function: []const u8, @@ -592,6 +595,9 @@ pub const ParseIterator = struct { .I64 => try self.validator.validateBlock(EMPTY[0..], I64_OUT[0..]), .F32 => try self.validator.validateBlock(EMPTY[0..], F32_OUT[0..]), .F64 => try self.validator.validateBlock(EMPTY[0..], F64_OUT[0..]), + .V128 => try self.validator.validateBlock(EMPTY[0..], V128_OUT[0..]), + .FuncRef => try self.validator.validateBlock(EMPTY[0..], FUNCREF_OUT[0..]), + .ExternRef => try self.validator.validateBlock(EMPTY[0..], EXTERNREF_OUT[0..]), } } } @@ -625,6 +631,9 @@ pub const ParseIterator = struct { .I64 => try self.validator.validateLoop(EMPTY[0..], I64_OUT[0..]), .F32 => try self.validator.validateLoop(EMPTY[0..], F32_OUT[0..]), .F64 => try self.validator.validateLoop(EMPTY[0..], F64_OUT[0..]), + .V128 => try self.validator.validateBlock(EMPTY[0..], V128_OUT[0..]), + .FuncRef => try self.validator.validateBlock(EMPTY[0..], FUNCREF_OUT[0..]), + .ExternRef => try self.validator.validateBlock(EMPTY[0..], EXTERNREF_OUT[0..]), } } } @@ -663,6 +672,9 @@ pub const ParseIterator = struct { .I64 => try self.validator.validateIf(EMPTY[0..], I64_OUT[0..]), .F32 => try self.validator.validateIf(EMPTY[0..], F32_OUT[0..]), .F64 => try self.validator.validateIf(EMPTY[0..], F64_OUT[0..]), + .V128 => try self.validator.validateBlock(EMPTY[0..], V128_OUT[0..]), + .FuncRef => try self.validator.validateBlock(EMPTY[0..], FUNCREF_OUT[0..]), + .ExternRef => try self.validator.validateBlock(EMPTY[0..], EXTERNREF_OUT[0..]), } } } diff --git a/src/module.zig b/src/module.zig index 0e9b4bb1..b2baf44d 100644 --- a/src/module.zig +++ b/src/module.zig @@ -13,6 +13,8 @@ const Opcode = @import("opcode.zig").Opcode; const ParseIterator = instruction.ParseIterator; const OpcodeIterator = instruction.OpcodeIterator; const FuncType = common.FuncType; +const NumType = common.NumType; +const RefType = common.ValueType; const ValueType = common.ValueType; const Import = common.Import; const Export = common.Export; @@ -608,49 +610,56 @@ pub const Module = struct { var i: usize = 0; while (i < count) : (i += 1) { - const table_index = leb.readULEB128(u32, rd) catch |err| switch (err) { + const elem_type = leb.readULEB128(u32, rd) catch |err| switch (err) { error.EndOfStream => return error.UnexpectedEndOfInput, else => return err, }; - if (table_index >= self.tables.list.items.len) return error.ValidatorElemUnknownTable; + switch (elem_type) { + 0 => { + const table_index = 0; - const expr_start = rd.context.pos; - const expr = self.module[expr_start..]; - const meta = try opcode.findExprEnd(expr); + if (table_index >= self.tables.list.items.len) return error.ValidatorElemUnknownTable; - rd.skipBytes(meta.offset + 1, .{}) catch |err| switch (err) { - error.EndOfStream => return error.UnexpectedEndOfInput, - else => return err, - }; + const expr_start = rd.context.pos; + const expr = self.module[expr_start..]; + const meta = try opcode.findExprEnd(expr); - // Number of u32's in our data (not the length in bytes!) - const data_length = leb.readULEB128(u32, rd) catch |err| switch (err) { - error.EndOfStream => return error.UnexpectedEndOfInput, - else => return err, - }; - const data_start = rd.context.pos; - - var j: usize = 0; - while (j < data_length) : (j += 1) { - // When we pre-process all this data we can just store this - // but for the moment we're just using it to skip over - const func_index = leb.readULEB128(u32, rd) catch |err| switch (err) { - error.EndOfStream => return error.UnexpectedEndOfInput, - else => return err, - }; + rd.skipBytes(meta.offset + 1, .{}) catch |err| switch (err) { + error.EndOfStream => return error.UnexpectedEndOfInput, + else => return err, + }; - if (func_index >= self.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; + // Number of u32's in our data (not the length in bytes!) + const data_length = leb.readULEB128(u32, rd) catch |err| switch (err) { + error.EndOfStream => return error.UnexpectedEndOfInput, + else => return err, + }; + const data_start = rd.context.pos; + + var j: usize = 0; + while (j < data_length) : (j += 1) { + // When we pre-process all this data we can just store this + // but for the moment we're just using it to skip over + const func_index = leb.readULEB128(u32, rd) catch |err| switch (err) { + error.EndOfStream => return error.UnexpectedEndOfInput, + else => return err, + }; + + if (func_index >= self.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; + } + + const parsed_code = try self.parseConstantCode(self.module[expr_start .. expr_start + meta.offset + 1], .I32); + + try self.elements.list.append(Segment{ + .index = table_index, + .start = parsed_code.start, + .count = data_length, + .data = self.module[data_start..rd.context.pos], + }); + }, + else => return error.ValidatorElemTypeNotImplemented, } - - const parsed_code = try self.parseConstantCode(self.module[expr_start .. expr_start + meta.offset + 1], .I32); - - try self.elements.list.append(Segment{ - .index = table_index, - .start = parsed_code.start, - .count = data_length, - .data = self.module[data_start..rd.context.pos], - }); } } diff --git a/test/src/testrunner.zig b/test/src/testrunner.zig index 3b55b548..ded6cf0d 100644 --- a/test/src/testrunner.zig +++ b/test/src/testrunner.zig @@ -537,6 +537,7 @@ pub fn main() anyerror!void { error.ValidatorCallIndirectNoTable => continue, error.ValidatorCallIndirectInvalidTypeIndex => continue, error.ValidatorElemUnknownTable => continue, + // error.ValidatorElemTypeNotImplemented => continue, error.ValidatorTableMinGreaterThanMax => continue, error.ValidatorExportUnknownFunction => continue, error.ValidatorExportUnknownTable => continue,