From 4a3a9a98dc30aace079c64b78d476dfed54c7b58 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 1 Oct 2016 12:17:14 +0200 Subject: [PATCH] It doesn't really make a lot of sense to have BURG nonterminal names different to register classes, so combine them. Refactor the map code. --- mach/proto/mcg/mcg.h | 2 +- mach/proto/mcg/pass_convertstackops.c | 4 +- mach/proto/mcg/table | 160 +++++++++++++------------- modules/src/data/imap.c | 16 +++ modules/src/data/imap.h | 1 + modules/src/data/map.h | 30 ----- modules/src/data/{map.c => pmap.c} | 36 ++++-- modules/src/data/pmap.h | 31 +++++ modules/src/data/smap.c | 74 ++++++++++++ modules/src/data/smap.h | 31 +++++ util/mcgg/gram.y | 18 +-- util/mcgg/iburg.c | 107 +++++++++-------- util/mcgg/iburg.h | 15 ++- 13 files changed, 331 insertions(+), 194 deletions(-) delete mode 100644 modules/src/data/map.h rename modules/src/data/{map.c => pmap.c} (52%) create mode 100644 modules/src/data/pmap.h create mode 100644 modules/src/data/smap.c create mode 100644 modules/src/data/smap.h diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 176efb535..277bc6cf4 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -17,7 +17,7 @@ #include "em_flag.h" #include "em_ptyp.h" #include "array.h" -#include "map.h" +#include "pmap.h" #include "diagnostics.h" #include "astring.h" #include "ir.h" diff --git a/mach/proto/mcg/pass_convertstackops.c b/mach/proto/mcg/pass_convertstackops.c index 6f62fe747..285ca1626 100644 --- a/mach/proto/mcg/pass_convertstackops.c +++ b/mach/proto/mcg/pass_convertstackops.c @@ -1,6 +1,6 @@ #include "mcg.h" -static MAPOF(struct basicblock, struct basicblock) graph; +static PMAPOF(struct basicblock, struct basicblock) graph; static ARRAYOF(struct ir) pops; static ARRAYOF(struct ir) pushes; @@ -46,7 +46,7 @@ static bool collect_outputs_cb(struct ir* ir, void* user) struct basicblock* caller = user; if (ir->opcode == IR_BLOCK) - map_addp(&graph, caller, ir->u.bvalue); + pmap_add(&graph, caller, ir->u.bvalue); return false; } diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index eac421ddf..31e51cdb7 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -1,96 +1,102 @@ REGISTERS - r0 reg4 i ret0; - r1 reg4 i; - r2 reg4 i; - r3 reg4 i; - r4 reg4 i; - r5 reg4 i; - r6 reg4 i; - r7 reg4 i; - r8 reg4 i; - r9 reg4 i; - r10 reg4 i; - r11 reg4 i; + r0 any int ret; + r1 any int; + r2 any int; + r3 any int; + r4 any int; + r5 any int; + r6 any int; + r7 any int; + r8 any int; + r9 any int; + r10 any int; + r11 any int; - s0 reg4 f; - s1 reg4 f; - s2 reg4 f; - s3 reg4 f; - s4 reg4 f; - s5 reg4 f; - s6 reg4 f; - s7 reg4 f; - s8 reg4 f; - s9 reg4 f; + s0 any float; + s1 any float; + s2 any float; + s3 any float; + s4 any float; + s5 any float; + s6 any float; + s7 any float; + s8 any float; + s9 any float; + + cc cc; - cc conditioncode; DECLARATIONS address fragment; aluparam fragment; - reg allocates(reg4); - tristate allocates(conditioncode); - bistate allocates(conditioncode); + PATTERNS /* Special */ - reg; - - reg = REG4; + int; + float; PAIR(BLOCK4, BLOCK4); /* Miscellaneous special things */ - PUSH4(in:reg) + PUSH4(in:int) emit "push %in" cost 4; - reg = POP4 - emit "pop %reg" + int = POP4 + emit "pop %int" cost 4; RET emit "ret" cost 4; - SETRET4(in:reg) + SETRET4(in:ret) emit "mov r0, %in" cost 4; + int = REG4 cost 1; + float = REG4 cost 1; + + any = int cost 1; + int = any cost 1; + any = float cost 1; + float = any cost 1; + /* Memory operations */ - STORE4(addr:address, value:reg) + STORE4(addr:address, value:int) emit "str %value, %addr" cost 4; - reg = LOAD4(addr:address) - emit "ldr %reg, %addr" + int = LOAD4(addr:address) + emit "ldr %int, %addr" cost 4; - reg = LOAD1(addr:address) - emit "ldrb %reg, %addr" + int = LOAD1(addr:address) + emit "ldrb %int, %addr" cost 4; - reg = CIU14(LOAD1(addr:address)) - emit "ldrb %reg, %addr" + int = CIU14(LOAD1(addr:address)) + emit "ldrb %int, %addr" cost 4; - reg = CII14(CIU41(CIU14(LOAD1(addr:address)))) - emit "ldrsb %reg, %addr" + int = CII14(CIU41(CIU14(LOAD1(addr:address)))) + emit "ldrsb %int, %addr" cost 4; /* Locals */ - reg = in:LOCAL4 - emit "add %reg, fp, #$in" + int = in:LOCAL4 + emit "add %int, fp, #$in" cost 4; address = in:LOCAL4 @@ -99,10 +105,10 @@ PATTERNS /* Memory addressing modes */ - address = ADD4(addr:reg, offset:CONST4) + address = ADD4(addr:int, offset:CONST4) emit "[%addr, #$offset]"; - address = addr:reg + address = addr:int emit "[%addr]"; @@ -112,12 +118,7 @@ PATTERNS emit "b $addr" cost 4; - CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4)) - emit "beq $true" - emit "b $false" - cost 8; - - CJUMPEQ(value:bistate, PAIR(true:BLOCK4, false:BLOCK4)) + CJUMPEQ(value:cc, PAIR(true:BLOCK4, false:BLOCK4)) emit "beq $true" emit "b $false" cost 8; @@ -125,72 +126,67 @@ PATTERNS /* Comparisons */ - tristate = COMPARES4(left:reg, right:aluparam) + cc = COMPARES4(left:int, right:aluparam) emit "cmp %left, %right" cost 4; - bistate = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4) + cc = COMPARES4(COMPARES4(left:int, right:aluparam), CONST4) emit "cmp %left, %right" cost 4; - reg = tristate - emit "mov %reg, #0" - emit "movlt %reg, #-1" - emit "movgt %reg, #1" + int = cc + emit "mov %int, #0" + emit "movlt %int, #-1" + emit "movgt %int, #1" cost 12; - reg = bistate - emit "moveq %reg, #1" - emit "movne %reg, #0" - cost 8; - /* Conversions */ - reg = CII14(CIU41(value:reg)) - emit "sxtb %reg, %value" + int = CII14(CIU41(value:int)) + emit "sxtb %int, %value" cost 4; - reg = CIU41(in:reg) - emit "and %reg, %in, #0xff" + int = CIU41(in:int) + emit "and %int, %in, #0xff" cost 4; /* ALU operations */ - reg = ADD4(left:reg, right:aluparam) - emit "add %reg, %left, %right" + int = ADD4(left:int, right:aluparam) + emit "add %int, %left, %right" cost 4; - reg = ADD4(left:aluparam, right:reg) - emit "add %reg, %right, %left" + int = ADD4(left:aluparam, right:int) + emit "add %int, %right, %left" cost 4; aluparam = value:CONST4 emit "#$value"; - aluparam = value:reg + aluparam = value:int emit "%value"; - reg = value:aluparam - emit "mov %reg, %value" + int = value:aluparam + emit "mov %int, %value" cost 4; - reg = value:LABEL4 - emit "adr %reg, $value" + int = value:LABEL4 + emit "adr %int, $value" cost 4; - reg = value:BLOCK4 - emit "adr %reg, $value" + int = value:BLOCK4 + emit "adr %int, $value" cost 4; - reg = value:CONST4 - emit "ldr %reg, #$value" + any = value:CONST4 + emit "ldr %any, address-containing-$value" cost 8; /* FPU operations */ - reg = ADDF4(left:reg, right:reg) - emit "fadds %reg, %left, %right" + float = ADDF4(left:float, right:float) + emit "fadds %float, %left, %right" cost 4; diff --git a/modules/src/data/imap.c b/modules/src/data/imap.c index 15c66e769..81982a704 100644 --- a/modules/src/data/imap.c +++ b/modules/src/data/imap.c @@ -56,3 +56,19 @@ void imap_add(void* mapp, int left, void* right) append(map, left, right); } +void* imap_get(void* mapp, int left) +{ + struct imap* map = mapp; + int i; + + for (i=0; icount; i++) + { + struct imap_node* node = &map->item[i]; + if (node->left == left) + return node->right; + } + + return NULL; +} + + diff --git a/modules/src/data/imap.h b/modules/src/data/imap.h index 022368ec8..cb312e16c 100644 --- a/modules/src/data/imap.h +++ b/modules/src/data/imap.h @@ -25,6 +25,7 @@ struct imap extern void imap_put(void* map, int left, void* right); extern void imap_add(void* map, int left, void* right); +extern void* imap_get(void* map, int left); #endif diff --git a/modules/src/data/map.h b/modules/src/data/map.h deleted file mode 100644 index 859618bd7..000000000 --- a/modules/src/data/map.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef MAP_H -#define MAP_H - -struct map_node -{ - void* left; - void* right; -}; - -/* Danger, Will Robinson! The type and the macro must be compatible. */ - -struct map -{ - struct map_node* item; - int count; - int max; -}; - -#define MAPOF(LEFT, RIGHT) \ - struct { \ - struct { LEFT* left; RIGHT* right; }* item; \ - int count; \ - int max; \ - } - -extern void map_putp(void* map, void* left, void* right); -extern void map_addp(void* map, void* left, void* right); - -#endif - diff --git a/modules/src/data/map.c b/modules/src/data/pmap.c similarity index 52% rename from modules/src/data/map.c rename to modules/src/data/pmap.c index d75284762..9ed2d9fed 100644 --- a/modules/src/data/map.c +++ b/modules/src/data/pmap.c @@ -1,16 +1,16 @@ #include #include -#include "map.h" +#include "pmap.h" static void append(void* mapp, void* left, void* right) { - struct map* map = mapp; - struct map_node* node; + struct pmap* map = mapp; + struct pmap_node* node; if (map->count == map->max) { int newmax = (map->max == 0) ? 8 : (map->max * 2); - struct map_node* newarray = realloc(map->item, newmax * sizeof(*newarray)); + struct pmap_node* newarray = realloc(map->item, newmax * sizeof(*newarray)); map->max = newmax; map->item = newarray; @@ -23,14 +23,14 @@ static void append(void* mapp, void* left, void* right) node->right = right; } -void map_putp(void* mapp, void* left, void* right) +void pmap_put(void* mapp, void* left, void* right) { - struct map* map = mapp; + struct pmap* map = mapp; int i; for (i=0; icount; i++) { - struct map_node* node = &map->item[i]; + struct pmap_node* node = &map->item[i]; if (node->left == left) { node->right = right; @@ -41,14 +41,14 @@ void map_putp(void* mapp, void* left, void* right) append(map, left, right); } -void map_addp(void* mapp, void* left, void* right) +void pmap_add(void* mapp, void* left, void* right) { - struct map* map = mapp; + struct pmap* map = mapp; int i; for (i=0; icount; i++) { - struct map_node* node = &map->item[i]; + struct pmap_node* node = &map->item[i]; if ((node->left == left) && (node->right == right)) return; } @@ -56,3 +56,19 @@ void map_addp(void* mapp, void* left, void* right) append(map, left, right); } +void* pmap_get(void* mapp, void* left) +{ + struct pmap* map = mapp; + int i; + + for (i=0; icount; i++) + { + struct pmap_node* node = &map->item[i]; + if (node->left == left) + return node->right; + } + + return NULL; +} + + diff --git a/modules/src/data/pmap.h b/modules/src/data/pmap.h new file mode 100644 index 000000000..19986fc12 --- /dev/null +++ b/modules/src/data/pmap.h @@ -0,0 +1,31 @@ +#ifndef PMAP_H +#define PMAP_H + +struct pmap_node +{ + void* left; + void* right; +}; + +/* Danger, Will Robinson! The type and the macro must be compatible. */ + +struct pmap +{ + struct pmap_node* item; + int count; + int max; +}; + +#define PMAPOF(LEFT, RIGHT) \ + struct { \ + struct { LEFT* left; RIGHT* right; }* item; \ + int count; \ + int max; \ + } + +extern void pmap_put(void* map, void* left, void* right); +extern void pmap_add(void* map, void* left, void* right); +extern void* pmap_get(void* map, void* left); + +#endif + diff --git a/modules/src/data/smap.c b/modules/src/data/smap.c new file mode 100644 index 000000000..312241a20 --- /dev/null +++ b/modules/src/data/smap.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include "smap.h" + +static void append(void* mapp, const char* left, void* right) +{ + struct smap* map = mapp; + struct smap_node* node; + + if (map->count == map->max) + { + int newmax = (map->max == 0) ? 8 : (map->max * 2); + struct smap_node* newarray = realloc(map->item, newmax * sizeof(*newarray)); + + map->max = newmax; + map->item = newarray; + } + + node = &map->item[map->count]; + map->count++; + + node->left = left; + node->right = right; +} + +void smap_put(void* mapp, const char* left, void* right) +{ + struct smap* map = mapp; + int i; + + for (i=0; icount; i++) + { + struct smap_node* node = &map->item[i]; + if (strcmp(node->left, left) == 0) + { + node->right = right; + return; + } + } + + append(map, left, right); +} + +void smap_add(void* mapp, const char* left, void* right) +{ + struct smap* map = mapp; + int i; + + for (i=0; icount; i++) + { + struct smap_node* node = &map->item[i]; + if ((strcmp(node->left, left) == 0) && (node->right == right)) + return; + } + + append(map, left, right); +} + +void* smap_get(void* mapp, const char* left) +{ + struct smap* map = mapp; + int i; + + for (i=0; icount; i++) + { + struct smap_node* node = &map->item[i]; + if (strcmp(node->left, left) == 0) + return node->right; + } + + return NULL; +} + diff --git a/modules/src/data/smap.h b/modules/src/data/smap.h new file mode 100644 index 000000000..7ccdb51de --- /dev/null +++ b/modules/src/data/smap.h @@ -0,0 +1,31 @@ +#ifndef SMAP_H +#define SMAP_H + +struct smap_node +{ + const char* left; + void* right; +}; + +/* Danger, Will Robinson! The type and the macro must be compatible. */ + +struct smap +{ + struct smap_node* item; + int count; + int max; +}; + +#define SMAPOF(RIGHT) \ + struct { \ + struct { const char* left; RIGHT* right; }* item; \ + int count; \ + int max; \ + } + +extern void smap_put(void* map, const char* left, void* right); +extern void smap_add(void* map, const char* left, void* right); +extern void* smap_get(void* map, const char* left); + +#endif + diff --git a/util/mcgg/gram.y b/util/mcgg/gram.y index 26a0e9b5b..94b188398 100644 --- a/util/mcgg/gram.y +++ b/util/mcgg/gram.y @@ -22,7 +22,7 @@ static int nextern = 1; Rule rule; struct reg* reg; struct stringlist* stringlist; - char* stringpair[2]; + struct terminfo terminfo; } %term ALLOCATES @@ -48,7 +48,7 @@ static int nextern = 1; %type pattern %type cfragments %type qfragments -%type labelledid +%type terminfo %type rhs %% @@ -106,14 +106,16 @@ pattern ; rhs - : labelledid { $$ = tree($1[1], $1[0], NULL, NULL); } - | labelledid '(' rhs ')' { $$ = tree($1[1], $1[0], $3, NULL); } - | labelledid '(' rhs ',' rhs ')' { $$ = tree($1[1], $1[0], $3, $5); } + : terminfo { $$ = tree(&$1, NULL, NULL); } + | terminfo '(' rhs ')' { $$ = tree(&$1, $3, NULL); } + | terminfo '(' rhs ',' rhs ')' { $$ = tree(&$1, $3, $5); } ; -labelledid - : ID { $$[0] = NULL; $$[1] = $1; } - | ID ':' ID { $$[0] = $1; $$[1] = $3; } +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; } ; cfragments diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index aeb68ae31..70d4ab080 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -9,9 +9,11 @@ #include #include #include +#include #include "iburg.h" #include "ircodes.h" #include "astring.h" +#include "smap.h" static char rcsid[] = "$Id$"; @@ -21,13 +23,14 @@ static char* prefix = "burm"; static int Tflag = 1; /* tracing */ static int ntnumber = 0; static Nonterm start = 0; -static struct reg* regs = NULL; -static struct regclass* regclasses = NULL; static Term terms; static Nonterm nts; static Rule rules; static int nrules; +static SMAPOF(struct reg) registers; +static SMAPOF(struct regclass) registerclasses; + static void print(char* fmt, ...); static void ckreach(Nonterm p); static void registerterminals(void); @@ -44,8 +47,8 @@ static void emitleaf(Term p, int ntnumber); static void emitnts(Rule rules, int nrules); static void emitpredicatedefinitions(Rule rules); static void emitrecord(char* pre, Rule r, int cost); -static void emitregisterclasses(struct regclass* rc); -static void emitregisters(struct reg* regs); +static void emitregisterclasses(); +static void emitregisters(); static void emitrule(Nonterm nts); static void emitstate(Term terms, Nonterm start, int ntnumber); static void emitstring(Rule rules); @@ -128,12 +131,14 @@ int main(int argc, char* argv[]) if (start) ckreach(start); + #if 0 for (p = nts; p; p = p->link) if (!p->reached) yyerror("can't reach non-terminal `%s'\n", p->name); + #endif - emitregisterclasses(regclasses); - emitregisters(regs); + emitregisterclasses(); + emitregisters(); emitdefs(nts, ntnumber); emitstruct(nts, ntnumber); emitnts(rules, nrules); @@ -230,52 +235,40 @@ static void* install(const char* name) struct reg* makereg(const char* id) { - struct reg* p = lookup(id); - struct reg** q = ®s; + struct reg* p = smap_get(®isters, id); static int number = 1; if (p) yyerror("redefinition of '%s'", id); - p = install(id); - p->kind = REG; + p = calloc(1, sizeof(*p)); + p->name = id; p->number = number++; + smap_put(®isters, id, p); - while (*q && (*q)->number < p->number) - q = &(*q)->link; - assert(*q == 0 || (*q)->number != p->number); - p->link = *q; - *q = p; return p; } void addregclass(struct reg* reg, const char* id) { - struct regclass* p = lookup(id); - struct regclass** q = ®classes; + struct regclass* p = smap_get(®isterclasses, id); static int number = 1; - if (p && (p->kind != REGCLASS)) - yyerror("redefinition of '%s' as something else\n", id); if (!p) { - p = install(id); - p->kind = REGCLASS; + p = calloc(1, sizeof(*p)); + p->name = id; p->number = number++; - - while (*q && (*q)->number < p->number) - q = &(*q)->link; - assert(*q == 0 || (*q)->number != p->number); - p->link = *q; - *q = p; + smap_put(®isterclasses, id, p); } reg->classes |= 1<<(p->number); + nonterm(id, true); } struct regclass* getregclass(const char* id) { - struct regclass* p = lookup(id); - if (!p || (p->kind != REGCLASS)) + struct regclass* p = smap_get(®isterclasses, id); + if (!p) yyerror("'%s' is not the name of a register class", id); return p; } @@ -333,10 +326,10 @@ Term term(const char* id, int esn) } /* tree - create & initialize a tree node with the given fields */ -Tree tree(const char* id, const char* label, Tree left, Tree right) +Tree tree(struct terminfo* ti, Tree left, Tree right) { Tree t = calloc(1, sizeof *t); - Term p = lookup(id); + Term p = lookup(ti->name); int arity = 0; if (left && right) @@ -345,22 +338,22 @@ Tree tree(const char* id, const char* label, Tree left, Tree right) arity = 1; if (p == NULL && arity > 0) { - yyerror("undefined terminal `%s'\n", id); - p = term(id, -1); + yyerror("undefined terminal `%s'\n", ti->name); + p = term(ti->name, -1); } else if (p == NULL && arity == 0) - p = (Term)nonterm(id, false); + p = (Term)nonterm(ti->name, false); else if (p && p->kind == NONTERM && arity > 0) { - yyerror("`%s' is a non-terminal\n", id); - p = term(id, -1); + yyerror("`%s' is a non-terminal\n", ti->name); + p = term(ti->name, -1); } if (p->kind == TERM && p->arity == -1) p->arity = arity; if (p->kind == TERM && arity != p->arity) - yyerror("inconsistent arity for terminal `%s'\n", id); + yyerror("inconsistent arity for terminal `%s'\n", ti->name); t->op = p; - t->label = label; + t->label = ti->label; t->nterms = p->kind == TERM; if (t->left = left) t->nterms += left->nterms; @@ -423,6 +416,10 @@ static void print(char* fmt, ...) fprintf(outfp, "%x", va_arg(ap, uint32_t)); break; + case 'X': + fprintf(outfp, "0x%" PRIx64 "ULL", va_arg(ap, uint64_t)); + break; + case 's': fputs(va_arg(ap, char*), outfp); break; @@ -503,34 +500,34 @@ static void ckreach(Nonterm p) reach(r->pattern); } -static void emitregisterclasses(struct regclass* rc) +static void emitregisterclasses(void) { - int k = 0; + int i; + print("const char* %Pregister_class_names[] = {\n"); - while (rc) + print("%1NULL,\n"); /* register class id 0 is invalid */ + for (i=0; inumber; k++) - print("%1NULL,\n"); - k++; + struct regclass* rc = registerclasses.item[i].right; + assert(rc->number == (i+1)); print("%1\"%s\",\n", rc->name); - rc = rc->link; } print("};\n\n"); } -static void emitregisters(struct reg* r) +static void emitregisters(void) { - int k = 0; - print("const struct %Pregister_data %Pregister_data[] = {\n"); - while (r) - { - for (; k < r->number; k++) - print("%1{ 0 },\n"); - k++; + int i; - print("%1{ \"%s\", %d },\n", r->name, r->classes); - r = r->link; + print("const struct %Pregister_data %Pregister_data[] = {\n"); + print("%1{ 0 },\n"); /* register id 0 is invalid */ + for (i=0; inumber == (i+1)); + + print("%1{ \"%s\", %X },\n", r->name, r->classes); } print("};\n\n"); } diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 7bf8b8a0e..1a4211e91 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -15,21 +15,24 @@ typedef enum typedef struct rule* Rule; typedef struct term* Term; +struct terminfo +{ + const char* name; + const char* label; + const char* regattr; +}; + struct reg { const char* name; /* register name */ - Kind kind; /* REG */ int number; /* identifying number */ - uint32_t classes; // bitfield of classes */ - struct reg* link; /* next in list */ + uint64_t classes; // bitfield of classes */ }; struct regclass { const char* name; /* class name */ - Kind kind; /* REGCLASS */ int number; /* identifying number */ - struct regclass* link; /* next in list */ }; extern struct reg* makereg(const char* name); @@ -72,7 +75,7 @@ struct tree Tree left, right; /* operands */ int nterms; /* number of terminal nodes in this tree */ }; -extern Tree tree(const char* op, const char* label, Tree left, Tree right); +extern Tree tree(struct terminfo* ti, Tree left, Tree right); struct rule { /* rules: */