diff --git a/mach/proto/mcg/basicblock.c b/mach/proto/mcg/basicblock.c index 0ac2a5567..e44f553ee 100644 --- a/mach/proto/mcg/basicblock.c +++ b/mach/proto/mcg/basicblock.c @@ -39,4 +39,8 @@ void bb_alias(struct basicblock* block, const char* name) p->block = block; } +void bb_print(char k, struct basicblock* block) +{ +} + /* vim: set sw=4 ts=4 expandtab : */ diff --git a/mach/proto/mcg/build.lua b/mach/proto/mcg/build.lua index 46394d510..d1b2a3f49 100644 --- a/mach/proto/mcg/build.lua +++ b/mach/proto/mcg/build.lua @@ -24,7 +24,8 @@ cprogram { "modules/src/em_code+lib_k", "modules/src/em_data+lib", "modules/src/idf+lib", - "modules/src/read_em+lib_kv", + "modules/src/read_em+lib_ev", + "modules/src/string+lib", "modules/src/system+lib", "./*.h", "util/mcgg+mcgg", diff --git a/mach/proto/mcg/compile.c b/mach/proto/mcg/compile.c new file mode 100644 index 000000000..d8ae7e3ea --- /dev/null +++ b/mach/proto/mcg/compile.c @@ -0,0 +1,41 @@ +#include "mcg.h" + +static void print_blocks(char k, struct procedure* proc) +{ + int i; + + tracef(k, "%c: procedure %s\n", k, proc->name); + for (int i=0; iblocks_count; i++) + { + struct basicblock* bb = proc->blocks[i]; + int j; + + tracef(k, "%c: block %s\n", k, bb->name); + + for (int j=0; jinblocks_count; j++) + { + struct basicblock* obb = bb->inblocks[j]; + tracef(k, "%c: %s ->\n", k, obb->name); + } + + for (int j=0; jirs_count; j++) + ir_print(k, bb->irs[j]); + + for (int j=0; joutblocks_count; j++) + { + struct basicblock* obb = bb->outblocks[j]; + tracef(k, "%c: -> %s\n", k, obb->name); + } + + } +} + +void compile(struct procedure* proc) +{ + int i; + + print_blocks('1', proc); +} + +/* vim: set sw=4 ts=4 expandtab : */ + diff --git a/mach/proto/mcg/ir.c b/mach/proto/mcg/ir.c index 814171586..34fed739a 100644 --- a/mach/proto/mcg/ir.c +++ b/mach/proto/mcg/ir.c @@ -35,18 +35,16 @@ struct ir* new_labelir(const char* label) return ir; } -struct ir* new_wordir(arith value) +struct ir* new_constir(int size, arith value) { - struct ir* ir = new_ir0(IR_ICONST, EM_wordsize); + struct ir* ir = new_ir0(IR_CONST, size); ir->u.ivalue = value; return ir; } -struct ir* new_regir(int reg) +struct ir* new_wordir(arith value) { - struct ir* ir = new_ir0(IR_REG, EM_pointersize); - ir->u.rvalue = reg; - return ir; + return new_constir(EM_wordsize, value); } struct ir* new_bbir(struct basicblock* bb) @@ -61,51 +59,50 @@ struct ir* new_anyir(int size) return new_ir0(IR_ANY, size); } -struct ir* new_phiir(int size) +struct ir* new_localir(int offset) { - return new_ir0(IR_PHI, size); + struct ir* ir = new_ir0(IR_LOCAL, EM_pointersize); + ir->u.ivalue = offset; + return ir; } -void ir_print(const struct ir* ir) +void ir_print(char k, const struct ir* ir) { - if (ir->left) - ir_print(ir->left); - if (ir->right) - ir_print(ir->right); + if (ir->left && !ir->left->is_sequence) + ir_print(k, ir->left); + if (ir->right && !ir->right->is_sequence) + ir_print(k, ir->right); - printf("\t; %c ", - ir->is_sequence ? 'S' : ' '); - printf("$%d = ", ir->id); - printf("%s%d(", - ir_names[ir->opcode], - ir->size); + tracef(k, "%c: %c ", k, ir->is_sequence ? 'S' : ' '); + tracef(k, "$%d = ", ir->id); + tracef(k, "%s", ir_names[ir->opcode]); + if (ir->size) + tracef(k, "%d", ir->size); + tracef(k, "("); switch (ir->opcode) { - case IR_ICONST: - printf("%d", ir->u.ivalue); + case IR_CONST: + case IR_LOCAL: + tracef(k, "%d", ir->u.ivalue); break; case IR_LABEL: - printf("%s", ir->u.lvalue); - break; - - case IR_REG: - printf("%d", ir->u.rvalue); + tracef(k, "%s", ir->u.lvalue); break; case IR_BLOCK: - printf("%s", ir->u.bvalue->name); + tracef(k, "%s", ir->u.bvalue->name); break; default: if (ir->left) - printf("$%d", ir->left->id); + tracef(k, "$%d", ir->left->id); if (ir->right) - printf(", $%d", ir->right->id); + tracef(k, ", $%d", ir->right->id); } - printf(")\n"); + tracef(k, ")\n"); } /* vim: set sw=4 ts=4 expandtab : */ diff --git a/mach/proto/mcg/ir.dat b/mach/proto/mcg/ir.dat index 4de21c007..033897384 100644 --- a/mach/proto/mcg/ir.dat +++ b/mach/proto/mcg/ir.dat @@ -1,11 +1,11 @@ # Simple terminals -ICONST +CONST REG LABEL BLOCK PAIR ANY -PHI +LOCAL # Magic stack operations PUSH @@ -22,11 +22,17 @@ MUL DIV MOD NEG -NOT + +ADDF +SUBF +MULF +DIVF +NEGF AND OR EOR +NOT # Conversions CII1 @@ -55,6 +61,7 @@ CJUMP RET # Special -SETREG -GETREG +STACKADJUST +GETRET +SETRET diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index 6574ecb80..10e171bb2 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -1,8 +1,6 @@ #ifndef IR_H #define IR_H -#include "ircodes.h" - enum { IRR_LB = -1, @@ -11,6 +9,14 @@ enum IRR_RR = -4, }; +enum +{ + IRS_1, + IRS_2, + IRS_4, + IRS_8 +}; + struct ir { int id; @@ -23,9 +29,6 @@ struct ir int rvalue; const char* lvalue; struct basicblock* bvalue; - struct { - ARRAY(struct ir, srcs); - } phivalue; } u; bool is_sequence : 1; }; @@ -39,13 +42,15 @@ extern struct ir* new_ir2(int opcode, int size, struct ir* c1, struct ir* c2); extern struct ir* new_labelir(const char* label); -extern struct ir* new_regir(int reg); extern struct ir* new_wordir(arith value); +extern struct ir* new_constir(int size, arith value); extern struct ir* new_bbir(struct basicblock* bb); extern struct ir* new_anyir(int size); -extern struct ir* new_phiir(int size); +extern struct ir* new_localir(int offset); -extern void ir_print(const struct ir* ir); +extern void ir_print(char k, const struct ir* ir); + +#include "ircodes.h" #endif diff --git a/mach/proto/mcg/ircodes.sh b/mach/proto/mcg/ircodes.sh index 8f88b8bf4..f1219c50e 100755 --- a/mach/proto/mcg/ircodes.sh +++ b/mach/proto/mcg/ircodes.sh @@ -4,11 +4,33 @@ in=$1 header=$2 source=$3 -echo "enum {" > $header -sed -n 's/^[A-Z].*$/IR_&,/p' < $in >> $header -echo "};" >> $header +awk -f - $in >$header << "EOF" + BEGIN { + print "enum {" + } -echo "const char* ir_names[] = {" > $source -sed -n 's/^[A-Z].*$/"&",/p' < $in >> $source -echo "};" >> $source + /^[^#]+/ { + print "\tIR_" $1 "," + } + + END { + print "};" + } +EOF + +awk -f - $in >$source << "EOF" + BEGIN { + print "#include \"mcg.h\"" + print "#include \"ir.h\"" + print "const char* ir_names[] = {" + } + + /^[^#]+/ { + printf("\t\"%s\",\n", $1) + } + + END { + print "};" + } +EOF diff --git a/mach/proto/mcg/main.c b/mach/proto/mcg/main.c index a89b5a7d9..61f0bd52e 100644 --- a/mach/proto/mcg/main.c +++ b/mach/proto/mcg/main.c @@ -33,6 +33,30 @@ const char* aprintf(const char* fmt, ...) return p; } +bool tracing(char k) +{ + switch (k) + { + case 'E': return true; + case '0': return true; + case '1': return true; + case '2': return true; + default: return true; + } +} + +void tracef(char k, const char* fmt, ...) +{ + va_list ap; + + if (tracing(k)) + { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } +} + int main(int argc, char* argv[]) { symbol_init(); diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 997ae5340..5de8be0c2 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -77,17 +77,18 @@ struct basicblock { const char* name; ARRAY(struct insn, insns); + ARRAY(struct ir, allirs); ARRAY(struct ir, irs); ARRAY(struct basicblock, inblocks); ARRAY(struct basicblock, outblocks); - ARRAY(struct ir, outs); - ARRAY(struct ir, ins); bool is_root : 1; bool is_terminated : 1; }; extern void fatal(const char* s, ...); extern const char* aprintf(const char* fmt, ...); +extern void tracef(char k, const char* fmt, ...); +extern bool tracing(char k); extern void parse_em(void); @@ -105,12 +106,15 @@ 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_print(char k, struct basicblock* block); extern void tb_filestart(void); extern void tb_fileend(void); extern void tb_procedure(struct procedure* proc); extern void tb_regvar(arith offset, int size, int type, int priority); +extern void compile(struct procedure* proc); + #endif /* vim: set sw=4 ts=4 expandtab : */ diff --git a/mach/proto/mcg/parse_em.c b/mach/proto/mcg/parse_em.c index a1c9889f7..e6d39f9f5 100644 --- a/mach/proto/mcg/parse_em.c +++ b/mach/proto/mcg/parse_em.c @@ -289,6 +289,7 @@ static void parse_pseu(void) case ps_end: /* procedure end */ tb_procedure(current_proc); + compile(current_proc); current_proc = NULL; code_bb = NULL; diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 5b014ec5e..82d7b14ec 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -6,7 +6,7 @@ static struct basicblock* current_bb; static int stackptr; static struct ir* stack[64]; -static struct ir* convert(struct ir* src, int destsize, int opcode); +static struct ir* convert(struct ir* src, int destsize, int opcodebase); static struct ir* appendir(struct ir* ir); static void reset_stack(void) @@ -37,8 +37,10 @@ static struct ir* pop(int size) if (size < EM_wordsize) size = EM_wordsize; return - new_ir0( - IR_POP, size + appendir( + new_ir0( + IR_POP, size + ) ); } else @@ -60,13 +62,25 @@ static void print_stack(void) { int i; - printf("\t; stack:"); + tracef('E', "E: stack:"); for (i=0; iid, ir->size); + tracef('E', " $%d.%d", ir->id, ir->size); } - printf(" (top)\n"); + tracef('E', " (top)\n"); +} + +static void appendallirs(struct ir* ir) +{ + if (CONTAINS(current_bb->allirs, ir)) + fatal("ir reachable from more than one place"); + + APPEND(current_bb->allirs, ir); + if (ir->left && !ir->left->is_sequence) + appendallirs(ir->left); + if (ir->right && !ir->right->is_sequence) + appendallirs(ir->right); } static struct ir* appendir(struct ir* ir) @@ -76,8 +90,9 @@ static struct ir* appendir(struct ir* ir) assert(current_bb != NULL); ir->is_sequence = true; APPEND(current_bb->irs, ir); + appendallirs(ir); - ir_print(ir); + ir_print('0', ir); return ir; } @@ -112,16 +127,6 @@ void tb_regvar(arith offset, int size, int type, int priority) /* ignored */ } -static struct ir* address_of_local(int index) -{ - return - new_ir2( - IR_ADD, EM_pointersize, - new_regir((index < 0) ? IRR_LB : IRR_AB), - new_wordir(index) - ); -} - static struct ir* address_of_external(const char* label, arith offset) { if (offset != 0) @@ -162,7 +167,7 @@ static struct ir* tristate_compare(int size, int opcode) return new_ir2( - opcode, size, + opcode, EM_wordsize, left, right ); } @@ -173,8 +178,8 @@ static void simple_convert(int opcode) struct ir* srcsize = pop(EM_wordsize); struct ir* value; - assert(srcsize->opcode == IR_ICONST); - assert(destsize->opcode == IR_ICONST); + assert(srcsize->opcode == IR_CONST); + assert(destsize->opcode == IR_CONST); value = pop(srcsize->u.ivalue); push( @@ -241,7 +246,7 @@ static void simple_branch2(int opcode, int size, new_ir2( IR_CJUMP, 0, new_ir2( - irop, size, + irop, size, left, right ), new_ir2( @@ -336,11 +341,17 @@ static void insn_ivalue(int opcode, arith value) case op_xor: simple_alu2(opcode, value, IR_EOR); break; case op_com: simple_alu1(opcode, value, IR_NOT); break; + case op_adf: simple_alu2(opcode, value, IR_ADDF); break; + case op_sbf: simple_alu2(opcode, value, IR_SUBF); break; + case op_mlf: simple_alu2(opcode, value, IR_MULF); break; + case op_dvf: simple_alu2(opcode, value, IR_DIVF); break; + case op_ngf: simple_alu1(opcode, value, IR_NEGF); break; + case op_lol: push( new_ir1( IR_LOAD, EM_wordsize, - address_of_local(value) + new_localir(value) ) ); break; @@ -349,7 +360,7 @@ static void insn_ivalue(int opcode, arith value) appendir( new_ir2( IR_STORE, EM_wordsize, - address_of_local(value), + new_localir(value), pop(EM_wordsize) ) ); @@ -357,7 +368,7 @@ static void insn_ivalue(int opcode, arith value) case op_lal: push( - address_of_local(value) + new_localir(value) ); break; @@ -476,17 +487,21 @@ static void insn_ivalue(int opcode, arith value) break; default: - appendir( - new_ir2( - IR_SETREG, EM_pointersize, - new_regir(IRR_SP), - new_ir2( - IR_ADD, EM_pointersize, - new_regir(IRR_SP), + while ((value > 0) && (stackptr > 0)) + { + struct ir* ir = pop(stack[stackptr-1]->size); + value -= ir->size; + } + + if (value != 0) + { + appendir( + new_ir1( + IR_STACKADJUST, EM_pointersize, new_wordir(value) ) - ) - ); + ); + } break; } break; @@ -497,10 +512,10 @@ static void insn_ivalue(int opcode, arith value) if (value > 0) { struct ir* retval = pop(value); + materialise_stack(); appendir( - new_ir2( - IR_SETREG, value, - new_regir(IRR_RR), + new_ir1( + IR_SETRET, value, retval ) ); @@ -518,9 +533,8 @@ static void insn_ivalue(int opcode, arith value) { push( appendir( - new_ir1( - IR_GETREG, value, - new_regir(IRR_RR) + new_ir0( + IR_GETRET, value ) ) ); @@ -630,13 +644,7 @@ 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); - } + tracef('0', "0: block %s\n", bb->name); current_bb = bb; reset_stack(); @@ -644,30 +652,30 @@ static void generate_tree(struct basicblock* bb) for (i=0; iinsns_count; i++) { struct insn* insn = bb->insns[i]; - printf("\t; EM: %s ", em_mnem[insn->opcode - sp_fmnem]); + tracef('E', "E: read %s ", em_mnem[insn->opcode - sp_fmnem]); switch (insn->paramtype) { case PARAM_NONE: - printf("\n"); + tracef('E', "\n"); insn_simple(insn->opcode); break; case PARAM_IVALUE: - printf("value=%d\n", insn->u.ivalue); + tracef('E', "value=%d\n", insn->u.ivalue); insn_ivalue(insn->opcode, insn->u.ivalue); break; case PARAM_LVALUE: - printf("label=%s offset=%d\n", + tracef('E', "label=%s offset=%d\n", insn->u.lvalue.label, insn->u.lvalue.offset); insn_lvalue(insn->opcode, insn->u.lvalue.label, insn->u.lvalue.offset); break; case PARAM_BVALUE: - printf("true=%s", insn->u.bvalue.left->name); + tracef('E', "true=%s", insn->u.bvalue.left->name); if (insn->u.bvalue.right) - printf(" false=%s", insn->u.bvalue.right->name); - printf("\n"); + tracef('E', " false=%s", insn->u.bvalue.right->name); + tracef('E', "\n"); insn_bvalue(insn->opcode, insn->u.bvalue.left, insn->u.bvalue.right); break; @@ -675,18 +683,11 @@ static void generate_tree(struct basicblock* bb) assert(0); } - print_stack(); + if (tracing('E')) + print_stack(); } 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)