Actually, I don't need vregs: hops work just as well. Particularly if I

restructure things so that I don't need to walk the blasted ir / burg tree
every time I look at an instruction.
This commit is contained in:
David Given 2016-09-27 23:38:47 +02:00
parent e77c5164cf
commit 4572f1b774
8 changed files with 166 additions and 94 deletions

View file

@ -28,7 +28,6 @@ cprogram {
vars = { vars = {
["+cflags"] = { ["+cflags"] = {
"-Werror-implicit-function-declaration", "-Werror-implicit-function-declaration",
"-Wint-conversion"
} }
} }
} }

View file

@ -1,6 +1,6 @@
#include "mcg.h" #include "mcg.h"
static char outbuf[256]; static int hop_count = 1;
static struct hop* current_hop; static struct hop* current_hop;
static const struct burm_emitter_data emitter_data; static const struct burm_emitter_data emitter_data;
@ -8,85 +8,97 @@ 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->id = hop_count++;
hop->insn_no = insn_no; hop->insn_no = insn_no;
hop->ir = ir; hop->ir = ir;
return hop; return hop;
} }
static void append(const char* fmt, ...) static struct insel* new_insel(enum insel_type type)
{ {
va_list ap; struct insel* insel = calloc(1, sizeof(*insel));
insel->type = type;
va_start(ap, fmt); return insel;
vsprintf(outbuf + strlen(outbuf), fmt, ap);
va_end(ap);
} }
static void emit_reg(struct ir* ir) void hop_add_string_insel(struct hop* hop, const char* string)
{ {
struct hop* hop = ir->hop; struct insel* insel = new_insel(INSEL_STRING);
if (hop) insel->u.string = string;
{ array_append(&hop->insels, insel);
/* 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);
}
} }
static void emit_string(const char* data) void hop_add_reg_insel(struct hop* hop, struct hop* reg)
{ {
append("%s", data); struct insel* insel = new_insel(INSEL_REG);
insel->u.reg = reg;
array_append(&hop->insels, insel);
} }
static void emit_value(struct ir* ir) void hop_add_value_insel(struct hop* hop, struct ir* ir)
{ {
append("(val)"); struct insel* insel = new_insel(INSEL_VALUE);
insel->u.value = ir;
array_append(&hop->insels, insel);
} }
static void emit_resultreg(void) void hop_add_eoi_insel(struct hop* hop)
{ {
append("%%%d", current_hop->resultvreg->id); struct insel* insel = new_insel(INSEL_EOI);
array_append(&hop->insels, insel);
} }
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) void hop_print(char k, struct hop* hop)
{ {
char* s; int i;
const struct burm_instruction_data* insndata = &burm_instruction_data[hop->insn_no]; bool soi = true;
current_hop = hop; i = 0;
outbuf[0] = 0; for (i=0; i<hop->insels.count; i++)
if (insndata->emitter)
{ {
insndata->emitter(hop->ir, &emitter_data); struct insel* insel = hop->insels.item[i];
s = strtok(outbuf, "\n"); if (soi)
do
{ {
tracef(k, "%c: %p: %s\n", k, hop, s); tracef(k, "%c: %d: ", k, hop->id);
s = strtok(NULL, "\n"); soi = false;
}
switch (insel->type)
{
case INSEL_EOI:
tracef(k, "\n");
soi = true;
break;
case INSEL_REG:
tracef(k, "%%%d", insel->u.reg->id);
break;
case INSEL_STRING:
tracef(k, "%s", insel->u.string);
break;
case INSEL_VALUE:
{
struct ir* ir = insel->u.value;
switch (ir->opcode)
{
case IR_BLOCK:
tracef(k, "%s", ir->u.bvalue->name);
break;
case IR_LOCAL:
case IR_CONST:
tracef(k, "0x%d", ir->u.ivalue);
break;
}
break;
}
} }
while (s);
} }
else
tracef(k, "%c: %p: (empty)\n", k, hop); if (!soi)
tracef(k, "\n", k);
} }

View file

@ -1,19 +1,43 @@
#ifndef HOP_H #ifndef HOP_H
#define HOP_H #define HOP_H
enum insel_type
{
INSEL_STRING,
INSEL_REG,
INSEL_VALUE,
INSEL_EOI
};
struct insel
{
enum insel_type type;
union
{
const char* string;
struct hop* reg;
struct ir* value;
}
u;
};
struct hop struct hop
{ {
int id;
int insn_no; int insn_no;
struct ir* ir; struct ir* ir;
struct vreg* resultvreg; struct hop* result;
ARRAYOF(struct vreg) invregs; ARRAYOF(struct hop) params;
ARRAYOF(struct vreg) outvregs; ARRAYOF(struct insel) insels;
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_string_insel(struct hop* hop, const char* string);
extern void hop_add_reg_insel(struct hop* hop, struct hop* reg);
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
extern void hop_add_eoi_insel(struct hop* hop);
extern void hop_print(char k, struct hop* hop); extern void hop_print(char k, struct hop* hop);
#endif #endif

View file

@ -20,7 +20,6 @@
#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];

View file

@ -1,6 +1,9 @@
#include "mcg.h" #include "mcg.h"
static struct basicblock* current_bb; static struct basicblock* current_bb;
static struct hop* current_hop;
static const struct burm_emitter_data emitter_data;
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];
@ -16,28 +19,67 @@ void burm_panic_cannot_match(struct ir* ir)
exit(1); exit(1);
} }
static void walk_instructions(struct hop* hop, struct ir* ir, int goal) static void emit_reg(struct ir* ir)
{
if (ir->hop)
hop_add_reg_insel(current_hop, ir->hop);
else
{
const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no];
if (insndata->emitter)
insndata->emitter(ir, &emitter_data);
}
}
static void emit_string(const char* data)
{
hop_add_string_insel(current_hop, data);
}
static void emit_value(struct ir* ir)
{
hop_add_value_insel(current_hop, ir);
}
static void emit_resultreg(void)
{
hop_add_reg_insel(current_hop, current_hop);
}
static void emit_eoi(void)
{
hop_add_eoi_insel(current_hop);
}
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];
struct hop* parent_hop = NULL;
int i; int i;
ir->insn_no = insn_no; ir->insn_no = insn_no;
if (!insndata->is_fragment) if (!insndata->is_fragment)
hop = ir->hop = new_hop(insn_no, ir);;
if (insndata->allocate)
{ {
hop->resultvreg = new_vreg(); parent_hop = current_hop;
array_append(&hop->newvregs, hop->resultvreg); current_hop = ir->hop = new_hop(insn_no, ir);
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(hop, children[i], nts[i]); walk_instructions(children[i], nts[i]);
ir->is_generated = true; ir->is_generated = true;
@ -50,8 +92,12 @@ static void walk_instructions(struct hop* hop, struct ir* ir, int goal)
if (!insndata->is_fragment) if (!insndata->is_fragment)
{ {
array_append(&current_bb->hops, hop); if (insndata->emitter)
hop_print('I', hop); insndata->emitter(ir, &emitter_data);
hop_print('I', current_hop);
array_append(&current_bb->hops, current_hop);
current_hop = parent_hop;
} }
} }
@ -73,7 +119,7 @@ static void select_instructions(void)
burm_panic_cannot_match(ir); burm_panic_cannot_match(ir);
ir_print('I', ir); ir_print('I', ir);
walk_instructions(NULL, ir, 1); walk_instructions(ir, 1);
} }
} }

View file

@ -21,6 +21,7 @@ DECLARATIONS
aluparam fragment; aluparam fragment;
reg allocates(GPR); reg allocates(GPR);
tristate allocates(CC); tristate allocates(CC);
bistate allocates(CC);
PATTERNS PATTERNS
@ -105,6 +106,11 @@ PATTERNS
emit "b $false" emit "b $false"
cost 8; cost 8;
CJUMPEQ(value:bistate, PAIR(true:BLOCK4, false:BLOCK4))
emit "beq $true"
emit "b $false"
cost 8;
/* Comparisons */ /* Comparisons */
@ -112,12 +118,21 @@ PATTERNS
emit "cmp %left, %right" emit "cmp %left, %right"
cost 4; cost 4;
bistate = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4)
emit "cmp %left, %right"
cost 4;
reg = tristate reg = tristate
emit "mov %reg, #0" emit "mov %reg, #0"
emit "movlt %reg, #-1" emit "movlt %reg, #-1"
emit "movgt %reg, #1" emit "movgt %reg, #1"
cost 12; cost 12;
reg = bistate
emit "moveq %reg, #1"
emit "movne %reg, #0"
cost 8;
/* Conversions */ /* Conversions */

View file

@ -1,10 +0,0 @@
#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;
}

View file

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