summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2019-03-07 17:28:52 +0200
committerJari Vetoniemi <mailroxas@gmail.com>2019-03-07 17:28:52 +0200
commitd0259b21becfa366bde486f90112b83d3ba6ec09 (patch)
tree8f99b1d0b01e07a5a6d7f4baea6c2ccfe1b07cfa
parent50e58bdd111ae4603c30314a656f57efa9d7f16c (diff)
-rw-r--r--GNUmakefile5
-rw-r--r--misc/radare2/asm_fspec.c13
-rw-r--r--spec/ability.fspec30
-rw-r--r--src/bin/fspec-dump.c22
-rw-r--r--src/compiler/compiler.lm137
5 files changed, 67 insertions, 140 deletions
diff --git a/GNUmakefile b/GNUmakefile
index a2be9ac..fd03496 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -13,7 +13,7 @@ override CPPFLAGS ?= -D_FORTIFY_SOURCE=2
override CPPFLAGS += -Isrc
override COLMFLAGS += -Isrc/compiler
-bins = fspec-info fspec-dump dec2bin xidec xi2path xils xifile uneaf
+bins = fspec-info fspec-dump dec2bin xidec xi2path xils xifile uneaf uncws
all: $(bins)
%.c: %.lm
@@ -49,6 +49,9 @@ xifile: src/bin/xi/xifile.c
uneaf: private LDLIBS += $(shell pkg-config --libs-only-l zlib)
uneaf: src/bin/fw/uneaf.c
+uncws: private LDLIBS += $(shell pkg-config --libs-only-l zlib)
+uncws: src/bin/bsw/uncws.c
+
install-bin: $(bins)
install -Dm755 $^ -t "$(DESTDIR)$(PREFIX)$(bindir)"
diff --git a/misc/radare2/asm_fspec.c b/misc/radare2/asm_fspec.c
index 9eb28ea..b93450e 100644
--- a/misc/radare2/asm_fspec.c
+++ b/misc/radare2/asm_fspec.c
@@ -13,11 +13,9 @@ enum fspec_instruction {
INS_PUSH,
INS_PUSHR,
INS_POP,
- INS_INCR,
INS_OP,
INS_QUEUE,
INS_IO,
- INS_EXEC,
INS_CALL,
INS_JMP,
INS_JMPIF
@@ -55,12 +53,10 @@ ins_name_str(const enum fspec_instruction name)
case INS_REG: return "reg";
case INS_PUSH: return "push";
case INS_PUSHR: return "pushr";
- case INS_INCR: return "incr";
case INS_POP: return "pop";
case INS_OP: return "op";
case INS_QUEUE: return "queue";
case INS_IO: return "io";
- case INS_EXEC: return "exec";
case INS_CALL: return "call";
case INS_JMP: return "jmp";
case INS_JMPIF: return "jmpif";
@@ -108,19 +104,20 @@ disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len)
} u = {0};
memcpy(u.v, buf, R_MIN(1, (size_t)len));
- const uint8_t insw = 1 << u.ins.n;
+ uint8_t insw = 1 << u.ins.n;
memcpy(u.v, buf, R_MIN(insw, len));
const char *buf_asm = "invalid";
- const bool reg_arg = (u.ins.name == INS_PUSHR || u.ins.name == INS_INCR || u.ins.name == INS_POP ||
- u.ins.name == INS_EXEC || u.ins.name == INS_CALL);
+ const bool reg_arg = (u.ins.name == INS_PUSHR || u.ins.name == INS_POP || u.ins.name == INS_CALL);
if (u.ins.name == INS_OP)
buf_asm = sdb_fmt("%s %s", ins_name_str(u.ins.name), op_name_str(u.ins.v));
else if (reg_arg)
buf_asm = sdb_fmt("%s r%" PRIu64, ins_name_str(u.ins.name), (uint64_t)u.ins.v);
- else
+ else if (u.ins.v != ((uint64_t)1 << 57) - 1)
buf_asm = sdb_fmt("%s %" PRIu64, ins_name_str(u.ins.name), (uint64_t)u.ins.v);
+ else
+ insw = 1; // ff invalid
r_strbuf_set(&op->buf_asm, buf_asm);
return (op->size = insw + (u.ins.name == INS_REG ? u.ins.v : 0));
diff --git a/spec/ability.fspec b/spec/ability.fspec
index 5a695a0..fa1281b 100644
--- a/spec/ability.fspec
+++ b/spec/ability.fspec
@@ -42,30 +42,16 @@ struct dat {
// PUSH<v> | 0x02 | Pushes `v` to the stack.
// PUSHR<r?> | 0x03 | Pushes the contents of register `r?` to the stack.
// POP<r?> [v] | 0x04 | Pops `v` into register `r?`.
-// INCR<r?> | 0x05 | Increments the register `r?` by one.
-// OP<op> [...] | 0x06 | Performs operation specified by the `op`, and pushes the result to the stack.
-// QUEUE<len> (...) | 0x07 | Queues next `len` bytes for execution for the next `IO` instruction.
+// OP<op> [...] | 0x05 | Performs operation specified by the `op`, and pushes the result to the stack.
+// QUEUE<len> (...) | 0x06 | Queues next `len` bytes for execution for the next `IO` instruction.
// * * The code is executed before or after `IO` instruction, depending whether VM is packing or unpacking.
-// IO<sz> (...) | 0x08 | Unpacking: Reads data from external VM input (usually a file) to register pointed by `r1`.
-// * * Packing: Writes data to external VM output (usually a file) from register pointed by `r1`.
+// IO<sz> [r?] (...) | 0x07 | Unpacking: Reads data from external VM input (usually a file) to register `r?`.
+// * * Packing: Writes data to external VM output (usually a file) from register `r?`.
// * * `sz` is the size of the element in bits.
// * * Rest of the stack is the number of elements, if empty, the elements to read/write is 1.
-// EXEC<r?> [r??] (...) | 0x09 | Sets `r1` to `r??` and executes instructions stored in register `r?`.
-// * * Rest of the stack is the number of times to execute, if empty, execution happens only once.
-// * * `r1` will be saved and restored during this instruction.
-// CALL<r?> (...) | 0x0A | Calls a function. The name of the function is stored in register `r?`.
-// JMP<off> | 0x0B | Jumps to the `off` (in bytes).
-// JMPIF<off> [v] | 0x0C | Performs `JMP`, if `v` is true.
-// STRUCT<r?> [r??] | 0x0D | Describes register `r?` as struct structure. register `r??` contains the name of the struct.
-// SELECT<r?> | 0x0E | Describes register `r?` as select structure.
-// FIELD<r?> (...) | 0x0F | Links field to last structure. register `r?` contains the name of the field.
-// * * Rest of the stack contains register indices for registers that are instances of this field.
-// BSZ<s:1, v> [sz] | 0x10 | Describes last field as a primitive field. `s` describes whether the field is signed. `v` describes how the
-// * * field should be represented. `sz` contains the size of field in bits.
-// REF<r?> | 0x11 | Describes field as a substructure. register `r?` contains the structure definition.
-// FDIMENSION<sz> | 0x12 | Adds fixed dimension to a field. `sz` indicates the size of the dimension.
-// VDIMENSION | 0x13 | Adds variable length dimension to a field.
-// ENUM<r?> | 0x14 | Links field to a enum
+// CALL<r?> (...) | 0x08 | Calls a function. The name of the function is stored in register `r?`.
+// JMP<off> | 0x09 | Jumps to the `off` (in bytes).
+// JMPIF<off> [v] | 0x0A | Performs `JMP`, if `v` is true.
//
// List of operations for the `OP` instruction:
// Name | Hex | Argc | Description
@@ -91,7 +77,7 @@ struct dat {
// CTERNARY | 0x13 | 3 | Conditional ternary operation `v1 ? v2 : v3`
// SUBSCRIPT | 0x14 | 2 | Subscript operation `v1[v2]`
//
-// List of visuals for the `PIO` instruction:
+// List of visuals:
// Name | Hex | Representation
// NUL | 0x00 | None
// DEC | 0x01 | Decimal
diff --git a/src/bin/fspec-dump.c b/src/bin/fspec-dump.c
index e7993e6..5732018 100644
--- a/src/bin/fspec-dump.c
+++ b/src/bin/fspec-dump.c
@@ -164,11 +164,9 @@ enum fspec_instruction {
INS_PUSH,
INS_PUSHR,
INS_POP,
- INS_INCR,
INS_OP,
INS_QUEUE,
INS_IO,
- INS_EXEC,
INS_CALL,
INS_JMP,
INS_JMPIF,
@@ -415,10 +413,6 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co
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);
@@ -428,6 +422,7 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co
break;
case INS_IO: {
const uint64_t R = stack_pop_num(&ctx->S, &ctx->mem);
+ assert(R > 0 && R < ARRAY_SIZE(ctx->R.value));
fprintf(stderr, "IO: sz: %lu, R: %lu\n", insv, R);
ctx->R.value[R].off = ctx->mem.ptr;
const uint64_t szb = DIV_ROUND_UP(insv, CHAR_BIT), bpe = (szb * CHAR_BIT) / insv;
@@ -442,21 +437,6 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co
return true;
}
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: {
fprintf(stderr, "CALL R: %lu\n", insv);
ctx->S.numv = 0;
diff --git a/src/compiler/compiler.lm b/src/compiler/compiler.lm
index 502422d..28e7f96 100644
--- a/src/compiler/compiler.lm
+++ b/src/compiler/compiler.lm
@@ -241,7 +241,6 @@ lookup(type:str, name:str, s:scope)
global g_cscope:map<any, scope> = new map<any, scope>()
global g_regs:map<any, int> = new map<any, int>()
-global g_offs:map<any, int> = new map<any, int>()
global g_ops:map<str, int> = new map<str, int>()
global g_visuals:map<str, int> = new map<str, int>()
global g_types:map<str, int> = new map<str, int>()
@@ -283,22 +282,19 @@ global INS_REG:int = 1
global INS_PUSH:int = 2
global INS_PUSHR:int = 3
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
+global INS_OP:int = 5
+global INS_QUEUE:int = 6
+global INS_IO:int = 7
+global INS_CALL:int = 8
+global INS_JMP:int = 9
+global INS_JMPIF:int = 10
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_r1:int = 1
-global g_regc:int = g_r1 + 1
+global g_regc:int = 1
void
new_reg(v:any, data:str)
@@ -334,6 +330,11 @@ find_data_in(s:any)
write_ins(INS_VERSION, 1)
write_ins_with_data(INS_REG, '')
+for d:fspec::declaration::type in source {
+ if (d.primitive)
+ new_reg(%d, nil)
+}
+
for e:expr::paren::type in source
find_data_in(e.collapsed)
for e:expr::bracket::type in source
@@ -343,12 +344,14 @@ for e:expr::arg::type in source
for f:reference::function::type in source
write_data_if_not_there($f.name)
for d:fspec::declaration::type in source {
- if (d.name)
- write_data_if_not_there($d.name)
if (d.container && d.container.data.name)
write_data_if_not_there($d.container.data.name)
+ if (d.name)
+ write_data_if_not_there($d.name)
}
+print("ASD\n")
+
void
write_expr(expr:collapser::reducer::collapsed)
{
@@ -377,12 +380,10 @@ write_expr(expr:collapser::reducer::collapsed)
off:int = 0
for r:reference::variable::type in vop {
d = lookup('variable', $r.name, s)
- if (d.container) {
+ if (d.container)
s = g_cscope->find(%d.container)
- off = g_offs->find(%d.container)
- }
}
- write_ins(INS_PUSHR, off + g_regs->find(%d) - off)
+ write_ins(INS_PUSHR, g_regs->find(%d))
} else {
write_ins(INS_OP, g_ops->find($vop.op))
}
@@ -418,9 +419,6 @@ 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) {
@@ -436,10 +434,19 @@ write_declaration(d:fspec::declaration::type, index:int)
}
if (!c) {
+ write_ins(INS_PUSH, index)
write_ins(INS_IO, d.primitive.bits)
} else {
- write_ins(INS_PUSH, g_offs->find(%c))
- write_ins(INS_EXEC, g_regs->find(%c))
+ for i:fspec::container::strukt::item in repeat(d.container.data.items) {
+ if (i.data.name) {
+ write_declaration(i.data, index)
+ index = index + 1
+ } else if (i.data.function) {
+ for a:expr::arg::type in i.data.function
+ write_expr(a.collapsed.result)
+ write_ins(INS_CALL, g_regs->find($i.data.function.name))
+ }
+ }
}
if (d.extra) {
@@ -448,40 +455,8 @@ write_declaration(d:fspec::declaration::type, index:int)
}
}
-void
-walk1(d:fspec::declaration::type)
-{
- 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)
- walk1(i.data)
-
- for i:fspec::container::select::item in repeat(d.container.data.items)
- walk1(i.data)
-
- 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)
- }
-
- for i:fspec::container::strukt::item in repeat(d.container.data.items) {
- if (i.data.primitive)
- new_reg(%i.data, nil)
- }
-
- for i:fspec::container::select::item in repeat(d.container.data.items) {
- if (i.data.primitive)
- new_reg(%i.data, nil)
- }
-}
-
-void
-walk2(d:fspec::declaration::type)
+int
+walk2(d:fspec::declaration::type, index:int)
{
if (!d.container) {
print('something went wrong!\n')
@@ -497,37 +472,22 @@ walk2(d:fspec::declaration::type)
insert('variable', $i.decl.name, %i.decl)
for i:fspec::container::strukt::item in repeat(d.container.data.items) {
- if (i.data.container)
- walk2(i.data)
- if (i.data.name)
- insert('variable', $i.data.name, %i.data)
- }
-
- for i:fspec::container::select::item in repeat(d.container.data.items) {
- if (i.data.container)
- walk2(i.data)
- if (i.data.name)
- insert('variable', $i.data.name, %i.data)
- }
-
- if (!d.name) {
- write_ins(INS_PUSH, g_offs->find(%d.container))
- write_ins(INS_POP, g_r1)
- }
-
- index:int = 0
- for i:fspec::container::strukt::item in repeat(d.container.data.items)
if (i.data.name) {
+ insert('variable', $i.data.name, %i.data)
write_declaration(i.data, index)
index = index + 1
} else if (i.data.function) {
for a:expr::arg::type in i.data.function
write_expr(a.collapsed.result)
write_ins(INS_CALL, g_regs->find($i.data.function.name))
+ } else if (i.data.container) {
+ index = walk2(i.data, index)
}
+ }
for i:fspec::container::select::item in repeat(d.container.data.items) {
if (i.data.name) {
+ insert('variable', $i.data.name, %i.data)
if (i.expr) {
write_expr(d.container.data.select.collapsed.result)
write_expr(i.expr.collapsed.result)
@@ -535,26 +495,27 @@ walk2(d:fspec::declaration::type)
}
write_declaration(i.data, index)
index = index + 1
+ } else if (i.data.container) {
+ index = walk2(i.data, index)
}
}
- if (insbuf_written()) {
- new_reg(%d.container, flush_insbuf())
- print(flush_insbuf())
- }
-
g_cscope->insert(%d, g_scopes->top)
if ($d.container.data.type != 'enum')
pop_scope()
-}
-for d:fspec::declaration::type in repeat(source.items)
- walk1(d)
+ return index
+}
push_scope()
-for d:fspec::declaration::type in repeat(source.items)
- walk2(d)
-pop_scope()
+index:int = 1
+for d:fspec::declaration::type in repeat(source.items) {
+ walk2(d, index)
-print(flush_insbuf())
+ if (insbuf_written()) {
+ write_ins_with_data(INS_REG, flush_insbuf())
+ print(flush_insbuf())
+ }
+}
+pop_scope()