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

495942
sideros.asm Normal file

File diff suppressed because it is too large Load diff

View file

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

View file

@ -54,6 +54,8 @@ pub const Module = struct {
memory: Memory, memory: Memory,
functions: []Function, functions: []Function,
exports: Exports, exports: Exports,
exported_memory: u32,
imported_funcs: u32,
pub fn deinit(self: Module, allocator: Allocator) void { pub fn deinit(self: Module, allocator: Allocator) void {
// self.exports.deinit(allocator); // self.exports.deinit(allocator);
@ -96,9 +98,9 @@ pub const Runtime = struct {
pub fn init(allocator: Allocator, module: Module, global_runtime: *wasm.GlobalRuntime) !Runtime { 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 // 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) { 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); const memory = try allocator.alloc(u8, max);
return Runtime{ return Runtime{
@ -137,13 +139,22 @@ pub const Runtime = struct {
.br_table => @panic("UNIMPLEMENTED"), .br_table => @panic("UNIMPLEMENTED"),
.@"return" => break :loop, .@"return" => break :loop,
.call => { .call => {
// TODO: figure out how many parameters to push 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); var parameters = std.ArrayList(Value).init(allocator);
defer parameters.deinit(); defer parameters.deinit();
for (self.module.functions[index.u32].func_type.parameters) |_| { for (self.module.functions[index.u32 - self.module.imported_funcs].func_type.parameters) |_| {
try parameters.append(self.stack.pop().?); try parameters.append(self.stack.pop().?);
} }
try self.call(allocator, index.u32, parameters.items); try self.call(allocator, index.u32 - self.module.imported_funcs, parameters.items);
}
}, },
.call_indirect => @panic("UNIMPLEMENTED"), .call_indirect => @panic("UNIMPLEMENTED"),
@ -212,15 +223,19 @@ pub const Runtime = struct {
.i64_load16_u => @panic("UNIMPLEMENTED"), .i64_load16_u => @panic("UNIMPLEMENTED"),
.i64_load32_s => @panic("UNIMPLEMENTED"), .i64_load32_s => @panic("UNIMPLEMENTED"),
.i64_load32_u => @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"), .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"), .f32_store => @panic("UNIMPLEMENTED"),
.f64_store => @panic("UNIMPLEMENTED"), .f64_store => @panic("UNIMPLEMENTED"),
.i32_store8 => @panic("UNIMPLEMENTED"), .i32_store8 => @panic("UNIMPLEMENTED"),
@ -504,7 +519,7 @@ pub fn handleGlobalInit(allocator: Allocator, ir: IR) !Value {
.i32_const => try stack.append(Value{ .i32 = index.i32 }), .i32_const => try stack.append(Value{ .i32 = index.i32 }),
else => { else => {
std.debug.panic("TODO: Handle opcode {any}\n", .{opcode}); std.debug.panic("TODO: Handle opcode {any}\n", .{opcode});
} },
} }
instruction_pointer += 1; instruction_pointer += 1;
} }