From dcba03646b0bc956743650060f1113e19aab582c Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 19 Sep 2016 23:30:41 +0200 Subject: [PATCH] Treebuilder now gets to the bottom of my test file, merrily generating (probably horribly broken) IR. --- mach/proto/mcg/ir.dat | 22 +++++++------ mach/proto/mcg/parse_em.c | 44 +++++++++++++++++++------ mach/proto/mcg/treebuilder.c | 63 ++++++++++++++++++++++++++++-------- 3 files changed, 97 insertions(+), 32 deletions(-) diff --git a/mach/proto/mcg/ir.dat b/mach/proto/mcg/ir.dat index ea47cb0a0..4de21c007 100644 --- a/mach/proto/mcg/ir.dat +++ b/mach/proto/mcg/ir.dat @@ -24,16 +24,20 @@ MOD NEG NOT -# Conversions -FROMI1 -FROMI2 -FROMI4 -FROMI8 +AND +OR +EOR -FROMU1 -FROMU2 -FROMU4 -FROMU8 +# Conversions +CII1 +CII2 +CII4 +CII8 + +CIU1 +CIU2 +CIU4 +CIU8 # Tristate comparisons COMPARES diff --git a/mach/proto/mcg/parse_em.c b/mach/proto/mcg/parse_em.c index 9310dda40..13320fe32 100644 --- a/mach/proto/mcg/parse_em.c +++ b/mach/proto/mcg/parse_em.c @@ -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) diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index acd8f30cd..bf57026a0 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -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; + struct ir* dest = pop(EM_pointersize); - assert(srcsize->opcode == IR_ICONST); - assert(destsize->opcode == IR_ICONST); - - 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;