Fixed the functions

This commit is contained in:
luccie-cmd 2025-08-04 20:48:35 +02:00
parent 6f942fe9c2
commit 83d91cfffe
4 changed files with 495996 additions and 41 deletions

View file

@ -22,7 +22,7 @@ pub fn main() !void {
// defer global_runtime.deinit();
// try global_runtime.addFunction("debug", mods.Wasm.debug);
// //const file = try std.fs.cwd().openFile("assets/core.wasm", .{});
// // const file = try std.fs.cwd().openFile("assets/core.wasm", .{});
// const file = try std.fs.cwd().openFile("./test.wasm", .{});
// const all = try file.readToEndAlloc(allocator, 1_000_000); // 1 MB
// defer allocator.free(all);

View file

@ -12,11 +12,13 @@ functions: []vm.Function,
memory: Memtype,
exports: vm.Exports,
importCount: u32,
exported_memory: u32,
globalValues: []vm.Value,
globalTypes: []Globaltype,
const Parser = @This();
const PAGE_SIZE = 64_000;
pub const Error = error{
OutOfMemory,
@ -45,6 +47,7 @@ pub const Error = error{
pub fn init(allocator: Allocator, bytes: []const u8) !Parser {
return .{
.exported_memory = 0,
.importCount = 0,
.bytes = bytes,
.byte_idx = 0,
@ -79,6 +82,8 @@ pub fn module(self: *Parser) vm.Module {
.min = self.memory.lim.min,
.max = self.memory.lim.max,
},
.imported_funcs = self.importCount,
.exported_memory = self.exported_memory,
.functions = self.functions,
.exports = self.exports,
};
@ -226,12 +231,12 @@ const Limits = struct {
fn parseLimits(self: *Parser) !Limits {
return switch (try self.readByte()) {
0x00 => .{
.min = try self.readU32(),
.min = try self.readU32() * PAGE_SIZE,
.max = null,
},
0x01 => .{
.min = try self.readU32(),
.max = try self.readU32(),
.min = try self.readU32() * PAGE_SIZE,
.max = try self.readU32() * PAGE_SIZE,
},
else => Error.invalid_limits,
};
@ -305,18 +310,6 @@ pub fn parseModule(self: *Parser) !void {
if (self.exports.preinit != null and self.exports.preinit.? != 0){
self.exports.preinit.? -= self.importCount;
}
if (self.exports.logDebug != null and self.exports.logDebug.? != 0){
self.exports.logDebug.? -= self.importCount;
}
if (self.exports.logInfo != null and self.exports.logInfo.? != 0){
self.exports.logInfo.? -= self.importCount;
}
if (self.exports.logWarn != null and self.exports.logWarn.? != 0){
self.exports.logWarn.? -= self.importCount;
}
if (self.exports.logErr != null and self.exports.logErr.? != 0){
self.exports.logErr.? -= self.importCount;
}
}
fn parseCustomsec(self: *Parser) !void {
@ -365,24 +358,26 @@ fn parseImportsec(self: *Parser) !void {
const size = try self.readU32();
const end_idx = self.byte_idx + size;
// TODO(ernesto): this should be used to do name resolution.
const imports = try self.parseVector(Parser.parseImport);
self.importCount = @intCast(imports.len);
var index: u32 = 0;
for (imports) |i| {
switch (i.importdesc) {
.func => {
if (std.mem.eql(u8, i.name, "logDebug")) {
self.exports.logDebug = i.importdesc.func;
self.exports.logDebug = index;
} else if (std.mem.eql(u8, i.name, "logInfo")) {
self.exports.logInfo = i.importdesc.func;
self.exports.logInfo = index;
} else if (std.mem.eql(u8, i.name, "logWarn")) {
self.exports.logWarn = i.importdesc.func;
self.exports.logWarn = index;
} else if (std.mem.eql(u8, i.name, "logErr")) {
self.exports.logErr = i.importdesc.func;
self.exports.logErr = index;
} else {
std.log.warn("imported function {s} not supported\n", .{i.name});
}
index += 1;
},
else => std.debug.print("[TODO]: Handle import desc {any}\n", .{i.importdesc}),
}
@ -514,6 +509,9 @@ fn parseExportsec(self: *Parser) !void {
std.log.warn("exported function {s} not supported\n", .{e.name});
}
},
.mem => {
self.exported_memory = e.exportdesc.mem * PAGE_SIZE;
},
else => std.debug.print("[WARN]: export ignored\n", .{}),
}
}

View file

@ -54,6 +54,8 @@ pub const Module = struct {
memory: Memory,
functions: []Function,
exports: Exports,
exported_memory: u32,
imported_funcs: u32,
pub fn deinit(self: Module, allocator: Allocator) void {
// self.exports.deinit(allocator);
@ -96,9 +98,9 @@ pub const Runtime = struct {
pub fn init(allocator: Allocator, module: Module, global_runtime: *wasm.GlobalRuntime) !Runtime {
// if memory max is not set the memory is allowed to grow but it is not supported at the moment
const max = module.memory.max orelse 1_000;
const max = module.memory.max orelse module.memory.min;
if (module.memory.max == null) {
std.log.warn("Growing memory is not yet supported, usign a default value of 1Kb\n", .{});
std.log.warn("Growing memory is not yet supported, usign the minimum memory\n", .{});
}
const memory = try allocator.alloc(u8, max);
return Runtime{
@ -137,13 +139,22 @@ pub const Runtime = struct {
.br_table => @panic("UNIMPLEMENTED"),
.@"return" => break :loop,
.call => {
// TODO: figure out how many parameters to push
var parameters = std.ArrayList(Value).init(allocator);
defer parameters.deinit();
for (self.module.functions[index.u32].func_type.parameters) |_| {
try parameters.append(self.stack.pop().?);
if (index.u32 == self.module.exports.logDebug) {
std.debug.print("TODO: logDebug\n", .{});
} else if (index.u32 == self.module.exports.logInfo) {
std.debug.print("TODO: logInfo\n", .{});
} else if (index.u32 == self.module.exports.logWarn) {
std.debug.print("TODO: logWarn\n", .{});
} else if (index.u32 == self.module.exports.logErr) {
std.debug.print("TODO: logErr\n", .{});
} else {
var parameters = std.ArrayList(Value).init(allocator);
defer parameters.deinit();
for (self.module.functions[index.u32 - self.module.imported_funcs].func_type.parameters) |_| {
try parameters.append(self.stack.pop().?);
}
try self.call(allocator, index.u32 - self.module.imported_funcs, parameters.items);
}
try self.call(allocator, index.u32, parameters.items);
},
.call_indirect => @panic("UNIMPLEMENTED"),
@ -212,15 +223,19 @@ pub const Runtime = struct {
.i64_load16_u => @panic("UNIMPLEMENTED"),
.i64_load32_s => @panic("UNIMPLEMENTED"),
.i64_load32_u => @panic("UNIMPLEMENTED"),
// .i32_store => {
// // TODO(ernesto): I'm pretty sure this is wrong
// const start = index.memarg.offset + index.memarg.alignment;
// const end = start + @sizeOf(u32);
// const val = std.mem.nativeToLittle(i32, self.stack.pop().?.i32);
// @memcpy(self.memory[start..end], std.mem.asBytes(&val));
// },
.i32_store => @panic("UNIMPLEMENTED"),
.i64_store => @panic("UNIMPLEMENTED"),
.i64_store => {
// TODO(ernesto): I'm pretty sure this is wrong
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})\n", .{offsetVal});
}
const offset: u64 = @intCast(offsetVal);
const start: usize = @intCast(@as(u64, index.memarg.offset) + offset);
const end = start + @sizeOf(u64);
@memcpy(self.memory[start..end], std.mem.asBytes(&val));
},
.f32_store => @panic("UNIMPLEMENTED"),
.f64_store => @panic("UNIMPLEMENTED"),
.i32_store8 => @panic("UNIMPLEMENTED"),
@ -497,19 +512,19 @@ pub fn handleGlobalInit(allocator: Allocator, ir: IR) !Value {
var instruction_pointer: usize = 0;
var stack = try std.ArrayList(Value).initCapacity(allocator, 10);
defer stack.deinit();
while (instruction_pointer < ir.opcodes.len){
while (instruction_pointer < ir.opcodes.len) {
const opcode: IR.Opcode = ir.opcodes[instruction_pointer];
const index = ir.indices[instruction_pointer];
switch (opcode) {
.i32_const => try stack.append(Value{ .i32 = index.i32 }),
else => {
std.debug.panic("TODO: Handle opcode {any}\n", .{opcode});
}
},
}
instruction_pointer += 1;
}
if (stack.items.len != 1){
if (stack.items.len != 1) {
std.debug.panic("Improper amount of variables at end\n", .{});
}
return stack.pop().?;
}
}