Refactor l2vm
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#define ERR_IMAGE_MAGIC 1
|
||||
#define ERR_IMAGE_INDEX 2
|
||||
#define ERR_IMAGE_IO 3
|
||||
#define ERR_OPCODE_UNDEFINED 4
|
||||
#define ERR_RANGE 5
|
||||
#define ERR_SYMBOL_UNDEFINED 6
|
||||
#define ERR_OUT_OF_MEMORY 7
|
||||
#define ERR_OPERAND_TYPE 8
|
||||
#define ERR_STACK_UNDERFLOW 9
|
||||
#define ERR_STACK_OVERFLOW 10
|
||||
#define ERR_NOT_FOUND 11
|
||||
|
||||
const char *vm_strerror(int e);
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "vector.h"
|
||||
|
||||
struct vm_state;
|
||||
struct vm_ref_entry;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// uint64_t only
|
||||
struct stack {
|
||||
size_t sp, size;
|
||||
uint64_t *data;
|
||||
};
|
||||
|
||||
int stack_init(struct stack *st, size_t size);
|
||||
void stack_free(struct stack *st);
|
||||
int stack_push(struct stack *st, uint64_t w);
|
||||
int stack_pop(struct stack *st, uint64_t *w);
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
#define MAXARG 12
|
||||
#define MAXLOC 64
|
||||
|
||||
#define REF_NATIVE (1 << 0)
|
||||
struct vm_ref_entry {
|
||||
size_t unit_index;
|
||||
int flags;
|
||||
union {
|
||||
size_t ref_index;
|
||||
uintptr_t ref_native;
|
||||
};
|
||||
};
|
||||
|
||||
struct vm_func_entry {
|
||||
size_t argc, local_count;
|
||||
uint64_t local_regs[MAXLOC];
|
||||
uint64_t arg_regs[MAXARG];
|
||||
uint32_t *bytecode;
|
||||
};
|
||||
|
||||
struct vm_unit {
|
||||
struct vector ref_table;
|
||||
struct vector functions;
|
||||
|
||||
uint64_t *global_pool;
|
||||
size_t global_pool_size;
|
||||
|
||||
int is_loaded;
|
||||
};
|
||||
|
||||
struct vm_func_entry *unit_add_function(struct vm_unit *u);
|
||||
struct vm_ref_entry *unit_add_ref(struct vm_unit *u);
|
||||
void unit_free(struct vm_unit *u);
|
||||
@@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
#include "op.h"
|
||||
|
||||
#define FLAG_REF (1ULL << 63)
|
||||
+23
-51
@@ -1,76 +1,48 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "vector.h"
|
||||
#include "stack.h"
|
||||
|
||||
#define LIB_LOCAL ((size_t) -1)
|
||||
|
||||
#define MAXARG 12
|
||||
#define MAXLOC 64
|
||||
#define FLAG_REF (1ULL << 63)
|
||||
|
||||
struct vm_value;
|
||||
|
||||
#define REF_NATIVE (1 << 0)
|
||||
struct vm_ref_entry {
|
||||
size_t unit_index;
|
||||
int flags;
|
||||
union {
|
||||
size_t ref_index;
|
||||
uintptr_t ref_native;
|
||||
};
|
||||
};
|
||||
|
||||
struct vm_func_entry {
|
||||
size_t argc, local_count;
|
||||
uint64_t local_regs[MAXLOC];
|
||||
uint64_t arg_regs[MAXARG];
|
||||
uint32_t *bytecode;
|
||||
};
|
||||
|
||||
struct vm_unit {
|
||||
struct vector ref_table;
|
||||
struct vector functions;
|
||||
|
||||
uint64_t *global_pool;
|
||||
size_t global_pool_size;
|
||||
|
||||
int is_loaded;
|
||||
};
|
||||
static inline uint64_t encode_ref(struct vm_value *ref) {
|
||||
uintptr_t addr = (uintptr_t) ref;
|
||||
assert(!(addr & 1));
|
||||
if (sizeof(uintptr_t) == 8) {
|
||||
return (addr >> 1) | FLAG_REF;
|
||||
} else {
|
||||
assert(0 && "TODO");
|
||||
}
|
||||
}
|
||||
|
||||
struct vm_state {
|
||||
// Runtime stack
|
||||
uint64_t *stack;
|
||||
size_t sp, stack_size;
|
||||
uint64_t *call_stack;
|
||||
size_t csp, call_stack_size;
|
||||
struct stack data_stack;
|
||||
struct stack call_stack;
|
||||
|
||||
struct vector units;
|
||||
size_t lp, fp, ip;
|
||||
};
|
||||
|
||||
void vm_state_init(struct vm_state *vm,
|
||||
size_t stack_size);
|
||||
struct vm_unit *vm_add_unit(struct vm_state *vm,
|
||||
size_t stack_size);
|
||||
struct vm_func_entry *unit_add_function(struct vm_unit *u);
|
||||
struct vm_ref_entry *unit_add_ref(struct vm_unit *u);
|
||||
int vm_state_init(struct vm_state *vm, size_t stack_size);
|
||||
void vm_state_free(struct vm_state *vm);
|
||||
|
||||
void vm_call_index(struct vm_state *vm, size_t unit_index, size_t index);
|
||||
void vm_call_ref(struct vm_state *vm, struct vm_value *ref);
|
||||
struct vm_unit *vm_add_unit(struct vm_state *vm, size_t stack_size);
|
||||
|
||||
// Bytecode interpretation
|
||||
int vm_eval_step(struct vm_state *vm);
|
||||
int vm_eval_unit(struct vm_state *vm, size_t index);
|
||||
|
||||
// Stack frames
|
||||
uint64_t vm_get_arg(struct vm_state *vm, size_t index);
|
||||
|
||||
// Stack operation
|
||||
void push(struct vm_state *vm, uint64_t w);
|
||||
uint64_t pop(struct vm_state *vm);
|
||||
int vm_pop(struct vm_state *vm, uint64_t *w);
|
||||
int vm_pop_integer(struct vm_state *vm, int64_t *v);
|
||||
|
||||
void push_ref(struct vm_state *vm, struct vm_value *ref);
|
||||
void push_integer(struct vm_state *vm, int64_t w);
|
||||
int vm_push_integer(struct vm_state *vm, int64_t v);
|
||||
int vm_push_bool(struct vm_state *vm, int v);
|
||||
int vm_push_ref(struct vm_state *vm, struct vm_value *obj);
|
||||
|
||||
uint64_t pop_integer(struct vm_state *vm);
|
||||
uint64_t vm_get_arg(struct vm_state *vm, size_t index);
|
||||
|
||||
@@ -7,7 +7,7 @@ struct vm_string {
|
||||
char *data;
|
||||
};
|
||||
|
||||
void vm_string_init(struct vm_string *s, const char *data);
|
||||
int vm_string_init(struct vm_string *s, const char *data);
|
||||
void vm_string_empty(struct vm_string *s);
|
||||
const char *vm_cstr(const struct vm_string *s);
|
||||
size_t vm_strlen(const struct vm_string *s);
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "vmstring.h"
|
||||
#include "vm.h"
|
||||
#include "vmstate.h"
|
||||
|
||||
enum vm_type {
|
||||
VT_CONS,
|
||||
@@ -55,6 +55,8 @@ static inline int pair_q(uint64_t w) {
|
||||
return ref_q(w) && (!null_q(w) && getref(w)->type == VT_CONS);
|
||||
}
|
||||
|
||||
void vm_value_free(struct vm_value *val);
|
||||
|
||||
struct vm_value *vm_cons(uint64_t w0, uint64_t w1);
|
||||
struct vm_value *vm_makestr(const char *str);
|
||||
struct vm_value *vm_func(size_t lib_index, size_t fn_index);
|
||||
|
||||
Reference in New Issue
Block a user