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);
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;
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;
+}
+
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);
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 */
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 */
struct reg* reg;
struct stringlist* stringlist;
struct terminfo terminfo;
+ struct expr* expr;
}
%term ALLOCATES
%term DECLARATIONS
%term EMIT
%term FRAGMENT
-%term INS
-%term OUTS
%term PATTERNS
%term REGISTERS
-%term WHEN
+%term PREFERS
+%term REQUIRES
%token <n> INT
%token <string> ID
-%token <string> CFRAGMENT
%token <string> QFRAGMENT
%type <nonterm> allocates
%type <stringlist> qfragments
%type <terminfo> terminfo
%type <tree> rhs
+%type <expr> predicate
+%type <expr> predicate_args
%%
spec
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; }
;
| 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;
| 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 <stdarg.h>
#include <ctype.h>
if (fmt[strlen(fmt)-1] != '\n')
fprintf(stderr, "\n");
errcnt++;
+ exit(1);
}
void yywarn(char *fmt, ...) {
default:
assert(0);
}
- print("%d;\n", r->cost);
+ print("%d);\n", r->cost);
emitrecord("\t\t\t", r, 0);
print("%2}\n");
}
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;
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; i<r->prefers.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)
{
/* 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 */
#define BURG_INCLUDED
#include "stringlist.h"
+#include "array.h"
extern char* stringf(char* fmt, ...);
typedef struct rule* Rule;
typedef struct term* Term;
+struct expr
+{
+ const char* name;
+ struct expr* next;
+};
+
struct terminfo
{
const char* name;
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);
%option yylineno
%option debug
-%x CSTRING
%x QSTRING
%x COMMENT
%%
-<INITIAL>"{" {
- yylval.string = ""; //stringf("#line %d\n", yylineno);
- braces = 1;
- BEGIN(CSTRING);
- return CFRAGMENT;
- }
-
-<CSTRING>"{" {
- braces++;
- yylval.string = strdup(yytext);
- return CFRAGMENT;
- }
-
-<CSTRING>"}" {
- braces--;
- if (braces == 0)
- BEGIN(INITIAL);
- else
- {
- yylval.string = strdup(yytext);
- return CFRAGMENT;
- }
- }
-
-<CSTRING>[^{}]+ {
- yylval.string = strdup(yytext);
- return CFRAGMENT;
- }
-
<INITIAL>"\"" BEGIN(QSTRING);
<QSTRING>"\"" BEGIN(INITIAL);
"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 ;