Some instruction selection is now happening.
authorDavid Given <dg@cowlark.com>
Sat, 24 Sep 2016 20:46:08 +0000 (22:46 +0200)
committerDavid Given <dg@cowlark.com>
Sat, 24 Sep 2016 20:46:08 +0000 (22:46 +0200)
15 files changed:
mach/proto/mcg/ir.h
mach/proto/mcg/main.c
mach/proto/mcg/mcg.h
mach/proto/mcg/mcgg_generated_footer.h
mach/proto/mcg/mcgg_generated_header.h
mach/proto/mcg/pass_instsel.c [new file with mode: 0644]
mach/proto/mcg/procedure.c
mach/proto/mcg/table
mach/proto/mcg/treebuilder.c
util/mcgg/build.lua
util/mcgg/iburg.c
util/mcgg/iburg.h
util/mcgg/ir.dat
util/mcgg/mcgg.h [new file with mode: 0644]
util/mcgg/scan.l

index 795b6dd..eaf0314 100644 (file)
@@ -33,7 +33,11 @@ struct ir
                const char* lvalue;
                struct basicblock* bvalue;
        } u;
+
+       void* state_label; /* used by the iburg instruction selector */
+
        bool is_sequence : 1;
+       bool is_generated : 1;
 };
 
 extern const char* ir_names[];
index 5be59e6..83d5101 100644 (file)
@@ -37,9 +37,10 @@ bool tracing(char k)
 {
     switch (k)
     {
+        case 0:   return true;
         case 'E': return false;
         case '0': return false;
-        case '1': return true;
+        case '1': return false;
         case '2': return true;
         default:  return true;
     }
index 4fa1b11..193ed36 100644 (file)
@@ -119,6 +119,7 @@ extern void tb_regvar(arith offset, int size, int type, int priority);
 extern void pass_convert_stack_ops(struct procedure* proc);
 extern void pass_remove_dead_blocks(struct procedure* proc);
 extern void pass_eliminate_trivial_blocks(struct procedure* proc);
+extern void pass_instruction_selector(struct procedure* proc);
 
 extern void procedure_compile(struct procedure* proc);
 
index 56bdc91..11b4020 100644 (file)
@@ -19,6 +19,7 @@ static void dumpCover(NODEPTR_TYPE p, int goalnt, int indent) {
 #endif
 }
 
+#if 0
 static NODEPTR_TYPE tree(int op, NODEPTR_TYPE l, NODEPTR_TYPE r) {
        NODEPTR_TYPE p = malloc(sizeof *p);
 
@@ -48,4 +49,5 @@ int main(void) {
        dumpCover(p, 1, 0);
        return 0;
 }
+#endif
 
index 2545e8a..36e394b 100644 (file)
@@ -1,32 +1,20 @@
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <limits.h>
-#include <stdlib.h>
+#include "mcg.h"
+#include "mcgg.h"
 
-#define TRACE
 
-#define STATE_TYPE void*
-typedef struct tree {
-       int op;
-       struct tree *kids[2];
-       STATE_TYPE state_label;
-} *NODEPTR_TYPE;
-#define OP_LABEL(p) ((p)->op)
-#define LEFT_CHILD(p) ((p)->kids[0])
-#define RIGHT_CHILD(p) ((p)->kids[1])
-#define STATE_LABEL(p) ((p)->state_label)
 #define PANIC printf
 
-static void burm_trace(NODEPTR_TYPE p, int eruleno, int cost, int bestcost) {
-#ifdef TRACE
-       extern const char *burm_string[];
-
-       fprintf(stderr, "0x%p matched %s with cost %d vs. %d\n", p,
-               burm_string[eruleno], cost, bestcost);
-#endif
+static int OP_LABEL(struct ir* ir)
+{
+       if (ir->is_generated)
+               return ir_to_esn(IR_REG, ir->size);
+       return ir_to_esn(ir->opcode, ir->size);
 }
 
-#define burm_assert(b, s) assert(b && s)
+#define LEFT_CHILD(p) ((p)->left)
+#define RIGHT_CHILD(p) ((p)->right)
+        
+#define burm_assert(b, s) assert(b)
+
+extern void burm_panic_cannot_match(struct ir* ir);
 
diff --git a/mach/proto/mcg/pass_instsel.c b/mach/proto/mcg/pass_instsel.c
new file mode 100644 (file)
index 0000000..8d1fa47
--- /dev/null
@@ -0,0 +1,87 @@
+#include "mcg.h"
+#include "mcgg.h"
+
+#if 0
+static void dumpCover(NODEPTR_TYPE p, int goalnt, int indent) {
+#ifdef TRACE
+       int eruleno = burm_rule(STATE_LABEL(p), goalnt);
+       const short *nts = burm_nts[eruleno];
+       NODEPTR_TYPE kids[10];
+       int i;
+
+       for (i = 0; i < indent; i++)
+               fprintf(stderr, " ");
+       fprintf(stderr, "%s\n", burm_string[eruleno]);
+       burm_kids(p, eruleno, kids);
+       for (i = 0; nts[i]; i++)
+       {
+               if (kids[i])
+                       dumpCover(kids[i], nts[i], indent + 1);
+               else
+                       fprintf(stderr, "failed!\n");
+       }
+#endif
+}
+#endif
+
+void burm_trace(struct ir* p, int ruleno, int cost, int bestcost) {
+       tracef('I', "I: 0x%p matched %s with cost %d vs. %d\n", p,
+               burm_string[ruleno], cost, bestcost);
+}
+
+void burm_panic_cannot_match(struct ir* ir)
+{
+       fprintf(stderr, "could not find any patterns to match:\n");
+       ir_print(0, ir);
+       fprintf(stderr, "aborting!\n");
+       exit(1);
+}
+
+static void queue_instructions(struct ir* ir, int goal)
+{
+       struct ir* children[10];
+       int ruleno = burm_rule(ir->state_label, goal);
+       const short* nts = burm_nts[ruleno];
+       int i;
+
+       burm_kids(ir, ruleno, children);
+       for (i=0; nts[i]; i++)
+               queue_instructions(children[i], nts[i]);
+
+       printf("selected insn %d: %s\n", ruleno, burm_string[ruleno]);
+}
+
+static void select_instructions(struct basicblock* bb)
+{
+       int i;
+
+       tracef('I', "I: BLOCK: %s\n", bb->name);
+
+       for (i=0; i<bb->irs_count; i++)
+       {
+               int insnno;
+               struct ir* ir = bb->irs[i];
+               burm_label(ir);
+
+               insnno = burm_rule(ir->state_label, 1);
+               if (!insnno)
+                       burm_panic_cannot_match(ir);
+
+               queue_instructions(ir, 1);
+       }
+}
+
+void pass_instruction_selector(struct procedure* proc)
+{
+    int i;
+
+    for (i=0; i<proc->blocks_count; i++)
+    {
+        struct basicblock* bb = proc->blocks[i];
+        select_instructions(bb);
+    }
+       exit(1);
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
index 8958a8b..b0bc1a0 100644 (file)
@@ -31,6 +31,8 @@ void procedure_compile(struct procedure* proc)
     pass_convert_stack_ops(proc);
 
     print_blocks('2', proc);
+
+    pass_instruction_selector(proc);
 }
 
 /* vim: set sw=4 ts=4 expandtab : */
index daf0fbb..f9f468f 100644 (file)
@@ -1,5 +1,33 @@
 PATTERNS
 
+/* Special */
+
+       reg;
+
+       PAIR(BLOCK4, BLOCK4);
+
+
+/* Miscellaneous special things */
+
+       PUSH4(in:reg)
+               emit "push %in"
+               cost 4;
+
+       reg = POP4
+               outs out:ANY
+               emit "pop %out"
+               cost 4;
+
+       RET
+               emit "ret"
+               cost 4;
+
+       SETRET4(in:reg)
+               emit "mov r0, %in"
+               cost 4;
+
+/* Memory operations */
+
        STORE4(addr:address, value:reg)
                ins value:GPR
                emit "str %value, %addr"
@@ -7,9 +35,33 @@ PATTERNS
 
        reg = LOAD4(addr:address)
                outs dest:ANY
-               emit "ld %dest, %addr"
+               emit "ldr %dest, %addr"
+               cost 4;
+
+       reg = LOAD1(addr:address)
+               outs dest:ANY
+               emit "ldrb %dest, %addr"
+               cost 4;
+
+       reg = CIU14(LOAD1(addr:address))
+               outs dest:ANY
+               emit "ldrb %dest, %addr"
+               cost 4;
+
+
+/* Locals */
+
+       reg = in:LOCAL4
+               outs out:GPR
+               emit "add %out, fp, #%in.ivalue"
                cost 4;
 
+       address = in:LOCAL4
+               fragment "[fp, #%in.ivalue]";
+
+
+/* Memory addressing modes */
+
        address = ADD4(addr:reg, offset:CONST)
                ins addr:GPR
                fragment "[%addr, #%offset.ivalue]";
@@ -18,7 +70,47 @@ PATTERNS
                ins addr:GPR
                fragment "[%addr]";
 
-       reg;
+
+/* Branches */
+
+       JUMP(addr:BLOCK4)
+               emit "b %addr.bvalue"
+               cost 4;
+
+       CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4))
+               emit "beq %trueblock.bvalue"
+               emit "bne %falseblock.bvalue"
+               cost 8;
+
+
+/* Comparisons */
+
+       tristate = COMPARES4(val1:reg, val2:aluparam)
+               outs CC
+               emit "cmp %val1, %val2"
+               cost 4;
+
+       reg = tristate
+               emit "mov %out, #0"
+               emit "movlt %out, #-1"
+               emit "movgt %out, #1"
+               cost 12;
+
+
+/* Conversions */
+
+       reg = CII14(CIU41(value:reg))
+               outs out:GPR
+               emit "sxtb %out, %value"
+               cost 4;
+
+       reg = CIU41(in:reg)
+               outs out:GPR
+               emit "and %out, %in, #0xff"
+               cost 4;
+
+
+/* ALU operations */
 
        reg = ADD4(left:reg, right:aluparam)
                ins left:GPR, right:GPR
@@ -33,7 +125,6 @@ PATTERNS
                cost 4;
 
        aluparam = value:CONST4
-               when { return false; }
                fragment "#%value.ivalue";
 
        aluparam = reg;
@@ -45,7 +136,12 @@ PATTERNS
 
        reg = value:LABEL4
                outs out:GPR
-               emit "adr %out, #value.lvalue"
+               emit "adr %out, %value.lvalue"
+               cost 4;
+
+       reg = value:BLOCK4
+               outs out:GPR
+               emit "adr %out, %value.bvalue"
                cost 4;
 
        reg = value:CONST4
index ea699d7..1b0d51d 100644 (file)
@@ -231,9 +231,9 @@ static void simple_branch2(int opcode, int size,
     materialise_stack();
     appendir(
         new_ir2(
-            IR_CJUMP, 0,
+            irop, 0,
             new_ir2(
-                irop,  size,
+                IR_COMPARES,  size,
                 left, right
             ),
             new_ir2(
@@ -260,13 +260,13 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock
 {
     switch (opcode)
     {
-        case op_zeq: compare0_branch2(opcode, leftbb, rightbb, IR_IFEQ); break;
-        case op_zlt: compare0_branch2(opcode, leftbb, rightbb, IR_IFLT); break;
-        case op_zle: compare0_branch2(opcode, leftbb, rightbb, IR_IFLE); break;
+        case op_zeq: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPEQ); break;
+        case op_zlt: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPLT); break;
+        case op_zle: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPLE); break;
 
-        case op_zne: compare0_branch2(opcode, rightbb, leftbb, IR_IFEQ); break;
-        case op_zge: compare0_branch2(opcode, rightbb, leftbb, IR_IFLT); break;
-        case op_zgt: compare0_branch2(opcode, rightbb, leftbb, IR_IFLE); break;
+        case op_zne: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPEQ); break;
+        case op_zge: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPLT); break;
+        case op_zgt: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPLE); break;
 
         case op_bra:
         {
index 8afdbc0..0485197 100644 (file)
@@ -28,7 +28,8 @@ clibrary {
                matching(filenamesof("+ircodes"), "%.c$")
        },
        hdrs = {
-               matching(filenamesof("+ircodes"), "%.h$")
+               matching(filenamesof("+ircodes"), "%.h$"),
+               "./mcgg.h"
        }
 }
 
@@ -40,7 +41,7 @@ cprogram {
                matching(filenamesof("+yacc"), "%.c$")
        },
        deps = {
-               "./*.h",
+               "./iburg.h",
                "+lib",
                "+yacc"
        }
index e581b7b..c26cfee 100644 (file)
@@ -419,7 +419,7 @@ static void print(char* fmt, ...)
 
 void printlineno(void)
 {
-       print("#line %d\n", yylineno);
+       //print("#line %d\n", yylineno);
 }
 
 /* reach - mark all non-terminals in tree t as reachable */
@@ -451,6 +451,9 @@ static void emitcase(Term p, int ntnumber)
 {
        Rule r;
 
+       if (!p->rules)
+               return;
+
        print("%1case %d: /* %S */\n", p->esn, p);
        switch (p->arity)
        {
@@ -823,7 +826,8 @@ static void emitstate(Term terms, Nonterm start, int ntnumber)
        for (p = terms; p; p = p->link)
                emitcase(p, ntnumber);
        print("%1default:\n"
-             "%2%Passert(0, PANIC(\"Bad operator %%d in %Pstate\\n\", op));\n%1}\n"
+          "%2%Ppanic_cannot_match(node);\n"
+                 "%1}\n"
              "%1return (STATE_TYPE)p;\n}\n\n");
 }
 
index 59c84a3..0ad0fde 100644 (file)
@@ -86,15 +86,6 @@ extern int yylineno;
 
 extern void printlineno(void);
 
-/* Excruciating macro which packs ir opcodes and sizes into an int for iburg's benefit.
- *
- * Sizes are mapped as: 0=1, 1=1, 2=2, 4=3, 8=4.
- */
-#define ir_to_esn(iropcode, size) \
-       ((iropcode)*4 + \
-               (((size) == 4) ? 2 : \
-                ((size) == 8) ? 3 : \
-                ((size) == 0) ? 0 : \
-                 (size-1)))
+#include "mcgg.h"
 
 #endif
index 95059a6..a7487cd 100644 (file)
@@ -7,7 +7,7 @@ S CONST
 S REG
 S LABEL
 S BLOCK
-S PAIR
+V PAIR
 S ANY
 S LOCAL
 S PHI
@@ -64,7 +64,9 @@ V CALL
  
 # Flow control --- these never return
 V JUMP
-V CJUMP
+V CJUMPEQ
+V CJUMPLT
+V CJUMPLE
 V RET
  
 # Special
diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h
new file mode 100644 (file)
index 0000000..297be18
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef MCGG_H
+#define MCGG_H
+
+/* Excruciating macro which packs ir opcodes and sizes into an int for iburg's benefit.
+ *
+ * Sizes are mapped as: 0=1, 1=1, 2=2, 4=3, 8=4.
+ */
+#define ir_to_esn(iropcode, size) \
+       ((iropcode)*4 + \
+               (((size) == 4) ? 2 : \
+                ((size) == 8) ? 3 : \
+                ((size) == 0) ? 0 : \
+                 (size-1)))
+
+
+#define STATE_TYPE void*
+typedef struct ir* NODEPTR_TYPE;
+
+#define STATE_LABEL(p) ((p)->state_label)
+
+extern void* burm_label(struct ir* ir);
+extern int burm_rule(void* state, int goalnt);
+extern const char* burm_string[];
+extern const short *burm_nts[];
+extern struct ir** burm_kids(struct ir* p, int eruleno, struct ir* kids[]);
+extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost);
+
+#endif
+
+/* vim: set sw=4 ts=4 expandtab : */
index ebcb9c1..0e0a92c 100644 (file)
@@ -22,7 +22,7 @@ static int braces = 0;
 <ECHO>[^%\n]*               fputs(yytext, outfp);
 
 <INITIAL>"{"                {
-                                yylval.string = stringf("#line %d\n", yylineno);
+                                yylval.string = ""; //stringf("#line %d\n", yylineno);
                                 braces = 1;
                                 BEGIN(CSTRING);
                                 return CFRAGMENT;