fixed leb128 integer decoding

This commit is contained in:
Lorenzo Torres 2025-03-23 22:40:03 +01:00
parent 1d720c790d
commit 7660bc09bc
3 changed files with 305 additions and 281 deletions

View file

@ -22,7 +22,6 @@ const Index = packed union {
di: DIndex, di: DIndex,
}; };
opcodes: []Opcode, opcodes: []Opcode,
/// Indices means something different depending on the Opcode. /// Indices means something different depending on the Opcode.
/// Read the docs of each opcode to know what the index means. /// Read the docs of each opcode to know what the index means.
@ -274,6 +273,4 @@ pub const Opcode = enum(u8) {
// VECTOR INSTRUCTIONS // VECTOR INSTRUCTIONS
/// TODO: vector instructions. Value in wasm: 0xFC. Note: there are opcodes available lol /// TODO: vector instructions. Value in wasm: 0xFC. Note: there are opcodes available lol
vecinst = 0xF3, vecinst = 0xF3,
}; };

View file

@ -39,39 +39,49 @@ pub fn leb128Result(T: type) type {
} }
pub fn leb128Decode_stream(comptime T: type, stream: anytype) !leb128Result(T) { pub fn leb128Decode_stream(comptime T: type, stream: anytype) !leb128Result(T) {
switch (@typeInfo(T)) { //switch (@typeInfo(T)) {
.int => {}, // .int => {},
else => @compileError("LEB128 integer decoding only support integers, but got " ++ @typeName(T)), // else => @compileError("LEB128 integer decoding only support integers, but got " ++ @typeName(T)),
} //}
if (@typeInfo(T).int.bits != 32 and @typeInfo(T).int.bits != 64) {
@compileError("LEB128 integer decoding only supports 32 or 64 bits integers but got " ++ std.fmt.comptimePrint("{d} bits", .{@typeInfo(T).int.bits}));
}
var result: T = 0; //if (@typeInfo(T).int.bits != 32 and @typeInfo(T).int.bits != 64) {
// TODO: is the type of shift important. Reading Wikipedia (not very much tho) it seems like we can use u32 and call it a day... // @compileError("LEB128 integer decoding only supports 32 or 64 bits integers but got " ++ std.fmt.comptimePrint("{d} bits", .{@typeInfo(T).int.bits}));
var shift: if (@typeInfo(T).int.bits == 32) u5 else u6 = 0; //}
var byte: u8 = undefined;
var len: usize = 0;
while (stream.readByte()) |b| {
len += 1;
result |= @as(T, @intCast((b & 0x7f))) << shift;
if ((b & (0x1 << 7)) == 0) {
byte = b;
break;
}
shift += 7;
} else |err| {
return err;
}
if (@typeInfo(T).int.signedness == .signed) { //var result: T = 0;
const size = @sizeOf(T) * 8; //// TODO: is the type of shift important. Reading Wikipedia (not very much tho) it seems like we can use u32 and call it a day...
if (shift < size and (byte & 0x40) != 0) { //var shift: if (@typeInfo(T).int.bits == 32) u5 else u6 = 0;
result |= (~@as(T, 0) << shift); //var byte: u8 = undefined;
} //var len: usize = 0;
} //while (stream.readByte()) |b| {
// len += 1;
// result |= @as(T, @intCast((b & 0x7f))) << shift;
// if ((b & (0x1 << 7)) == 0) {
// byte = b;
// break;
// }
// shift += 7;
//} else |err| {
// return err;
//}
return .{ .len = len, .val = result }; //if (@typeInfo(T).int.signedness == .signed) {
// const size = @sizeOf(T) * 8;
// if (shift < size and (byte & 0x40) != 0) {
// result |= (~@as(T, 0) << shift);
// }
//}
//return .{ .len = len, .val = result };
const start = try stream.context.getPos();
const value = try switch (@typeInfo(T).int.signedness) {
.signed => std.leb.readIleb128(T, stream),
else => std.leb.readUleb128(T, stream),
};
const end = try stream.context.getPos();
return .{ .len = end - start, .val = value };
} }
fn leb128Decode(comptime T: type, bytes: []const u8) leb128Result(T) { fn leb128Decode(comptime T: type, bytes: []const u8) leb128Result(T) {
@ -275,10 +285,14 @@ pub const Runtime = struct {
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 != self.stack.pop().?.i32))) }); try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 != self.stack.pop().?.i32))) });
}, },
0x48 => { 0x48 => {
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 < self.stack.pop().?.i32))) }); const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32;
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(b < a))) });
}, },
0x49 => { 0x49 => {
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u32, @bitCast(self.stack.pop().?.i32)) < @as(u32, @bitCast(self.stack.pop().?.i32))))) }); const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32;
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(b < a))) });
}, },
0x4a => { 0x4a => {
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 > self.stack.pop().?.i32))) }); try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 > self.stack.pop().?.i32))) });

View file

@ -1,3 +1,16 @@
const std = @import("std"); const std = @import("std");
const mesh = @import("mesh.zig"); const mesh = @import("mesh.zig");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
pub const Model = packed struct {
const Chunk = packed struct {
length: u32,
ty: u32,
},
header: packed struct {
magic: u32,
version: u32,
length: u32,
},
};