Some instruction selection is now happening.
This commit is contained in:
parent
c8fcbe282a
commit
629e0ddfc6
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,32 +1,20 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#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);
|
||||
|
||||
|
|
87
mach/proto/mcg/pass_instsel.c
Normal file
87
mach/proto/mcg/pass_instsel.c
Normal 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 : */
|
||||
|
|
@ -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 : */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
30
util/mcgg/mcgg.h
Normal file
30
util/mcgg/mcgg.h
Normal 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 : */
|
|
@ -22,7 +22,7 @@ static int braces = 0;
|
|||
<ECHO>[^%\n]* fputs(yytext, outfp);
|
||||
|
||||
<INITIAL>"{" {
|
||||
yylval.string = stringf("#line %d\n", yylineno);
|
||||
yylval.string = ""; //stringf("#line %d\n", yylineno);
|
||||
braces = 1;
|
||||
BEGIN(CSTRING);
|
||||
return CFRAGMENT;
|
||||
|
|
Loading…
Reference in a new issue