diff --git a/mach/proto/mcg/main.c b/mach/proto/mcg/main.c index 6c9a28006..5be59e639 100644 --- a/mach/proto/mcg/main.c +++ b/mach/proto/mcg/main.c @@ -39,7 +39,7 @@ bool tracing(char k) { case 'E': return false; case '0': return false; - case '1': return false; + case '1': return true; case '2': return true; default: return true; } @@ -57,6 +57,13 @@ void tracef(char k, const char* fmt, ...) } } +static bool find_procedures_cb(struct symbol* symbol, void* user) +{ + if (symbol->proc) + procedure_compile(symbol->proc); + return false; +} + int main(int argc, char* argv[]) { symbol_init(); @@ -64,8 +71,17 @@ int main(int argc, char* argv[]) if (!EM_open(argv[1])) fatal("Couldn't open input file: %s", EM_error); + /* Reads in the EM, outputs the data sections, parses any code and + * generates IR trees. */ + parse_em(); + /* For every procedure, go ahead and do the compilation proper. We do this + * now so that we know that all the data has been read correctly and our + * symbol table is complete (we may need to refer to it). */ + + symbol_walk(find_procedures_cb, NULL); + EM_close(); return 0; } diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index a7b8d6835..4fa1b1177 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -36,6 +36,7 @@ struct symbol { const char* name; int section; + struct procedure* proc; bool is_defined : 1; bool is_exported : 1; bool is_proc : 1; @@ -96,6 +97,9 @@ extern bool symbol_exists(const char* name); extern struct symbol* symbol_get(const char* name); extern void symbol_declare(const char* name, bool is_exported, bool is_proc); +typedef bool symbol_walker_t(struct symbol* symbol, void* user); +extern struct symbol* symbol_walk(symbol_walker_t* walker, void* user); + extern void data_label(const char* name); extern void data_int(arith data, size_t size, bool is_ro); extern void data_block(const uint8_t* data, size_t size, bool is_ro); @@ -116,7 +120,7 @@ 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 compile(struct procedure* proc); +extern void procedure_compile(struct procedure* proc); #endif diff --git a/mach/proto/mcg/parse_em.c b/mach/proto/mcg/parse_em.c index 7daecfecd..699e6b4f4 100644 --- a/mach/proto/mcg/parse_em.c +++ b/mach/proto/mcg/parse_em.c @@ -280,6 +280,9 @@ static void parse_pseu(void) } case ps_pro: /* procedure start */ + { + struct symbol* symbol; + current_proc = calloc(sizeof(struct procedure), 1); current_proc->name = strdup(insn.em_pnam); current_proc->root_bb = bb_get(current_proc->name); @@ -287,11 +290,16 @@ static void parse_pseu(void) code_bb = current_proc->root_bb; code_bb->is_root = true; APPEND(current_proc->blocks, code_bb); + + symbol = symbol_get(current_proc->name); + symbol->section = SECTION_TEXT; + symbol->proc = current_proc; + symbol->is_proc = true; break; + } case ps_end: /* procedure end */ tb_procedure(current_proc); - compile(current_proc); current_proc = NULL; code_bb = NULL; @@ -336,6 +344,17 @@ static void parse_mes(void) fatal("malformed MES"); } +static void create_data_label(const char* label) +{ + data_label(label); + if (current_proc) + { + data_bb = bb_get(label); + data_bb->is_fake = true; + APPEND(current_proc->blocks, data_bb); + } +} + void parse_em(void) { EM_getinstr(&insn); @@ -354,16 +373,11 @@ void parse_em(void) break; case EM_DEFDLB: - { - const char* label = dlabel_to_str(insn.em_dlb); - data_label(label); - data_bb = bb_get(label); - data_bb->is_fake = true; + create_data_label(dlabel_to_str(insn.em_dlb)); break; - } case EM_DEFDNAM: - data_label(strdup(insn.em_dnam)); + create_data_label(strdup(insn.em_dnam)); break; case EM_STARTMES: diff --git a/mach/proto/mcg/pass_eliminatetrivialblocks.c b/mach/proto/mcg/pass_eliminatetrivialblocks.c index 96c8e080d..3b7280466 100644 --- a/mach/proto/mcg/pass_eliminatetrivialblocks.c +++ b/mach/proto/mcg/pass_eliminatetrivialblocks.c @@ -5,7 +5,8 @@ static bool rewrite_jumps_cb(struct ir* ir, void* user) if (ir->opcode == IR_BLOCK) { struct basicblock* bb = ir->u.bvalue; - if ((bb->irs_count > 0) + if (!bb->is_fake + && (bb->irs_count > 0) && (bb->irs[0]->opcode == IR_JUMP) && (bb->irs[0]->left->opcode == IR_BLOCK)) { diff --git a/mach/proto/mcg/compile.c b/mach/proto/mcg/procedure.c similarity index 79% rename from mach/proto/mcg/compile.c rename to mach/proto/mcg/procedure.c index c6fea43d6..8958a8b7e 100644 --- a/mach/proto/mcg/compile.c +++ b/mach/proto/mcg/procedure.c @@ -11,14 +11,16 @@ static void print_blocks(char k, struct procedure* proc) int j; tracef(k, "%c:\n", k); - tracef(k, "%c: BLOCK: %s\n", k, bb->name); + tracef(k, "%c: %sBLOCK: %s\n", k, + bb->is_fake ? "FAKE " : "", + bb->name); for (int j=0; jirs_count; j++) ir_print(k, bb->irs[j]); } } -void compile(struct procedure* proc) +void procedure_compile(struct procedure* proc) { int i; diff --git a/mach/proto/mcg/symbol.c b/mach/proto/mcg/symbol.c index 14ec4a97a..f8c2f52fb 100644 --- a/mach/proto/mcg/symbol.c +++ b/mach/proto/mcg/symbol.c @@ -1,7 +1,10 @@ #include "mcg.h" +typedef int idf_walker_t(struct idf* idf, void* user); + static void init_idf(); static struct idf* str2idf(char* tg, int cp); +static struct idf* walk_idf(idf_walker_t* cb, void* user); #define IDF_TYPE struct symbol #define IDF_NAME symbol @@ -39,3 +42,22 @@ void symbol_declare(const char* name, bool is_exported, bool is_proc) } } +struct symbol* symbol_walk(symbol_walker_t* cb, void* user) +{ + int i; + + for (i=0; isymbol; + if (cb(symbol, user)) + return &symbol; + idf = idf->id_next; + } + } + + return NULL; +} + diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 39d529f3d..ea699d720 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -281,6 +281,12 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock break; } + case op_lae: + push( + new_bbir(leftbb) + ); + break; + default: fatal("treebuilder: unknown bvalue instruction '%s'", em_mnem[opcode - sp_fmnem]); @@ -312,6 +318,27 @@ static void simple_alu2(int opcode, int size, int irop) ); } +static struct ir* extract_block_refs(struct basicblock* bb) +{ + struct ir* outir = NULL; + int i; + + for (i=0; iinsns_count; i++) + { + struct insn* insn = bb->insns[i]; + assert(insn->opcode == op_bra); + assert(insn->paramtype == PARAM_BVALUE); + + outir = new_ir2( + IR_PAIR, 0, + new_bbir(insn->u.bvalue.left), + outir + ); + } + + return outir; +} + static void insn_ivalue(int opcode, arith value) { switch (opcode) @@ -540,17 +567,13 @@ static void insn_ivalue(int opcode, arith value) fatal("csa/csb are only supported if they refer " "directly to a descriptor block"); - /* Turn the label reference into a block. */ - - descriptor->opcode = IR_BLOCK; - descriptor->u.bvalue = bb_get(descriptor->u.lvalue); - push(descriptor); materialise_stack(); appendir( - new_ir1( + new_ir2( IR_JUMP, 0, - new_labelir(helper) + new_labelir(helper), + extract_block_refs(bb_get(descriptor->u.lvalue)) ) ); break; @@ -675,6 +698,7 @@ void tb_procedure(struct procedure* current_proc) for (i=0; iblocks_count; i++) generate_tree(current_proc->blocks[i]); + } /* vim: set sw=4 ts=4 expandtab : */