119 lines
3.2 KiB
C
119 lines
3.2 KiB
C
#ifndef __SPL_RT_H__
|
|
#define __SPL_RT_H__
|
|
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#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 <stdint.h>
|
|
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__ */
|