2016-09-24 20:46:08 +00:00
|
|
|
#include "mcg.h"
|
2016-09-25 21:29:59 +00:00
|
|
|
|
2016-09-26 22:19:45 +00:00
|
|
|
static struct basicblock* current_bb;
|
2016-09-27 21:38:47 +00:00
|
|
|
static struct hop* current_hop;
|
2016-10-01 20:58:29 +00:00
|
|
|
static struct ir* current_ir;
|
2016-09-27 21:38:47 +00:00
|
|
|
|
|
|
|
static const struct burm_emitter_data emitter_data;
|
2016-09-24 20:46:08 +00:00
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
void burm_trace(struct burm_node* p, int ruleno, int cost, int bestcost) {
|
2016-09-25 15:14:54 +00:00
|
|
|
const struct burm_instruction_data* insndata = &burm_instruction_data[ruleno];
|
2016-09-25 21:29:59 +00:00
|
|
|
//tracef('I', "I: 0x%p matched %s with cost %d vs. %d\n", p,
|
|
|
|
// insndata->name, cost, bestcost);
|
2016-09-24 20:46:08 +00:00
|
|
|
}
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
void burm_panic_cannot_match(struct burm_node* node)
|
2016-09-24 20:46:08 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "could not find any patterns to match:\n");
|
2016-10-03 18:52:36 +00:00
|
|
|
ir_print(0, node->ir);
|
2016-09-24 20:46:08 +00:00
|
|
|
fprintf(stderr, "aborting!\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
static void emit_reg(struct burm_node* node, int goal)
|
2016-09-27 21:38:47 +00:00
|
|
|
{
|
2016-10-02 21:25:54 +00:00
|
|
|
struct hop* hop = imap_get(¤t_ir->hops, goal);
|
|
|
|
|
|
|
|
hop_add_vreg_insel(current_hop, hop->output);
|
2016-09-27 21:38:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void emit_string(const char* data)
|
|
|
|
{
|
|
|
|
hop_add_string_insel(current_hop, data);
|
|
|
|
}
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
static void emit_fragment(struct burm_node* node, int goal)
|
2016-09-29 20:06:04 +00:00
|
|
|
{
|
2016-10-03 18:52:36 +00:00
|
|
|
int insn_no = burm_rule(node->state_label, goal);
|
2016-09-29 20:06:04 +00:00
|
|
|
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
|
|
|
|
if (insndata->emitter)
|
2016-10-03 18:52:36 +00:00
|
|
|
insndata->emitter(node, &emitter_data);
|
2016-09-29 20:06:04 +00:00
|
|
|
}
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
static void emit_value(struct burm_node* node)
|
2016-09-27 21:38:47 +00:00
|
|
|
{
|
2016-10-03 18:52:36 +00:00
|
|
|
hop_add_value_insel(current_hop, node->ir);
|
2016-09-27 21:38:47 +00:00
|
|
|
}
|
|
|
|
|
2016-10-02 21:25:54 +00:00
|
|
|
static void emit_eoi(void)
|
2016-09-27 21:38:47 +00:00
|
|
|
{
|
2016-10-02 21:25:54 +00:00
|
|
|
hop_add_eoi_insel(current_hop);
|
2016-09-27 21:38:47 +00:00
|
|
|
}
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
static void emit_constraint_equals(struct burm_node* node, int goal)
|
2016-09-27 21:38:47 +00:00
|
|
|
{
|
2016-10-03 18:52:36 +00:00
|
|
|
#if 0
|
2016-10-02 21:25:54 +00:00
|
|
|
struct hop* hop;
|
|
|
|
|
|
|
|
if (!goal)
|
2016-10-03 18:52:36 +00:00
|
|
|
goal = ir->goal_no;
|
2016-10-02 21:25:54 +00:00
|
|
|
hop = imap_get(¤t_ir->hops, goal);
|
|
|
|
|
|
|
|
current_hop->output = hop->output;
|
2016-10-03 18:52:36 +00:00
|
|
|
#endif
|
2016-09-27 21:38:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct burm_emitter_data emitter_data =
|
|
|
|
{
|
|
|
|
&emit_string,
|
2016-09-29 20:06:04 +00:00
|
|
|
&emit_fragment,
|
2016-09-27 21:38:47 +00:00
|
|
|
&emit_reg,
|
|
|
|
&emit_value,
|
2016-10-02 21:25:54 +00:00
|
|
|
&emit_eoi,
|
|
|
|
&emit_constraint_equals
|
2016-09-27 21:38:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
static void walk_instructions(struct burm_node* node, int goal)
|
2016-09-25 20:17:14 +00:00
|
|
|
{
|
2016-10-03 18:52:36 +00:00
|
|
|
struct burm_node* children[10];
|
|
|
|
int insn_no = burm_rule(node->state_label, goal);
|
2016-09-25 20:17:14 +00:00
|
|
|
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
|
|
|
|
const short* nts = burm_nts[insn_no];
|
2016-09-27 21:38:47 +00:00
|
|
|
struct hop* parent_hop = NULL;
|
2016-10-03 18:52:36 +00:00
|
|
|
struct ir* ir = node->ir;
|
2016-09-25 20:17:14 +00:00
|
|
|
int i;
|
2016-09-26 22:19:45 +00:00
|
|
|
|
|
|
|
if (!insndata->is_fragment)
|
2016-09-25 21:29:59 +00:00
|
|
|
{
|
2016-09-27 21:38:47 +00:00
|
|
|
parent_hop = current_hop;
|
2016-09-29 20:06:04 +00:00
|
|
|
current_hop = new_hop(insn_no, ir);
|
2016-10-02 21:25:54 +00:00
|
|
|
if (goal != 1)
|
|
|
|
{
|
|
|
|
current_hop->output = new_vreg();
|
|
|
|
imap_add(¤t_ir->hops, goal, current_hop);
|
|
|
|
}
|
2016-09-25 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
burm_kids(node, insn_no, children);
|
2016-09-25 20:17:14 +00:00
|
|
|
for (i=0; nts[i]; i++)
|
2016-09-27 21:38:47 +00:00
|
|
|
walk_instructions(children[i], nts[i]);
|
2016-09-24 20:46:08 +00:00
|
|
|
|
2016-10-01 20:58:29 +00:00
|
|
|
tracef('I', "I: $%d goal %d selected %s %d: %s\n",
|
2016-09-25 15:14:54 +00:00
|
|
|
ir->id,
|
2016-10-03 18:52:36 +00:00
|
|
|
goal,
|
2016-09-25 15:14:54 +00:00
|
|
|
insndata->is_fragment ? "fragment" : "instruction",
|
2016-09-25 20:17:14 +00:00
|
|
|
insn_no,
|
2016-09-25 15:14:54 +00:00
|
|
|
insndata->name);
|
2016-09-25 20:17:14 +00:00
|
|
|
|
2016-09-26 22:19:45 +00:00
|
|
|
if (!insndata->is_fragment)
|
|
|
|
{
|
2016-10-02 21:25:54 +00:00
|
|
|
/* This may cause the vregs to be reassigned for this instruction (and
|
|
|
|
* fragments contained within it). */
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
insndata->emitter(node, &emitter_data);
|
2016-09-27 21:38:47 +00:00
|
|
|
|
|
|
|
hop_print('I', current_hop);
|
2016-09-29 20:06:04 +00:00
|
|
|
array_append(&ir->hops, current_hop);
|
2016-09-27 21:38:47 +00:00
|
|
|
current_hop = parent_hop;
|
2016-09-26 22:19:45 +00:00
|
|
|
}
|
2016-09-24 20:46:08 +00:00
|
|
|
}
|
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
static struct burm_node* build_shadow_tree(struct ir* root, struct ir* ir)
|
|
|
|
{
|
|
|
|
struct burm_node* node = calloc(1, sizeof(*node));
|
|
|
|
node->ir = ir;
|
|
|
|
|
|
|
|
if (ir->root == root)
|
|
|
|
{
|
|
|
|
node->label = ir_to_esn(ir->opcode, ir->size);
|
|
|
|
|
|
|
|
if (ir->left)
|
|
|
|
node->left = build_shadow_tree(root, ir->left);
|
|
|
|
|
|
|
|
if (ir->right)
|
|
|
|
node->right = build_shadow_tree(root, ir->right);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
node->label = ir_to_esn(IR_REG, 0);
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2016-09-26 22:19:45 +00:00
|
|
|
static void select_instructions(void)
|
2016-09-24 20:46:08 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2016-09-26 22:19:45 +00:00
|
|
|
tracef('I', "I: BLOCK: %s\n", current_bb->name);
|
2016-09-24 20:46:08 +00:00
|
|
|
|
2016-09-26 22:19:45 +00:00
|
|
|
for (i=0; i<current_bb->irs.count; i++)
|
2016-09-24 20:46:08 +00:00
|
|
|
{
|
2016-10-03 18:52:36 +00:00
|
|
|
struct burm_node* shadow;
|
2016-09-24 20:46:08 +00:00
|
|
|
int insnno;
|
2016-10-03 18:52:36 +00:00
|
|
|
|
2016-10-01 20:58:29 +00:00
|
|
|
current_ir = current_bb->irs.item[i];
|
2016-10-03 18:52:36 +00:00
|
|
|
shadow = build_shadow_tree(current_ir, current_ir);
|
|
|
|
burm_label(shadow);
|
2016-09-24 20:46:08 +00:00
|
|
|
|
2016-10-03 18:52:36 +00:00
|
|
|
insnno = burm_rule(shadow->state_label, 1);
|
2016-09-24 20:46:08 +00:00
|
|
|
if (!insnno)
|
2016-10-03 18:52:36 +00:00
|
|
|
burm_panic_cannot_match(shadow);
|
2016-09-24 20:46:08 +00:00
|
|
|
|
2016-10-01 20:58:29 +00:00
|
|
|
ir_print('I', current_ir);
|
2016-10-03 18:52:36 +00:00
|
|
|
walk_instructions(shadow, 1);
|
2016-09-24 20:46:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void pass_instruction_selector(struct procedure* proc)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2016-09-26 20:48:58 +00:00
|
|
|
for (i=0; i<proc->blocks.count; i++)
|
2016-09-24 20:46:08 +00:00
|
|
|
{
|
2016-09-26 22:19:45 +00:00
|
|
|
current_bb = proc->blocks.item[i];
|
|
|
|
select_instructions();
|
2016-09-24 20:46:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vim: set sw=4 ts=4 expandtab : */
|
|
|
|
|