From 32a7568a12485081ddd4d89e4f02cf07e312cef8 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Tue, 20 Feb 2018 22:55:49 -0800 Subject: [PATCH 1/1] initial commit --- codegen.mud | 154 +++++++++++++++++++++++++++++++++++++++++++ doc/distribution.dot | 59 +++++++++++++++++ gen.c | 105 +++++++++++++++++++++++++++++ main.c | 107 ++++++++++++++++++++++++++++++ 4 files changed, 425 insertions(+) create mode 100644 codegen.mud create mode 100644 doc/distribution.dot create mode 100644 gen.c create mode 100644 main.c diff --git a/codegen.mud b/codegen.mud new file mode 100644 index 0000000..08da96b --- /dev/null +++ b/codegen.mud @@ -0,0 +1,154 @@ +. +"> + +> + + ;"assembler name (e.g. GRTR?, SUB)" + ;"numeric opcode" + ;"argspec. see examples." + ;"C implementation (use names from argspec)" + ;"unique name (e.g. GRTRB, SUBB)" + + )> + > .i > <3 .ops> >) .results>> + >>> + > + > + + .act>)> + > "=" >> ",">> + > + > + + .act>)> + >> ": return \"" > "\";" ,CR>> + > + > + + )> + result> + ");" ,CR>) + (ELSE + > BYTE> + >> " = p[" "];" ,CR>) + (<==? <2 <1 .args>> OFFSET> + >> " = (int8_t)p[" "];" ,CR>) + (<==? <2 <1 .args>> FIX> + >> " = GETFIX(bp[p[" "]]);" ,CR>) + >)>>> + > + > + > + +) + "NAME" act) + .act>)> + > ": {" ,CR + >> + "const uint8_t * const oldp = p;" ,CR + "p += " >>>> !\; ,CR + > ,CR + "break;" ,CR !\} ,CR>> + > + > + + + +) (s "\"<%s") "NAME" act) + \\n\""> .act>)> + result> + "%hhi") + (ELSE > BYTE> + "%hhu") + (<==? <2 <1 .args>> OFFSET> + "%hhi") + (<==? <2 <1 .args>> FIX> + "fix%hhu")>)>>> + > + > + + "\"">) + (i 0) + (n >)) + )> + > + "]">> + >> + +) + "NAME" act) + .act>)> + >> ": " ,CR + "if (inlen < " >>> ") { return EBADOPARGS; };" ,CR + "*buf += snprintf(*buf, outlen, " + > + "(*p)"> + ");" ,CR + "*p += " >>> ";" ,CR + "return 0;" ,CR>> + > + > + + rhs)) JUMP(offs);" + SUB (SUB (x FIX) (y FIX) result) + SUBB (SUB (x FIX) (rhs BYTE) result) + MUL (MUL (x FIX) (y FIX) result) + HALT (HALT) "return;">> + +> + +> + +> +;> + +> + +> + +;> + +> diff --git a/doc/distribution.dot b/doc/distribution.dot new file mode 100644 index 0000000..136decb --- /dev/null +++ b/doc/distribution.dot @@ -0,0 +1,59 @@ +/* +Written in 2018 by Keziah Wesley + +To the extent possible under law, the author(s) have dedicated all +copyright and related and neighboring rights to this software to the +public domain worldwide. This software is distributed without any +warranty. + +You should have received a copy of the CC0 Public Domain Dedication +along with this software. If not, see +. +*/ + +strict digraph system { + layout = "dot"; + rankdir = LR; + + # red = runtime + + Muddle [style = filled]; + + { + rank = same; + MUM [style = filled, fillcolor = red, fontcolor = white, shape = box]; + LiteMuddle [style = filled]; + MIMC [shape = box]; + MIMops [style = filled]; + MIMOC [shape = box]; + } + + { + rank = same; + MIM [style = filled, fillcolor = red, fontcolor = white, shape = box]; + C [style = filled]; + cc [shape = box]; + opcodes [style = filled, label = "opcodes"]; + } + + native2 [style = filled, fillcolor = red, label = "native", fontcolor = white, shape = diamond]; + + LiteMuddle -> MIMC [label = "input"]; + MIMC -> MIMops [label = "output"]; + MIMops -> MIM [label = "runs on", color = red]; + MIMops -> MIMOC [label = "input"/*, weight = 0*/]; + MIMOC -> opcodes [label = "output"]; + opcodes -> native2 [label = "runs on", color = red]; + C -> cc [label = "input"]; + cc -> opcodes [label = "output"]; + + //Muddle -> MUMC [weight= 0]; + //MUMC -> MIMops; + + Muddle -> MUM [label = "runs on", color = red]; + MUM -> LiteMuddle [label = "written in"]; + + MIMC -> Muddle [label = "written in", weight = 0, style = dashed]; + MIMOC -> Muddle [label = "written in", weight = 0, style = dashed]; + MIM -> C [label = "written in"]; +} diff --git a/gen.c b/gen.c new file mode 100644 index 0000000..916a659 --- /dev/null +++ b/gen.c @@ -0,0 +1,105 @@ +/* +Copyright (C) 2017-2018 Keziah Wesley + +You can redistribute and/or modify this file under the terms of the +GNU Affero General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any +later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public +License along with this file. If not, see +. +*/ +/* GENERATED FILE. CHANGES WILL BE OVERRIDDEN. +This file is generated by Muddle code; it is included in the distribution for bootstrapping. */ +enum {I_HALT=4,I_MUL=3,I_SUBB=2,I_SUB=1,I_GRTRB=0,}; + +void run (const uint8_t * p0, const uint8_t * p, object * bp, int sp) { +for (;;) { +TRACE(p0, p); +switch (*p) { +case I_HALT: { +const uint8_t * const oldp = p; +p += 1; +return; +break; +} +case I_MUL: { +int64_t x = GETFIX(bp[p[1]]); +int64_t y = GETFIX(bp[p[2]]); +object * _res = RESULT(3); +const uint8_t * const oldp = p; +p += 4; +*_res = (NEWFIX( x * y )); +break; +} +case I_SUBB: { +int64_t x = GETFIX(bp[p[1]]); +uint8_t rhs = p[2]; +object * _res = RESULT(3); +const uint8_t * const oldp = p; +p += 4; +*_res = (NEWFIX( x - rhs )); +break; +} +case I_SUB: { +int64_t x = GETFIX(bp[p[1]]); +int64_t y = GETFIX(bp[p[2]]); +object * _res = RESULT(3); +const uint8_t * const oldp = p; +p += 4; +*_res = (NEWFIX( x - y )); +break; +} +case I_GRTRB: { +int64_t x = GETFIX(bp[p[1]]); +uint8_t rhs = p[2]; +uint8_t invert = p[3]; +int8_t offs = (int8_t)p[4]; +const uint8_t * const oldp = p; +p += 5; +if (invert ^ (x > rhs)) JUMP(offs); +break; +} +default: assert(0 && "bad opcode"); +} +} +} + +int snprint_op_disasm(char ** buf, size_t outlen, const uint8_t ** p, size_t inlen) +{ +switch (**p) { +case 4: +if (inlen < 0) { return EBADOPARGS; }; +*buf += snprintf(*buf, outlen, "<%s>\n", "HALT"); +*p += 0; +return 0; +case 3: +if (inlen < 3) { return EBADOPARGS; }; +*buf += snprintf(*buf, outlen, "<%s fix%hhu fix%hhu %hhi>\n", "MUL", (*p)[1], (*p)[2], (*p)[3]); +*p += 3; +return 0; +case 2: +if (inlen < 3) { return EBADOPARGS; }; +*buf += snprintf(*buf, outlen, "<%s fix%hhu %hhu %hhi>\n", "SUBB", (*p)[1], (*p)[2], (*p)[3]); +*p += 3; +return 0; +case 1: +if (inlen < 3) { return EBADOPARGS; }; +*buf += snprintf(*buf, outlen, "<%s fix%hhu fix%hhu %hhi>\n", "SUB", (*p)[1], (*p)[2], (*p)[3]); +*p += 3; +return 0; +case 0: +if (inlen < 4) { return EBADOPARGS; }; +*buf += snprintf(*buf, outlen, "<%s fix%hhu %hhu %hhu %hhi>\n", "GRTRB", (*p)[1], (*p)[2], (*p)[3], (*p)[4]); +*p += 4; +return 0; +} +return EBADOPCODE; +} + diff --git a/main.c b/main.c new file mode 100644 index 0000000..b4aa7b3 --- /dev/null +++ b/main.c @@ -0,0 +1,107 @@ +/* +Copyright (C) 2017-2018 Keziah Wesley + +You can redistribute and/or modify this file under the terms of the +GNU Affero General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any +later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public +License along with this file. If not, see +. +*/ + +#include +#include +#include +#include + +enum { + PT_UNBOUND, + PT_FIX = (1 << 16), + PT_MASK = (0x7fff << 16), +}; + +enum { + TT_UNBOUND = PT_UNBOUND, + TT_FIX = PT_FIX, +}; + +enum { + B_IF, + B_IF_NOT, +}; + +enum { + R_STACK = 0xff, +}; + +typedef struct { + uint32_t type; + uint32_t _stuff; + union { + int64_t fix; + }; +} object; + +inline static int64_t GETFIX (object o) { + assert ((o.type & PT_MASK) == PT_FIX); + return o.fix; +} +inline static object NEWFIX (int64_t v) { + return (object){ .type = TT_FIX, .fix = (v) }; +} +#define RESULT(i) (&bp[(p[i] == R_STACK) ? sp++ : p[i]]) +#define JUMP(off) do { p = (off < 0) ? oldp + off : p + off; } while (0) + +int snprint_op_disasm (char ** buf, size_t outlen, const uint8_t ** p, size_t inlen); +void run (const uint8_t * op, const uint8_t * p, object * bp, int sp); + +static void trace(const uint8_t * p0, const uint8_t * p) +{ + char buf[512]; + char *b = buf; + b += snprintf(buf, 512, "%ld: ", p-p0); + int n = snprint_op_disasm (&b, 512, &p, (size_t)-1); + assert (!n); + printf(buf); +} + +enum { + EOKAY, + EBADOPCODE, + EBADOPARGS, +}; + +#define TRACE(p0, p) trace(p0, p) + +#include "gen.c" + +int main () +{ + // hand-assembled iterative factorial: + uint8_t locl_N = 0; + uint8_t locl_TMP1 = 1; + uint8_t progn[] = { + I_GRTRB, locl_N, 1, B_IF, 1, // + I_HALT, // + I_MUL, locl_N, locl_TMP1, locl_TMP1, // LOOP + I_SUBB, locl_N, 1, locl_N, // + I_GRTRB, locl_N, 1, B_IF, (uint8_t)-8, // + I_HALT, // + }; + + object stack[128]; + memset(stack, '\0', 128 * sizeof(*stack)); + stack[0] = NEWFIX(7); + stack[1] = NEWFIX(1); + + run (progn, progn, stack, 2); + printf("%lu", GETFIX(stack[1])); + return 0; +} -- 2.31.1