diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index b32d43210..efaffdc36 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -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; diff --git a/util/mcgg/build.lua b/util/mcgg/build.lua index 0485197a9..ee230d73a 100644 --- a/util/mcgg/build.lua +++ b/util/mcgg/build.lua @@ -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}", diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index cbbfab50a..52df9cc31 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -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) { diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 361cdba33..0a6c90dfc 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -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 */ diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h index 297be186b..10d8f5166 100644 --- a/util/mcgg/mcgg.h +++ b/util/mcgg/mcgg.h @@ -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 : */ diff --git a/util/mcgg/scan.l b/util/mcgg/scan.l index 941830c73..479a115fc 100644 --- a/util/mcgg/scan.l +++ b/util/mcgg/scan.l @@ -14,7 +14,7 @@ static int braces = 0; %x CSTRING %x QSTRING -%x ECHO +%x COMMENT %% @@ -50,7 +50,7 @@ static int braces = 0; "\"" BEGIN(QSTRING); "\"" BEGIN(INITIAL); -%[a-zA-Z_]+ { +%[a-zA-Z_][a-zA_Z_0-9]+ { yylval.string = strdup(yytext); return QFRAGMENT; } @@ -60,6 +60,11 @@ static int braces = 0; return QFRAGMENT; } +"/*" BEGIN(COMMENT); +"*/" BEGIN(INITIAL); +[^*]* ; +"*" ; + "%%" 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]* ;