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.
This commit is contained in:
David Given 2016-10-01 12:17:14 +02:00
parent 3a973a19f3
commit 4a3a9a98dc
13 changed files with 331 additions and 194 deletions

View file

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

View file

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

View file

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

View file

@ -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; i<map->count; i++)
{
struct imap_node* node = &map->item[i];
if (node->left == left)
return node->right;
}
return NULL;
}

View file

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

View file

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

View file

@ -1,16 +1,16 @@
#include <stdlib.h>
#include <stdbool.h>
#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; i<map->count; 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; i<map->count; 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; i<map->count; i++)
{
struct pmap_node* node = &map->item[i];
if (node->left == left)
return node->right;
}
return NULL;
}

31
modules/src/data/pmap.h Normal file
View file

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

74
modules/src/data/smap.c Normal file
View file

@ -0,0 +1,74 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#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; i<map->count; 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; i<map->count; 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; i<map->count; i++)
{
struct smap_node* node = &map->item[i];
if (strcmp(node->left, left) == 0)
return node->right;
}
return NULL;
}

31
modules/src/data/smap.h Normal file
View file

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

View file

@ -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 <rule> pattern
%type <stringlist> cfragments
%type <stringlist> qfragments
%type <stringpair> labelledid
%type <terminfo> terminfo
%type <tree> 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

View file

@ -9,9 +9,11 @@
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <inttypes.h>
#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 = &regs;
struct reg* p = smap_get(&registers, 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(&registers, 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 = &regclasses;
struct regclass* p = smap_get(&registerclasses, 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(&registerclasses, 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(&registerclasses, 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; i<registerclasses.count; i++)
{
for (; k < rc->number; 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; i<registers.count; i++)
{
struct reg* r = registers.item[i].right;
assert(r->number == (i+1));
print("%1{ \"%s\", %X },\n", r->name, r->classes);
}
print("};\n\n");
}

View file

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