stage1 指针计算类型的错误修复 as运算符优先级的修改 ir2vm的bug修复
This commit is contained in:
1 parent
06f3884c30
commit
09d05e3a34
10 files changed
+191
-60
No files matched your search
+3
-2
@@ -101,12 +101,13 @@ ArrowExpr = { RangeExpr ~ ((THIN_R_ARROW | THIN_L_ARROW | FAT_D_ARROW | THIN_D_A
|
||||
RangeExpr = { ShiftExpr ~ (DOT2 ~ ShiftExpr?)? }
|
||||
ShiftExpr = { AddExpr ~ ((L_ARROW2_EQ | L_ARROW2 | R_ARROW2_EQ | R_ARROW2) ~ AddExpr)* }
|
||||
AddExpr = { MulExpr ~ ((PLUS | MINUS) ~ MulExpr)* }
|
||||
MulExpr = { PrefixExpr ~ ((ASTERISK | SLASH | PERCENT) ~ PrefixExpr)* }
|
||||
MulExpr = { CastExpr ~ ((ASTERISK | SLASH | PERCENT) ~ CastExpr)* }
|
||||
CastExpr = { PrefixExpr ~ (KEYWORD_as ~ TypeExpr)* }
|
||||
PrefixExpr = { PrefixOp* ~ PostfixExpr }
|
||||
PrefixOp = { MINUS | BANG | TILDE | AMPERSAND }
|
||||
|
||||
PostfixExpr = {
|
||||
PrimaryExpr ~ (LPAREN ~ ExprList ~ RPAREN | DOT ~ IDENTIFIER | DOT ~ ASTERISK | LBRACKET ~ Expr ~ RBRACKET | LBRACKET ~ Expr ~ DOT2 ~ Expr? ~ RBRACKET | KEYWORD_as ~ TypeExpr)*
|
||||
PrimaryExpr ~ (LPAREN ~ ExprList ~ RPAREN | DOT ~ IDENTIFIER | DOT ~ ASTERISK | LBRACKET ~ Expr ~ RBRACKET | LBRACKET ~ Expr ~ DOT2 ~ Expr? ~ RBRACKET)*
|
||||
}
|
||||
|
||||
ExprList = { (Expr ~ COMMA)* ~ Expr? }
|
||||
|
||||
@@ -379,7 +379,7 @@ int main(int argc, char **argv) {
|
||||
} else if (strcmp(mode_name, "run") == 0) {
|
||||
// HACK
|
||||
Nob_Cmd cmd = {0};
|
||||
nob_cmd_append(&cmd, BUILD_FOLDER "spl_cli");
|
||||
nob_cmd_append(&cmd, BUILD_FOLDER "spl_cli", "-d");
|
||||
nob_cmd_append(&cmd, BUILD_FOLDER "test.sir");
|
||||
return nob_cmd_run(&cmd) ? 0 : 1;
|
||||
} else {
|
||||
|
||||
+6
-2
@@ -637,10 +637,14 @@ int main(int argc, const char **argv) {
|
||||
|
||||
spl_vm_t vm;
|
||||
spl_vm_init(&vm);
|
||||
if (o.debug)
|
||||
if (o.debug) {
|
||||
fprintf(stderr, "spl_cli: debug mode on\n");
|
||||
spl_vm_set_debug(&vm, 1);
|
||||
if (o.trace)
|
||||
}
|
||||
if (o.trace) {
|
||||
fprintf(stderr, "spl_cli: trace mode on\n");
|
||||
spl_vm_set_trace(&vm, 1);
|
||||
}
|
||||
if (spl_vm_load_prog(&vm, &prog) != 0) {
|
||||
fprintf(stderr, "spl_cli: failed to load prog\n");
|
||||
spl_vm_drop(&vm);
|
||||
|
||||
+3
-1
@@ -170,7 +170,9 @@ typedef struct spl_vm_func {
|
||||
typedef VEC(spl_vm_func_t) spl_vm_func_vec_t;
|
||||
|
||||
/* Native function pointer type */
|
||||
typedef spl_vm_val_t (*spl_vm_fn_t)(int nargs, spl_vm_val_t *args);
|
||||
struct spl_vm;
|
||||
typedef struct spl_vm spl_vm_t;
|
||||
typedef spl_vm_val_t (*spl_vm_fn_t)(spl_vm_t *vm, int nargs, spl_vm_val_t *args);
|
||||
typedef struct spl_vm_native {
|
||||
char *name;
|
||||
spl_vm_val_t idx_of_strtab;
|
||||
|
||||
+106
-31
@@ -36,21 +36,21 @@
|
||||
} while (0)
|
||||
|
||||
#define SYSCALL_0(name, ret_expr) \
|
||||
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
|
||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||
CHECK_NARGS(#name, 0); \
|
||||
(void)args; \
|
||||
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
|
||||
}
|
||||
|
||||
#define SYSCALL_1(name, t1, ret_expr) \
|
||||
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
|
||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||
CHECK_NARGS(#name, 1); \
|
||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
|
||||
}
|
||||
|
||||
#define SYSCALL_2(name, t1, t2, ret_expr) \
|
||||
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
|
||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||
CHECK_NARGS(#name, 2); \
|
||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||
@@ -58,7 +58,7 @@
|
||||
}
|
||||
|
||||
#define SYSCALL_3(name, t1, t2, t3, ret_expr) \
|
||||
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
|
||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||
CHECK_NARGS(#name, 3); \
|
||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||
@@ -67,7 +67,7 @@
|
||||
}
|
||||
|
||||
#define SYSCALL_4(name, t1, t2, t3, t4, ret_expr) \
|
||||
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
|
||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||
CHECK_NARGS(#name, 4); \
|
||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||
@@ -76,6 +76,42 @@
|
||||
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
|
||||
}
|
||||
|
||||
/* syscall / VM 内部统一地址检查宏。
|
||||
* 失败时打印 ctx + 地址 + size + ip,置 native_error,return 0。
|
||||
* 要求所在函数有可用的 _vm 变量。 */
|
||||
#define ADDRCHECK(vm, ptr, size, ctx) \
|
||||
do { \
|
||||
uintptr_t _acp = (uintptr_t)(ptr); \
|
||||
usize _acs = (usize)(size); \
|
||||
if (!spl_vm_addr_valid(_acp, _acs)) { \
|
||||
fprintf(stderr, "%s: invalid address %p size=%zu (ip=%zu fp=%zu sp=%zu)\n", (ctx), \
|
||||
(void *)_acp, _acs, (vm)->ip, (vm)->fp, (vm)->sp); \
|
||||
spl_vm_backtrace((vm), (vm)->fp); \
|
||||
(vm)->exit_code = 2; \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* syscall 内部:把当前栈和调用栈打印出来,供出错时定位 */
|
||||
#define SYSCALL_DUMP(vm) \
|
||||
do { \
|
||||
fprintf(stderr, " --- syscall dump (sp=%zu fp=%zu cp=%zu ip=%zu) ---\n", (vm)->sp, \
|
||||
(vm)->fp, (vm)->cp, (vm)->ip); \
|
||||
spl_vm_backtrace((vm), (vm)->fp); \
|
||||
spl_vm_stackdump((vm), (vm)->sp); \
|
||||
} while (0)
|
||||
|
||||
/* syscall 内部:报告致命错误,dump 后让 VM 停在当前 ip */
|
||||
#define SYSCALL_FAIL(vm, ...) \
|
||||
do { \
|
||||
fprintf(stderr, "syscall error: "); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
SYSCALL_DUMP(vm); \
|
||||
(vm)->exit_code = 1; \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
/* =================================================================
|
||||
* OS syscalls
|
||||
* ================================================================= */
|
||||
@@ -108,7 +144,7 @@ SYSCALL_4(vm_fread, void *, size_t, size_t, FILE *, fread(a1, a2, a3, a4))
|
||||
SYSCALL_4(vm_fwrite, const void *, size_t, size_t, FILE *, fwrite(a1, a2, a3, a4))
|
||||
|
||||
/* vm_fsize - get file size in bytes */
|
||||
static spl_vm_val_t vm_fsize(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_fsize(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_fsize", 1);
|
||||
FILE *f = (FILE *)(uintptr_t)args[0];
|
||||
long cur = ftell(f);
|
||||
@@ -123,7 +159,7 @@ SYSCALL_0(vm_stdout, stdout)
|
||||
SYSCALL_0(vm_stderr, stderr)
|
||||
|
||||
/* vm_read_file - read entire file into a malloc'd, null-terminated buffer */
|
||||
static spl_vm_val_t vm_read_file(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_read_file(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_read_file", 1);
|
||||
const char *path = (const char *)(uintptr_t)args[0];
|
||||
if (path == nullptr) {
|
||||
@@ -149,28 +185,69 @@ static spl_vm_val_t vm_read_file(int nargs, spl_vm_val_t *args) {
|
||||
return (spl_vm_val_t)(uintptr_t)buf;
|
||||
}
|
||||
|
||||
/* vm_alloc - allocate memory (malloc) */
|
||||
SYSCALL_1(vm_alloc, size_t, (uintptr_t)malloc(a1))
|
||||
static spl_vm_val_t vm_alloc(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_alloc", 1);
|
||||
size_t sz = (size_t)args[0];
|
||||
if (sz == 0)
|
||||
SYSCALL_FAIL(_vm, "vm_alloc: zero size");
|
||||
if (sz > (size_t)1 << 32)
|
||||
SYSCALL_FAIL(_vm, "vm_alloc: size too large (%zu)", sz);
|
||||
void *p = malloc(sz);
|
||||
if (!p)
|
||||
SYSCALL_FAIL(_vm, "vm_alloc: malloc(%zu) failed", sz);
|
||||
return (spl_vm_val_t)(uintptr_t)p;
|
||||
}
|
||||
|
||||
/* vm_free - free memory */
|
||||
SYSCALL_1(vm_free, void *, (free(a1), (spl_vm_val_t)0))
|
||||
static spl_vm_val_t vm_free(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
(void)_vm;
|
||||
CHECK_NARGS("vm_free", 1);
|
||||
void *p = (void *)(uintptr_t)args[0];
|
||||
if (p)
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vm_realloc - reallocate memory (realloc) */
|
||||
SYSCALL_2(vm_realloc, void *, size_t, (uintptr_t)realloc(a1, a2))
|
||||
static spl_vm_val_t vm_realloc(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_realloc", 2);
|
||||
void *p = (void *)(uintptr_t)args[0];
|
||||
size_t sz = (size_t)args[1];
|
||||
if (!p)
|
||||
SYSCALL_FAIL(_vm, "vm_realloc: NULL ptr");
|
||||
if (sz == 0)
|
||||
SYSCALL_FAIL(_vm, "vm_realloc: zero size");
|
||||
ADDRCHECK(_vm, p, 1, "vm_realloc");
|
||||
void *np = realloc(p, sz);
|
||||
if (!np)
|
||||
SYSCALL_FAIL(_vm, "vm_realloc: realloc(%p, %zu) failed", p, sz);
|
||||
return (spl_vm_val_t)(uintptr_t)np;
|
||||
}
|
||||
|
||||
/* vm_strlen - get string length */
|
||||
SYSCALL_1(vm_strlen, const char *, strlen(a1))
|
||||
static spl_vm_val_t vm_memcpy(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_memcpy", 3);
|
||||
void *dst = (void *)(uintptr_t)args[0];
|
||||
const void *src = (const void *)(uintptr_t)args[1];
|
||||
size_t size = (size_t)args[2];
|
||||
if (size == 0)
|
||||
return (spl_vm_val_t)(uintptr_t)dst;
|
||||
ADDRCHECK(_vm, dst, size, "vm_memcpy(dst)");
|
||||
ADDRCHECK(_vm, src, size, "vm_memcpy(src)");
|
||||
memcpy(dst, src, size);
|
||||
return (spl_vm_val_t)(uintptr_t)dst;
|
||||
}
|
||||
|
||||
/* vm_strcmp - compare two strings */
|
||||
SYSCALL_2(vm_strcmp, const char *, const char *, strcmp(a1, a2))
|
||||
static spl_vm_val_t vm_memcmp(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_memcmp", 3);
|
||||
const void *a = (const void *)(uintptr_t)args[0];
|
||||
const void *b = (const void *)(uintptr_t)args[1];
|
||||
size_t size = (size_t)args[2];
|
||||
if (size == 0)
|
||||
return 0;
|
||||
ADDRCHECK(_vm, a, size, "vm_memcmp(a)");
|
||||
ADDRCHECK(_vm, b, size, "vm_memcmp(b)");
|
||||
return (spl_vm_val_t)memcmp(a, b, size);
|
||||
}
|
||||
|
||||
/* vm_memcpy - copy memory, returns dst */
|
||||
SYSCALL_3(vm_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1))
|
||||
|
||||
/* vm_memcmp - compare two memory */
|
||||
SYSCALL_3(vm_memcmp, void *, const void *, size_t, (memcmp(a1, a2, a3), (uintptr_t)a1))
|
||||
|
||||
static spl_vm_val_t vm_printf(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_printf(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
if (nargs <= 0)
|
||||
return 0;
|
||||
|
||||
@@ -245,7 +322,7 @@ static spl_vm_val_t vm_printf(int nargs, spl_vm_val_t *args) {
|
||||
* ================================================================= */
|
||||
|
||||
/* vm_new - create a new sub-VM instance, returns spl_vm_t* */
|
||||
static spl_vm_val_t vm_new(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_new", 0);
|
||||
(void)args;
|
||||
spl_vm_t *vm = (spl_vm_t *)malloc(sizeof(spl_vm_t));
|
||||
@@ -256,7 +333,7 @@ static spl_vm_val_t vm_new(int nargs, spl_vm_val_t *args) {
|
||||
}
|
||||
|
||||
/* vm_drop - destroy a sub-VM and its loaded program */
|
||||
static spl_vm_val_t vm_drop(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_drop", 1);
|
||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||
if (!vm)
|
||||
@@ -272,7 +349,7 @@ static spl_vm_val_t vm_drop(int nargs, spl_vm_val_t *args) {
|
||||
}
|
||||
|
||||
/* vm_load - load a .sir file, register syscalls, return spl_prog_t* */
|
||||
static spl_vm_val_t vm_load(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_load(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_load", 2);
|
||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||
const char *path = (const char *)(uintptr_t)args[1];
|
||||
@@ -296,7 +373,7 @@ static spl_vm_val_t vm_load(int nargs, spl_vm_val_t *args) {
|
||||
}
|
||||
|
||||
/* vm_push - push a value onto the sub-VM's stack (for passing arguments) */
|
||||
static spl_vm_val_t vm_push(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_push(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_push", 2);
|
||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||
spl_vm_val_t val = args[1];
|
||||
@@ -321,7 +398,7 @@ static spl_vm_val_t vm_push(int nargs, spl_vm_val_t *args) {
|
||||
* - Sets fp = sp - nargs (so arg0 = data[fp], arg1 = data[fp+1], ...)
|
||||
* - Sets ip to the function address
|
||||
*/
|
||||
static spl_vm_val_t vm_call(int nargs, spl_vm_val_t *args) {
|
||||
static spl_vm_val_t vm_call(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||
CHECK_NARGS("vm_call", 3);
|
||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||
const char *name = (const char *)(uintptr_t)args[1];
|
||||
@@ -387,8 +464,6 @@ void spl_syscall_register(spl_prog_t *prog) {
|
||||
{"vm_alloc", 0, vm_alloc},
|
||||
{"vm_free", 0, vm_free},
|
||||
{"vm_realloc", 0, vm_realloc},
|
||||
{"vm_strlen", 0, vm_strlen},
|
||||
{"vm_strcmp", 0, vm_strcmp},
|
||||
{"vm_memcpy", 0, vm_memcpy},
|
||||
{"vm_memcmp", 0, vm_memcmp},
|
||||
{"vm_printf", 0, vm_printf},
|
||||
|
||||
+30
-4
@@ -587,6 +587,25 @@ void spl_vm_drop(spl_vm_t *vm) {
|
||||
vec_free(vm->breakpoints);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
int spl_vm_addr_valid(uintptr_t p, usize size) {
|
||||
if (p == 0)
|
||||
return 0;
|
||||
if (p < 0x1000)
|
||||
return 0;
|
||||
uintptr_t max =
|
||||
(sizeof(void *) == 8) ? (uintptr_t)0x00007FFFFFFFFFFFULL : (uintptr_t)0x7FFFFFFF;
|
||||
if (p > max)
|
||||
return 0;
|
||||
if (size > 0) {
|
||||
if (p + size < p)
|
||||
return 0;
|
||||
if (p + size > max)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void spl_vm_add_breakpoint(spl_vm_t *vm, usize ip) {
|
||||
if (!vm)
|
||||
return;
|
||||
@@ -1108,10 +1127,17 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
VM_ERROR(vm->error_msg);
|
||||
}
|
||||
spl_vm_val_t *_arg_base = vm->stacks.data + vm->sp - _nargs;
|
||||
// spl_vm_stackdump(vm, vm->sp);
|
||||
// printf("addr %p nargs %zd sp %zd stack %p arg_base %p\n", _nat->impl_fn, _nargs, vm->sp,
|
||||
// vm->stacks.data, _arg_base);
|
||||
spl_vm_val_t _result = _nat->impl_fn(_nargs, _arg_base);
|
||||
spl_vm_val_t _result = _nat->impl_fn(vm, _nargs, _arg_base);
|
||||
if (vm->exit_code) {
|
||||
snprintf(vm->error_msg, sizeof(vm->error_msg), "NCALL %s failed (ip=%zd)",
|
||||
_nat->name ? _nat->name : "?", vm->ip - 1);
|
||||
fprintf(stderr, "native call: %s\n", _nat->name ? _nat->name : "?");
|
||||
fprintf(stderr, " nargs=%zd arg_base=%p sp=%zu\n", _nargs, (void *)_arg_base,
|
||||
vm->sp);
|
||||
spl_vm_backtrace(vm, vm->fp);
|
||||
spl_vm_stackdump(vm, vm->sp);
|
||||
return -1;
|
||||
}
|
||||
vm->sp -= _nargs;
|
||||
PUSH(_result);
|
||||
break;
|
||||
|
||||
+3
-1
@@ -19,7 +19,7 @@ typedef struct {
|
||||
typedef VEC(spl_vm_val_t) spl_stack_vec_t;
|
||||
typedef VEC(spl_callframe_t) spl_frame_vec_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct spl_vm {
|
||||
spl_stack_vec_t stacks;
|
||||
spl_frame_vec_t frames;
|
||||
uintptr_t gp; // global pointer
|
||||
@@ -52,6 +52,8 @@ void spl_vm_init_ex(spl_vm_t *vm, int stack_size, int call_depth);
|
||||
/* Free dynamically allocated memory in VM */
|
||||
void spl_vm_drop(spl_vm_t *vm);
|
||||
|
||||
int spl_vm_addr_valid(uintptr_t p, usize size);
|
||||
|
||||
int spl_vm_load_prog(spl_vm_t *vm, spl_prog_t *prog);
|
||||
int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv, const char **envp);
|
||||
|
||||
|
||||
+18
-8
@@ -148,6 +148,7 @@ static spl_ast_node_ref_t parse_param_decl_impl(parser_t *p);
|
||||
static spl_ast_node_ref_t parse_var_pattern(parser_t *p);
|
||||
static spl_ast_node_ref_t parse_match_pattern(parser_t *p);
|
||||
|
||||
static spl_ast_node_ref_t parse_cast(parser_t *p);
|
||||
static spl_ast_node_ref_t parse_prefix(parser_t *p);
|
||||
static spl_ast_node_ref_t parse_postfix(parser_t *p);
|
||||
static spl_ast_node_ref_t parse_primary(parser_t *p);
|
||||
@@ -1215,7 +1216,7 @@ static spl_binary_op_t token_to_binary_op(spl_tok_type_t tt) {
|
||||
}
|
||||
|
||||
static spl_ast_node_ref_t parse_expr_prec(parser_t *p, int min_prec) {
|
||||
spl_ast_node_ref_t left = parse_prefix(p);
|
||||
spl_ast_node_ref_t left = parse_cast(p);
|
||||
if (p->failed)
|
||||
return left;
|
||||
|
||||
@@ -1259,6 +1260,22 @@ static spl_ast_node_ref_t parse_expr(parser_t *p) {
|
||||
return parse_expr_prec(p, 1); // 最低优先级
|
||||
}
|
||||
|
||||
static spl_ast_node_ref_t parse_cast(parser_t *p) {
|
||||
spl_ast_node_ref_t expr = parse_prefix(p);
|
||||
while (!p->failed) {
|
||||
const spl_tok_t *t = peek(p);
|
||||
if (!t || t->type != KW_AS || p->stop_as)
|
||||
break;
|
||||
advance(p);
|
||||
spl_ast_node_ref_t type = parse_type_expr(p);
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_CAST, t);
|
||||
node_at(p->ast, ref)->cast.expr = expr;
|
||||
node_at(p->ast, ref)->cast.type = type;
|
||||
expr = ref;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
static spl_ast_node_ref_t parse_prefix(parser_t *p) {
|
||||
const spl_tok_t *t = peek(p);
|
||||
if (!t)
|
||||
@@ -1393,13 +1410,6 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
|
||||
node_at(p->ast, ref)->index.index = begin;
|
||||
expr = ref;
|
||||
}
|
||||
} else if (t->type == KW_AS && !p->stop_as) {
|
||||
advance(p);
|
||||
spl_ast_node_ref_t type = parse_type_expr(p);
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_CAST, t);
|
||||
node_at(p->ast, ref)->cast.expr = expr;
|
||||
node_at(p->ast, ref)->cast.type = type;
|
||||
expr = ref;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
+15
-7
@@ -152,7 +152,12 @@ static uint8_t vm_kind_of(spl_ir2vm_t *ctx, spl_type_id_t tid) {
|
||||
}
|
||||
}
|
||||
|
||||
static spl_type_id_t ir_result_tid(const spl_ir_node_t *n) {
|
||||
/* 计算 IR 节点的"值类型"。
|
||||
* 语义区分:
|
||||
* mem.offset(elem_t, ptr, off) → 结果类型 *elem_t
|
||||
* mem.field(agg_t, base, idx) → 结果类型 *field_t
|
||||
* 这两个 builder 的 .tid 存的是 pointee / aggregate,不能直接当结果类型用。 */
|
||||
static spl_type_id_t ir_result_tid(spl_ir2vm_t *ctx, const spl_ir_node_t *n) {
|
||||
switch (n->kind) {
|
||||
case SPL_IR_ARITH_ADD:
|
||||
case SPL_IR_ARITH_SUB:
|
||||
@@ -194,9 +199,12 @@ static spl_type_id_t ir_result_tid(const spl_ir_node_t *n) {
|
||||
case SPL_IR_MEM_LOAD:
|
||||
return n->mem_load.tid;
|
||||
case SPL_IR_MEM_OFFSET:
|
||||
return n->mem_offset.tid;
|
||||
case SPL_IR_MEM_FIELD_PTR:
|
||||
return n->mem_field_ptr.tid;
|
||||
return spl_type_builder_ptr((spl_type_t *)ctx->type, n->mem_offset.tid);
|
||||
case SPL_IR_MEM_FIELD_PTR: {
|
||||
spl_type_id_t field =
|
||||
ir_agg_field_tid(ctx, n->mem_field_ptr.tid, n->mem_field_ptr.field_idx);
|
||||
return spl_type_builder_ptr((spl_type_t *)ctx->type, field);
|
||||
}
|
||||
case SPL_IR_TYPE_CONST:
|
||||
return n->type_const.tid;
|
||||
case SPL_IR_TYPE_BITSIZEOF:
|
||||
@@ -304,7 +312,7 @@ static void frame_build(frame_layout_t *fl, spl_ir2vm_t *ctx, spl_ir_func_ref_t
|
||||
|
||||
for (usize i = 1; i < n; ++i) {
|
||||
const spl_ir_node_t *node = &vec_at(f->nodes, i);
|
||||
if (ir_result_tid(node)) {
|
||||
if (ir_result_tid(ctx, node)) {
|
||||
vec_at(fl->slots, i).result_off = off;
|
||||
off += sizeof(spl_vm_val_t);
|
||||
}
|
||||
@@ -786,7 +794,7 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
for (usize i = 0; i < nargs; ++i) {
|
||||
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
|
||||
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
|
||||
spl_type_id_t ptid = ir_result_tid(pn);
|
||||
spl_type_id_t ptid = ir_result_tid(ctx, pn);
|
||||
uint8_t pk = vm_kind_of(ctx, ptid);
|
||||
cg_load_slot(cg, pref, pk);
|
||||
}
|
||||
@@ -802,7 +810,7 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
for (usize i = 0; i < nargs; ++i) {
|
||||
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
|
||||
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
|
||||
spl_type_id_t ptid = ir_result_tid(pn);
|
||||
spl_type_id_t ptid = ir_result_tid(ctx, pn);
|
||||
uint8_t pk = vm_kind_of(ctx, ptid);
|
||||
cg_load_slot(cg, pref, pk);
|
||||
}
|
||||
|
||||
+6
-3
@@ -651,9 +651,11 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
switch (n->kind) {
|
||||
|
||||
case SPL_AST_EXPR_UNARY: {
|
||||
/* & 与 .* 的结果类型由操作数决定,不能靠 expected 反向定型 */
|
||||
/* ADDRESS / DEREF 的结果类型由操作数决定,不能用 expected 反向定型。
|
||||
* 但不能直接 return ——— 那会绕过 expected 兼容性检查。
|
||||
* 走 break 落到兜底:infer 后做 is_subtype / comptime 判定。 */
|
||||
if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF)
|
||||
return sema_infer(sema, ref);
|
||||
break;
|
||||
if (!sema_coerce(sema, n->unary.operand, expected))
|
||||
return 0;
|
||||
n->resolved_lang_tid = expected;
|
||||
@@ -1213,7 +1215,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
for (usize i = 0; i < nargs && i < fixed; ++i) {
|
||||
spl_lang_type_id_t pt =
|
||||
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i);
|
||||
sema_coerce(sema, vec_at(n->call.args, i), pt);
|
||||
if (!sema_coerce(sema, vec_at(n->call.args, i), pt))
|
||||
return 0;
|
||||
}
|
||||
/* varargs:默认提升到 isize */
|
||||
if (has_varargs) {
|
||||
|
||||
Reference in new issue
Block a user