Browse Source

vm stuff

master
Martin Dørum 3 years ago
parent
commit
64ec7d4725
4 changed files with 79 additions and 16 deletions
  1. 3
    0
      include/lang2/bytecode.h
  2. 1
    1
      include/lang2/parse/lex.h
  3. 17
    11
      include/lang2/vm/vm.h
  4. 58
    4
      src/vm/vm.c

+ 3
- 0
include/lang2/bytecode.h View File

L2_OP_ADD, L2_OP_ADD,
L2_OP_JUMP, L2_OP_JUMP,
L2_OP_CALL, L2_OP_CALL,
L2_OP_RET,
L2_OP_ALLOC_INTEGER,
L2_OP_ALLOC_REAL,
L2_OP_ALLOC_STRING, L2_OP_ALLOC_STRING,
L2_OP_ALLOC_ARRAY, L2_OP_ALLOC_ARRAY,
L2_OP_HALT, L2_OP_HALT,

+ 1
- 1
include/lang2/parse/lex.h View File

#ifndef L2_PARSE_LEX_H #ifndef L2_PARSE_LEX_H
#define L2_PARSE_LEX_H #define L2_PARSE_LEX_H


#include "../io.h"
#include "io.h"


enum l2_token_kind { enum l2_token_kind {
L2_TOK_OPEN_PAREN, L2_TOK_OPEN_PAREN,

+ 17
- 11
include/lang2/vm/vm.h View File



#include <stdlib.h> #include <stdlib.h>


#include "../bytecode.h"
#include "bytecode.h"
#include "bitset.h"


enum {
L2_VAL_TYPE_STRING = (1 << 30) + 0,
L2_VAL_TYPE_ARRAY = (1 << 30) + 1,
L2_VAL_MARKED = 1 << 29,
};
struct l2_vm_value { struct l2_vm_value {
l2_word flags;
enum l2_value_flags {
L2_VAL_TYPE_INTEGER,
L2_VAL_TYPE_REAL,
L2_VAL_TYPE_STRING,
L2_VAL_TYPE_ARRAY,
L2_VAL_MARKED = 1 << 7,
} flags;
union {
int64_t integer;
double real;
void *data;
};
}; };


struct l2_vm_string { struct l2_vm_string {
struct l2_vm_value val; struct l2_vm_value val;
char *mem;
size_t len; size_t len;
}; };


struct l2_vm_array { struct l2_vm_array {
struct l2_vm_value val; struct l2_vm_value val;
l2_word *data;
size_t len; size_t len;
size_t size; size_t size;
}; };
struct l2_op *ops; struct l2_op *ops;
size_t opcount; size_t opcount;


struct l2_vm_value *allocs[1024];
size_t allocslen;
struct l2_vm_value *values;
size_t valuessize;
struct l2_bitset valueset;


l2_word stack[1024]; l2_word stack[1024];
l2_word iptr; l2_word iptr;

+ 58
- 4
src/vm/vm.c View File

vm->opcount = opcount; vm->opcount = opcount;
vm->iptr = 0; vm->iptr = 0;
vm->sptr = 0; vm->sptr = 0;

vm->values = NULL;
vm->valuessize = 0;
l2_bitset_init(&vm->valueset);
} }


static l2_word alloc(struct l2_vm *vm, size_t size) {
l2_word id = vm->allocslen++;
vm->allocs[id] = malloc(size);
return id | 1 << 31;
static l2_word alloc_val(struct l2_vm *vm) {
size_t id = l2_bitset_set_next(&vm->valueset);
if (id > vm->valuessize) {
if (vm->valuessize == 0) {
vm->valuessize = 16;
}

while (id > vm->valuessize) {
vm->valuessize *= 2;
}

vm->values = realloc(vm->values, sizeof(*vm->values) * vm->valuessize);
}

return (l2_word)id;
} }


void l2_vm_step(struct l2_vm *vm) { void l2_vm_step(struct l2_vm *vm) {
struct l2_op op = vm->ops[vm->iptr++]; struct l2_op op = vm->ops[vm->iptr++];


l2_word word;
switch (op.code) { switch (op.code) {
case L2_OP_PUSH: case L2_OP_PUSH:
vm->stack[vm->sptr++] = op.val; vm->stack[vm->sptr++] = op.val;
vm->iptr = vm->stack[--vm->sptr]; vm->iptr = vm->stack[--vm->sptr];
break; break;


case L2_OP_CALL:
word = vm->stack[--vm->sptr];
vm->stack[vm->sptr++] = vm->iptr + 1;
vm->iptr = word;
break;

case L2_OP_RET:
vm->iptr = vm->stack[--vm->sptr];
break;

case L2_OP_ALLOC_INTEGER:
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_INTEGER;
vm->values[word].integer = 0;
vm->stack[vm->sptr++] = word;
break;

case L2_OP_ALLOC_REAL:
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_REAL;
vm->values[word].real = 0;
vm->stack[vm->sptr++] = word;
break;

case L2_OP_ALLOC_STRING:
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_STRING;
vm->values[word].data = calloc(1, sizeof(struct l2_vm_string));
vm->stack[vm->sptr++] = word;
break;

case L2_OP_ALLOC_ARRAY:
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_ARRAY;
vm->values[word].data = calloc(1, sizeof(struct l2_vm_array));
vm->stack[vm->sptr++] = word;
break;

case L2_OP_HALT: case L2_OP_HALT:
break; break;
} }

Loading…
Cancel
Save