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;
|
||||
|
||||
reg = POP4
|
||||
outs out:ANY
|
||||
emit "pop %out"
|
||||
emit "pop %reg"
|
||||
cost 4;
|
||||
|
||||
RET
|
||||
|
@ -29,31 +28,26 @@ PATTERNS
|
|||
/* Memory operations */
|
||||
|
||||
STORE4(addr:address, value:reg)
|
||||
ins value:GPR
|
||||
emit "str %value, %addr"
|
||||
cost 4;
|
||||
|
||||
reg = LOAD4(addr:address)
|
||||
outs dest:ANY
|
||||
emit "ldr %dest, %addr"
|
||||
emit "ldr %reg, %addr"
|
||||
cost 4;
|
||||
|
||||
reg = LOAD1(addr:address)
|
||||
outs dest:ANY
|
||||
emit "ldrb %dest, %addr"
|
||||
emit "ldrb %reg, %addr"
|
||||
cost 4;
|
||||
|
||||
reg = CIU14(LOAD1(addr:address))
|
||||
outs dest:ANY
|
||||
emit "ldrb %dest, %addr"
|
||||
emit "ldrb %reg, %addr"
|
||||
cost 4;
|
||||
|
||||
|
||||
/* Locals */
|
||||
|
||||
reg = in:LOCAL4
|
||||
outs out:GPR
|
||||
emit "add %out, fp, #%in"
|
||||
emit "add %reg, fp, #%in"
|
||||
cost 4;
|
||||
|
||||
address = in:LOCAL4
|
||||
|
@ -63,11 +57,9 @@ PATTERNS
|
|||
/* Memory addressing modes */
|
||||
|
||||
address = ADD4(addr:reg, offset:CONST)
|
||||
ins addr:GPR
|
||||
fragment "[%addr, #%offset]";
|
||||
|
||||
address = addr:reg
|
||||
ins addr:GPR
|
||||
fragment "[%addr]";
|
||||
|
||||
|
||||
|
@ -85,43 +77,37 @@ PATTERNS
|
|||
|
||||
/* Comparisons */
|
||||
|
||||
tristate = COMPARES4(val1:reg, val2:aluparam)
|
||||
tristate = COMPARES4(left:reg, right:aluparam)
|
||||
outs CC
|
||||
emit "cmp %val1, %val2"
|
||||
emit "cmp %left, %right"
|
||||
cost 4;
|
||||
|
||||
reg = tristate
|
||||
emit "mov %out, #0"
|
||||
emit "movlt %out, #-1"
|
||||
emit "movgt %out, #1"
|
||||
emit "mov %reg, #0"
|
||||
emit "movlt %reg, #-1"
|
||||
emit "movgt %reg, #1"
|
||||
cost 12;
|
||||
|
||||
|
||||
/* Conversions */
|
||||
|
||||
reg = CII14(CIU41(value:reg))
|
||||
outs out:GPR
|
||||
emit "sxtb %out, %value"
|
||||
emit "sxtb %reg, %value"
|
||||
cost 4;
|
||||
|
||||
reg = CIU41(in:reg)
|
||||
outs out:GPR
|
||||
emit "and %out, %in, #0xff"
|
||||
emit "and %reg, %in, #0xff"
|
||||
cost 4;
|
||||
|
||||
|
||||
/* ALU operations */
|
||||
|
||||
reg = ADD4(left:reg, right:aluparam)
|
||||
ins left:GPR, right:GPR
|
||||
outs out:GPR
|
||||
emit "add %out, %left, %right"
|
||||
emit "add %reg, %left, %right"
|
||||
cost 4;
|
||||
|
||||
reg = ADD4(left:aluparam, right:reg)
|
||||
ins left:GPR, right:GPR
|
||||
outs out:GPR
|
||||
emit "add %out, %right, %left"
|
||||
emit "add %reg, %right, %left"
|
||||
cost 4;
|
||||
|
||||
aluparam = value:CONST4
|
||||
|
@ -130,21 +116,17 @@ PATTERNS
|
|||
aluparam = reg;
|
||||
|
||||
reg = value:aluparam
|
||||
outs out:GPR
|
||||
emit "mov %out, %value"
|
||||
emit "mov %reg, %value"
|
||||
cost 4;
|
||||
|
||||
reg = value:LABEL4
|
||||
outs out:GPR
|
||||
emit "adr %out, %value"
|
||||
emit "adr %reg, %value"
|
||||
cost 4;
|
||||
|
||||
reg = value:BLOCK4
|
||||
outs out:GPR
|
||||
emit "adr %out, %value"
|
||||
emit "adr %reg, %value"
|
||||
cost 4;
|
||||
|
||||
reg = value:CONST4
|
||||
outs out:GPR
|
||||
emit "ldr %out, #value"
|
||||
emit "ldr %reg, #value"
|
||||
cost 4;
|
||||
|
|
|
@ -58,12 +58,6 @@ definerule("mcgg",
|
|||
error("you must supply exactly one input file")
|
||||
end
|
||||
|
||||
local cpptable = cppfile {
|
||||
name = e.name.."/cpptable",
|
||||
outleaf = "cpptable",
|
||||
srcs = e.srcs
|
||||
}
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
|
@ -72,7 +66,7 @@ definerule("mcgg",
|
|||
},
|
||||
ins = {
|
||||
"util/mcgg+mcgg",
|
||||
cpptable
|
||||
e.srcs[1]
|
||||
},
|
||||
commands = {
|
||||
"%{ins[1]} -i %{ins[2]} -o %{outs}",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <string.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 emitrule(Nonterm nts);
|
||||
static void emitpredicatedefinitions(Rule rules);
|
||||
static void emitemitters(Rule rules);
|
||||
static void emitstate(Term terms, Nonterm start, int ntnumber);
|
||||
static void emitstring(Rule rules);
|
||||
static void emitstruct(Nonterm nts, int ntnumber);
|
||||
|
@ -133,6 +135,7 @@ int main(int argc, char* argv[])
|
|||
emitrule(nts);
|
||||
emitclosure(nts);
|
||||
emitpredicatedefinitions(rules);
|
||||
emitemitters(rules);
|
||||
if (start)
|
||||
emitstate(terms, start, ntnumber);
|
||||
print("#ifdef STATE_LABEL\n");
|
||||
|
@ -334,6 +337,7 @@ Rule rule(char* id, Tree pattern, int ern)
|
|||
Term p = pattern->op;
|
||||
|
||||
nrules++;
|
||||
r->lineno = yylineno;
|
||||
r->lhs = nonterm(id);
|
||||
r->packed = ++r->lhs->lhscount;
|
||||
for (q = &r->lhs->rules; *q; q = &(*q)->decode)
|
||||
|
@ -791,6 +795,7 @@ static void emitpredicatedefinitions(Rule r)
|
|||
Stringlist s = r->when;
|
||||
if (s)
|
||||
{
|
||||
print("/* %R */\n", r);
|
||||
print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern);
|
||||
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 */
|
||||
static void emitcostcalc(Rule r)
|
||||
{
|
||||
|
|
|
@ -58,6 +58,7 @@ struct rule
|
|||
{ /* rules: */
|
||||
Nonterm lhs; /* lefthand side non-terminal */
|
||||
Tree pattern; /* rule pattern */
|
||||
int lineno; /* line number where allocated */
|
||||
int ern; /* external rule number */
|
||||
int packed; /* packed external rule number */
|
||||
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 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
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
||||
|
|
|
@ -14,7 +14,7 @@ static int braces = 0;
|
|||
|
||||
%x CSTRING
|
||||
%x QSTRING
|
||||
%x ECHO
|
||||
%x COMMENT
|
||||
|
||||
%%
|
||||
|
||||
|
@ -50,7 +50,7 @@ static int braces = 0;
|
|||
<INITIAL>"\"" BEGIN(QSTRING);
|
||||
<QSTRING>"\"" BEGIN(INITIAL);
|
||||
|
||||
<QSTRING>%[a-zA-Z_]+ {
|
||||
<QSTRING>%[a-zA-Z_][a-zA_Z_0-9]+ {
|
||||
yylval.string = strdup(yytext);
|
||||
return QFRAGMENT;
|
||||
}
|
||||
|
@ -60,6 +60,11 @@ static int braces = 0;
|
|||
return QFRAGMENT;
|
||||
}
|
||||
|
||||
<INITIAL>"/*" BEGIN(COMMENT);
|
||||
<COMMENT>"*/" BEGIN(INITIAL);
|
||||
<COMMENT>[^*]* ;
|
||||
<COMMENT>"*" ;
|
||||
|
||||
"%%" return PPERCENT;
|
||||
"%term" return TERMINAL;
|
||||
"%start" return START;
|
||||
|
@ -72,6 +77,8 @@ static int braces = 0;
|
|||
"fragment" return FRAGMENT;
|
||||
"cost" return COST;
|
||||
|
||||
"//"[^\n]*\n ;
|
||||
|
||||
[A-Za-z_][A-Za-z0-9_]* { yylval.string = strdup(yytext); return ID; }
|
||||
[0-9]+ { yylval.n = atoi(yytext); return INT; }
|
||||
[ \t\r\n]* ;
|
||||
|
|
Loading…
Reference in a new issue