script

script.git
git clone git://git.lenczewski.org/script.git
Log | Files | Refs

commit 6a5f2ced150f268918dd720df39df2e303beeea9
parent 5492185850c59c6ea42c385edc684ecdf7e32646
Author: MikoĊ‚aj Lenczewski <mblenczewski@gmail.com>
Date:   Tue, 21 Jan 2025 16:51:05 +0000

Add additional primitive types

Add more C-like datatypes to both script and script_ir.

Diffstat:
Mlibscript/debug.c | 66+++++++++++++++++++++++++++++++++++++++++++++---------------------
Mlibscript/libscript.c | 91++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mlibscript/libscript.h | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mscriptvm/scriptvm.c | 172+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
4 files changed, 291 insertions(+), 124 deletions(-)

diff --git a/libscript/debug.c b/libscript/debug.c @@ -7,7 +7,22 @@ dump_token_type_str(enum script_token_type type) [SCR_TOKEN_EOF] = "EOF", [SCR_TOKEN_IDENT] = "IDENT", [SCR_TOKEN_LITERAL_INT] = "LITERAL_INT", + + [SCR_TOKEN_U8] = "U8", + [SCR_TOKEN_U16] = "U16", + [SCR_TOKEN_U32] = "U32", [SCR_TOKEN_U64] = "U64", + + [SCR_TOKEN_S8] = "S8", + [SCR_TOKEN_S16] = "S16", + [SCR_TOKEN_S32] = "S32", + [SCR_TOKEN_S64] = "S64", + + [SCR_TOKEN_F32] = "F32", + [SCR_TOKEN_F64] = "F64", + + [SCR_TOKEN_C8] = "C8", + [SCR_TOKEN_RETURN] = "RETURN", [SCR_TOKEN_LPAREN] = "(", [SCR_TOKEN_RPAREN] = ")", @@ -73,20 +88,24 @@ dump_token_stream(struct compile_ctx *ctx) static void dump_typeinfo(struct compile_ctx *ctx, struct script_typeinfo *typeinfo, size_t indent) { + static char const *type_strs[] = { + [SCR_TYPE_U8] = "U8", + [SCR_TYPE_U16] = "U16", + [SCR_TYPE_U32] = "U32", + [SCR_TYPE_U64] = "U64", + + [SCR_TYPE_S8] = "S8", + [SCR_TYPE_S16] = "S16", + [SCR_TYPE_S32] = "S32", + [SCR_TYPE_S64] = "S64", + }; + #define leader(indent) \ for (size_t i = 0; i < indent; i++) dbglog(ctx, " "); - switch (typeinfo->type) { - case SCR_TYPE_U64: { - static char const *type_str[] = { - [SCR_TYPE_U64] = "U64", - }; - - leader(indent) - dbglog(ctx, "Typeinfo { type: %s, size: %zu, alignment: %zu }\n", - type_str[typeinfo->type], typeinfo->size, typeinfo->alignment); - } break; - } + leader(indent) + dbglog(ctx, "Typeinfo { type: %s, size: %zu, alignment: %zu }\n", + type_strs[typeinfo->type], typeinfo->size, typeinfo->alignment); #undef leader } @@ -105,7 +124,7 @@ dump_symbol(struct compile_ctx *ctx, struct script_symbol *sym, size_t indent) case SCR_SYMBOL_VARIABLE: leader(indent) dbglog(ctx, "variable: global: %d, ident: %.*s, addr: 0x%lx\n", - sym->variable.parent == NULL, (int) len, str, sym->variable.addr); + sym->parent_scope == NULL, (int) len, str, sym->variable.addr); leader(indent + 1) dbglog(ctx, "typeinfo:\n"); @@ -183,14 +202,12 @@ dump_stmt(struct compile_ctx *ctx, struct script_stmt *node, size_t indent) char *str; size_t len; - struct script_list *list; switch (node->type) { case SCR_STMT_BLOCK: leader(indent) dbglog(ctx, "block\n"); - list = &node->block.children; - SCRIPT_LIST_ITER(list) { + SCRIPT_LIST_ITER(&node->block.children) { struct script_stmt *child = SCRIPT_FROM_NODE(it, struct script_stmt, list_node); @@ -268,7 +285,18 @@ static inline char const * dump_ir_typeinfo_str(struct script_ir_typeinfo *typeinfo) { switch (typeinfo->type) { + case SCR_IR_TYPE_U8: return "U8"; + case SCR_IR_TYPE_U16: return "U16"; + case SCR_IR_TYPE_U32: return "U32"; case SCR_IR_TYPE_U64: return "U64"; + case SCR_IR_TYPE_S8: return "S8"; + case SCR_IR_TYPE_S16: return "S16"; + case SCR_IR_TYPE_S32: return "S32"; + case SCR_IR_TYPE_S64: return "S64"; + case SCR_IR_TYPE_F32: return "F32"; + case SCR_IR_TYPE_F64: return "F64"; + case SCR_IR_TYPE_C8: return "C8"; + case SCR_IR_TYPE_PTR: return "PTR"; } } @@ -278,9 +306,6 @@ dump_ir_operands(struct compile_ctx *ctx, struct script_ir_operand *buf, size_t for (size_t i = 0; i < len; i++) { struct script_ir_operand *operand = &buf[i]; - char *str; - size_t str_len; - switch (operand->type) { case SCR_IR_OPERAND_LITERAL: dbglog(ctx, "LITERAL{0x%" PRIx64 "}", operand->literal); @@ -290,9 +315,8 @@ dump_ir_operands(struct compile_ctx *ctx, struct script_ir_operand *buf, size_t dbglog(ctx, "POINTER{0x%" PRIx64 "}", operand->pointer); break; - case SCR_IR_OPERAND_IDENT: - ident_pool_get(&ctx->ident_pool, operand->ident, &str, &str_len); - dbglog(ctx, "IDENT{%.*s}", (int) str_len, str); + case SCR_IR_OPERAND_ADDRESS: + dbglog(ctx, "ADDRESS{0x%" PRIx64 "}", operand->address); break; } diff --git a/libscript/libscript.c b/libscript/libscript.c @@ -9,12 +9,44 @@ try_tokenise_keyword(char *src, char *end, struct script_token *out) { size_t len = end - src; - if (len == strlen("return") && strncmp(src, "return", len) == 0) { - out->type = SCR_TOKEN_RETURN; + if (len == strlen("u8") && strncmp(src, "u8", len) == 0) { + out->type = SCR_TOKEN_U8; + return 0; + } else if (len == strlen("u16") && strncmp(src, "u16", len) == 0) { + out->type = SCR_TOKEN_U16; + return 0; + } else if (len == strlen("u32") && strncmp(src, "u32", len) == 0) { + out->type = SCR_TOKEN_U32; return 0; } else if (len == strlen("u64") && strncmp(src, "u64", len) == 0) { out->type = SCR_TOKEN_U64; return 0; + } else if (len == strlen("s8") && strncmp(src, "s8", len) == 0) { + out->type = SCR_TOKEN_S8; + return 0; + } else if (len == strlen("s16") && strncmp(src, "s16", len) == 0) { + out->type = SCR_TOKEN_S16; + return 0; + } else if (len == strlen("s32") && strncmp(src, "s32", len) == 0) { + out->type = SCR_TOKEN_S32; + return 0; + } else if (len == strlen("s64") && strncmp(src, "s64", len) == 0) { + out->type = SCR_TOKEN_S64; + return 0; + } else if (len == strlen("f32") && strncmp(src, "f32", len) == 0) { + out->type = SCR_TOKEN_F32; + return 0; + } else if (len == strlen("f64") && strncmp(src, "f64", len) == 0) { + out->type = SCR_TOKEN_F64; + return 0; + } else if (len == strlen("c8") && strncmp(src, "c8", len) == 0) { + out->type = SCR_TOKEN_C8; + return 0; + } + + if (len == strlen("return") && strncmp(src, "return", len) == 0) { + out->type = SCR_TOKEN_RETURN; + return 0; } return -1; @@ -183,20 +215,23 @@ expect(struct compile_ctx *ctx, enum script_token_type expected) static inline int is_primitive_typeinfo(struct script_typeinfo *typeinfo) { - switch (typeinfo->type) { - case SCR_TYPE_U64: - return 1; + (void) typeinfo; - default: - return 0; - } + return 1; } static struct script_typeinfo * primitive_typeinfo(enum script_type type) { static struct script_typeinfo typeinfos[] = { + [SCR_TYPE_U8] = { .type = SCR_TYPE_U8, .size = 1, .alignment = 1, }, + [SCR_TYPE_U16] = { .type = SCR_TYPE_U16, .size = 2, .alignment = 2, }, + [SCR_TYPE_U32] = { .type = SCR_TYPE_U32, .size = 4, .alignment = 4, }, [SCR_TYPE_U64] = { .type = SCR_TYPE_U64, .size = 8, .alignment = 8, }, + [SCR_TYPE_S8] = { .type = SCR_TYPE_S8, .size = 1, .alignment = 1, }, + [SCR_TYPE_S16] = { .type = SCR_TYPE_S16, .size = 2, .alignment = 2, }, + [SCR_TYPE_S32] = { .type = SCR_TYPE_S32, .size = 4, .alignment = 4, }, + [SCR_TYPE_S64] = { .type = SCR_TYPE_S64, .size = 8, .alignment = 8, }, }; return &typeinfos[type]; @@ -209,11 +244,10 @@ literal_typeinfo(struct compile_ctx *ctx, enum script_token_type type) case SCR_TOKEN_LITERAL_INT: // TODO: better rules surrounding literal types return primitive_typeinfo(SCR_TYPE_U64); - default: { + default: dbglog(ctx, "error: invalid token type has no type info: %s\n", dump_token_type_str(type)); return NULL; - } break; } } @@ -236,8 +270,10 @@ parse_typeinfo(struct compile_ctx *ctx) } static struct script_expr * -parse_expr(struct compile_ctx *ctx) +parse_expr(struct compile_ctx *ctx, struct script_typeinfo *expected_typeinfo) { + (void) expected_typeinfo; /* TODO: use this hint to upcast types if needed */ + struct script_expr *stack[128]; size_t i = 0; @@ -335,7 +371,7 @@ parse_return(struct compile_ctx *ctx, struct script_symbol *parent) stmt->type = SCR_STMT_RET; expect(ctx, SCR_TOKEN_RETURN); - stmt->ret.expr = parse_expr(ctx); + stmt->ret.expr = parse_expr(ctx, NULL); /* TODO: validate that return type is the same as parent scope function type */ @@ -345,14 +381,14 @@ parse_return(struct compile_ctx *ctx, struct script_symbol *parent) } static struct script_stmt * -parse_vardecl(struct compile_ctx *ctx, struct script_symbol *parent) +parse_vardecl(struct compile_ctx *ctx, struct script_symbol *parent_scope) { struct script_symbol *sym = symbol_table_push(&ctx->symtab); assert(sym); sym->type = SCR_SYMBOL_VARIABLE; + sym->parent_scope = parent_scope; sym->list_node.prev = sym->list_node.next = NULL; - sym->variable.parent = parent; struct script_stmt *stmt = ALLOC_SIZED(&ctx->arena, struct script_stmt); assert(stmt); @@ -365,7 +401,7 @@ parse_vardecl(struct compile_ctx *ctx, struct script_symbol *parent) sym->variable.addr = symbol_table_next_addr(&ctx->symtab, sym->variable.typeinfo); expect(ctx, SCR_TOKEN_EQUALS); - stmt->vardecl.expr = parse_expr(ctx); + stmt->vardecl.expr = parse_expr(ctx, sym->variable.typeinfo); assert(stmt->vardecl.typeinfo == stmt->vardecl.expr->typeinfo); @@ -399,7 +435,17 @@ static inline struct script_ir_typeinfo * primitive_ir_typeinfo(enum script_ir_type type) { static struct script_ir_typeinfo typeinfos[] = { + [SCR_IR_TYPE_U8] = { .type = SCR_IR_TYPE_U8, .size = 1, .alignment = 1, }, + [SCR_IR_TYPE_U16] = { .type = SCR_IR_TYPE_U16, .size = 2, .alignment = 2, }, + [SCR_IR_TYPE_U32] = { .type = SCR_IR_TYPE_U32, .size = 4, .alignment = 4, }, [SCR_IR_TYPE_U64] = { .type = SCR_IR_TYPE_U64, .size = 8, .alignment = 8, }, + [SCR_IR_TYPE_S8] = { .type = SCR_IR_TYPE_S8, .size = 1, .alignment = 1, }, + [SCR_IR_TYPE_S16] = { .type = SCR_IR_TYPE_S16, .size = 2, .alignment = 2, }, + [SCR_IR_TYPE_S32] = { .type = SCR_IR_TYPE_S32, .size = 4, .alignment = 4, }, + [SCR_IR_TYPE_S64] = { .type = SCR_IR_TYPE_S64, .size = 8, .alignment = 8, }, + [SCR_IR_TYPE_F32] = { .type = SCR_IR_TYPE_F32, .size = 4, .alignment = 4, }, + [SCR_IR_TYPE_F64] = { .type = SCR_IR_TYPE_F64, .size = 8, .alignment = 8, }, + [SCR_IR_TYPE_C8] = { .type = SCR_IR_TYPE_C8, .size = 1, .alignment = 1, }, }; return &typeinfos[type]; @@ -409,7 +455,20 @@ static inline struct script_ir_typeinfo * typeinfo_to_ir_typeinfo(struct script_typeinfo *typeinfo) { switch (typeinfo->type) { + case SCR_TYPE_U8: return primitive_ir_typeinfo(SCR_IR_TYPE_U8); + case SCR_TYPE_U16: return primitive_ir_typeinfo(SCR_IR_TYPE_U16); + case SCR_TYPE_U32: return primitive_ir_typeinfo(SCR_IR_TYPE_U32); case SCR_TYPE_U64: return primitive_ir_typeinfo(SCR_IR_TYPE_U64); + + case SCR_TYPE_S8: return primitive_ir_typeinfo(SCR_IR_TYPE_S8); + case SCR_TYPE_S16: return primitive_ir_typeinfo(SCR_IR_TYPE_S16); + case SCR_TYPE_S32: return primitive_ir_typeinfo(SCR_IR_TYPE_S32); + case SCR_TYPE_S64: return primitive_ir_typeinfo(SCR_IR_TYPE_S64); + + case SCR_TYPE_F32: return primitive_ir_typeinfo(SCR_IR_TYPE_F32); + case SCR_TYPE_F64: return primitive_ir_typeinfo(SCR_IR_TYPE_F64); + + case SCR_TYPE_C8: return primitive_ir_typeinfo(SCR_IR_TYPE_C8); } } @@ -421,6 +480,7 @@ emit_expr(struct compile_ctx *ctx, struct script_ir_inst *scratch, struct script case SCR_EXPR_IDENT: sym = symbol_table_find(&ctx->symtab, expr->ident); assert(sym); + assert(sym->type == SCR_SYMBOL_VARIABLE); scratch->opcode = SCR_IR_LOAD; scratch->typeinfo = typeinfo_to_ir_typeinfo(expr->typeinfo); @@ -483,6 +543,7 @@ emit_vardecl(struct compile_ctx *ctx, struct script_ir_inst *scratch, struct scr struct script_symbol *sym = symbol_table_find(&ctx->symtab, stmt->vardecl.ident); assert(sym); + assert(sym->type == SCR_SYMBOL_VARIABLE); if (emit_expr(ctx, scratch, stmt->vardecl.expr) < 0) return -1; diff --git a/libscript/libscript.h b/libscript/libscript.h @@ -53,7 +53,21 @@ enum script_token_type { SCR_TOKEN_LITERAL_INT, /* keywords */ + SCR_TOKEN_U8, + SCR_TOKEN_U16, + SCR_TOKEN_U32, SCR_TOKEN_U64, + + SCR_TOKEN_S8, + SCR_TOKEN_S16, + SCR_TOKEN_S32, + SCR_TOKEN_S64, + + SCR_TOKEN_F32, + SCR_TOKEN_F64, + + SCR_TOKEN_C8, + SCR_TOKEN_RETURN, /* punctuation */ @@ -94,7 +108,20 @@ struct script_token { */ enum script_type { + SCR_TYPE_U8, + SCR_TYPE_U16, + SCR_TYPE_U32, SCR_TYPE_U64, + + SCR_TYPE_S8, + SCR_TYPE_S16, + SCR_TYPE_S32, + SCR_TYPE_S64, + + SCR_TYPE_F32, + SCR_TYPE_F64, + + SCR_TYPE_C8, }; struct script_typeinfo { @@ -104,26 +131,6 @@ struct script_typeinfo { size_t alignment; }; -enum script_symbol_type { - SCR_SYMBOL_VARIABLE, -}; - -struct script_symbol { - enum script_symbol_type type; - - struct script_flystr ident; - - union { - struct { - struct script_symbol *parent; - struct script_typeinfo *typeinfo; - uintptr_t addr; - } variable; - }; - - struct script_list_node list_node; -}; - enum script_expr_type { SCR_EXPR_IDENT, SCR_EXPR_LITERAL_INT, @@ -181,6 +188,26 @@ struct script_stmt { struct script_list_node list_node; }; +enum script_symbol_type { + SCR_SYMBOL_VARIABLE, +}; + +struct script_symbol { + enum script_symbol_type type; + + struct script_flystr ident; + struct script_symbol *parent_scope; + + union { + struct { + struct script_typeinfo *typeinfo; + uintptr_t addr; + } variable; + }; + + struct script_list_node list_node; +}; + /* ir * =========================================================================== */ @@ -200,7 +227,22 @@ enum script_ir_opcode { }; enum script_ir_type { + SCR_IR_TYPE_U8, + SCR_IR_TYPE_U16, + SCR_IR_TYPE_U32, SCR_IR_TYPE_U64, + + SCR_IR_TYPE_S8, + SCR_IR_TYPE_S16, + SCR_IR_TYPE_S32, + SCR_IR_TYPE_S64, + + SCR_IR_TYPE_F32, + SCR_IR_TYPE_F64, + + SCR_IR_TYPE_C8, + + SCR_IR_TYPE_PTR, }; struct script_ir_typeinfo { @@ -211,7 +253,7 @@ struct script_ir_typeinfo { enum script_ir_operand_type { SCR_IR_OPERAND_LITERAL, SCR_IR_OPERAND_POINTER, - SCR_IR_OPERAND_IDENT, + SCR_IR_OPERAND_ADDRESS, }; struct script_ir_operand { @@ -219,7 +261,7 @@ struct script_ir_operand { union { uint64_t literal; uintptr_t pointer; - struct script_flystr ident; + uintptr_t address; }; }; diff --git a/scriptvm/scriptvm.c b/scriptvm/scriptvm.c @@ -116,12 +116,61 @@ parse_opts(int argc, char **argv) static void emit(int fd, struct script_program const *prog) { - (void) fd; - (void) prog; + static char const *opcode_str[] = { + [SCR_IR_LOAD] = "LOAD", + [SCR_IR_STORE] = "STORE", + [SCR_IR_PUSH] = "PUSH", + [SCR_IR_POP] = "POP", + [SCR_IR_RET] = "RET", + [SCR_IR_ADD] = "ADD", + [SCR_IR_SUB] = "SUB", + [SCR_IR_MUL] = "MUL", + [SCR_IR_DIV] = "DIV", + }; + + static char const *typeinfo_str[] = { + [SCR_IR_TYPE_U8] = "U8", + [SCR_IR_TYPE_U16] = "U16", + [SCR_IR_TYPE_U32] = "U32", + [SCR_IR_TYPE_U64] = "U64", + [SCR_IR_TYPE_S8] = "S8", + [SCR_IR_TYPE_S16] = "S16", + [SCR_IR_TYPE_S32] = "S32", + [SCR_IR_TYPE_S64] = "S64", + [SCR_IR_TYPE_F32] = "F32", + [SCR_IR_TYPE_F64] = "F64", + [SCR_IR_TYPE_C8] = "C8", + [SCR_IR_TYPE_PTR] = "PTR", + }; + + for (size_t i = 0; i < prog->instructions.len; i++) { + struct script_ir_inst *inst = prog->instructions.ptr + i; + + dprintf(fd, "[%03zu] %7s<%s> ", + i, opcode_str[inst->opcode], typeinfo_str[inst->typeinfo->type]); + + for (size_t j = 0; j < inst->operand_count; j++) { + struct script_ir_operand *operand = &inst->operands[j]; + + switch (operand->type) { + case SCR_IR_OPERAND_LITERAL: + dprintf(fd, "LIT{0x%" PRIx64 "}", operand->literal); + break; + + case SCR_IR_OPERAND_POINTER: + dprintf(fd, "PTR{0x%" PRIx64 "}", operand->pointer); + break; + + case SCR_IR_OPERAND_ADDRESS: + dprintf(fd, "ADDR{0x%" PRIx64 "}", operand->address); + break; + } - // TODO: walk the ast and emit bytecode for it + dprintf(fd, ","); + } - fprintf(stderr, "TODO!!!\n"); + dprintf(fd, "\n"); + } } struct vm_state { @@ -184,65 +233,52 @@ load(struct vm_state *vm, struct script_ir_typeinfo *typeinfo, uintptr_t addr) } static inline void -store(struct vm_state *vm, struct script_ir_typeinfo *typeinfo, uintptr_t addr) +store(struct vm_state *vm, struct script_ir_typeinfo *typeinfo, uintptr_t addr, uint64_t val) { - uint64_t value = pop(vm, typeinfo); - assert(addr + typeinfo->size < vm->heap.len); unsigned char *storage = vm->heap.ptr + addr; assert(IS_ALIGNED((uintptr_t) storage, typeinfo->alignment)); - memcpy(storage, &value, typeinfo->size); -} - -static inline uint64_t -vmadd(struct script_ir_typeinfo *typeinfo, uint64_t lhs, uint64_t rhs) -{ - switch (typeinfo->type) { - case SCR_IR_TYPE_U64: - return lhs + rhs; - } -} - -static inline uint64_t -vmsub(struct script_ir_typeinfo *typeinfo, uint64_t lhs, uint64_t rhs) -{ - switch (typeinfo->type) { - case SCR_IR_TYPE_U64: - return lhs - rhs; - } + memcpy(storage, &val, typeinfo->size); } static inline uint64_t -vmmul(struct script_ir_typeinfo *typeinfo, uint64_t lhs, uint64_t rhs) +arithmetic(enum script_ir_opcode opcode, struct script_ir_typeinfo *typeinfo, + uint64_t lhs, uint64_t rhs) { - switch (typeinfo->type) { - case SCR_IR_TYPE_U64: - return lhs * rhs; +#define map(lhs, rhs, op, Tin, Tout) \ + ((Tout) (((Tin) (lhs)) op ((Tin) (rhs)))) + +#define vmop(op) \ + switch (typeinfo->type) { \ + case SCR_IR_TYPE_U8: res = map(lhs, rhs, op, uint8_t, uint64_t); \ + case SCR_IR_TYPE_U16: res = map(lhs, rhs, op, uint16_t, uint64_t); \ + case SCR_IR_TYPE_U32: res = map(lhs, rhs, op, uint32_t, uint64_t); \ + case SCR_IR_TYPE_U64: res = map(lhs, rhs, op, uint64_t, uint64_t); \ + case SCR_IR_TYPE_S8: res = map(lhs, rhs, op, int8_t, uint64_t); \ + case SCR_IR_TYPE_S16: res = map(lhs, rhs, op, int16_t, uint64_t); \ + case SCR_IR_TYPE_S32: res = map(lhs, rhs, op, int32_t, uint64_t); \ + case SCR_IR_TYPE_S64: res = map(lhs, rhs, op, int64_t, uint64_t); \ + case SCR_IR_TYPE_F32: res = map(lhs, rhs, op, float, uint64_t); \ + case SCR_IR_TYPE_F64: res = map(lhs, rhs, op, double, uint64_t); \ + case SCR_IR_TYPE_C8: res = map(lhs, rhs, op, uint8_t, uint64_t); \ + case SCR_IR_TYPE_PTR: res = map(lhs, rhs, op, uintptr_t, uint64_t); \ } -} - -static inline uint64_t -vmdiv(struct script_ir_typeinfo *typeinfo, uint64_t lhs, uint64_t rhs) -{ - switch (typeinfo->type) { - case SCR_IR_TYPE_U64: - return lhs / rhs; - } -} - -static inline void -arithmetic(struct vm_state *vm, enum script_ir_opcode opcode, - struct script_ir_typeinfo *typeinfo) -{ - uint64_t lhs = pop(vm, typeinfo); - uint64_t rhs = pop(vm, typeinfo); uint64_t res; switch (opcode) { - case SCR_IR_ADD: res = vmadd(typeinfo, lhs, rhs); break; - case SCR_IR_SUB: res = vmsub(typeinfo, lhs, rhs); break; - case SCR_IR_MUL: res = vmmul(typeinfo, lhs, rhs); break; - case SCR_IR_DIV: res = vmdiv(typeinfo, lhs, rhs); break; + case SCR_IR_ADD: { + vmop(+) + } break; + case SCR_IR_SUB: { + vmop(-) + } break; + case SCR_IR_MUL: { + vmop(*) + } break; + case SCR_IR_DIV: { + vmop(/) + } break; + default: assert(0); } @@ -250,7 +286,7 @@ arithmetic(struct vm_state *vm, enum script_ir_opcode opcode, fprintf(stderr, "arith: %d, lhs: 0x%" PRIx64 ", rhs: 0x%" PRIx64 ", " "res: 0x%" PRIx64 "\n", opcode, lhs, rhs, res); - push(vm, typeinfo, res); + return res; } static uint64_t @@ -263,41 +299,45 @@ interpret(struct vm_state *vm, struct script_program *program) fprintf(stderr, "inst: %d\n", inst->opcode); switch (inst->opcode) { - case SCR_IR_LOAD: + case SCR_IR_LOAD: { assert(inst->operand_count); assert(inst->operands[0].type == SCR_IR_OPERAND_POINTER); load(vm, inst->typeinfo, inst->operands[0].pointer); - break; + } break; - case SCR_IR_STORE: + case SCR_IR_STORE: { assert(inst->operand_count); assert(inst->operands[0].type == SCR_IR_OPERAND_POINTER); - store(vm, inst->typeinfo, inst->operands[0].pointer); - break; + uint64_t value = pop(vm, inst->typeinfo); + store(vm, inst->typeinfo, inst->operands[0].pointer, value); + } break; - case SCR_IR_PUSH: + case SCR_IR_PUSH: { assert(inst->operand_count); assert(inst->operands[0].type == SCR_IR_OPERAND_LITERAL); push(vm, inst->typeinfo, inst->operands[0].literal); - break; + } break; - case SCR_IR_POP: + case SCR_IR_POP: { assert(inst->operand_count == 0); (void) pop(vm, inst->typeinfo); - break; + } break; - case SCR_IR_RET: + case SCR_IR_RET: { assert(inst->operand_count == 0); vm->r0 = pop(vm, inst->typeinfo); - break; + } break; case SCR_IR_ADD: case SCR_IR_SUB: case SCR_IR_MUL: - case SCR_IR_DIV: + case SCR_IR_DIV: { assert(inst->operand_count == 0); - arithmetic(vm, inst->opcode, inst->typeinfo); - break; + uint64_t lhs = pop(vm, inst->typeinfo); + uint64_t rhs = pop(vm, inst->typeinfo); + uint64_t res = arithmetic(inst->opcode, inst->typeinfo, lhs, rhs); + push(vm, inst->typeinfo, res); + } break; } vm->pc++;