51e34acab1
Use the new syntax in the mips, pdp, powerpc tables to declare functions before calling them. These declarations prevent compiler warnings about implicitly declaring functions. They also provide prototypes of the function parameters. Also fix a warning in the powerpc table: use `bsearch(...) != NULL` to avoid converting the pointer from bsearch() to an int. The syntax for topgen is a block `{...}` among the parameters in the top table. It looks like the syntax of LLgen, but topgen doesn't allow nested blocks, so declarations like `struct whatever {...};` don't work. The token OPEN_BRACKET that begins a declaration_block doesn't conflict with the LETTER that begins a parameter_line or the '%' that begins a separator. Because a block writes a #line command to gen.h, a parameter line now also writes a #line command to gen.h, so it doesn't get a wrong line number from a previous block.
350 lines
7 KiB
Plaintext
350 lines
7 KiB
Plaintext
/* $Id$ */
|
|
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
/* t o p g e n . g
|
|
*
|
|
* Grammar of optimizer description, and some code generation
|
|
*/
|
|
|
|
%token LETTER, DIGIT, OTHER, SPACE;
|
|
%token LINE_TERMINATOR, OPERAND_SEPARATOR, INSTRUCTION_SEPARATOR,
|
|
PATTERN_SEPARATOR, OPEN_BRACKET, CLOSE_BRACKET;
|
|
%lexical LLlex;
|
|
%start LLparse, optim_description;
|
|
|
|
{
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "token.h"
|
|
#include "symtab.h"
|
|
#include "misc.h"
|
|
#include "hash.h"
|
|
#include "pattern.h"
|
|
|
|
char idbuf[BUFSIZ], buf[BUFSIZ];
|
|
int countid; /* # of variables */
|
|
int countpat; /* # of patterns */
|
|
static int patlen; /* Maximum number of instructions in pattern */
|
|
static int maxoperand; /* Maximum number of operands of instruction */
|
|
extern FILE *input; /* file descriptor of inputfile */
|
|
|
|
|
|
|
|
extern int onlyspace(char* s);
|
|
extern void error(char *s, char* s1);
|
|
|
|
|
|
}
|
|
|
|
optim_description
|
|
{ struct symtab *p; } :
|
|
SPACE* parameters
|
|
{ p = findident("MAXOP",LOOKING,&deftable);
|
|
if (p == 0) maxoperand = 2; /* default */
|
|
else maxoperand = p->s_num;
|
|
}
|
|
separator SPACE* mode_definitions
|
|
separator SPACE* patterns
|
|
separator
|
|
{ register int c;
|
|
fprintf(genc, linedir, lineno, inpfile);
|
|
while ((c = getc(input)) != EOF) {
|
|
putc(c,genc);
|
|
}
|
|
}
|
|
;
|
|
|
|
parameters :
|
|
[ parameter_line | declaration_block ]*
|
|
;
|
|
|
|
parameter_line
|
|
{ struct symtab *p;
|
|
int lin;
|
|
} :
|
|
identifier
|
|
{ p = findident(idbuf,ENTERING,&deftable);}
|
|
SPACE
|
|
{ lin = lineno;}
|
|
value
|
|
{ p->s_num = atoi(buf);}
|
|
/* This action in fact only needed for MAXOP */
|
|
LINE_TERMINATOR
|
|
SPACE*
|
|
{ fprintf(genh, linedir, lin, inpfile);
|
|
fprintf(genh,"#define %s %s\n",p->s_name,buf);}
|
|
;
|
|
|
|
value
|
|
{ char *p1 = buf;} :
|
|
[
|
|
[ OPEN_BRACKET
|
|
| CLOSE_BRACKET
|
|
| OPERAND_SEPARATOR
|
|
| PATTERN_SEPARATOR
|
|
| INSTRUCTION_SEPARATOR
|
|
| SPACE
|
|
| LETTER
|
|
| DIGIT
|
|
| OTHER
|
|
| '%'
|
|
]
|
|
{ *p1++ = dot.t_attrib;}
|
|
]*
|
|
{ *p1 = '\0';}
|
|
;
|
|
|
|
declaration_block :
|
|
OPEN_BRACKET
|
|
{ fprintf(genh, linedir, lineno, inpfile);}
|
|
[
|
|
[ LINE_TERMINATOR
|
|
| OPERAND_SEPARATOR
|
|
| PATTERN_SEPARATOR
|
|
| INSTRUCTION_SEPARATOR
|
|
| SPACE
|
|
| LETTER
|
|
| DIGIT
|
|
| OTHER
|
|
| '%'
|
|
]
|
|
{ putc(dot.t_attrib, genh);}
|
|
]*
|
|
CLOSE_BRACKET
|
|
SPACE*
|
|
{ putc('\n', genh);}
|
|
;
|
|
|
|
mode_definitions
|
|
{ int lin; } :
|
|
{ fputs("tok_chk(varno) {\n\tint r;\n", genc);
|
|
fputs("\tchar *VAL;\n\n",genc);
|
|
fputs("\tVAL = var[varno].value;\n",genc);
|
|
fputs("\tswitch(varno) {\n",genc);
|
|
}
|
|
[
|
|
token_list
|
|
constraint(&lin)
|
|
{ fprintf(genc,linedir,lin,inpfile);
|
|
fprintf(genc,"\t\tr = (%s); break;\n",buf);
|
|
}
|
|
LINE_TERMINATOR
|
|
SPACE*
|
|
]*
|
|
{ fputs("\tdefault :\n\t\tassert(0);\n",genc);
|
|
fputs("\t}\n\treturn r;\n}\n\n",genc);
|
|
}
|
|
;
|
|
|
|
token_list :
|
|
new_identifier
|
|
SPACE*
|
|
[
|
|
OPERAND_SEPARATOR
|
|
SPACE*
|
|
new_identifier
|
|
SPACE*
|
|
]*
|
|
;
|
|
|
|
new_identifier
|
|
{ struct symtab *p;} :
|
|
identifier
|
|
{ p = findident(idbuf,ENTERING,&idtable);
|
|
p->s_num = ++countid;
|
|
fprintf(genc,"\tcase %d:\n", countid);
|
|
}
|
|
;
|
|
|
|
constraint (int *lin;)
|
|
{ char *p = buf; } :
|
|
OPEN_BRACKET
|
|
{ *lin = lineno;}
|
|
[
|
|
[ LINE_TERMINATOR
|
|
| OPERAND_SEPARATOR
|
|
| PATTERN_SEPARATOR
|
|
| INSTRUCTION_SEPARATOR
|
|
| LETTER
|
|
| DIGIT
|
|
| SPACE
|
|
| OTHER
|
|
| '%'
|
|
]
|
|
{ *p++ = dot.t_attrib;}
|
|
]*
|
|
{ *p = '\0';
|
|
if (onlyspace(buf)) strcpy(buf,"TRUE");
|
|
}
|
|
CLOSE_BRACKET
|
|
SPACE*
|
|
;
|
|
|
|
patterns
|
|
{ int lin;
|
|
char *constr;
|
|
int np, nr;
|
|
} :
|
|
[
|
|
{ countpat++;
|
|
constr = (char *) 0;
|
|
fprintf(genc,"struct instr_descr pat%d[] = {\n",
|
|
countpat);
|
|
}
|
|
instruction_list(&np)
|
|
{ if (np > patlen) patlen = np;
|
|
fputs("\n};\n\n",genc);
|
|
}
|
|
[
|
|
constraint(&lin)
|
|
{ /* Save the constraint, we need it later on */
|
|
constr = malloc((unsigned)(strlen(buf)+1));
|
|
strcpy(constr,buf);
|
|
}
|
|
]?
|
|
PATTERN_SEPARATOR
|
|
{ fprintf(genc,"struct instr_descr rep%d[] = {\n",
|
|
countpat);
|
|
}
|
|
replacement(&nr)
|
|
{ fputs("\n};\n\n",genc);}
|
|
LINE_TERMINATOR
|
|
SPACE*
|
|
{ addpattern(constr,lin,np,nr);}
|
|
]*
|
|
{ printhashtable();
|
|
printpatterns();
|
|
fprintf(genh,"#define NRVARS %d\n",countid);
|
|
fprintf(genh,"#define NRPATTERNS %d\n",countpat);
|
|
fprintf(genh,"#define MIN_WINDOW_SIZE %d\n",
|
|
patlen+3);
|
|
fclose(genh);
|
|
}
|
|
;
|
|
|
|
instruction_list(int *n;) :
|
|
instruction(1)
|
|
{ *n = 1;}
|
|
[
|
|
INSTRUCTION_SEPARATOR
|
|
{ fputs(",\n",genc);}
|
|
SPACE*
|
|
instruction(0)
|
|
{ *n += 1;}
|
|
]*
|
|
;
|
|
|
|
instruction(int opt;)
|
|
{ int count = 0;} :
|
|
opcode(opt)
|
|
{ if (strcmp(buf,"ANY") != 0) {
|
|
fprintf(genc,"\t{\"%s\", {",buf);
|
|
}
|
|
else fputs("\t{(char *) 0, {",genc);
|
|
count = 0;
|
|
}
|
|
[
|
|
operand(' ')
|
|
{ count = 1;}
|
|
[
|
|
OPERAND_SEPARATOR
|
|
{ count++;}
|
|
SPACE*
|
|
operand(',')
|
|
]*
|
|
{ if (count > maxoperand) {
|
|
error("Too many operands","");
|
|
}
|
|
}
|
|
]?
|
|
{ while (count++ < maxoperand) {
|
|
fprintf(genc,"%c{\"\",-1,\"\"}",count == 1 ? ' ' : ',');
|
|
}
|
|
putc('}',genc);
|
|
putc('}',genc);
|
|
}
|
|
;
|
|
|
|
opcode(int opt;)
|
|
{ char *p = buf;} :
|
|
[
|
|
[ LETTER
|
|
| DIGIT
|
|
| OTHER
|
|
]
|
|
{ *p++ = dot.t_attrib;}
|
|
]+
|
|
SPACE+
|
|
{ *p = '\0';
|
|
if (opt) addtohashtable(buf,countpat);
|
|
}
|
|
;
|
|
|
|
operand(int c;)
|
|
{ register struct symtab *p = 0;} :
|
|
{ fprintf(genc, "%c{\"", c);}
|
|
[
|
|
identifier
|
|
{ if (!p) {
|
|
p = findident(idbuf,LOOKING,&idtable);
|
|
if (p) fprintf(genc,"\",%d,\"",p->s_num);
|
|
else fputs(idbuf,genc);
|
|
}
|
|
else fputs(idbuf,genc);
|
|
}
|
|
| DIGIT
|
|
{ putc(dot.t_attrib,genc);}
|
|
| OTHER
|
|
{ putc(dot.t_attrib,genc);}
|
|
]+
|
|
{ if (p) fputs("\"}",genc);
|
|
else fputs("\",0,\"\"}",genc);
|
|
}
|
|
SPACE*
|
|
;
|
|
|
|
replacement (int *n;)
|
|
{register int i;} :
|
|
SPACE*
|
|
{ *n = 0;}
|
|
[
|
|
instruction(0)
|
|
{ *n = 1;}
|
|
[
|
|
INSTRUCTION_SEPARATOR
|
|
{ fputs(",\n", genc);}
|
|
SPACE*
|
|
instruction(0)
|
|
{ *n += 1;}
|
|
]*
|
|
| /* empty replacement, but there must be a
|
|
* structure initializer anyway
|
|
*/
|
|
{ fputs("\t{\"\", {",genc);
|
|
for (i = 0; i < maxoperand; i++) {
|
|
fprintf(genc, "%c{\"\",-1,\"\"}",i?',':' ');
|
|
}
|
|
fputs("}}",genc);
|
|
}
|
|
]
|
|
;
|
|
|
|
|
|
identifier
|
|
{ char *p = idbuf; } :
|
|
LETTER
|
|
{ *p++ = dot.t_attrib;}
|
|
[ %while (1)
|
|
LETTER { *p++ = dot.t_attrib;}
|
|
| DIGIT { *p++ = dot.t_attrib;}
|
|
]*
|
|
{ *p = '\0';}
|
|
;
|
|
|
|
separator :
|
|
'%' '%' SPACE* LINE_TERMINATOR
|
|
;
|