Fleshed out hops and vregs. The result is almost looking like code now ---
uncanny.
This commit is contained in:
parent
f552c9c7c6
commit
e77c5164cf
9 changed files with 128 additions and 120 deletions
|
@ -1,39 +1,92 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
|
|
||||||
|
static char outbuf[256];
|
||||||
|
static struct hop* current_hop;
|
||||||
|
|
||||||
|
static const struct burm_emitter_data emitter_data;
|
||||||
|
|
||||||
struct hop* new_hop(int insn_no, struct ir* ir)
|
struct hop* new_hop(int insn_no, struct ir* ir)
|
||||||
{
|
{
|
||||||
struct hop* hop = calloc(1, sizeof *hop);
|
struct hop* hop = calloc(1, sizeof *hop);
|
||||||
hop->insn_no = insn_no;
|
hop->insn_no = insn_no;
|
||||||
hop->ir = ir;
|
hop->ir = ir;
|
||||||
|
return hop;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_reg(struct vreg* vregs[], struct vreg* vreg)
|
static void append(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
int i;
|
va_list ap;
|
||||||
|
|
||||||
for (i=0; i<HOP_INOUT_REGS; i++)
|
va_start(ap, fmt);
|
||||||
if (!vregs[i])
|
vsprintf(outbuf + strlen(outbuf), fmt, ap);
|
||||||
{
|
va_end(ap);
|
||||||
vregs[i] = vreg;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fatal("too many input registers for instruction");
|
static void emit_reg(struct ir* ir)
|
||||||
|
{
|
||||||
|
struct hop* hop = ir->hop;
|
||||||
|
if (hop)
|
||||||
|
{
|
||||||
|
/* Reference to another hop must be its result register. */
|
||||||
|
append("%%%d", hop->resultvreg->id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* ...if there is no hop, it's a fragment. */
|
||||||
|
const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no];
|
||||||
|
insndata->emitter(ir, &emitter_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hop_add_in_reg(struct hop* hop, struct vreg* vreg)
|
static void emit_string(const char* data)
|
||||||
{
|
{
|
||||||
add_reg(hop->invregs, vreg);
|
append("%s", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hop_add_out_reg(struct hop* hop, struct vreg* vreg)
|
static void emit_value(struct ir* ir)
|
||||||
{
|
{
|
||||||
add_reg(hop->outvregs, vreg);
|
append("(val)");
|
||||||
}
|
}
|
||||||
|
|
||||||
void hop_emit(struct hop* hop, const struct burm_emitter_data* ed)
|
static void emit_resultreg(void)
|
||||||
{
|
{
|
||||||
|
append("%%%d", current_hop->resultvreg->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_eoi(void)
|
||||||
|
{
|
||||||
|
append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct burm_emitter_data emitter_data =
|
||||||
|
{
|
||||||
|
&emit_string,
|
||||||
|
&emit_reg,
|
||||||
|
&emit_value,
|
||||||
|
&emit_resultreg,
|
||||||
|
&emit_eoi
|
||||||
|
};
|
||||||
|
|
||||||
|
void hop_print(char k, struct hop* hop)
|
||||||
|
{
|
||||||
|
char* s;
|
||||||
const struct burm_instruction_data* insndata = &burm_instruction_data[hop->insn_no];
|
const struct burm_instruction_data* insndata = &burm_instruction_data[hop->insn_no];
|
||||||
insndata->emitter(hop->ir, ed);
|
|
||||||
|
current_hop = hop;
|
||||||
|
outbuf[0] = 0;
|
||||||
|
if (insndata->emitter)
|
||||||
|
{
|
||||||
|
insndata->emitter(hop->ir, &emitter_data);
|
||||||
|
|
||||||
|
s = strtok(outbuf, "\n");
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tracef(k, "%c: %p: %s\n", k, hop, s);
|
||||||
|
s = strtok(NULL, "\n");
|
||||||
|
}
|
||||||
|
while (s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tracef(k, "%c: %p: (empty)\n", k, hop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,20 @@
|
||||||
#ifndef HOP_H
|
#ifndef HOP_H
|
||||||
#define HOP_H
|
#define HOP_H
|
||||||
|
|
||||||
struct vreg
|
|
||||||
{
|
|
||||||
int id;
|
|
||||||
int regclass;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define HOP_INOUT_REGS 4
|
|
||||||
|
|
||||||
struct hop
|
struct hop
|
||||||
{
|
{
|
||||||
int insn_no;
|
int insn_no;
|
||||||
struct ir* ir;
|
struct ir* ir;
|
||||||
struct vreg* invregs[HOP_INOUT_REGS];
|
struct vreg* resultvreg;
|
||||||
struct vreg* outvregs[HOP_INOUT_REGS];
|
ARRAYOF(struct vreg) invregs;
|
||||||
|
ARRAYOF(struct vreg) outvregs;
|
||||||
|
ARRAYOF(struct vreg) newvregs;
|
||||||
|
ARRAYOF(struct vreg) deadvregs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct hop* new_hop(int insn_no, struct ir* ir);
|
extern struct hop* new_hop(int insn_no, struct ir* ir);
|
||||||
|
|
||||||
extern void hop_add_in_reg(struct hop* hop, struct vreg* reg);
|
extern void hop_print(char k, struct hop* hop);
|
||||||
extern void hop_add_out_reg(struct hop* hop, struct vreg* reg);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ struct ir
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
void* state_label; /* used by the iburg instruction selector */
|
void* state_label; /* used by the iburg instruction selector */
|
||||||
int insn_no;
|
int insn_no; /* the table rule number for this instruction */
|
||||||
int vreg;
|
struct hop* hop; /* only for IRs that root a hardware op */
|
||||||
|
|
||||||
bool is_sequence : 1;
|
bool is_sequence : 1;
|
||||||
bool is_generated : 1;
|
bool is_generated : 1;
|
||||||
|
|
|
@ -41,7 +41,8 @@ bool tracing(char k)
|
||||||
case 'E': return false;
|
case 'E': return false;
|
||||||
case '0': return false;
|
case '0': return false;
|
||||||
case '1': return false;
|
case '1': return false;
|
||||||
case '2': return true;
|
case '2': return false;
|
||||||
|
case 'I': return true;
|
||||||
default: return true;
|
default: return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "ir.h"
|
#include "ir.h"
|
||||||
#include "mcgg.h"
|
#include "mcgg.h"
|
||||||
|
#include "vreg.h"
|
||||||
#include "hop.h"
|
#include "hop.h"
|
||||||
|
|
||||||
extern char em_pseu[][4];
|
extern char em_pseu[][4];
|
||||||
|
|
|
@ -1,29 +1,6 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
|
|
||||||
static int vregcount;
|
static struct basicblock* current_bb;
|
||||||
|
|
||||||
#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) {
|
void burm_trace(struct ir* p, int ruleno, int cost, int bestcost) {
|
||||||
const struct burm_instruction_data* insndata = &burm_instruction_data[ruleno];
|
const struct burm_instruction_data* insndata = &burm_instruction_data[ruleno];
|
||||||
|
@ -39,72 +16,30 @@ void burm_panic_cannot_match(struct ir* ir)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct burm_emitter_data emitter_data;
|
static void walk_instructions(struct hop* hop, struct ir* ir, int goal)
|
||||||
|
|
||||||
static void emit_string(const char* data)
|
|
||||||
{
|
|
||||||
tracef('I', "I: emit: %s\n", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_reg(struct ir* ir)
|
|
||||||
{
|
|
||||||
const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no];
|
|
||||||
if (insndata->is_fragment)
|
|
||||||
insndata->emitter(ir, &emitter_data);
|
|
||||||
else
|
|
||||||
tracef('I', "I: emit reg %d\n", ir->vreg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_value(struct ir* ir)
|
|
||||||
{
|
|
||||||
tracef('I', "I: emit value\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_resultreg(void)
|
|
||||||
{
|
|
||||||
tracef('I', "I: emit resultreg\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_eoi(void)
|
|
||||||
{
|
|
||||||
tracef('I', "I: emit eoi\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct burm_emitter_data emitter_data =
|
|
||||||
{
|
|
||||||
&emit_string,
|
|
||||||
&emit_reg,
|
|
||||||
&emit_value,
|
|
||||||
&emit_resultreg,
|
|
||||||
&emit_eoi
|
|
||||||
};
|
|
||||||
|
|
||||||
static void walk_instructions(struct ir* ir, int goal)
|
|
||||||
{
|
{
|
||||||
struct ir* children[10];
|
struct ir* children[10];
|
||||||
int insn_no = burm_rule(ir->state_label, goal);
|
int insn_no = burm_rule(ir->state_label, goal);
|
||||||
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
|
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
|
||||||
const short* nts = burm_nts[insn_no];
|
const short* nts = burm_nts[insn_no];
|
||||||
int i;
|
int i;
|
||||||
int resultreg = 0;
|
|
||||||
|
|
||||||
ir->insn_no = insn_no;
|
ir->insn_no = insn_no;
|
||||||
|
if (!insndata->is_fragment)
|
||||||
|
hop = ir->hop = new_hop(insn_no, ir);;
|
||||||
|
|
||||||
if (insndata->allocate)
|
if (insndata->allocate)
|
||||||
{
|
{
|
||||||
resultreg = vregcount++;
|
hop->resultvreg = new_vreg();
|
||||||
tracef('I', "I: new %s %d\n",
|
array_append(&hop->newvregs, hop->resultvreg);
|
||||||
burm_register_class_names[insndata->allocate], resultreg);
|
array_append(&hop->outvregs, hop->resultvreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
burm_kids(ir, insn_no, children);
|
burm_kids(ir, insn_no, children);
|
||||||
for (i=0; nts[i]; i++)
|
for (i=0; nts[i]; i++)
|
||||||
walk_instructions(children[i], nts[i]);
|
walk_instructions(hop, children[i], nts[i]);
|
||||||
|
|
||||||
if (ir->vreg)
|
ir->is_generated = true;
|
||||||
tracef('I', "I: use %d\n", ir->vreg);
|
|
||||||
if (resultreg)
|
|
||||||
ir->vreg = resultreg;
|
|
||||||
|
|
||||||
tracef('I', "I: $%d %s selected %s %d: %s\n",
|
tracef('I', "I: $%d %s selected %s %d: %s\n",
|
||||||
ir->id,
|
ir->id,
|
||||||
|
@ -112,30 +47,33 @@ static void walk_instructions(struct ir* ir, int goal)
|
||||||
insndata->is_fragment ? "fragment" : "instruction",
|
insndata->is_fragment ? "fragment" : "instruction",
|
||||||
insn_no,
|
insn_no,
|
||||||
insndata->name);
|
insndata->name);
|
||||||
ir->is_generated = true;
|
|
||||||
|
|
||||||
if (!insndata->is_fragment && insndata->emitter)
|
if (!insndata->is_fragment)
|
||||||
insndata->emitter(ir, &emitter_data);
|
{
|
||||||
|
array_append(¤t_bb->hops, hop);
|
||||||
|
hop_print('I', hop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void select_instructions(struct basicblock* bb)
|
static void select_instructions(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
tracef('I', "I: BLOCK: %s\n", bb->name);
|
tracef('I', "I: BLOCK: %s\n", current_bb->name);
|
||||||
|
|
||||||
for (i=0; i<bb->irs.count; i++)
|
for (i=0; i<current_bb->irs.count; i++)
|
||||||
{
|
{
|
||||||
int insnno;
|
int insnno;
|
||||||
struct ir* ir = bb->irs.item[i];
|
struct ir* ir = current_bb->irs.item[i];
|
||||||
burm_label(ir);
|
burm_label(ir);
|
||||||
|
|
||||||
insnno = burm_rule(ir->state_label, 1);
|
insnno = burm_rule(ir->state_label, 1);
|
||||||
if (!insnno)
|
if (!insnno)
|
||||||
burm_panic_cannot_match(ir);
|
burm_panic_cannot_match(ir);
|
||||||
|
|
||||||
walk_instructions(ir, 1);
|
ir_print('I', ir);
|
||||||
|
walk_instructions(NULL, ir, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,12 +81,10 @@ void pass_instruction_selector(struct procedure* proc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
vregcount = 1;
|
|
||||||
|
|
||||||
for (i=0; i<proc->blocks.count; i++)
|
for (i=0; i<proc->blocks.count; i++)
|
||||||
{
|
{
|
||||||
struct basicblock* bb = proc->blocks.item[i];
|
current_bb = proc->blocks.item[i];
|
||||||
select_instructions(bb);
|
select_instructions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ PATTERNS
|
||||||
|
|
||||||
CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4))
|
CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4))
|
||||||
emit "beq $true"
|
emit "beq $true"
|
||||||
emit "bne $false"
|
emit "b $false"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
|
|
||||||
|
|
10
mach/proto/mcg/vreg.c
Normal file
10
mach/proto/mcg/vreg.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "mcg.h"
|
||||||
|
|
||||||
|
static int vreg_count = 0;
|
||||||
|
|
||||||
|
struct vreg* new_vreg(void)
|
||||||
|
{
|
||||||
|
struct vreg* vreg = calloc(1, sizeof *vreg);
|
||||||
|
vreg->id = vreg_count++;
|
||||||
|
return vreg;
|
||||||
|
}
|
13
mach/proto/mcg/vreg.h
Normal file
13
mach/proto/mcg/vreg.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef VREG_H
|
||||||
|
#define VREG_H
|
||||||
|
|
||||||
|
struct vreg
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct vreg* new_vreg(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue