65 lines
1.3 KiB
C
65 lines
1.3 KiB
C
#pragma once
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <assert.h>
|
|
|
|
#include "vector.h"
|
|
#include "stack.h"
|
|
|
|
#define FLAG_REF (1ULL << 63)
|
|
#define MAXARG 12
|
|
#define MAXLOC 64
|
|
|
|
#define VM_SINGLESTEP (1 << 0)
|
|
|
|
struct vm_value;
|
|
|
|
enum vm_state {
|
|
STATE_INIT = 0,
|
|
STATE_RUNNING,
|
|
STATE_BREAKPOINT,
|
|
STATE_EXITED,
|
|
STATE_ERROR
|
|
};
|
|
|
|
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 {
|
|
struct stack data_stack;
|
|
struct stack call_stack;
|
|
|
|
struct vector units;
|
|
size_t bp, lp, fp, ip;
|
|
|
|
uint32_t flags;
|
|
|
|
enum vm_state state;
|
|
};
|
|
|
|
int vm_init(struct vm *vm, size_t stack_size);
|
|
void vm_free(struct vm *vm);
|
|
|
|
struct vm_unit *vm_add_unit(struct vm *vm, size_t stack_size);
|
|
|
|
// Bytecode interpretation
|
|
int vm_eval_step(struct vm *vm);
|
|
int vm_eval_unit(struct vm *vm, size_t index);
|
|
|
|
// Stack operation
|
|
int vm_pop(struct vm *vm, uint64_t *w);
|
|
int vm_pop_integer(struct vm *vm, int64_t *v);
|
|
|
|
int vm_push_integer(struct vm *vm, int64_t v);
|
|
int vm_push_bool(struct vm *vm, int v);
|
|
int vm_push_ref(struct vm *vm, struct vm_value *obj);
|
|
|
|
uint64_t vm_get_arg(struct vm *vm, size_t index);
|