Fleshed out hops and vregs. The result is almost looking like code now ---

uncanny.
This commit is contained in:
David Given 2016-09-27 00:19:45 +02:00
parent f552c9c7c6
commit e77c5164cf
9 changed files with 128 additions and 120 deletions

View file

@ -1,39 +1,92 @@
#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* hop = calloc(1, sizeof *hop);
hop->insn_no = insn_no;
hop->ir = ir;
return hop;
}
static void add_reg(struct vreg* vregs[], struct vreg* vreg)
static void append(const char* fmt, ...)
{
int i;
for (i=0; i<HOP_INOUT_REGS; i++)
if (!vregs[i])
{
vregs[i] = vreg;
return;
}
fatal("too many input registers for instruction");
va_list ap;
va_start(ap, fmt);
vsprintf(outbuf + strlen(outbuf), fmt, ap);
va_end(ap);
}
void hop_add_in_reg(struct hop* hop, struct vreg* vreg)
static void emit_reg(struct ir* ir)
{
add_reg(hop->invregs, vreg);
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_out_reg(struct hop* hop, struct vreg* vreg)
static void emit_string(const char* data)
{
add_reg(hop->outvregs, vreg);
append("%s", data);
}
void hop_emit(struct hop* hop, const struct burm_emitter_data* ed)
static void emit_value(struct ir* ir)
{
append("(val)");
}
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];
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);
}

View file

@ -1,26 +1,20 @@
#ifndef HOP_H
#define HOP_H
struct vreg
{
int id;
int regclass;
};
#define HOP_INOUT_REGS 4
struct hop
{
int insn_no;
struct ir* ir;
struct vreg* invregs[HOP_INOUT_REGS];
struct vreg* outvregs[HOP_INOUT_REGS];
struct vreg* resultvreg;
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 void hop_add_in_reg(struct hop* hop, struct vreg* reg);
extern void hop_add_out_reg(struct hop* hop, struct vreg* reg);
extern void hop_print(char k, struct hop* hop);
#endif

View file

@ -20,8 +20,8 @@ struct ir
} u;
void* state_label; /* used by the iburg instruction selector */
int insn_no;
int vreg;
int insn_no; /* the table rule number for this instruction */
struct hop* hop; /* only for IRs that root a hardware op */
bool is_sequence : 1;
bool is_generated : 1;

View file

@ -41,7 +41,8 @@ bool tracing(char k)
case 'E': return false;
case '0': return false;
case '1': return false;
case '2': return true;
case '2': return false;
case 'I': return true;
default: return true;
}
}

View file

@ -20,6 +20,7 @@
#include "map.h"
#include "ir.h"
#include "mcgg.h"
#include "vreg.h"
#include "hop.h"
extern char em_pseu[][4];

View file

@ -1,29 +1,6 @@
#include "mcg.h"
static int vregcount;
#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
static struct basicblock* current_bb;
void burm_trace(struct ir* p, int ruleno, int cost, int bestcost) {
const struct burm_instruction_data* insndata = &burm_instruction_data[ruleno];
@ -39,72 +16,30 @@ void burm_panic_cannot_match(struct ir* ir)
exit(1);
}
static const struct burm_emitter_data emitter_data;
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)
static void walk_instructions(struct hop* hop, struct ir* ir, int goal)
{
struct ir* children[10];
int insn_no = burm_rule(ir->state_label, goal);
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
const short* nts = burm_nts[insn_no];
int i;
int resultreg = 0;
ir->insn_no = insn_no;
if (!insndata->is_fragment)
hop = ir->hop = new_hop(insn_no, ir);;
if (insndata->allocate)
{
resultreg = vregcount++;
tracef('I', "I: new %s %d\n",
burm_register_class_names[insndata->allocate], resultreg);
hop->resultvreg = new_vreg();
array_append(&hop->newvregs, hop->resultvreg);
array_append(&hop->outvregs, hop->resultvreg);
}
burm_kids(ir, insn_no, children);
for (i=0; nts[i]; i++)
walk_instructions(children[i], nts[i]);
walk_instructions(hop, children[i], nts[i]);
if (ir->vreg)
tracef('I', "I: use %d\n", ir->vreg);
if (resultreg)
ir->vreg = resultreg;
ir->is_generated = true;
tracef('I', "I: $%d %s selected %s %d: %s\n",
ir->id,
@ -112,30 +47,33 @@ static void walk_instructions(struct ir* ir, int goal)
insndata->is_fragment ? "fragment" : "instruction",
insn_no,
insndata->name);
ir->is_generated = true;
if (!insndata->is_fragment && insndata->emitter)
insndata->emitter(ir, &emitter_data);
if (!insndata->is_fragment)
{
array_append(&current_bb->hops, hop);
hop_print('I', hop);
}
}
static void select_instructions(struct basicblock* bb)
static void select_instructions(void)
{
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;
struct ir* ir = bb->irs.item[i];
struct ir* ir = current_bb->irs.item[i];
burm_label(ir);
insnno = burm_rule(ir->state_label, 1);
if (!insnno)
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;
vregcount = 1;
for (i=0; i<proc->blocks.count; i++)
{
struct basicblock* bb = proc->blocks.item[i];
select_instructions(bb);
current_bb = proc->blocks.item[i];
select_instructions();
}
}

View file

@ -102,7 +102,7 @@ PATTERNS
CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4))
emit "beq $true"
emit "bne $false"
emit "b $false"
cost 8;

10
mach/proto/mcg/vreg.c Normal file
View 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
View file

@ -0,0 +1,13 @@
#ifndef VREG_H
#define VREG_H
struct vreg
{
int id;
};
extern struct vreg* new_vreg(void);
#endif