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:
M | libscript/debug.c | | | 66 | +++++++++++++++++++++++++++++++++++++++++++++--------------------- |
M | libscript/libscript.c | | | 91 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
M | libscript/libscript.h | | | 86 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- |
M | scriptvm/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++;