Come up with a syntax for register constraints.

This commit is contained in:
David Given 2016-10-02 21:51:25 +02:00
parent c079e97492
commit 3aa30e50d1
5 changed files with 129 additions and 87 deletions

View file

@ -29,6 +29,9 @@ REGISTERS
DECLARATIONS
reg;
cc;
address fragment;
aluparam fragment;
@ -37,88 +40,75 @@ PATTERNS
/* Special */
int;
float;
any;
reg;
PAIR(BLOCK4, BLOCK4);
/* Miscellaneous special things */
PUSH4(in:int)
PUSH4(in:reg)
emit "push %in"
cost 4;
int = POP4
emit "pop %int"
reg = POP4
emit "pop %reg"
cost 4;
RET
emit "ret"
cost 4;
SETRET4(in:ret)
emit "mov r0, %in"
SETRET4(in:reg)
with ret reg
cost 4;
STACKADJUST4(delta:aluparam)
emit "add sp, sp, %delta"
cost 4;
int = in:REG4
prefers int(in)
reg = in:REG4
with (reg == in)
cost 1;
int = NOP4(in:int)
emit "mov %int, %in"
reg = NOP4(in:reg)
with (reg == in)
cost 1;
any = PHI4
cost 0;
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 */
STORE4(addr:address, value:int)
STORE4(addr:address, value:reg)
with int value
emit "str %value, %addr"
cost 4;
STORE1(addr:address, value:int)
STORE1(addr:address, value:reg)
with int value
emit "strb %value, %addr"
cost 4;
int = LOAD4(addr:address)
emit "ldr %int, %addr"
reg = LOAD4(addr:address)
emit "ldr %reg, %addr"
cost 4;
int = LOAD1(addr:address)
emit "ldrb %int, %addr"
reg = LOAD1(addr:address)
emit "ldrb %reg, %addr"
cost 4;
int = CIU14(LOAD1(addr:address))
emit "ldrb %int, %addr"
reg = CIU14(LOAD1(addr:address))
emit "ldrb %reg, %addr"
cost 4;
int = CII14(CIU41(CIU14(LOAD1(addr:address))))
emit "ldrsb %int, %addr"
reg = CII14(CIU41(CIU14(LOAD1(addr:address))))
emit "ldrsb %reg, %addr"
cost 4;
/* Locals */
int = in:LOCAL4
emit "add %int, fp, #$in"
reg = in:LOCAL4
emit "add %reg, fp, #$in"
cost 4;
address = in:LOCAL4
@ -127,13 +117,16 @@ PATTERNS
/* Memory addressing modes */
address = ADD4(addr:int, offset:CONST4)
address = ADD4(addr:reg, offset:CONST4)
with int addr
emit "[%addr, #$offset]";
address = ADD4(addr1:int, addr2:int)
address = ADD4(addr1:reg, addr2:reg)
with int addr1, int addr2
emit "[%addr1, %addr2]";
address = addr:int
address = addr:reg
with int addr
emit "[%addr]";
@ -166,80 +159,80 @@ PATTERNS
/* Comparisons */
cc = COMPARES4(left:int, right:aluparam)
cc = COMPARES4(left:reg, right:aluparam)
emit "cmp %left, %right"
cost 4;
cc = COMPARES4(COMPARES4(left:int, right:aluparam), CONST4)
cc = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4)
emit "cmp %left, %right"
cost 4;
int = cc
emit "mov %int, #0"
emit "movlt %int, #-1"
emit "movgt %int, #1"
reg = cc
emit "mov %reg, #0"
emit "movlt %reg, #-1"
emit "movgt %reg, #1"
cost 12;
/* Conversions */
int = CII14(CIU41(value:int))
emit "sxtb %int, %value"
reg = CII14(CIU41(value:reg))
emit "sxtb %reg, %value"
cost 4;
int = CIU41(in:int)
emit "and %int, %in, #0xff"
reg = CIU41(in:reg)
emit "and %reg, %in, #0xff"
cost 4;
/* ALU operations */
int = ADD4(left:int, right:aluparam)
emit "add %int, %left, %right"
reg = ADD4(left:reg, right:aluparam)
emit "add %reg, %left, %right"
cost 4;
int = ADD4(left:aluparam, right:int)
emit "add %int, %right, %left"
reg = ADD4(left:aluparam, right:reg)
emit "add %reg, %right, %left"
cost 4;
int = MOD4(left:int, right:int)
emit "udiv %int, %left, %right"
emit "mls %int, %int, %right, %left"
reg = MOD4(left:reg, right:reg)
emit "udiv %reg, %left, %right"
emit "mls %reg, %reg, %right, %left"
cost 8;
int = DIV4(left:int, right:aluparam)
emit "div %int, %left, %right"
reg = DIV4(left:reg, right:aluparam)
emit "div %reg, %left, %right"
cost 4;
aluparam = value:CONST4
emit "#$value";
aluparam = value:int
aluparam = value:reg
emit "%value";
int = value:aluparam
emit "mov %int, %value"
reg = value:aluparam
emit "mov %reg, %value"
cost 4;
int = value:LABEL4
emit "adr %int, $value"
reg = value:LABEL4
emit "adr %reg, $value"
cost 4;
int = value:BLOCK4
emit "adr %int, $value"
reg = value:BLOCK4
emit "adr %reg, $value"
cost 4;
int = value:CONST4
emit "ldr %int, address-containing-$value"
reg = value:CONST4
emit "ldr %reg, address-containing-$value"
cost 8;
float = value:CONSTF4
emit "vldr %float, address-containing-$value"
reg = value:CONSTF4
emit "vldr %reg, address-containing-$value"
cost 8;
/* FPU operations */
float = ADDF4(left:float, right:float)
emit "fadds %float, %left, %right"
reg = ADDF4(left:reg, right:reg)
emit "fadds %reg, %left, %right"
cost 4;

View file

@ -24,28 +24,34 @@ static int nextern = 1;
struct stringlist* stringlist;
struct terminfo terminfo;
struct expr* expr;
struct constraint* constraint;
}
%term ALLOCATES
%term COST
%term DECLARATIONS
%term EMIT
%term EQUALS
%term FRAGMENT
%term NOTEQUALS
%term PATTERNS
%term REGISTERS
%term PREFERS
%term REQUIRES
%term REGISTERS
%term WHEN
%term WITH
%token <n> INT
%token <string> ID
%token <string> QFRAGMENT
%type <nonterm> allocates
%type <constraint> constraint
%type <constraint> constraints
%type <nonterm> declaration
%type <reg> register
%type <rule> emit
%type <rule> pattern_constraints
%type <rule> pattern_emit
%type <rule> pattern
%type <stringlist> cfragments
%type <stringlist> qfragments
%type <terminfo> terminfo
%type <tree> rhs
@ -102,9 +108,10 @@ pattern
: ID '=' rhs { nonterm($1, false); $$ = rule($1, $3, nextern++); }
| rhs { $$ = rule("stmt", $1, nextern++); }
| pattern PREFERS predicate { $$ = $1; array_append(&$$->prefers, $3); }
| pattern REQUIRES predicate { $$ = $1; array_append(&$$->requires, $3); }
| emit { $$ = $1; }
| pattern WHEN predicate { $$ = $1; array_append(&$$->requires, $3); }
| pattern COST INT { $$ = $1; $$->cost = $3; }
| pattern_constraints { $$ = $1; }
| pattern_emit { $$ = $1; }
;
rhs
@ -115,12 +122,10 @@ rhs
terminfo
: ID { $$.name = $1; }
| ID '.' ID { $$.name = $1; $$.regattr = $3; }
| ID ':' ID { $$.label = $1; $$.name = $3; }
| ID ':' ID '.' ID { $$.label = $1; $$.name = $3; $$.regattr = $5; }
;
emit
pattern_emit
: pattern EMIT qfragments {
$$ = $1;
if (!$$->lhs->is_fragment)
@ -129,6 +134,33 @@ emit
}
;
pattern_constraints
: pattern WITH constraints {
struct constraint* c = $3;
$$ = $1;
while (c)
{
array_append(&$$->constraints, c);
c = c->next;
}
}
;
constraints
: constraint { $$ = $1; }
| constraints ',' constraint { $$ = $3; $$->next = $1; }
;
constraint
: '(' constraint ')' { $$ = $2; }
| ID ID { $$ = calloc(1, sizeof(*$$));
$$->type = CONSTRAINT_ATTR; $$->left = $1; $$->right = $2; }
| ID EQUALS ID { $$ = calloc(1, sizeof(*$$));
$$->type = CONSTRAINT_EQUALS; $$->left = $1; $$->right = $3; }
| ID NOTEQUALS ID { $$ = calloc(1, sizeof(*$$));
$$->type = CONSTRAINT_NOTEQUALS; $$->left = $1; $$->right = $3; }
;
qfragments
: /* nothing */ { $$ = calloc(1, sizeof *$$); }
| qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); }
@ -139,7 +171,7 @@ predicate
;
predicate_args
: /* nothing */
: /* nothing */ { $$ = NULL; }
| ID { $$ = calloc(1, sizeof *$$); $$->name = $1; }
| ID ',' predicate_args { $$ = calloc(1, sizeof *$$); $$->name = $1; $$->next = $3; }
;

View file

@ -262,7 +262,6 @@ void addregclass(struct reg* reg, const char* id)
}
reg->classes |= 1<<(p->number);
nonterm(id, true);
}
struct regclass* getregclass(const char* id)

View file

@ -16,6 +16,21 @@ typedef enum
typedef struct rule* Rule;
typedef struct term* Term;
enum
{
CONSTRAINT_ATTR,
CONSTRAINT_EQUALS,
CONSTRAINT_NOTEQUALS
};
struct constraint
{
int type;
const char* left;
const char* right;
struct constraint* next;
};
struct expr
{
const char* name;
@ -26,7 +41,6 @@ struct terminfo
{
const char* name;
const char* label;
const char* regattr;
};
struct reg
@ -97,8 +111,9 @@ 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 */
ARRAYOF(struct predicate) prefers; /* C predicates */
ARRAYOF(struct predicate) requires; /* C predicates */
ARRAYOF(struct expr) prefers; /* C predicates */
ARRAYOF(struct expr) requires; /* C predicates */
ARRAYOF(struct constraint) constraints; /* register constraints */
struct stringlist code; /* compiler output code strings */
};
extern Rule rule(char* id, Tree pattern, int ern);

View file

@ -43,7 +43,10 @@ static int braces = 0;
"emit" return EMIT;
"fragment" return FRAGMENT;
"prefers" return PREFERS;
"requires" return REQUIRES;
"when" return WHEN;
"with" return WITH;
"==" return EQUALS;
"!=" return NOTEQUALS;
"//"[^\n]*\n ;