Rethink the way patterns are mapped to rules; generate emitters (probably
badly).
This commit is contained in:
parent
7c028bdd45
commit
9f78e0b36b
|
@ -14,8 +14,7 @@ PATTERNS
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = POP4
|
reg = POP4
|
||||||
outs out:ANY
|
emit "pop %reg"
|
||||||
emit "pop %out"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
RET
|
RET
|
||||||
|
@ -29,31 +28,26 @@ PATTERNS
|
||||||
/* Memory operations */
|
/* Memory operations */
|
||||||
|
|
||||||
STORE4(addr:address, value:reg)
|
STORE4(addr:address, value:reg)
|
||||||
ins value:GPR
|
|
||||||
emit "str %value, %addr"
|
emit "str %value, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = LOAD4(addr:address)
|
reg = LOAD4(addr:address)
|
||||||
outs dest:ANY
|
emit "ldr %reg, %addr"
|
||||||
emit "ldr %dest, %addr"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = LOAD1(addr:address)
|
reg = LOAD1(addr:address)
|
||||||
outs dest:ANY
|
emit "ldrb %reg, %addr"
|
||||||
emit "ldrb %dest, %addr"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CIU14(LOAD1(addr:address))
|
reg = CIU14(LOAD1(addr:address))
|
||||||
outs dest:ANY
|
emit "ldrb %reg, %addr"
|
||||||
emit "ldrb %dest, %addr"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
||||||
/* Locals */
|
/* Locals */
|
||||||
|
|
||||||
reg = in:LOCAL4
|
reg = in:LOCAL4
|
||||||
outs out:GPR
|
emit "add %reg, fp, #%in"
|
||||||
emit "add %out, fp, #%in"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
address = in:LOCAL4
|
address = in:LOCAL4
|
||||||
|
@ -63,11 +57,9 @@ PATTERNS
|
||||||
/* Memory addressing modes */
|
/* Memory addressing modes */
|
||||||
|
|
||||||
address = ADD4(addr:reg, offset:CONST)
|
address = ADD4(addr:reg, offset:CONST)
|
||||||
ins addr:GPR
|
|
||||||
fragment "[%addr, #%offset]";
|
fragment "[%addr, #%offset]";
|
||||||
|
|
||||||
address = addr:reg
|
address = addr:reg
|
||||||
ins addr:GPR
|
|
||||||
fragment "[%addr]";
|
fragment "[%addr]";
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,43 +77,37 @@ PATTERNS
|
||||||
|
|
||||||
/* Comparisons */
|
/* Comparisons */
|
||||||
|
|
||||||
tristate = COMPARES4(val1:reg, val2:aluparam)
|
tristate = COMPARES4(left:reg, right:aluparam)
|
||||||
outs CC
|
outs CC
|
||||||
emit "cmp %val1, %val2"
|
emit "cmp %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = tristate
|
reg = tristate
|
||||||
emit "mov %out, #0"
|
emit "mov %reg, #0"
|
||||||
emit "movlt %out, #-1"
|
emit "movlt %reg, #-1"
|
||||||
emit "movgt %out, #1"
|
emit "movgt %reg, #1"
|
||||||
cost 12;
|
cost 12;
|
||||||
|
|
||||||
|
|
||||||
/* Conversions */
|
/* Conversions */
|
||||||
|
|
||||||
reg = CII14(CIU41(value:reg))
|
reg = CII14(CIU41(value:reg))
|
||||||
outs out:GPR
|
emit "sxtb %reg, %value"
|
||||||
emit "sxtb %out, %value"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CIU41(in:reg)
|
reg = CIU41(in:reg)
|
||||||
outs out:GPR
|
emit "and %reg, %in, #0xff"
|
||||||
emit "and %out, %in, #0xff"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
||||||
/* ALU operations */
|
/* ALU operations */
|
||||||
|
|
||||||
reg = ADD4(left:reg, right:aluparam)
|
reg = ADD4(left:reg, right:aluparam)
|
||||||
ins left:GPR, right:GPR
|
emit "add %reg, %left, %right"
|
||||||
outs out:GPR
|
|
||||||
emit "add %out, %left, %right"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = ADD4(left:aluparam, right:reg)
|
reg = ADD4(left:aluparam, right:reg)
|
||||||
ins left:GPR, right:GPR
|
emit "add %reg, %right, %left"
|
||||||
outs out:GPR
|
|
||||||
emit "add %out, %right, %left"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
aluparam = value:CONST4
|
aluparam = value:CONST4
|
||||||
|
@ -130,21 +116,17 @@ PATTERNS
|
||||||
aluparam = reg;
|
aluparam = reg;
|
||||||
|
|
||||||
reg = value:aluparam
|
reg = value:aluparam
|
||||||
outs out:GPR
|
emit "mov %reg, %value"
|
||||||
emit "mov %out, %value"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:LABEL4
|
reg = value:LABEL4
|
||||||
outs out:GPR
|
emit "adr %reg, %value"
|
||||||
emit "adr %out, %value"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:BLOCK4
|
reg = value:BLOCK4
|
||||||
outs out:GPR
|
emit "adr %reg, %value"
|
||||||
emit "adr %out, %value"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:CONST4
|
reg = value:CONST4
|
||||||
outs out:GPR
|
emit "ldr %reg, #value"
|
||||||
emit "ldr %out, #value"
|
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
|
@ -58,12 +58,6 @@ definerule("mcgg",
|
||||||
error("you must supply exactly one input file")
|
error("you must supply exactly one input file")
|
||||||
end
|
end
|
||||||
|
|
||||||
local cpptable = cppfile {
|
|
||||||
name = e.name.."/cpptable",
|
|
||||||
outleaf = "cpptable",
|
|
||||||
srcs = e.srcs
|
|
||||||
}
|
|
||||||
|
|
||||||
return normalrule {
|
return normalrule {
|
||||||
name = e.name,
|
name = e.name,
|
||||||
cwd = e.cwd,
|
cwd = e.cwd,
|
||||||
|
@ -72,7 +66,7 @@ definerule("mcgg",
|
||||||
},
|
},
|
||||||
ins = {
|
ins = {
|
||||||
"util/mcgg+mcgg",
|
"util/mcgg+mcgg",
|
||||||
cpptable
|
e.srcs[1]
|
||||||
},
|
},
|
||||||
commands = {
|
commands = {
|
||||||
"%{ins[1]} -i %{ins[2]} -o %{outs}",
|
"%{ins[1]} -i %{ins[2]} -o %{outs}",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -40,6 +41,7 @@ static void emitnts(Rule rules, int nrules);
|
||||||
static void emitrecord(char* pre, Rule r, int cost);
|
static void emitrecord(char* pre, Rule r, int cost);
|
||||||
static void emitrule(Nonterm nts);
|
static void emitrule(Nonterm nts);
|
||||||
static void emitpredicatedefinitions(Rule rules);
|
static void emitpredicatedefinitions(Rule rules);
|
||||||
|
static void emitemitters(Rule rules);
|
||||||
static void emitstate(Term terms, Nonterm start, int ntnumber);
|
static void emitstate(Term terms, Nonterm start, int ntnumber);
|
||||||
static void emitstring(Rule rules);
|
static void emitstring(Rule rules);
|
||||||
static void emitstruct(Nonterm nts, int ntnumber);
|
static void emitstruct(Nonterm nts, int ntnumber);
|
||||||
|
@ -133,6 +135,7 @@ int main(int argc, char* argv[])
|
||||||
emitrule(nts);
|
emitrule(nts);
|
||||||
emitclosure(nts);
|
emitclosure(nts);
|
||||||
emitpredicatedefinitions(rules);
|
emitpredicatedefinitions(rules);
|
||||||
|
emitemitters(rules);
|
||||||
if (start)
|
if (start)
|
||||||
emitstate(terms, start, ntnumber);
|
emitstate(terms, start, ntnumber);
|
||||||
print("#ifdef STATE_LABEL\n");
|
print("#ifdef STATE_LABEL\n");
|
||||||
|
@ -334,6 +337,7 @@ Rule rule(char* id, Tree pattern, int ern)
|
||||||
Term p = pattern->op;
|
Term p = pattern->op;
|
||||||
|
|
||||||
nrules++;
|
nrules++;
|
||||||
|
r->lineno = yylineno;
|
||||||
r->lhs = nonterm(id);
|
r->lhs = nonterm(id);
|
||||||
r->packed = ++r->lhs->lhscount;
|
r->packed = ++r->lhs->lhscount;
|
||||||
for (q = &r->lhs->rules; *q; q = &(*q)->decode)
|
for (q = &r->lhs->rules; *q; q = &(*q)->decode)
|
||||||
|
@ -791,6 +795,7 @@ static void emitpredicatedefinitions(Rule r)
|
||||||
Stringlist s = r->when;
|
Stringlist s = r->when;
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
|
print("/* %R */\n", r);
|
||||||
print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern);
|
print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern);
|
||||||
while (s)
|
while (s)
|
||||||
{
|
{
|
||||||
|
@ -803,6 +808,115 @@ static void emitpredicatedefinitions(Rule r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emittreefetchers(uint32_t path, Tree tree)
|
||||||
|
{
|
||||||
|
if (tree->label)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
uint32_t p = path;
|
||||||
|
print("%1NODEPTR_TYPE node_%s = ", tree->label);
|
||||||
|
while (p > 0)
|
||||||
|
{
|
||||||
|
switch (p % 3)
|
||||||
|
{
|
||||||
|
case 1: print("LEFT_CHILD("); break;
|
||||||
|
case 2: print("RIGHT_CHILD("); break;
|
||||||
|
}
|
||||||
|
p /= 3;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("node");
|
||||||
|
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
print(")");
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
print(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tree->left)
|
||||||
|
emittreefetchers(path*3 + 1, tree->left);
|
||||||
|
if (tree->right)
|
||||||
|
emittreefetchers(path*3 + 2, tree->right);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Tree find_label(Tree root, const char* name)
|
||||||
|
{
|
||||||
|
Tree t;
|
||||||
|
|
||||||
|
if (root->label && (strcmp(root->label, name) == 0))
|
||||||
|
return root;
|
||||||
|
|
||||||
|
t = NULL;
|
||||||
|
if (root->left && !t)
|
||||||
|
t = find_label(root->left, name);
|
||||||
|
if (root->right && !t)
|
||||||
|
t = find_label(root->right, name);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* emitemitters - emit the code generation routines */
|
||||||
|
static void emitemitters(Rule rules)
|
||||||
|
{
|
||||||
|
Rule r;
|
||||||
|
|
||||||
|
r = rules;
|
||||||
|
while (r)
|
||||||
|
{
|
||||||
|
Stringlist s = r->code;
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
print("/* %R */\n", r);
|
||||||
|
print("static void %Pemitter_%d(NODEPTR_TYPE node, struct %Pemitter_data* data) {\n", r->ern);
|
||||||
|
emittreefetchers(0, r->pattern);
|
||||||
|
print("%1NODEPTR_TYPE node_%s = node;\n", r->lhs->name);
|
||||||
|
|
||||||
|
while (s)
|
||||||
|
{
|
||||||
|
if (s->payload[0] == '%')
|
||||||
|
{
|
||||||
|
const char* label = s->payload + 1;
|
||||||
|
Tree t = find_label(r->pattern, label);
|
||||||
|
if (!t && (strcmp(label, r->lhs->name) != 0))
|
||||||
|
{
|
||||||
|
yylineno = r->lineno;
|
||||||
|
yyerror("label '%s' not found", label);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
print("%1data->emit_ir(node_%s);\n", label);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
print("%1data->emit_string(\"%s\");\n", s->payload);
|
||||||
|
|
||||||
|
s = s->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("}\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r->link;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = rules;
|
||||||
|
print("%Pemitter_t* const %Pemitters[] = {\n");
|
||||||
|
while (r)
|
||||||
|
{
|
||||||
|
Stringlist s = r->code;
|
||||||
|
print("%1");
|
||||||
|
if (s)
|
||||||
|
print("&%Pemitter_%d,", r->ern);
|
||||||
|
else
|
||||||
|
print("NULL,");
|
||||||
|
print(" /* %R */\n", r);
|
||||||
|
|
||||||
|
r = r->link;
|
||||||
|
}
|
||||||
|
print("};\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* emitcost - emit a cost calculation via a predicate */
|
/* emitcost - emit a cost calculation via a predicate */
|
||||||
static void emitcostcalc(Rule r)
|
static void emitcostcalc(Rule r)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,6 +58,7 @@ struct rule
|
||||||
{ /* rules: */
|
{ /* rules: */
|
||||||
Nonterm lhs; /* lefthand side non-terminal */
|
Nonterm lhs; /* lefthand side non-terminal */
|
||||||
Tree pattern; /* rule pattern */
|
Tree pattern; /* rule pattern */
|
||||||
|
int lineno; /* line number where allocated */
|
||||||
int ern; /* external rule number */
|
int ern; /* external rule number */
|
||||||
int packed; /* packed external rule number */
|
int packed; /* packed external rule number */
|
||||||
int cost; /* associated cost */
|
int cost; /* associated cost */
|
||||||
|
|
|
@ -25,6 +25,16 @@ extern const short *burm_nts[];
|
||||||
extern struct ir** burm_kids(struct ir* p, int eruleno, struct ir* kids[]);
|
extern struct ir** burm_kids(struct ir* p, int eruleno, struct ir* kids[]);
|
||||||
extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost);
|
extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost);
|
||||||
|
|
||||||
|
struct burm_emitter_data
|
||||||
|
{
|
||||||
|
void* user;
|
||||||
|
void (*emit_string)(const char* data);
|
||||||
|
void (*emit_ir)(struct ir* ir);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void burm_emitter_t(struct ir* ir, struct burm_emitter_data* data);
|
||||||
|
extern burm_emitter_t* const burm_emitters[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
|
@ -14,7 +14,7 @@ static int braces = 0;
|
||||||
|
|
||||||
%x CSTRING
|
%x CSTRING
|
||||||
%x QSTRING
|
%x QSTRING
|
||||||
%x ECHO
|
%x COMMENT
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ static int braces = 0;
|
||||||
<INITIAL>"\"" BEGIN(QSTRING);
|
<INITIAL>"\"" BEGIN(QSTRING);
|
||||||
<QSTRING>"\"" BEGIN(INITIAL);
|
<QSTRING>"\"" BEGIN(INITIAL);
|
||||||
|
|
||||||
<QSTRING>%[a-zA-Z_]+ {
|
<QSTRING>%[a-zA-Z_][a-zA_Z_0-9]+ {
|
||||||
yylval.string = strdup(yytext);
|
yylval.string = strdup(yytext);
|
||||||
return QFRAGMENT;
|
return QFRAGMENT;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,11 @@ static int braces = 0;
|
||||||
return QFRAGMENT;
|
return QFRAGMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<INITIAL>"/*" BEGIN(COMMENT);
|
||||||
|
<COMMENT>"*/" BEGIN(INITIAL);
|
||||||
|
<COMMENT>[^*]* ;
|
||||||
|
<COMMENT>"*" ;
|
||||||
|
|
||||||
"%%" return PPERCENT;
|
"%%" return PPERCENT;
|
||||||
"%term" return TERMINAL;
|
"%term" return TERMINAL;
|
||||||
"%start" return START;
|
"%start" return START;
|
||||||
|
@ -72,6 +77,8 @@ static int braces = 0;
|
||||||
"fragment" return FRAGMENT;
|
"fragment" return FRAGMENT;
|
||||||
"cost" return COST;
|
"cost" return COST;
|
||||||
|
|
||||||
|
"//"[^\n]*\n ;
|
||||||
|
|
||||||
[A-Za-z_][A-Za-z0-9_]* { yylval.string = strdup(yytext); return ID; }
|
[A-Za-z_][A-Za-z0-9_]* { yylval.string = strdup(yytext); return ID; }
|
||||||
[0-9]+ { yylval.n = atoi(yytext); return INT; }
|
[0-9]+ { yylval.n = atoi(yytext); return INT; }
|
||||||
[ \t\r\n]* ;
|
[ \t\r\n]* ;
|
||||||
|
|
Loading…
Reference in a new issue