From: David Given Date: Mon, 19 Sep 2016 22:19:39 +0000 (+0200) Subject: Create hacky fake basic blocks for data fragments, used to track which X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=36d7d1ee4ed47f37a0feb4a6867df5809d1fff0b;p=ack.git Create hacky fake basic blocks for data fragments, used to track which instruction labels descriptor blocks refer to; this allows csa and csb to know where they're going. --- diff --git a/mach/proto/mcg/basicblock.c b/mach/proto/mcg/basicblock.c index 74d5e8add..0ac2a5567 100644 --- a/mach/proto/mcg/basicblock.c +++ b/mach/proto/mcg/basicblock.c @@ -39,32 +39,4 @@ void bb_alias(struct basicblock* block, const char* name) p->block = block; } -void bb_wire_outs_to_ins(struct basicblock* inblock, struct basicblock* outblock) -{ - int i; - - if (!outblock->is_wired) - { - for (i=0; iouts_count; i++) - { - struct ir* value = inblock->outs[i]; - APPEND(outblock->ins, - new_phiir(value->size) - ); - } - outblock->is_wired = true; - } - - assert(inblock->outs_count == outblock->ins_count); - for (i=0; iouts_count; i++) - { - struct ir* srcvalue = inblock->outs[i]; - struct ir* destvalue = outblock->ins[i]; - assert(srcvalue->size == destvalue->size); - assert(destvalue->opcode == IR_PHI); - - APPENDU(destvalue->u.phivalue.srcs, srcvalue); - } -} - /* vim: set sw=4 ts=4 expandtab : */ diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index ce332fff9..997ae5340 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -82,7 +82,7 @@ struct basicblock ARRAY(struct basicblock, outblocks); ARRAY(struct ir, outs); ARRAY(struct ir, ins); - bool is_wired : 1; + bool is_root : 1; bool is_terminated : 1; }; @@ -105,7 +105,6 @@ extern void data_bss(arith size, int init); extern void bb_init(void); extern struct basicblock* bb_get(const char* name); extern void bb_alias(struct basicblock* block, const char* name); -extern void bb_wire_outs_to_ins(struct basicblock* outblock, struct basicblock* inblock); extern void tb_filestart(void); extern void tb_fileend(void); diff --git a/mach/proto/mcg/parse_em.c b/mach/proto/mcg/parse_em.c index 13320fe32..a1c9889f7 100644 --- a/mach/proto/mcg/parse_em.c +++ b/mach/proto/mcg/parse_em.c @@ -2,7 +2,8 @@ static struct e_instr insn; static struct procedure* current_proc; -static struct basicblock* current_bb; +static struct basicblock* code_bb; +static struct basicblock* data_bb; static void queue_insn_label(int opcode, const char* label, arith offset); @@ -61,8 +62,8 @@ static const char* dlabel_to_str(label l) static void terminate_block(void) { - current_bb->is_terminated = true; - current_bb = NULL; + code_bb->is_terminated = true; + code_bb = NULL; } static struct insn* new_insn(int opcode) @@ -76,7 +77,7 @@ static void queue_insn_simple(int opcode) { struct insn* insn = new_insn(opcode); insn->paramtype = PARAM_NONE; - APPEND(current_bb->insns, insn); + APPEND(code_bb->insns, insn); switch (opcode) { @@ -88,29 +89,17 @@ static void queue_insn_simple(int opcode) static void queue_insn_value(int opcode, arith value) { + struct insn* insn = new_insn(opcode); + insn->paramtype = PARAM_IVALUE; + insn->u.ivalue = value; + APPEND(code_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); + terminate_block(); break; - } - - default: - { - struct insn* insn = new_insn(opcode); - insn->paramtype = PARAM_IVALUE; - insn->u.ivalue = value; - APPEND(current_bb->insns, insn); - } } } @@ -120,7 +109,14 @@ static void queue_insn_label(int opcode, const char* label, arith offset) insn->paramtype = PARAM_LVALUE; insn->u.lvalue.label = label; insn->u.lvalue.offset = offset; - APPEND(current_bb->insns, insn); + APPEND(code_bb->insns, insn); + + switch (opcode) + { + case op_bra: + terminate_block(); + break; + } } static void queue_insn_block(int opcode, struct basicblock* left, struct basicblock* right) @@ -129,12 +125,15 @@ static void queue_insn_block(int opcode, struct basicblock* left, struct basicbl insn->paramtype = PARAM_BVALUE; insn->u.bvalue.left = left; insn->u.bvalue.right = right; - APPEND(current_bb->insns, insn); + APPEND(code_bb->insns, insn); - APPENDU(current_bb->outblocks, left); + APPENDU(code_bb->outblocks, left); + APPENDU(left->inblocks, code_bb); if (right) - APPENDU(current_bb->outblocks, right); - APPENDU(current_bb->inblocks, current_bb); + { + APPENDU(code_bb->outblocks, right); + APPENDU(right->inblocks, code_bb); + } terminate_block(); } @@ -169,10 +168,10 @@ static void change_basicblock(struct basicblock* newbb) { APPENDU(current_proc->blocks, newbb); - if (current_bb && !current_bb->is_terminated) + if (code_bb && !code_bb->is_terminated) queue_insn_block(op_bra, newbb, NULL); - current_bb = newbb; + code_bb = newbb; } static void queue_ilabel(arith label) @@ -242,8 +241,21 @@ static void parse_pseu(void) break; case ilb_ptyp: - data_offset(ilabel_to_str(insn.em_ilb), 0, ro); + { + const char* label = ilabel_to_str(insn.em_ilb); + + /* This is really hacky; to handle basic block flow + * descriptor blocks, we need to track which bbs a descriptor + * can exit to. So we create fake bb objects for each + * block, purely to track this. + */ + + if (data_bb) + APPENDU(data_bb->outblocks, bb_get(label)); + + data_offset(label, 0, ro); break; + } default: unknown_type("con, rom"); @@ -270,15 +282,16 @@ static void parse_pseu(void) current_proc->name = strdup(insn.em_pnam); current_proc->root_bb = bb_get(current_proc->name); current_proc->nlocals = insn.em_nlocals; - current_bb = current_proc->root_bb; - APPEND(current_proc->blocks, current_bb); + code_bb = current_proc->root_bb; + code_bb->is_root = true; + APPEND(current_proc->blocks, code_bb); break; case ps_end: /* procedure end */ tb_procedure(current_proc); current_proc = NULL; - current_bb = NULL; + code_bb = NULL; break; default: @@ -338,8 +351,12 @@ void parse_em(void) break; case EM_DEFDLB: - data_label(dlabel_to_str(insn.em_dlb)); + { + const char* label = dlabel_to_str(insn.em_dlb); + data_label(label); + data_bb = bb_get(label); break; + } case EM_DEFDNAM: data_label(strdup(insn.em_dnam)); @@ -350,7 +367,7 @@ void parse_em(void) break; case EM_MNEM: - if (current_bb) + if (code_bb) { int flags = em_flag[insn.em_opcode - sp_fmnem]; diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index bf57026a0..5b014ec5e 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -85,7 +85,7 @@ static void materialise_stack(void) { int i; - for (i=stackptr-1; i>=0; i--) + for (i=0; isize) @@ -153,7 +167,7 @@ static struct ir* tristate_compare(int size, int opcode) ); } -static void simple_convert(opcode) +static void simple_convert(int opcode) { struct ir* destsize = pop(EM_wordsize); struct ir* srcsize = pop(EM_wordsize); @@ -513,6 +527,42 @@ static void insn_ivalue(int opcode, arith value) break; } + case op_csa: + case op_csb: + { + struct basicblock* data_bb; + int i; + const char* helper = aprintf(".%s%d", + (opcode == op_csa) ? "csa" : "csb", + value); + struct ir* descriptor = pop(EM_pointersize); + + if (descriptor->opcode != IR_LABEL) + fatal("csa/csb are only supported if they refer " + "directly to a descriptor block"); + + /* Splice the outgoing bbs in the data block into our own. */ + + data_bb = bb_get(descriptor->u.lvalue); + for (i=0; ioutblocks_count; i++) + { + struct basicblock* bb = data_bb->outblocks[i]; + printf("\t; may jump to %s\n", bb->name); + APPENDU(current_bb->outblocks, bb); + APPENDU(bb->inblocks, current_bb); + } + + push(descriptor); + materialise_stack(); + appendir( + new_ir1( + IR_JUMP, 0, + new_labelir(helper) + ) + ); + break; + } + default: fatal("treebuilder: unknown ivalue instruction '%s'", em_mnem[opcode - sp_fmnem]); @@ -525,11 +575,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) { case op_lae: push( - new_ir2( - IR_ADD, EM_pointersize, - new_labelir(label), - new_wordir(offset) - ) + address_of_external(label, offset) ); break; @@ -537,11 +583,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) push( new_ir1( IR_LOAD, EM_wordsize, - new_ir2( - IR_ADD, EM_pointersize, - new_labelir(label), - new_wordir(offset) - ) + address_of_external(label, offset) ) ); break; @@ -550,11 +592,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) appendir( new_ir2( IR_STORE, EM_wordsize, - new_ir2( - IR_ADD, EM_pointersize, - new_labelir(label), - new_wordir(offset) - ), + address_of_external(label, offset), pop(EM_wordsize) ) ); @@ -570,6 +608,17 @@ static void insn_lvalue(int opcode, const char* label, arith offset) ) ); break; + + case op_bra: + assert(offset == 0); + materialise_stack(); + appendir( + new_ir1( + IR_JUMP, 0, + new_labelir(label) + ) + ); + break; default: fatal("treebuilder: unknown lvalue instruction '%s'", @@ -582,6 +631,13 @@ static void generate_tree(struct basicblock* bb) int i; printf("; BLOCK %s\n", bb->name); + if (bb->inblocks_count > 0) + { + printf("; Entered from:\n"); + for (i=0; iinblocks_count; i++) + printf("; %s\n", bb->inblocks[i]->name); + } + current_bb = bb; reset_stack(); @@ -623,6 +679,14 @@ static void generate_tree(struct basicblock* bb) } assert(stackptr == 0); + + if (bb->outblocks_count > 0) + { + printf("; Exiting to:\n"); + for (i=0; ioutblocks_count; i++) + printf("; %s\n", bb->outblocks[i]->name); + } + printf("\n"); } void tb_procedure(struct procedure* current_proc)