[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

@ -1,19 +1,19 @@
pub extern fn logErr( pub extern fn logErr(
string: *const u8, string: *const u8,
len: u64, len: u64,
) void; ) callconv(.c) void;
pub extern fn logWarn( pub extern fn logWarn(
string: *const u8, string: *const u8,
len: u64, len: u64,
) void; ) callconv(.c) void;
pub extern fn logInfo( pub extern fn logInfo(
string: *const u8, string: *const u8,
len: u64, len: u64,
) void; ) callconv(.c) void;
pub extern fn logDebug( pub extern fn logDebug(
string: *const u8, string: *const u8,
len: u64, len: u64,
) void; ) callconv(.c) void;

View file

@ -25,6 +25,7 @@ const PAGE_SIZE = 65536;
pub const Error = error{ pub const Error = error{
OutOfMemory, OutOfMemory,
DivideBy0,
Overflow, Overflow,
invalid_instruction, invalid_instruction,
invalid_magic, 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", .{}); std.log.warn("Growing memory is not yet supported, usign the minimum memory\n", .{});
} }
const memory = try allocator.alloc(u8, max); const memory = try allocator.alloc(u8, max);
std.crypto.secureZero(u8, memory); @memset(memory, 0);
@memcpy(memory[0..module.data.len], module.data); @memcpy(memory[0..module.data.len], module.data);
return Runtime{ return Runtime{
.module = module, .module = module,
@ -124,6 +124,7 @@ pub const Runtime = struct {
loop: while (frame.program_counter < frame.code.opcodes.len) { loop: while (frame.program_counter < frame.code.opcodes.len) {
const opcode: IR.Opcode = frame.code.opcodes[frame.program_counter]; const opcode: IR.Opcode = frame.code.opcodes[frame.program_counter];
const index = frame.code.indices[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) { switch (opcode) {
.@"unreachable" => { .@"unreachable" => {
std.debug.panic("Reached unreachable statement at IR counter {any}\n", .{frame.program_counter}); 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... // TODO(ernesto): This code is repeated...
.i32_load => { .i32_load => {
const offsetVal = self.stack.pop().?.i32; const start = index.memarg.offset + @as(u32, @intCast(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 end = start + @sizeOf(i32); const end = start + @sizeOf(i32);
try self.stack.append(.{ .i32 = std.mem.littleToNative(i32, std.mem.bytesAsValue(i32, self.memory[start..end]).*) }); 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 => { .i32_load8_u => {
const start = index.memarg.offset + @as(u32, @intCast(self.stack.pop().?.i32)); const start = index.memarg.offset + @as(u32, @intCast(self.stack.pop().?.i32));
const end = start + @sizeOf(u8); 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_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_s => @panic("UNIMPLEMENTED"),
.i64_load8_u => @panic("UNIMPLEMENTED"), .i64_load8_u => @panic("UNIMPLEMENTED"),
.i64_load16_s => @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 start = index.memarg.offset + @as(u32, @intCast(self.stack.pop().?.i32));
const end = start + @sizeOf(u32); 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); 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 => { .i32_store => {
const val = std.mem.nativeToLittle(i32, self.stack.pop().?.i32); 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 val = std.mem.nativeToLittle(i64, self.stack.pop().?.i64);
const offsetVal = self.stack.pop().?.i32; const offsetVal = self.stack.pop().?.i32;
if (offsetVal < 0) { 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 offset: u64 = @intCast(offsetVal);
const start: usize = @intCast(@as(u64, index.memarg.offset) + offset); const start: usize = @intCast(@as(u64, index.memarg.offset) + offset);
@ -344,9 +347,14 @@ pub const Runtime = struct {
.f64_const => @panic("UNIMPLEMENTED"), .f64_const => @panic("UNIMPLEMENTED"),
.i32_eqz => { .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 => { .i32_ne => {
const a = self.stack.pop().?.i32; const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32; const b = self.stack.pop().?.i32;
@ -378,7 +386,8 @@ pub const Runtime = struct {
}, },
.i64_eqz => { .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_eq => @panic("UNIMPLEMENTED"),
.i64_ne => @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) }); try self.stack.append(Value{ .i32 = @bitCast(b_unsigned / a_unsigned) });
}, },
.i32_rem_s => @panic("UNIMPLEMENTED"), .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 => { .i32_or => {
const a = self.stack.pop().?.i32; const a = self.stack.pop().?.i32;
const b = self.stack.pop().?.i32; const b = self.stack.pop().?.i32;
try self.stack.append(Value{ .i32 = a | b }); 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 => { .i32_shl => {
const a = self.stack.pop().?.i32; const a = self.stack.pop().?.i32;
const b = 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 { pub fn call(self: *Runtime, allocator: Allocator, function: usize, parameters: []Value) AllocationError!void {
const f = self.module.functions[function]; const f = self.module.functions[function];
if (parameters.len > 1){
reverseSlice(parameters); reverseSlice(parameters);
}
switch (f.typ) { switch (f.typ) {
.internal => { .internal => {
const ir: IR = f.typ.internal.ir; const ir: IR = f.typ.internal.ir;