Rethink the way patterns are mapped to rules; generate emitters (probably

badly).
This commit is contained in:
David Given 2016-09-25 11:49:51 +02:00
parent 7c028bdd45
commit 9f78e0b36b
6 changed files with 153 additions and 45 deletions

View file

@ -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;

View file

@ -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}",

View file

@ -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)
{

View file

@ -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 */

View file

@ -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 : */

View file

@ -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]* ;