From 91e277e046479bbbb1b3a76dc980b127fbca409c Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 1 Oct 2016 13:56:52 +0200 Subject: [PATCH] Predicates work; we now have prefers and requires clauses. Predicates must be functions. Not convinced that semantic types are actually working --- there are still problems with earlier statements leaving things in the wrong registers. --- mach/proto/mcg/hop.c | 4 ++ mach/proto/mcg/ir.h | 1 + mach/proto/mcg/mcgg_generated_header.h | 10 ++++ mach/proto/mcg/pass_instructionselection.c | 5 +- mach/proto/mcg/table | 26 +++++--- util/mcgg/gram.y | 28 +++++---- util/mcgg/iburg.c | 70 ++++++++++++++-------- util/mcgg/iburg.h | 10 +++- util/mcgg/scan.l | 35 +---------- 9 files changed, 112 insertions(+), 77 deletions(-) diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 35bed381b..a57d4988a 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -89,6 +89,10 @@ void hop_print(char k, struct hop* hop) tracef(k, "%s", ir->u.bvalue->name); break; + case IR_LABEL: + tracef(k, "%s", ir->u.lvalue); + break; + case IR_LOCAL: case IR_CONST: tracef(k, "0x%d", ir->u.ivalue); diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index 069a76bd5..abf4a1792 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -20,6 +20,7 @@ struct ir void* state_label; /* used by the iburg instruction selector */ int insn_no; /* the table rule number for this instruction */ + int goal_no; /* the semantic type of this instruction; not stmt */ ARRAYOF(struct hop) hops; /* only for root IRs */ bool is_root : 1; diff --git a/mach/proto/mcg/mcgg_generated_header.h b/mach/proto/mcg/mcgg_generated_header.h index a3e79afc0..b37fe8cd3 100644 --- a/mach/proto/mcg/mcgg_generated_header.h +++ b/mach/proto/mcg/mcgg_generated_header.h @@ -20,3 +20,13 @@ static int OP_LABEL(struct ir* ir) extern void burm_panic_cannot_match(struct ir* ir); +static bool burm_predicate_int(struct ir* ir) +{ + return ir->goal_no == 3; +} + +static bool burm_predicate_float(struct ir* ir) +{ + return ir->goal_no == 5; +} + diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index 2b0bb96c3..ea13ae52b 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -83,10 +83,13 @@ static void walk_instructions(struct ir* ir, int goal) ir->is_generated = true; ir->insn_no = insn_no; + if (goal != 1) + ir->goal_no = goal; - tracef('I', "I: $%d %s selected %s %d: %s\n", + tracef('I', "I: $%d %s goal %d selected %s %d: %s\n", ir->id, ir->is_root ? "S" : " ", + ir->goal_no, insndata->is_fragment ? "fragment" : "instruction", insn_no, insndata->name); diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index 31e51cdb7..c88c68fcb 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -61,13 +61,19 @@ PATTERNS emit "mov r0, %in" cost 4; - int = REG4 cost 1; - float = REG4 cost 1; + int = in:REG4 + prefers int(in) + cost 1; - any = int cost 1; - int = any cost 1; - any = float cost 1; - float = any cost 1; + float = in:REG4 + prefers float(in) + cost 1; + + ret = in:any emit "mov %ret, %in" cost 1; + any = in:int emit "mov %any, %in" cost 1; + int = in:any emit "mov %int, %in" cost 1; + any = in:float emit "mov %any, %in" cost 1; + float = in:any emit "mov %float, %in" cost 1; /* Memory operations */ @@ -180,8 +186,12 @@ PATTERNS emit "adr %int, $value" cost 4; - any = value:CONST4 - emit "ldr %any, address-containing-$value" + int = value:CONST4 + emit "ldr %int, address-containing-$value" + cost 8; + + float = value:CONST4 + emit "vldr %float, address-containing-$value" cost 8; /* FPU operations */ diff --git a/util/mcgg/gram.y b/util/mcgg/gram.y index 94b188398..e65a6256b 100644 --- a/util/mcgg/gram.y +++ b/util/mcgg/gram.y @@ -23,6 +23,7 @@ static int nextern = 1; struct reg* reg; struct stringlist* stringlist; struct terminfo terminfo; + struct expr* expr; } %term ALLOCATES @@ -30,15 +31,13 @@ static int nextern = 1; %term DECLARATIONS %term EMIT %term FRAGMENT -%term INS -%term OUTS %term PATTERNS %term REGISTERS -%term WHEN +%term PREFERS +%term REQUIRES %token INT %token ID -%token CFRAGMENT %token QFRAGMENT %type allocates @@ -50,6 +49,8 @@ static int nextern = 1; %type qfragments %type terminfo %type rhs +%type predicate +%type predicate_args %% spec @@ -100,7 +101,8 @@ patterns pattern : ID '=' rhs { nonterm($1, false); $$ = rule($1, $3, nextern++); } | rhs { $$ = rule("stmt", $1, nextern++); } - | pattern WHEN cfragments { $$ = $1; stringlist_addall(&$$->when, $3); } + | pattern PREFERS predicate { $$ = $1; array_append(&$$->prefers, $3); } + | pattern REQUIRES predicate { $$ = $1; array_append(&$$->requires, $3); } | emit { $$ = $1; } | pattern COST INT { $$ = $1; $$->cost = $3; } ; @@ -118,11 +120,6 @@ terminfo | ID ':' ID '.' ID { $$.label = $1; $$.name = $3; $$.regattr = $5; } ; -cfragments - : /* nothing */ { $$ = calloc(1, sizeof *$$); } - | cfragments CFRAGMENT { $$ = $1; stringlist_add($$, $2); } - ; - emit : pattern EMIT qfragments { $$ = $1; @@ -137,6 +134,16 @@ qfragments | qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); } ; +predicate + : ID '(' predicate_args ')' { $$ = calloc(1, sizeof *$$); $$->name = $1; $$->next = $3; } + ; + +predicate_args + : /* nothing */ + | ID { $$ = calloc(1, sizeof *$$); $$->name = $1; } + | ID ',' predicate_args { $$ = calloc(1, sizeof *$$); $$->name = $1; $$->next = $3; } + ; + %% #include #include @@ -157,6 +164,7 @@ void yyerror(char *fmt, ...) { if (fmt[strlen(fmt)-1] != '\n') fprintf(stderr, "\n"); errcnt++; + exit(1); } void yywarn(char *fmt, ...) { diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index 70d4ab080..074198d0c 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -598,7 +598,7 @@ static void emitcase(Term p, int ntnumber) default: assert(0); } - print("%d;\n", r->cost); + print("%d);\n", r->cost); emitrecord("\t\t\t", r, 0); print("%2}\n"); } @@ -859,27 +859,6 @@ static void emitrule(Nonterm nts) print("%1default:\n%2%Passert(0, PANIC(\"Bad goal nonterminal %%d in %Prule\\n\", goalnt));\n%1}\n%1return 0;\n}\n\n"); } -/* emitpredicates - emit predicates for rules */ -static void emitpredicatedefinitions(Rule r) -{ - while (r) - { - struct stringfragment* f = r->when.first; - if (f) - { - print("/* %R */\n", r); - print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern); - while (f) - { - print("%s", f->data); - f = f->next; - } - print("\n}\n\n"); - } - r = r->link; - } -} - static void print_path(uint32_t path) { int i = 0; @@ -932,6 +911,50 @@ static void label_not_found(Rule rule, const char* label) exit(1); } +/* emitpredicates - emit predicates for rules */ +static void emitpredicatedefinitions(Rule r) +{ + int i; + + while (r) + { + print("/* %R */\n", r); + print("static int %Padjust_cost_%d(NODEPTR_TYPE node, int cost) {\n", r->ern); + + for (i=0; iprefers.count; i++) + { + struct expr* p = r->prefers.item[i]; + bool first = true; + + print("%1if (%Ppredicate_%s(", p->name); + + p = p->next; + while (p) + { + uint32_t path = find_label(r->pattern, p->name, 0, NULL); + if (path == PATH_MISSING) + label_not_found(r, p->name); + + if (!first) + print(", "); + else + first = false; + + print_path(path); + p = p->next; + } + + print(")) cost -= 1;\n"); + } + + print("%1if (cost > %d) return %d;\n", maxcost, maxcost); + print("%1if (cost < 1) return 1;\n"); + print("%1return cost;\n"); + print("}\n\n"); + r = r->link; + } +} + /* emitinsndata - emit the code generation data */ static void emitinsndata(Rule rules) { @@ -1051,8 +1074,7 @@ static void emitinsndata(Rule rules) /* emitcost - emit a cost calculation via a predicate */ static void emitcostcalc(Rule r) { - if (r->when.first) - print("!%Ppredicate_%d(node) ? %d : ", r->ern, maxcost); + print("%Padjust_cost_%d(node, ", r->ern); } /* emitstate - emit state function */ diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 1a4211e91..919f4471d 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -2,6 +2,7 @@ #define BURG_INCLUDED #include "stringlist.h" +#include "array.h" extern char* stringf(char* fmt, ...); @@ -15,6 +16,12 @@ typedef enum typedef struct rule* Rule; typedef struct term* Term; +struct expr +{ + const char* name; + struct expr* next; +}; + struct terminfo { const char* name; @@ -90,7 +97,8 @@ struct rule Rule chain; /* next chain rule with same rhs */ Rule decode; /* next rule with same lhs */ Rule kids; /* next rule with same burm_kids pattern */ - struct stringlist when; /* C predicate string */ + ARRAYOF(struct predicate) prefers; /* C predicates */ + ARRAYOF(struct predicate) requires; /* C predicates */ struct stringlist code; /* compiler output code strings */ }; extern Rule rule(char* id, Tree pattern, int ern); diff --git a/util/mcgg/scan.l b/util/mcgg/scan.l index 83e0fe3cf..30280c492 100644 --- a/util/mcgg/scan.l +++ b/util/mcgg/scan.l @@ -12,41 +12,11 @@ static int braces = 0; %option yylineno %option debug -%x CSTRING %x QSTRING %x COMMENT %% -"{" { - yylval.string = ""; //stringf("#line %d\n", yylineno); - braces = 1; - BEGIN(CSTRING); - return CFRAGMENT; - } - -"{" { - braces++; - yylval.string = strdup(yytext); - return CFRAGMENT; - } - -"}" { - braces--; - if (braces == 0) - BEGIN(INITIAL); - else - { - yylval.string = strdup(yytext); - return CFRAGMENT; - } - } - -[^{}]+ { - yylval.string = strdup(yytext); - return CFRAGMENT; - } - "\"" BEGIN(QSTRING); "\"" BEGIN(INITIAL); @@ -72,9 +42,8 @@ static int braces = 0; "cost" return COST; "emit" return EMIT; "fragment" return FRAGMENT; -"ins" return INS; -"outs" return OUTS; -"when" return WHEN; +"prefers" return PREFERS; +"requires" return REQUIRES; "//"[^\n]*\n ;