From bb9aa030a56ed69db30ed29bc08f09d8fc255482 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 24 Sep 2016 01:04:00 +0200 Subject: [PATCH] Procedure compilation now happens after the entire EM file has been read in (so that we can look inside data blocks which might be defined in the future... sigh, csa and csb). csa and csb no longer generate invalid IR. --- mach/proto/mcg/main.c | 18 +++++++++- mach/proto/mcg/mcg.h | 6 +++- mach/proto/mcg/parse_em.c | 30 +++++++++++----- mach/proto/mcg/pass_eliminatetrivialblocks.c | 3 +- mach/proto/mcg/{compile.c => procedure.c} | 6 ++-- mach/proto/mcg/symbol.c | 22 ++++++++++++ mach/proto/mcg/treebuilder.c | 38 ++++++++++++++++---- 7 files changed, 103 insertions(+), 20 deletions(-) rename mach/proto/mcg/{compile.c => procedure.c} (79%) 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 : */ -- 2.34.1