Treebuilder now gets to the bottom of my test file, merrily generating
authorDavid Given <dg@cowlark.com>
Mon, 19 Sep 2016 21:30:41 +0000 (23:30 +0200)
committerDavid Given <dg@cowlark.com>
Mon, 19 Sep 2016 21:30:41 +0000 (23:30 +0200)
(probably horribly broken) IR.

mach/proto/mcg/ir.dat
mach/proto/mcg/parse_em.c
mach/proto/mcg/treebuilder.c

index ea47cb0..4de21c0 100644 (file)
@@ -24,16 +24,20 @@ MOD
 NEG
 NOT
 
+AND
+OR
+EOR
+
 # Conversions
-FROMI1
-FROMI2
-FROMI4
-FROMI8
-
-FROMU1
-FROMU2
-FROMU4
-FROMU8
+CII1
+CII2
+CII4
+CII8
+
+CIU1
+CIU2
+CIU4
+CIU8
 
 # Tristate comparisons
 COMPARES
index 9310dda..13320fe 100644 (file)
@@ -4,6 +4,8 @@ static struct e_instr insn;
 static struct procedure* current_proc;
 static struct basicblock* current_bb;
 
+static void queue_insn_label(int opcode, const char* label, arith offset);
+
 static const char* type_to_str(int type)
 {
        switch (type)
@@ -57,6 +59,12 @@ static const char* dlabel_to_str(label l)
     return aprintf("__D%d", l);
 }
 
+static void terminate_block(void)
+{
+    current_bb->is_terminated = true;
+    current_bb = NULL;
+}
+
 static struct insn* new_insn(int opcode)
 {
     struct insn* insn = calloc(sizeof(struct insn), 1);
@@ -72,19 +80,38 @@ static void queue_insn_simple(int opcode)
 
     switch (opcode)
     {
-        case op_ret:
-            current_bb->is_terminated = true;
-            current_bb = NULL;
+        case op_bra:
+            terminate_block();
             break;
     }
 }
 
 static void queue_insn_value(int opcode, arith value)
 {
-    struct insn* insn = new_insn(opcode);
-    insn->paramtype = PARAM_IVALUE;
-    insn->u.ivalue = value;
-    APPEND(current_bb->insns, insn);
+    switch (opcode)
+    {
+        case op_csa:
+        case op_csb:
+        {
+            const char* helper = aprintf(".%s%d",
+                (opcode == op_csa) ? "csa" : "csb",
+                value);
+
+            queue_insn_label(op_cal, helper, 0);
+            queue_insn_value(op_asp, value + EM_pointersize);
+            queue_insn_value(op_lfr, value);
+            queue_insn_simple(op_bra);
+            break;
+        }
+
+        default:
+        {
+            struct insn* insn = new_insn(opcode);
+            insn->paramtype = PARAM_IVALUE;
+            insn->u.ivalue = value;
+            APPEND(current_bb->insns, insn);
+        }
+    }
 }
 
 static void queue_insn_label(int opcode, const char* label, arith offset)
@@ -109,8 +136,7 @@ static void queue_insn_block(int opcode, struct basicblock* left, struct basicbl
         APPENDU(current_bb->outblocks, right);
     APPENDU(current_bb->inblocks, current_bb);
 
-    current_bb->is_terminated = true;
-    current_bb = NULL;
+    terminate_block();
 }
 
 static void queue_insn_ilabel(int opcode, int label)
index acd8f30..bf57026 100644 (file)
@@ -23,7 +23,7 @@ static void push(struct ir* ir)
      * first. */
 
     if (ir->size < EM_wordsize)
-        ir = convert(ir, EM_wordsize, IR_FROMU1);
+        ir = convert(ir, EM_wordsize, IR_CIU1);
 
     stack[stackptr++] = ir;
 }
@@ -48,7 +48,7 @@ static struct ir* pop(int size)
         /* If we try to pop something which is smaller than a word, convert it first. */
         
         if (size < EM_wordsize)
-            ir = convert(ir, size, IR_FROMU1);
+            ir = convert(ir, size, IR_CIU1);
 
         if (ir->size != size)
             fatal("expected an item on stack of size %d, but got %d\n", size, ir->size);
@@ -153,25 +153,41 @@ static struct ir* tristate_compare(int size, int opcode)
         );
 }
 
+static void simple_convert(opcode)
+{
+    struct ir* destsize = pop(EM_wordsize);
+    struct ir* srcsize = pop(EM_wordsize);
+    struct ir* value;
+
+    assert(srcsize->opcode == IR_ICONST);
+    assert(destsize->opcode == IR_ICONST);
+
+    value = pop(srcsize->u.ivalue);
+    push(
+        convert(value, destsize->u.ivalue, opcode)
+    );
+}
+
 static void insn_simple(int opcode)
 {
     switch (opcode)
     {
-        case op_cii:
+        case op_bra:
         {
-            struct ir* destsize = pop(EM_wordsize);
-            struct ir* srcsize = pop(EM_wordsize);
-            struct ir* value;
-
-            assert(srcsize->opcode == IR_ICONST);
-            assert(destsize->opcode == IR_ICONST);
+            struct ir* dest = pop(EM_pointersize);
 
-            value = pop(srcsize->u.ivalue);
-            push(
-                convert(value, destsize->u.ivalue, IR_FROMI1)
+            materialise_stack();
+            appendir(
+                new_ir1(
+                    IR_JUMP, 0,
+                    dest
+                )
             );
             break;
         }
+            
+        case op_cii: simple_convert(IR_CII1); break;
+        case op_ciu: simple_convert(IR_CIU1); break;
 
         case op_cmp:
             push(
@@ -179,6 +195,20 @@ static void insn_simple(int opcode)
             );
             break;
 
+        case op_cai:
+        {
+            struct ir* dest = pop(EM_pointersize);
+
+            materialise_stack();
+            appendir(
+                new_ir1(
+                    IR_CALL, 0,
+                    dest
+                )
+            );
+            break;
+        }
+
         default:
             fatal("treebuilder: unknown simple instruction '%s'",
                 em_mnem[opcode - sp_fmnem]);
@@ -287,6 +317,11 @@ static void insn_ivalue(int opcode, arith value)
         case op_rmi: simple_alu2(opcode, value, IR_MOD); break;
         case op_ngi: simple_alu1(opcode, value, IR_NEG); break;
 
+        case op_and: simple_alu2(opcode, value, IR_AND); break;
+        case op_ior: simple_alu2(opcode, value, IR_OR); break;
+        case op_xor: simple_alu2(opcode, value, IR_EOR); break;
+        case op_com: simple_alu1(opcode, value, IR_NOT); break;
+
         case op_lol:
             push(
                 new_ir1(
@@ -359,7 +394,7 @@ static void insn_ivalue(int opcode, arith value)
             struct ir* ptr = pop(EM_pointersize);
 
             if (value != EM_pointersize)
-                off = convert(off, EM_pointersize, IR_FROMI1);
+                off = convert(off, EM_pointersize, IR_CII1);
 
             push(
                 new_ir2(
@@ -396,7 +431,7 @@ static void insn_ivalue(int opcode, arith value)
                 );
 
             if (value != EM_pointersize)
-                delta = convert(delta, value, IR_FROMI1);
+                delta = convert(delta, value, IR_CII1);
 
             push(delta);
             break;