summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2018-10-19 14:35:35 +0300
committerJari Vetoniemi <mailroxas@gmail.com>2018-10-19 14:35:35 +0300
commit7f0cb1b2deb0c46cbef02eded30a16f0432d5bdc (patch)
treea199bc20e569184a815f550d22c6dddd4c8783cd /src
parent290a1c5179de0e3999527336495e6931950114bb (diff)
remote work commit
Diffstat (limited to 'src')
-rw-r--r--src/bin/fspec-dump.c65
-rw-r--r--src/compiler/compiler.lm57
-rw-r--r--src/compiler/native.c30
3 files changed, 87 insertions, 65 deletions
diff --git a/src/bin/fspec-dump.c b/src/bin/fspec-dump.c
index 195674f..e7993e6 100644
--- a/src/bin/fspec-dump.c
+++ b/src/bin/fspec-dump.c
@@ -1,3 +1,4 @@
+#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -162,7 +163,8 @@ enum fspec_instruction {
INS_REG,
INS_PUSH,
INS_PUSHR,
- INS_STORE,
+ INS_POP,
+ INS_INCR,
INS_OP,
INS_QUEUE,
INS_IO,
@@ -229,16 +231,42 @@ struct fspec_ctx {
struct fspec_istream ir, binary;
};
+static uint8_t
+bytes_for_v(const uint64_t v)
+{
+ for (uint8_t n = 0; n < 4; ++n) {
+ const uint8_t bytes = (1 << n);
+ if (v < (uint64_t)(1 << (CHAR_BIT * bytes)))
+ return bytes;
+ }
+ errx(EXIT_FAILURE, "number `%" PRIu64 "` is too big", v);
+ return 0;
+}
+
static void
-stack_push_num(struct fspec_stack *stack, struct fspec_buffer *buf, const uint64_t v)
+register_set_num(struct fspec_register *r, struct fspec_buffer *buf, const uint64_t v)
{
- assert(stack->numv < ARRAY_SIZE(stack->value));
- const uint8_t bsz = DIV_ROUND_UP(__builtin_ctzl((v ? v : 1)), CHAR_BIT);
- stack->value[stack->numv++] = (struct fspec_register){ .off = buf->ptr, .len = bsz };
+ const uint8_t bsz = bytes_for_v(v);
+ *r = (struct fspec_register){ .off = buf->ptr, .len = bsz };
const union { uint8_t u8[sizeof(v)]; uint64_t v; } u = { .v = v };
fspec_buffer_write(buf, u.u8, bsz);
}
+static uint64_t
+register_get_num(const struct fspec_register *r, const struct fspec_buffer *buf)
+{
+ union { uint8_t u8[sizeof(uint64_t)]; uint64_t v; } u = {0};
+ memcpy(u.u8, buf->data + r->off, MIN(r->len, sizeof(u.u8)));
+ return (u.v << r->shift[0]) >> r->shift[1];
+}
+
+static void
+stack_push_num(struct fspec_stack *stack, struct fspec_buffer *buf, const uint64_t v)
+{
+ assert(stack->numv < ARRAY_SIZE(stack->value));
+ register_set_num(&stack->value[stack->numv++], buf, v);
+}
+
static void
stack_push(struct fspec_stack *stack, struct fspec_register *value)
{
@@ -257,10 +285,7 @@ static uint64_t
stack_pop_num(struct fspec_stack *stack, const struct fspec_buffer *buf)
{
assert(stack->numv > 0);
- const struct fspec_register v = stack->value[--stack->numv];
- union { uint8_t u8[sizeof(uint64_t)]; uint64_t v; } u = {0};
- memcpy(u.u8, buf->data + v.off, MIN(v.len, sizeof(u.u8)));
- return (u.v << v.shift[0]) >> v.shift[1];
+ return register_get_num(&stack->value[--stack->numv], buf);
}
static bool
@@ -356,11 +381,11 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co
for (const uint8_t *pc = ir; pc < ir + irlen;) {
union {
struct { unsigned name:5; unsigned n:2; uint64_t v:57; } ins;
- uint8_t v[16];
+ uint8_t v[sizeof(uint64_t)];
} u = {0};
- memcpy(u.v, pc, sizeof(u.v[0]));
- const uint8_t insw = sizeof(uint16_t) * (1 << u.ins.n);
+ memcpy(u.v, pc, 1);
+ const uint8_t insw = 1 << u.ins.n;
memcpy(u.v, pc, insw);
pc += insw;
@@ -386,10 +411,14 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co
fprintf(stderr, "PUSHR R: %lu\n", insv);
stack_push(&ctx->S, &ctx->R.value[insv]);
break;
- case INS_STORE:
- fprintf(stderr, "STORE R: %lu\n", insv);
+ case INS_POP:
+ fprintf(stderr, "POP R: %lu\n", insv);
stack_pop(&ctx->S, &ctx->R.value[insv]);
break;
+ case INS_INCR:
+ fprintf(stderr, "INCR R: %lu\n", insv);
+ register_set_num(&ctx->R.value[insv], &ctx->mem, register_get_num(&ctx->R.value[insv], &ctx->mem) + 1);
+ break;
case INS_OP:
fprintf(stderr, "OP op: %lu\n", insv);
do_op(ctx, insv);
@@ -408,20 +437,24 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co
assert(ctx->mem.ptr + szb * nmemb <= ctx->mem.size);
ctx->mem.ptr += ctx->binary.read(ctx, ctx->mem.data + ctx->mem.ptr, szb * nmemb);
} while (ctx->S.numv);
+ ctx->R.value[R].len = ctx->mem.ptr - ctx->R.value[R].off;
if (ctx->mem.ptr == ctx->R.value[R].off)
return true;
- ctx->R.value[R].len = ctx->mem.ptr - ctx->R.value[R].off;
}
break;
case INS_EXEC: {
fprintf(stderr, "EXEC R: %lu\n", insv);
+ const struct fspec_register old_r1 = ctx->R.value[1];
+ stack_pop(&ctx->S, &ctx->R.value[1]);
uint64_t nmemb = 1;
do {
nmemb *= (ctx->S.numv ? stack_pop_num(&ctx->S, &ctx->mem) : 1);
+ fprintf(stderr, "off: %lu len: %lu nmemb: %lu\n", ctx->R.value[insv].off, ctx->R.value[insv].len, nmemb);
for (uint64_t i = 0; i < nmemb; ++i)
if (fspec_execute(ctx, ctx->mem.data + ctx->R.value[insv].off, ctx->R.value[insv].len, ind + INDSTP))
return true;
} while (ctx->S.numv);
+ ctx->R.value[1] = old_r1;
}
break;
case INS_CALL: {
@@ -494,7 +527,7 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co
pc = (r1 ? ir + insv : pc);
break;
default:
- errx(EXIT_FAILURE, "unknown instruction: %u\n", u.ins.name);
+ errx(EXIT_FAILURE, "unknown instruction: %u :: %u\n", u.ins.name, insw);
}
}
return false;
diff --git a/src/compiler/compiler.lm b/src/compiler/compiler.lm
index 1ca7705..502422d 100644
--- a/src/compiler/compiler.lm
+++ b/src/compiler/compiler.lm
@@ -167,6 +167,7 @@ if (!source) {
struct scope
names:map<str, map<str, any>>
+ roff:int
end
global g_scopes:list<scope> = new list<scope>()
@@ -281,21 +282,23 @@ global INS_VERSION:int = 0
global INS_REG:int = 1
global INS_PUSH:int = 2
global INS_PUSHR:int = 3
-global INS_STORE:int = 4
-global INS_OP:int = 5
-global INS_QUEUE:int = 6
-global INS_IO:int = 7
-global INS_EXEC:int = 8
-global INS_CALL:int = 9
-global INS_JMP:int = 10
-global INS_JMPIF:int = 11
+global INS_POP:int = 4
+global INS_INCR:int = 5
+global INS_OP:int = 6
+global INS_QUEUE:int = 7
+global INS_IO:int = 8
+global INS_EXEC:int = 9
+global INS_CALL:int = 10
+global INS_JMP:int = 11
+global INS_JMPIF:int = 12
int insbuf_written() = c_insbuf_written
str flush_insbuf() = c_flush_insbuf
void write_ins(ins:int, num:int) = c_write_ins
void write_ins_with_data(ins:int, data:str) = c_write_ins_with_data
-global g_regc:int = 1
+global g_r1:int = 1
+global g_regc:int = g_r1 + 1
void
new_reg(v:any, data:str)
@@ -329,6 +332,8 @@ find_data_in(s:any)
}
write_ins(INS_VERSION, 1)
+write_ins_with_data(INS_REG, '')
+
for e:expr::paren::type in source
find_data_in(e.collapsed)
for e:expr::bracket::type in source
@@ -344,10 +349,6 @@ for d:fspec::declaration::type in source {
write_data_if_not_there($d.container.data.name)
}
-global g_fcr:int = g_regc
-write_ins_with_data(INS_REG, '')
-g_regc = g_regc + 1
-
void
write_expr(expr:collapser::reducer::collapsed)
{
@@ -381,7 +382,7 @@ write_expr(expr:collapser::reducer::collapsed)
off = g_offs->find(%d.container)
}
}
- write_ins(INS_PUSHR, off + g_regs->find(%d))
+ write_ins(INS_PUSHR, off + g_regs->find(%d) - off)
} else {
write_ins(INS_OP, g_ops->find($vop.op))
}
@@ -417,6 +418,9 @@ write_declaration(d:fspec::declaration::type, index:int)
c:fspec::container::type = d.container
if (d.cref) c = lookup($d.cref, $d.parent, nil)
+ if (!c && index > 0)
+ write_ins(INS_INCR, g_r1)
+
locs:map<any, int> = new map<any, int>()
if (d.extra) {
for l:fspec::declaration::dimension in repeat(d.extra.dimension) {
@@ -432,15 +436,9 @@ write_declaration(d:fspec::declaration::type, index:int)
}
if (!c) {
- write_ins(INS_PUSHR, g_fcr)
- if (index != 0) {
- write_ins(INS_PUSH, index)
- write_ins(INS_OP, g_ops->find('#+'))
- }
write_ins(INS_IO, d.primitive.bits)
} else {
write_ins(INS_PUSH, g_offs->find(%c))
- write_ins(INS_STORE, g_fcr)
write_ins(INS_EXEC, g_regs->find(%c))
}
@@ -453,20 +451,19 @@ write_declaration(d:fspec::declaration::type, index:int)
void
walk1(d:fspec::declaration::type)
{
- if (!d.container) {
- print('something went wrong!\n')
- exit(1)
- }
+ c:fspec::container::type = d.container
+ if (d.cref) c = lookup($d.cref, $d.parent, nil)
+
+ if (!c || !d.name)
+ return 0
for i:fspec::container::strukt::item in repeat(d.container.data.items)
- if (i.data.container)
- walk1(i.data)
+ walk1(i.data)
for i:fspec::container::select::item in repeat(d.container.data.items)
- if (i.data.container)
- walk1(i.data)
+ walk1(i.data)
- g_offs->insert(%d.container, g_regc)
+ g_offs->insert(%d, g_regc)
for i:fspec::container::enum::item in repeat(d.container.data.items) {
# somehow need to get this constant time (not reg)
@@ -515,7 +512,7 @@ walk2(d:fspec::declaration::type)
if (!d.name) {
write_ins(INS_PUSH, g_offs->find(%d.container))
- write_ins(INS_STORE, g_fcr)
+ write_ins(INS_POP, g_r1)
}
index:int = 0
diff --git a/src/compiler/native.c b/src/compiler/native.c
index bbb0060..feac349 100644
--- a/src/compiler/native.c
+++ b/src/compiler/native.c
@@ -1,5 +1,6 @@
#include <colm/tree.h>
#include <colm/bytecode.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
@@ -111,35 +112,26 @@ c_op_stack_pop(program_t *prg, tree_t **sp, value_t a)
}
static uint8_t
-bits_for_n(const uint8_t n, const uint8_t used)
-{
- return 16 * (1 << n) - used;
-}
-
-static uint8_t
n_for_v(const uint64_t v, const uint8_t used)
{
- const uint8_t bits = __builtin_ctzl((v ? v : 1));
- if (used <= 16 && bits < bits_for_n(0, used))
- return 0;
- else if (used <= 32 && bits < bits_for_n(1, used))
- return 1;
- else if (used <= 64 && bits < bits_for_n(2, used))
- return 2;
-
- errx(EXIT_FAILURE, "numbers over 57 bits not supported right now.. sorry :D");
+ for (uint8_t n = 0; n < 4; ++n) {
+ const uint8_t bits = CHAR_BIT * (1 << n);
+ if (used < bits && v < (uint64_t)(1 << (bits - used)))
+ return n;
+ }
+ errx(EXIT_FAILURE, "number `%" PRIu64 "` is too big to be compiled in instruction", v);
return 3;
}
static void
-vle_instruction(const uint8_t name, const uint64_t v, uint8_t out[16], uint8_t *out_written)
+vle_instruction(const uint8_t name, const uint64_t v, uint8_t out[8], uint8_t *out_written)
{
assert(out && out_written);
const union {
struct { unsigned name:5; unsigned n:2; uint64_t v:57; } ins;
- uint8_t v[16];
+ uint8_t v[sizeof(uint64_t)];
} u = { .ins = { .name = name, .n = n_for_v(v, 7), .v = v } };
- *out_written = sizeof(uint16_t) * (1 << u.ins.n);
+ *out_written = sizeof(u.v[0]) * (1 << u.ins.n);
memcpy(out, u.v, *out_written);
}
@@ -165,7 +157,7 @@ c_insbuf_written(program_t *prg, tree_t **sp)
void
c_write_ins(program_t *prg, tree_t **sp, value_t a, value_t b)
{
- uint8_t out[16], written;
+ uint8_t out[8], written;
vle_instruction(a, b, out, &written);
memcpy(&insbuf.data[insbuf.written], out, written);
insbuf.written += written;