Browse Source

1-byte version of instructions

master
Martin Dørum 7 months 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

@@ -42,7 +42,7 @@ enum l2_opcode {
L2_OP_ADD,

/*
* Call a function; func_call <argc:u4>
* Call a function; func_call <argc>
* Pop <argc> times
* Pop <func>
* Push array with args
@@ -50,6 +50,7 @@ enum l2_opcode {
* (Before returning, the function will push a return value onto the stack)
*/
L2_OP_FUNC_CALL_U4,
L2_OP_FUNC_CALL_U1,

/*
* Call an infix function
@@ -62,31 +63,35 @@ enum l2_opcode {
L2_OP_FUNC_CALL_INFIX,

/*
* Jump relative; rjmp <count:u4>
* Jump relative; rjmp <count>
* Jump <count> words forwards
*/
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>
* Push <val>
*/
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>
* Assign <val> to stack frame at <key>
*/
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>
* Assign <val> to stack frame at <key>
*/
L2_OP_STACK_FRAME_REPLACE_U4,
L2_OP_STACK_FRAME_REPLACE_U1,

/*
* Return from a function.
@@ -105,11 +110,12 @@ enum l2_opcode {
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>
* Push <var>
*/
L2_OP_ALLOC_ATOM_U4,
L2_OP_ALLOC_ATOM_U1,

/*
* Allocate a real from two words; alloc_real <double:u8>
@@ -119,11 +125,12 @@ enum l2_opcode {
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>
* Push <var>
*/
L2_OP_ALLOC_BUFFER_STATIC_U4,
L2_OP_ALLOC_BUFFER_STATIC_U1,

/*
* Allocate an array; <count:u4>
@@ -132,6 +139,7 @@ enum l2_opcode {
* Push <var>
*/
L2_OP_ALLOC_ARRAY_U4,
L2_OP_ALLOC_ARRAY_U1,

/*
* Allocate an integer->value map.
@@ -141,11 +149,12 @@ enum l2_opcode {
L2_OP_ALLOC_NAMESPACE,

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

/*
* Set a namespace's name to a value; namespace_set <key:u4>
@@ -154,6 +163,7 @@ enum l2_opcode {
* Assign <val> to <ns[<key>]>
*/
L2_OP_NAMESPACE_SET_U4,
L2_OP_NAMESPACE_SET_U1,

/*
* Lookup a value from a namespace; namespace_lookup <key:u4>
@@ -161,6 +171,7 @@ enum l2_opcode {
* Push <ns[<key>]>
*/
L2_OP_NAMESPACE_LOOKUP_U4,
L2_OP_NAMESPACE_LOOKUP_U1,

/*
* Look up a value from an array; array_lookup <key:u4>
@@ -168,6 +179,7 @@ enum l2_opcode {
* Push <arr[<key>]>
*/
L2_OP_ARRAY_LOOKUP_U4,
L2_OP_ARRAY_LOOKUP_U1,

/*
* Set a value in an array; array_set <key>
@@ -175,7 +187,8 @@ enum l2_opcode {
* Read <arr>
* 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.

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

@@ -24,6 +24,7 @@ void l2_gen_free(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_placeholder(struct l2_generator *gen);
void l2_gen_discard(struct l2_generator *gen);
void l2_gen_swap_discard(struct l2_generator *gen);
void l2_gen_ret(struct l2_generator *gen);

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

@@ -72,8 +72,18 @@ void l2_gen_halt(struct l2_generator *gen) {
}

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_u4le(gen, len);
put_u4le(gen, 0);
}

void l2_gen_discard(struct l2_generator *gen) {
@@ -101,49 +111,63 @@ void l2_gen_number(struct l2_generator *gen, double num) {

void l2_gen_atom(struct l2_generator *gen, char **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) {
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) {
size_t id = l2_strset_get(&gen->stringset, *str);
if (id == 0) {
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;

gen->pos += aligned / sizeof(l2_word);
gen->pos += 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);
gen->strings = realloc(gen->strings, id * sizeof(*gen->strings));
gen->strings[id - 1].length = len;
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 {
free(*str);
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);
}
}
}

@@ -154,20 +178,36 @@ void l2_gen_string_copy(struct l2_generator *gen, char *str) {
l2_gen_string(gen, &s);
} else {
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) {
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) {
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) {
@@ -176,36 +216,66 @@ void l2_gen_namespace(struct l2_generator *gen) {

void l2_gen_namespace_set(struct l2_generator *gen, char **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) {
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) {
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) {
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) {
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) {
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) {
@@ -218,43 +288,78 @@ void l2_gen_dynamic_set(struct l2_generator *gen) {

void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **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) {
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) {
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) {
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) {
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) {
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) {
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) {

+ 2
- 2
lib/loader.c View File

@@ -45,8 +45,8 @@ int l2_bc_load(FILE *inf, struct l2_io_writer *w) {
((uint32_t)version_buf[2]) << 16 |
((uint32_t)version_buf[3]) << 24;
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",
version, l2_bytecode_version);
return -1;

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

@@ -147,8 +147,8 @@ static int parse_function_literal(
w.w.write = l2_io_mem_write;
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;

@@ -161,15 +161,16 @@ static int parse_function_literal(
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);

l2_gen_function(gen, pos);

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

@@ -15,6 +15,10 @@ static l2_word read_u4le(unsigned char *ops, size_t *ptr) {
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) {
unsigned char *data = &ops[*ptr];
uint64_t integer = 0 |
@@ -169,6 +173,9 @@ void l2_vm_print_op(unsigned char *ops, size_t opcount, size_t *ptr) {
case L2_OP_FUNC_CALL_U4:
printf("FUNC_CALL %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_FUNC_CALL_U1:
printf("FUNC_CALL %02x\n", read_u1le(ops, ptr));
return;

case L2_OP_FUNC_CALL_INFIX:
printf("FUNC_CALL_INFIX\n");
@@ -177,18 +184,30 @@ void l2_vm_print_op(unsigned char *ops, size_t opcount, size_t *ptr) {
case L2_OP_RJMP_U4:
printf("RJMP %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_RJMP_U1:
printf("RJMP %02x\n", read_u1le(ops, ptr));
return;

case L2_OP_STACK_FRAME_LOOKUP_U4:
printf("STACK_FRAME_LOOKUP %08x\n", read_u4le(ops, ptr));
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:
printf("STACK_FRAME_SET %08x\n", read_u4le(ops, ptr));
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:
printf("STACK_FRAME_REPLACE %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_STACK_FRAME_REPLACE_U1:
printf("STACK_FRAME_REPLACE %02x\n", read_u1le(ops, ptr));
return;

case L2_OP_RET:
printf("RET\n");
@@ -201,6 +220,9 @@ void l2_vm_print_op(unsigned char *ops, size_t opcount, size_t *ptr) {
case L2_OP_ALLOC_ATOM_U4:
printf("ALLOC_ATOM %08x\n", read_u4le(ops, ptr));
return;
case L2_OP_ALLOC_ATOM_U1:
printf("ALLOC_ATOM %02x\n", read_u1le(ops, ptr));
return;

case L2_OP_ALLOC_REAL_D8:
printf("ALLOC_REAL %f\n", read_d8le(ops, ptr));
@@ -213,9 +235,19 @@ void l2_vm_print_op(unsigned char *ops, size_t opcount, size_t *ptr) {
printf("ALLOC_BUFFER_STATIC %08x %08x\n", w1, w2);
}
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:
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;

case L2_OP_ALLOC_NAMESPACE:
@@ -223,24 +255,39 @@ void l2_vm_print_op(unsigned char *ops, size_t opcount, size_t *ptr) {
return;

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;

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;

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;

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;

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

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

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

@@ -379,6 +379,10 @@ static l2_word read_u4le(struct l2_vm *vm) {
return ret;
}

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

static double read_d8le(struct l2_vm *vm) {
unsigned char *data = &vm->ops[vm->iptr];
uint64_t integer = 0 |
@@ -432,46 +436,46 @@ void l2_vm_step(struct l2_vm *vm) {
vm->sptr -= 1;
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:
{
@@ -489,12 +493,14 @@ void l2_vm_step(struct l2_vm *vm) {
vm->stack[vm->sptr++] = 0;
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;
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:
{
@@ -505,44 +511,42 @@ void l2_vm_step(struct l2_vm *vm) {
}
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:
word = alloc_val(vm);
@@ -553,50 +557,51 @@ void l2_vm_step(struct l2_vm *vm) {
vm->sptr += 1;
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;
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:
{

Loading…
Cancel
Save