Some instruction selection is now happening.

This commit is contained in:
David Given 2016-09-24 22:46:08 +02:00
parent c8fcbe282a
commit 629e0ddfc6
15 changed files with 264 additions and 55 deletions

View file

@ -33,7 +33,11 @@ struct ir
const char* lvalue; const char* lvalue;
struct basicblock* bvalue; struct basicblock* bvalue;
} u; } u;
void* state_label; /* used by the iburg instruction selector */
bool is_sequence : 1; bool is_sequence : 1;
bool is_generated : 1;
}; };
extern const char* ir_names[]; extern const char* ir_names[];

View file

@ -37,9 +37,10 @@ bool tracing(char k)
{ {
switch (k) switch (k)
{ {
case 0: return true;
case 'E': return false; case 'E': return false;
case '0': return false; case '0': return false;
case '1': return true; case '1': return false;
case '2': return true; case '2': return true;
default: return true; default: return true;
} }

View file

@ -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_convert_stack_ops(struct procedure* proc);
extern void pass_remove_dead_blocks(struct procedure* proc); extern void pass_remove_dead_blocks(struct procedure* proc);
extern void pass_eliminate_trivial_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); extern void procedure_compile(struct procedure* proc);

View file

@ -19,6 +19,7 @@ static void dumpCover(NODEPTR_TYPE p, int goalnt, int indent) {
#endif #endif
} }
#if 0
static NODEPTR_TYPE tree(int op, NODEPTR_TYPE l, NODEPTR_TYPE r) { static NODEPTR_TYPE tree(int op, NODEPTR_TYPE l, NODEPTR_TYPE r) {
NODEPTR_TYPE p = malloc(sizeof *p); NODEPTR_TYPE p = malloc(sizeof *p);
@ -48,4 +49,5 @@ int main(void) {
dumpCover(p, 1, 0); dumpCover(p, 1, 0);
return 0; return 0;
} }
#endif

View file

@ -1,32 +1,20 @@
#include <stdio.h> #include "mcg.h"
#include <assert.h> #include "mcgg.h"
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <stdlib.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 #define PANIC printf
static void burm_trace(NODEPTR_TYPE p, int eruleno, int cost, int bestcost) { static int OP_LABEL(struct ir* ir)
#ifdef TRACE {
extern const char *burm_string[]; if (ir->is_generated)
return ir_to_esn(IR_REG, ir->size);
fprintf(stderr, "0x%p matched %s with cost %d vs. %d\n", p, return ir_to_esn(ir->opcode, ir->size);
burm_string[eruleno], cost, bestcost);
#endif
} }
#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);

View file

@ -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; i<bb->irs_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; i<proc->blocks_count; i++)
{
struct basicblock* bb = proc->blocks[i];
select_instructions(bb);
}
exit(1);
}
/* vim: set sw=4 ts=4 expandtab : */

View file

@ -31,6 +31,8 @@ void procedure_compile(struct procedure* proc)
pass_convert_stack_ops(proc); pass_convert_stack_ops(proc);
print_blocks('2', proc); print_blocks('2', proc);
pass_instruction_selector(proc);
} }
/* vim: set sw=4 ts=4 expandtab : */ /* vim: set sw=4 ts=4 expandtab : */

View file

@ -1,5 +1,33 @@
PATTERNS 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) STORE4(addr:address, value:reg)
ins value:GPR ins value:GPR
emit "str %value, %addr" emit "str %value, %addr"
@ -7,9 +35,33 @@ PATTERNS
reg = LOAD4(addr:address) reg = LOAD4(addr:address)
outs dest:ANY outs dest:ANY
emit "ld %dest, %addr" emit "ldr %dest, %addr"
cost 4; 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) address = ADD4(addr:reg, offset:CONST)
ins addr:GPR ins addr:GPR
fragment "[%addr, #%offset.ivalue]"; fragment "[%addr, #%offset.ivalue]";
@ -18,7 +70,47 @@ PATTERNS
ins addr:GPR ins addr:GPR
fragment "[%addr]"; 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) reg = ADD4(left:reg, right:aluparam)
ins left:GPR, right:GPR ins left:GPR, right:GPR
@ -33,7 +125,6 @@ PATTERNS
cost 4; cost 4;
aluparam = value:CONST4 aluparam = value:CONST4
when { return false; }
fragment "#%value.ivalue"; fragment "#%value.ivalue";
aluparam = reg; aluparam = reg;
@ -45,7 +136,12 @@ PATTERNS
reg = value:LABEL4 reg = value:LABEL4
outs out:GPR 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; cost 4;
reg = value:CONST4 reg = value:CONST4

View file

@ -231,9 +231,9 @@ static void simple_branch2(int opcode, int size,
materialise_stack(); materialise_stack();
appendir( appendir(
new_ir2( new_ir2(
IR_CJUMP, 0, irop, 0,
new_ir2( new_ir2(
irop, size, IR_COMPARES, size,
left, right left, right
), ),
new_ir2( new_ir2(
@ -260,13 +260,13 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock
{ {
switch (opcode) switch (opcode)
{ {
case op_zeq: compare0_branch2(opcode, leftbb, rightbb, IR_IFEQ); break; case op_zeq: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPEQ); break;
case op_zlt: compare0_branch2(opcode, leftbb, rightbb, IR_IFLT); break; case op_zlt: compare0_branch2(opcode, leftbb, rightbb, IR_CJUMPLT); break;
case op_zle: compare0_branch2(opcode, leftbb, rightbb, IR_IFLE); 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_zne: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPEQ); break;
case op_zge: compare0_branch2(opcode, rightbb, leftbb, IR_IFLT); break; case op_zge: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPLT); break;
case op_zgt: compare0_branch2(opcode, rightbb, leftbb, IR_IFLE); break; case op_zgt: compare0_branch2(opcode, rightbb, leftbb, IR_CJUMPLE); break;
case op_bra: case op_bra:
{ {

View file

@ -28,7 +28,8 @@ clibrary {
matching(filenamesof("+ircodes"), "%.c$") matching(filenamesof("+ircodes"), "%.c$")
}, },
hdrs = { hdrs = {
matching(filenamesof("+ircodes"), "%.h$") matching(filenamesof("+ircodes"), "%.h$"),
"./mcgg.h"
} }
} }
@ -40,7 +41,7 @@ cprogram {
matching(filenamesof("+yacc"), "%.c$") matching(filenamesof("+yacc"), "%.c$")
}, },
deps = { deps = {
"./*.h", "./iburg.h",
"+lib", "+lib",
"+yacc" "+yacc"
} }

View file

@ -419,7 +419,7 @@ static void print(char* fmt, ...)
void printlineno(void) void printlineno(void)
{ {
print("#line %d\n", yylineno); //print("#line %d\n", yylineno);
} }
/* reach - mark all non-terminals in tree t as reachable */ /* reach - mark all non-terminals in tree t as reachable */
@ -451,6 +451,9 @@ static void emitcase(Term p, int ntnumber)
{ {
Rule r; Rule r;
if (!p->rules)
return;
print("%1case %d: /* %S */\n", p->esn, p); print("%1case %d: /* %S */\n", p->esn, p);
switch (p->arity) switch (p->arity)
{ {
@ -823,7 +826,8 @@ static void emitstate(Term terms, Nonterm start, int ntnumber)
for (p = terms; p; p = p->link) for (p = terms; p; p = p->link)
emitcase(p, ntnumber); emitcase(p, ntnumber);
print("%1default:\n" 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"); "%1return (STATE_TYPE)p;\n}\n\n");
} }

View file

@ -86,15 +86,6 @@ extern int yylineno;
extern void printlineno(void); extern void printlineno(void);
/* Excruciating macro which packs ir opcodes and sizes into an int for iburg's benefit. #include "mcgg.h"
*
* 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)))
#endif #endif

View file

@ -7,7 +7,7 @@ S CONST
S REG S REG
S LABEL S LABEL
S BLOCK S BLOCK
S PAIR V PAIR
S ANY S ANY
S LOCAL S LOCAL
S PHI S PHI
@ -64,7 +64,9 @@ V CALL
# Flow control --- these never return # Flow control --- these never return
V JUMP V JUMP
V CJUMP V CJUMPEQ
V CJUMPLT
V CJUMPLE
V RET V RET
# Special # Special

30
util/mcgg/mcgg.h Normal file
View file

@ -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 : */

View file

@ -22,7 +22,7 @@ static int braces = 0;
<ECHO>[^%\n]* fputs(yytext, outfp); <ECHO>[^%\n]* fputs(yytext, outfp);
<INITIAL>"{" { <INITIAL>"{" {
yylval.string = stringf("#line %d\n", yylineno); yylval.string = ""; //stringf("#line %d\n", yylineno);
braces = 1; braces = 1;
BEGIN(CSTRING); BEGIN(CSTRING);
return CFRAGMENT; return CFRAGMENT;