Much better handling of fragments (no run-time code needed to distinguish them
from registers) and better handling of individual hops within a paragraph --- no more ghastly hacks to try and distinguish the input from the output.
This commit is contained in:
parent
a0131fdb47
commit
0d246c0d73
|
@ -28,10 +28,11 @@ void hop_add_string_insel(struct hop* hop, const char* string)
|
||||||
array_append(&hop->insels, insel);
|
array_append(&hop->insels, insel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hop_add_reg_insel(struct hop* hop, struct hop* reg)
|
void hop_add_reg_insel(struct hop* hop, struct ir* ir, int insn_no)
|
||||||
{
|
{
|
||||||
struct insel* insel = new_insel(INSEL_REG);
|
struct insel* insel = new_insel(INSEL_REG);
|
||||||
insel->u.reg = reg;
|
insel->u.reg.ir = ir;
|
||||||
|
insel->u.reg.insn_no = insn_no;
|
||||||
array_append(&hop->insels, insel);
|
array_append(&hop->insels, insel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ void hop_print(char k, struct hop* hop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INSEL_REG:
|
case INSEL_REG:
|
||||||
tracef(k, "%%%d", insel->u.reg->id);
|
tracef(k, "$%d.%d", insel->u.reg.ir->id, insel->u.reg.insn_no);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INSEL_STRING:
|
case INSEL_STRING:
|
||||||
|
|
|
@ -15,7 +15,12 @@ struct insel
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
const char* string;
|
const char* string;
|
||||||
struct hop* reg;
|
struct
|
||||||
|
{
|
||||||
|
struct ir* ir;
|
||||||
|
int insn_no;
|
||||||
|
}
|
||||||
|
reg;
|
||||||
struct ir* value;
|
struct ir* value;
|
||||||
}
|
}
|
||||||
u;
|
u;
|
||||||
|
@ -26,15 +31,13 @@ struct hop
|
||||||
int id;
|
int id;
|
||||||
int insn_no;
|
int insn_no;
|
||||||
struct ir* ir;
|
struct ir* ir;
|
||||||
struct hop* result;
|
|
||||||
ARRAYOF(struct hop) params;
|
|
||||||
ARRAYOF(struct insel) insels;
|
ARRAYOF(struct insel) insels;
|
||||||
};
|
};
|
||||||
|
|
||||||
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_string_insel(struct hop* hop, const char* string);
|
||||||
extern void hop_add_reg_insel(struct hop* hop, struct hop* reg);
|
extern void hop_add_reg_insel(struct hop* hop, struct ir* ir, int insn_no);
|
||||||
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
|
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
|
||||||
extern void hop_add_eoi_insel(struct hop* hop);
|
extern void hop_add_eoi_insel(struct hop* hop);
|
||||||
|
|
||||||
|
@ -42,4 +45,3 @@ extern void hop_print(char k, struct hop* hop);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,14 +71,14 @@ struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user)
|
||||||
if (cb(ir, user))
|
if (cb(ir, user))
|
||||||
return ir;
|
return ir;
|
||||||
|
|
||||||
if (ir->left && !ir->left->is_sequence)
|
if (ir->left && !ir->left->is_root)
|
||||||
{
|
{
|
||||||
struct ir* irr = ir_walk(ir->left, cb, user);
|
struct ir* irr = ir_walk(ir->left, cb, user);
|
||||||
if (irr)
|
if (irr)
|
||||||
return irr;
|
return irr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ir->right && !ir->right->is_sequence)
|
if (ir->right && !ir->right->is_root)
|
||||||
{
|
{
|
||||||
struct ir* irr = ir_walk(ir->right, cb, user);
|
struct ir* irr = ir_walk(ir->right, cb, user);
|
||||||
if (irr)
|
if (irr)
|
||||||
|
@ -126,7 +126,7 @@ static void print_expr(char k, const struct ir* ir)
|
||||||
default:
|
default:
|
||||||
if (ir->left)
|
if (ir->left)
|
||||||
{
|
{
|
||||||
if (ir->left->is_sequence)
|
if (ir->left->is_root)
|
||||||
tracef(k, "$%d", ir->left->id);
|
tracef(k, "$%d", ir->left->id);
|
||||||
else
|
else
|
||||||
print_expr(k, ir->left);
|
print_expr(k, ir->left);
|
||||||
|
@ -134,7 +134,7 @@ static void print_expr(char k, const struct ir* ir)
|
||||||
if (ir->right)
|
if (ir->right)
|
||||||
{
|
{
|
||||||
tracef(k, ", ");
|
tracef(k, ", ");
|
||||||
if (ir->right->is_sequence)
|
if (ir->right->is_root)
|
||||||
tracef(k, "$%d", ir->right->id);
|
tracef(k, "$%d", ir->right->id);
|
||||||
else
|
else
|
||||||
print_expr(k, ir->right);
|
print_expr(k, ir->right);
|
||||||
|
|
|
@ -20,9 +20,9 @@ struct ir
|
||||||
|
|
||||||
void* state_label; /* used by the iburg instruction selector */
|
void* state_label; /* used by the iburg instruction selector */
|
||||||
int insn_no; /* the table rule number for this instruction */
|
int insn_no; /* the table rule number for this instruction */
|
||||||
struct hop* hop; /* only for IRs that root a hardware op */
|
ARRAYOF(struct hop) hops; /* only for root IRs */
|
||||||
|
|
||||||
bool is_sequence : 1;
|
bool is_root : 1;
|
||||||
bool is_generated : 1;
|
bool is_generated : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
|
|
||||||
static int OP_LABEL(struct ir* ir)
|
static int OP_LABEL(struct ir* ir)
|
||||||
{
|
{
|
||||||
if (ir->is_generated)
|
if (ir->is_root && ir->is_generated)
|
||||||
{
|
{
|
||||||
assert(ir->is_sequence);
|
|
||||||
return ir_to_esn(IR_REG, ir->size);
|
return ir_to_esn(IR_REG, ir->size);
|
||||||
}
|
}
|
||||||
return ir_to_esn(ir->opcode, ir->size);
|
return ir_to_esn(ir->opcode, ir->size);
|
||||||
|
|
|
@ -112,9 +112,9 @@ static void convert_block(struct procedure* proc, struct basicblock* bb)
|
||||||
for (i=0; i<pushes.count; i++)
|
for (i=0; i<pushes.count; i++)
|
||||||
{
|
{
|
||||||
struct ir* ir = pushes.item[i];
|
struct ir* ir = pushes.item[i];
|
||||||
assert(ir->is_sequence);
|
assert(ir->is_root);
|
||||||
*ir = *ir->left;
|
*ir = *ir->left;
|
||||||
ir->is_sequence = true;
|
ir->is_root = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<pops.count; i++)
|
for (i=0; i<pops.count; i++)
|
||||||
|
@ -126,7 +126,7 @@ static void convert_block(struct procedure* proc, struct basicblock* bb)
|
||||||
for (j=1; j<pushes.count; j++)
|
for (j=1; j<pushes.count; j++)
|
||||||
phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]);
|
phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]);
|
||||||
|
|
||||||
phi->is_sequence = ir->is_sequence;
|
phi->is_root = ir->is_root;
|
||||||
*ir = *phi;
|
*ir = *phi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,9 @@ void burm_panic_cannot_match(struct ir* ir)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_reg(struct ir* ir)
|
static void emit_reg(struct ir* ir, int goal)
|
||||||
{
|
{
|
||||||
if (ir->hop)
|
hop_add_reg_insel(current_hop, ir, goal);
|
||||||
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)
|
static void emit_string(const char* data)
|
||||||
|
@ -36,6 +29,14 @@ static void emit_string(const char* data)
|
||||||
hop_add_string_insel(current_hop, data);
|
hop_add_string_insel(current_hop, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emit_fragment(struct ir* ir, int goal)
|
||||||
|
{
|
||||||
|
int insn_no = burm_rule(ir->state_label, goal);
|
||||||
|
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
|
||||||
|
if (insndata->emitter)
|
||||||
|
insndata->emitter(ir, &emitter_data);
|
||||||
|
}
|
||||||
|
|
||||||
static void emit_value(struct ir* ir)
|
static void emit_value(struct ir* ir)
|
||||||
{
|
{
|
||||||
hop_add_value_insel(current_hop, ir);
|
hop_add_value_insel(current_hop, ir);
|
||||||
|
@ -43,7 +44,6 @@ static void emit_value(struct ir* ir)
|
||||||
|
|
||||||
static void emit_resultreg(void)
|
static void emit_resultreg(void)
|
||||||
{
|
{
|
||||||
hop_add_reg_insel(current_hop, current_hop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_eoi(void)
|
static void emit_eoi(void)
|
||||||
|
@ -54,6 +54,7 @@ static void emit_eoi(void)
|
||||||
static const struct burm_emitter_data emitter_data =
|
static const struct burm_emitter_data emitter_data =
|
||||||
{
|
{
|
||||||
&emit_string,
|
&emit_string,
|
||||||
|
&emit_fragment,
|
||||||
&emit_reg,
|
&emit_reg,
|
||||||
&emit_value,
|
&emit_value,
|
||||||
&emit_resultreg,
|
&emit_resultreg,
|
||||||
|
@ -70,11 +71,10 @@ static void walk_instructions(struct ir* ir, int goal)
|
||||||
struct hop* parent_hop = NULL;
|
struct hop* parent_hop = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ir->insn_no = insn_no;
|
|
||||||
if (!insndata->is_fragment)
|
if (!insndata->is_fragment)
|
||||||
{
|
{
|
||||||
parent_hop = current_hop;
|
parent_hop = current_hop;
|
||||||
current_hop = ir->hop = new_hop(insn_no, ir);
|
current_hop = new_hop(insn_no, ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
burm_kids(ir, insn_no, children);
|
burm_kids(ir, insn_no, children);
|
||||||
|
@ -82,10 +82,11 @@ static void walk_instructions(struct ir* ir, int goal)
|
||||||
walk_instructions(children[i], nts[i]);
|
walk_instructions(children[i], nts[i]);
|
||||||
|
|
||||||
ir->is_generated = true;
|
ir->is_generated = true;
|
||||||
|
ir->insn_no = insn_no;
|
||||||
|
|
||||||
tracef('I', "I: $%d %s selected %s %d: %s\n",
|
tracef('I', "I: $%d %s selected %s %d: %s\n",
|
||||||
ir->id,
|
ir->id,
|
||||||
ir->is_sequence ? "S" : " ",
|
ir->is_root ? "S" : " ",
|
||||||
insndata->is_fragment ? "fragment" : "instruction",
|
insndata->is_fragment ? "fragment" : "instruction",
|
||||||
insn_no,
|
insn_no,
|
||||||
insndata->name);
|
insndata->name);
|
||||||
|
@ -96,12 +97,11 @@ static void walk_instructions(struct ir* ir, int goal)
|
||||||
insndata->emitter(ir, &emitter_data);
|
insndata->emitter(ir, &emitter_data);
|
||||||
|
|
||||||
hop_print('I', current_hop);
|
hop_print('I', current_hop);
|
||||||
array_append(¤t_bb->hops, current_hop);
|
array_append(&ir->hops, current_hop);
|
||||||
current_hop = parent_hop;
|
current_hop = parent_hop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void select_instructions(void)
|
static void select_instructions(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -1,27 +1,38 @@
|
||||||
REGISTERS
|
REGISTERS
|
||||||
|
|
||||||
r0 GPR RET0;
|
r0 reg4 int ret0;
|
||||||
r1 GPR RET1;
|
r1 reg4 int ret1;
|
||||||
r2 GPR;
|
r2 reg4 int;
|
||||||
r3 GPR;
|
r3 reg4 int;
|
||||||
r4 GPR;
|
r4 reg4 int;
|
||||||
r5 GPR;
|
r5 reg4 int;
|
||||||
r6 GPR;
|
r6 reg4 int;
|
||||||
r7 GPR;
|
r7 reg4 int;
|
||||||
r8 GPR;
|
r8 reg4 int;
|
||||||
r9 GPR;
|
r9 reg4 int;
|
||||||
r10 GPR;
|
r10 reg4 int;
|
||||||
r11 GPR;
|
r11 reg4 int;
|
||||||
|
|
||||||
cc CC;
|
s0 reg4 float;
|
||||||
|
s1 reg4 float;
|
||||||
|
s2 reg4 float;
|
||||||
|
s3 reg4 float;
|
||||||
|
s4 reg4 float;
|
||||||
|
s5 reg4 float;
|
||||||
|
s6 reg4 float;
|
||||||
|
s7 reg4 float;
|
||||||
|
s8 reg4 float;
|
||||||
|
s9 reg4 float;
|
||||||
|
|
||||||
|
cc conditioncode;
|
||||||
|
|
||||||
DECLARATIONS
|
DECLARATIONS
|
||||||
|
|
||||||
address fragment;
|
address fragment;
|
||||||
aluparam fragment;
|
aluparam fragment;
|
||||||
reg allocates(GPR);
|
reg allocates(reg4);
|
||||||
tristate allocates(CC);
|
tristate allocates(conditioncode);
|
||||||
bistate allocates(CC);
|
bistate allocates(conditioncode);
|
||||||
|
|
||||||
PATTERNS
|
PATTERNS
|
||||||
|
|
||||||
|
@ -158,7 +169,8 @@ PATTERNS
|
||||||
aluparam = value:CONST4
|
aluparam = value:CONST4
|
||||||
emit "#$value";
|
emit "#$value";
|
||||||
|
|
||||||
aluparam = reg;
|
aluparam = value:reg
|
||||||
|
emit "%value";
|
||||||
|
|
||||||
reg = value:aluparam
|
reg = value:aluparam
|
||||||
emit "mov %reg, %value"
|
emit "mov %reg, %value"
|
||||||
|
@ -175,3 +187,10 @@ PATTERNS
|
||||||
reg = value:CONST4
|
reg = value:CONST4
|
||||||
emit "ldr %reg, #$value"
|
emit "ldr %reg, #$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
|
/* FPU operations */
|
||||||
|
|
||||||
|
reg = ADDF4(left:reg, right:reg)
|
||||||
|
emit "fadds %reg, %left, %right"
|
||||||
|
cost 4;
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ static struct ir* appendir(struct ir* ir)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
assert(current_bb != NULL);
|
assert(current_bb != NULL);
|
||||||
ir->is_sequence = true;
|
ir->is_root = true;
|
||||||
array_append(¤t_bb->irs, ir);
|
array_append(¤t_bb->irs, ir);
|
||||||
|
|
||||||
ir_print('0', ir);
|
ir_print('0', ir);
|
||||||
|
@ -479,7 +479,7 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
case op_dup:
|
case op_dup:
|
||||||
{
|
{
|
||||||
struct ir* v = pop(value);
|
struct ir* v = pop(value);
|
||||||
if (!v->is_sequence)
|
if (!v->is_root)
|
||||||
appendir(v);
|
appendir(v);
|
||||||
push(v);
|
push(v);
|
||||||
push(v);
|
push(v);
|
||||||
|
|
|
@ -295,7 +295,7 @@ struct regclass* getregclass(const char* id)
|
||||||
{
|
{
|
||||||
struct regclass* p = lookup(id);
|
struct regclass* p = lookup(id);
|
||||||
if (!p || (p->kind != REGCLASS))
|
if (!p || (p->kind != REGCLASS))
|
||||||
yyerror("'%p' is not the name of a register class");
|
yyerror("'%s' is not the name of a register class", id);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,18 +917,22 @@ static void print_path(uint32_t path)
|
||||||
|
|
||||||
static const uint32_t PATH_MISSING = 0xffffffff;
|
static const uint32_t PATH_MISSING = 0xffffffff;
|
||||||
|
|
||||||
static uint32_t find_label(Tree root, const char* name, uint32_t path)
|
static uint32_t find_label(Tree root, const char* name, uint32_t path, Tree* found)
|
||||||
{
|
{
|
||||||
uint32_t p;
|
uint32_t p;
|
||||||
|
|
||||||
if (root->label && (strcmp(root->label, name) == 0))
|
if (root->label && (strcmp(root->label, name) == 0))
|
||||||
|
{
|
||||||
|
if (found)
|
||||||
|
*found = root;
|
||||||
return path;
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
p = PATH_MISSING;
|
p = PATH_MISSING;
|
||||||
if (root->left && (p == PATH_MISSING))
|
if (root->left && (p == PATH_MISSING))
|
||||||
p = find_label(root->left, name, path*3 + 1);
|
p = find_label(root->left, name, path*3 + 1, found);
|
||||||
if (root->right && (p == PATH_MISSING))
|
if (root->right && (p == PATH_MISSING))
|
||||||
p = find_label(root->right, name, path*3 + 2);
|
p = find_label(root->right, name, path*3 + 2, found);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,15 +967,23 @@ static void emitinsndata(Rule rules)
|
||||||
const char* label = f->data + 1;
|
const char* label = f->data + 1;
|
||||||
|
|
||||||
if (strcmp(label, r->lhs->name) == 0)
|
if (strcmp(label, r->lhs->name) == 0)
|
||||||
print("%1data->emit_resultreg();\n");
|
print("%1data->emit_reg(node, %P%s_NT);\n", label);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t path = find_label(r->pattern, label, 0);
|
Tree node;
|
||||||
print("%1data->emit_reg(");
|
uint32_t path = find_label(r->pattern, label, 0, &node);
|
||||||
|
Nonterm nt = node->op;
|
||||||
|
|
||||||
if (path == PATH_MISSING)
|
if (path == PATH_MISSING)
|
||||||
label_not_found(r, label);
|
label_not_found(r, label);
|
||||||
|
|
||||||
|
if (nt->is_fragment)
|
||||||
|
print("%1data->emit_fragment(");
|
||||||
|
else
|
||||||
|
print("%1data->emit_reg(");
|
||||||
|
|
||||||
print_path(path);
|
print_path(path);
|
||||||
print(");\n");
|
print(", %P%s_NT);\n", ((Nonterm)node->op)->name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -979,7 +991,7 @@ static void emitinsndata(Rule rules)
|
||||||
case '$':
|
case '$':
|
||||||
{
|
{
|
||||||
const char* label = f->data + 1;
|
const char* label = f->data + 1;
|
||||||
uint32_t path = find_label(r->pattern, label, 0);
|
uint32_t path = find_label(r->pattern, label, 0, NULL);
|
||||||
print("%1data->emit_value(");
|
print("%1data->emit_value(");
|
||||||
if (path == PATH_MISSING)
|
if (path == PATH_MISSING)
|
||||||
label_not_found(r, label);
|
label_not_found(r, label);
|
||||||
|
|
|
@ -27,7 +27,8 @@ extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost);
|
||||||
struct burm_emitter_data
|
struct burm_emitter_data
|
||||||
{
|
{
|
||||||
void (*emit_string)(const char* data);
|
void (*emit_string)(const char* data);
|
||||||
void (*emit_reg)(struct ir* ir);
|
void (*emit_fragment)(struct ir* ir, int goal);
|
||||||
|
void (*emit_reg)(struct ir* ir, int goal);
|
||||||
void (*emit_value)(struct ir* ir);
|
void (*emit_value)(struct ir* ir);
|
||||||
void (*emit_resultreg)(void);
|
void (*emit_resultreg)(void);
|
||||||
void (*emit_eoi)(void);
|
void (*emit_eoi)(void);
|
||||||
|
|
Loading…
Reference in a new issue