Massive rewrite of how emitters and the instruction selector works, after I
realised that the existing approach wasn't working. Now, hopefully, tracks the instruction trees generated during selection properly.
This commit is contained in:
parent
68f98cbad7
commit
bd28bddb92
|
@ -20,6 +20,7 @@ struct ir
|
||||||
ARRAYOF(struct ir) phivalue;
|
ARRAYOF(struct ir) phivalue;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
|
struct vreg* result; /* vreg containing IR result */
|
||||||
IMAPOF(struct hop) hops; /* only for root IRs; by goal */
|
IMAPOF(struct hop) hops; /* only for root IRs; by goal */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,22 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
|
|
||||||
|
#define MAX_CHILDREN 10
|
||||||
|
|
||||||
|
struct insn
|
||||||
|
{
|
||||||
|
struct ir* ir;
|
||||||
|
struct hop* hop;
|
||||||
|
const struct burm_instruction_data* insndata;
|
||||||
|
int num_children;
|
||||||
|
struct insn* children[MAX_CHILDREN];
|
||||||
|
};
|
||||||
|
|
||||||
static struct basicblock* current_bb;
|
static struct basicblock* current_bb;
|
||||||
static struct hop* current_hop;
|
static struct hop* current_hop;
|
||||||
static struct ir* current_ir;
|
static struct ir* current_ir;
|
||||||
|
static struct insn* current_insn;
|
||||||
|
|
||||||
static const struct burm_emitter_data emitter_data;
|
static void emit(struct insn* insn);
|
||||||
|
|
||||||
void burm_trace(struct burm_node* p, int ruleno, int cost, int bestcost) {
|
void burm_trace(struct burm_node* 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];
|
||||||
|
@ -20,11 +32,23 @@ void burm_panic_cannot_match(struct burm_node* node)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_reg(struct burm_node* node, int goal)
|
static void emit_return_reg(void)
|
||||||
{
|
{
|
||||||
struct hop* hop = imap_get(¤t_ir->hops, goal);
|
hop_add_vreg_insel(current_hop, current_hop->output);
|
||||||
|
}
|
||||||
|
|
||||||
hop_add_vreg_insel(current_hop, hop->output);
|
static void emit_reg(int child)
|
||||||
|
{
|
||||||
|
struct insn* insn = current_insn->children[child];
|
||||||
|
struct vreg* vreg;
|
||||||
|
|
||||||
|
if (insn->hop)
|
||||||
|
vreg = insn->hop->output;
|
||||||
|
else
|
||||||
|
vreg = insn->ir->result;
|
||||||
|
|
||||||
|
if (vreg)
|
||||||
|
hop_add_vreg_insel(current_hop, vreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_string(const char* data)
|
static void emit_string(const char* data)
|
||||||
|
@ -32,17 +56,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 burm_node* node, int goal)
|
static void emit_fragment(int child)
|
||||||
{
|
{
|
||||||
int insn_no = burm_rule(node->state_label, goal);
|
emit(current_insn->children[child]);
|
||||||
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
|
|
||||||
if (insndata->emitter)
|
|
||||||
insndata->emitter(node, &emitter_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_value(struct burm_node* node)
|
static void emit_value(int child)
|
||||||
{
|
{
|
||||||
hop_add_value_insel(current_hop, node->ir);
|
hop_add_value_insel(current_hop, current_insn->children[child]->ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_eoi(void)
|
static void emit_eoi(void)
|
||||||
|
@ -50,73 +71,75 @@ static void emit_eoi(void)
|
||||||
hop_add_eoi_insel(current_hop);
|
hop_add_eoi_insel(current_hop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_constraint_equals(struct burm_node* node, int goal)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
struct hop* hop;
|
|
||||||
|
|
||||||
if (!goal)
|
|
||||||
goal = ir->goal_no;
|
|
||||||
hop = imap_get(¤t_ir->hops, goal);
|
|
||||||
|
|
||||||
current_hop->output = hop->output;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct burm_emitter_data emitter_data =
|
static const struct burm_emitter_data emitter_data =
|
||||||
{
|
{
|
||||||
&emit_string,
|
&emit_string,
|
||||||
&emit_fragment,
|
&emit_fragment,
|
||||||
|
&emit_return_reg,
|
||||||
&emit_reg,
|
&emit_reg,
|
||||||
&emit_value,
|
&emit_value,
|
||||||
&emit_eoi,
|
&emit_eoi,
|
||||||
&emit_constraint_equals
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void emit(struct insn* insn)
|
||||||
static void walk_instructions(struct burm_node* node, int goal)
|
|
||||||
{
|
{
|
||||||
struct burm_node* children[10];
|
struct insn* old = current_insn;
|
||||||
int insn_no = burm_rule(node->state_label, goal);
|
current_insn = insn;
|
||||||
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
|
|
||||||
const short* nts = burm_nts[insn_no];
|
insn->insndata->emitter(&emitter_data);
|
||||||
struct hop* parent_hop = NULL;
|
|
||||||
struct ir* ir = node->ir;
|
current_insn = old;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct insn* walk_instructions(struct burm_node* node, int goal)
|
||||||
|
{
|
||||||
|
struct insn* insn = calloc(1, sizeof(*insn));
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!insndata->is_fragment)
|
insn->ir = node->ir;
|
||||||
|
insn->num_children = 0;
|
||||||
|
|
||||||
|
if (goal)
|
||||||
{
|
{
|
||||||
parent_hop = current_hop;
|
int insn_no = burm_rule(node->state_label, goal);
|
||||||
current_hop = new_hop(insn_no, ir);
|
const short* nts = burm_nts[insn_no];
|
||||||
if (goal != 1)
|
struct burm_node* children[MAX_CHILDREN] = {0};
|
||||||
{
|
|
||||||
current_hop->output = new_vreg();
|
insn->insndata = &burm_instruction_data[insn_no];
|
||||||
imap_add(¤t_ir->hops, goal, current_hop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
burm_kids(node, insn_no, children);
|
burm_kids(node, insn_no, children);
|
||||||
for (i=0; nts[i]; i++)
|
|
||||||
walk_instructions(children[i], nts[i]);
|
|
||||||
|
|
||||||
tracef('I', "I: $%d goal %d selected %s %d: %s\n",
|
i = 0;
|
||||||
ir->id,
|
for (;;)
|
||||||
goal,
|
|
||||||
insndata->is_fragment ? "fragment" : "instruction",
|
|
||||||
insn_no,
|
|
||||||
insndata->name);
|
|
||||||
|
|
||||||
if (!insndata->is_fragment)
|
|
||||||
{
|
{
|
||||||
/* This may cause the vregs to be reassigned for this instruction (and
|
if (!children[i])
|
||||||
* fragments contained within it). */
|
break;
|
||||||
|
|
||||||
insndata->emitter(node, &emitter_data);
|
insn->children[i] = walk_instructions(children[i], nts[i]);
|
||||||
|
insn->num_children++;
|
||||||
hop_print('I', current_hop);
|
i++;
|
||||||
array_append(&ir->hops, current_hop);
|
|
||||||
current_hop = parent_hop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tracef('I', "I: $%d goal %d %s selected %d: %s\n",
|
||||||
|
node->ir->id,
|
||||||
|
goal,
|
||||||
|
insn->insndata->is_fragment ? "fragment" : "instruction",
|
||||||
|
insn_no,
|
||||||
|
insn->insndata->name);
|
||||||
|
|
||||||
|
if (!insn->insndata->is_fragment)
|
||||||
|
{
|
||||||
|
insn->hop = current_hop = new_hop(0, insn->ir);
|
||||||
|
insn->hop->output = new_vreg();
|
||||||
|
emit(insn);
|
||||||
|
hop_print('I', current_hop);
|
||||||
|
|
||||||
|
if (goal != 1)
|
||||||
|
insn->ir->result = insn->hop->output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct burm_node* build_shadow_tree(struct ir* root, struct ir* ir)
|
static struct burm_node* build_shadow_tree(struct ir* root, struct ir* ir)
|
||||||
|
|
|
@ -52,6 +52,7 @@ PATTERNS
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = POP4
|
reg = POP4
|
||||||
|
with int reg
|
||||||
emit "pop %reg"
|
emit "pop %reg"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
@ -68,12 +69,11 @@ PATTERNS
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = in:REG
|
reg = in:REG
|
||||||
with (reg == in)
|
emit "mov %reg, %in"
|
||||||
emit "reg %reg"
|
|
||||||
cost 1;
|
cost 1;
|
||||||
|
|
||||||
reg = NOP(in:reg)
|
reg = NOP(in:reg)
|
||||||
with (reg == in)
|
emit "mov %reg, %in"
|
||||||
cost 1;
|
cost 1;
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,18 +90,22 @@ PATTERNS
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = LOAD4(addr:address)
|
reg = LOAD4(addr:address)
|
||||||
|
with int reg
|
||||||
emit "ldr %reg, %addr"
|
emit "ldr %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = LOAD1(addr:address)
|
reg = LOAD1(addr:address)
|
||||||
|
with int reg
|
||||||
emit "ldrb %reg, %addr"
|
emit "ldrb %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CIU14(LOAD1(addr:address))
|
reg = CIU14(LOAD1(addr:address))
|
||||||
|
with int reg
|
||||||
emit "ldrb %reg, %addr"
|
emit "ldrb %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CII14(CIU41(CIU14(LOAD1(addr:address))))
|
reg = CII14(CIU41(CIU14(LOAD1(addr:address))))
|
||||||
|
with int reg
|
||||||
emit "ldrsb %reg, %addr"
|
emit "ldrsb %reg, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
@ -109,6 +113,7 @@ PATTERNS
|
||||||
/* Locals */
|
/* Locals */
|
||||||
|
|
||||||
reg = in:LOCAL4
|
reg = in:LOCAL4
|
||||||
|
with int reg
|
||||||
emit "add %reg, fp, #$in"
|
emit "add %reg, fp, #$in"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
@ -161,14 +166,17 @@ PATTERNS
|
||||||
/* Comparisons */
|
/* Comparisons */
|
||||||
|
|
||||||
cc = COMPARES4(left:reg, right:aluparam)
|
cc = COMPARES4(left:reg, right:aluparam)
|
||||||
|
with cc cc
|
||||||
emit "cmp %left, %right"
|
emit "cmp %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
cc = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4)
|
cc = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4)
|
||||||
|
with cc cc
|
||||||
emit "cmp %left, %right"
|
emit "cmp %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = cc
|
reg = cc
|
||||||
|
with int reg
|
||||||
emit "mov %reg, #0"
|
emit "mov %reg, #0"
|
||||||
emit "movlt %reg, #-1"
|
emit "movlt %reg, #-1"
|
||||||
emit "movgt %reg, #1"
|
emit "movgt %reg, #1"
|
||||||
|
@ -178,10 +186,12 @@ PATTERNS
|
||||||
/* Conversions */
|
/* Conversions */
|
||||||
|
|
||||||
reg = CII14(CIU41(value:reg))
|
reg = CII14(CIU41(value:reg))
|
||||||
|
with int reg
|
||||||
emit "sxtb %reg, %value"
|
emit "sxtb %reg, %value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CIU41(in:reg)
|
reg = CIU41(in:reg)
|
||||||
|
with int reg
|
||||||
emit "and %reg, %in, #0xff"
|
emit "and %reg, %in, #0xff"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
@ -189,19 +199,23 @@ PATTERNS
|
||||||
/* ALU operations */
|
/* ALU operations */
|
||||||
|
|
||||||
reg = ADD4(left:reg, right:aluparam)
|
reg = ADD4(left:reg, right:aluparam)
|
||||||
|
with int reg
|
||||||
emit "add %reg, %left, %right"
|
emit "add %reg, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = ADD4(left:aluparam, right:reg)
|
reg = ADD4(left:aluparam, right:reg)
|
||||||
|
with int reg
|
||||||
emit "add %reg, %right, %left"
|
emit "add %reg, %right, %left"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = MOD4(left:reg, right:reg)
|
reg = MOD4(left:reg, right:reg)
|
||||||
|
with int reg
|
||||||
emit "udiv %reg, %left, %right"
|
emit "udiv %reg, %left, %right"
|
||||||
emit "mls %reg, %reg, %right, %left"
|
emit "mls %reg, %reg, %right, %left"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
reg = DIV4(left:reg, right:aluparam)
|
reg = DIV4(left:reg, right:aluparam)
|
||||||
|
with int reg
|
||||||
emit "div %reg, %left, %right"
|
emit "div %reg, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
@ -212,28 +226,34 @@ PATTERNS
|
||||||
emit "%value";
|
emit "%value";
|
||||||
|
|
||||||
reg = value:aluparam
|
reg = value:aluparam
|
||||||
|
with int reg
|
||||||
emit "mov %reg, %value"
|
emit "mov %reg, %value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:LABEL4
|
reg = value:LABEL4
|
||||||
|
with int reg
|
||||||
emit "adr %reg, $value"
|
emit "adr %reg, $value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:BLOCK4
|
reg = value:BLOCK4
|
||||||
|
with int reg
|
||||||
emit "adr %reg, $value"
|
emit "adr %reg, $value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:CONST4
|
reg = value:CONST4
|
||||||
|
with int reg
|
||||||
emit "ldr %reg, address-containing-$value"
|
emit "ldr %reg, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
reg = value:CONSTF4
|
reg = value:CONSTF4
|
||||||
|
with int reg
|
||||||
emit "vldr %reg, address-containing-$value"
|
emit "vldr %reg, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
/* FPU operations */
|
/* FPU operations */
|
||||||
|
|
||||||
reg = ADDF4(left:reg, right:reg)
|
reg = ADDF4(left:reg, right:reg)
|
||||||
|
with int reg
|
||||||
emit "fadds %reg, %left, %right"
|
emit "fadds %reg, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ static int nextern = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
%term ALLOCATES
|
%term ALLOCATES
|
||||||
|
%term COPY
|
||||||
%term COST
|
%term COST
|
||||||
%term DECLARATIONS
|
%term DECLARATIONS
|
||||||
%term EMIT
|
%term EMIT
|
||||||
|
|
|
@ -679,20 +679,22 @@ static void emitheader(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* computekids - compute paths to kids in tree t */
|
/* computekids - compute paths to kids in tree t */
|
||||||
static char* computekids(Tree t, const char* v, char* bp, int* ip)
|
static char* computekids(Tree node, const char* v, char* bp, int* ip)
|
||||||
{
|
{
|
||||||
Term p = t->op;
|
Term t = node->op;
|
||||||
|
|
||||||
if (p->kind == NONTERM)
|
if (!node->left && !node->right)
|
||||||
{
|
{
|
||||||
sprintf(bp, "\t\tkids[%d] = %s;\n", (*ip)++, v);
|
sprintf(bp, "\t\tkids[%d] = %s;\n", (*ip)++, v);
|
||||||
bp += strlen(bp);
|
bp += strlen(bp);
|
||||||
}
|
}
|
||||||
else if (p->arity > 0)
|
|
||||||
|
if (t->kind == TERM)
|
||||||
{
|
{
|
||||||
bp = computekids(t->left, aprintf("LEFT_CHILD(%s)", v), bp, ip);
|
if (t->arity >= 1)
|
||||||
if (p->arity == 2)
|
bp = computekids(node->left, aprintf("LEFT_CHILD(%s)", v), bp, ip);
|
||||||
bp = computekids(t->right, aprintf("RIGHT_CHILD(%s)", v), bp, ip);
|
if (t->arity == 2)
|
||||||
|
bp = computekids(node->right, aprintf("RIGHT_CHILD(%s)", v), bp, ip);
|
||||||
}
|
}
|
||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
@ -910,6 +912,27 @@ static void label_not_found(Rule rule, const char* label)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool find_child_index(Tree node, const char* name, int* index, Tree* found)
|
||||||
|
{
|
||||||
|
/* This must return the same ordering as the burm_kids() function uses. */
|
||||||
|
|
||||||
|
if (node->label && strcmp(node->label, name) == 0)
|
||||||
|
{
|
||||||
|
if (found)
|
||||||
|
*found = node;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node->left && !node->right)
|
||||||
|
(*index)++;
|
||||||
|
|
||||||
|
if (node->left && find_child_index(node->left, name, index, found))
|
||||||
|
return true;
|
||||||
|
if (node->right && find_child_index(node->right, name, index, found))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* emitpredicates - emit predicates for rules */
|
/* emitpredicates - emit predicates for rules */
|
||||||
static void emitpredicatedefinitions(Rule r)
|
static void emitpredicatedefinitions(Rule r)
|
||||||
{
|
{
|
||||||
|
@ -954,49 +977,6 @@ static void emitpredicatedefinitions(Rule r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void invalid_equals_constraint(Rule rule)
|
|
||||||
{
|
|
||||||
yylineno = rule->lineno;
|
|
||||||
yyerror("left hand side of an equality constraint must be the output register");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_ir_expr(Rule rule, const char* label)
|
|
||||||
{
|
|
||||||
if (strcmp(label, rule->lhs->name) == 0)
|
|
||||||
print("node, %P%s_NT", label);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Tree node;
|
|
||||||
uint32_t path = find_label(rule->pattern, label, 0, &node);
|
|
||||||
Nonterm nt = node->op;
|
|
||||||
|
|
||||||
if (path == PATH_MISSING)
|
|
||||||
label_not_found(rule, label);
|
|
||||||
|
|
||||||
print_path(path);
|
|
||||||
if (nt->kind == NONTERM)
|
|
||||||
print(", %P%s_NT", ((Nonterm)node->op)->name);
|
|
||||||
else
|
|
||||||
print(", 0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_constraint(Rule rule, struct constraint* c)
|
|
||||||
{
|
|
||||||
switch (c->type)
|
|
||||||
{
|
|
||||||
case CONSTRAINT_EQUALS:
|
|
||||||
if (strcmp(c->left, rule->lhs->name) != 0)
|
|
||||||
invalid_equals_constraint(rule);
|
|
||||||
|
|
||||||
print("%1data->emit_constraint_equals(");
|
|
||||||
emit_ir_expr(rule, c->right);
|
|
||||||
print(");\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* emitinsndata - emit the code generation data */
|
/* emitinsndata - emit the code generation data */
|
||||||
static void emitinsndata(Rule rules)
|
static void emitinsndata(Rule rules)
|
||||||
{
|
{
|
||||||
|
@ -1007,6 +987,7 @@ static void emitinsndata(Rule rules)
|
||||||
while (r)
|
while (r)
|
||||||
{
|
{
|
||||||
struct stringfragment* f = r->code.first;
|
struct stringfragment* f = r->code.first;
|
||||||
|
yylineno = r->lineno;
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
|
@ -1019,20 +1000,7 @@ static void emitinsndata(Rule rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
print("/* %R */\n", r);
|
print("/* %R */\n", r);
|
||||||
print("static void %Pemitter_%d(NODEPTR_TYPE node, const struct %Pemitter_data* data) {\n", r->ern);
|
print("static void %Pemitter_%d(const struct %Pemitter_data* data) {\n", r->ern);
|
||||||
|
|
||||||
/* Constraints come first, because they may cause vreg reassignment, which
|
|
||||||
* we want to happen before the instruction emission. */
|
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<r->constraints.count; i++)
|
|
||||||
{
|
|
||||||
struct constraint* c = r->constraints.item[i];
|
|
||||||
emit_constraint(r, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (f)
|
while (f)
|
||||||
{
|
{
|
||||||
|
@ -1043,23 +1011,26 @@ 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_reg(node, %P%s_NT);\n", label);
|
print("%1data->emit_return_reg();\n", label);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Tree node;
|
Tree node;
|
||||||
uint32_t path = find_label(r->pattern, label, 0, &node);
|
int index = 0;
|
||||||
|
if (!find_child_index(r->pattern, label, &index, &node))
|
||||||
|
label_not_found(r, label);
|
||||||
Nonterm nt = node->op;
|
Nonterm nt = node->op;
|
||||||
|
|
||||||
if (path == PATH_MISSING)
|
if (nt->kind == NONTERM)
|
||||||
label_not_found(r, label);
|
{
|
||||||
|
|
||||||
if (nt->is_fragment)
|
if (nt->is_fragment)
|
||||||
print("%1data->emit_fragment(");
|
print("%1data->emit_fragment(");
|
||||||
else
|
else
|
||||||
print("%1data->emit_reg(");
|
print("%1data->emit_reg(");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
print("%1data->emit_reg(");
|
||||||
|
|
||||||
print_path(path);
|
print("%d);\n", index);
|
||||||
print(", %P%s_NT);\n", ((Nonterm)node->op)->name);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1067,12 +1038,11 @@ 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, NULL);
|
int index = 0;
|
||||||
print("%1data->emit_value(");
|
if (!find_child_index(r->pattern, label, &index, NULL))
|
||||||
if (path == PATH_MISSING)
|
|
||||||
label_not_found(r, label);
|
label_not_found(r, label);
|
||||||
print_path(path);
|
|
||||||
print(");\n");
|
print("%1data->emit_value(%d);\n", index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,14 +39,14 @@ extern void burm_trace(NODEPTR_TYPE 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_fragment)(NODEPTR_TYPE node, int goal);
|
void (*emit_fragment)(int child);
|
||||||
void (*emit_reg)(NODEPTR_TYPE node, int goal);
|
void (*emit_return_reg)(void);
|
||||||
void (*emit_value)(NODEPTR_TYPE node);
|
void (*emit_reg)(int child);
|
||||||
|
void (*emit_value)(int child);
|
||||||
void (*emit_eoi)(void);
|
void (*emit_eoi)(void);
|
||||||
void (*emit_constraint_equals)(NODEPTR_TYPE node, int goal);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void burm_emitter_t(NODEPTR_TYPE node, const struct burm_emitter_data* data);
|
typedef void burm_emitter_t(const struct burm_emitter_data* data);
|
||||||
|
|
||||||
struct burm_instruction_data
|
struct burm_instruction_data
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue