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:
David Given 2016-10-01 13:56:52 +02:00
parent 4a3a9a98dc
commit 91e277e046
9 changed files with 112 additions and 77 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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 */

View file

@ -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, ...) {

View file

@ -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 */

View file

@ -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);

View file

@ -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 ;