[MODS/WASM] Add some more instructions

This commit is contained in:
luccie-cmd 2025-08-06 11:40:32 +02:00
parent a295365993
commit 98cbb47031
3 changed files with 43 additions and 20 deletions

View file

@ -25,6 +25,7 @@ const PAGE_SIZE = 65536;
pub const Error = error{
OutOfMemory,
DivideBy0,
Overflow,
invalid_instruction,
invalid_magic,

View file

@ -105,7 +105,7 @@ pub const Runtime = struct {
std.log.warn("Growing memory is not yet supported, usign the minimum memory\n", .{});
}
const memory = try allocator.alloc(u8, max);
std.crypto.secureZero(u8, memory);
@memset(memory, 0);
@memcpy(memory[0..module.data.len], module.data);
return Runtime{
.module = module,
@ -124,6 +124,7 @@ pub const Runtime = struct {
loop: while (frame.program_counter < frame.code.opcodes.len) {
const opcode: IR.Opcode = frame.code.opcodes[frame.program_counter];
const index = frame.code.indices[frame.program_counter];
// std.debug.print("Executing at {X} {any} \n", .{frame.program_counter, opcode});
switch (opcode) {
.@"unreachable" => {
std.debug.panic("Reached unreachable statement at IR counter {any}\n", .{frame.program_counter});
@ -225,11 +226,7 @@ pub const Runtime = struct {
// TODO(ernesto): This code is repeated...
.i32_load => {
const offsetVal = self.stack.pop().?.i32;
if (offsetVal < 0) {
std.debug.panic("offsetVal is negative (val: {any} arg: {any})\n", .{ offsetVal, index.memarg });
}
const start = index.memarg.offset + @as(u32, @intCast(offsetVal));
const start = index.memarg.offset + @as(u32, @intCast(self.stack.pop().?.i32));
const end = start + @sizeOf(i32);
try self.stack.append(.{ .i32 = std.mem.littleToNative(i32, std.mem.bytesAsValue(i32, self.memory[start..end]).*) });
},
@ -252,10 +249,16 @@ pub const Runtime = struct {
.i32_load8_u => {
const start = index.memarg.offset + @as(u32, @intCast(self.stack.pop().?.i32));
const end = start + @sizeOf(u8);
try self.stack.append(.{ .i32 = std.mem.littleToNative(u8, std.mem.bytesAsValue(u8, self.memory[start..end]).*) });
const raw_value = std.mem.readInt(u8, @as(*const [1]u8, @ptrCast(self.memory[start..end])), std.builtin.Endian.little);
try self.stack.append(.{ .i32 = @intCast(@as(u32, raw_value)) });
},
.i32_load16_s => @panic("UNIMPLEMENTED"),
.i32_load16_u => @panic("UNIMPLEMENTED"),
.i32_load16_u => {
const start = index.memarg.offset + @as(u32, @intCast(self.stack.pop().?.i32));
const end = start + @sizeOf(u16);
const raw_value = std.mem.readInt(u16, @as(*const [2]u8, @ptrCast(self.memory[start..end])), std.builtin.Endian.little);
try self.stack.append(.{ .i32 = @intCast(@as(u32, raw_value)) });
},
.i64_load8_s => @panic("UNIMPLEMENTED"),
.i64_load8_u => @panic("UNIMPLEMENTED"),
.i64_load16_s => @panic("UNIMPLEMENTED"),
@ -265,7 +268,7 @@ pub const Runtime = struct {
const start = index.memarg.offset + @as(u32, @intCast(self.stack.pop().?.i32));
const end = start + @sizeOf(u32);
const raw_value = std.mem.readInt(u32, @as(*const [4]u8, @ptrCast(self.memory[start..end])), std.builtin.Endian.little);
try self.stack.append(.{ .i64 = @intCast(@as(u64, raw_value)) }); // Zero-extend
try self.stack.append(.{ .i64 = @intCast(@as(u64, raw_value)) });
},
.i32_store => {
const val = std.mem.nativeToLittle(i32, self.stack.pop().?.i32);
@ -282,7 +285,7 @@ pub const Runtime = struct {
const val = std.mem.nativeToLittle(i64, self.stack.pop().?.i64);
const offsetVal = self.stack.pop().?.i32;
if (offsetVal < 0) {
std.debug.panic("offsetVal is negative (val: {any} ip: {any} prev: {any} next: {any})\n", .{ offsetVal, frame.program_counter, frame.code.opcodes[frame.program_counter - 1], frame.code.opcodes[frame.program_counter + 1] });
std.debug.panic("offsetVal is negative (val: {any})\n", .{offsetVal});
}
const offset: u64 = @intCast(offsetVal);
const start: usize = @intCast(@as(u64, index.memarg.offset) + offset);
@ -344,9 +347,14 @@ pub const Runtime = struct {
.f64_const => @panic("UNIMPLEMENTED"),
.i32_eqz => {
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 == 0))) });
const val = self.stack.pop().?.i32;
try self.stack.append(Value{ .i32 = @intFromBool(val == 0) });
},
.i32_eq => {
const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32;
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(a == b))) });
},
.i32_eq => @panic("UNIMPLEMENTED"),
.i32_ne => {
const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32;
@ -378,7 +386,8 @@ pub const Runtime = struct {
},
.i64_eqz => {
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 == 0))) });
const val = self.stack.pop().?.i64;
try self.stack.append(Value{ .i64 = @intFromBool(val == 0) });
},
.i64_eq => @panic("UNIMPLEMENTED"),
.i64_ne => @panic("UNIMPLEMENTED"),
@ -439,13 +448,24 @@ pub const Runtime = struct {
try self.stack.append(Value{ .i32 = @bitCast(b_unsigned / a_unsigned) });
},
.i32_rem_s => @panic("UNIMPLEMENTED"),
.i32_rem_u => @panic("UNIMPLEMENTED"),
.i32_rem_u => {
const divisor = self.stack.pop().?.i32;
const dividend = self.stack.pop().?.i32;
if (divisor == 0) {
std.debug.panic("Divide by 0\n", .{});
}
try self.stack.append(Value{ .i32 = dividend - divisor * @divTrunc(dividend, divisor) });
},
.i32_or => {
const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32;
try self.stack.append(Value{ .i32 = a | b });
},
.i32_xor => @panic("UNIMPLEMENTED"),
.i32_xor => {
const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32;
try self.stack.append(Value{ .i32 = a ^ b });
},
.i32_shl => {
const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32;
@ -586,7 +606,9 @@ pub const Runtime = struct {
pub fn call(self: *Runtime, allocator: Allocator, function: usize, parameters: []Value) AllocationError!void {
const f = self.module.functions[function];
reverseSlice(parameters);
if (parameters.len > 1){
reverseSlice(parameters);
}
switch (f.typ) {
.internal => {
const ir: IR = f.typ.internal.ir;