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:
parent
3a973a19f3
commit
4a3a9a98dc
|
@ -17,7 +17,7 @@
|
||||||
#include "em_flag.h"
|
#include "em_flag.h"
|
||||||
#include "em_ptyp.h"
|
#include "em_ptyp.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "map.h"
|
#include "pmap.h"
|
||||||
#include "diagnostics.h"
|
#include "diagnostics.h"
|
||||||
#include "astring.h"
|
#include "astring.h"
|
||||||
#include "ir.h"
|
#include "ir.h"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "mcg.h"
|
#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) pops;
|
||||||
static ARRAYOF(struct ir) pushes;
|
static ARRAYOF(struct ir) pushes;
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ static bool collect_outputs_cb(struct ir* ir, void* user)
|
||||||
struct basicblock* caller = user;
|
struct basicblock* caller = user;
|
||||||
|
|
||||||
if (ir->opcode == IR_BLOCK)
|
if (ir->opcode == IR_BLOCK)
|
||||||
map_addp(&graph, caller, ir->u.bvalue);
|
pmap_add(&graph, caller, ir->u.bvalue);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,96 +1,102 @@
|
||||||
REGISTERS
|
REGISTERS
|
||||||
|
|
||||||
r0 reg4 i ret0;
|
r0 any int ret;
|
||||||
r1 reg4 i;
|
r1 any int;
|
||||||
r2 reg4 i;
|
r2 any int;
|
||||||
r3 reg4 i;
|
r3 any int;
|
||||||
r4 reg4 i;
|
r4 any int;
|
||||||
r5 reg4 i;
|
r5 any int;
|
||||||
r6 reg4 i;
|
r6 any int;
|
||||||
r7 reg4 i;
|
r7 any int;
|
||||||
r8 reg4 i;
|
r8 any int;
|
||||||
r9 reg4 i;
|
r9 any int;
|
||||||
r10 reg4 i;
|
r10 any int;
|
||||||
r11 reg4 i;
|
r11 any int;
|
||||||
|
|
||||||
s0 reg4 f;
|
s0 any float;
|
||||||
s1 reg4 f;
|
s1 any float;
|
||||||
s2 reg4 f;
|
s2 any float;
|
||||||
s3 reg4 f;
|
s3 any float;
|
||||||
s4 reg4 f;
|
s4 any float;
|
||||||
s5 reg4 f;
|
s5 any float;
|
||||||
s6 reg4 f;
|
s6 any float;
|
||||||
s7 reg4 f;
|
s7 any float;
|
||||||
s8 reg4 f;
|
s8 any float;
|
||||||
s9 reg4 f;
|
s9 any float;
|
||||||
|
|
||||||
|
cc cc;
|
||||||
|
|
||||||
cc conditioncode;
|
|
||||||
|
|
||||||
DECLARATIONS
|
DECLARATIONS
|
||||||
|
|
||||||
address fragment;
|
address fragment;
|
||||||
aluparam fragment;
|
aluparam fragment;
|
||||||
reg allocates(reg4);
|
|
||||||
tristate allocates(conditioncode);
|
|
||||||
bistate allocates(conditioncode);
|
|
||||||
|
|
||||||
PATTERNS
|
PATTERNS
|
||||||
|
|
||||||
/* Special */
|
/* Special */
|
||||||
|
|
||||||
reg;
|
int;
|
||||||
|
float;
|
||||||
reg = REG4;
|
|
||||||
|
|
||||||
PAIR(BLOCK4, BLOCK4);
|
PAIR(BLOCK4, BLOCK4);
|
||||||
|
|
||||||
|
|
||||||
/* Miscellaneous special things */
|
/* Miscellaneous special things */
|
||||||
|
|
||||||
PUSH4(in:reg)
|
PUSH4(in:int)
|
||||||
emit "push %in"
|
emit "push %in"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = POP4
|
int = POP4
|
||||||
emit "pop %reg"
|
emit "pop %int"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
RET
|
RET
|
||||||
emit "ret"
|
emit "ret"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
SETRET4(in:reg)
|
SETRET4(in:ret)
|
||||||
emit "mov r0, %in"
|
emit "mov r0, %in"
|
||||||
cost 4;
|
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 */
|
/* Memory operations */
|
||||||
|
|
||||||
STORE4(addr:address, value:reg)
|
STORE4(addr:address, value:int)
|
||||||
emit "str %value, %addr"
|
emit "str %value, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = LOAD4(addr:address)
|
int = LOAD4(addr:address)
|
||||||
emit "ldr %reg, %addr"
|
emit "ldr %int, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = LOAD1(addr:address)
|
int = LOAD1(addr:address)
|
||||||
emit "ldrb %reg, %addr"
|
emit "ldrb %int, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CIU14(LOAD1(addr:address))
|
int = CIU14(LOAD1(addr:address))
|
||||||
emit "ldrb %reg, %addr"
|
emit "ldrb %int, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CII14(CIU41(CIU14(LOAD1(addr:address))))
|
int = CII14(CIU41(CIU14(LOAD1(addr:address))))
|
||||||
emit "ldrsb %reg, %addr"
|
emit "ldrsb %int, %addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
||||||
/* Locals */
|
/* Locals */
|
||||||
|
|
||||||
reg = in:LOCAL4
|
int = in:LOCAL4
|
||||||
emit "add %reg, fp, #$in"
|
emit "add %int, fp, #$in"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
address = in:LOCAL4
|
address = in:LOCAL4
|
||||||
|
@ -99,10 +105,10 @@ PATTERNS
|
||||||
|
|
||||||
/* Memory addressing modes */
|
/* Memory addressing modes */
|
||||||
|
|
||||||
address = ADD4(addr:reg, offset:CONST4)
|
address = ADD4(addr:int, offset:CONST4)
|
||||||
emit "[%addr, #$offset]";
|
emit "[%addr, #$offset]";
|
||||||
|
|
||||||
address = addr:reg
|
address = addr:int
|
||||||
emit "[%addr]";
|
emit "[%addr]";
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,12 +118,7 @@ PATTERNS
|
||||||
emit "b $addr"
|
emit "b $addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
CJUMPEQ(value:tristate, PAIR(true:BLOCK4, false:BLOCK4))
|
CJUMPEQ(value:cc, PAIR(true:BLOCK4, false:BLOCK4))
|
||||||
emit "beq $true"
|
|
||||||
emit "b $false"
|
|
||||||
cost 8;
|
|
||||||
|
|
||||||
CJUMPEQ(value:bistate, PAIR(true:BLOCK4, false:BLOCK4))
|
|
||||||
emit "beq $true"
|
emit "beq $true"
|
||||||
emit "b $false"
|
emit "b $false"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
@ -125,72 +126,67 @@ PATTERNS
|
||||||
|
|
||||||
/* Comparisons */
|
/* Comparisons */
|
||||||
|
|
||||||
tristate = COMPARES4(left:reg, right:aluparam)
|
cc = COMPARES4(left:int, right:aluparam)
|
||||||
emit "cmp %left, %right"
|
emit "cmp %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
bistate = COMPARES4(COMPARES4(left:reg, right:aluparam), CONST4)
|
cc = COMPARES4(COMPARES4(left:int, right:aluparam), CONST4)
|
||||||
emit "cmp %left, %right"
|
emit "cmp %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = tristate
|
int = cc
|
||||||
emit "mov %reg, #0"
|
emit "mov %int, #0"
|
||||||
emit "movlt %reg, #-1"
|
emit "movlt %int, #-1"
|
||||||
emit "movgt %reg, #1"
|
emit "movgt %int, #1"
|
||||||
cost 12;
|
cost 12;
|
||||||
|
|
||||||
reg = bistate
|
|
||||||
emit "moveq %reg, #1"
|
|
||||||
emit "movne %reg, #0"
|
|
||||||
cost 8;
|
|
||||||
|
|
||||||
|
|
||||||
/* Conversions */
|
/* Conversions */
|
||||||
|
|
||||||
reg = CII14(CIU41(value:reg))
|
int = CII14(CIU41(value:int))
|
||||||
emit "sxtb %reg, %value"
|
emit "sxtb %int, %value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = CIU41(in:reg)
|
int = CIU41(in:int)
|
||||||
emit "and %reg, %in, #0xff"
|
emit "and %int, %in, #0xff"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
||||||
/* ALU operations */
|
/* ALU operations */
|
||||||
|
|
||||||
reg = ADD4(left:reg, right:aluparam)
|
int = ADD4(left:int, right:aluparam)
|
||||||
emit "add %reg, %left, %right"
|
emit "add %int, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = ADD4(left:aluparam, right:reg)
|
int = ADD4(left:aluparam, right:int)
|
||||||
emit "add %reg, %right, %left"
|
emit "add %int, %right, %left"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
aluparam = value:CONST4
|
aluparam = value:CONST4
|
||||||
emit "#$value";
|
emit "#$value";
|
||||||
|
|
||||||
aluparam = value:reg
|
aluparam = value:int
|
||||||
emit "%value";
|
emit "%value";
|
||||||
|
|
||||||
reg = value:aluparam
|
int = value:aluparam
|
||||||
emit "mov %reg, %value"
|
emit "mov %int, %value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:LABEL4
|
int = value:LABEL4
|
||||||
emit "adr %reg, $value"
|
emit "adr %int, $value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:BLOCK4
|
int = value:BLOCK4
|
||||||
emit "adr %reg, $value"
|
emit "adr %int, $value"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
reg = value:CONST4
|
any = value:CONST4
|
||||||
emit "ldr %reg, #$value"
|
emit "ldr %any, address-containing-$value"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
/* FPU operations */
|
/* FPU operations */
|
||||||
|
|
||||||
reg = ADDF4(left:reg, right:reg)
|
float = ADDF4(left:float, right:float)
|
||||||
emit "fadds %reg, %left, %right"
|
emit "fadds %float, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
|
|
@ -56,3 +56,19 @@ void imap_add(void* mapp, int left, void* right)
|
||||||
append(map, left, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct imap
|
||||||
|
|
||||||
extern void imap_put(void* map, int left, void* right);
|
extern void imap_put(void* map, int left, void* right);
|
||||||
extern void imap_add(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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "map.h"
|
#include "pmap.h"
|
||||||
|
|
||||||
static void append(void* mapp, void* left, void* right)
|
static void append(void* mapp, void* left, void* right)
|
||||||
{
|
{
|
||||||
struct map* map = mapp;
|
struct pmap* map = mapp;
|
||||||
struct map_node* node;
|
struct pmap_node* node;
|
||||||
|
|
||||||
if (map->count == map->max)
|
if (map->count == map->max)
|
||||||
{
|
{
|
||||||
int newmax = (map->max == 0) ? 8 : (map->max * 2);
|
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->max = newmax;
|
||||||
map->item = newarray;
|
map->item = newarray;
|
||||||
|
@ -23,14 +23,14 @@ static void append(void* mapp, void* left, void* right)
|
||||||
node->right = 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;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<map->count; 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)
|
if (node->left == left)
|
||||||
{
|
{
|
||||||
node->right = right;
|
node->right = right;
|
||||||
|
@ -41,14 +41,14 @@ void map_putp(void* mapp, void* left, void* right)
|
||||||
append(map, left, 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;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<map->count; 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))
|
if ((node->left == left) && (node->right == right))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -56,3 +56,19 @@ void map_addp(void* mapp, void* left, void* right)
|
||||||
append(map, left, 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
31
modules/src/data/pmap.h
Normal 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
74
modules/src/data/smap.c
Normal 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
31
modules/src/data/smap.h
Normal 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
|
||||||
|
|
|
@ -22,7 +22,7 @@ static int nextern = 1;
|
||||||
Rule rule;
|
Rule rule;
|
||||||
struct reg* reg;
|
struct reg* reg;
|
||||||
struct stringlist* stringlist;
|
struct stringlist* stringlist;
|
||||||
char* stringpair[2];
|
struct terminfo terminfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
%term ALLOCATES
|
%term ALLOCATES
|
||||||
|
@ -48,7 +48,7 @@ static int nextern = 1;
|
||||||
%type <rule> pattern
|
%type <rule> pattern
|
||||||
%type <stringlist> cfragments
|
%type <stringlist> cfragments
|
||||||
%type <stringlist> qfragments
|
%type <stringlist> qfragments
|
||||||
%type <stringpair> labelledid
|
%type <terminfo> terminfo
|
||||||
%type <tree> rhs
|
%type <tree> rhs
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
@ -106,14 +106,16 @@ pattern
|
||||||
;
|
;
|
||||||
|
|
||||||
rhs
|
rhs
|
||||||
: labelledid { $$ = tree($1[1], $1[0], NULL, NULL); }
|
: terminfo { $$ = tree(&$1, NULL, NULL); }
|
||||||
| labelledid '(' rhs ')' { $$ = tree($1[1], $1[0], $3, NULL); }
|
| terminfo '(' rhs ')' { $$ = tree(&$1, $3, NULL); }
|
||||||
| labelledid '(' rhs ',' rhs ')' { $$ = tree($1[1], $1[0], $3, $5); }
|
| terminfo '(' rhs ',' rhs ')' { $$ = tree(&$1, $3, $5); }
|
||||||
;
|
;
|
||||||
|
|
||||||
labelledid
|
terminfo
|
||||||
: ID { $$[0] = NULL; $$[1] = $1; }
|
: ID { $$.name = $1; }
|
||||||
| ID ':' ID { $$[0] = $1; $$[1] = $3; }
|
| ID '.' ID { $$.name = $1; $$.regattr = $3; }
|
||||||
|
| ID ':' ID { $$.label = $1; $$.name = $3; }
|
||||||
|
| ID ':' ID '.' ID { $$.label = $1; $$.name = $3; $$.regattr = $5; }
|
||||||
;
|
;
|
||||||
|
|
||||||
cfragments
|
cfragments
|
||||||
|
|
|
@ -9,9 +9,11 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include "iburg.h"
|
#include "iburg.h"
|
||||||
#include "ircodes.h"
|
#include "ircodes.h"
|
||||||
#include "astring.h"
|
#include "astring.h"
|
||||||
|
#include "smap.h"
|
||||||
|
|
||||||
static char rcsid[] = "$Id$";
|
static char rcsid[] = "$Id$";
|
||||||
|
|
||||||
|
@ -21,13 +23,14 @@ static char* prefix = "burm";
|
||||||
static int Tflag = 1; /* tracing */
|
static int Tflag = 1; /* tracing */
|
||||||
static int ntnumber = 0;
|
static int ntnumber = 0;
|
||||||
static Nonterm start = 0;
|
static Nonterm start = 0;
|
||||||
static struct reg* regs = NULL;
|
|
||||||
static struct regclass* regclasses = NULL;
|
|
||||||
static Term terms;
|
static Term terms;
|
||||||
static Nonterm nts;
|
static Nonterm nts;
|
||||||
static Rule rules;
|
static Rule rules;
|
||||||
static int nrules;
|
static int nrules;
|
||||||
|
|
||||||
|
static SMAPOF(struct reg) registers;
|
||||||
|
static SMAPOF(struct regclass) registerclasses;
|
||||||
|
|
||||||
static void print(char* fmt, ...);
|
static void print(char* fmt, ...);
|
||||||
static void ckreach(Nonterm p);
|
static void ckreach(Nonterm p);
|
||||||
static void registerterminals(void);
|
static void registerterminals(void);
|
||||||
|
@ -44,8 +47,8 @@ static void emitleaf(Term p, int ntnumber);
|
||||||
static void emitnts(Rule rules, int nrules);
|
static void emitnts(Rule rules, int nrules);
|
||||||
static void emitpredicatedefinitions(Rule rules);
|
static void emitpredicatedefinitions(Rule rules);
|
||||||
static void emitrecord(char* pre, Rule r, int cost);
|
static void emitrecord(char* pre, Rule r, int cost);
|
||||||
static void emitregisterclasses(struct regclass* rc);
|
static void emitregisterclasses();
|
||||||
static void emitregisters(struct reg* regs);
|
static void emitregisters();
|
||||||
static void emitrule(Nonterm nts);
|
static void emitrule(Nonterm nts);
|
||||||
static void emitstate(Term terms, Nonterm start, int ntnumber);
|
static void emitstate(Term terms, Nonterm start, int ntnumber);
|
||||||
static void emitstring(Rule rules);
|
static void emitstring(Rule rules);
|
||||||
|
@ -128,12 +131,14 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
if (start)
|
if (start)
|
||||||
ckreach(start);
|
ckreach(start);
|
||||||
|
#if 0
|
||||||
for (p = nts; p; p = p->link)
|
for (p = nts; p; p = p->link)
|
||||||
if (!p->reached)
|
if (!p->reached)
|
||||||
yyerror("can't reach non-terminal `%s'\n", p->name);
|
yyerror("can't reach non-terminal `%s'\n", p->name);
|
||||||
|
#endif
|
||||||
|
|
||||||
emitregisterclasses(regclasses);
|
emitregisterclasses();
|
||||||
emitregisters(regs);
|
emitregisters();
|
||||||
emitdefs(nts, ntnumber);
|
emitdefs(nts, ntnumber);
|
||||||
emitstruct(nts, ntnumber);
|
emitstruct(nts, ntnumber);
|
||||||
emitnts(rules, nrules);
|
emitnts(rules, nrules);
|
||||||
|
@ -230,52 +235,40 @@ static void* install(const char* name)
|
||||||
|
|
||||||
struct reg* makereg(const char* id)
|
struct reg* makereg(const char* id)
|
||||||
{
|
{
|
||||||
struct reg* p = lookup(id);
|
struct reg* p = smap_get(®isters, id);
|
||||||
struct reg** q = ®s;
|
|
||||||
static int number = 1;
|
static int number = 1;
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
yyerror("redefinition of '%s'", id);
|
yyerror("redefinition of '%s'", id);
|
||||||
p = install(id);
|
p = calloc(1, sizeof(*p));
|
||||||
p->kind = REG;
|
p->name = id;
|
||||||
p->number = number++;
|
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;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addregclass(struct reg* reg, const char* id)
|
void addregclass(struct reg* reg, const char* id)
|
||||||
{
|
{
|
||||||
struct regclass* p = lookup(id);
|
struct regclass* p = smap_get(®isterclasses, id);
|
||||||
struct regclass** q = ®classes;
|
|
||||||
static int number = 1;
|
static int number = 1;
|
||||||
|
|
||||||
if (p && (p->kind != REGCLASS))
|
|
||||||
yyerror("redefinition of '%s' as something else\n", id);
|
|
||||||
if (!p)
|
if (!p)
|
||||||
{
|
{
|
||||||
p = install(id);
|
p = calloc(1, sizeof(*p));
|
||||||
p->kind = REGCLASS;
|
p->name = id;
|
||||||
p->number = number++;
|
p->number = number++;
|
||||||
|
smap_put(®isterclasses, id, p);
|
||||||
while (*q && (*q)->number < p->number)
|
|
||||||
q = &(*q)->link;
|
|
||||||
assert(*q == 0 || (*q)->number != p->number);
|
|
||||||
p->link = *q;
|
|
||||||
*q = p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
struct regclass* p = lookup(id);
|
struct regclass* p = smap_get(®isterclasses, id);
|
||||||
if (!p || (p->kind != REGCLASS))
|
if (!p)
|
||||||
yyerror("'%s' is not the name of a register class", id);
|
yyerror("'%s' is not the name of a register class", id);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -333,10 +326,10 @@ Term term(const char* id, int esn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tree - create & initialize a tree node with the given fields */
|
/* 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);
|
Tree t = calloc(1, sizeof *t);
|
||||||
Term p = lookup(id);
|
Term p = lookup(ti->name);
|
||||||
int arity = 0;
|
int arity = 0;
|
||||||
|
|
||||||
if (left && right)
|
if (left && right)
|
||||||
|
@ -345,22 +338,22 @@ Tree tree(const char* id, const char* label, Tree left, Tree right)
|
||||||
arity = 1;
|
arity = 1;
|
||||||
if (p == NULL && arity > 0)
|
if (p == NULL && arity > 0)
|
||||||
{
|
{
|
||||||
yyerror("undefined terminal `%s'\n", id);
|
yyerror("undefined terminal `%s'\n", ti->name);
|
||||||
p = term(id, -1);
|
p = term(ti->name, -1);
|
||||||
}
|
}
|
||||||
else if (p == NULL && arity == 0)
|
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)
|
else if (p && p->kind == NONTERM && arity > 0)
|
||||||
{
|
{
|
||||||
yyerror("`%s' is a non-terminal\n", id);
|
yyerror("`%s' is a non-terminal\n", ti->name);
|
||||||
p = term(id, -1);
|
p = term(ti->name, -1);
|
||||||
}
|
}
|
||||||
if (p->kind == TERM && p->arity == -1)
|
if (p->kind == TERM && p->arity == -1)
|
||||||
p->arity = arity;
|
p->arity = arity;
|
||||||
if (p->kind == TERM && arity != p->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->op = p;
|
||||||
t->label = label;
|
t->label = ti->label;
|
||||||
t->nterms = p->kind == TERM;
|
t->nterms = p->kind == TERM;
|
||||||
if (t->left = left)
|
if (t->left = left)
|
||||||
t->nterms += left->nterms;
|
t->nterms += left->nterms;
|
||||||
|
@ -423,6 +416,10 @@ static void print(char* fmt, ...)
|
||||||
fprintf(outfp, "%x", va_arg(ap, uint32_t));
|
fprintf(outfp, "%x", va_arg(ap, uint32_t));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
fprintf(outfp, "0x%" PRIx64 "ULL", va_arg(ap, uint64_t));
|
||||||
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
fputs(va_arg(ap, char*), outfp);
|
fputs(va_arg(ap, char*), outfp);
|
||||||
break;
|
break;
|
||||||
|
@ -503,34 +500,34 @@ static void ckreach(Nonterm p)
|
||||||
reach(r->pattern);
|
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");
|
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++)
|
struct regclass* rc = registerclasses.item[i].right;
|
||||||
print("%1NULL,\n");
|
assert(rc->number == (i+1));
|
||||||
k++;
|
|
||||||
|
|
||||||
print("%1\"%s\",\n", rc->name);
|
print("%1\"%s\",\n", rc->name);
|
||||||
rc = rc->link;
|
|
||||||
}
|
}
|
||||||
print("};\n\n");
|
print("};\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitregisters(struct reg* r)
|
static void emitregisters(void)
|
||||||
{
|
{
|
||||||
int k = 0;
|
int i;
|
||||||
print("const struct %Pregister_data %Pregister_data[] = {\n");
|
|
||||||
while (r)
|
|
||||||
{
|
|
||||||
for (; k < r->number; k++)
|
|
||||||
print("%1{ 0 },\n");
|
|
||||||
k++;
|
|
||||||
|
|
||||||
print("%1{ \"%s\", %d },\n", r->name, r->classes);
|
print("const struct %Pregister_data %Pregister_data[] = {\n");
|
||||||
r = r->link;
|
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");
|
print("};\n\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,21 +15,24 @@ typedef enum
|
||||||
typedef struct rule* Rule;
|
typedef struct rule* Rule;
|
||||||
typedef struct term* Term;
|
typedef struct term* Term;
|
||||||
|
|
||||||
|
struct terminfo
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
const char* label;
|
||||||
|
const char* regattr;
|
||||||
|
};
|
||||||
|
|
||||||
struct reg
|
struct reg
|
||||||
{
|
{
|
||||||
const char* name; /* register name */
|
const char* name; /* register name */
|
||||||
Kind kind; /* REG */
|
|
||||||
int number; /* identifying number */
|
int number; /* identifying number */
|
||||||
uint32_t classes; // bitfield of classes */
|
uint64_t classes; // bitfield of classes */
|
||||||
struct reg* link; /* next in list */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct regclass
|
struct regclass
|
||||||
{
|
{
|
||||||
const char* name; /* class name */
|
const char* name; /* class name */
|
||||||
Kind kind; /* REGCLASS */
|
|
||||||
int number; /* identifying number */
|
int number; /* identifying number */
|
||||||
struct regclass* link; /* next in list */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct reg* makereg(const char* name);
|
extern struct reg* makereg(const char* name);
|
||||||
|
@ -72,7 +75,7 @@ struct tree
|
||||||
Tree left, right; /* operands */
|
Tree left, right; /* operands */
|
||||||
int nterms; /* number of terminal nodes in this tree */
|
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
|
struct rule
|
||||||
{ /* rules: */
|
{ /* rules: */
|
||||||
|
|
Loading…
Reference in a new issue