Refactor l2vm

This commit is contained in:
2021-04-07 22:24:33 +03:00
parent 8f694a0bca
commit c74ea3b417
25 changed files with 653 additions and 285 deletions
+15
View File
@@ -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);
+2
View File
@@ -1,6 +1,8 @@
#pragma once
#include <stdio.h>
#include "list.h"
#include "vector.h"
struct vm_state;
struct vm_ref_entry;
+14
View File
@@ -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);
+38
View File
@@ -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);
-4
View File
@@ -1,4 +0,0 @@
#pragma once
#include "op.h"
#define FLAG_REF (1ULL << 63)
+23 -51
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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);