#ifndef __SPL_RT_H__ #define __SPL_RT_H__ #include #include #include #include #include #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define SPL_FN static inline #elif defined(__GNUC__) || defined(__clang__) #define SPL_FN static __inline__ #else #define SPL_FN static #endif #include typedef uint8_t u8; typedef int8_t i8; typedef uint16_t u16; typedef int16_t i16; typedef uint32_t u32; typedef int32_t i32; typedef uint64_t u64; typedef int64_t i64; #ifndef SPL_USIZE_TYPEDEF #define SPL_USIZE_TYPEDEF typedef u64 usize; #endif #ifndef SPL_ISIZE_TYPEDEF #define SPL_ISIZE_TYPEDEF typedef i64 isize; #endif SPL_FN void spl_panic(const char *msg) { fprintf(stderr, "%s\n", msg ? msg : "panic"); exit(1); } SPL_FN void spl_trap(void) { abort(); } #include "spl_rt_core.h" SPL_FN void *vm_fopen(void *path, void *mode) { return (void *)fopen((const char *)path, (const char *)mode); } SPL_FN i32 vm_fclose(void *f) { return f ? fclose((FILE *)f) : 0; } SPL_FN u64 vm_fread(void *buf, u64 sz, u64 n, void *f) { return f ? (u64)fread(buf, (size_t)sz, (size_t)n, (FILE *)f) : 0; } SPL_FN u64 vm_fwrite(void *buf, u64 sz, u64 n, void *f) { return f ? (u64)fwrite(buf, (size_t)sz, (size_t)n, (FILE *)f) : 0; } SPL_FN u64 vm_fsize(void *f) { long cur, end; if (!f) return 0; cur = ftell((FILE *)f); if (cur < 0) return 0; if (fseek((FILE *)f, 0, SEEK_END) != 0) return 0; end = ftell((FILE *)f); fseek((FILE *)f, cur, SEEK_SET); return end < 0 ? 0 : (u64)end; } SPL_FN void *vm_stdin(void) { return (void *)stdin; } SPL_FN void *vm_stdout(void) { return (void *)stdout; } SPL_FN void *vm_stderr(void) { return (void *)stderr; } SPL_FN i32 vm_putchar(i32 c) { return fputc(c, stdout); } SPL_FN i32 vm_getchar(void) { return fgetc(stdin); } SPL_FN void vm_exit(i32 code) { exit(code); } SPL_FN u64 vm_timestamp(u64 kind) { time_t sec = time(NULL); if (kind == 1) return (u64)sec; if (kind == 2) return 0; if (kind == 4) return (u64)sec * 1000000000ull; return 0; } #define SPL_VM_EMBED_IMPLIMENTATION #include "spl_vm_embed.h" /* 配置层外部函数处理器(native 端):把 nested VM 未解析的 native 按名分发到 * 编译器生成的 `ct_*` 函数(表由 ir2c 生成,见 stage2/ir2c.spl)。 */ extern void *spl_ct_lookup(const char *name); typedef spl_vm_val_t (*spl_native_ct_fn_t)(void *, spl_vm_val_t, spl_vm_val_t, spl_vm_val_t); SPL_FN spl_vm_val_t spl_native_foreign(spl_vm_t *vm, const spl_vm_call_t *call, void *user) { void *fn; spl_vm_val_t a0 = 0, a1 = 0; (void)vm; if (!call) return 0; fn = spl_ct_lookup(call->name); if (!fn) return 0; if (call->nargs > 0) a0 = call->args[0]; if (call->nargs > 1) a1 = call->args[1]; /* ct_* 统一形状:返回 u64,参数 (ctx, u64, u64);多余参数被忽略。 */ return ((spl_native_ct_fn_t)fn)(user, a0, a1, 0); } SPL_FN void vm_set_foreign(void *p, unsigned long long handler, void *ctx) { (void)handler; spl_vm_set_foreign((spl_vm_t *)p, spl_native_foreign, ctx); } #endif /* __SPL_RT_H__ */