diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index 795b6dd6d..eaf031475 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -33,7 +33,11 @@ struct ir const char* lvalue; struct basicblock* bvalue; } u; + + void* state_label; /* used by the iburg instruction selector */ + bool is_sequence : 1; + bool is_generated : 1; }; extern const char* ir_names[]; diff --git a/mach/proto/mcg/main.c b/mach/proto/mcg/main.c index 5be59e639..83d510107 100644 --- a/mach/proto/mcg/main.c +++ b/mach/proto/mcg/main.c @@ -37,9 +37,10 @@ bool tracing(char k) { switch (k) { + case 0: return true; case 'E': return false; case '0': return false; - case '1': return true; + case '1': return false; case '2': return true; default: return true; } diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 4fa1b1177..193ed3690 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -119,6 +119,7 @@ extern void tb_regvar(arith offset, int size, int type, int priority); 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 pass_instruction_selector(struct procedure* proc); extern void procedure_compile(struct procedure* proc); diff --git a/mach/proto/mcg/mcgg_generated_footer.h b/mach/proto/mcg/mcgg_generated_footer.h index 56bdc9168..11b40205a 100644 --- a/mach/proto/mcg/mcgg_generated_footer.h +++ b/mach/proto/mcg/mcgg_generated_footer.h @@ -19,6 +19,7 @@ static void dumpCover(NODEPTR_TYPE p, int goalnt, int indent) { #endif } +#if 0 static NODEPTR_TYPE tree(int op, NODEPTR_TYPE l, NODEPTR_TYPE r) { NODEPTR_TYPE p = malloc(sizeof *p); @@ -48,4 +49,5 @@ int main(void) { dumpCover(p, 1, 0); return 0; } +#endif diff --git a/mach/proto/mcg/mcgg_generated_header.h b/mach/proto/mcg/mcgg_generated_header.h index 2545e8af3..36e394b6c 100644 --- a/mach/proto/mcg/mcgg_generated_header.h +++ b/mach/proto/mcg/mcgg_generated_header.h @@ -1,32 +1,20 @@ -#include -#include -#include -#include -#include -#include +#include "mcg.h" +#include "mcgg.h" -#define TRACE -#define STATE_TYPE void* -typedef struct tree { - int op; - struct tree *kids[2]; - STATE_TYPE state_label; -} *NODEPTR_TYPE; -#define OP_LABEL(p) ((p)->op) -#define LEFT_CHILD(p) ((p)->kids[0]) -#define RIGHT_CHILD(p) ((p)->kids[1]) -#define STATE_LABEL(p) ((p)->state_label) #define PANIC printf -static void burm_trace(NODEPTR_TYPE p, int eruleno, int cost, int bestcost) { -#ifdef TRACE - extern const char *burm_string[]; - - fprintf(stderr, "0x%p matched %s with cost %d vs. %d\n", p, - burm_string[eruleno], cost, bestcost); -#endif +static int OP_LABEL(struct ir* ir) +{ + if (ir->is_generated) + return ir_to_esn(IR_REG, ir->size); + return ir_to_esn(ir->opcode, ir->size); } -#define burm_assert(b, s) assert(b && s) +#define LEFT_CHILD(p) ((p)->left) +#define RIGHT_CHILD(p) ((p)->right) + +#define burm_assert(b, s) assert(b) + +extern void burm_panic_cannot_match(struct ir* ir); diff --git a/mach/proto/mcg/pass_instsel.c b/mach/proto/mcg/pass_instsel.c new file mode 100644 index 000000000..8d1fa4718 --- /dev/null +++ b/mach/proto/mcg/pass_instsel.c @@ -0,0 +1,87 @@ +#include "mcg.h" +#include "mcgg.h" + +#if 0 +static void dumpCover(NODEPTR_TYPE p, int goalnt, int indent) { +#ifdef TRACE + int eruleno = burm_rule(STATE_LABEL(p), goalnt); + const short *nts = burm_nts[eruleno]; + NODEPTR_TYPE kids[10]; + int i; + + for (i = 0; i < indent; i++) + fprintf(stderr, " "); + fprintf(stderr, "%s\n", burm_string[eruleno]); + burm_kids(p, eruleno, kids); + for (i = 0; nts[i]; i++) + { + if (kids[i]) + dumpCover(kids[i], nts[i], indent + 1); + else + fprintf(stderr, "failed!\n"); + } +#endif +} +#endif + +void burm_trace(struct ir* p, int ruleno, int cost, int bestcost) { + tracef('I', "I: 0x%p matched %s with cost %d vs. %d\n", p, + burm_string[ruleno], cost, bestcost); +} + +void burm_panic_cannot_match(struct ir* ir) +{ + fprintf(stderr, "could not find any patterns to match:\n"); + ir_print(0, ir); + fprintf(stderr, "aborting!\n"); + exit(1); +} + +static void queue_instructions(struct ir* ir, int goal) +{ + struct ir* children[10]; + int ruleno = burm_rule(ir->state_label, goal); + const short* nts = burm_nts[ruleno]; + int i; + + burm_kids(ir, ruleno, children); + for (i=0; nts[i]; i++) + queue_instructions(children[i], nts[i]); + + printf("selected insn %d: %s\n", ruleno, burm_string[ruleno]); +} + +static void select_instructions(struct basicblock* bb) +{ + int i; + + tracef('I', "I: BLOCK: %s\n", bb->name); + + for (i=0; iirs_count; i++) + { + int insnno; + struct ir* ir = bb->irs[i]; + burm_label(ir); + + insnno = burm_rule(ir->state_label, 1); + if (!insnno) + burm_panic_cannot_match(ir); + + queue_instructions(ir, 1); + } +} + +void pass_instruction_selector(struct procedure* proc) +{ + int i; + + for (i=0; iblocks_count; i++) + { + struct basicblock* bb = proc->blocks[i]; + select_instructions(bb); + } + exit(1); +} + +/* vim: set sw=4 ts=4 expandtab : */ + diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index 8958a8b7e..b0bc1a0e3 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -31,6 +31,8 @@ void procedure_compile(struct procedure* proc) pass_convert_stack_ops(proc); print_blocks('2', proc); + + pass_instruction_selector(proc); } /* vim: set sw=4 ts=4 expandtab : */ diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index daf0fbbad..f9f468f53 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -1,5 +1,33 @@ PATTERNS +/* Special */ + + reg; + + PAIR(BLOCK4, BLOCK4); + + +/* Miscellaneous special things */ + + PUSH4(in:reg) + emit "push %in" + cost 4; + + reg = POP4 + outs out:ANY + emit "pop %out" + cost 4; + + RET + emit "ret" + cost 4; + + SETRET4(in:reg) + emit "mov r0, %in" + cost 4; + +/* Memory operations */ + STORE4(addr:address, value:reg) ins value:GPR emit "str %value, %addr" @@ -7,9 +35,33 @@ PATTERNS reg = LOAD4(addr:address) outs dest:ANY - emit "ld %dest, %addr" + emit "ldr %dest, %addr" cost 4; + reg = LOAD1(addr:address) + outs dest:ANY + emit "ldrb %dest, %addr" + cost 4; + + reg = CIU14(LOAD1(addr:address)) + outs dest:ANY + emit "ldrb %dest, %addr" + cost 4; + + +/* Locals */ + + reg = in:LOCAL4 + outs out:GPR + emit "add %out, fp, #%in.ivalue" + cost 4; + + address = in:LOCAL4 + fragment "[fp, #%in.ivalue]"; + + +/* Memory addressing modes */ + address = ADD4(addr:reg, offset:CONST) ins addr:GPR fragment "[%addr, #%offset.ivalue]"; @@ -18,7 +70,47 @@ PATTERNS ins addr:GPR fragment "[%addr]"; - reg; + +/* Branches */ + + JUMP(addr:BLOCK4) + emit "b %addr.bvalue" + cost 4; + + CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4)) + emit "beq %trueblock.bvalue" + emit "bne %falseblock.bvalue" + cost 8; + + +/* Comparisons */ + + tristate = COMPARES4(val1:reg, val2:aluparam) + outs CC + emit "cmp %val1, %val2" + cost 4; + + reg = tristate + emit "mov %out, #0" + emit "movlt %out, #-1" + emit "movgt %out, #1" + cost 12; + + +/* Conversions */ + + reg = CII14(CIU41(value:reg)) + outs out:GPR + emit "sxtb %out, %value" + cost 4; + + reg = CIU41(in:reg) + outs out:GPR + emit "and %out, %in, #0xff" + cost 4; + + +/* ALU operations */ reg = ADD4(left:reg, right:aluparam) ins left:GPR, right:GPR @@ -33,7 +125,6 @@ PATTERNS cost 4; aluparam = value:CONST4 - when { return false; } fragment "#%value.ivalue"; aluparam = reg; @@ -45,7 +136,12 @@ PATTERNS reg = value:LABEL4 outs out:GPR - emit "adr %out, #value.lvalue" + emit "adr %out, %value.lvalue" + cost 4; + + reg = value:BLOCK4 + outs out:GPR + emit "adr %out, %value.bvalue" cost 4; reg = value:CONST4 diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index ea699d720..1b0d51da5 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -231,9 +231,9 @@ static void simple_branch2(int opcode, int size, materialise_stack(); appendir( new_ir2( - IR_CJUMP, 0, + irop, 0, new_ir2( - irop, size, + IR_COMPARES, size, left, right ), new_ir2( @@ -260,13 +260,13 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock { switch (opcode) { - case op_zeq: compare0_branch2(opcode, leftbb, rightbb, IR_IFEQ); break; - case op_zlt: compare0_branch2(opcode, leftbb, rightbb, IR_IFLT); break; - case op_zle: compare0_branch2(opcode, leftbb, rightbb, IR_IFLE); break; + case op_zeq: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPEQ); break; + case op_zlt: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPLT); break; + case op_zle: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPLE); break; - case op_zne: compare0_branch2(opcode, rightbb, leftbb, IR_IFEQ); break; - case op_zge: compare0_branch2(opcode, rightbb, leftbb, IR_IFLT); break; - case op_zgt: compare0_branch2(opcode, rightbb, leftbb, IR_IFLE); break; + case op_zne: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPEQ); break; + case op_zge: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPLT); break; + case op_zgt: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPLE); break; case op_bra: { diff --git a/util/mcgg/build.lua b/util/mcgg/build.lua index 8afdbc0a9..0485197a9 100644 --- a/util/mcgg/build.lua +++ b/util/mcgg/build.lua @@ -28,7 +28,8 @@ clibrary { matching(filenamesof("+ircodes"), "%.c$") }, hdrs = { - matching(filenamesof("+ircodes"), "%.h$") + matching(filenamesof("+ircodes"), "%.h$"), + "./mcgg.h" } } @@ -40,7 +41,7 @@ cprogram { matching(filenamesof("+yacc"), "%.c$") }, deps = { - "./*.h", + "./iburg.h", "+lib", "+yacc" } diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index e581b7b90..c26cfeef7 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -419,7 +419,7 @@ static void print(char* fmt, ...) void printlineno(void) { - print("#line %d\n", yylineno); + //print("#line %d\n", yylineno); } /* reach - mark all non-terminals in tree t as reachable */ @@ -451,6 +451,9 @@ static void emitcase(Term p, int ntnumber) { Rule r; + if (!p->rules) + return; + print("%1case %d: /* %S */\n", p->esn, p); switch (p->arity) { @@ -823,7 +826,8 @@ static void emitstate(Term terms, Nonterm start, int ntnumber) for (p = terms; p; p = p->link) emitcase(p, ntnumber); print("%1default:\n" - "%2%Passert(0, PANIC(\"Bad operator %%d in %Pstate\\n\", op));\n%1}\n" + "%2%Ppanic_cannot_match(node);\n" + "%1}\n" "%1return (STATE_TYPE)p;\n}\n\n"); } diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 59c84a3ea..0ad0fdeea 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -86,15 +86,6 @@ extern int yylineno; extern void printlineno(void); -/* Excruciating macro which packs ir opcodes and sizes into an int for iburg's benefit. - * - * Sizes are mapped as: 0=1, 1=1, 2=2, 4=3, 8=4. - */ -#define ir_to_esn(iropcode, size) \ - ((iropcode)*4 + \ - (((size) == 4) ? 2 : \ - ((size) == 8) ? 3 : \ - ((size) == 0) ? 0 : \ - (size-1))) +#include "mcgg.h" #endif diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 95059a650..a7487cda0 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -7,7 +7,7 @@ S CONST S REG S LABEL S BLOCK -S PAIR +V PAIR S ANY S LOCAL S PHI @@ -64,7 +64,9 @@ V CALL # Flow control --- these never return V JUMP -V CJUMP +V CJUMPEQ +V CJUMPLT +V CJUMPLE V RET # Special diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h new file mode 100644 index 000000000..297be186b --- /dev/null +++ b/util/mcgg/mcgg.h @@ -0,0 +1,30 @@ +#ifndef MCGG_H +#define MCGG_H + +/* Excruciating macro which packs ir opcodes and sizes into an int for iburg's benefit. + * + * Sizes are mapped as: 0=1, 1=1, 2=2, 4=3, 8=4. + */ +#define ir_to_esn(iropcode, size) \ + ((iropcode)*4 + \ + (((size) == 4) ? 2 : \ + ((size) == 8) ? 3 : \ + ((size) == 0) ? 0 : \ + (size-1))) + + +#define STATE_TYPE void* +typedef struct ir* NODEPTR_TYPE; + +#define STATE_LABEL(p) ((p)->state_label) + +extern void* burm_label(struct ir* ir); +extern int burm_rule(void* state, int goalnt); +extern const char* burm_string[]; +extern const short *burm_nts[]; +extern struct ir** burm_kids(struct ir* p, int eruleno, struct ir* kids[]); +extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost); + +#endif + +/* vim: set sw=4 ts=4 expandtab : */ diff --git a/util/mcgg/scan.l b/util/mcgg/scan.l index ebcb9c107..0e0a92cd4 100644 --- a/util/mcgg/scan.l +++ b/util/mcgg/scan.l @@ -22,7 +22,7 @@ static int braces = 0; [^%\n]* fputs(yytext, outfp); "{" { - yylval.string = stringf("#line %d\n", yylineno); + yylval.string = ""; //stringf("#line %d\n", yylineno); braces = 1; BEGIN(CSTRING); return CFRAGMENT;