Browse Source

1-byte version of instructions

master
Martin Dørum 3 years ago
parent
commit
382c4b9b1d
7 changed files with 369 additions and 197 deletions
  1. 22
    9
      include/lang2/bytecode.h
  2. 1
    0
      include/lang2/gen/gen.h
  3. 159
    54
      lib/gen/gen.c
  4. 2
    2
      lib/loader.c
  5. 10
    9
      lib/parse/parse.c
  6. 53
    6
      lib/vm/print.c
  7. 122
    117
      lib/vm/vm.c

+ 22
- 9
include/lang2/bytecode.h View File

L2_OP_ADD, L2_OP_ADD,


/* /*
* Call a function; func_call <argc:u4>
* Call a function; func_call <argc>
* Pop <argc> times * Pop <argc> times
* Pop <func> * Pop <func>
* Push array with args * Push array with args
* (Before returning, the function will push a return value onto the stack) * (Before returning, the function will push a return value onto the stack)
*/ */
L2_OP_FUNC_CALL_U4, L2_OP_FUNC_CALL_U4,
L2_OP_FUNC_CALL_U1,


/* /*
* Call an infix function * Call an infix function
L2_OP_FUNC_CALL_INFIX, L2_OP_FUNC_CALL_INFIX,


/* /*
* Jump relative; rjmp <count:u4>
* Jump relative; rjmp <count>
* Jump <count> words forwards * Jump <count> words forwards
*/ */
L2_OP_RJMP_U4, L2_OP_RJMP_U4,
L2_OP_RJMP_U1,


/* /*
* Look up a value from the current stack frame; stack_frame_lookup <key:u4>
* Look up a value from the current stack frame; stack_frame_lookup <key>
* Find <val> in stack frame using <key> * Find <val> in stack frame using <key>
* Push <val> * Push <val>
*/ */
L2_OP_STACK_FRAME_LOOKUP_U4, L2_OP_STACK_FRAME_LOOKUP_U4,
L2_OP_STACK_FRAME_LOOKUP_U1,


/* /*
* Set a value in the current stack frame; stack_frame_set <key:u4>
* Set a value in the current stack frame; stack_frame_set <key>
* Read <val> * Read <val>
* Assign <val> to stack frame at <key> * Assign <val> to stack frame at <key>
*/ */
L2_OP_STACK_FRAME_SET_U4, L2_OP_STACK_FRAME_SET_U4,
L2_OP_STACK_FRAME_SET_U1,


/* /*
* Replace a value on the stack; stack_frame_replace <key:U4>
* Replace a value on the stack; stack_frame_replace <key>
* Read <val> * Read <val>
* Assign <val> to stack frame at <key> * Assign <val> to stack frame at <key>
*/ */
L2_OP_STACK_FRAME_REPLACE_U4, L2_OP_STACK_FRAME_REPLACE_U4,
L2_OP_STACK_FRAME_REPLACE_U1,


/* /*
* Return from a function. * Return from a function.
L2_OP_ALLOC_NONE, L2_OP_ALLOC_NONE,


/* /*
* Allocate an atom from one word; alloc_atom <word:u4>
* Allocate an atom from one word; alloc_atom <word>
* Alloc atom <var> from <word> * Alloc atom <var> from <word>
* Push <var> * Push <var>
*/ */
L2_OP_ALLOC_ATOM_U4, L2_OP_ALLOC_ATOM_U4,
L2_OP_ALLOC_ATOM_U1,


/* /*
* Allocate a real from two words; alloc_real <double:u8> * Allocate a real from two words; alloc_real <double:u8>
L2_OP_ALLOC_REAL_D8, L2_OP_ALLOC_REAL_D8,


/* /*
* Allocate a buffer from static data; alloc_buffer_static <length:u4> <offset:u4>
* Allocate a buffer from static data; alloc_buffer_static <length> <offset>
* Alloc buffer <var> with <length> and <offset> * Alloc buffer <var> with <length> and <offset>
* Push <var> * Push <var>
*/ */
L2_OP_ALLOC_BUFFER_STATIC_U4, L2_OP_ALLOC_BUFFER_STATIC_U4,
L2_OP_ALLOC_BUFFER_STATIC_U1,


/* /*
* Allocate an array; <count:u4> * Allocate an array; <count:u4>
* Push <var> * Push <var>
*/ */
L2_OP_ALLOC_ARRAY_U4, L2_OP_ALLOC_ARRAY_U4,
L2_OP_ALLOC_ARRAY_U1,


/* /*
* Allocate an integer->value map. * Allocate an integer->value map.
L2_OP_ALLOC_NAMESPACE, L2_OP_ALLOC_NAMESPACE,


/* /*
* Allocate a function; alloc_function <pos:u4>
* Allocate a function; alloc_function <pos>
* Alloc function <var> pointing to location <word> * Alloc function <var> pointing to location <word>
* Push <var> * Push <var>
*/ */
L2_OP_ALLOC_FUNCTION_U4, L2_OP_ALLOC_FUNCTION_U4,
L2_OP_ALLOC_FUNCTION_U1,


/* /*
* Set a namespace's name to a value; namespace_set <key:u4> * Set a namespace's name to a value; namespace_set <key:u4>
* Assign <val> to <ns[<key>]> * Assign <val> to <ns[<key>]>
*/ */
L2_OP_NAMESPACE_SET_U4, L2_OP_NAMESPACE_SET_U4,
L2_OP_NAMESPACE_SET_U1,


/* /*
* Lookup a value from a namespace; namespace_lookup <key:u4> * Lookup a value from a namespace; namespace_lookup <key:u4>
* Push <ns[<key>]> * Push <ns[<key>]>
*/ */
L2_OP_NAMESPACE_LOOKUP_U4, L2_OP_NAMESPACE_LOOKUP_U4,
L2_OP_NAMESPACE_LOOKUP_U1,


/* /*
* Look up a value from an array; array_lookup <key:u4> * Look up a value from an array; array_lookup <key:u4>
* Push <arr[<key>]> * Push <arr[<key>]>
*/ */
L2_OP_ARRAY_LOOKUP_U4, L2_OP_ARRAY_LOOKUP_U4,
L2_OP_ARRAY_LOOKUP_U1,


/* /*
* Set a value in an array; array_set <key> * Set a value in an array; array_set <key>
* Read <arr> * Read <arr>
* Assign <val> to <arr[<key>]> * Assign <val> to <arr[<key>]>
*/ */
L2_OP_ARRAY_SET,
L2_OP_ARRAY_SET_U4,
L2_OP_ARRAY_SET_U1,


/* /*
* Look up a runtime value in an array or object. * Look up a runtime value in an array or object.

+ 1
- 0
include/lang2/gen/gen.h View File



void l2_gen_halt(struct l2_generator *gen); void l2_gen_halt(struct l2_generator *gen);
void l2_gen_rjmp(struct l2_generator *gen, l2_word len); void l2_gen_rjmp(struct l2_generator *gen, l2_word len);
void l2_gen_rjmp_placeholder(struct l2_generator *gen);
void l2_gen_discard(struct l2_generator *gen); void l2_gen_discard(struct l2_generator *gen);
void l2_gen_swap_discard(struct l2_generator *gen); void l2_gen_swap_discard(struct l2_generator *gen);
void l2_gen_ret(struct l2_generator *gen); void l2_gen_ret(struct l2_generator *gen);

+ 159
- 54
lib/gen/gen.c View File

} }


void l2_gen_rjmp(struct l2_generator *gen, l2_word len) { void l2_gen_rjmp(struct l2_generator *gen, l2_word len) {
if (len <= 0xff) {
put(gen, L2_OP_RJMP_U1);
put(gen, len);
} else {
put(gen, L2_OP_RJMP_U4);
put_u4le(gen, len);
}
}

void l2_gen_rjmp_placeholder(struct l2_generator *gen) {
put(gen, L2_OP_RJMP_U4); put(gen, L2_OP_RJMP_U4);
put_u4le(gen, len);
put_u4le(gen, 0);
} }


void l2_gen_discard(struct l2_generator *gen) { void l2_gen_discard(struct l2_generator *gen) {


void l2_gen_atom(struct l2_generator *gen, char **str) { void l2_gen_atom(struct l2_generator *gen, char **str) {
size_t id = l2_strset_put(&gen->atomset, str); size_t id = l2_strset_put(&gen->atomset, str);
put(gen, L2_OP_ALLOC_ATOM_U4);
put_u4le(gen, id);
if (id <= 0xff) {
put(gen, L2_OP_ALLOC_ATOM_U1);
put(gen, id);
} else {
put(gen, L2_OP_ALLOC_ATOM_U4);
put_u4le(gen, id);
}
} }


void l2_gen_atom_copy(struct l2_generator *gen, char *str) { void l2_gen_atom_copy(struct l2_generator *gen, char *str) {
size_t id = l2_strset_put_copy(&gen->atomset, str); size_t id = l2_strset_put_copy(&gen->atomset, str);
put(gen, L2_OP_ALLOC_ATOM_U4);
put_u4le(gen, id);
if (id <= 0xff) {
put(gen, L2_OP_ALLOC_ATOM_U1);
put(gen, id);
} else {
put(gen, L2_OP_ALLOC_ATOM_U4);
put_u4le(gen, id);
}
} }


void l2_gen_string(struct l2_generator *gen, char **str) { void l2_gen_string(struct l2_generator *gen, char **str) {
size_t id = l2_strset_get(&gen->stringset, *str); size_t id = l2_strset_get(&gen->stringset, *str);
if (id == 0) { if (id == 0) {
size_t len = strlen(*str); size_t len = strlen(*str);
size_t aligned = len;
if (aligned % sizeof(l2_word) != 0) {
aligned += sizeof(l2_word) - (aligned % sizeof(l2_word));
}


put(gen, L2_OP_RJMP_U4);
put_u4le(gen, aligned / sizeof(l2_word));
l2_gen_rjmp(gen, len);
l2_word pos = gen->pos; l2_word pos = gen->pos;


gen->pos += aligned / sizeof(l2_word);
gen->pos += len;
l2_bufio_put_n(&gen->writer, *str, len); l2_bufio_put_n(&gen->writer, *str, len);
for (size_t i = len; i < aligned; ++i) {
l2_bufio_put(&gen->writer, '\0');
}


id = l2_strset_put(&gen->stringset, str); id = l2_strset_put(&gen->stringset, str);
gen->strings = realloc(gen->strings, id * sizeof(*gen->strings)); gen->strings = realloc(gen->strings, id * sizeof(*gen->strings));
gen->strings[id - 1].length = len; gen->strings[id - 1].length = len;
gen->strings[id - 1].pos = pos; gen->strings[id - 1].pos = pos;


put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4);
put_u4le(gen, len);
put_u4le(gen, pos);
if (len <= 0xff && pos <= 0xff) {
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U1);
put(gen, len);
put(gen, pos);
} else {
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4);
put_u4le(gen, len);
put_u4le(gen, pos);
}
} else { } else {
free(*str); free(*str);
struct l2_generator_string *s = &gen->strings[id - 1]; struct l2_generator_string *s = &gen->strings[id - 1];
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4);
put_u4le(gen, s->length);
put_u4le(gen, s->pos);
if (s->length <= 0xff && s->pos <= 0xff) {
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U1);
put(gen, s->length);
put(gen, s->pos);
} else {
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4);
put_u4le(gen, s->length);
put_u4le(gen, s->pos);
}
} }
} }


l2_gen_string(gen, &s); l2_gen_string(gen, &s);
} else { } else {
struct l2_generator_string *s = &gen->strings[id - 1]; struct l2_generator_string *s = &gen->strings[id - 1];
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4);
put_u4le(gen, s->length);
put_u4le(gen, s->pos);
if (s->length <= 0xff && s->pos <= 0xff) {
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U1);
put(gen, s->length);
put(gen, s->pos);
} else {
put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4);
put_u4le(gen, s->length);
put_u4le(gen, s->pos);
}
} }
} }


void l2_gen_function(struct l2_generator *gen, l2_word pos) { void l2_gen_function(struct l2_generator *gen, l2_word pos) {
put(gen, L2_OP_ALLOC_FUNCTION_U4);
put_u4le(gen, pos);
if (pos <= 0xff) {
put(gen, L2_OP_ALLOC_FUNCTION_U1);
put(gen, pos);
} else {
put(gen, L2_OP_ALLOC_FUNCTION_U4);
put_u4le(gen, pos);
}
} }


void l2_gen_array(struct l2_generator *gen, l2_word count) { void l2_gen_array(struct l2_generator *gen, l2_word count) {
put(gen, L2_OP_ALLOC_ARRAY_U4);
put_u4le(gen, count);
if (count <= 0xff) {
put(gen, L2_OP_ALLOC_ARRAY_U1);
put(gen, count);
} else {
put(gen, L2_OP_ALLOC_ARRAY_U4);
put_u4le(gen, count);
}
} }


void l2_gen_namespace(struct l2_generator *gen) { void l2_gen_namespace(struct l2_generator *gen) {


void l2_gen_namespace_set(struct l2_generator *gen, char **ident) { void l2_gen_namespace_set(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident); size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_NAMESPACE_SET_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_NAMESPACE_SET_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_NAMESPACE_SET_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_namespace_set_copy(struct l2_generator *gen, char *ident) { void l2_gen_namespace_set_copy(struct l2_generator *gen, char *ident) {
size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); size_t atom_id = l2_strset_put_copy(&gen->atomset, ident);
put(gen, L2_OP_NAMESPACE_SET_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_NAMESPACE_SET_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_NAMESPACE_SET_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident) { void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident); size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_NAMESPACE_LOOKUP_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_NAMESPACE_LOOKUP_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_NAMESPACE_LOOKUP_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_namespace_lookup_copy(struct l2_generator *gen, char *ident) { void l2_gen_namespace_lookup_copy(struct l2_generator *gen, char *ident) {
size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); size_t atom_id = l2_strset_put_copy(&gen->atomset, ident);
put(gen, L2_OP_NAMESPACE_LOOKUP_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_NAMESPACE_LOOKUP_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_NAMESPACE_LOOKUP_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_array_lookup(struct l2_generator *gen, int number) { void l2_gen_array_lookup(struct l2_generator *gen, int number) {
put(gen, L2_OP_ARRAY_LOOKUP_U4);
put_u4le(gen, number);
if (number <= 0xff) {
put(gen, L2_OP_ARRAY_LOOKUP_U1);
put(gen, number);
} else {
put(gen, L2_OP_ARRAY_LOOKUP_U4);
put_u4le(gen, number);
}
} }


void l2_gen_array_set(struct l2_generator *gen, int number) { void l2_gen_array_set(struct l2_generator *gen, int number) {
put(gen, L2_OP_ARRAY_SET);
put(gen, number);
if (number <= 0xff) {
put(gen, L2_OP_ARRAY_SET_U1);
put(gen, number);
} else {
put(gen, L2_OP_ARRAY_SET_U4);
put_u4le(gen, number);
}
} }


void l2_gen_dynamic_lookup(struct l2_generator *gen) { void l2_gen_dynamic_lookup(struct l2_generator *gen) {


void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) { void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident); size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_STACK_FRAME_LOOKUP_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_STACK_FRAME_LOOKUP_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_STACK_FRAME_LOOKUP_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_stack_frame_lookup_copy(struct l2_generator *gen, char *ident) { void l2_gen_stack_frame_lookup_copy(struct l2_generator *gen, char *ident) {
size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); size_t atom_id = l2_strset_put_copy(&gen->atomset, ident);
put(gen, L2_OP_STACK_FRAME_LOOKUP_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_STACK_FRAME_LOOKUP_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_STACK_FRAME_LOOKUP_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_stack_frame_set(struct l2_generator *gen, char **ident) { void l2_gen_stack_frame_set(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident); size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_STACK_FRAME_SET_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_STACK_FRAME_SET_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_STACK_FRAME_SET_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_stack_frame_set_copy(struct l2_generator *gen, char *ident) { void l2_gen_stack_frame_set_copy(struct l2_generator *gen, char *ident) {
size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); size_t atom_id = l2_strset_put_copy(&gen->atomset, ident);
put(gen, L2_OP_STACK_FRAME_SET_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_STACK_FRAME_SET_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_STACK_FRAME_SET_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident) { void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident); size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_STACK_FRAME_REPLACE_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_STACK_FRAME_REPLACE_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_STACK_FRAME_REPLACE_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_stack_frame_replace_copy(struct l2_generator *gen, char *ident) { void l2_gen_stack_frame_replace_copy(struct l2_generator *gen, char *ident) {
size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); size_t atom_id = l2_strset_put_copy(&gen->atomset, ident);
put(gen, L2_OP_STACK_FRAME_REPLACE_U4);
put_u4le(gen, atom_id);
if (atom_id <= 0xff) {
put(gen, L2_OP_STACK_FRAME_REPLACE_U1);
put(gen, atom_id);
} else {
put(gen, L2_OP_STACK_FRAME_REPLACE_U4);
put_u4le(gen, atom_id);
}
} }


void l2_gen_func_call(struct l2_generator *gen, l2_word argc) { void l2_gen_func_call(struct l2_generator *gen, l2_word argc) {
put(gen, L2_OP_FUNC_CALL_U4);
put_u4le(gen, argc);
if (argc <= 0xff) {
put(gen, L2_OP_FUNC_CALL_U1);
put(gen, argc);
} else {
put(gen, L2_OP_FUNC_CALL_U4);
put_u4le(gen, argc);
}
} }


void l2_gen_func_call_infix(struct l2_generator *gen) { void l2_gen_func_call_infix(struct l2_generator *gen) {

+ 2
- 2
lib/loader.c View File

((uint32_t)version_buf[2]) << 16 | ((uint32_t)version_buf[2]) << 16 |
((uint32_t)version_buf[3]) << 24; ((uint32_t)version_buf[3]) << 24;
if (version != l2_bytecode_version) { if (version != l2_bytecode_version) {
fprintf(
stderr, "Version mismatch! Bytecode file uses bytecode version %i"
fprintf(stderr,
"Version mismatch! Bytecode file uses bytecode version %i"
", but your build of lang2 uses bytecode version %i\n", ", but your build of lang2 uses bytecode version %i\n",
version, l2_bytecode_version); version, l2_bytecode_version);
return -1; return -1;

+ 10
- 9
lib/parse/parse.c View File

w.w.write = l2_io_mem_write; w.w.write = l2_io_mem_write;
gen->writer.w = &w.w; gen->writer.w = &w.w;


// Generates two words; RJMP, 0
l2_gen_rjmp(gen, 0);
// Generates five bytes; RJMP, then 4 byte counter
l2_gen_rjmp_placeholder(gen);


l2_word pos = gen->pos; l2_word pos = gen->pos;


return -1; return -1;
} }


l2_word *ops = w.mem;
l2_word opcount = w.len / sizeof(l2_word);
unsigned char *ops = w.mem;
l2_word opcount = w.len - 5;


// Due to the earlier gen_rjmp, the second word will be the argument to RJMP.
// Need to set it properly to skip the function body.
// The '- 2' is because we don't skip the RJMP, <count> sequence.
ops[1] = opcount - 2;
// Write the jump distance (little endian)
ops[1] = (opcount >> 0) & 0xff;
ops[2] = (opcount >> 8) & 0xff;
ops[3] = (opcount >> 16) & 0xff;
ops[4] = (opcount >> 24) & 0xff;


l2_bufio_put_n(&gen->writer, ops, opcount * sizeof(l2_word));
l2_bufio_put_n(&gen->writer, ops, w.len);
free(w.mem); free(w.mem);


l2_gen_function(gen, pos); l2_gen_function(gen, pos);

+ 53
- 6
lib/vm/print.c View File

return ret; return ret;
} }


static l2_word read_u1le(unsigned char *ops, size_t *ptr) {
return ops[(*ptr)++];
}

static double read_d8le(unsigned char *ops, size_t *ptr) { static double read_d8le(unsigned char *ops, size_t *ptr) {
unsigned char *data = &ops[*ptr]; unsigned char *data = &ops[*ptr];
uint64_t integer = 0 | uint64_t integer = 0 |
case L2_OP_FUNC_CALL_U4: case L2_OP_FUNC_CALL_U4:
printf("FUNC_CALL %08x\n", read_u4le(ops, ptr)); printf("FUNC_CALL %08x\n", read_u4le(ops, ptr));
return; return;
case L2_OP_FUNC_CALL_U1:
printf("FUNC_CALL %02x\n", read_u1le(ops, ptr));
return;


case L2_OP_FUNC_CALL_INFIX: case L2_OP_FUNC_CALL_INFIX:
printf("FUNC_CALL_INFIX\n"); printf("FUNC_CALL_INFIX\n");
case L2_OP_RJMP_U4: case L2_OP_RJMP_U4:
printf("RJMP %08x\n", read_u4le(ops, ptr)); printf("RJMP %08x\n", read_u4le(ops, ptr));
return; return;
case L2_OP_RJMP_U1:
printf("RJMP %02x\n", read_u1le(ops, ptr));
return;


case L2_OP_STACK_FRAME_LOOKUP_U4: case L2_OP_STACK_FRAME_LOOKUP_U4:
printf("STACK_FRAME_LOOKUP %08x\n", read_u4le(ops, ptr)); printf("STACK_FRAME_LOOKUP %08x\n", read_u4le(ops, ptr));
return; return;
case L2_OP_STACK_FRAME_LOOKUP_U1:
printf("STACK_FRAME_LOOKUP %02x\n", read_u1le(ops, ptr));
return;


case L2_OP_STACK_FRAME_SET_U4: case L2_OP_STACK_FRAME_SET_U4:
printf("STACK_FRAME_SET %08x\n", read_u4le(ops, ptr)); printf("STACK_FRAME_SET %08x\n", read_u4le(ops, ptr));
return; return;
case L2_OP_STACK_FRAME_SET_U1:
printf("STACK_FRAME_SET %02x\n", read_u1le(ops, ptr));
return;


case L2_OP_STACK_FRAME_REPLACE_U4: case L2_OP_STACK_FRAME_REPLACE_U4:
printf("STACK_FRAME_REPLACE %08x\n", read_u4le(ops, ptr)); printf("STACK_FRAME_REPLACE %08x\n", read_u4le(ops, ptr));
return; return;
case L2_OP_STACK_FRAME_REPLACE_U1:
printf("STACK_FRAME_REPLACE %02x\n", read_u1le(ops, ptr));
return;


case L2_OP_RET: case L2_OP_RET:
printf("RET\n"); printf("RET\n");
case L2_OP_ALLOC_ATOM_U4: case L2_OP_ALLOC_ATOM_U4:
printf("ALLOC_ATOM %08x\n", read_u4le(ops, ptr)); printf("ALLOC_ATOM %08x\n", read_u4le(ops, ptr));
return; return;
case L2_OP_ALLOC_ATOM_U1:
printf("ALLOC_ATOM %02x\n", read_u1le(ops, ptr));
return;


case L2_OP_ALLOC_REAL_D8: case L2_OP_ALLOC_REAL_D8:
printf("ALLOC_REAL %f\n", read_d8le(ops, ptr)); printf("ALLOC_REAL %f\n", read_d8le(ops, ptr));
printf("ALLOC_BUFFER_STATIC %08x %08x\n", w1, w2); printf("ALLOC_BUFFER_STATIC %08x %08x\n", w1, w2);
} }
return; return;
case L2_OP_ALLOC_BUFFER_STATIC_U1:
{
l2_word w1 = read_u1le(ops, ptr);
l2_word w2 = read_u1le(ops, ptr);;
printf("ALLOC_BUFFER_STATIC %02x %02x\n", w1, w2);
}
return;


case L2_OP_ALLOC_ARRAY_U4: case L2_OP_ALLOC_ARRAY_U4:
printf("ALLOC_ARRAY_U4 %08x\n", read_u4le(ops, ptr));
printf("ALLOC_ARRAY %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_ALLOC_ARRAY_U1:
printf("ALLOC_ARRAY %02x\n", read_u1le(ops, ptr));
return; return;


case L2_OP_ALLOC_NAMESPACE: case L2_OP_ALLOC_NAMESPACE:
return; return;


case L2_OP_ALLOC_FUNCTION_U4: case L2_OP_ALLOC_FUNCTION_U4:
printf("ALLOC_FUNCTION_U4 %08x\n", read_u4le(ops, ptr));
printf("ALLOC_FUNCTION %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_ALLOC_FUNCTION_U1:
printf("ALLOC_FUNCTION %02x\n", read_u1le(ops, ptr));
return; return;


case L2_OP_NAMESPACE_SET_U4: case L2_OP_NAMESPACE_SET_U4:
printf("NAMESPACE_SET_U4 %08x\n", read_u4le(ops, ptr));
printf("NAMESPACE_SET %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_NAMESPACE_SET_U1:
printf("NAMESPACE_SET %02x\n", read_u1le(ops, ptr));
return; return;


case L2_OP_NAMESPACE_LOOKUP_U4: case L2_OP_NAMESPACE_LOOKUP_U4:
printf("NAMESPACE_LOOKUP_U4 %08x\n", read_u4le(ops, ptr));
printf("NAMESPACE_LOOKUP %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_NAMESPACE_LOOKUP_U1:
printf("NAMESPACE_LOOKUP %02x\n", read_u1le(ops, ptr));
return; return;


case L2_OP_ARRAY_LOOKUP_U4: case L2_OP_ARRAY_LOOKUP_U4:
printf("ARRAY_LOOKUP_U4 %08x\n", read_u4le(ops, ptr));
printf("ARRAY_LOOKUP %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_ARRAY_LOOKUP_U1:
printf("ARRAY_LOOKUP %02x\n", read_u1le(ops, ptr));
return; return;


case L2_OP_ARRAY_SET:
case L2_OP_ARRAY_SET_U4:
printf("ARRAY_SET %08x\n", read_u4le(ops, ptr)); printf("ARRAY_SET %08x\n", read_u4le(ops, ptr));
return; return;
case L2_OP_ARRAY_SET_U1:
printf("ARRAY_SET %02x\n", read_u1le(ops, ptr));
return;


case L2_OP_DYNAMIC_LOOKUP: case L2_OP_DYNAMIC_LOOKUP:
printf("DYNAMIC_LOOKUP\n"); printf("DYNAMIC_LOOKUP\n");

+ 122
- 117
lib/vm/vm.c View File

return ret; return ret;
} }


static l2_word read_u1le(struct l2_vm *vm) {
return vm->ops[vm->iptr++];
}

static double read_d8le(struct l2_vm *vm) { static double read_d8le(struct l2_vm *vm) {
unsigned char *data = &vm->ops[vm->iptr]; unsigned char *data = &vm->ops[vm->iptr];
uint64_t integer = 0 | uint64_t integer = 0 |
vm->sptr -= 1; vm->sptr -= 1;
break; break;


case L2_OP_FUNC_CALL_U4:
{
l2_word argc = read_u4le(vm);
vm->sptr -= argc;
l2_word *argv = vm->stack + vm->sptr;

l2_word func_id = vm->stack[--vm->sptr];
call_func(vm, func_id, argc, argv);
}
break;
#define X(read) \
l2_word argc = read(vm); \
vm->sptr -= argc; \
l2_word *argv = vm->stack + vm->sptr; \
l2_word func_id = vm->stack[--vm->sptr]; \
call_func(vm, func_id, argc, argv)
case L2_OP_FUNC_CALL_U4: { X(read_u4le); } break;
case L2_OP_FUNC_CALL_U1: { X(read_u1le); } break;
#undef X


case L2_OP_RJMP_U4:
vm->iptr += read_u4le(vm) + 1;
break;
#define X(read) word = read(vm); vm->iptr += word;
case L2_OP_RJMP_U4: { X(read_u4le); } break;
case L2_OP_RJMP_U1: { X(read_u1le); } break;
#undef X


case L2_OP_STACK_FRAME_LOOKUP_U4:
{
l2_word key = read_u4le(vm);
struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns];
vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, ns, key);
}
break;
#define X(read) \
l2_word key = read(vm); \
struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, ns, key);
case L2_OP_STACK_FRAME_LOOKUP_U4: { X(read_u4le); } break;
case L2_OP_STACK_FRAME_LOOKUP_U1: { X(read_u1le); } break;
#undef X


case L2_OP_STACK_FRAME_SET_U4:
{
l2_word key = read_u4le(vm);
l2_word val = vm->stack[vm->sptr - 1];
struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns];
l2_vm_namespace_set(ns, key, val);
}
break;
#define X(read) \
l2_word key = read(vm); \
l2_word val = vm->stack[vm->sptr - 1]; \
struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
l2_vm_namespace_set(ns, key, val);
case L2_OP_STACK_FRAME_SET_U4: { X(read_u4le); } break;
case L2_OP_STACK_FRAME_SET_U1: { X(read_u1le); } break;
#undef X


case L2_OP_STACK_FRAME_REPLACE_U4:
{
l2_word key = read_u4le(vm);
l2_word val = vm->stack[vm->sptr - 1];
struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns];
l2_vm_namespace_replace(vm, ns, key, val); // TODO: error if returns -1
}
break;
#define X(read) \
l2_word key = read(vm); \
l2_word val = vm->stack[vm->sptr - 1]; \
struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
l2_vm_namespace_replace(vm, ns, key, val); // TODO: error if returns -1
case L2_OP_STACK_FRAME_REPLACE_U4: { X(read_u4le); } break;
case L2_OP_STACK_FRAME_REPLACE_U1: { X(read_u1le); } break;
#undef X


case L2_OP_RET: case L2_OP_RET:
{ {
vm->stack[vm->sptr++] = 0; vm->stack[vm->sptr++] = 0;
break; break;


case L2_OP_ALLOC_ATOM_U4:
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_ATOM;
vm->values[word].atom = read_u4le(vm);
#define X(read) \
word = alloc_val(vm); \
vm->values[word].flags = L2_VAL_TYPE_ATOM; \
vm->values[word].atom = read(vm); \
vm->stack[vm->sptr++] = word; vm->stack[vm->sptr++] = word;
break;
case L2_OP_ALLOC_ATOM_U4: { X(read_u4le); } break;
case L2_OP_ALLOC_ATOM_U1: { X(read_u1le); } break;
#undef X


case L2_OP_ALLOC_REAL_D8: case L2_OP_ALLOC_REAL_D8:
{ {
} }
break; break;


case L2_OP_ALLOC_BUFFER_STATIC_U4:
{
word = alloc_val(vm);
l2_word length = read_u4le(vm);
l2_word offset = read_u4le(vm);
vm->values[word].flags = L2_VAL_TYPE_BUFFER;
vm->values[word].buffer = malloc(sizeof(struct l2_vm_buffer) + length);
vm->values[word].buffer->len = length;
memcpy(
(unsigned char *)vm->values[word].buffer + sizeof(struct l2_vm_buffer),
vm->ops + offset, length);
vm->stack[vm->sptr] = word;
vm->sptr += 1;
}
break;

case L2_OP_ALLOC_ARRAY_U4:
{
l2_word count = read_u4le(vm);
l2_word arr_id = alloc_val(vm);
struct l2_vm_value *arr = &vm->values[arr_id];
arr->flags = L2_VAL_TYPE_ARRAY;
if (count == 0) {
arr->array = NULL;
vm->stack[vm->sptr++] = arr_id;
break;
}

arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word));
arr->array->len = count;
arr->array->size = count;
for (l2_word i = 0; i < count; ++i) {
arr->array->data[count - 1 - i] = vm->stack[--vm->sptr];
}
#define X(read) \
word = alloc_val(vm); \
l2_word length = read(vm); \
l2_word offset = read(vm); \
vm->values[word].flags = L2_VAL_TYPE_BUFFER; \
vm->values[word].buffer = malloc(sizeof(struct l2_vm_buffer) + length); \
vm->values[word].buffer->len = length; \
memcpy( \
(unsigned char *)vm->values[word].buffer + sizeof(struct l2_vm_buffer), \
vm->ops + offset, length); \
vm->stack[vm->sptr] = word; \
vm->sptr += 1;
case L2_OP_ALLOC_BUFFER_STATIC_U4: { X(read_u4le); } break;
case L2_OP_ALLOC_BUFFER_STATIC_U1: { X(read_u1le); } break;
#undef X


vm->stack[vm->sptr++] = arr_id;
}
break;
#define X(read) \
l2_word count = read(vm); \
l2_word arr_id = alloc_val(vm); \
struct l2_vm_value *arr = &vm->values[arr_id]; \
arr->flags = L2_VAL_TYPE_ARRAY; \
if (count == 0) { \
arr->array = NULL; \
vm->stack[vm->sptr++] = arr_id; \
break; \
} \
arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word)); \
arr->array->len = count; \
arr->array->size = count; \
for (l2_word i = 0; i < count; ++i) { \
arr->array->data[count - 1 - i] = vm->stack[--vm->sptr]; \
} \
vm->stack[vm->sptr++] = arr_id;
case L2_OP_ALLOC_ARRAY_U4: { X(read_u4le); } break;
case L2_OP_ALLOC_ARRAY_U1: { X(read_u1le); } break;
#undef X


case L2_OP_ALLOC_NAMESPACE: case L2_OP_ALLOC_NAMESPACE:
word = alloc_val(vm); word = alloc_val(vm);
vm->sptr += 1; vm->sptr += 1;
break; break;


case L2_OP_ALLOC_FUNCTION_U4:
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_FUNCTION;
vm->values[word].func.pos = read_u4le(vm);
vm->values[word].func.ns = vm->fstack[vm->fsptr - 1].ns;
vm->stack[vm->sptr] = word;
#define X(read) \
word = alloc_val(vm); \
vm->values[word].flags = L2_VAL_TYPE_FUNCTION; \
vm->values[word].func.pos = read(vm); \
vm->values[word].func.ns = vm->fstack[vm->fsptr - 1].ns; \
vm->stack[vm->sptr] = word; \
vm->sptr += 1; vm->sptr += 1;
break;
case L2_OP_ALLOC_FUNCTION_U4: { X(read_u4le); } break;
case L2_OP_ALLOC_FUNCTION_U1: { X(read_u1le); } break;
#undef X


case L2_OP_NAMESPACE_SET_U4:
{
l2_word key = read_u4le(vm);
l2_word val = vm->stack[vm->sptr - 1];
l2_word ns = vm->stack[vm->sptr - 2];
l2_vm_namespace_set(&vm->values[ns], key, val);
}
break;
#define X(read) \
l2_word key = read(vm); \
l2_word val = vm->stack[vm->sptr - 1]; \
l2_word ns = vm->stack[vm->sptr - 2]; \
l2_vm_namespace_set(&vm->values[ns], key, val);
case L2_OP_NAMESPACE_SET_U4: { X(read_u4le); } break;
case L2_OP_NAMESPACE_SET_U1: { X(read_u1le); } break;
#undef X


case L2_OP_NAMESPACE_LOOKUP_U4:
{
l2_word key = read_u4le(vm);
l2_word ns = vm->stack[--vm->sptr];
vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, &vm->values[ns], key);
}
break;
#define X(read) \
l2_word key = read(vm); \
l2_word ns = vm->stack[--vm->sptr]; \
vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, &vm->values[ns], key);
case L2_OP_NAMESPACE_LOOKUP_U4: { X(read_u4le); } break;
case L2_OP_NAMESPACE_LOOKUP_U1: { X(read_u1le); } break;
#undef X


case L2_OP_ARRAY_LOOKUP_U4:
{
l2_word key = read_u4le(vm);
l2_word arr = vm->stack[--vm->sptr];
// TODO: Error if out of bounds or incorrect type
vm->stack[vm->sptr++] = vm->values[arr].array->data[key];
}
break;
#define X(read) \
l2_word key = read(vm); \
l2_word arr = vm->stack[--vm->sptr]; \
/* TODO: Error if out of bounds or incorrect type */ \
vm->stack[vm->sptr++] = vm->values[arr].array->data[key];
case L2_OP_ARRAY_LOOKUP_U4: { X(read_u4le); } break;
case L2_OP_ARRAY_LOOKUP_U1: { X(read_u1le); } break;
#undef X


case L2_OP_ARRAY_SET:
{
l2_word key = vm->ops[vm->iptr++];
l2_word val = vm->stack[vm->sptr - 1];
l2_word arr = vm->stack[vm->sptr - 2];
// TODO: Error if out of bounds or incorrect type
vm->values[arr].array->data[key] = val;
}
break;
#define X(read) \
l2_word key = read(vm); \
l2_word val = vm->stack[vm->sptr - 1]; \
l2_word arr = vm->stack[vm->sptr - 2]; \
/* TODO: Error if out of bounds or incorrect type */ \
vm->values[arr].array->data[key] = val;
case L2_OP_ARRAY_SET_U4: { X(read_u4le); } break;
case L2_OP_ARRAY_SET_U1: { X(read_u1le); } break;


case L2_OP_DYNAMIC_LOOKUP: case L2_OP_DYNAMIC_LOOKUP:
{ {

Loading…
Cancel
Save