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.
This commit is contained in:
parent
4a3a9a98dc
commit
91e277e046
|
@ -89,6 +89,10 @@ void hop_print(char k, struct hop* hop)
|
||||||
tracef(k, "%s", ir->u.bvalue->name);
|
tracef(k, "%s", ir->u.bvalue->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IR_LABEL:
|
||||||
|
tracef(k, "%s", ir->u.lvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
case IR_LOCAL:
|
case IR_LOCAL:
|
||||||
case IR_CONST:
|
case IR_CONST:
|
||||||
tracef(k, "0x%d", ir->u.ivalue);
|
tracef(k, "0x%d", ir->u.ivalue);
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct ir
|
||||||
|
|
||||||
void* state_label; /* used by the iburg instruction selector */
|
void* state_label; /* used by the iburg instruction selector */
|
||||||
int insn_no; /* the table rule number for this instruction */
|
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 */
|
ARRAYOF(struct hop) hops; /* only for root IRs */
|
||||||
|
|
||||||
bool is_root : 1;
|
bool is_root : 1;
|
||||||
|
|
|
@ -20,3 +20,13 @@ static int OP_LABEL(struct ir* ir)
|
||||||
|
|
||||||
extern void burm_panic_cannot_match(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,10 +83,13 @@ static void walk_instructions(struct ir* ir, int goal)
|
||||||
|
|
||||||
ir->is_generated = true;
|
ir->is_generated = true;
|
||||||
ir->insn_no = insn_no;
|
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->id,
|
||||||
ir->is_root ? "S" : " ",
|
ir->is_root ? "S" : " ",
|
||||||
|
ir->goal_no,
|
||||||
insndata->is_fragment ? "fragment" : "instruction",
|
insndata->is_fragment ? "fragment" : "instruction",
|
||||||
insn_no,
|
insn_no,
|
||||||
insndata->name);
|
insndata->name);
|
||||||
|
|
|
@ -61,13 +61,19 @@ PATTERNS
|
||||||
emit "mov r0, %in"
|
emit "mov r0, %in"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
int = REG4 cost 1;
|
int = in:REG4
|
||||||
float = REG4 cost 1;
|
prefers int(in)
|
||||||
|
cost 1;
|
||||||
|
|
||||||
any = int cost 1;
|
float = in:REG4
|
||||||
int = any cost 1;
|
prefers float(in)
|
||||||
any = float cost 1;
|
cost 1;
|
||||||
float = any 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 */
|
/* Memory operations */
|
||||||
|
@ -180,8 +186,12 @@ PATTERNS
|
||||||
emit "adr %int, $value"
|
emit "adr %int, $value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
any = value:CONST4
|
int = value:CONST4
|
||||||
emit "ldr %any, address-containing-$value"
|
emit "ldr %int, address-containing-$value"
|
||||||
|
cost 8;
|
||||||
|
|
||||||
|
float = value:CONST4
|
||||||
|
emit "vldr %float, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
/* FPU operations */
|
/* FPU operations */
|
||||||
|
|
|
@ -23,6 +23,7 @@ static int nextern = 1;
|
||||||
struct reg* reg;
|
struct reg* reg;
|
||||||
struct stringlist* stringlist;
|
struct stringlist* stringlist;
|
||||||
struct terminfo terminfo;
|
struct terminfo terminfo;
|
||||||
|
struct expr* expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
%term ALLOCATES
|
%term ALLOCATES
|
||||||
|
@ -30,15 +31,13 @@ static int nextern = 1;
|
||||||
%term DECLARATIONS
|
%term DECLARATIONS
|
||||||
%term EMIT
|
%term EMIT
|
||||||
%term FRAGMENT
|
%term FRAGMENT
|
||||||
%term INS
|
|
||||||
%term OUTS
|
|
||||||
%term PATTERNS
|
%term PATTERNS
|
||||||
%term REGISTERS
|
%term REGISTERS
|
||||||
%term WHEN
|
%term PREFERS
|
||||||
|
%term REQUIRES
|
||||||
|
|
||||||
%token <n> INT
|
%token <n> INT
|
||||||
%token <string> ID
|
%token <string> ID
|
||||||
%token <string> CFRAGMENT
|
|
||||||
%token <string> QFRAGMENT
|
%token <string> QFRAGMENT
|
||||||
|
|
||||||
%type <nonterm> allocates
|
%type <nonterm> allocates
|
||||||
|
@ -50,6 +49,8 @@ static int nextern = 1;
|
||||||
%type <stringlist> qfragments
|
%type <stringlist> qfragments
|
||||||
%type <terminfo> terminfo
|
%type <terminfo> terminfo
|
||||||
%type <tree> rhs
|
%type <tree> rhs
|
||||||
|
%type <expr> predicate
|
||||||
|
%type <expr> predicate_args
|
||||||
%%
|
%%
|
||||||
|
|
||||||
spec
|
spec
|
||||||
|
@ -100,7 +101,8 @@ patterns
|
||||||
pattern
|
pattern
|
||||||
: ID '=' rhs { nonterm($1, false); $$ = rule($1, $3, nextern++); }
|
: ID '=' rhs { nonterm($1, false); $$ = rule($1, $3, nextern++); }
|
||||||
| rhs { $$ = rule("stmt", $1, 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; }
|
| emit { $$ = $1; }
|
||||||
| pattern COST INT { $$ = $1; $$->cost = $3; }
|
| pattern COST INT { $$ = $1; $$->cost = $3; }
|
||||||
;
|
;
|
||||||
|
@ -118,11 +120,6 @@ terminfo
|
||||||
| ID ':' ID '.' ID { $$.label = $1; $$.name = $3; $$.regattr = $5; }
|
| ID ':' ID '.' ID { $$.label = $1; $$.name = $3; $$.regattr = $5; }
|
||||||
;
|
;
|
||||||
|
|
||||||
cfragments
|
|
||||||
: /* nothing */ { $$ = calloc(1, sizeof *$$); }
|
|
||||||
| cfragments CFRAGMENT { $$ = $1; stringlist_add($$, $2); }
|
|
||||||
;
|
|
||||||
|
|
||||||
emit
|
emit
|
||||||
: pattern EMIT qfragments {
|
: pattern EMIT qfragments {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
@ -137,6 +134,16 @@ qfragments
|
||||||
| qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); }
|
| 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 <stdarg.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -157,6 +164,7 @@ void yyerror(char *fmt, ...) {
|
||||||
if (fmt[strlen(fmt)-1] != '\n')
|
if (fmt[strlen(fmt)-1] != '\n')
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
errcnt++;
|
errcnt++;
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void yywarn(char *fmt, ...) {
|
void yywarn(char *fmt, ...) {
|
||||||
|
|
|
@ -598,7 +598,7 @@ static void emitcase(Term p, int ntnumber)
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
print("%d;\n", r->cost);
|
print("%d);\n", r->cost);
|
||||||
emitrecord("\t\t\t", r, 0);
|
emitrecord("\t\t\t", r, 0);
|
||||||
print("%2}\n");
|
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");
|
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)
|
static void print_path(uint32_t path)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -932,6 +911,50 @@ static void label_not_found(Rule rule, const char* label)
|
||||||
exit(1);
|
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 */
|
/* emitinsndata - emit the code generation data */
|
||||||
static void emitinsndata(Rule rules)
|
static void emitinsndata(Rule rules)
|
||||||
{
|
{
|
||||||
|
@ -1051,8 +1074,7 @@ static void emitinsndata(Rule rules)
|
||||||
/* emitcost - emit a cost calculation via a predicate */
|
/* emitcost - emit a cost calculation via a predicate */
|
||||||
static void emitcostcalc(Rule r)
|
static void emitcostcalc(Rule r)
|
||||||
{
|
{
|
||||||
if (r->when.first)
|
print("%Padjust_cost_%d(node, ", r->ern);
|
||||||
print("!%Ppredicate_%d(node) ? %d : ", r->ern, maxcost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* emitstate - emit state function */
|
/* emitstate - emit state function */
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define BURG_INCLUDED
|
#define BURG_INCLUDED
|
||||||
|
|
||||||
#include "stringlist.h"
|
#include "stringlist.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
extern char* stringf(char* fmt, ...);
|
extern char* stringf(char* fmt, ...);
|
||||||
|
|
||||||
|
@ -15,6 +16,12 @@ typedef enum
|
||||||
typedef struct rule* Rule;
|
typedef struct rule* Rule;
|
||||||
typedef struct term* Term;
|
typedef struct term* Term;
|
||||||
|
|
||||||
|
struct expr
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
struct expr* next;
|
||||||
|
};
|
||||||
|
|
||||||
struct terminfo
|
struct terminfo
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
|
@ -90,7 +97,8 @@ struct rule
|
||||||
Rule chain; /* next chain rule with same rhs */
|
Rule chain; /* next chain rule with same rhs */
|
||||||
Rule decode; /* next rule with same lhs */
|
Rule decode; /* next rule with same lhs */
|
||||||
Rule kids; /* next rule with same burm_kids pattern */
|
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 */
|
struct stringlist code; /* compiler output code strings */
|
||||||
};
|
};
|
||||||
extern Rule rule(char* id, Tree pattern, int ern);
|
extern Rule rule(char* id, Tree pattern, int ern);
|
||||||
|
|
|
@ -12,41 +12,11 @@ static int braces = 0;
|
||||||
%option yylineno
|
%option yylineno
|
||||||
%option debug
|
%option debug
|
||||||
|
|
||||||
%x CSTRING
|
|
||||||
%x QSTRING
|
%x QSTRING
|
||||||
%x COMMENT
|
%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);
|
<INITIAL>"\"" BEGIN(QSTRING);
|
||||||
<QSTRING>"\"" BEGIN(INITIAL);
|
<QSTRING>"\"" BEGIN(INITIAL);
|
||||||
|
|
||||||
|
@ -72,9 +42,8 @@ static int braces = 0;
|
||||||
"cost" return COST;
|
"cost" return COST;
|
||||||
"emit" return EMIT;
|
"emit" return EMIT;
|
||||||
"fragment" return FRAGMENT;
|
"fragment" return FRAGMENT;
|
||||||
"ins" return INS;
|
"prefers" return PREFERS;
|
||||||
"outs" return OUTS;
|
"requires" return REQUIRES;
|
||||||
"when" return WHEN;
|
|
||||||
|
|
||||||
"//"[^\n]*\n ;
|
"//"[^\n]*\n ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue