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

View file

@ -24,28 +24,34 @@ static int nextern = 1;
struct stringlist* stringlist; struct stringlist* stringlist;
struct terminfo terminfo; struct terminfo terminfo;
struct expr* expr; struct expr* expr;
struct constraint* constraint;
} }
%term ALLOCATES %term ALLOCATES
%term COST %term COST
%term DECLARATIONS %term DECLARATIONS
%term EMIT %term EMIT
%term EQUALS
%term FRAGMENT %term FRAGMENT
%term NOTEQUALS
%term PATTERNS %term PATTERNS
%term REGISTERS
%term PREFERS %term PREFERS
%term REQUIRES %term REGISTERS
%term WHEN
%term WITH
%token <n> INT %token <n> INT
%token <string> ID %token <string> ID
%token <string> QFRAGMENT %token <string> QFRAGMENT
%type <nonterm> allocates %type <nonterm> allocates
%type <constraint> constraint
%type <constraint> constraints
%type <nonterm> declaration %type <nonterm> declaration
%type <reg> register %type <reg> register
%type <rule> emit %type <rule> pattern_constraints
%type <rule> pattern_emit
%type <rule> pattern %type <rule> pattern
%type <stringlist> cfragments
%type <stringlist> qfragments %type <stringlist> qfragments
%type <terminfo> terminfo %type <terminfo> terminfo
%type <tree> rhs %type <tree> rhs
@ -102,9 +108,10 @@ 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 PREFERS predicate { $$ = $1; array_append(&$$->prefers, $3); } | pattern PREFERS predicate { $$ = $1; array_append(&$$->prefers, $3); }
| pattern REQUIRES predicate { $$ = $1; array_append(&$$->requires, $3); } | pattern WHEN predicate { $$ = $1; array_append(&$$->requires, $3); }
| emit { $$ = $1; }
| pattern COST INT { $$ = $1; $$->cost = $3; } | pattern COST INT { $$ = $1; $$->cost = $3; }
| pattern_constraints { $$ = $1; }
| pattern_emit { $$ = $1; }
; ;
rhs rhs
@ -115,12 +122,10 @@ rhs
terminfo terminfo
: ID { $$.name = $1; } : ID { $$.name = $1; }
| ID '.' ID { $$.name = $1; $$.regattr = $3; }
| ID ':' ID { $$.label = $1; $$.name = $3; } | ID ':' ID { $$.label = $1; $$.name = $3; }
| ID ':' ID '.' ID { $$.label = $1; $$.name = $3; $$.regattr = $5; }
; ;
emit pattern_emit
: pattern EMIT qfragments { : pattern EMIT qfragments {
$$ = $1; $$ = $1;
if (!$$->lhs->is_fragment) 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 qfragments
: /* nothing */ { $$ = calloc(1, sizeof *$$); } : /* nothing */ { $$ = calloc(1, sizeof *$$); }
| qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); } | qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); }
@ -139,7 +171,7 @@ predicate
; ;
predicate_args predicate_args
: /* nothing */ : /* nothing */ { $$ = NULL; }
| ID { $$ = calloc(1, sizeof *$$); $$->name = $1; } | ID { $$ = calloc(1, sizeof *$$); $$->name = $1; }
| ID ',' predicate_args { $$ = calloc(1, sizeof *$$); $$->name = $1; $$->next = $3; } | 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); reg->classes |= 1<<(p->number);
nonterm(id, true);
} }
struct regclass* getregclass(const char* id) struct regclass* getregclass(const char* id)

View file

@ -16,6 +16,21 @@ typedef enum
typedef struct rule* Rule; typedef struct rule* Rule;
typedef struct term* Term; 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 struct expr
{ {
const char* name; const char* name;
@ -26,7 +41,6 @@ struct terminfo
{ {
const char* name; const char* name;
const char* label; const char* label;
const char* regattr;
}; };
struct reg struct reg
@ -97,8 +111,9 @@ 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 */
ARRAYOF(struct predicate) prefers; /* C predicates */ ARRAYOF(struct expr) prefers; /* C predicates */
ARRAYOF(struct predicate) requires; /* C predicates */ ARRAYOF(struct expr) requires; /* C predicates */
ARRAYOF(struct constraint) constraints; /* register constraints */
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

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