From 7658e0d4e8e6715094e132080ec64b4674849d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=AA=E3=82=AD=E8=90=8C?= Date: Wed, 11 Jun 2025 10:43:22 +0200 Subject: [PATCH] haku2: VM logging --- crates/haku2/src/haku2.zig | 10 +++++++- crates/haku2/src/lib.rs | 49 +++++++++++++++++++++++++++++++++++++ crates/haku2/src/log.zig | 42 +++++++++++++++++++++++++++++++ crates/haku2/src/vm.zig | 4 +++ crates/rkgk/src/api/wall.rs | 2 +- 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 crates/haku2/src/log.zig diff --git a/crates/haku2/src/haku2.zig b/crates/haku2/src/haku2.zig index 046d990..bf298ca 100644 --- a/crates/haku2/src/haku2.zig +++ b/crates/haku2/src/haku2.zig @@ -8,13 +8,21 @@ const render = @import("render.zig"); const Scratch = @import("scratch.zig"); const value = @import("value.zig"); const Vm = @import("vm.zig"); +const log = @import("log.zig"); -const allocator = +const vm_trace = true; + +pub const allocator = if (builtin.cpu.arch == .wasm32) std.heap.wasm_allocator else @import("allocator.zig").hostAllocator; +pub const std_options: std.Options = .{ + .log_level = if (vm_trace) .debug else .info, + .logFn = log.logFn, +}; + // Scratch export fn haku2_scratch_new(max: usize) ?*Scratch { diff --git a/crates/haku2/src/lib.rs b/crates/haku2/src/lib.rs index d9306ed..7ddf7e3 100644 --- a/crates/haku2/src/lib.rs +++ b/crates/haku2/src/lib.rs @@ -5,6 +5,7 @@ use std::{ marker::{PhantomData, PhantomPinned}, mem::forget, ptr::{self, NonNull}, + slice, }; #[unsafe(no_mangle)] @@ -40,6 +41,54 @@ unsafe extern "C" fn __haku2_dealloc(ptr: *mut u8, size: usize, align: usize) { } } +#[unsafe(no_mangle)] +unsafe extern "C" fn __haku2_log_err( + scope: *const u8, + scope_len: usize, + msg: *const u8, + len: usize, +) { + let scope = String::from_utf8_lossy(slice::from_raw_parts(scope, scope_len)); + let msg = String::from_utf8_lossy(slice::from_raw_parts(msg, len)); + log::error!("{scope}: {msg}"); +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn __haku2_log_warn( + scope: *const u8, + scope_len: usize, + msg: *const u8, + len: usize, +) { + let scope = String::from_utf8_lossy(slice::from_raw_parts(scope, scope_len)); + let msg = String::from_utf8_lossy(slice::from_raw_parts(msg, len)); + log::warn!("{scope}: {msg}"); +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn __haku2_log_info( + scope: *const u8, + scope_len: usize, + msg: *const u8, + len: usize, +) { + let scope = String::from_utf8_lossy(slice::from_raw_parts(scope, scope_len)); + let msg = String::from_utf8_lossy(slice::from_raw_parts(msg, len)); + log::info!("{scope}: {msg}"); +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn __haku2_log_debug( + scope: *const u8, + scope_len: usize, + msg: *const u8, + len: usize, +) { + let scope = String::from_utf8_lossy(slice::from_raw_parts(scope, scope_len)); + let msg = String::from_utf8_lossy(slice::from_raw_parts(msg, len)); + log::debug!("{scope}: {msg}"); +} + #[repr(C)] struct ScratchC { _data: (), diff --git a/crates/haku2/src/log.zig b/crates/haku2/src/log.zig new file mode 100644 index 0000000..94b466d --- /dev/null +++ b/crates/haku2/src/log.zig @@ -0,0 +1,42 @@ +const std = @import("std"); +const log = std.log; + +const root = @import("root"); + +pub fn logFn( + comptime level: log.Level, + comptime scope: @TypeOf(.enum_literal), + comptime fmt: []const u8, + args: anytype, +) void { + const stack_buf_size = 1024; + var stack_buf: [stack_buf_size]u8 = undefined; + var heap_buf: ?[]u8 = null; + + // Tricky code ahead: when the heap allocation fails, we still want to fall back to + // logging _something_. + + const len: usize = @truncate(std.fmt.count(fmt, args)); + if (len > stack_buf_size) { + heap_buf = root.allocator.alloc(u8, len) catch null; + } + defer if (heap_buf) |buf| { + root.allocator.free(buf); + }; + + const buf: []u8 = if (heap_buf) |b| b else stack_buf[0..len]; + const msg = std.fmt.bufPrint(buf, fmt, args) catch buf[0..len]; // no space? yeah whatever print as much as you can + + const scope_name = @tagName(scope); + switch (level) { + .err => __haku2_log_err(scope_name.ptr, scope_name.len, msg.ptr, msg.len), + .warn => __haku2_log_warn(scope_name.ptr, scope_name.len, msg.ptr, msg.len), + .info => __haku2_log_info(scope_name.ptr, scope_name.len, msg.ptr, msg.len), + .debug => __haku2_log_debug(scope_name.ptr, scope_name.len, msg.ptr, msg.len), + } +} + +extern fn __haku2_log_err(scope: [*]const u8, scope_len: usize, msg: [*]const u8, len: usize) void; +extern fn __haku2_log_warn(scope: [*]const u8, scope_len: usize, msg: [*]const u8, len: usize) void; +extern fn __haku2_log_info(scope: [*]const u8, scope_len: usize, msg: [*]const u8, len: usize) void; +extern fn __haku2_log_debug(scope: [*]const u8, scope_len: usize, msg: [*]const u8, len: usize) void; diff --git a/crates/haku2/src/vm.zig b/crates/haku2/src/vm.zig index 9cab95e..ee89be7 100644 --- a/crates/haku2/src/vm.zig +++ b/crates/haku2/src/vm.zig @@ -1,6 +1,7 @@ const std = @import("std"); const mem = std.mem; const debug = std.debug; +const log = std.log; const testAllocator = std.testing.allocator; const bytecode = @import("bytecode.zig"); @@ -54,6 +55,8 @@ pub fn init(a: mem.Allocator, defs: *const bytecode.Defs, limits: *const Limits) } pub fn throw(vm: *Vm, comptime fmt: []const u8, args: anytype) Error { + log.debug("throw: fmt={s}", .{fmt}); + const Args = @TypeOf(args); const max_args_size = @sizeOf(@TypeOf(vm.exception.?.args)); if (@sizeOf(Args) > max_args_size) { @@ -75,6 +78,7 @@ pub fn throw(vm: *Vm, comptime fmt: []const u8, args: anytype) Error { .args = undefined, }; @memcpy(exn.args[0..@sizeOf(Args)], mem.asBytes(&args)); + vm.exception = exn; return error.Exception; } diff --git a/crates/rkgk/src/api/wall.rs b/crates/rkgk/src/api/wall.rs index 42587c6..173b15a 100644 --- a/crates/rkgk/src/api/wall.rs +++ b/crates/rkgk/src/api/wall.rs @@ -574,7 +574,7 @@ fn jumpstart_trampoline<'a>( fn jumpstart_trampoline2(haku: &mut Haku) { if !haku.has_cont2() { if let Err(e) = haku.eval_brush2() { - error!("eval_brush2: {e}"); + error!("eval_brush2: {e:?}"); } } }