badly).
cost 4;
reg = POP4
- outs out:ANY
- emit "pop %out"
+ emit "pop %reg"
cost 4;
RET
/* 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
/* Memory addressing modes */
address = ADD4(addr:reg, offset:CONST)
- ins addr:GPR
fragment "[%addr, #%offset]";
address = addr:reg
- ins addr:GPR
fragment "[%addr]";
/* 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
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;
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,
},
ins = {
"util/mcgg+mcgg",
- cpptable
+ e.srcs[1]
},
commands = {
"%{ins[1]} -i %{ins[2]} -o %{outs}",
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
+#include <stdint.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
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);
emitrule(nts);
emitclosure(nts);
emitpredicatedefinitions(rules);
+ emitemitters(rules);
if (start)
emitstate(terms, start, ntnumber);
print("#ifdef STATE_LABEL\n");
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)
Stringlist s = r->when;
if (s)
{
+ print("/* %R */\n", r);
print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern);
while (s)
{
}
}
+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)
{
{ /* 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 */
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 : */
%x CSTRING
%x QSTRING
-%x ECHO
+%x COMMENT
%%
<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;
}
return QFRAGMENT;
}
+<INITIAL>"/*" BEGIN(COMMENT);
+<COMMENT>"*/" BEGIN(INITIAL);
+<COMMENT>[^*]* ;
+<COMMENT>"*" ;
+
"%%" return PPERCENT;
"%term" return TERMINAL;
"%start" return START;
"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]* ;