artificial commit to compensate for changes in 93f3093f2b7e from a CVS

vendor branch
This commit is contained in:
keie
1984-06-21 13:13:10 +00:00
112 changed files with 21715 additions and 0 deletions

23
util/ack/.distr Normal file
View File

@@ -0,0 +1,23 @@
Makefile
ack.h
data.c
data.h
dmach.c
dmach.h
files.c
grows.c
grows.h
intable.c
list.c
list.h
main.c
malloc.c
mktables.c
pc
rmach.c
run.c
scan.c
svars.c
trans.c
trans.h
util.c

63
util/ack/Makefile Normal file
View File

@@ -0,0 +1,63 @@
HFILES=ack.h list.h trans.h data.h dmach.h grows.h
DSRC=list.c data.c main.c scan.c svars.c trans.c util.c rmach.c run.c grows.c\
files.c
ISRC=dmach.c intable.c
OBJ=list.o data.o main.o scan.o svars.o trans.o util.o rmach.o run.o \
dmach.o intable.o grows.o files.o
ACKDIR=../../lib/ack
FE=fe
INTABLES=pdp int
LNTABLES=6500 m68k2 m68k4 6809 8080 acc apc nascom vax2 vax4 z80 i86
CFLAGS=-O -n
BINDIR=../../bin
head: ack
install: ack
cp ack $(BINDIR)/ack
-cd $(BINDIR) ; \
for i in $(INTABLES) $(LNTABLES) ; do ln ack $$i ; done
(cd pc ; make install )
cmp: ack
cmp ack $(BINDIR)/ack
(cd pc ; make cmp )
clean:
-rm -f *.old *.o ack
(cd pc ; make clean )
ack: $(OBJ)
$(CC) -o ack $(CFLAGS) $(OBJ)
grows.o files.o list.o run.o \
data.o main.o scan.o trans.o rmach.o util.o : ack.h list.h
files.o data.o main.o scan.o run.o trans.o rmach.o: trans.h data.h
files.o rmach.o trans.o grows.c : grows.h
rmach.c: dmach.h
files.o main.o rmach.o : ../../h/em_path.h
main.o : ../../h/local.h
malloc.o svars.o: ack.h
dmach.c intable.c: mktables dmach.h
: mktables $(ACKDIR) # $(FE) $(INTABLES)
mktables $(ACKDIR)
mktables: mktables.c
cc -o mktables mktables.c
pr:
@pr Makefile $(HFILES) $(DSRC) $(ACKDIR)/*
@(cd pc ; make pr)
opr:
make pr | opr
lint: $(ISRC)
lint -hbx $(DSRC) $(ISRC)

88
util/ack/ack.h Normal file
View File

@@ -0,0 +1,88 @@
/****************************************************************************/
/* User settable options */
/****************************************************************************/
#define FRONTENDS "fe" /* The front-end definitions */
#define ACKNAME "AckXXXXXX" /* Handed to mktemp for temp. files */
/****************************************************************************/
/* Internal mnemonics, should not be tinkered with */
/****************************************************************************/
/* The names of some string variables */
#define HOME "EM"
#define RTS "RTS"
#define NEEDS "NEEDS"
#define HEAD "HEAD"
#define TAIL "TAIL"
#define SRC "SOURCE"
#define LIBVAR "LNAME"
/* Intended for flags, possibly in bit fields */
#define YES 1
#define NO 0
#define MAYBE 2
#define EXTERN extern
#define SUFCHAR '.' /* Start of SUFFIX in file name */
#define SPACE ' '
#define TAB '\t'
#define EQUAL '='
#define S_VAR '{' /* Start of variable */
#define C_VAR '}' /* End of variable */
#define A_VAR '?' /* Variable alternative */
#define BSLASH '\\' /* Backslash */
#define STAR '*' /* STAR */
#define C_IN '<' /* Token specifying input */
#define C_OUT '>' /* Token specifying output */
#define S_EXPR '(' /* Start of expression */
#define C_EXPR ')' /* End of expression */
#define M_EXPR ':' /* Middle of two suffix lists */
#define T_EXPR '=' /* Start of tail */
#define NO_SCAN 0200 /* Bit set in character to defeat recogn. */
typedef struct {
char *p_path; /* points to the full pathname */
int p_keeps:1; /* The string should be thrown when unused */
int p_keep:1; /* The file should be thrown away after use */
} path ;
/* Return values of setpath() */
enum f_path { F_OK, F_NOMATCH, F_NOPATH } ;
/* Library routines */
extern char *index();
extern char *rindex();
extern char *strcpy();
extern char *strcat();
extern char *mktemp();
extern int unlink();
extern int close();
extern int open();
extern int creat();
/* Own routines */
enum f_path setpath();
enum f_path scan_end();
extern int noodstop();
extern char *getvar();
extern char *keeps();
extern char *basename();
extern char *skipblank();
extern char *firstblank();
extern char *getcore();
extern char *changecore();
#define freecore(area) free(area)
/* #define DEBUG 1 /* Allow debugging of Ack */
#ifndef DEBUG
# define debug 0 /* To surprise all these 'if ( debug ) 's */
#else
extern int debug ;
#endif

9
util/ack/data.c Normal file
View File

@@ -0,0 +1,9 @@
#include "ack.h"
#include "list.h"
#include "trans.h"
#undef EXTERN
#define EXTERN
#include "data.h"

43
util/ack/data.h Normal file
View File

@@ -0,0 +1,43 @@
EXTERN char *stopsuffix; /* Suffix to stop at */
EXTERN char *machine; /* The machine id */
EXTERN char *rts; /* The runtime-system id */
EXTERN list_head arguments; /* List of arguments */
EXTERN list_head flags; /* List of flags */
EXTERN list_head c_arguments; /* List of linker arguments */
EXTERN list_head tr_list; /* List of transformations */
EXTERN list_head R_list; /* List of -R flags */
EXTERN list_head head_list; /* List of suffices for headers */
EXTERN list_head tail_list; /* List of suffices for tails */
EXTERN int k_flag; /* Like -k of lint */
EXTERN int g_flag; /* do_run() */
EXTERN int t_flag; /* Preserve intermediate files */
EXTERN int v_flag; /* Verbose */
EXTERN int w_flag; /* Don't print warnings */
EXTERN int nill_flag; /* Don't file names */
EXTERN int Optflag; /* Optimizing */
#ifdef DEBUG
EXTERN int debug; /* Debugging control */
#endif
EXTERN int n_error; /* Number of errors encountered */
EXTERN char *progname; /* The program call name */
EXTERN char *outfile; /* The result file e.g. a.out */
EXTERN char *template; /* The template for temporary file
names */
EXTERN trf *combiner; /* Pointer to the Loader/Linker */
EXTERN trf *cpp_trafo; /* Pointer to C-preprocessor */
EXTERN path in; /* The current input pathname */
EXTERN path out; /* The current output pathname */
EXTERN path orig; /* The original input path */
EXTERN char *p_basename; /* The current basename */
EXTERN char *p_suffix; /* The current input suffix */

15
util/ack/dmach.h Normal file
View File

@@ -0,0 +1,15 @@
/***************************************************************/
/* */
/* Definition for table that maps a name on an intable index */
/* */
/***************************************************************/
typedef struct {
char *ma_name ; /* The name of the machine */
int ma_index ;
} dmach ;
extern dmach massoc[] ;
extern char intable[] ;

94
util/ack/files.c Normal file
View File

@@ -0,0 +1,94 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
#include "list.h"
#include "trans.h"
#include "grows.h"
#include "data.h"
#include "../../h/em_path.h"
setfiles(phase) register trf *phase ; {
/* Set the out structure according to the in structure,
the transformation and some global data */
growstring pathname ;
register list_elem *elem ;
if ( phase->t_combine ) {
out.p_keep=YES ;
out.p_path=outfile ;
out.p_keeps=NO ;
in.p_path= (char *)0 ;
in.p_keep=YES ;
in.p_keeps=NO ;
} else {
gr_init(&pathname) ;
if ( !phase->t_keep && !t_flag ) {
gr_cat(&pathname,TMP_DIR) ;
gr_cat(&pathname,"/") ;
gr_cat(&pathname,template) ;
out.p_keep=NO ;
} else {
gr_cat(&pathname,p_basename) ;
out.p_keep=YES ;
}
gr_cat(&pathname,phase->t_out) ;
out.p_path= gr_final(&pathname) ;
out.p_keeps= YES ;
}
scanlist( l_first(arguments), elem) {
if ( strcmp(l_content(*elem),out.p_path)==0 ) {
error("attempt to overwrite argument file") ;
return 0 ;
}
}
return 1 ;
}
disc_files() {
if ( in.p_path ) {
if ( !in.p_keep ) {
if ( unlink(in.p_path)!=0 ) {
werror("couldn't unlink %s",in.p_path);
}
}
if ( in.p_keeps ) throws(in.p_path) ;
}
in=out ;
out.p_path= (char *)0 ;
out.p_keeps=NO ;
out.p_keep=NO ;
}
rmtemps() {
/* Called in case of disaster, always remove the current output file!
*/
if ( out.p_path ) {
unlink(out.p_path) ;
if ( out.p_keeps ) throws(out.p_path) ;
out.p_path= (char *)0 ;
out.p_keeps=NO ;
out.p_keep=NO ;
}
if ( !in.p_keep && in.p_path ) {
unlink(in.p_path) ;
if ( in.p_keeps ) throws(in.p_path) ;
in.p_path= (char *)0 ;
out.p_keeps= NO ;
out.p_keep=NO ;
}
}

79
util/ack/grows.c Normal file
View File

@@ -0,0 +1,79 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
/**************************************************************************/
/* */
/* Bookkeeping for growing strings */
/* */
/**************************************************************************/
#include "ack.h"
#include "grows.h"
gr_add(id,c) register growstring *id ; char c ; {
if ( id->gr_size==id->gr_max) {
if ( id->gr_size==0 ) { /* The first time */
id->gr_max= 2*GR_MORE ;
id->gr_string= getcore(id->gr_max) ;
} else {
id->gr_max += GR_MORE ;
id->gr_string= changecore(id->gr_string,id->gr_max ) ;
}
}
*(id->gr_string+id->gr_size++)= c ;
}
gr_cat(id,string) growstring *id ; char *string ; {
register char *ptr ;
#ifdef DEBUG
if ( id->gr_size && *(id->gr_string+id->gr_size-1) ) {
vprint("Non-zero terminated %*s\n",
id->gr_size, id->gr_string ) ;
}
#endif
if ( id->gr_size ) id->gr_size-- ;
ptr=string ;
for (;;) {
gr_add(id,*ptr) ;
if ( *ptr++ ) continue ;
break ;
}
}
gr_throw(id) register growstring *id ; {
/* Throw the string away */
if ( id->gr_max==0 ) return ;
freecore(id->gr_string) ;
id->gr_max=0 ;
id->gr_size=0 ;
}
gr_init(id) growstring *id ; {
id->gr_size=0 ; id->gr_max=0 ;
}
char *gr_final(id) growstring *id ; {
/* Throw away the bookkeeping, adjust the string to its final
length and return a pointer to a string to be get rid of with
throws
*/
register char *retval ;
retval= keeps(gr_start(*id)) ;
gr_throw(id) ;
return retval ;
}

19
util/ack/grows.h Normal file
View File

@@ -0,0 +1,19 @@
/* struct used to identify and do bookkeeping for growing strings */
typedef struct {
char *gr_string ; /* Points to start of string */
unsigned gr_size ; /* Current string size */
unsigned gr_max ; /* Maximum string size */
} growstring ;
#define GR_MORE 50 /* Steps to grow */
#define gr_start(id) (id).gr_string /* The start of the string */
/* Routines used */
extern int gr_throw() ; /* To free the core */
extern int gr_add() ; /* To add one character */
extern int gr_cat() ; /* concatenate the contents and the string */
extern int gr_init() ; /* Initialize the bookkeeping */
extern char *gr_final() ; /* Transform to a stable storage string */

73
util/ack/list.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
#include "list.h"
/* List handling, operations allowed:
adding strings to the list,
throwing away whole lists,
linearize a list.
Routines:
l_add(header,string) Add an element to a list.
header List header, list_head *
string String pointer, char *
the string is NOT copied
l_clear(header) Delete an whole list.
header List header, list_head *
*/
l_add(header,string) list_head *header ; char *string ; {
register list_elem *new;
/* NOSTRICT */
new= (list_elem *)getcore(sizeof *new);
l_content(*new)= string ;
/* NOSTRICT */
l_next(*new)= (list_elem *)0 ;
if ( !header->ca_first ) {
header->ca_first= new ;
} else {
header->ca_last->ca_next= new ;
}
header->ca_last= new ;
}
l_clear(header) list_head *header ; {
register list_elem *old, *next;
for ( old=header->ca_first ; old ; old= next ) {
next= old->ca_next ;
freecore((char *)old) ;
}
header->ca_first= (list_elem *) 0 ;
header->ca_last = (list_elem *) 0 ;
}
l_throw(header) list_head *header ; {
register list_elem *old, *next;
for ( old=header->ca_first ; old ; old= next ) {
throws(l_content(*old)) ;
next= old->ca_next ;
freecore((char *)old) ;
}
header->ca_first= (list_elem *) 0 ;
header->ca_last = (list_elem *) 0 ;
}

23
util/ack/list.h Normal file
View File

@@ -0,0 +1,23 @@
struct ca_elem {
struct ca_elem *ca_next; /* The link */
char *ca_cont; /* The contents */
} ;
struct ca_list {
struct ca_elem *ca_first; /* The head */
struct ca_elem *ca_last; /* The tail */
} ;
typedef struct ca_list list_head ; /* The decl. for headers */
typedef struct ca_elem list_elem ; /* The decl. for elements */
/* Some operations */
/* Access */
#define l_first(header) (header).ca_first
#define l_next(elem) (elem).ca_next
#define l_content(elem) (elem).ca_cont
/* To be used for scanning lists, ptr is the running variable */
#define scanlist(elem,ptr) \
for ( ptr= elem ; ptr; ptr= l_next(*ptr) )

340
util/ack/main.c Normal file
View File

@@ -0,0 +1,340 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
#include "list.h"
#include "trans.h"
#include "../../h/em_path.h"
#include "../../h/local.h"
#include "data.h"
#include <signal.h>
static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ;
extern char *getenv();
main(argc,argv) char **argv ; {
register list_elem *elem ;
register char *frontend ;
register int *n_sig ;
progname=argv[0];
varinit();
vieuwargs(argc,argv);
if ( (frontend=getenv("ACKFE")) ) {
setlist(frontend) ;
} else {
setlist(FRONTENDS);
}
setlist(machine);
transini();
scanneeds();
template= mktemp(ACKNAME) ;
if ( n_error && !k_flag ) return n_error ;
for ( n_sig=sigs ; *n_sig ; n_sig++ ) {
if ( signal(*n_sig,noodstop)==SIG_IGN ) {
signal(*n_sig,SIG_IGN) ;
}
}
scanlist ( l_first(arguments), elem ) {
if ( !process(l_content(*elem)) && !k_flag ) return 1 ;
}
orig.p_path= (char *)0 ;
if ( !combiner && !stopsuffix ) {
/* Call combiner directly without any transformation */
scanlist(l_first(tr_list),elem) {
if ( t_cont(*elem)->t_combine ) {
combiner= t_cont(*elem) ;
}
}
}
if ( !combiner || n_error ) return n_error ;
if ( !do_combine() ) return 1 ;
if ( g_flag ) {
return do_run();
}
return 0 ;
}
char *srcvar() {
return orig.p_path ;
}
varinit() {
/* initialize the string variables */
setsvar(keeps(HOME),keeps(EM_DIR)) ;
setpvar(keeps(SRC),srcvar) ;
}
/************************* flag processing ***********************/
vieuwargs(argc,argv) char **argv ; {
register char *argp;
register int nextarg ;
register int eaten ;
firstarg(argv[0]) ;
nextarg= 1 ;
while ( nextarg<argc ) {
argp= argv[nextarg] ;
nextarg++ ;
if ( argp[0]!='-' || argp[1]=='l' ) {
/* Not a flag, or a library */
l_add(&arguments,argp) ;
continue ;
}
/* Flags */
eaten=0 ; /* Did not 'eat' tail of flag yet */
switch ( argp[1] ) {
case 'm': if ( machine ) fuerror("Two machines?") ;
machine= &argp[2];
eaten=1 ;
break ;
case 'o': if ( nextarg>=argc ) {
fuerror("-o can't be the last flag") ;
}
if ( outfile ) fuerror("Two results?") ;
outfile= argv[nextarg++] ;
break ;
case 'O': Optflag++ ;
break ;
case 'v': v_flag++ ;
break ;
case 'g': g_flag++ ;
break ;
case 'c': if ( stopsuffix ) fuerror("Two -c flags") ;
stopsuffix= &argp[2]; eaten=1;
if ( *stopsuffix && *stopsuffix!=SUFCHAR ) {
fuerror("-c flag has invalid tail") ;
}
break ;
case 'k': k_flag++ ;
break ;
case 't': t_flag++ ;
break ;
case 'R': do_Rflag(argp); eaten=1;
break ;
case 'r': if ( argp[2]!=SUFCHAR ) {
error("-r must be followed by %c",SUFCHAR) ;
}
keeptail(&argp[2]); eaten=1 ;
break ;
case '.': if ( rts ) fuerror("Two run-time systems?") ;
rts= &argp[1] ; eaten=1;
keephead(rts) ; keeptail(rts) ;
break ;
#ifdef DEBUG
case 'd': debug++ ;
break ;
#endif
case 0 : nill_flag++ ; eaten++ ;
break;
case 'w': { register char *tokeep ;
w_flag++;
tokeep=keeps(argp) ;
*tokeep |= NO_SCAN ;
l_add(&flags,tokeep) ;
}
break ;
default: /* The flag is not recognized,
put it on the list for the sub-processes
*/
#ifdef DEBUG
if ( debug ) {
vprint("Flag %s: phase dependent\n",argp) ;
}
#endif
l_add(&flags,keeps(argp)) ;
eaten=1 ;
}
if ( argp[2] && !eaten ) {
werror("Unexpected characters at end of %s",argp) ;
}
}
if ( !machine && ! (machine=getenv("ACKM")) ) {
#ifdef ACKM
machine= ACKM; /* The default machine */
#else
fuerror("No machine specified") ;
#endif
}
return ;
}
firstarg(argp) register char *argp ; {
register char *name ;
name=rindex(argp,'/') ;
if ( name && *(name+1) ) {
name++ ;
} else {
name= argp ;
}
if ( strcmp(name,"ack")==0 ) return ;
if ( strcmp(name,"acc")==0 || strcmp(name,"cc")==0 ) {
rts= ".c" ; keephead(rts) ; keeptail(rts) ;
return ;
}
if ( strcmp(name,"apc")==0 || strcmp(name,"pc")==0 ) {
rts= ".p" ; keephead(rts) ; keeptail(rts) ;
return ;
}
machine= name;
}
/************************* argument processing ***********************/
process(arg) char *arg ; {
/* Process files & library arguments */
register list_elem *elem ;
register trf *phase ;
int first=YES ;
#ifdef DEBUG
if ( debug ) vprint("Processing %s\n",arg) ;
#endif
if ( arg[0]=='-' ) { l_add(&c_arguments,keeps(arg)) ; return 1 ; }
p_suffix= rindex(arg,SUFCHAR) ;
if ( p_basename ) throws(p_basename) ;
orig.p_keep= YES ; /* Don't throw away the original ! */
orig.p_path= arg ;
p_basename= keeps(basename(arg)) ;
if ( !p_suffix ) { l_add(&c_arguments,keeps(arg)) ; return 1 ; }
/* Try to find a path through the transformations */
switch( setpath() ) {
case F_NOPATH :
error("Cannot produce the desired file from %s",arg) ;
l_add(&c_arguments,keeps(arg)) ;
return 1 ;
case F_NOMATCH :
if ( stopsuffix ) werror("Unknown suffix in %s",arg) ;
l_add(&c_arguments,keeps(arg)) ;
return 1 ;
case F_OK :
break ;
}
orig.p_keeps= NO;
in= orig ;
scanlist(l_first(tr_list), elem) {
phase= t_cont(*elem) ;
if ( phase->t_do ) { /* perform this transformation */
if ( first ) {
if ( !nill_flag ) {
printf("%s\n",arg) ;
}
}
switch ( phase->t_prep ) {
default : if ( !mayprep() ) break ;
case YES: if ( !transform(cpp_trafo) ) {
n_error++ ;
#ifdef DEBUG
vprint("Pre-processor failed\n") ;
#endif
return 0 ;
}
case NO :
break ;
}
if ( cpp_trafo && stopsuffix &&
strcmp(cpp_trafo->t_out,stopsuffix)==0 ) {
break ;
}
if ( !transform(phase) ) {
n_error++ ;
#ifdef DEBUG
if ( debug ) {
vprint("phase %s for %s failed\n",
phase->t_name,orig.p_path) ;
}
#endif
return 0 ;
}
first=NO ;
}
}
#ifdef DEBUG
if ( debug ) vprint("Transformation complete for %s\n",orig.p_path) ;
#endif
if ( !in.p_keep ) fatal("attempt to discard the result file") ;
l_add(&c_arguments,keeps(in.p_path));
disc_files() ;
return 1 ;
}
mayprep() {
int file ;
char fc ;
file=open(in.p_path,0);
if ( file<0 ) return 0 ;
if ( read(file,&fc,1)!=1 ) fc=0 ;
close(file) ;
return fc=='#' ;
}
keephead(suffix) char *suffix ; {
l_add(&head_list, suffix) ;
}
keeptail(suffix) char *suffix ; {
l_add(&tail_list, suffix) ;
}
scanneeds() {
register list_elem *elem ;
scanlist(l_first(head_list), elem) { setneeds(l_content(*elem),0) ; }
l_clear(&head_list) ;
scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem),1) ; }
l_clear(&tail_list) ;
}
setneeds(suffix,tail) char *suffix ; {
register list_elem *elem ;
register trf *phase ;
p_suffix= suffix ;
switch ( setpath() ) {
case F_OK :
scanlist( l_first(tr_list), elem ) {
phase = t_cont(*elem) ;
if ( phase->t_do ) {
if ( phase->t_needed ) {
if ( tail )
add_tail(phase->t_needed) ;
else
add_head(phase->t_needed) ;
}
}
}
break ;
case F_NOMATCH :
werror("\"%s\": unrecognized suffix",suffix) ;
break ;
case F_NOPATH :
werror("incomplete internal specification for %s files",
suffix) ;
break ;
}
}

208
util/ack/malloc.c Normal file
View File

@@ -0,0 +1,208 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
#ifdef DEBUG
#define ASSERT(p) if(!(p))botch("p");else
botch(s)
char *s;
{
printf("malloc/free botched: %s\n",s);
abort();
}
#else
#define ASSERT(p)
#endif
/* avoid break bug */
#ifdef pdp11
#define GRANULE 64
#else
#define GRANULE 0
#endif
/* C storage allocator
* circular first-fit strategy
* works with noncontiguous, but monotonically linked, arena
* each block is preceded by a ptr to the (pointer of)
* the next following block
* blocks are exact number of words long
* aligned to the data type requirements of ALIGN
* pointers to blocks must have BUSY bit 0
* bit in ptr is 1 for busy, 0 for idle
* gaps in arena are merely noted as busy blocks
* last block of arena (pointed to by alloct) is empty and
* has a pointer to first
* idle blocks are coalesced during space search
*
* a different implementation may need to redefine
* ALIGN, NALIGN, BLOCK, BUSY, INT
* where INT is integer type to which a pointer can be cast
*/
#define INT int
#define ALIGN int
#define NALIGN 1
#define WORD sizeof(union store)
#define BLOCK 1024 /* a multiple of WORD*/
#define BUSY 1
#define NULL 0
#define testbusy(p) ((INT)(p)&BUSY)
#define setbusy(p) (union store *)((INT)(p)|BUSY)
#define clearbusy(p) (union store *)((INT)(p)&~BUSY)
union store { union store *ptr;
ALIGN dummy[NALIGN];
int calloc; /*calloc clears an array of integers*/
};
static union store allocs[2]; /*initial arena*/
static union store *allocp; /*search ptr*/
static union store *alloct; /*arena top*/
static union store *allocx; /*for benefit of realloc*/
char *sbrk();
char *
malloc(nbytes)
unsigned nbytes;
{
register union store *p, *q;
register nw;
static temp; /*coroutines assume no auto*/
if(allocs[0].ptr==0) { /*first time*/
allocs[0].ptr = setbusy(&allocs[1]);
allocs[1].ptr = setbusy(&allocs[0]);
alloct = &allocs[1];
allocp = &allocs[0];
}
nw = (nbytes+WORD+WORD-1)/WORD;
ASSERT(allocp>=allocs && allocp<=alloct);
ASSERT(allock());
for(p=allocp; ; ) {
for(temp=0; ; ) {
if(!testbusy(p->ptr)) {
while(!testbusy((q=p->ptr)->ptr)) {
ASSERT(q>p&&q<alloct);
p->ptr = q->ptr;
}
if(q>=p+nw && p+nw>=p)
goto found;
}
q = p;
p = clearbusy(p->ptr);
if(p>q)
ASSERT(p<=alloct);
else if(q!=alloct || p!=allocs) {
ASSERT(q==alloct&&p==allocs);
return(NULL);
} else if(++temp>1)
break;
}
temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD);
q = (union store *)sbrk(0);
if(q+temp+GRANULE < q) {
return(NULL);
}
q = (union store *)sbrk(temp*WORD);
if((INT)q == -1) {
return(NULL);
}
ASSERT(q>alloct);
alloct->ptr = q;
if(q!=alloct+1)
alloct->ptr = setbusy(alloct->ptr);
alloct = q->ptr = q+temp-1;
alloct->ptr = setbusy(allocs);
}
found:
allocp = p + nw;
ASSERT(allocp<=alloct);
if(q>allocp) {
allocx = allocp->ptr;
allocp->ptr = p->ptr;
}
p->ptr = setbusy(allocp);
return((char *)(p+1));
}
/* freeing strategy tuned for LIFO allocation
*/
free(ap)
register char *ap;
{
register union store *p = (union store *)ap;
ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct);
ASSERT(allock());
allocp = --p;
ASSERT(testbusy(p->ptr));
p->ptr = clearbusy(p->ptr);
ASSERT(p->ptr > allocp && p->ptr <= alloct);
}
/* realloc(p, nbytes) reallocates a block obtained from malloc()
* and freed since last call of malloc()
* to have new size nbytes, and old content
* returns new location, or 0 on failure
*/
char *
realloc(p, nbytes)
register union store *p;
unsigned nbytes;
{
register union store *q;
union store *s, *t;
register unsigned nw;
unsigned onw;
if(testbusy(p[-1].ptr))
free((char *)p);
onw = p[-1].ptr - p;
q = (union store *)malloc(nbytes);
if(q==NULL || q==p)
return((char *)q);
s = p;
t = q;
nw = (nbytes+WORD-1)/WORD;
if(nw<onw)
onw = nw;
while(onw--!=0)
*t++ = *s++;
if(q<p && q+nw>=p)
(q+(q+nw-p))->ptr = allocx;
return((char *)q);
}
#ifdef DEBUG
allock()
{
#ifdef DEBUG
register union store *p;
int x;
x = 0;
for(p= &allocs[0]; clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) {
if(p==allocp)
x++;
}
ASSERT(p==alloct);
return(x==1|p==allocp);
#else
return(1);
#endif
}
#endif

121
util/ack/mktables.c Normal file
View File

@@ -0,0 +1,121 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include <stdio.h>
#include <ctype.h>
char *fname = 0 ;
char dname[200] ;
char *tail ;
FILE *intab ;
FILE *dmach ;
int index ;
main(argc,argv) char **argv ; {
register i ;
start(argv[1]) ;
for ( i=2 ; i<argc ; i++ ) {
fname= argv[i] ;
readm() ;
}
stop(argc>2) ;
return 0 ;
}
start(dir) char *dir ; {
tail= dname ;
while ( *dir ) {
*tail++ = *dir ++ ;
}
if ( tail!=dname ) *tail++= '/' ;
index=0 ;
intab= fopen("intable.c","w");
dmach= fopen("dmach.c","w");
if ( intab==NULL || dmach==NULL ) {
fprintf(stderr,"Couln't create output file(s)\n");
exit ( 1) ;
}
fprintf(dmach,"#include \"dmach.h\"\n\ndmach\tmassoc[] = {\n") ;
fprintf(intab,"char intable[] = {\n") ;
}
stop(filled) {
fprintf(dmach,"\t{\"\",\t-1\t}\n} ;\n") ;
if ( !filled ) fprintf(intab,"\t0\n") ;
fprintf(intab,"\n} ;\n") ;
fclose(dmach); fclose(intab) ;
}
FILE *do_open(file) char *file ; {
strcpy(tail,file) ;
return fopen(dname,"r") ;
}
readm() {
register int i ;
register int token ;
register FILE *in ;
in=do_open(fname) ;
if ( in==NULL ) {
fprintf(stderr,"Cannot open %s\n",fname) ;
return ;
}
i=0 ;
fprintf(dmach,"\t{\"%s\",\t%d\t},\n",fname,index) ;
fprintf(intab,"\n/* %s */\n\t",fname) ;
for (;;) {
token=getc(in) ;
index++ ;
if ( ++i == 10 ) {
fprintf(intab,"\n\t") ;
i=0 ;
} else {
fprintf(intab," ") ;
}
if ( !isascii(token) || !(isprint(token) || isspace(token)) ){
if ( token!=EOF ) {
fprintf(stderr,"warning: non-ascii in %s\n",fname) ;
fprintf(intab,"%4d,",token) ;
} else {
fprintf(intab," 0,",token) ;
break ;
}
} else if ( isprint(token) ) {
switch ( token ) {
case '\'': fprintf(intab,"'\\''") ; break ;
case '\\': fprintf(intab,"'\\\\'") ; break ;
default: fprintf(intab," '%c'",token) ; break ;
}
} else switch ( token ) {
case '\n' : fprintf(intab,"'\\n'") ; break ;
case '\t' : fprintf(intab,"'\\t'") ; break ;
case '\r' : fprintf(intab,"'\\r'") ; break ;
case '\f' : fprintf(intab,"'\\f'") ; break ;
case ' ' : fprintf(intab," ' '") ; break ;
default : fprintf(stderr,"warning: unrec. %d\n",
token) ;
fprintf(intab,"%4d",token) ;
break ;
}
fprintf(intab,",") ;
}
fclose(in) ;
}

2
util/ack/pc/.distr Normal file
View File

@@ -0,0 +1,2 @@
Makefile
em_pc.c

25
util/ack/pc/Makefile Normal file
View File

@@ -0,0 +1,25 @@
d=../../..
h=$d/h
PC_PATH=$d/lib/em_pc
em_pc: em_pc.c $h/local.h $h/em_path.h
cc -n -o em_pc -O -I$h em_pc.c
cmp: em_pc
cmp em_pc $(PC_PATH)
install: em_pc
cp em_pc $(PC_PATH)
lint:
lint -hpxc -I$h em_pc.c
clean:
rm -f *.o *.old em_pc
opr:
make pr ^ opr
pr:
pr -n em_pc.c

681
util/ack/pc/em_pc.c Normal file
View File

@@ -0,0 +1,681 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
/*
* put all the pieces of the pascal part of the EM project together
* original author: Johan Stevenson, Vrije Universiteit, Amsterdam
* heavily modified by: Ed Keizer, Vrije Universiteit, Amsterdam
*/
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <em_path.h>
#include <pc_size.h>
#include <local.h>
#define MAX_FLAG 40 /* The Max. no of '{' flags allowed */
#define void int
char *pc_path = PEM_PATH ;
char *err_path = ERR_PATH;
int toterr;
int parent;
char *eeflag;
char *vvflag = "-V";
int no_pemflag = 0 ;
char *pemflag[MAX_FLAG];
char *eflag;
char *wflag;
int sizes[sz_last+1] = {
2, /* sz_addr */
8, /* sz_real */
0, /* sz_head */
512, /* sz_buff */
4096, /* sz_mset */
2, /* sz_iset */
};
#define CALLSIZE 60
char *callvector[CALLSIZE];
char **av;
int ac;
int fileargs; /* number of recognized, processed args */
int flagargs;
char *progname;
char *source;
#define CHARSIZE 2500
#define CHARMARG 50
char charbuf[CHARSIZE];
char *charp = charbuf;
char *tmp_dir = TMP_DIR;
char *unique = "pcXXXXXX";
char sigs[] = {
SIGHUP,
SIGINT,
SIGTERM,
0
};
/*
* forward function declarations
*/
void finish();
void pem();
int list();
char *flag();
char *tempfile();
char **initvector();
char *basename();
/*
* used library routines and data
*/
extern char *sys_errlist[];
extern int errno;
int atoi();
void exit();
void sleep();
void execv();
char *sbrk();
int chdir();
int fork();
int wait();
int getpid();
int open();
int close();
int read();
main(argc,argv) char **argv; {
register char *p;
char *files[3] ;
for (p = sigs; *p; p++)
if (signal(*p,finish) == SIG_IGN)
signal(*p,SIG_IGN);
ac = argc;
av = argv;
progname = *av++;
init();
while ( --ac>0 ) {
p = *av++;
if (*p == '-') {
flagargs++;
p = flag(p);
} else {
if ( fileargs>=3 ) fatal("Too many file arguments") ;
files[fileargs++]= p;
}
}
if ( fileargs!=3 ) fatal("Not enough arguments") ;
source=files[2] ;
pem(files[0],files[1]) ;
finish();
}
char *flag(f) char *f; {
register char *p;
p = f+1;
switch (*p++) {
case 'e':
eflag = f;
break;
case 'E':
eeflag = f;
break;
case 'w':
wflag = f;
break;
case 'V':
vvflag = f;
return(0);
case '{':
if ( no_pemflag>=MAX_FLAG ) {
ermess("too many flags, ignored %s",f) ;
} else {
pemflag[no_pemflag++] = p;
}
return(0);
case 'R':
pc_path= p ;
return 0 ;
case 'r' :
err_path= p ;
return 0 ;
default:
return(f);
}
if (*p)
fatal("bad flag %s",f);
return(0);
}
initsizes(f) FILE *f; {
register c, i;
register char *p;
p = vvflag + 2;
while (c = *p++) {
i = atoi(p);
while (*p >= '0' && *p <= '9')
p++;
switch (c) {
case 'p': sz_addr = i; continue;
case 'f': sz_real = i; continue;
case 'h': sz_head = i; continue;
case 'b': sz_buff = i; continue;
case 'm': sz_mset = i; continue;
case 'j': sz_iset = i; continue;
case 'w':
case 'i': if (i == 2) continue; break;
case 'l': if (i == 4) continue; break;
}
fatal("bad V-flag %s",vvflag);
}
if (sz_head == 0)
sz_head = 6*sz_word + 2*sz_addr;
for (i = 0; i <= sz_last; i++)
fprintf(f, "%d\n",sizes[i]);
}
/* ------------------ calling sequences -------------------- */
pem(p,q) char *p,*q; {
register char **v,*d;
int i;
FILE *erfil;
v = initvector(pc_path);
d = tempfile('d');
if ((erfil = fopen(d,"w")) == NULL)
syserr(d);
initsizes(erfil);
fprintf(erfil,"%s\n",basename(source));
for ( i=0 ; i<no_pemflag ; i++ ) fprintf(erfil,"%s\n",pemflag[i]);
fclose(erfil);
*v++ = q;
*v++ = d;
call(v,p,(char *)0);
if (toterr == 0)
if (list(p,d) < 0)
toterr++;
donewith(d);
}
/* ------------------- miscellaneous routines --------------- */
char *basename(p) char *p; {
register char *q;
q = p;
while (*q)
if (*q++ == '/')
p = q;
return(p);
}
char *tempfile(suf) {
register char *p,*q;
register i;
p = charp; q = tmp_dir;
while (*p = *q++)
p++;
*p++ = '/';
q = unique;
while (*p = *q++)
p++;
i = fileargs;
do
*p++ = i % 10 + '0';
while (i /= 10);
*p++ = '.'; *p++ = suf; *p++ = '\0';
q = charp; charp = p;
return(q);
}
call(v,in,out) char **v,*in,*out; {
register pid;
int status;
while ((parent = fork()) < 0)
sleep(1);
if (parent == 0) {
if (in) {
close(0);
if (open(in,0) != 0)
syserr(in);
}
if (out) {
close(1);
if (creat(out,0666) != 1)
syserr(out);
}
*v = 0;
execv(callvector[0],callvector+1);
syserr(callvector[0]);
}
while ((pid = wait(&status)) != parent) {
if (pid == -1)
fatal("process %d disappeared",parent);
fatal("unknown child %d died",pid);
}
if ((status & 0177) > 3) {
/*
if ((status & 0200) && tflag==0)
unlink("core");
*/
fatal("signal %d in %s. Ask an expert for help",
status&0177,callvector[0]);
}
if (status & 0177400)
toterr++;
}
char **initvector(path) char *path; {
register char *p,**v;
v = callvector;
p = path;
*v++ = p;
*v++ = basename(p);
return(v);
}
finish() {
register char *p,*q;
register fd;
struct direct dir;
signal(SIGINT,SIG_IGN);
if (parent != 0) {
chdir(tmp_dir);
fd = open(".",0);
while (read(fd,(char *) &dir,sizeof dir) == sizeof dir) {
if (dir.d_ino == 0)
continue;
p = unique;
q = dir.d_name;
while (*p++ == *q++)
if (*p == '\0') {
unlink(dir.d_name);
break;
}
}
close(fd);
}
exit(toterr ? -1 : 0);
}
donewith(p) char *p; {
if (p >= charbuf && p < &charbuf[CHARSIZE])
unlink(p);
}
init() {
register char *p;
register i,fd;
if ((fd = open(tmp_dir,0)) < 0)
tmp_dir = ".";
close(fd);
p = unique+2;
parent = i = getpid();
do
*p++ = i % 10 + '0';
while (i /= 10);
*p++ = '.'; *p = '\0';
}
/* ------------------- pascal listing ----------------------- */
#define MAXERNO 300
#define MAXERRLIST 10
#define IDMAX 8
struct errec {
int erno;
char mess[IDMAX+1];
int mesi;
int chno;
int lino;
};
struct errec curr;
struct errec next;
int *index = 0;
int maxerno;
int errerr;
int errfat;
int listlino;
int listorig;
int listrela;
char *listfnam;
FILE *inpfil;
FILE *mesfil;
FILE *errfil;
int errorline();
int geterrec();
int nexterror();
int list(p,q) char *p,*q; {
if ((errfil = fopen(q,"r")) == NULL)
syserr(q);
if (geterrec() == 0)
if (eeflag==0) {
fclose(errfil);
return(0);
}
if (index == 0) {
index = (int *) sbrk(MAXERNO * sizeof index[0]);
fillindex();
}
if ((inpfil = fopen(p,"r")) == NULL)
syserr(p);
errerr = 0;
errfat = 0;
listlino = 0;
listorig = 0;
listrela = 0;
listfnam = source;
if (eeflag)
listfull();
else if (eflag)
listpartial();
else
listshort();
fclose(errfil);
fclose(inpfil);
fflush(stdout);
return(errfat ? -1 : 1);
}
listshort() {
while (nexterror()) {
while (listlino < curr.lino)
nextline(0);
printf("%s, line %d: ",listfnam,listrela);
string(&curr);
}
}
listfull() {
if (nexterror())
do {
do {
nextline(1);
} while (listlino < curr.lino);
} while (errorline());
while (nextline(1))
;
}
listpartial() {
if (nexterror())
do {
do {
nextline(listlino >= curr.lino-2);
} while (listlino < curr.lino);
} while (errorline());
}
int nextline(printing) {
register ch;
listlino++;
ch = getc(inpfil);
if (ch == '#') {
if (lineline(printing) == 0)
fatal("bad line directive");
return(1);
}
listrela++;
if (listfnam == source)
listorig++;
if (ch != EOF) {
if (printing)
printf("%5d\t",listorig);
do {
if (printing)
putchar(ch);
if (ch == '\n')
return(1);
} while ((ch = getc(inpfil)) != EOF);
}
return(0);
}
lineline(printing) {
register ch;
register char *p,*q;
static char line[100];
p = line;
while ((ch = getc(inpfil)) != '\n') {
if (ch == EOF || p == &line[100-1])
return(0);
*p++ = ch;
}
*p = '\0'; p = line;
if (printing)
printf("\t#%s\n",p);
if ((listrela = atoi(p)-1) < 0)
return(0);
while ((ch = *p++) != '"')
if (ch == '\0')
return(0);
q = p;
while (ch = *p++) {
if (ch == '"') {
*--p = '\0';
if ( source ) {
listfnam = strcmp(q,source)==0 ? source : q;
return(1);
}
source=q ; listfnam=q ;
return 1 ;
}
if (ch == '/')
q = p;
}
return(0);
}
int errorline() {
register c;
register struct errec *p,*q;
struct errec lerr[MAXERRLIST];
int goon;
printf("*** ***");
p = lerr;
c = 0;
do {
if (c < curr.chno) {
printf("%*c",curr.chno-c,'^');
c = curr.chno;
}
if (p < &lerr[MAXERRLIST])
*p++ = curr;
goon = nexterror();
} while (goon && curr.lino==listlino);
putchar('\n');
for (q = lerr; q < p; q++)
string(q);
putchar('\n');
return(goon);
}
int geterrec() {
register ch;
register char *p;
ch = getc(errfil);
next.erno = 0;
next.mesi = -1;
next.mess[0] = '\0';
if (ch == EOF)
return(0);
if (ch >= '0' && ch <= '9') {
ch = getnum(ch,&next.mesi);
} else if (ch == '\'') {
p = next.mess;
while ((ch = getc(errfil)) != ' ' && ch != EOF)
if (p < &next.mess[IDMAX])
*p++ = ch;
*p = '\0';
}
ch = getnum(ch, &next.erno);
ch = getnum(ch, &next.lino);
ch = getnum(ch, &next.chno);
if (ch != '\n')
fatal("bad error line");
return(1);
}
int getnum(ch, ip) register ch; register *ip; {
register neg;
*ip = 0;
while (ch == ' ')
ch = getc(errfil);
if (neg = ch=='-')
ch = getc(errfil);
while (ch >= '0' && ch <= '9') {
*ip = *ip * 10 - '0' + ch;
ch = getc(errfil);
}
if (neg)
*ip = -(*ip);
return(ch);
}
int nexterror() {
do { /* skip warnings if wflag */
curr = next;
if (curr.erno == 0)
return(0);
for (;;) {
if (geterrec() == 0)
break;
if (next.lino != curr.lino || next.chno != curr.chno)
break;
if (curr.erno < 0 && next.erno > 0)
/* promote warnings if they cause fatals */
curr.erno = -curr.erno;
if (next.mess[0] != '\0' || next.mesi != -1)
/* give all parameterized errors */
break;
if (curr.mess[0] != '\0' || curr.mesi != -1)
/* and at least a non-parameterized one */
break;
}
} while (curr.erno < 0 && wflag != 0);
return(1);
}
fillindex() {
register *ip,n,c;
if ((mesfil = fopen(err_path,"r")) == NULL)
syserr(err_path);
ip = index;
*ip++ = 0;
n = 0;
while ((c = getc(mesfil)) != EOF) {
n++;
if (c == '\n') {
*ip++ = n;
if (ip > &index[MAXERNO])
fatal("too many errors on %s",err_path);
}
}
maxerno = ip - index;
}
string(ep) register struct errec *ep; {
register i,n;
errerr++;
if ((i = ep->erno) < 0) {
i = -i;
printf("Warning: ");
} else
errfat++;
if (i == 0 || i >= maxerno)
fatal("bad error number %d",i);
n = index[i] - index[i-1];
fseek(mesfil,(long)index[i-1],0);
while (--n >= 0) {
i = getc(mesfil);
if (i == '%' && --n>=0) {
i = getc(mesfil);
if (i == 'i')
printf("%d", ep->mesi);
else if (i == 's')
printf("%s", ep->mess);
else
putchar(i);
} else
putchar(i);
}
}
/* ------------------- error routines -------------------------- */
/* VARARGS1 */
void ermess(s,a1,a2,a3,a4) char *s; {
fprintf(stderr,"%s: ",progname);
fprintf(stderr,s,a1,a2,a3,a4);
fprintf(stderr,"\n");
}
syserr(s) char *s; {
fatal("%s: %s",s,sys_errlist[errno]);
}
/* VARARGS1 */
void fatal(s,a1,a2,a3,a4) char *s; {
ermess(s,a1,a2,a3,a4);
toterr++;
finish();
}

154
util/ack/run.c Normal file
View File

@@ -0,0 +1,154 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
#include "list.h"
#include "trans.h"
#include "data.h"
#include <signal.h>
#define ARG_MORE 40 /* The size of args chunks to allocate */
static char **arglist ; /* The first argument */
static unsigned argcount ; /* The current number of arguments */
static unsigned argmax; /* The maximum number of arguments so far */
int do_run() {
fatal("-g flag not implemeted") ;
/*NOTREACHED*/
return 0 ;
}
int runphase(phase) register trf *phase ; {
register list_elem *elem ;
if ( v_flag || debug ) {
if ( v_flag==1 && !debug ) {
vprint("%s",phase->t_name) ;
if ( !phase->t_combine ) {
vprint(" %s%s\n",p_basename,
rindex(in.p_path,SUFCHAR) ) ;
} else {
scanlist(l_first(c_arguments), elem) {
vprint(" %s",l_content(*elem)) ;
}
vprint("\n") ;
}
} else {
/* list all args */
vprint("%s",phase->t_prog) ;
scanlist(l_first(phase->t_flags), elem) {
vprint(" %s",l_content(*elem)) ;
}
scanlist(l_first(phase->t_args), elem) {
vprint(" %s",l_content(*elem)) ;
}
vprint("\n") ;
}
}
argcount=0 ;
x_arg(phase->t_name) ;
scanlist(l_first(phase->t_flags), elem) {
x_arg(l_content(*elem)) ;
}
scanlist(l_first(phase->t_args), elem) {
x_arg(l_content(*elem)) ;
}
x_arg( (char *)0 ) ;
return run_exec(phase) ;
}
int run_exec(phase) trf *phase ; {
int status, child, waitchild ;
do_flush();
while ( (child=fork())== -1 ) ;
if ( child ) {
/* The parent */
do {
waitchild= wait(&status) ;
if ( waitchild== -1 ) {
fatal("missing child") ;
}
} while ( waitchild!=child) ;
if ( status ) {
if ( status&0200 && (status&0177)!=SIGQUIT &&
!t_flag ) unlink("core") ;
switch ( status&0177 ) {
case 0 :
break ;
case SIGHUP:
case SIGINT:
case SIGQUIT:
case SIGTERM:
quit(-5) ;
default:
error("%s died with signal %d",
phase->t_prog,status&0177) ;
}
/* The assumption is that processes voluntarely
dying with a non-zero status already produced
some sort of error message to the outside world.
*/
n_error++ ;
return 0 ;
}
return 1 ; /* From the parent */
}
/* The child */
if ( phase->t_stdin ) {
if ( !in.p_path ) {
fatal("no input file for %s",phase->t_name) ;
}
close(0) ;
if ( open(in.p_path,0)!=0 ) {
error("cannot open %s",in.p_path) ;
exit(1) ;
}
}
if ( phase->t_stdout ) {
if ( !out.p_path ) {
fatal("no output file for %s",phase->t_name) ;
}
close(1) ;
if ( creat(out.p_path,0666)!=1 ) {
close(1); dup(2);
error("cannot open %s",out.p_path) ;
exit(1) ;
}
}
execv(phase->t_prog,arglist) ;
if ( phase->t_stdout ) { close(1) ; dup(2) ; }
error("Cannot execute %s",phase->t_prog) ;
exit(1) ;
/*NOTREACHED*/
}
x_arg(string) char *string ; {
/* Add one execute argument to the argument vector */
if ( argcount==argmax ) {
if ( argmax==0 ) {
argmax= 2*ARG_MORE ;
arglist= (char **)getcore(argmax*sizeof (char *)) ;
} else {
argmax += ARG_MORE ;
arglist= (char **)changecore((char *)arglist,
argmax*sizeof (char *)) ;
}
}
*(arglist+argcount++) = string ;
}

244
util/ack/scan.c Normal file
View File

@@ -0,0 +1,244 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
#include "list.h"
#include "trans.h"
#include "data.h"
enum f_path setpath() { /* Try to find a transformation path */
start_scan();
/*
The end result is the setting of the t_do flags
in the transformation list.
The list is scanned for possible transformations
stopping at stopsuffix or a combine transformation.
The scan flags are set by this process.
When a transformation is found, it is compared with
the last transformation found, if better (or the first)
the scan bits are copied to the t_do bits, except for
the combiner which is remembered in a global pointer.
At the end of all transformations for all files, the combiner
is called, unless errors occurred.
*/
try(l_first(tr_list),p_suffix);
return scan_end();
}
/******************** data used only while scanning *******************/
static int last_ncount; /* The # of non-optimizing transformations
in the best path sofar */
static int last_ocount; /* The # of optimizing transformations in the
best path sofar */
static int com_err; /* Complain only once about multiple linkers*/
static trf *final; /* The last non-combining transformation */
static int suf_found; /* Was the suffix at least recognized ? */
/******************** The hard work ********************/
start_scan() {
register list_elem *scan ;
scanlist(l_first(tr_list),scan) {
t_cont(*scan)->t_do=NO ; t_cont(*scan)->t_scan=NO ;
t_cont(*scan)->t_keep=NO ;
}
final= (trf *)0 ;
suf_found= 0 ;
#ifdef DEBUG
if ( debug>=3 ) vprint("Scan_start\n");
#endif
last_ncount= -1 ;
last_ocount= 0 ;
}
try(f_scan,suffix) list_elem *f_scan; char *suffix; {
register list_elem *scan ;
register trf *trafo ;
/* Try to find a transformation path starting at f_scan for a
file with the indicated suffix.
If the suffix is already reached or the combiner is found
call scan_found() to OK the scan.
If a transformation is found it calls itself recursively
with as starting point the next transformation in the list.
*/
if ( stopsuffix && *stopsuffix && strcmp(stopsuffix,suffix)==0 ) {
scan_found();
return ;
}
scanlist(f_scan, scan) {
trafo= t_cont(*scan) ;
if ( satisfy(trafo,suffix) ) {
/* Found a transformation */
suf_found= 1;
#ifdef DEBUG
if ( debug>=4 ) {
vprint("Found %s for %s: result %s\n",
trafo->t_name,suffix,trafo->t_out);
}
#endif
trafo->t_scan=YES ;
if ( trafo->t_prep ) {
if ( !cpp_trafo ) {
find_cpp() ;
}
if ( stopsuffix &&
strcmp(stopsuffix,
cpp_trafo->t_out)==0 )
{
scan_found() ;
return ;
}
}
if ( trafo->t_combine ) {
if ( stopsuffix ) {
trafo->t_scan=NO;
if ( *stopsuffix ) return ;
} else {
if( combiner &&
combiner!=trafo && !com_err ){
com_err++ ;
werror("Multiple linkers present %s and %s",
trafo->t_name,combiner->t_name) ;
} else {
combiner=trafo;
}
}
scan_found() ;
} else {
try(l_next(*scan),trafo->t_out);
}
trafo->t_scan= NO ;
}
}
}
scan_found() {
register list_elem *scan;
int ncount, ocount ;
register trf *keepit ;
keepit= (trf *)0 ;
suf_found= 1;
#ifdef DEBUG
if ( debug>=3 ) vprint("Scan found\n") ;
#endif
/* Gather data used in comparison */
ncount=0; ocount=0;
scanlist(l_first(tr_list),scan) {
if (t_cont(*scan)->t_scan) {
#ifdef DEBUG
if ( debug>=4 ) vprint("%s-",t_cont(*scan)->t_name) ;
#endif
if( t_cont(*scan)->t_optim ) ocount++ ;else ncount++ ;
if ( !(t_cont(*scan)->t_combine) ) {
keepit= t_cont(*scan) ;
}
}
}
#ifdef DEBUG
if ( debug>=4 ) vprint("\n");
#endif
/* Is this transformation better then any found yet ? */
#ifdef DEBUG
if ( debug>=3 ) {
vprint("old n:%d, o:%d - new n:%d, o:%d\n",
last_ncount,last_ocount,ncount,ocount) ;
}
#endif
if ( last_ncount== -1 || /* None found yet */
last_ncount>ncount || /* Shorter nec. path */
(last_ncount==ncount && /* Same nec. path, optimize?*/
(Optflag? last_ocount<ocount : last_ocount>ocount ) ) ) {
/* Yes it is */
#ifdef DEBUG
if ( debug>=3 ) vprint("Better\n");
#endif
scanlist(l_first(tr_list),scan) {
t_cont(*scan)->t_do=t_cont(*scan)->t_scan;
}
last_ncount=ncount; last_ocount=ocount;
if ( keepit ) final=keepit ;
}
}
int satisfy(trafo,suffix) register trf *trafo; char *suffix ; {
register char *f_char, *l_char ;
/* Check whether this transformation is present for
the current machine and the parameter suffix is among
the input suffices. If so, return 1. 0 otherwise
*/
if ( trafo->t_isprep ) return 0 ;
l_char=trafo->t_in ;
while ( l_char ) {
f_char= l_char ;
if ( *f_char!=SUFCHAR || ! *(f_char+1) ) {
fuerror("Illegal input suffix entry for %s",
trafo->t_name) ;
}
l_char=index(f_char+1,SUFCHAR);
if ( l_char ? strncmp(f_char,suffix,l_char-f_char)==0 :
strcmp(f_char,suffix)==0 ) {
return 1 ;
}
}
return 0 ;
}
enum f_path scan_end() { /* Finalization */
/* Return value indicating whether a transformation was found */
/* Set the flags for the transformation up to, but not including,
the combiner
*/
#ifdef DEBUG
if ( debug>=3 ) vprint("End_scan\n");
#endif
if ( last_ncount== -1 ) return suf_found ? F_NOPATH : F_NOMATCH ;
#ifdef DEBUG
if ( debug>=2 ) vprint("Transformation found\n");
#endif
if ( cpp_trafo && stopsuffix &&
strcmp(stopsuffix,cpp_trafo->t_out)==0 ) {
final= cpp_trafo ;
}
/* There might not be a final when the file can be eaten
by the combiner
*/
if ( final ) final->t_keep=YES ;
if ( combiner ) {
if ( !combiner->t_do ) error("Combiner YES/NO");
combiner->t_do=NO ;
}
return F_OK ;
}
find_cpp() {
register list_elem *elem ;
scanlist( l_first(tr_list), elem ) {
if ( t_cont(*elem)->t_isprep ) {
if ( cpp_trafo ) fuerror("Multiple cpp's present") ;
cpp_trafo= t_cont(*elem) ;
}
}
if ( !cpp_trafo ) fuerror("No cpp present") ;
}

125
util/ack/svars.c Normal file
View File

@@ -0,0 +1,125 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
/* The processing of string valued variables,
this is an almost self contained module.
Five externally visible routines:
setsvar(name,result)
Associate the name with the result.
name a string pointer
result a string pointer
setpvar(name,routine)
Associate the name with the routine.
name a string pointer
routine a routine id
The parameters name and result are supposed to be pointing to
non-volatile string storage used only for this call.
char *getvar(name)
returns the pointer to a string associated with name,
the pointer is produced by returning result or the
value returned by calling the routine.
name a string pointer
Other routines called
fatal(args*) When something goes wrong
getcore(size) Core allocation
*/
extern char *getcore();
extern fatal();
struct vars {
char *v_name;
enum { routine, string } v_type;
union {
char *v_string;
char *(*v_routine)();
} v_value ;
struct vars *v_next ;
};
static struct vars *v_first ;
static struct vars *newvar(name) char *name; {
register struct vars *new ;
for ( new=v_first ; new ; new= new->v_next ) {
if ( strcmp(name,new->v_name)==0 ) {
throws(name) ;
if ( new->v_type== string ) {
throws(new->v_value.v_string) ;
}
return new ;
}
}
new= (struct vars *)getcore( (unsigned)sizeof (struct vars));
new->v_name= name ;
new->v_next= v_first ;
v_first= new ;
return new ;
}
setsvar(name,str) char *name, *str ; {
register struct vars *new ;
new= newvar(name);
#ifdef DEBUG
if ( debug>=2 ) vprint("%s=%s\n", name, str) ;
#endif
new->v_type= string;
new->v_value.v_string= str;
}
setpvar(name,rout) char *name, *(*rout)() ; {
register struct vars *new ;
new= newvar(name);
#ifdef DEBUG
if ( debug>=2 ) vprint("%s= (*%o)()\n",name,rout) ;
#endif
new->v_type= routine;
new->v_value.v_routine= rout;
}
char *getvar(name) char *name ; {
register struct vars *scan ;
for ( scan=v_first ; scan ; scan= scan->v_next ) {
if ( strcmp(name,scan->v_name)==0 ) {
switch ( scan->v_type ) {
case string:
return scan->v_value.v_string ;
case routine:
return (*scan->v_value.v_routine)() ;
}
}
}
return (char *)0 ;
}

672
util/ack/trans.c Normal file
View File

@@ -0,0 +1,672 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
#include "ack.h"
#include "list.h"
#include "trans.h"
#include "grows.h"
#include "data.h"
/****************************************************************************/
/* Routines for transforming from one file type to another */
/****************************************************************************/
static growstring head ;
static int touch_head= NO ;
static growstring tail ;
static int touch_tail= NO ;
char *headvar(),*tailvar() ;
int transform(phase) register trf *phase ; {
int ok ;
if ( !setfiles(phase) ) return 0 ;
if ( !phase->t_visited ) {
/* The flags are set up once.
At the first time the phase is used.
The program name and flags may already be touched
by vieuwargs.
*/
phase->t_visited=YES ;
if ( !rts && phase->t_rts ) rts= phase->t_rts ;
if ( phase->t_needed ) {
add_head(phase->t_needed) ;
add_tail(phase->t_needed) ;
}
}
getcallargs(phase) ;
ok= runphase(phase) ;
if ( !ok ) rmtemps() ;
/* Free the space occupied by the arguments,
except for the combiner, since we are bound to exit soon
and do not foresee further need of memory space */
if ( !phase->t_combine ) discardargs(phase) ;
disc_files() ;
return ok ;
}
int do_combine() {
setsvar(keeps(RTS), keeps(rts? rts : "") ) ;
if ( !outfile ) outfile= combiner->t_out ;
getmapflags(combiner);
return transform(combiner) ;
}
getmapflags(phase) register trf *phase ; {
register list_elem *elem ;
int scanned ;
register char *ptr ;
scanlist(l_first(flags),elem) {
scanned= *(l_content(*elem))&NO_SCAN ;
*(l_content(*elem)) &= ~NO_SCAN ;
if ( mapflag(&(phase->t_mapf),l_content(*elem)) ) {
scanned=NO_SCAN ;
#ifdef DEBUG
if ( debug >=4 ) {
vprint("phase %s, added mapflag for %s\n",
phase->t_name,
l_content(*elem) ) ;
}
#endif
}
*(l_content(*elem)) |= scanned ;
}
if ( phase->t_combine ) {
scanlist(l_first(c_arguments),elem) {
if ( mapflag(&(phase->t_mapf),l_content(*elem)) ) {
throws(l_content(*elem)) ;
ptr= keeps(getvar(LIBVAR)) ;
clr_noscan(ptr) ;
l_content(*elem)= ptr ;
}
}
scanlist(l_first(flags),elem) {
/* Get the flags remaining for the loader,
That is: all the flags neither eaten by ack nor
one of the subprograms called so-far.
The last fact is indicated by the NO_SCAN bit
in the first character of the flag.
*/
if ( !( *(l_content(*elem))&NO_SCAN ) ) {
l_add(&(phase->t_flags),l_content(*elem)) ;
}
}
}
}
do_Rflag(argp) char *argp ; {
l_add(&R_list,argp) ;
}
char *needvar() {
static growstring needed ;
static int been_here = NO ;
if ( !been_here ) {
gr_init(&needed) ;
been_here=YES ;
gr_cat(&needed,headvar()) ;
gr_cat(&needed,tailvar()) ;
}
return gr_start(needed) ;
}
char *headvar() {
if ( !touch_head) return "" ;
return gr_start(head) ;
}
add_head(str) char *str; {
if ( !touch_head) {
gr_init(&head) ;
touch_head=YES ;
}
gr_cat(&head,str) ;
}
char *tailvar() {
if ( !touch_tail ) return "" ;
return gr_start(tail) ;
}
add_tail(str) char *str ; {
if ( !touch_tail ) {
gr_init(&tail) ;
touch_tail=YES ;
}
gr_cat(&tail,str) ;
}
transini() {
register list_elem *elem ;
register trf *phase ;
scanlist(l_first(R_list), elem) {
set_Rflag(l_content(*elem)) ;
}
l_clear(&R_list) ;
scanlist(l_first(tr_list), elem) {
phase = t_cont(*elem) ;
if ( !phase->t_combine ) getmapflags(phase);
}
setpvar(keeps(NEEDS),needvar) ;
setpvar(keeps(HEAD),headvar) ;
setpvar(keeps(TAIL),tailvar) ;
}
set_Rflag(argp) register char *argp ; {
int seen ;
register char *eos ;
register list_elem *prog ;
register int length ;
char *eq ;
eos= index(&argp[2],'-');
eq= index(&argp[2],EQUAL) ;
if ( !eos ) {
eos= eq ;
} else {
if ( eq && eq<eos ) eos= eq ;
}
if ( !eos ) fuerror("Incorrect use of -R flag") ;
length= eos - &argp[2] ;
seen=NO ;
scanlist(l_first(tr_list), prog) {
if ( strncmp(t_cont(*prog)->t_name, &argp[2], length )==0 ) {
if ( *eos=='-' ) {
l_add(&(t_cont(*prog)->t_flags),eos) ;
} else {
t_cont(*prog)->t_prog= eos+1 ;
}
seen=YES ;
}
}
if ( !seen ) error("Cannot find program for %s",argp) ;
return ;
}
/**************************************************************************/
/* */
/* The creation of arguments for exec for a transformation */
/* */
/**************************************************************************/
growstring scanb(line) char *line ; {
/* Scan a line for backslashes, setting the NO_SCAN bit in characters
preceded by a backslash.
*/
register char *in_c ;
register int token ;
growstring result ;
enum { TEXT, ESCAPED } state = TEXT ;
gr_init(&result) ;
for ( in_c= line ; *in_c ; in_c++ ) {
token= *in_c&0377 ;
switch( state ) {
case TEXT :
if ( token==BSLASH ) {
state= ESCAPED ;
} else {
gr_add(&result,token) ;
}
break ;
case ESCAPED :
gr_add(&result,token|NO_SCAN) ;
state=TEXT ;
break ;
}
}
gr_add(&result,0) ;
if ( state!=TEXT ) werror("flag line ends with %c",BSLASH) ;
return result ;
}
growstring scanvars(line) char *line ; {
/* Scan a line variable replacements started by S_VAR.
Two sequences exist: S_VAR name E_VAR, S_VAR name A_VAR text E_VAR.
neither name nor text may contain further replacements.
In the first form an error message is issued if the name is not
present in the variables, the second form produces text
in that case.
The sequence S_VAR S_VAR is transformed into S_VAR.
This to allow later recognition in mapflags, where B_SLASH
would be preventing any recognition.
*/
register char *in_c ;
register int token ;
growstring result ;
growstring name ;
register char *tr ;
enum { TEXT, FIRST, NAME, SKIP, COPY } state = TEXT ;
gr_init(&result) ; gr_init(&name) ;
for ( in_c= line ; *in_c ; in_c++ ) {
token= *in_c&0377 ;
switch( state ) {
case TEXT :
if ( token==S_VAR ) {
state= FIRST ;
} else {
gr_add(&result,token) ;
}
break ;
case FIRST :
switch ( token ) {
case S_VAR :
state= TEXT ;
gr_add(&result,token) ;
break ;
case A_VAR :
case C_VAR :
fatal("empty string variable name") ;
default :
state=NAME ;
gr_add(&name,token) ;
break ;
}
break ;
case NAME:
switch ( token ) {
case A_VAR :
gr_add(&name,0) ;
if ( tr=getvar(gr_start(name)) ) {
while ( *tr ) {
gr_add(&result,*tr++) ;
}
state=SKIP ;
} else {
state=COPY ;
}
gr_throw(&name) ;
break ;
case C_VAR :
gr_add(&name,0) ;
if ( tr=getvar(gr_start(name)) ) {
while ( *tr ) {
gr_add(&result,*tr++);
}
} else {
werror("No definition for %s",
gr_start(name)) ;
}
state=TEXT ;
gr_throw(&name) ;
break ;
default:
gr_add(&name,token) ;
break ;
}
break ;
case SKIP :
if ( token==C_VAR ) state= TEXT ;
break ;
case COPY :
if ( token==C_VAR ) state= TEXT ; else {
gr_add(&result,token) ;
}
break ;
}
}
gr_add(&result,0) ;
if ( state!=TEXT ) {
werror("flag line misses %c",C_VAR) ;
gr_throw(&name) ;
}
return result ;
}
growstring scanexpr(line) char *line ; {
/* Scan a line for conditional or flag expressions,
dependent on the type. The format is
S_EXPR suflist M_EXPR suflist T_EXPR tail C_EXPR
the head and tail are passed to treat, together with the
growstring for futher treatment.
Nesting is not allowed.
*/
register char *in_c ;
char *heads ;
register int token ;
growstring sufs, tailval ;
growstring result ;
static list_head fsuff, lsuff ;
enum { TEXT, FDOT, FSUF, LDOT, LSUF, FTAIL } state = TEXT ;
gr_init(&result) ; gr_init(&sufs) ; gr_init(&tailval) ;
for ( in_c= line ; *in_c ; in_c++ ) {
token= *in_c&0377 ;
switch( state ) {
case TEXT :
if ( token==S_EXPR ) {
state= FDOT ;
heads=in_c ;
} else gr_add(&result,token) ;
break ;
case FDOT :
if ( token==M_EXPR ) {
state=LDOT ;
break ;
}
token &= ~NO_SCAN ;
if ( token!=SUFCHAR ) {
error("Missing %c in expression",SUFCHAR) ;
}
gr_add(&sufs,token) ; state=FSUF ;
break ;
case FSUF :
if ( token==M_EXPR || (token&~NO_SCAN)==SUFCHAR) {
gr_add(&sufs,0) ;
l_add(&fsuff,gr_final(&sufs)) ;
}
if ( token==M_EXPR ) {
state=LDOT ;
} else gr_add(&sufs,token&~NO_SCAN) ;
break ;
case LDOT :
if ( token==T_EXPR ) {
state=FTAIL ;
break ;
}
token &= ~NO_SCAN ;
if ( token!=SUFCHAR ) {
error("Missing %c in expression",SUFCHAR) ;
}
gr_add(&sufs,token) ; state=LSUF ;
break ;
case LSUF :
if ( token==T_EXPR || (token&~NO_SCAN)==SUFCHAR) {
gr_add(&sufs,0) ;
l_add(&lsuff,gr_final(&sufs)) ;
}
if ( token==T_EXPR ) {
state=FTAIL ;
} else gr_add(&sufs,token&~NO_SCAN) ;
break ;
case FTAIL :
if ( token==C_EXPR ) {
/* Found one !! */
gr_add(&tailval,0) ;
condit(&result,&fsuff,&lsuff,gr_start(tailval)) ;
l_throw(&fsuff) ; l_throw(&lsuff) ;
gr_throw(&tailval) ;
state=TEXT ;
} else gr_add(&tailval,token) ;
break ;
}
}
gr_add(&result,0) ;
if ( state!=TEXT ) {
l_throw(&fsuff) ; l_throw(&lsuff) ; gr_throw(&tailval) ;
werror("flag line has unclosed expression starting with %6s",
heads) ;
}
return result ;
}
condit(line,fsuff,lsuff,tailval) growstring *line ;
list_head *fsuff, *lsuff;
char *tailval ;
{
register list_elem *first ;
register list_elem *last ;
#ifdef DEBUG
if ( debug>=4 ) vprint("Conditional for %s, ",tailval) ;
#endif
scanlist( l_first(*fsuff), first ) {
scanlist( l_first(*lsuff), last ) {
if ( strcmp(l_content(*first),l_content(*last))==0 ) {
/* Found */
#ifdef DEBUG
if ( debug>=4 ) vprint(" matched\n") ;
#endif
while ( *tailval) gr_add(line,*tailval++ ) ;
return ;
}
}
}
#ifdef DEBUG
if ( debug>=4) vprint(" non-matched\n") ;
#endif
}
int mapflag(maplist,cflag) list_head *maplist ; char *cflag ; {
/* Expand a flag expression */
/* The flag "cflag" is checked for each of the mapflags.
A mapflag entry has the form
-text NAME=replacement or -text*text NAME=replacement
The star matches anything as in the shell.
If the entry matches the assignment will take place
This replacement is subjected to argument matching only.
When a match took place the replacement is returned
when not, (char *)0.
The replacement sits in stable storage.
*/
register list_elem *elem ;
scanlist(l_first(*maplist),elem) {
if ( mapexpand(l_content(*elem),cflag) ) {
return 1 ;
}
}
return 0 ;
}
int mapexpand(mapentry,cflag)
char *mapentry, *cflag ;
{
register char *star ;
register char *ptr ;
register char *space ;
int length ;
star=index(mapentry,STAR) ;
space=firstblank(mapentry) ;
if ( star >space ) star= (char *)0 ;
if ( star ) {
length= space-star-1 ;
if ( strncmp(mapentry,cflag,star-mapentry) ||
strncmp(star+1,cflag+strlen(cflag)-length,length) ) {
return 0 ;
}
/* Match */
/* Now set star to the first char of the star
replacement and length to its length
*/
length=strlen(cflag)-(star-mapentry)-length ;
if ( length<0 ) return 0 ;
star=cflag+(star-mapentry) ;
#ifdef DEBUG
if ( debug>=6 ) {
vprint("Starmatch (%s,%s) %.*s\n",
mapentry,cflag,length,star) ;
}
#endif
} else {
if ( strncmp(mapentry,cflag,space-mapentry)!=0 ||
cflag[space-mapentry] ) {
return 0 ;
}
}
ptr= skipblank(space) ;
if ( *ptr==0 ) return 1 ;
doassign(ptr,star,length) ;
return 1 ;
}
doassign(line,star,length) char *line, *star ; {
growstring varval, name, temp ;
register char *ptr ;
gr_init(&varval) ;
gr_init(&name) ;
ptr= line ;
for ( ; *ptr && *ptr!=SPACE && *ptr!=TAB && *ptr!=EQUAL ; ptr++ ) {
gr_add(&name,*ptr) ;
}
ptr= index(ptr,EQUAL) ;
if ( !ptr ) {
error("Missing %c in assignment %s",EQUAL,line);
return ;
}
temp= scanvars(ptr+1) ;
for ( ptr=gr_start(temp); *ptr; ptr++ ) switch ( *ptr ) {
case STAR :
if ( star ) {
while ( length-- ) gr_add(&varval,*star++|NO_SCAN) ;
break ;
}
default :
gr_add(&varval,*ptr) ;
break ;
}
gr_throw(&temp) ;
setsvar(gr_final(&name),gr_final(&varval)) ;
}
#define ISBLANK(c) ( (c)==SPACE || (c)==TAB )
unravel(line,action) char *line ; int (*action)() ; {
/* Unravel the line, get arguments a la shell */
/* each argument is handled to action */
/* The input string is left intact */
register char *in_c ;
register int token ;
enum { BLANK, ARG } state = BLANK ;
growstring argum ;
in_c=line ;
for (;;) {
token= *in_c&0377 ;
switch ( state ) {
case BLANK :
if ( token==0 ) break ;
if ( !ISBLANK(token) ) {
state= ARG ;
gr_init(&argum) ;
gr_add(&argum,token&~NO_SCAN) ;
}
break ;
case ARG :
if ( ISBLANK(token) || token==0 ) {
gr_add(&argum,0) ;
(*action)(gr_start(argum)) ;
gr_throw(&argum) ;
state=BLANK ;
} else {
gr_add(&argum,token&~NO_SCAN) ;
}
break ;
}
if ( token == 0 ) break ;
in_c++ ;
}
}
char *c_rep(string,place,rep) char *string, *place, *rep ; {
/* Produce a string in stable storage produced from 'string'
with the character at place replaced by rep
*/
growstring name ;
register char *nc ;
register char *xc ;
gr_init(&name) ;
for ( nc=string ; *nc && nc<place ; nc++ ) {
gr_add(&name,*nc) ;
}
#ifdef DEBUG
if ( *nc==0 ) fatal("Place is not in string") ;
#endif
for ( xc=rep ; *xc ; xc++ ) gr_add(&name,*xc|NO_SCAN) ;
gr_add(&name,0) ;
gr_cat(&name,nc+1) ;
return gr_final(&name) ;
}
static list_head *curargs ;
addargs(string) char *string ; {
register char *temp, *repc ;
register list_elem *elem ;
repc=index(string,C_IN) ;
if ( repc ) {
/* INPUT FILE TOKEN seen, replace it and scan further */
if ( repc==string && string[1]==0 ) {
if ( in.p_path ) { /* All but combiner */
l_add(curargs,keeps(in.p_path)) ;
} else {
scanlist( l_first(c_arguments), elem ) {
l_add(curargs,l_content(*elem)) ;
}
}
return ;
}
if ( in.p_path ) { /* Not for the combiner */
temp=c_rep(string,repc,in.p_path) ;
addargs(temp) ;
throws(temp) ;
} else { /* For the combiner */
scanlist( l_first(c_arguments), elem ) {
temp=c_rep(string,repc,l_content(*elem)) ;
addargs(temp) ;
throws(temp) ;
}
}
return ;
}
repc=index(string,C_OUT) ;
if ( repc ) {
/* replace the outfile token as with the infile token */
#ifdef DEBUG
if ( !out.p_path ) fatal("missing output filename") ;
#endif
temp=c_rep(string,repc,out.p_path) ;
addargs(temp) ;
throws(temp) ;
return ;
}
temp= keeps(string) ;
clr_noscan(temp) ;
l_add(curargs,temp) ;
}
getcallargs(phase) register trf *phase ; {
growstring arg1, arg2 ;
arg1= scanvars(phase->t_argd) ;
#ifdef DEBUG
if ( debug>=3 ) { vprint("\tvars: ") ; prns(gr_start(arg1)) ; }
#endif
arg2= scanexpr(gr_start(arg1)) ;
#ifdef DEBUG
if ( debug>=3 ) { vprint("\texpr: ") ; prns(gr_start(arg2)) ; }
#endif
gr_throw(&arg1) ;
curargs= &phase->t_args ;
unravel( gr_start(arg2), addargs ) ;
gr_throw(&arg2) ;
}
discardargs(phase) register trf *phase ; {
l_throw(&phase->t_args) ;
}

30
util/ack/trans.h Normal file
View File

@@ -0,0 +1,30 @@
/* This structure is the center of all actions */
/* It contains the description of all phases,
the suffices they consume and produce and various properties */
typedef struct transform trf;
struct transform {
char *t_in ; /* Suffices in '.o.k' */
char *t_out ; /* Result '.suffix' or 'name' */
char *t_name ; /* The name of this transformation */
list_head t_mapf ; /* Mapflags argument, uses varrep */
char *t_argd ; /* Argument descriptor, uses varrep */
char *t_needed ; /* Suffix indicating the libraries needed */
char *t_rts ; /* Suffix indicating the major language used*/
int t_stdin:1 ; /* The input is taken on stdin */
int t_stdout:1 ; /* The output comes on stdout */
int t_combine:1 ; /* Transform several files to one result */
int t_visited:1 ; /* NO before setup, YES after */
int t_prep:2 ; /* Needs preprocessor YES/NO/MAYBE */
int t_optim:1 ; /* Is optimizer */
int t_isprep:1 ; /* Is preprocessor */
int t_keep:1 ; /* Keep the output file */
char *t_prog ; /* Pathname for load file */
list_head t_flags ; /* List of flags */
list_head t_args ; /* List of arguments */
int t_scan:1 ; /* Used while finding path's */
int t_do:1 ; /* Is in path to execute */
} ;
#define t_cont(elem) ((trf *)l_content(elem))

190
util/ack/util.c Normal file
View File

@@ -0,0 +1,190 @@
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
/**********************************************************************/
/* */
/* Several utility routines used throughout ack */
/* error handling, string handling and such. */
/* */
/**********************************************************************/
#include "ack.h"
#include <ctype.h>
#include <stdio.h>
extern char *progname ;
extern int w_flag ;
extern int n_error;
extern char *calloc();
extern char *realloc();
#ifdef DEBUG
# define STDOUT stdout
#else
# define STDOUT stderr
#endif
char *basename(string) char *string ; {
static char retval[20] ;
char *last_dot, *last_start ;
register char *store;
register char *fetch ;
register int ctoken ;
last_dot= (char *)0 ;
last_start= string ;
for ( fetch=string ; ; fetch++ ) {
switch ( ctoken= *fetch&0377 ) {
case SUFCHAR : last_dot=fetch ; break ;
case '/' : last_start=fetch+1 ; break ;
case 0 : goto out ;
}
if ( !isascii(ctoken) || !isprint(ctoken) ) {
werror("non-ascii characters in argument %s",string) ;
}
}
out:
if ( ! *last_start ) fuerror("empty filename \"%s\"",string) ;
for ( fetch= last_start, store=retval ;
*fetch && fetch!=last_dot && store< &retval[sizeof retval-1] ;
fetch++, store++ ) {
*store= *fetch ;
}
*store= 0 ;
return retval ;
}
clr_noscan(str) char *str ; {
register char *ptr ;
for ( ptr=str ; *ptr ; ptr++ ) {
*ptr&= ~NO_SCAN ;
}
}
char *skipblank(str) char *str ; {
register char *ptr ;
for ( ptr=str ; *ptr==SPACE || *ptr==TAB ; ptr++ ) ;
return ptr ;
}
char *firstblank(str) char *str ; {
register char *ptr ;
for ( ptr=str ; *ptr && *ptr!=SPACE && *ptr!=TAB ; ptr++ ) ;
return ptr ;
}
/* VARARGS1 */
fatal(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
/* Fatal internal error */
fprintf(STDOUT,"%s: fatal internal error, ",progname) ;
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
fprintf(STDOUT,"\n") ;
quit(-2) ;
}
/* VARARGS1 */
vprint(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
/* Diagnostic print, no auto NL */
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
}
#ifdef DEBUG
prns(s) register char *s ; {
for ( ; *s ; s++ ) {
putc((*s&0377)&~NO_SCAN,STDOUT) ;
}
putc('\n',STDOUT) ;
}
#endif
/* VARARGS1 */
fuerror(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
/* Fatal user error */
fprintf(STDOUT,"%s: ",progname) ;
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
fprintf(STDOUT,"\n") ;
quit(-1) ;
}
/* VARARGS1 */
werror(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
/* Warning user error, w_flag */
if ( w_flag ) return ;
fprintf(STDOUT,"%s: warning, ",progname) ;
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
fprintf(STDOUT,"\n") ;
}
/* VARARGS1 */
error(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
/* User error, it is the callers responsibility to quit */
fprintf(STDOUT,"%s: ",progname) ;
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
fprintf(STDOUT,"\n") ;
n_error++ ;
}
do_flush() {
fflush(stdout) ;
fflush(stderr) ;
}
noodstop() {
quit(-3) ;
}
quit(code) {
rmtemps();
exit(code);
}
/******
char *keeps(string)
Keep the string in stable storage.
throws(string)
Remove the string stored by keep from stable storage.
***********/
char *keeps(str) char *str ; {
register char *result ;
result= getcore( (unsigned)(strlen(str)+1) ) ;
if ( !result ) fatal("Out of core") ;
return strcpy(result,str) ;
}
throws(str) char *str ; {
freecore(str) ;
}
char *getcore(size) unsigned size ; {
register char *retptr ;
retptr= calloc(1,size) ;
if ( !retptr ) fatal("Out of memory") ;
return retptr ;
}
char *changecore(ptr,size) char *ptr ; unsigned size ; {
register char *retptr ;
retptr= realloc(ptr,size) ;
if ( !retptr ) fatal("Out of memory") ;
return retptr ;
}

30
util/cgg/Makefile Normal file
View File

@@ -0,0 +1,30 @@
# $Header$
PREFLAGS=-I../../h
CFLAGS=$(PREFLAGS)
LDFLAGS=-i
LINTOPTS=-hbxac $(PREFLAGS)
LIBS=../../lib/em_data.a
# LEXLIB is system dependent, try -ll or -lln first
LEXLIB=-lln
cgg: bootgram.o
cc $(LDFLAGS) bootgram.o $(LIBS) $(LEXLIB) -o cgg
bootgram.c: bootgram.y
@echo expect 1 shift/reduce conflict
yacc bootgram.y
mv y.tab.c bootgram.c
install: cgg
cp cgg ../../lib/cgg
cmp: cgg
cmp cgg ../../lib/cgg
lint: bootgram.c
lint $(LINTOPTS) bootgram.c
clean:
rm -f bootgram.o bootgram.c bootlex.c cgg
bootgram.o: bootlex.c
bootgram.o: ../../h/cg_pattern.h

2317
util/cgg/bootgram.y Normal file

File diff suppressed because it is too large Load Diff

189
util/cgg/bootlex.l Normal file
View File

@@ -0,0 +1,189 @@
%{
#ifndef NORCSID
static char rcsid2[]="$Header$";
#endif
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
#undef input
#undef output
#undef unput
#define MAXBACKUP 50
%}
%%
"/*" { char c;
c = input();
do {
while (c!='*')
c = input();
c = input();
} while (c!='/');
}
"REGISTERS:" return(REGISTERHEAD);
"TOKENS:" return(TOKENHEAD);
"TOKENEXPRESSIONS:" return(EXPRESSIONHEAD);
"CODE:" return(CODEHEAD);
"MOVES:" return(MOVEHEAD);
"TESTS:" return(TESTHEAD);
"STACKS:" return(STACKHEAD);
"SIZEFACTOR" return(SIZEFAC);
"TIMEFACTOR" return(TIMEFAC);
"FORMAT" return(FORMAT);
"cost" return(COST);
"remove" return(REMOVE);
"|" return(SEP);
"samesign" return(SAMESIGN);
"inreg" return(INREG);
"sfit" return(SFIT);
"ufit" return(UFIT);
"defined" return(DEFINED);
"rom" return(ROM);
"loww" return(LOWW);
"highw" return(HIGHW);
"move" return(MOVE);
"erase" return(ERASE);
"allocate" return(ALLOCATE);
"tostring" return(TOSTRING);
"nocc" return(NOCC);
"setcc" return(SETCC);
"samecc" return(SAMECC);
"test" return(TEST);
"STACK" return(STACK);
"nocoercions" return(NOCOERC);
"&&" return(AND2);
"||" return(OR2);
"==" return(CMPEQ);
"!=" return(CMPNE);
"<=" return(CMPLE);
"<" return(CMPLT);
">" return(CMPGT);
">=" return(CMPGE);
">>" return(RSHIFT);
"<<" return(LSHIFT);
"!" return(NOT);
"~" return(COMP);
"..." return(ELLIPS);
EM_WSIZE { yylval.yy_intp = &wsize; return(CIDENT); }
EM_PSIZE { yylval.yy_intp = &psize; return(CIDENT); }
EM_BSIZE { yylval.yy_intp = &bsize; return(CIDENT); }
REGISTER { yylval.yy_string = "REGISTER"; return(TYPENAME); }
INT { yylval.yy_string = "INT"; return(TYPENAME); }
STRING { yylval.yy_string = "STRING"; return(TYPENAME); }
regvar return(REGVAR);
loop return(LOOP);
pointer return(POINTER);
float return(FLOAT);
return return(RETURN);
[_A-Za-z][_A-Za-z0-9]+ {register ident_p ip;
if(!lookident || (ip=ilookup(yytext,JUSTLOOKING))==0) {
yylval.yy_string = scopy(yytext);return(IDENT);
} else {
yylval.yy_ident = ip;
switch(ip->i_type) {
default:assert(0);
case IREG:return(RIDENT);
case IPRP:return(PIDENT);
case ITOK:return(TIDENT);
case IEXP:return(EIDENT);
}
}
}
[a-z] {yylval.yy_char = yytext[0]; return(LCASELETTER);}
[0-9]* {yylval.yy_int = atoi(yytext);return(NUMBER);}
(\"|"%)") { char *p; int c,tipe;
p=yytext;
for (;;) {
c = input();
switch(c) {
default: *p++=c;break;
case '\\':
*p++=c; *p++=input(); break;
case '\n':
yyerror("Unterminated string");
break;
case '"':
tipe=STRING; goto endstr;
case '%':
c=input();
if (c == '(') {
tipe=LSTRING;goto endstr;
} else {
*p++ = '%'; unput(c); break;
}
}
}
endstr:
*p++ = 0;
yylval.yy_string = scopy(yytext);
return(tipe);
}
[ \t]* |
\n ;
. return(yytext[0]);
%%
char linebuf[256];
char prevbuf[256];
int linep;
int linepos; /* corrected for tabs */
char charstack[MAXBACKUP];
int nbackup=0;
output(c) {
assert(0);
}
input() {
if(nbackup)
return(charstack[--nbackup]);
if(linebuf[linep]==0) {
strcpy(prevbuf,linebuf);
if(fgets(linebuf,256,stdin)==NULL)
return(0);
lino++;
linepos=linep=0;
}
if (linebuf[linep] == '\t')
linepos = (linepos+8) & ~07;
else linepos++;
return(linebuf[linep++]);
}
unput(c) {
chktabsiz(nbackup,MAXBACKUP,"Lexical backup table");
charstack[nbackup++] = c;
}
yyerror(s,a1,a2,a3,a4) string s; {
fprintf(stderr,"%d\t%s%d\t%s\t%*c ",lino-1,prevbuf,lino,linebuf,
linepos-1,'^');
fprintf(stderr,s,a1,a2,a3,a4);
fprintf(stderr,"\n");
nerrors++;
}

202
util/opt/Makefile Normal file
View File

@@ -0,0 +1,202 @@
# $Header$
CFILES=main.c getline.c lookup.c var.c process.c backward.c util.c\
alloc.c putline.c cleanup.c peephole.c flow.c reg.c
OFILES=main.o getline.o lookup.o var.o process.o backward.o util.o\
alloc.o putline.o cleanup.o peephole.o flow.o reg.o
KFILES=main.k getline.k lookup.k var.k process.k backward.k util.k\
alloc.k putline.k cleanup.k peephole.k flow.k reg.k
LIBS=../../lib/em_data.a
CFLAGS=-O -DNDEBUG
LDFLAGS=-i
LINT=lint
OPR=wide|opr
XREF=xref -c -w80
PROPTS=
# LEXLIB is implementation dependent, try -ll or -lln first
LEXLIB=-ll
.DEFAULT:
co -q $<
opt: $(OFILES) pattern.o $(LIBS)
cc $(LDFLAGS) $(CFLAGS) $(OFILES) pattern.o $(LIBS) -o opt
test: opt testopt
testopt
cmp : opt
cmp opt ../../lib/em_opt
install:opt
size opt ../../lib/em_opt
cp opt ../../lib/em_opt
pattern.c: patterns mktab
/lib/cpp patterns | mktab > pattern.c
mktab: mktab.o $(LIBS)
cc $(CFLAGS) mktab.o $(LIBS) $(LEXLIB) -o mktab
depend: makedepend
makedepend
lint: $(CFILES) pattern.c
$(LINT) $(CFILES) pattern.c>lint 2>&1
printall:
-pr $(PROPTS) Makefile -n *.h `ls $(CFILES)` mktab.y scan.l patterns|$(OPR)
touch print
print: Makefile *.h $(CFILES) mktab.y scan.l patterns
-pr $(PROPTS) -n $? | $(OPR)
opr:
make pr ^ $(OPR)
pr:
@pr $(PROPTS) -n Makefile *.h $(CFILES) mktab.y scan.l patterns
xref:
$(XREF) *.h $(CFILES) | pr $(PROPTS) -h "XREF EMOPT"|$(OPR)&
sizes: opt
-nm opt | sort -n| /usr/plain/bin/map
clean:
rm -f *.o opt mktab mktab.c scan.c pattern.c
kfiles: $(KFILES)
.SUFFIXES: .k
.c.k: ; cem -c $*.c
# the next lines are generated automatically
# AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
alloc.o: alloc.h
alloc.o: assert.h
alloc.o: line.h
alloc.o: lookup.h
alloc.o: param.h
alloc.o: proinf.h
alloc.o: types.h
backward.o: ../../h/em_mnem.h
backward.o: ../../h/em_pseu.h
backward.o: ../../h/em_spec.h
backward.o: alloc.h
backward.o: assert.h
backward.o: ext.h
backward.o: line.h
backward.o: lookup.h
backward.o: param.h
backward.o: proinf.h
backward.o: types.h
cleanup.o: ../../h/em_mes.h
cleanup.o: ../../h/em_pseu.h
cleanup.o: ../../h/em_spec.h
cleanup.o: assert.h
cleanup.o: ext.h
cleanup.o: lookup.h
cleanup.o: param.h
cleanup.o: types.h
flow.o: ../../h/em_flag.h
flow.o: ../../h/em_mnem.h
flow.o: ../../h/em_spec.h
flow.o: alloc.h
flow.o: ext.h
flow.o: line.h
flow.o: optim.h
flow.o: param.h
flow.o: proinf.h
flow.o: types.h
getline.o: ../../h/em_flag.h
getline.o: ../../h/em_mes.h
getline.o: ../../h/em_pseu.h
getline.o: ../../h/em_spec.h
getline.o: alloc.h
getline.o: assert.h
getline.o: ext.h
getline.o: line.h
getline.o: lookup.h
getline.o: param.h
getline.o: proinf.h
getline.o: types.h
lookup.o: alloc.h
lookup.o: lookup.h
lookup.o: param.h
lookup.o: proinf.h
lookup.o: types.h
main.o: ../../h/em_spec.h
main.o: alloc.h
main.o: ext.h
main.o: param.h
main.o: types.h
mktab.o: ../../h/em_mnem.h
mktab.o: ../../h/em_spec.h
mktab.o: optim.h
mktab.o: param.h
mktab.o: pattern.h
mktab.o: scan.c
mktab.o: types.h
pattern.o: param.h
pattern.o: pattern.h
pattern.o: types.h
peephole.o: ../../h/em_mnem.h
peephole.o: ../../h/em_spec.h
peephole.o: alloc.h
peephole.o: assert.h
peephole.o: ext.h
peephole.o: line.h
peephole.o: lookup.h
peephole.o: optim.h
peephole.o: param.h
peephole.o: pattern.h
peephole.o: proinf.h
peephole.o: types.h
process.o: ../../h/em_pseu.h
process.o: ../../h/em_spec.h
process.o: alloc.h
process.o: assert.h
process.o: ext.h
process.o: line.h
process.o: lookup.h
process.o: param.h
process.o: proinf.h
process.o: types.h
putline.o: ../../h/em_flag.h
putline.o: ../../h/em_mnem.h
putline.o: ../../h/em_pseu.h
putline.o: ../../h/em_spec.h
putline.o: alloc.h
putline.o: assert.h
putline.o: ext.h
putline.o: line.h
putline.o: lookup.h
putline.o: optim.h
putline.o: param.h
putline.o: proinf.h
putline.o: types.h
reg.o: ../../h/em_mes.h
reg.o: ../../h/em_pseu.h
reg.o: ../../h/em_spec.h
reg.o: alloc.h
reg.o: assert.h
reg.o: ext.h
reg.o: line.h
reg.o: param.h
reg.o: proinf.h
reg.o: types.h
scan.o: stdio.h
special.o: param.h
special.o: types.h
util.o: assert.h
util.o: ext.h
util.o: lookup.h
util.o: optim.h
util.o: param.h
util.o: proinf.h
util.o: types.h
var.o: lookup.h
var.o: param.h
var.o: proinf.h
var.o: types.h

448
util/opt/alloc.c Normal file
View File

@@ -0,0 +1,448 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "alloc.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
#ifdef USEMALLOC
short * myalloc();
#define newcore(size) myalloc(size)
#define oldcore(p,size) free(p)
#else
/* #define CORECHECK /* if defined tests are made to insure
each block occurs at most once */
#define CCHUNK 1024 /* number of shorts asked from system */
short *newcore(),*freshcore();
extern char *sbrk();
#ifdef COREDEBUG
int shortsasked=0;
#endif
#endif
/*
* The following two sizetables contain the sizes of the various kinds
* of line and argument structures.
* Care has been taken to make this table implementation independent,
* but if you think very hard you might find a compiler failing the
* assumptions made.
* A wasteful but safe approach is to replace every line of them by
* sizeof(line_t)
* and
* sizeof(arg_t)
* respectively.
*/
#define LBASE (sizeof(line_t)-sizeof(un_l_a))
int lsizetab[] = {
LBASE,
LBASE+sizeof(short),
LBASE+sizeof(offset),
LBASE+sizeof(num_p),
LBASE+sizeof(sym_p),
LBASE+sizeof(s_la_sval),
LBASE+sizeof(s_la_lval),
LBASE+sizeof(arg_p),
LBASE
};
#define ABASE (sizeof(arg_t)-sizeof(un_a_a))
int asizetab[] = {
ABASE+sizeof(offset),
ABASE+sizeof(num_p),
ABASE+sizeof(sym_p),
ABASE+sizeof(s_a_val),
ABASE+sizeof(argb_t),
ABASE+sizeof(s_a_con),
ABASE+sizeof(s_a_con),
ABASE+sizeof(s_a_con),
};
/*
* alloc routines:
* Two parts:
* 1) typed alloc and free routines
* 2) untyped raw core allocation
*/
/*
* PART 1
*/
line_p newline(optyp) int optyp; {
register line_p lnp;
register kind=optyp;
if (kind>OPMINI)
kind = OPMINI;
lnp = (line_p) newcore(lsizetab[kind]);
lnp->l_optyp = optyp;
return(lnp);
}
oldline(lnp) register line_p lnp; {
register kind=lnp->l_optyp&BMASK;
if (kind>OPMINI)
kind = OPMINI;
if (kind == OPLIST)
oldargs(lnp->l_a.la_arg);
oldcore((short *) lnp,lsizetab[kind]);
}
arg_p newarg(kind) int kind; {
register arg_p ap;
ap = (arg_p) newcore(asizetab[kind]);
ap->a_typ = kind;
return(ap);
}
oldargs(ap) register arg_p ap; {
register arg_p next;
while (ap != (arg_p) 0) {
next = ap->a_next;
switch(ap->a_typ) {
case ARGSTR:
oldargb(ap->a_a.a_string.ab_next);
break;
case ARGICN:
case ARGUCN:
case ARGFCN:
oldargb(ap->a_a.a_con.ac_con.ab_next);
break;
}
oldcore((short *) ap,asizetab[ap->a_typ]);
ap = next;
}
}
oldargb(abp) register argb_p abp; {
register argb_p next;
while (abp != (argb_p) 0) {
next = abp->ab_next;
oldcore((short *) abp,sizeof (argb_t));
abp = next;
}
}
reg_p newreg() {
return((reg_p) newcore(sizeof(reg_t)));
}
oldreg(rp) reg_p rp; {
oldcore((short *) rp,sizeof(reg_t));
}
num_p newnum() {
return((num_p) newcore(sizeof(num_t)));
}
oldnum(lp) num_p lp; {
oldcore((short *) lp,sizeof(num_t));
}
offset *newrom() {
return((offset *) newcore(MAXROM*sizeof(offset)));
}
sym_p newsym(len) int len; {
/*
* sym_t includes a 2 character s_name at the end
* extend this structure with len-2 characters
*/
return((sym_p) newcore(sizeof(sym_t) - 2 + len));
}
argb_p newargb() {
return((argb_p) newcore(sizeof(argb_t)));
}
#ifndef USEMALLOC
/******************************************************************/
/****** Start of raw core management package *****************/
/******************************************************************/
#define MAXSHORT 30 /* Maximum number of shorts one can ask for */
short *freelist[MAXSHORT];
typedef struct coreblock {
struct coreblock *co_next;
short co_size;
} core_t,*core_p;
#define SINC (sizeof(core_t)/sizeof(short))
#ifdef COREDEBUG
coreverbose() {
register size;
register short *p;
register sum;
sum = 0;
for(size=1;size<MAXSHORT;size++)
for (p=freelist[size];p!=0;p = *(short **) p)
sum += size;
fprintf(stderr,"Used core %u\n",(shortsasked-sum)*sizeof(short));
}
#endif
#ifdef SEPID
compactcore() {
register core_p corelist=0,tp,cl;
int size;
#ifdef COREDEBUG
fprintf(stderr,"Almost out of core\n");
#endif
for(size=SINC;size<MAXSHORT;size++) {
while ((tp = (core_p) freelist[size]) != (core_p) 0) {
freelist[size] = (short *) tp->co_next;
tp->co_size = size;
if (corelist==0 || tp<corelist) {
tp->co_next = corelist;
corelist = tp;
} else {
for(cl=corelist;cl->co_next != 0 && tp>cl->co_next;
cl = cl->co_next)
;
tp->co_next = cl->co_next;
cl->co_next = tp;
}
}
}
while (corelist != 0) {
while ((short *) corelist->co_next ==
(short *) corelist + corelist->co_size) {
corelist->co_size += corelist->co_next->co_size;
corelist->co_next = corelist->co_next->co_next;
}
assert(corelist->co_next==0 ||
(short *) corelist->co_next >
(short *) corelist + corelist->co_size);
while (corelist->co_size >= MAXSHORT+SINC) {
oldcore((short *) corelist + corelist->co_size-(MAXSHORT-1),
sizeof(short)*(MAXSHORT-1));
corelist->co_size -= MAXSHORT;
}
if (corelist->co_size >= MAXSHORT) {
oldcore((short *) corelist + corelist->co_size-SINC,
sizeof(short)*SINC);
corelist->co_size -= SINC;
}
cl = corelist->co_next;
oldcore((short *) corelist, sizeof(short)*corelist->co_size);
corelist = cl;
}
}
short *grabcore(size) int size; {
register short *p;
register trysize;
/*
* Desperate situation, can't get more core from system.
* Postpone giving up just a little bit by splitting up
* larger free blocks if possible.
* Algorithm is worst fit.
*/
assert(size<2*MAXSHORT);
for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
p = freelist[trysize/sizeof(short)];
if ( p != (short *) 0) {
freelist[trysize/sizeof(short)] = *(short **) p;
oldcore(p+size/sizeof(short),trysize-size);
return(p);
}
}
/*
* Can't get more core from the biggies, try to combine the
* little ones. This is expensive but probably better than
* giving up.
*/
compactcore();
if ((p=freelist[size/sizeof(short)]) != 0) {
freelist[size/sizeof(short)] = * (short **) p;
return(p);
}
for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
p = freelist[trysize/sizeof(short)];
if ( p != (short *) 0) {
freelist[trysize/sizeof(short)] = *(short **) p;
oldcore(p+size/sizeof(short),trysize-size);
return(p);
}
}
/*
* That's it then. Finished.
*/
return(0);
}
#endif /* SEPID */
short *newcore(size) int size; {
register short *p,*q;
if( size < 2*MAXSHORT ) {
if ((p=freelist[size/sizeof(short)]) != (short *) 0)
freelist[size/sizeof(short)] = *(short **) p;
else {
p = freshcore(size);
#ifdef SEPID
if (p == (short *) 0)
p = grabcore(size);
#endif
}
} else
p = freshcore(size);
if (p == 0)
error("out of memory");
for (q=p; size > 0 ; size -= sizeof(short))
*q++ = 0;
return(p);
}
#ifdef NOMALLOC
/*
* stdio uses malloc and free.
* you can use these as substitutes
*/
char *malloc(size) int size; {
/*
* malloc(III) is called by stdio,
* this routine is a substitute.
*/
return( (char *) newcore(size));
}
free() {
}
#endif
oldcore(p,size) short *p; int size; {
#ifdef CORECHECK
register short *cp;
#endif
assert(size<2*MAXSHORT);
#ifdef CORECHECK
for (cp=freelist[size/sizeof(short)]; cp != (short *) 0;
cp = (short *) *cp)
assert(cp != p);
#endif
*(short **) p = freelist[size/sizeof(short)];
freelist[size/sizeof(short)] = p;
}
short *ccur,*cend;
coreinit(p1,p2) short *p1,*p2; {
/*
* coreinit is called with the boundaries of a piece of
* memory that can be used for starters.
*/
ccur = p1;
cend = p2;
}
short *freshcore(size) int size; {
register short *temp;
static int cchunk=CCHUNK;
while(&ccur[size/sizeof(short)] >= cend && cchunk>0) {
do {
temp = (short *) sbrk(cchunk*sizeof(short));
if (temp == (short *) -1)
cchunk >>= 1;
else if (temp != cend)
ccur = cend = temp;
} while (temp == (short *) -1 && cchunk>0);
cend += cchunk;
#ifdef COREDEBUG
shortsasked += cchunk;
#endif
}
if (cchunk==0)
return(0);
temp = ccur;
ccur = &ccur[size/sizeof(short)];
return(temp);
}
#else /* USEMALLOC */
coreinit() {
/*
* Empty function, no initialization needed
*/
}
short *myalloc(size) register size; {
register short *p,*q;
extern char *malloc();
p = (short *)malloc(size);
if (p == 0)
error("out of memory");
for(q=p;size>0;size -= sizeof(short))
*q++ = 0;
return(p);
}
#endif

55
util/opt/alloc.h Normal file
View File

@@ -0,0 +1,55 @@
/* $Header$ */
extern line_p newline();
extern offset *newrom();
extern sym_p newsym();
extern num_p newnum();
extern arg_p newarg();
extern argb_p newargb();
extern reg_p newreg();
extern oldline();
extern oldloc();
extern oldreg();
/* #define USEMALLOC /* if defined malloc() and free() are used */
/* #define COREDEBUG /* keep records and print statistics */
/*
* The next define gives if defined the number of pseudo's outside
* procedures that are collected without processing.
* If undefined all pseudo's will be collected but that may
* give trouble on small machines, because of lack of room.
*/
#define PSEUBETWEEN 200
#ifndef USEMALLOC
/*
* Now the real bitsqueezing starts.
* When running on a machine where code and data live in
* separate address-spaces it is worth putting in some extra
* code to save on probably less data.
*/
#define SEPID /* code and data in separate spaces */
/*
* If the stack segment and the data are separate as on a PDP11 under UNIX
* it is worth squeezing some shorts out of the stack page.
*/
#ifndef EM_WSIZE
/*
* Compiled with 'standard' C compiler
*/
#define STACKROOM 3200 /* number of shorts space in stack */
#else
/*
* Compiled with pcc, has trouble with lots of variables
*/
#define STACKROOM 2000
#endif
#else
#define STACKROOM 1 /* 0 gives problems */
#endif /* USEMALLOC */

7
util/opt/assert.h Normal file
View File

@@ -0,0 +1,7 @@
/* $Header$ */
#ifndef NDEBUG
#define assert(x) if(!(x)) badassertion(__FILE__,__LINE__)
#else
#define assert(x) /* nothing */
#endif

187
util/opt/backward.c Normal file
View File

@@ -0,0 +1,187 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "line.h"
#include "lookup.h"
#include "alloc.h"
#include "proinf.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_mnem.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
#define local(x) if (((x)->s_flags&SYMKNOWN) == 0)\
x->s_flags &= ~ SYMGLOBAL
#define global(x) if(((x)->s_flags&SYMKNOWN) == 0)\
x->s_flags |= SYMGLOBAL
#define DTYPHOL 1
#define DTYPBSS 2
#define DTYPCON 3
#define DTYPROM 4
byte curdtyp;
bool goodrom;
short curfrag = 3; /* see also peephole.c */
offset rombuf[MAXROM];
int rc;
backward() {
register line_p lnp;
line_p next;
register arg_p ap;
line_p i,p;
int n;
register sym_p sp;
i = p = (line_p) 0;
curdtyp=0;
for (lnp = curpro.lastline; lnp != (line_p) 0; lnp = next) {
next = lnp->l_next;
switch(lnp->l_optyp) {
case OPSYMBOL:
global(lnp->l_a.la_sp);
break;
case OPSVAL:
global(lnp->l_a.la_sval.lasv_sp);
break;
case OPLVAL:
global(lnp->l_a.la_lval.lalv_sp);
break;
case OPLIST:
ap = lnp->l_a.la_arg;
while (ap != (arg_p) 0 ) {
switch(ap->a_typ) {
case ARGSYM:
global(ap->a_a.a_sp);
break;
case ARGVAL:
global(ap->a_a.a_val.av_sp);
}
ap = ap->a_next;
}
break;
}
/*
* references to symbols are processed now.
* for plain instructions nothing else is needed
*/
switch(lnp->l_instr&BMASK) {
/*
* count all local occurences for register counts;
* op_lal is omitted and not by accident.
*/
case op_del:
case op_inl:
case op_ldl:
case op_lil:
case op_lol:
case op_sdl:
case op_sil:
case op_stl:
case op_zrl:
switch(lnp->l_optyp) {
case OPNO:
case OPNUMLAB:
case OPSYMBOL:
case OPSVAL:
case OPLVAL:
case OPLIST:
break;
case OPOFFSET:
incregusage(lnp->l_a.la_offset);
break;
case OPSHORT:
incregusage((offset)lnp->l_a.la_short);
break;
default:
incregusage((offset)(lnp->l_optyp&BMASK)-Z_OPMINI);
break;
}
/* fall through !! */
default:
assert((lnp->l_instr&BMASK)<=op_last);
lnp->l_next = i;
i = lnp;
continue;
case ps_sym:
sp = lnp->l_a.la_sp;
local(sp);
if (curdtyp == DTYPROM && goodrom) {
sp->s_rom = newrom();
for (n=0;n<rc;n++)
sp->s_rom[n] = rombuf[n];
}
sp->s_frag = curfrag;
break;
case ps_hol:
curdtyp = DTYPHOL;
curfrag++;
break;
case ps_bss:
curdtyp = DTYPBSS;
curfrag++;
break;
case ps_con:
if (curdtyp != DTYPCON) {
curdtyp = DTYPCON;
curfrag++;
}
break;
case ps_rom:
if (curdtyp != DTYPROM) {
curdtyp = DTYPROM;
curfrag++;
}
ap = lnp->l_a.la_arg;
rc = 0;
while (ap != (arg_p) 0 && rc < MAXROM) {
if (ap->a_typ == ARGOFF) {
rombuf[rc++] = ap->a_a.a_offset;
ap = ap->a_next;
} else
ap = (arg_p) 0;
}
goodrom = (rc >= 2);
break;
case ps_mes:
break;
case ps_inp:
case ps_ina:
local(lnp->l_a.la_sp);
case ps_exp:
case ps_exa:
case ps_exc:
oldline(lnp);
continue;
}
lnp->l_next = p;
p = lnp;
}
if (prodepth != 0)
local(curpro.symbol);
instrs = i; pseudos = p; curpro.lastline = (line_p) 0;
}

65
util/opt/cleanup.c Normal file
View File

@@ -0,0 +1,65 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "../../h/em_pseu.h"
#include "../../h/em_spec.h"
#include "../../h/em_mes.h"
#include "lookup.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
cleanup() {
FILE *infile;
register c;
register sym_p *spp,sp;
for (spp=symhash;spp< &symhash[NSYMHASH];spp++)
for (sp = *spp; sp != (sym_p) 0; sp = sp->s_next)
if ((sp->s_flags & SYMOUT) == 0)
outdef(sp);
if(!Lflag)
return;
c=fclose(outfile);
assert(c != EOF);
outfile = stdout;
infile = fopen(template,"r");
if (infile == NULL)
error("temp file disappeared");
outshort(sp_magic);
outinst(ps_mes);
outint(ms_ext);
for (spp=symhash;spp< &symhash[NSYMHASH];spp++)
for (sp = *spp; sp != (sym_p) 0; sp = sp->s_next)
if ((sp->s_flags&(SYMDEF|SYMGLOBAL)) == (SYMDEF|SYMGLOBAL))
outsym(sp);
putc(sp_cend,outfile);
while ( (c=getc(infile)) != EOF)
putc(c,outfile);
c=fclose(infile);
assert(c != EOF);
c=unlink(template);
assert(c == 0);
}

16
util/opt/ext.h Normal file
View File

@@ -0,0 +1,16 @@
/* $Header$ */
#ifndef FILE
#include <stdio.h>
#endif
extern unsigned linecount;
extern int prodepth;
extern bool Lflag;
extern bool nflag;
extern byte em_flag[];
extern line_p instrs,pseudos;
extern FILE *outfile;
extern char template[];
extern offset wordsize;
extern offset pointersize;
extern char *progname;

126
util/opt/flow.c Normal file
View File

@@ -0,0 +1,126 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "../../h/em_flag.h"
#include "../../h/em_spec.h"
#include "../../h/em_mnem.h"
#include "alloc.h"
#include "line.h"
#include "proinf.h"
#include "optim.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
flow() {
findreach(); /* determine reachable labels */
cleaninstrs(); /* throw away unreachable code */
}
findreach() {
register num_p *npp,np;
reach(instrs);
for(npp=curpro.numhash;npp< &curpro.numhash[NNUMHASH]; npp++)
for(np= *npp; np != (num_p) 0 ; np = np->n_next)
if (np->n_flags&NUMDATA) {
np->n_repl->n_flags |= NUMREACH;
np->n_repl->n_jumps++;
if (!(np->n_flags&NUMSCAN)) {
np->n_flags |= NUMSCAN;
reach(np->n_line->l_next);
}
}
}
reach(lnp) register line_p lnp; {
register num_p np;
for (;lnp != (line_p) 0; lnp = lnp->l_next) {
if(lnp->l_optyp == OPNUMLAB) {
/*
* Branch instruction or label
*/
np = lnp->l_a.la_np;
if ((lnp->l_instr&BMASK) != op_lab)
np = np->n_repl;
np->n_flags |= NUMREACH;
if (!(np->n_flags&NUMSCAN)) {
np->n_flags |= NUMSCAN;
reach(np->n_line->l_next);
}
if ((lnp->l_instr&BMASK) == op_lab)
return;
else
np->n_jumps++;
}
if ((em_flag[(lnp->l_instr&BMASK)-sp_fmnem]&EM_FLO)==FLO_T)
return;
}
}
cleaninstrs() {
register line_p *lpp,lp,*lastbra;
bool reachable,superfluous;
int instr;
lpp = &instrs; lastbra = (line_p *) 0; reachable = TRUE;
while ((lp = *lpp) != (line_p) 0) {
instr = lp->l_instr&BMASK;
if (instr == op_lab) {
if ((lp->l_a.la_np->n_flags&NUMREACH) != 0) {
reachable = TRUE;
if (lastbra != (line_p *) 0
&& (*lastbra)->l_next == lp
&& (*lastbra)->l_a.la_np->n_repl==lp->l_a.la_np) {
oldline(*lastbra);
OPTIM(O_BRALAB);
lpp = lastbra;
*lpp = lp;
lp->l_a.la_np->n_jumps--;
}
}
if ( lp->l_a.la_np->n_repl != lp->l_a.la_np ||
((lp->l_a.la_np->n_flags&NUMDATA)==0 &&
lp->l_a.la_np->n_jumps == 0))
superfluous = TRUE;
else
superfluous = FALSE;
} else
superfluous = FALSE;
if ( (!reachable) || superfluous) {
lp = lp->l_next;
oldline(*lpp);
OPTIM(O_UNREACH);
*lpp = lp;
} else {
if ( instr <= sp_lmnem &&
(em_flag[instr-sp_fmnem]&EM_FLO)==FLO_T) {
reachable = FALSE;
if ((lp->l_instr&BMASK) == op_bra)
lastbra = lpp;
}
lpp = &lp->l_next;
}
}
}

556
util/opt/getline.c Normal file
View File

@@ -0,0 +1,556 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "line.h"
#include "lookup.h"
#include "alloc.h"
#include "proinf.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_flag.h"
#include "../../h/em_mes.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
static short tabval; /* temp store for shorts */
static offset tabval2; /* temp store for offsets */
static char string[IDL+1]; /* temp store for names */
/*
* The next constants are close to sp_cend for fast switches
*/
#define INST 256 /* instruction: number in tabval */
#define PSEU 257 /* pseudo: number in tabval */
#define ILBX 258 /* label: number in tabval */
#define DLBX 259 /* symbol: name in string[] */
#define CSTX1 260 /* short constant: stored in tabval */
#define CSTX2 261 /* offset: value in tabval2 */
#define VALX1 262 /* symbol+short: in string[] and tabval */
#define VALX2 263 /* symbol+offset: in string[] and tabval2 */
#define ATEOF 264 /* bumped into end of file */
#define readbyte getchar
short readshort() {
register int l_byte, h_byte;
l_byte = readbyte();
h_byte = readbyte();
if ( h_byte>=128 ) h_byte -= 256 ;
return l_byte | (h_byte*256) ;
}
#ifdef LONGOFF
offset readoffset() {
register long l;
register int h_byte;
l = readbyte();
l |= ((unsigned) readbyte())*256 ;
l |= readbyte()*256L*256L ;
h_byte = readbyte() ;
if ( h_byte>=128 ) h_byte -= 256 ;
return l | (h_byte*256L*256*256L) ;
}
#endif
draininput() {
/*
* called when MES ERR is encountered.
* Drain input in case it is a pipe.
*/
while (getchar() != EOF)
;
}
short getint() {
switch(table2()) {
default: error("int expected");
case CSTX1:
return(tabval);
}
}
sym_p getsym(status) int status; {
switch(table2()) {
default:
error("symbol expected");
case DLBX:
return(symlookup(string,status,0));
case sp_pnam:
return(symlookup(string,status,SYMPRO));
}
}
offset getoff() {
switch (table2()) {
default: error("offset expected");
case CSTX1:
return((offset) tabval);
#ifdef LONGOFF
case CSTX2:
return(tabval2);
#endif
}
}
make_string(n) int n; {
register char *s;
extern char *sprintf();
s=sprintf(string,".%u",n);
assert(s == string);
}
inident() {
register n;
register char *p = string;
register c;
n = getint();
while (n--) {
c = readbyte();
if (p<&string[IDL])
*p++ = c;
}
*p++ = 0;
}
int table3(n) int n; {
switch (n) {
case sp_ilb1: tabval = readbyte(); return(ILBX);
case sp_ilb2: tabval = readshort(); return(ILBX);
case sp_dlb1: make_string(readbyte()); return(DLBX);
case sp_dlb2: make_string(readshort()); return(DLBX);
case sp_dnam: inident(); return(DLBX);
case sp_pnam: inident(); return(n);
case sp_cst2: tabval = readshort(); return(CSTX1);
#ifdef LONGOFF
case sp_cst4: tabval2 = readoffset(); return(CSTX2);
#endif
case sp_doff: if (table2()!=DLBX) error("symbol expected");
switch(table2()) {
default: error("offset expected");
case CSTX1: return(VALX1);
#ifdef LONGOFF
case CSTX2: return(VALX2);
#endif
}
default: return(n);
}
}
int table1() {
register n;
n = readbyte();
if (n == EOF)
return(ATEOF);
if ((n <= sp_lmnem) && (n >= sp_fmnem)) {
tabval = n;
return(INST);
}
if ((n <= sp_lpseu) && (n >= sp_fpseu)) {
tabval = n;
return(PSEU);
}
if ((n < sp_filb0 + sp_nilb0) && (n >= sp_filb0)) {
tabval = n - sp_filb0;
return(ILBX);
}
return(table3(n));
}
int table2() {
register n;
n = readbyte();
if ((n < sp_fcst0 + sp_ncst0) && (n >= sp_fcst0)) {
tabval = n - sp_zcst0;
return(CSTX1);
}
return(table3(n));
}
getlines() {
register line_p lnp;
register instr;
for(;;) {
linecount++;
switch(table1()) {
default:
error("unknown instruction byte");
/* NOTREACHED */
case ATEOF:
if (prodepth!=0)
error("procedure unterminated at eof");
process();
return;
case INST:
tstinpro();
instr = tabval;
break;
case DLBX:
lnp = newline(OPSYMBOL);
lnp->l_instr = ps_sym;
lnp->l_a.la_sp= symlookup(string,DEFINING,0);
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
continue;
case ILBX:
tstinpro();
lnp = newline(OPNUMLAB);
lnp->l_instr = op_lab;
lnp->l_a.la_np = numlookup((unsigned) tabval);
if (lnp->l_a.la_np->n_line != (line_p) 0)
error("label %u multiple defined",(unsigned) tabval);
lnp->l_a.la_np->n_line = lnp;
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
continue;
case PSEU:
if(inpseudo(tabval))
return;
continue;
}
/*
* Now we have an instruction number in instr
* There might be an operand, look for it
*/
if ((em_flag[instr-sp_fmnem]&EM_PAR)==PAR_NO) {
lnp = newline(OPNO);
} else switch(table2()) {
default:
error("unknown offset byte");
case sp_cend:
lnp = newline(OPNO);
break;
case CSTX1:
if ((em_flag[instr-sp_fmnem]&EM_PAR)!= PAR_B) {
if (CANMINI(tabval))
lnp = newline(tabval+Z_OPMINI);
else {
lnp = newline(OPSHORT);
lnp->l_a.la_short = tabval;
}
} else {
lnp = newline(OPNUMLAB);
lnp->l_a.la_np = numlookup((unsigned) tabval);
}
break;
#ifdef LONGOFF
case CSTX2:
lnp = newline(OPOFFSET);
lnp->l_a.la_offset = tabval2;
break;
#endif
case ILBX:
tstinpro();
lnp = newline(OPNUMLAB);
lnp->l_a.la_np = numlookup((unsigned) tabval);
break;
case DLBX:
lnp = newline(OPSYMBOL);
lnp->l_a.la_sp = symlookup(string,OCCURRING,0);
break;
case sp_pnam:
lnp = newline(OPSYMBOL);
lnp->l_a.la_sp = symlookup(string,OCCURRING,SYMPRO);
break;
case VALX1:
lnp = newline(OPSVAL);
lnp->l_a.la_sval.lasv_sp = symlookup(string,OCCURRING,0);
lnp->l_a.la_sval.lasv_short = tabval;
break;
#ifdef LONGOFF
case VALX2:
lnp = newline(OPLVAL);
lnp->l_a.la_lval.lalv_sp = symlookup(string,OCCURRING,0);
lnp->l_a.la_lval.lalv_offset = tabval2;
break;
#endif
}
lnp->l_instr = instr;
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
}
}
argstring(length,abp) offset length; register argb_p abp; {
while (length--) {
if (abp->ab_index == NARGBYTES)
abp = abp->ab_next = newargb();
abp->ab_contents[abp->ab_index++] = readbyte();
}
}
line_p arglist(n) int n; {
line_p lnp;
register arg_p ap,*app;
bool moretocome;
offset length;
/*
* creates an arglist with n elements
* if n == 0 the arglist is variable and terminated by sp_cend
*/
lnp = newline(OPLIST);
app = &lnp->l_a.la_arg;
moretocome = TRUE;
do {
switch(table2()) {
default:
error("unknown byte in arglist");
case CSTX1:
tabval2 = (offset) tabval;
case CSTX2:
*app = ap = newarg(ARGOFF);
ap->a_a.a_offset = tabval2;
app = &ap->a_next;
break;
case ILBX:
tstinpro();
*app = ap = newarg(ARGNUM);
ap->a_a.a_np = numlookup((unsigned) tabval);
ap->a_a.a_np->n_flags |= NUMDATA;
app = &ap->a_next;
break;
case DLBX:
*app = ap = newarg(ARGSYM);
ap->a_a.a_sp = symlookup(string,OCCURRING,0);
app = &ap->a_next;
break;
case sp_pnam:
*app = ap = newarg(ARGSYM);
ap->a_a.a_sp = symlookup(string,OCCURRING,SYMPRO);
app = &ap->a_next;
break;
case VALX1:
tabval2 = (offset) tabval;
case VALX2:
*app = ap = newarg(ARGVAL);
ap->a_a.a_val.av_sp = symlookup(string,OCCURRING,0);
ap->a_a.a_val.av_offset = tabval2;
app = &ap->a_next;
break;
case sp_scon:
*app = ap = newarg(ARGSTR);
length = getoff();
argstring(length,&ap->a_a.a_string);
app = &ap->a_next;
break;
case sp_icon:
*app = ap = newarg(ARGICN);
goto casecon;
case sp_ucon:
*app = ap = newarg(ARGUCN);
goto casecon;
case sp_fcon:
*app = ap = newarg(ARGFCN);
casecon:
length = getint();
ap->a_a.a_con.ac_length = (short) length;
argstring(getoff(),&ap->a_a.a_con.ac_con);
app = &ap->a_next;
break;
case sp_cend:
moretocome = FALSE;
}
if (n && (--n) == 0)
moretocome = FALSE;
} while (moretocome);
return(lnp);
}
offset aoff(ap,n) register arg_p ap; {
while (n>0) {
if (ap != (arg_p) 0)
ap = ap->a_next;
n--;
}
if (ap == (arg_p) 0)
error("too few parameters");
if (ap->a_typ != ARGOFF)
error("offset expected");
return(ap->a_a.a_offset);
}
int inpseudo(n) short n; {
register line_p lnp,head,tail;
short n1,n2;
proinf savearea;
#ifdef PSEUBETWEEN
static int pcount=0;
if (pcount++ >= PSEUBETWEEN && prodepth==0) {
process();
pcount=0;
}
#endif
switch(n) {
default:
error("unknown pseudo");
case ps_bss:
case ps_hol:
lnp = arglist(3);
break;
case ps_rom:
case ps_con:
lnp = arglist(0);
break;
case ps_ina:
case ps_inp:
case ps_exa:
case ps_exp:
lnp = newline(OPSYMBOL);
lnp->l_a.la_sp = getsym(NOTHING);
break;
case ps_exc:
n1 = getint(); n2 = getint();
if (n1 != 0 && n2 != 0) {
tail = curpro.lastline;
while (--n2) tail = tail->l_next;
head = tail;
while (n1--) head = head->l_next;
lnp = tail->l_next;
tail->l_next = head->l_next;
head->l_next = curpro.lastline;
curpro.lastline = lnp;
}
lnp = newline(OPNO);
break;
case ps_mes:
lnp = arglist(0);
switch((int) aoff(lnp->l_a.la_arg,0)) {
case ms_err:
draininput(); exit(-1);
case ms_opt:
nflag = TRUE; break;
case ms_emx:
wordsize = aoff(lnp->l_a.la_arg,1);
pointersize = aoff(lnp->l_a.la_arg,2);
#ifndef LONGOFF
if (wordsize>2)
error("This optimizer cannot handle wordsize>2");
#endif
break;
case ms_gto:
curpro.gtoproc=1;
/* Treat as empty mes ms_reg */
case ms_reg:
tstinpro();
regvar(lnp->l_a.la_arg->a_next);
oldline(lnp);
lnp=newline(OPNO);
n=ps_exc; /* kludge to force out this line */
break;
}
break;
case ps_pro:
if (prodepth>0)
savearea = curpro;
else
process();
curpro.symbol = getsym(DEFINING);
switch(table2()) {
case sp_cend:
curpro.localbytes = (offset) -1;
break;
case CSTX1:
tabval2 = (offset) tabval;
case CSTX2:
curpro.localbytes = tabval2;
break;
default:
error("bad second arg of PRO");
}
prodepth++;
curpro.gtoproc=0;
if (prodepth>1) {
register i;
curpro.lastline = (line_p) 0;
curpro.freg = (reg_p) 0;
for(i=0;i<NNUMHASH;i++)
curpro.numhash[i] = (num_p) 0;
getlines();
curpro = savearea;
prodepth--;
}
return(0);
case ps_end:
if (prodepth==0)
error("END misplaced");
switch(table2()) {
case sp_cend:
if (curpro.localbytes == (offset) -1)
error("bytes for locals still unknown");
break;
case CSTX1:
tabval2 = (offset) tabval;
case CSTX2:
if (curpro.localbytes != (offset) -1 && curpro.localbytes != tabval2)
error("inconsistency in number of bytes for locals");
curpro.localbytes = tabval2;
break;
}
process();
curpro.symbol = (sym_p) 0;
if (prodepth==1) {
prodepth=0;
#ifdef PSEUBETWEEN
pcount=0;
#endif
return(0);
} else
return(1);
}
lnp->l_instr = n;
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
return(0);
}
tstinpro() {
if (prodepth==0)
error("This is not allowed outside a procedure");
}

88
util/opt/line.h Normal file
View File

@@ -0,0 +1,88 @@
/* $Header$ */
#define NARGBYTES 14
struct argbytes {
argb_p ab_next;
short ab_index;
char ab_contents[NARGBYTES];
};
typedef struct {
sym_p av_sp;
offset av_offset;
} s_a_val;
typedef struct {
short ac_length;
argb_t ac_con;
} s_a_con;
typedef union {
offset a_offset;
num_p a_np;
sym_p a_sp;
s_a_val a_val;
argb_t a_string;
s_a_con a_con;
} un_a_a;
struct arg {
arg_p a_next;
short a_typ;
un_a_a a_a;
};
/* possible values for .a_typ
*/
#define ARGOFF 0
#define ARGNUM 1
#define ARGSYM 2
#define ARGVAL 3
#define ARGSTR 4
#define ARGICN 5
#define ARGUCN 6
#define ARGFCN 7
typedef struct {
sym_p lasv_sp;
short lasv_short;
} s_la_sval;
typedef struct {
sym_p lalv_sp;
offset lalv_offset;
} s_la_lval;
typedef union {
short la_short;
offset la_offset;
num_p la_np;
sym_p la_sp;
s_la_sval la_sval;
s_la_lval la_lval;
arg_p la_arg;
} un_l_a;
struct line {
line_p l_next; /* maintains linked list */
byte l_instr; /* instruction number */
byte l_optyp; /* specifies what follows */
un_l_a l_a;
};
/* Possible values for .l_optyp */
#define OPNO 0 /* no operand */
#define OPSHORT 1 /* 16 bit number */
#define OPOFFSET 2 /* 16 or 32 bit number */
#define OPNUMLAB 3 /* local label for branches */
#define OPSYMBOL 4 /* global label or procedurename */
#define OPSVAL 5 /* symbol + 16 bit constant */
#define OPLVAL 6 /* symbol + 16 or 32 bit constant */
#define OPLIST 7 /* operand list for some pseudos */
#define OPMINI 8 /* start of minis */
#define Z_OPMINI (OPMINI+100) /* tunable */
#define CANMINI(x) ((x)>=OPMINI-Z_OPMINI && (x)<256-Z_OPMINI)

94
util/opt/lookup.c Normal file
View File

@@ -0,0 +1,94 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "lookup.h"
#include "alloc.h"
#include "proinf.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
unsigned hash(string) char *string; {
register char *p;
register unsigned i,sum;
for (sum=i=0,p=string;*p;i += 3)
sum ^= (*p++)<<(i&07);
return(sum);
}
sym_p symlookup(name,status,flags) char *name; int status,flags; {
register sym_p *spp,sp;
register i;
static short genfrag = 32767;
spp = &symhash[hash(name)%NSYMHASH];
while (*spp != (sym_p) 0)
if (strncmp((*spp)->s_name,name,IDL)==0) {
sp = *spp;
if ((sp->s_flags^flags)&SYMPRO)
error("%s is both proc and datalabel",name);
if (status == DEFINING) {
if (sp->s_flags&SYMDEF)
error("redefined symbol %s",name);
sp->s_flags |= SYMDEF;
}
return(sp);
} else
spp = &(*spp)->s_next;
/*
* symbol not found, enter in table
*/
i = strlen(name) + 1;
if (i & 1)
i++;
if (i > IDL)
i = IDL;
*spp = sp = newsym(i);
strncpy(sp->s_name,name,i);
sp->s_flags = flags;
if (status == DEFINING)
sp->s_flags |= SYMDEF;
sp->s_frag = genfrag--;
return(sp);
}
num_p numlookup(number) unsigned number; {
register num_p *npp, np;
npp = &curpro.numhash[number%NNUMHASH];
while (*npp != (num_p) 0)
if ((*npp)->n_number == number)
return(*npp);
else
npp = &(*npp)->n_next;
/*
* local label not found, enter in tabel
*/
*npp = np = newnum();
np->n_number = number;
np->n_repl = np;
return(np);
}

25
util/opt/lookup.h Normal file
View File

@@ -0,0 +1,25 @@
/* $Header$ */
#define IDL 100
struct sym {
sym_p s_next;
offset *s_rom;
short s_flags;
short s_frag;
offset s_value;
char s_name[2]; /* to be extended up to IDL */
};
/* contents of .s_flags */
#define SYMPRO 000001
#define SYMGLOBAL 000002
#define SYMKNOWN 000004
#define SYMOUT 000010
#define SYMDEF 000020
#define NSYMHASH 127
extern sym_p symhash[NSYMHASH],symlookup();
#define OCCURRING 0
#define DEFINING 1
#define NOTHING 2

77
util/opt/main.c Normal file
View File

@@ -0,0 +1,77 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "alloc.h"
#include "../../h/em_spec.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
/*
* Main program for EM optimizer
*/
main(argc,argv) int argc; char *argv[]; {
short somespace[STACKROOM];
progname = argv[0];
while (argc-->1 && **++argv == '-')
flags(*argv);
if (argc>1) {
fprintf(stderr,"Usage: %s [-Ln] [name]\n",progname);
exit(-1);
}
if (argc)
if (freopen(*argv,"r",stdin) == NULL)
error("Cannot open %s",*argv);
fileinit();
coreinit(somespace,somespace+STACKROOM);
getlines();
cleanup();
return(0);
}
flags(s) register char *s; {
for (s++;*s;s++)
switch(*s) {
case 'L': Lflag = TRUE; break;
case 'n': nflag = TRUE; break;
}
}
fileinit() {
char *mktemp();
short readshort();
if (readshort() != (short) sp_magic)
error("wrong input file");
if (Lflag) {
outfile = fopen(mktemp(template),"w");
if (outfile == NULL)
error("can't create %s",template);
} else {
outfile = stdout;
outshort(sp_magic);
}
}

15
util/opt/makedepend Executable file
View File

@@ -0,0 +1,15 @@
: '$Header$'
for extension in c y
do
for file in *.$extension
do ofile=`basename $file .$extension`.o
grep '^# *include.*"' $file|sed "s/.*\"\(.*\)\".*/$ofile: \1/"
done
done | sort -u >depend
ed - Makefile <<'!'
/AUTOAUTOAUTO/+,$d
$r depend
w
q
!
rm -f depend

366
util/opt/mktab.y Normal file
View File

@@ -0,0 +1,366 @@
%{
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "pattern.h"
#include "../../h/em_spec.h"
#include "../../h/em_mnem.h"
#include "optim.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
#define MAXNODES 1000
expr_t nodes[MAXNODES];
expr_p lastnode = nodes+1;
int curind,prevind;
int patlen,maxpatlen,rpllen;
int lino = 1;
int patno=1;
#define MAX 100
int patmnem[MAX],rplmnem[MAX],rplexpr[MAX];
byte nparam[N_EX_OPS];
bool nonumlab[N_EX_OPS];
bool onlyconst[N_EX_OPS];
int nerrors=0;
%}
%union {
int y_int;
}
%left OR2
%left AND2
%left OR1
%left XOR1
%left AND1
%left CMPEQ,CMPNE
%left CMPLT,CMPLE,CMPGT,CMPGE
%left RSHIFT,LSHIFT
%left ARPLUS,ARMINUS
%left ARTIMES,ARDIVIDE,ARMOD
%nonassoc NOT,COMP,UMINUS
%nonassoc '$'
%token SFIT,UFIT,NOTREG,PSIZE,WSIZE,DEFINED,SAMESIGN,ROM,ROTATE
%token <y_int> MNEM
%token <y_int> NUMBER
%type <y_int> expr,argno,optexpr
%start patternlist
%%
patternlist
: /* empty */
| patternlist '\n'
| patternlist pattern
;
pattern :
mnemlist optexpr ':' replacement '\n'
{ register i;
outbyte(0); outshort(prevind); prevind=curind-3;
out(patlen);
for (i=0;i<patlen;i++) outbyte(patmnem[i]);
out($2);
out(rpllen);
for (i=0;i<rpllen;i++) {
outbyte(rplmnem[i]);
out(rplexpr[i]);
}
#ifdef DIAGOPT
outshort(patno);
#endif
patno++;
printf("\n");
if (patlen>maxpatlen) maxpatlen=patlen;
}
| error '\n'
{ yyerrok; }
;
replacement
: expr /* special optimization */
{
#ifdef ALLOWSPECIAL
rpllen=1; rplmnem[0]=0; rplexpr[0]=$1;
#else
yyerror("No specials allowed");
#endif
}
| repllist
;
repllist: /* empty */
{ rpllen=0; }
| repllist repl
;
repl : MNEM optexpr
{ rplmnem[rpllen] = $1; rplexpr[rpllen++] = $2; }
;
mnemlist: MNEM
{ patlen=0; patmnem[patlen++] = $1; }
| mnemlist MNEM
{ patmnem[patlen++] = $2; }
;
optexpr : /* empty */
{ $$ = 0; }
| expr
;
expr
: '$' argno
{ $$ = lookup(0,EX_ARG,$2,0); }
| NUMBER
{ $$ = lookup(0,EX_CON,(int)(short)$1,0); }
| PSIZE
{ $$ = lookup(0,EX_POINTERSIZE,0,0); }
| WSIZE
{ $$ = lookup(0,EX_WORDSIZE,0,0); }
| DEFINED '(' expr ')'
{ $$ = lookup(0,EX_DEFINED,$3,0); }
| SAMESIGN '(' expr ',' expr ')'
{ $$ = lookup(1,EX_SAMESIGN,$3,$5); }
| SFIT '(' expr ',' expr ')'
{ $$ = lookup(0,EX_SFIT,$3,$5); }
| UFIT '(' expr ',' expr ')'
{ $$ = lookup(0,EX_UFIT,$3,$5); }
| ROTATE '(' expr ',' expr ')'
{ $$ = lookup(0,EX_ROTATE,$3,$5); }
| NOTREG '(' expr ')'
{ $$ = lookup(0,EX_NOTREG,$3,0); }
| ROM '(' argno ',' expr ')'
{ $$ = lookup(0,EX_ROM,$3,$5); }
| '(' expr ')'
{ $$ = $2; }
| expr CMPEQ expr
{ $$ = lookup(1,EX_CMPEQ,$1,$3); }
| expr CMPNE expr
{ $$ = lookup(1,EX_CMPNE,$1,$3); }
| expr CMPGT expr
{ $$ = lookup(0,EX_CMPGT,$1,$3); }
| expr CMPGE expr
{ $$ = lookup(0,EX_CMPGE,$1,$3); }
| expr CMPLT expr
{ $$ = lookup(0,EX_CMPLT,$1,$3); }
| expr CMPLE expr
{ $$ = lookup(0,EX_CMPLE,$1,$3); }
| expr OR2 expr
{ $$ = lookup(0,EX_OR2,$1,$3); }
| expr AND2 expr
{ $$ = lookup(0,EX_AND2,$1,$3); }
| expr OR1 expr
{ $$ = lookup(1,EX_OR1,$1,$3); }
| expr XOR1 expr
{ $$ = lookup(1,EX_XOR1,$1,$3); }
| expr AND1 expr
{ $$ = lookup(1,EX_AND1,$1,$3); }
| expr ARPLUS expr
{ $$ = lookup(1,EX_PLUS,$1,$3); }
| expr ARMINUS expr
{ $$ = lookup(0,EX_MINUS,$1,$3); }
| expr ARTIMES expr
{ $$ = lookup(1,EX_TIMES,$1,$3); }
| expr ARDIVIDE expr
{ $$ = lookup(0,EX_DIVIDE,$1,$3); }
| expr ARMOD expr
{ $$ = lookup(0,EX_MOD,$1,$3); }
| expr LSHIFT expr
{ $$ = lookup(0,EX_LSHIFT,$1,$3); }
| expr RSHIFT expr
{ $$ = lookup(0,EX_RSHIFT,$1,$3); }
| ARPLUS expr %prec UMINUS
{ $$ = $2; }
| ARMINUS expr %prec UMINUS
{ $$ = lookup(0,EX_UMINUS,$2,0); }
| NOT expr
{ $$ = lookup(0,EX_NOT,$2,0); }
| COMP expr
{ $$ = lookup(0,EX_COMP,$2,0); }
;
argno : NUMBER
{ if ($1<1 || $1>patlen) {
YYERROR;
}
$$ = (int) $1;
}
;
%%
extern char em_mnem[][4];
#define HASHSIZE (2*(sp_lmnem-sp_fmnem))
struct hashmnem {
char h_name[3];
byte h_value;
} hashmnem[HASHSIZE];
inithash() {
register i;
enter("lab",op_lab);
enter("LLP",op_LLP);
enter("LEP",op_LEP);
enter("SLP",op_SLP);
enter("SEP",op_SEP);
for(i=0;i<=sp_lmnem-sp_fmnem;i++)
enter(em_mnem[i],i+sp_fmnem);
}
unsigned hashname(name) register char *name; {
register unsigned h;
h = (*name++)&BMASK;
h = (h<<4)^((*name++)&BMASK);
h = (h<<4)^((*name++)&BMASK);
return(h);
}
enter(name,value) char *name; {
register unsigned h;
h=hashname(name)%HASHSIZE;
while (hashmnem[h].h_name[0] != 0)
h = (h+1)%HASHSIZE;
strncpy(hashmnem[h].h_name,name,3);
hashmnem[h].h_value = value;
}
int mlookup(name) char *name; {
register unsigned h;
h = hashname(name)%HASHSIZE;
while (strncmp(hashmnem[h].h_name,name,3) != 0 &&
hashmnem[h].h_name[0] != 0)
h = (h+1)%HASHSIZE;
return(hashmnem[h].h_value&BMASK); /* 0 if not found */
}
main() {
inithash();
initio();
yyparse();
if (nerrors==0)
printnodes();
return nerrors;
}
yyerror(s) char *s; {
fprintf(stderr,"line %d: %s\n",lino,s);
nerrors++;
}
lookup(comm,operator,lnode,rnode) {
register expr_p p;
for (p=nodes+1;p<lastnode;p++) {
if (p->ex_operator != operator)
continue;
if (!(p->ex_lnode == lnode && p->ex_rnode == rnode ||
comm && p->ex_lnode == rnode && p->ex_rnode == lnode))
continue;
return(p-nodes);
}
if (lastnode >= &nodes[MAXNODES])
yyerror("node table overflow");
lastnode++;
p->ex_operator = operator;
p->ex_lnode = lnode;
p->ex_rnode = rnode;
return(p-nodes);
}
printnodes() {
register expr_p p;
printf("};\n\nshort lastind = %d;\n\nexpr_t enodes[] = {\n",prevind);
for (p=nodes;p<lastnode;p++)
printf("/* %3d */\t%3d,%6u,%6u,\n",
p-nodes,p->ex_operator,p->ex_lnode,p->ex_rnode);
printf("};\n\niarg_t iargs[%d];\n",maxpatlen);
}
initio() {
register i;
printf("#include \"param.h\"\n#include \"types.h\"\n");
printf("#include \"pattern.h\"\n\n");
for(i=0;i<N_EX_OPS;i++) {
nparam[i]=2;
nonumlab[i]=TRUE;
onlyconst[i]=TRUE;
}
nparam[EX_POINTERSIZE] = 0;
nparam[EX_WORDSIZE] = 0;
nparam[EX_CON] = 0;
nparam[EX_ROM] = 0;
nparam[EX_ARG] = 0;
nparam[EX_DEFINED] = 0;
nparam[EX_OR2] = 1;
nparam[EX_AND2] = 1;
nparam[EX_UMINUS] = 1;
nparam[EX_NOT] = 1;
nparam[EX_COMP] = 1;
nparam[EX_NOTREG] = 1;
nonumlab[EX_CMPEQ] = FALSE;
nonumlab[EX_CMPNE] = FALSE;
onlyconst[EX_CMPEQ] = FALSE;
onlyconst[EX_CMPNE] = FALSE;
onlyconst[EX_CMPLE] = FALSE;
onlyconst[EX_CMPLT] = FALSE;
onlyconst[EX_CMPGE] = FALSE;
onlyconst[EX_CMPGT] = FALSE;
onlyconst[EX_PLUS] = FALSE;
onlyconst[EX_MINUS] = FALSE;
printf("byte nparam[] = {");
for (i=0;i<N_EX_OPS;i++) printf("%d,",nparam[i]);
printf("};\nbool nonumlab[] = {");
for (i=0;i<N_EX_OPS;i++) printf("%d,",nonumlab[i]);
printf("};\nbool onlyconst[] = {");
for (i=0;i<N_EX_OPS;i++) printf("%d,",onlyconst[i]);
printf("};\n\nbyte pattern[] = { 0\n");
curind = 1;
}
outbyte(b) {
printf(",%3d",b);
curind++;
}
outshort(s) {
outbyte(s&0377);
outbyte((s>>8)&0377);
}
out(w) {
if (w<255) {
outbyte(w);
} else {
outbyte(255);
outshort(w);
}
}
#include "scan.c"

12
util/opt/optim.h Normal file
View File

@@ -0,0 +1,12 @@
/* $Header$ */
/* #define DIAGOPT /* if defined diagnostics are produced */
#ifdef DIAGOPT
#define OPTIM(x) optim(x)
#define O_UNREACH 1001
#define O_BRALAB 1002
#define O_LINLNI 1003
#define O_LINGONE 1004
#else
#define OPTIM(x) /* NOTHING */
#endif

15
util/opt/param.h Normal file
View File

@@ -0,0 +1,15 @@
/* $Header$ */
#define LONGOFF /* if defined long offsets are used */
#define TRUE 1
#define FALSE 0
#define MAXROM 3
#define op_lab (sp_lmnem+1)
#define op_last op_lab
#define ps_sym (sp_lpseu+1)
#define ps_last ps_sym
#define BMASK 0377

126
util/opt/pattern.h Normal file
View File

@@ -0,0 +1,126 @@
/* $Header$ */
/*
* pattern contains the optimization patterns in an apparently
* unordered fashion. All patterns follow each other unaligned.
* Each pattern looks as follows:
* Byte 0: high byte of hash value associated with this pattern.
* Byte 1-2: index of next pattern with same low byte of hash value.
* Byte 3- : pattern and replacement.
* First comes the pattern length
* then the pattern opcodes,
* then a boolean expression,
* then the one-byte replacement length
* then the intermixed pattern opcodes and operands or
* 0 followed by the one-byte special optimization expression.
* If the DIAGOPT option is set, the optimization is followed
* by the line number in the tables.
*/
/* #define ALLOWSPECIAL /* Special optimizations allowed */
#define PO_HASH 0
#define PO_NEXT 1
#define PO_MATCH 3
struct exprnode {
short ex_operator;
short ex_lnode;
short ex_rnode;
};
typedef struct exprnode expr_t;
typedef struct exprnode *expr_p;
/*
* contents of .ex_operator
*/
#define EX_CON 0
#define EX_ARG 1
#define EX_CMPEQ 2
#define EX_CMPNE 3
#define EX_CMPGT 4
#define EX_CMPGE 5
#define EX_CMPLT 6
#define EX_CMPLE 7
#define EX_OR2 8
#define EX_AND2 9
#define EX_OR1 10
#define EX_XOR1 11
#define EX_AND1 12
#define EX_PLUS 13
#define EX_MINUS 14
#define EX_TIMES 15
#define EX_DIVIDE 16
#define EX_MOD 17
#define EX_LSHIFT 18
#define EX_RSHIFT 19
#define EX_UMINUS 20
#define EX_NOT 21
#define EX_COMP 22
#define EX_ROM 23
#define EX_NOTREG 24
#define EX_POINTERSIZE 25
#define EX_WORDSIZE 26
#define EX_DEFINED 27
#define EX_SAMESIGN 28
#define EX_SFIT 29
#define EX_UFIT 30
#define EX_ROTATE 31
#define N_EX_OPS 32 /* must be one higher then previous */
/*
* Definition of special opcodes used in patterns
*/
#define op_pfirst op_LLP
#define op_LLP (op_last+1)
#define op_LEP (op_last+2)
#define op_SLP (op_last+3)
#define op_SEP (op_last+4)
#define op_plast op_SEP
/*
* Definition of the structure in which instruction operands
* are kept during pattern matching.
*/
typedef struct eval eval_t;
typedef struct eval *eval_p;
struct eval {
short e_typ;
union {
offset e_con;
num_p e_np;
} e_v;
};
/*
* contents of .e_typ
*/
#define EV_UNDEF 0
#define EV_CONST 1
#define EV_NUMLAB 2
#define EV_FRAG 3 /* and all higher numbers */
typedef struct iarg iarg_t;
typedef struct iarg *iarg_p;
struct iarg {
eval_t ia_ev;
sym_p ia_sp;
};
/*
* The next extern declarations refer to data generated by mktab
*/
extern byte pattern[];
extern short lastind;
extern iarg_t iargs[];
extern byte nparam[];
extern bool nonumlab[];
extern bool onlyconst[];
extern expr_t enodes[];

475
util/opt/patterns Normal file
View File

@@ -0,0 +1,475 @@
/* $Header$ */
loc adi loc sbi $2==w && $4==w: loc $1-$3 adi w
ldc adi ldc sbi $2==2*w && $4==2*w: ldc $1-$3 adi 2*w
loc adi loc adi $2==w && $4==w: loc $1+$3 adi w
ldc adi ldc adi $2==2*w && $4==2*w: ldc $1+$3 adi 2*w
adp $1==0:
adp adp : adp $1+$2
adp lof : lof $1+$2
adp ldf : ldf $1+$2
adp loi $1!=0 && $2==w: lof $1
adp loi $1!=0 && $2==2*w: ldf $1
adp stf : stf $1+$2
adp sdf : sdf $1+$2
adp sti $1!=0 && $2==w: stf $1
adp sti $1!=0 && $2==2*w: sdf $1
asp $1==0:
asp asp : asp $1+$2
blm $1==0 : asp 2*p
cmi zeq $1==w: beq $2
cmi zge $1==w: bge $2
cmi zgt $1==w: bgt $2
cmi zle $1==w: ble $2
cmi zlt $1==w: blt $2
cmi zne $1==w: bne $2
dvi ngi $1==$2: ngi $1 dvi $1
lae adp : lae $1+$2
lae blm $2==w: loi w ste $1
lae blm $2==2*w: loi 2*w sde $1
lae ldf : lde $1+$2
lae lof : loe $1+$2
lae loi $2==w: loe $1
lae loi $2==2*w: lde $1
#ifdef INT
lae loi loe $3==$1-w && $2%w==0: lae $3 loi $2+w
lae loi lde $3==$1-2*w && $2%w==0: lae $3 loi $2+2*w
lae loi lae loi $1==$3+$4 && $2%w==0 && $4%w==0: lae $3 loi $2+$4
lae sti ste $3==$1+$2: lae $1 sti $2+w
lae sti sde $3==$1+$2: lae $1 sti $2+2*w
lae sti loc ste $4==$1-w: loc $3 lae $4 sti $2+w
lae sti lol ste $4==$1-w: lol $3 lae $4 sti $2+w
#endif
lae lae blm loe ste $4==$1+$3 && $5==$2+$3: lae $1 lae $2 blm $3+w
lae lae blm lde sde $4==$1+$3 && $5==$2+$3: lae $1 lae $2 blm $3+2*w
lae lae blm lae lae blm $4==$1+$3 && $5==$2+$3: lae $1 lae $2 blm $3+$6
lae lal blm lae lal blm $4==$1+$3 && $5==$2+$3 && samesign($2,$5):
lae $1 lal $2 blm $3+$6
lal lae blm lal lae blm $4==$1+$3 && $5==$2+$3 && samesign($1,$4):
lal $1 lae $2 blm $3+$6
lal lal blm lal lal blm $4==$1+$3 && $5==$2+$3 && samesign($1,$4) && samesign($2,$5):
lal $1 lal $2 blm $3+$6
lal lal sbs $3==w && samesign($1,$2): loc $1-$2
lae sdf : sde $1+$2
lae stf : ste $1+$2
lae sti $2==w: ste $1
lae sti $2==2*w: sde $1
lal adp samesign($1,$1+$2): lal $1+$2
lal blm $2==w: loi w stl $1
lal blm $2==2*w: loi 2*w sdl $1
#ifdef INT
lal sti loc stl notreg($4) && $4==$1-w && samesign($1,$4):
loc $3 lal $4 sti $2+w
lal sti loe stl notreg($4) && $4==$1-w && samesign($1,$4):
loe $3 lal $4 sti $2+w
#endif
lal ldf samesign($1,$1+$2): ldl $1+$2
lal lof samesign($1,$1+$2): lol $1+$2
lal loi $2==w: lol $1
lal loi $2==2*w: ldl $1
#ifdef INT
lal loi lol notreg($3) && $3==$1-w && samesign($1,$3) && $2%w==0:
lal $3 loi $2+w
lal loi ldl notreg($3) && $3==$1-2*w && samesign($1,$3) && $2%w==0:
lal $3 loi $2+2*w
lal loi lal loi $1==$3+$4 && samesign($1,$3) && $2%w==0 && $4%w==0:
lal $3 loi $2+$4
lal sti stl notreg($3) && $3==$1+$2 && samesign($1,$3): lal $1 sti $2+w
lal sti sdl notreg($3) && $3==$1+$2 && samesign($1,$3): lal $1 sti $2+2*w
#endif
lal sdf samesign($1,$1+$2): sdl $1+$2
lal stf samesign($1,$1+$2): stl $1+$2
lal sti $2==w: stl $1
lal sti $2==2*w: sdl $1
#ifdef INT
lde lde $2==$1-2*w: lae $2 loi 4*w
lde loe $2==$1-w: lae $2 loi 3*w
#endif
lde sde $2==$1:
lde sde lde sde $3==$1+2*w && $4==$2+2*w: lae $1 lae $2 blm 4*w
#ifdef INT
ldl ldl $2==$1-2*w && notreg($1) && notreg($2) && samesign($1,$2):
lal $2 loi 4*w
ldl lol $2==$1-w && notreg($1) && notreg($2) && samesign($1,$2):
lal $2 loi 3*w
#endif
ldl sdl $1==$2:
lxa loi lxa sti $3==$1 && $4==$2:
lxa lof lxa stf $3==$1 && $4==$2:
lxa ldf lxa sdf $3==$1 && $4==$2:
lxa stf lxa lof $3==$1 && $4==$2: dup w lxa $1 stf $2
lxa sdf lxa ldf $3==$1 && $4==$2: dup 2*w lxa $1 sdf $2
lxl lof lxl stf $3==$1 && $4==$2:
lxl ldf lxl sdf $3==$1 && $4==$2:
lxl stf lxl lof $3==$1 && $4==$2: dup w lxl $1 stf $2
lxl sdf lxl ldf $3==$1 && $4==$2: dup 2*w lxl $1 sdf $2
lxa sti lxa loi $3==$1 && $4==$2 && $2%w==0: dup $2 lxa $1 sti $2
loc adi $1==-1 && $2==w: dec
loc dec sfit($1-1,8*w) : loc $1-1
loc bgt $1==-1: zge $2
loc ble $1==-1: zlt $2
loc dvi $1==-1 && $2==w: ngi w
ldc dvi $1==-1 && $2==2*w: ngi 2*w
loc loe adi $1==-1 && $3==w: loe $2 dec
loc loe mli $1==-1 && $3==w: loe $2 ngi w
loc lol adi $1==-1 && $3==w: lol $2 dec
loc mli $1==-1 && $2==w: ngi w
ldc mli $1==-1 && $2==2*w: ngi 2*w
loc sbi $1==-1 && $2==w: inc
loc inc sfit($1+1,8*w) : loc $1+1
loc adi $1==0 && $2==w:
ldc adi $1==0 && $2==2*w:
zer adi $1==$2:
loc beq $1==0: zeq $2
loc bge $1==0: zge $2
loc bgt $1==0: zgt $2
loc ble $1==0: zle $2
loc blt $1==0: zlt $2
loc bne $1==0: zne $2
loc cmi teq $1==0 && $2==w: teq
loc cmi tge $1==0 && $2==w: tge
loc cmi tgt $1==0 && $2==w: tgt
loc cmi tle $1==0 && $2==w: tle
loc cmi tlt $1==0 && $2==w: tlt
loc cmi tne $1==0 && $2==w: tne
loc ior $1==0 && $2==w:
ldc ior $1==0 && $2==2*w:
zer ior $1==$2:
loc ste $1==0: zre $2
loc stl $1==0: zrl $2
loc sbi $1==0 && $2==w:
ldc sbi $1==0 && $2==2*w:
zer sbi $1==$2:
loc xor $1==0 && $2==w:
ldc xor $1==0 && $2==2*w:
zer xor $1==$2:
loc adi $1==1 && $2==w: inc
loc bge $1==1: zgt $2
loc blt $1==1: zle $2
loc dvi $1==1 && $2==w:
ldc dvi $1==1 && $2==2*w:
loc loe adi $1==1 && $3==w: loe $2 inc
loc loe mli $1==1 && $3==w: loe $2
loc lol adi $1==1 && $3==w: lol $2 inc
loc lol mli $1==1 && $3==w: lol $2
loc mli $1==1 && $2==w:
loc sbi $1==1 && $2==w: dec
loc loe mli $3==w: loe $2 loc $1 mli w
loc lol mli $3==w: lol $2 loc $1 mli w
ldc lde mli $3==2*w: lde $2 ldc $1 mli 2*w
ldc lde adi $3==2*w: lde $2 ldc $1 adi 2*w
ldc ldl mli $3==2*w: ldl $2 ldc $1 mli 2*w
ldc ldl adi $3==2*w: ldl $2 ldc $1 adi 2*w
loc mli $1==2 && $2==w: loc 1 sli w
loc mli $1==4 && $2==w: loc 2 sli w
loc mli $1==8 && $2==w: loc 3 sli w
loc mli $1==16 && $2==w: loc 4 sli w
loc mli $1==32 && $2==w: loc 5 sli w
loc mli $1==64 && $2==w: loc 6 sli w
loc mli $1==128 && $2==w: loc 7 sli w
loc mli $1==256 && $2==w: loc 8 sli w
loc adi !defined($2): adi $1
loc sbi !defined($2): sbi $1
loc mli !defined($2): mli $1
loc dvi !defined($2): dvi $1
loc rmi !defined($2): rmi $1
loc ngi !defined($2): ngi $1
loc sli !defined($2): sli $1
loc sri !defined($2): sri $1
loc adu !defined($2): adu $1
loc sbu !defined($2): sbu $1
loc mlu !defined($2): mlu $1
loc dvu !defined($2): dvu $1
loc rmu !defined($2): rmu $1
loc slu !defined($2): slu $1
loc sru !defined($2): sru $1
loc adf !defined($2): adf $1
loc sbf !defined($2): sbf $1
loc mlf !defined($2): mlf $1
loc dvf !defined($2): dvf $1
loc ngf !defined($2): ngf $1
loc fif !defined($2): fif $1
loc fef !defined($2): fef $1
loc zer !defined($2): zer $1
loc zrf !defined($2): zrf $1
loc los $2==w: loi $1
loc sts $2==w: sti $1
loc ads $2==w: adp $1
loc ass $2==w: asp $1
loc bls $2==w: blm $1
loc dus $2==w: dup $1
loc loc cii $1==$2:
loc loc cuu $1==$2:
loc loc cff $1==$2:
loc and !defined($2): and $1
loc ior !defined($2): ior $1
loc xor !defined($2): xor $1
loc com !defined($2): com $1
loc rol !defined($2): rol $1
loc rol $1==0:
loc ror !defined($2): ror $1
loc ror $1==0:
loc inn !defined($2): inn $1
loc set !defined($2): set $1
loc cmi !defined($2): cmi $1
loc cmu !defined($2): cmu $1
loc cmf !defined($2): cmf $1
loe dec ste $1==$3: dee $1
loe inc ste $1==$3: ine $1
loe loc mli $2==0 && $3==w: loc 0
#ifdef INT
loe loe $2==$1-w: lde $2
loe loe beq $2==$1+w: lde $1 beq $3
loe loe bge $2==$1+w: lde $1 ble $3
loe loe bgt $2==$1+w: lde $1 blt $3
loe loe ble $2==$1+w: lde $1 bge $3
loe loe blt $2==$1+w: lde $1 bgt $3
loe loe bne $2==$1+w: lde $1 bne $3
loe loe cmi $2==$1+w && $3==w: lde $1 cmi w ngi w
#endif
ngi teq $1==w: teq
ngi tge $1==w: tle
ngi tgt $1==w: tlt
ngi tle $1==w: tge
ngi tlt $1==w: tgt
ngi tne $1==w: tne
#ifdef INT
loe loe mli $2==$1+w && $3==w: lde $1 mli w
loe loe adi $2==$1+w && $3==w: lde $1 adi w
loe loe $1==$2: loe $1 dup w
#endif
loe ste $1==$2:
LLP blm $2==w: loi w sil $1
lol dec stl $1==$3: del $1
lol inc stl $1==$3: inl $1
lol loc mli $2==0 && $3==w: loc 0
LLP loi $2==w: lil $1
#ifdef INT
lol lol $2==$1-w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $2
lol lol beq $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 beq $3
lol lol bge $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 ble $3
lol lol bgt $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 blt $3
lol lol ble $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 bge $3
lol lol blt $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 bgt $3
lol lol bne $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 bne $3
lol lol cmi $3==w && $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 cmi w ngi w
lol lol mli $3==w && $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 mli w
lol lol adi $3==w && $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 adi w
lol lol $1==$2: lol $1 dup w
#endif
lol stl $1==$2:
LLP sti $2==w: sil $1
mli ngi $1==$2: ngi $1 mli $1
ngi adi $1==$2: sbi $1
ngf adf $1==$2: sbf $1
ngi sbi $1==$2: adi $1
ngf sbf $1==$2: adf $1
ngi ngi $1==$2:
ngf ngf $1==$2:
#ifdef INT
sde sde $2==$1+2*w: lae $1 sti 4*w
sde ste $2==$1+2*w: lae $1 sti 3*w
sde loc ste $3==$1-w: loc $2 lae $3 sti 3*w
sde lol ste $3==$1-w: lol $2 lae $3 sti 3*w
sde lde $1==$2: dup 2*w sde $1
#endif
sdf $1==0: sti 2*w
#ifdef INT
sdl sdl $2==$1+2*w && notreg($1) && notreg($2) && samesign($1,$2):
lal $1 sti 4*w
sdl stl $2==$1+2*w && notreg($1) && notreg($2) && samesign($1,$2):
lal $1 sti 3*w
sdl loc stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loc $2 lal $3 sti 3*w
sdl loe stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loe $2 lal $3 sti 3*w
sdl ldl $1==$2: dup 2*w sdl $1
ste loe $1==$2: dup w ste $1
ste ste $2==$1-w: sde $2
ste loc ste $3==$1-w: loc $2 sde $3
ste lol ste $3==$1-w: lol $2 sde $3
stl lol $1==$2: dup w stl $1
#endif
stf $1==0: sti w
sdl ldl ret $1==$2 && $3==2*w: ret 2*w
#ifdef INT
stl stl $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2): sdl $1
stl loc stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loc $2 sdl $3
stl loe stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loe $2 sdl $3
#endif
stl lol ret $1==$2 && $3==w: ret w
lal sti lal loi ret $1==$3 && $2==$4 && $2==$5: ret $2
loc sbi loc sbi $2==w && $4==w: loc $1+$3 sbi w
ldc sbi ldc sbi $2==2*w && $4==2*w: ldc $1+$3 sbi 2*w
loc sbi loc adi $2==w && $4==w: loc $1-$3 sbi w
ldc sbi ldc adi $2==2*w && $4==2*w: ldc $1-$3 sbi 2*w
teq teq : tne
teq tne : teq
teq zne : zeq $2
teq zeq : zne $2
tge teq : tlt
tge tne : tge
tge zeq : zlt $2
tge zne : zge $2
tgt teq : tle
tgt tne : tgt
tgt zeq : zle $2
tgt zne : zgt $2
tle teq : tgt
tle tne : tle
tle zeq : zgt $2
tle zne : zle $2
tlt teq : tge
tlt tne : tlt
tlt zeq : zge $2
tlt zne : zlt $2
tne teq : teq
tne tne : tne
tne zeq : zeq $2
tne zne : zne $2
#ifdef INT
loc loc loc $1==0 && $2==0 && $3==0 : zer 6
zer loc defined($1) && $2==0: zer $1+w
#endif
loi loc and $1==1 && $3==w && ($2&255)==255: loi 1
loi loc loc cii $1<w && $2==w: loi $1 loc $2 loc $3 cuu
cmp teq : cms p teq
cmp tne : cms p tne
cmu teq defined($1): cms $1 teq
cmu tne defined($1): cms $1 tne
cms zeq $1==w: beq $2
cms zne $1==w: bne $2
lol lae aar adp $3==w: adp $4 lol $1 lae $2 aar w
loe lae aar adp $3==w: adp $4 loe $1 lae $2 aar w
cmi zeq defined($1): cms $1 zeq $2
cmi zne defined($1): cms $1 zne $2
loe inc dup ste $1==$4 && $3==w: ine $1 loe $1
loe dec dup ste $1==$4 && $3==w: dee $1 loe $1
lol inc dup stl $1==$4 && $3==w: inl $1 lol $1
lol dec dup stl $1==$4 && $3==w: del $1 lol $1
adp dup SEP adp $1==-$4 && $2==p: dup p adp $1 SEP $3
adp dup SLP adp $1==-$4 && $2==p: dup p adp $1 SLP $3
inc dup ste dec $2==w: dup w inc ste $3
inc dup stl dec $2==w: dup w inc stl $3
zeq bra lab $1==$3: zne $2 lab $1
zge bra lab $1==$3: zlt $2 lab $1
zgt bra lab $1==$3: zle $2 lab $1
zlt bra lab $1==$3: zge $2 lab $1
zle bra lab $1==$3: zgt $2 lab $1
zne bra lab $1==$3: zeq $2 lab $1
beq bra lab $1==$3: bne $2 lab $1
bge bra lab $1==$3: blt $2 lab $1
bgt bra lab $1==$3: ble $2 lab $1
blt bra lab $1==$3: bge $2 lab $1
ble bra lab $1==$3: bgt $2 lab $1
bne bra lab $1==$3: beq $2 lab $1
lin lin : lin $2
lin lab lin : lab $2 lin $3
lin ret : ret $2
lin bra : bra $2
dup SLP loi $1==p && $3==w: SLP $2 lil $2
dup SLP sti $1==p && $3==w: SLP $2 sil $2
loc cms $1==0 && $2==w: tne
zer $1==w: loc 0
loc loc adi $3==w && sfit($1+$2,8*w) : loc $1+$2
loc loc sbi $3==w && sfit($1-$2,8*w) : loc $1-$2
loc loc mli $3==w && sfit($1*$2,8*w) : loc $1*$2
loc loc dvi $3==w && $2!=0 : loc $1/$2
loc loc and $3==w : loc $1&$2
loc loc ior $3==w : loc $1|$2
loc loc ior $1==0 && $2==0 && $3==2*w :
loc loc xor $3==w : loc $1^$2
loc loc xor $1==0 && $2==0 && $3==2*w :
loc loc rol $3==w : loc rotate($1,$2)
loc loc ror $3==w : loc rotate($1,8*w-$2)
loc ngi $2==w && sfit(-$1,8*w) : loc -$1
loc com $2==w : loc ~$1
ldc ngi $2==2*w : ldc -$1
loc lae aar $3==w && $1>=rom(2,0) && $1 <= rom(2,0)+rom(2,1) :
adp ($1-rom(2,0))*rom(2,2)
loc lae lar $3==w && $1>=rom(2,0) && $1 <= rom(2,0)+rom(2,1) :
adp ($1-rom(2,0))*rom(2,2) loi rom(2,2)
loc lae sar $3==w && $1>=rom(2,0) && $1 <= rom(2,0)+rom(2,1) :
adp ($1-rom(2,0))*rom(2,2) sti rom(2,2)
loc teq : loc $1==0
loc tne : loc $1!=0
loc tge : loc $1>=0
loc tle : loc $1<=0
loc tgt : loc $1>0
loc tlt : loc $1<0
loc zeq $1==0 : bra $2
loc zeq :
loc zne $1!=0 : bra $2
loc zne :
loc zge $1>=0 : bra $2
loc zge :
loc zle $1<=0 : bra $2
loc zle :
loc zgt $1>0 : bra $2
loc zgt :
loc zlt $1<0 : bra $2
loc zlt :
loc loc beq $1==$2 : bra $3
loc loc beq :
loc loc bne $1!=$2 : bra $3
loc loc bne :
loc loc bge $1>=$2 : bra $3
loc loc bge :
loc loc ble $1<=$2 : bra $3
loc loc ble :
loc loc bgt $1>$2 : bra $3
loc loc bgt :
loc loc blt $1<$2 : bra $3
loc loc blt :
lae loi lal sti $2==$4 && $2>4*w : lae $1 lal $3 blm $2
lal loi lae sti $2==$4 && $2>4*w : lal $1 lae $3 blm $2
lal loi lal sti $2==$4 && $2>4*w && ( $3<=$1-$2 || $3>=$1+$2 ) :
lal $1 lal $3 blm $2
lae loi lae sti $2==$4 && $2>4*w && ( !defined($1==$3) || $3<=$1-$2 || $3>=$1+$2 ) :
lae $1 lae $3 blm $2
loc loc loc cif $1==0 && $2==w : zrf $3
loc loc loc ciu $1>=0 && $2==w && $3==2*w : ldc $1
loc loc loc cii $2==w && $3==2*w : ldc $1
loi loc inn $1==$3 && $2>=0 && $2<$1*8 :
lof ($2/(8*w))*w loc $2&(8*w-1) inn w
ldl loc inn $3==2*w && $2>=0 && $2<16*w :
lol $1+($2/(8*w))*w loc $2&(8*w-1) inn w
lde loc inn $3==2*w && $2>=0 && $2<16*w :
loe $1+($2/(8*w))*w loc $2&(8*w-1) inn w
ldf loc inn $3==2*w && $2>=0 && $2<16*w :
lof $1+($2/(8*w))*w loc $2&(8*w-1) inn w
loc inn $1<0 || $1>=8*$2 : asp $2 loc 0
lol loc adi stl $3==w && $1==$4 : loc $2 lol $1 adi w stl $4
lol loe adi stl $3==w && $1==$4 : loe $2 lol $1 adi w stl $4
lol lol adi stl $3==w && $1==$4 && $1!=$2 : lol $2 lol $1 adi w stl $4
loe loc adi ste $3==w && $1==$4 : loc $2 loe $1 adi w ste $4
loe loe adi ste $3==w && $1==$4 && $1!=$2 : loe $2 loe $1 adi w ste $4
loe lol adi ste $3==w && $1==$4 : lol $2 loe $1 adi w ste $4
lol loc ior stl $3==w && $1==$4 : loc $2 lol $1 ior w stl $4
lol loe ior stl $3==w && $1==$4 : loe $2 lol $1 ior w stl $4
lol lol ior stl $3==w && $1==$4 && $1!=$2 : lol $2 lol $1 ior w stl $4
loe loc ior ste $3==w && $1==$4 : loc $2 loe $1 ior w ste $4
loe loe ior ste $3==w && $1==$4 && $1!=$2 : loe $2 loe $1 ior w ste $4
loe lol ior ste $3==w && $1==$4 : lol $2 loe $1 ior w ste $4
lol loc and stl $3==w && $1==$4 : loc $2 lol $1 and w stl $4
lol loe and stl $3==w && $1==$4 : loe $2 lol $1 and w stl $4
lol lol and stl $3==w && $1==$4 && $1!=$2 : lol $2 lol $1 and w stl $4
loe loc and ste $3==w && $1==$4 : loc $2 loe $1 and w ste $4
loe loe and ste $3==w && $1==$4 && $1!=$2 : loe $2 loe $1 and w ste $4
loe lol and ste $3==w && $1==$4 : lol $2 loe $1 and w ste $4
loi asp $1==$2 : asp p
lal loi loc loc loc loc ior $2==4*w && $7==4*w && ($3==0)+($4==0)+($5==0)+($6==0)>2 :
lol $1+3*w loc $3 ior w lol $1+2*w loc $4 ior w lol $1+w loc $5 ior w lol $1 loc $6 ior w
loc dup stl loc dup stl $2==2 && $5==2:
loc $1 stl $3 loc $4 stl $6 loc $1 loc $4

652
util/opt/peephole.c Normal file
View File

@@ -0,0 +1,652 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
#include "alloc.h"
#include "pattern.h"
#include "../../h/em_spec.h"
#include "../../h/em_mnem.h"
#include "optim.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
/* #define CHK_HASH /* print numbers patterns are hashed to */
#ifdef CHK_HASH
#include <stdio.h>
#endif
#define ILLHASH 0177777
short pathash[256]; /* table of indices into pattern[] */
int opind = 0; /* second index of next matrix */
byte transl[op_plast-op_pfirst+1][3] = {
/* LLP */ { op_LLP, op_lol, op_ldl },
/* LEP */ { op_LEP, op_loe, op_lde },
/* SLP */ { op_SLP, op_stl, op_sdl },
/* SEP */ { op_SEP, op_ste, op_sde }
};
opcheck(bp) register byte *bp; {
if (((*bp)&BMASK) >= op_pfirst)
*bp = transl[((*bp)&BMASK)-op_pfirst][opind];
}
/*
* The hashing method used is believed to be reasonably efficient.
* A minor speed improvement could be obtained by keeping a boolean
* array telling which opcode has any patterns starting with it.
* Currently only about one third of the opcodes actually have a
* pattern starting with it, but they are the most common ones.
* Estimated improvement possible: about 2%
*/
hashpatterns() {
short index;
register byte *bp,*tp;
register short i;
unsigned short hashvalue;
byte *save;
int patlen;
if (pointersize == wordsize)
opind=1;
else if (pointersize == 2*wordsize)
opind=2;
index = lastind; /* set by mktab */
while (index != 0) {
bp = &pattern[index];
tp = &bp[PO_MATCH];
i = *tp++&BMASK;
if (i==BMASK) {
i = *tp++&BMASK;
i |= (*tp++&BMASK)<<8;
}
save = tp;
patlen = i;
while (i--)
opcheck(tp++);
if ((*tp++&BMASK)==BMASK)
tp += 2;
i = *tp++&BMASK;
if (i==BMASK) {
i = *tp++&BMASK;
i |= (*tp++&BMASK)<<8;
}
while (i--) {
opcheck(tp++);
if ((*tp++&BMASK)==BMASK)
tp += 2;
}
/*
* Now the special opcodes are filled
* in properly, we can hash the pattern
*/
hashvalue = 0;
tp = save;
switch(patlen) {
default: /* 3 or more */
hashvalue = (hashvalue<<4)^(*tp++&BMASK);
case 2:
hashvalue = (hashvalue<<4)^(*tp++&BMASK);
case 1:
hashvalue = (hashvalue<<4)^(*tp++&BMASK);
}
assert(hashvalue!= ILLHASH);
i=index;
index = (bp[PO_NEXT]&BMASK)|(bp[PO_NEXT+1]<<8);
bp[PO_HASH] = hashvalue>>8;
hashvalue &= BMASK;
bp[PO_NEXT] = pathash[hashvalue]&BMASK;
bp[PO_NEXT+1] = pathash[hashvalue]>>8;
pathash[hashvalue] = i;
#ifdef CHK_HASH
fprintf(stderr,"%d\n",hashvalue);
#endif
}
}
peephole() {
static bool phashed = FALSE;
if (!phashed) {
hashpatterns();
phashed=TRUE;
}
optimize();
}
optimize() {
register num_p *npp,np;
register instr;
basicblock(&instrs);
for (npp=curpro.numhash;npp< &curpro.numhash[NNUMHASH]; npp++)
for (np = *npp; np != (num_p) 0; np=np->n_next) {
if(np->n_line->l_next == (line_p) 0)
continue;
instr = np->n_line->l_next->l_instr&BMASK;
if (instr == op_lab || instr == op_bra)
np->n_repl = np->n_line->l_next->l_a.la_np;
else
basicblock(&np->n_line->l_next);
}
}
offset oabs(off) offset off; {
return(off >= 0 ? off : -off);
}
line_p repline(ev,patlen) eval_t ev; {
register line_p lp;
register iarg_p iap;
register sym_p sp;
offset diff,newdiff;
assert(ev.e_typ != EV_UNDEF);
switch(ev.e_typ) {
case EV_CONST:
if ((short) ev.e_v.e_con == ev.e_v.e_con) {
if (CANMINI((short) ev.e_v.e_con))
lp = newline((short) (ev.e_v.e_con)+Z_OPMINI);
else {
lp = newline(OPSHORT);
lp->l_a.la_short = (short) ev.e_v.e_con;
}
} else {
lp = newline(OPOFFSET);
lp->l_a.la_offset = ev.e_v.e_con;
}
return(lp);
case EV_NUMLAB:
lp = newline(OPNUMLAB);
lp->l_a.la_np = ev.e_v.e_np;
return(lp);
default: /* fragment + offset */
/*
* There is a slight problem here, because we have to
* map fragment+offset to symbol+offset.
* Fortunately the fragment we have must be the fragment
* of one of the symbols in the matchpattern.
* So a short search should do the job.
*/
sp = (sym_p) 0;
for (iap= &iargs[patlen-1]; iap >= iargs; iap--)
if (iap->ia_ev.e_typ == ev.e_typ) {
/*
* Although lint complains, diff is not used
* before set.
*
* The proof is left as an exercise to the
* reader.
*/
newdiff = oabs(iap->ia_sp->s_value-ev.e_v.e_con);
if (sp==(sym_p) 0 || newdiff < diff) {
sp = iap->ia_sp;
diff = newdiff;
}
}
assert(sp != (sym_p) 0);
if (diff == 0) {
lp = newline(OPSYMBOL);
lp->l_a.la_sp = sp;
} else {
diff = ev.e_v.e_con - sp->s_value;
if ((short) diff == diff) {
lp = newline(OPSVAL);
lp->l_a.la_sval.lasv_short = (short) diff;
lp->l_a.la_sval.lasv_sp = sp;
} else {
lp = newline(OPLVAL);
lp->l_a.la_lval.lalv_offset = diff;
lp->l_a.la_lval.lalv_sp = sp;
}
}
return(lp);
}
}
offset rotate(w,amount) offset w,amount; {
offset highmask,lowmask;
#ifndef LONGOFF
assert(wordsize<=4);
#endif
highmask = (offset)(-1) << amount;
lowmask = ~highmask;
if (wordsize != 4)
highmask &= wordsize==2 ? 0xFFFF : 0xFF;
return(((w<<amount)&highmask)|((w>>(8*wordsize-amount))&lowmask));
}
eval_t undefres = { EV_UNDEF };
eval_t compute(pexp) register expr_p pexp; {
eval_t leaf1,leaf2,res;
register i;
register sym_p sp;
offset mask;
switch(nparam[pexp->ex_operator]) {
default:
assert(FALSE);
case 2:
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ == EV_UNDEF ||
nonumlab[pexp->ex_operator] && leaf2.e_typ == EV_NUMLAB ||
onlyconst[pexp->ex_operator] && leaf2.e_typ != EV_CONST)
return(undefres);
case 1:
leaf1 = compute(&enodes[pexp->ex_lnode]);
if (leaf1.e_typ == EV_UNDEF ||
nonumlab[pexp->ex_operator] && leaf1.e_typ == EV_NUMLAB ||
onlyconst[pexp->ex_operator] && leaf1.e_typ != EV_CONST)
return(undefres);
case 0:
break;
}
res.e_typ = EV_CONST;
res.e_v.e_con = 0;
switch(pexp->ex_operator) {
default:
assert(FALSE);
case EX_CON:
res.e_v.e_con = (offset) pexp->ex_lnode;
break;
case EX_ARG:
return(iargs[pexp->ex_lnode - 1].ia_ev);
case EX_CMPEQ:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
if (leaf1.e_typ == EV_NUMLAB) {
if (leaf1.e_v.e_np == leaf2.e_v.e_np)
res.e_v.e_con = 1;
break;
}
if (leaf1.e_v.e_con == leaf2.e_v.e_con)
res.e_v.e_con = 1;
break;
case EX_CMPNE:
if (leaf1.e_typ != leaf2.e_typ) {
res.e_v.e_con = 1;
break;
}
if (leaf1.e_typ == EV_NUMLAB) {
if (leaf1.e_v.e_np != leaf2.e_v.e_np)
res.e_v.e_con = 1;
break;
}
if (leaf1.e_v.e_con != leaf2.e_v.e_con)
res.e_v.e_con = 1;
break;
case EX_CMPGT:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con > leaf2.e_v.e_con;
break;
case EX_CMPGE:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con >= leaf2.e_v.e_con;
break;
case EX_CMPLT:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con < leaf2.e_v.e_con;
break;
case EX_CMPLE:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con <= leaf2.e_v.e_con;
break;
case EX_OR2:
if (leaf1.e_v.e_con != 0)
return(leaf1);
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ != EV_CONST)
return(undefres);
return(leaf2);
case EX_AND2:
if (leaf1.e_v.e_con == 0)
return(leaf1);
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ != EV_CONST)
return(undefres);
return(leaf2);
case EX_OR1:
res.e_v.e_con = leaf1.e_v.e_con | leaf2.e_v.e_con;
break;
case EX_XOR1:
res.e_v.e_con = leaf1.e_v.e_con ^ leaf2.e_v.e_con;
break;
case EX_AND1:
res.e_v.e_con = leaf1.e_v.e_con & leaf2.e_v.e_con;
break;
case EX_TIMES:
res.e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con;
break;
case EX_DIVIDE:
res.e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con;
break;
case EX_MOD:
res.e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con;
break;
case EX_LSHIFT:
res.e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con;
break;
case EX_RSHIFT:
res.e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con;
break;
case EX_UMINUS:
res.e_v.e_con = -leaf1.e_v.e_con;
break;
case EX_NOT:
res.e_v.e_con = !leaf1.e_v.e_con;
break;
case EX_COMP:
res.e_v.e_con = ~leaf1.e_v.e_con;
break;
case EX_PLUS:
if (leaf1.e_typ >= EV_FRAG) {
if (leaf2.e_typ >= EV_FRAG)
return(undefres);
res.e_typ = leaf1.e_typ;
} else
res.e_typ = leaf2.e_typ;
res.e_v.e_con = leaf1.e_v.e_con + leaf2.e_v.e_con;
break;
case EX_MINUS:
if (leaf1.e_typ >= EV_FRAG) {
if (leaf2.e_typ == EV_CONST)
res.e_typ = leaf1.e_typ;
else if (leaf2.e_typ != leaf1.e_typ)
return(undefres);
} else if (leaf2.e_typ >= EV_FRAG)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con;
break;
case EX_POINTERSIZE:
res.e_v.e_con = pointersize;
break;
case EX_WORDSIZE:
res.e_v.e_con = wordsize;
break;
case EX_NOTREG:
res.e_v.e_con = !inreg(leaf1.e_v.e_con);
break;
case EX_DEFINED:
leaf1 = compute(&enodes[pexp->ex_lnode]);
res.e_v.e_con = leaf1.e_typ != EV_UNDEF;
break;
case EX_SAMESIGN:
res.e_v.e_con = (leaf1.e_v.e_con ^ leaf2.e_v.e_con) >= 0;
break;
case EX_ROM:
if ((sp = iargs[pexp->ex_lnode - 1].ia_sp) != (sym_p) 0 &&
sp->s_rom != (offset *) 0) {
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ != EV_CONST ||
leaf2.e_v.e_con < 0 ||
leaf2.e_v.e_con >= MAXROM)
return(undefres);
res.e_v.e_con = sp->s_rom[leaf2.e_v.e_con];
break;
} else
return(undefres);
case EX_SFIT:
mask = 0;
for (i=leaf2.e_v.e_con - 1;i < 8*sizeof(offset); i++)
mask |= 1<<i;
res.e_v.e_con = (leaf1.e_v.e_con&mask) == 0 ||
(leaf1.e_v.e_con&mask) == mask;
break;
case EX_UFIT:
mask = 0;
for (i=leaf2.e_v.e_con;i < 8*sizeof(offset); i++)
mask |= 1<<i;
res.e_v.e_con = (leaf1.e_v.e_con&mask) == 0;
break;
case EX_ROTATE:
res.e_v.e_con = rotate(leaf1.e_v.e_con,leaf2.e_v.e_con);
break;
}
return(res);
}
#ifdef ALLOWSPECIAL
extern bool special();
#endif
bool tryrepl(lpp,bp,patlen)
line_p *lpp;
register byte *bp;
int patlen;
{
int rpllen,instr,rplval;
register line_p lp;
line_p replacement,*rlpp,tp;
rpllen = *bp++&BMASK;
if (rpllen == BMASK) {
rpllen = *bp++&BMASK;
rpllen |= (*bp++&BMASK)<<8;
}
#ifdef ALLOWSPECIAL
if (rpllen == 1 && *bp == 0)
return(special(lpp,bp+1,patlen));
#endif
replacement = (line_p) 0;
rlpp = &replacement;
while (rpllen--) {
instr = *bp++&BMASK;
rplval = *bp++&BMASK;
if (rplval == BMASK) {
rplval = (*bp++&BMASK);
rplval |= (*bp++&BMASK)<<8;
}
if (rplval)
lp = repline(compute(&enodes[rplval]),patlen);
else
lp = newline(OPNO);
/*
* One replacement instruction is generated,
* link in list and proceed with the next one.
*/
if (instr == op_lab)
lp->l_a.la_np->n_line = lp;
*rlpp = lp;
rlpp = &lp->l_next;
lp->l_instr = instr;
}
/*
* Replace instructions matched by the created replacement
*/
OPTIM((bp[0]&BMASK)|(bp[1]&BMASK)<<8);
for (lp= *lpp;patlen>0;patlen--,tp=lp,lp=lp->l_next)
;
tp->l_next = (line_p) 0;
*rlpp = lp;
lp = *lpp;
*lpp = replacement;
while ( lp != (line_p) 0 ) {
tp = lp->l_next;
oldline(lp);
lp = tp;
}
return(TRUE);
}
bool trypat(lpp,bp,len)
line_p *lpp;
register byte *bp;
int len;
{
register iarg_p iap;
int i,patlen;
register line_p lp;
eval_t result;
patlen = *bp++&BMASK;
if (patlen == BMASK) {
patlen = *bp++&BMASK;
patlen |= (*bp++&BMASK)<<8;
}
if (len == 3) {
if (patlen<3)
return(FALSE);
} else {
if (patlen != len)
return(FALSE);
}
/*
* Length is ok, now check opcodes
*/
for (i=0,lp= *lpp;i<patlen && lp != (line_p) 0;i++,lp=lp->l_next)
if (lp->l_instr != *bp++)
return(FALSE);
if (i != patlen)
return(FALSE);
/*
* opcodes are also correct, now comes the hard part
*/
for(i=0,lp= *lpp,iap= iargs; i<patlen;i++,iap++,lp=lp->l_next) {
switch(lp->l_optyp) {
case OPNO:
iap->ia_ev.e_typ = EV_UNDEF;
break;
default:
iap->ia_ev.e_typ = EV_CONST;
iap->ia_ev.e_v.e_con = (lp->l_optyp&BMASK)-Z_OPMINI;
break;
case OPSHORT:
iap->ia_ev.e_typ = EV_CONST;
iap->ia_ev.e_v.e_con = lp->l_a.la_short;
break;
#ifdef LONGOFF
case OPOFFSET:
iap->ia_ev.e_typ = EV_CONST;
iap->ia_ev.e_v.e_con = lp->l_a.la_offset;
break;
#endif
case OPNUMLAB:
iap->ia_ev.e_typ = EV_NUMLAB;
iap->ia_ev.e_v.e_np = lp->l_a.la_np;
break;
case OPSYMBOL:
iap->ia_ev.e_typ = lp->l_a.la_sp->s_frag;
iap->ia_sp = lp->l_a.la_sp;
iap->ia_ev.e_v.e_con = lp->l_a.la_sp->s_value;
break;
case OPSVAL:
iap->ia_ev.e_typ = lp->l_a.la_sval.lasv_sp->s_frag;
iap->ia_sp = lp->l_a.la_sval.lasv_sp;
iap->ia_ev.e_v.e_con = lp->l_a.la_sval.lasv_sp->s_value + lp->l_a.la_sval.lasv_short;
break;
#ifdef LONGOFF
case OPLVAL:
iap->ia_ev.e_typ = lp->l_a.la_lval.lalv_sp->s_frag;
iap->ia_sp = lp->l_a.la_lval.lalv_sp;
iap->ia_ev.e_v.e_con = lp->l_a.la_lval.lalv_sp->s_value + lp->l_a.la_lval.lalv_offset;
break;
#endif
}
}
i = *bp++&BMASK;
if ( i==BMASK ) {
i = *bp++&BMASK;
i |= (*bp++&BMASK)<<8;
}
if ( i != 0) {
/* there is a condition */
result = compute(&enodes[i]);
if (result.e_typ != EV_CONST || result.e_v.e_con == 0)
return(FALSE);
}
return(tryrepl(lpp,bp,patlen));
}
basicblock(alpp) line_p *alpp; {
register line_p *lpp,lp;
bool madeopt;
unsigned short hash[3];
line_p *next;
register byte *bp;
int i;
short index;
do { /* make pass over basicblock */
lpp = alpp; madeopt = FALSE;
while ((*lpp) != (line_p) 0 && ((*lpp)->l_instr&BMASK) != op_lab) {
lp = *lpp; next = &lp->l_next;
hash[0] = lp->l_instr&BMASK;
lp=lp->l_next;
if (lp != (line_p) 0) {
hash[1] = (hash[0]<<4)^(lp->l_instr&BMASK);
lp=lp->l_next;
if (lp != (line_p) 0)
hash[2] = (hash[1]<<4)^(lp->l_instr&BMASK);
else
hash[2] = ILLHASH;
} else {
hash[1] = ILLHASH;
hash[2] = ILLHASH;
}
/*
* hashvalues computed. Try for longest pattern first
*/
for (i=2;i>=0;i--) {
index = pathash[hash[i]&BMASK];
while (index != 0) {
bp = &pattern[index];
if((bp[PO_HASH]&BMASK) == (hash[i]>>8))
if(trypat(lpp,&bp[PO_MATCH],i+1)) {
madeopt = TRUE;
next = lpp;
i = 0; /* dirty way of double break */
break;
}
index=(bp[PO_NEXT]&BMASK)|(bp[PO_NEXT+1]<<8);
}
}
lpp = next;
}
} while(madeopt); /* as long as there is progress */
}

185
util/opt/process.c Normal file
View File

@@ -0,0 +1,185 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "alloc.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
process() {
if (wordsize == 0 || pointersize == 0)
error("No MES EMX encountered");
backward(); /* reverse and cleanup list */
symknown(); /* symbol scope is now known */
if (!nflag)
symvalue(); /* give symbols value */
if (prodepth != 0) {
if (!nflag) {
checklocs(); /* check definition of locals */
peephole(); /* local optimization */
relabel(); /* relabel local labels */
flow(); /* throw away unreachable code */
}
outpro(); /* generate PRO pseudo */
outregs(); /* generate MES ms_reg pseudos */
}
putlines(pseudos); /* pseudos first */
if (prodepth != 0) {
putlines(instrs); /* instructions next */
outend(); /* generate END pseudo */
cleanlocals(); /* forget instruction labels */
} else if(instrs != (line_p) 0)
error("instructions outside procedure");
#ifdef COREDEBUG
coreverbose();
#endif
}
relabel() {
register num_p *npp,np,tp;
register num_p repl,ttp;
/*
* For each label find its final destination after crossjumping.
* Care has to be taken to prevent a loop in the program to
* cause same in the optimizer.
*/
for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++)
for (np = *npp; np != (num_p) 0; np = np->n_next) {
assert((np->n_line->l_instr&BMASK) == op_lab
&& np->n_line->l_a.la_np == np);
for(tp=np; (tp->n_flags&(NUMKNOWN|NUMMARK))==0;
tp = tp->n_repl)
tp->n_flags |= NUMMARK;
repl = tp->n_repl;
for(tp=np; tp->n_flags&NUMMARK; tp = ttp) {
ttp = tp->n_repl;
tp->n_repl = repl;
tp->n_flags &= ~ NUMMARK;
tp->n_flags |= NUMKNOWN;
}
}
}
symknown() {
register sym_p *spp,sp;
for (spp = symhash; spp < &symhash[NSYMHASH]; spp++)
for (sp = *spp; sp != (sym_p) 0; sp = sp->s_next)
sp->s_flags |= SYMKNOWN;
}
cleanlocals() {
register num_p *npp,np,tp;
for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++) {
np = *npp;
while (np != (num_p) 0) {
tp = np->n_next;
oldnum(np);
np = tp;
}
*npp = (num_p) 0;
}
}
checklocs() {
register num_p *npp,np;
for (npp=curpro.numhash; npp < & curpro.numhash[NNUMHASH]; npp++)
for (np = *npp; np != (num_p) 0; np=np->n_next)
if (np->n_line == (line_p) 0)
error("local label %u undefined",
(unsigned) np->n_number);
}
offset align(count,alignment) offset count,alignment; {
assert(alignment==1||alignment==2||alignment==4);
return((count+alignment-1)&~(alignment-1));
}
symvalue() {
register line_p lp;
register sym_p sp;
register arg_p ap;
register argb_p abp;
short curfrag = 0;
offset count;
for (lp=pseudos; lp != (line_p) 0; lp = lp->l_next)
switch(lp->l_instr&BMASK) {
default:
assert(FALSE);
case ps_sym:
sp = lp->l_a.la_sp;
if (sp->s_frag != curfrag) {
count = 0;
curfrag = sp->s_frag;
}
count = align(count,wordsize);
sp->s_value = count;
break;
case ps_bss:
case ps_hol:
/* nothing to do, all bss pseudos are in diff frags */
case ps_mes:
break;
case ps_con:
case ps_rom:
for (ap=lp->l_a.la_arg; ap != (arg_p) 0; ap = ap->a_next)
switch(ap->a_typ) {
default:
assert(FALSE);
case ARGOFF:
count = align(count,wordsize)+wordsize;
break;
case ARGNUM:
case ARGSYM:
case ARGVAL:
count = align(count,wordsize)+pointersize;
break;
case ARGICN:
case ARGUCN:
case ARGFCN:
if (ap->a_a.a_con.ac_length < wordsize)
count = align(count,(offset)ap->a_a.a_con.ac_length);
else
count = align(count,wordsize);
count += ap->a_a.a_con.ac_length;
break;
case ARGSTR:
for (abp = &ap->a_a.a_string; abp != (argb_p) 0;
abp = abp->ab_next)
count += abp->ab_index;
break;
}
}
}

36
util/opt/proinf.h Normal file
View File

@@ -0,0 +1,36 @@
/* $Header$ */
struct num {
num_p n_next;
unsigned n_number;
unsigned n_jumps;
num_p n_repl;
short n_flags;
line_p n_line;
};
/* contents of .n_flags */
#define NUMDATA 000001
#define NUMREACH 000002
#define NUMKNOWN 000004
#define NUMMARK 000010
#define NUMSCAN 000020
#define NNUMHASH 37
extern num_p numlookup();
struct regs {
reg_p r_next;
offset r_par[4];
};
typedef struct proinf {
offset localbytes;
line_p lastline;
sym_p symbol;
reg_p freg;
bool gtoproc;
num_p numhash[NNUMHASH];
} proinf;
extern proinf curpro;

379
util/opt/putline.c Normal file
View File

@@ -0,0 +1,379 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_mnem.h"
#include "../../h/em_flag.h"
#include "alloc.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
#include "optim.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
#define outbyte(b) putc(b,outfile)
putlines(lnp) register line_p lnp; {
register arg_p ap;
line_p temp;
register instr;
short curlin= -2;
short thislin;
while ( lnp != (line_p) 0) {
instr = lnp->l_instr&BMASK;
switch(lnp->l_optyp) {
case OPSYMBOL:
if ((lnp->l_instr&BMASK) == ps_sym)
outdef(lnp->l_a.la_sp);
else
outocc(lnp->l_a.la_sp);
break;
case OPSVAL:
outocc(lnp->l_a.la_sval.lasv_sp);
break;
#ifdef LONGOFF
case OPLVAL:
outocc(lnp->l_a.la_lval.lalv_sp);
break;
#endif
case OPLIST:
ap = lnp->l_a.la_arg;
while (ap != (arg_p) 0) {
switch(ap->a_typ) {
case ARGSYM:
outocc(ap->a_a.a_sp);
break;
case ARGVAL:
outocc(ap->a_a.a_val.av_sp);
break;
}
ap = ap->a_next;
}
break;
}
/*
* global symbols now taken care of
*/
switch(instr) {
case ps_sym:
break;
case op_lni:
if (curlin != -2)
curlin++;
outinst(instr);
break;
case op_lin:
switch(lnp->l_optyp) {
case OPNO:
case OPOFFSET:
case OPNUMLAB:
case OPSYMBOL:
case OPSVAL:
case OPLVAL:
case OPLIST:
outinst(instr);
goto processoperand;
case OPSHORT:
thislin = lnp->l_a.la_short;
break;
default:
thislin = (lnp->l_optyp&BMASK)-Z_OPMINI;
break;
}
if (thislin == curlin && !nflag) {
temp = lnp->l_next;
oldline(lnp);
lnp = temp;
OPTIM(O_LINGONE);
continue;
} else if (thislin == curlin+1 && !nflag) {
instr = op_lni;
outinst(instr);
temp = lnp->l_next;
oldline(lnp);
OPTIM(O_LINLNI);
lnp = newline(OPNO);
lnp->l_next = temp;
lnp->l_instr = instr;
} else {
outinst(instr);
}
curlin = thislin;
break;
case op_lab:
curlin = -2;
break;
default:
outinst(instr);
}
processoperand:
switch(lnp->l_optyp) {
case OPNO:
if ((em_flag[instr-sp_fmnem]&EM_PAR)!=PAR_NO)
outbyte( (byte) sp_cend) ;
break;
default:
outint((lnp->l_optyp&BMASK)-Z_OPMINI);
break;
case OPSHORT:
outint(lnp->l_a.la_short);
break;
#ifdef LONGOFF
case OPOFFSET:
outoff(lnp->l_a.la_offset);
break;
#endif
case OPNUMLAB:
if (instr == op_lab)
numlab(lnp->l_a.la_np->n_repl);
else if (instr < sp_fpseu) /* plain instruction */
outint((short) lnp->l_a.la_np->n_repl->n_number);
else
outnum(lnp->l_a.la_np->n_repl);
break;
case OPSYMBOL:
outsym(lnp->l_a.la_sp);
break;
case OPSVAL:
outbyte( (byte) sp_doff) ;
outsym(lnp->l_a.la_sval.lasv_sp);
outint(lnp->l_a.la_sval.lasv_short);
break;
#ifdef LONGOFF
case OPLVAL:
outbyte( (byte) sp_doff) ;
outsym(lnp->l_a.la_lval.lalv_sp);
outoff(lnp->l_a.la_lval.lalv_offset);
break;
#endif
case OPLIST:
putargs(lnp->l_a.la_arg);
switch(instr) {
case ps_con:
case ps_rom:
case ps_mes:
outbyte( (byte) sp_cend) ;
}
}
/*
* instruction is output now.
* remove its useless body
*/
temp = lnp->l_next;
oldline(lnp);
lnp = temp;
if (ferror(outfile))
error("write error");
}
}
putargs(ap) register arg_p ap; {
while (ap != (arg_p) 0) {
switch(ap->a_typ) {
default:
assert(FALSE);
case ARGOFF:
outoff(ap->a_a.a_offset);
break;
case ARGNUM:
outnum(ap->a_a.a_np->n_repl);
break;
case ARGSYM:
outsym(ap->a_a.a_sp);
break;
case ARGVAL:
outbyte( (byte) sp_doff) ;
outsym(ap->a_a.a_val.av_sp);
outoff(ap->a_a.a_val.av_offset);
break;
case ARGSTR:
outbyte( (byte) sp_scon) ;
putstr(&ap->a_a.a_string);
break;
case ARGICN:
outbyte( (byte) sp_icon) ;
goto casecon;
case ARGUCN:
outbyte( (byte) sp_ucon) ;
goto casecon;
case ARGFCN:
outbyte( (byte) sp_fcon) ;
casecon:
outint(ap->a_a.a_con.ac_length);
putstr(&ap->a_a.a_con.ac_con);
break;
}
ap = ap->a_next;
}
}
putstr(abp) register argb_p abp; {
register argb_p tbp;
register length;
length = 0;
tbp = abp;
while (tbp!= (argb_p) 0) {
length += tbp->ab_index;
tbp = tbp->ab_next;
}
outint(length);
while (abp != (argb_p) 0) {
for (length=0;length<abp->ab_index;length++)
outbyte( (byte) abp->ab_contents[length] );
abp = abp->ab_next;
}
}
outdef(sp) register sym_p sp; {
/*
* The surrounding If statement is removed to be friendly
* to Backend writers having to deal with assemblers
* not following our conventions.
if ((sp->s_flags&SYMOUT)==0) {
*/
sp->s_flags |= SYMOUT;
if (sp->s_flags&SYMGLOBAL) {
outinst(sp->s_flags&SYMPRO ? ps_exp : ps_exa);
outsym(sp);
}
/*
}
*/
}
outocc(sp) register sym_p sp; {
if ((sp->s_flags&SYMOUT)==0) {
sp->s_flags |= SYMOUT;
if ((sp->s_flags&SYMGLOBAL)==0) {
outinst(sp->s_flags&SYMPRO ? ps_inp : ps_ina);
outsym(sp);
}
}
}
outpro() {
outdef(curpro.symbol);
outinst(ps_pro);
outsym(curpro.symbol);
outoff(curpro.localbytes);
}
outend() {
outinst(ps_end);
outoff(curpro.localbytes);
}
outinst(m) {
outbyte( (byte) m );
}
outoff(off) offset off; {
#ifdef LONGOFF
if ((short) off == off)
#endif
outint((short) off);
#ifdef LONGOFF
else {
outbyte( (byte) sp_cst4) ;
outshort( (short) (off&0177777L) );
outshort( (short) (off>>16) );
}
#endif
}
outint(i) short i; {
if (i>= -sp_zcst0 && i< sp_ncst0-sp_zcst0)
outbyte( (byte) (i+sp_zcst0+sp_fcst0) );
else {
outbyte( (byte) sp_cst2) ;
outshort(i);
}
}
outshort(i) short i; {
outbyte( (byte) (i&BMASK) );
outbyte( (byte) (i>>8) );
}
numlab(np) register num_p np; {
if (np->n_number < sp_nilb0)
outbyte( (byte) (np->n_number + sp_filb0) );
else
outnum(np);
}
outnum(np) register num_p np; {
if(np->n_number<256) {
outbyte( (byte) sp_ilb1) ;
outbyte( (byte) (np->n_number) );
} else {
outbyte( (byte) sp_ilb2) ;
outshort((short) np->n_number);
}
}
outsym(sp) register sym_p sp; {
register byte *p;
register unsigned num;
if (sp->s_name[0] == '.') {
num = atoi(&sp->s_name[1]);
if (num < 256) {
outbyte( (byte) sp_dlb1) ;
outbyte( (byte) (num) );
} else {
outbyte( (byte) sp_dlb2) ;
outshort((short) num);
}
} else {
p= sp->s_name;
while (*p && p < &sp->s_name[IDL])
p++;
num = p - sp->s_name;
outbyte( (byte) (sp->s_flags&SYMPRO ? sp_pnam : sp_dnam) );
outint((short) num);
p = sp->s_name;
while (num--)
outbyte( (byte) *p++ );
}
}

101
util/opt/reg.c Normal file
View File

@@ -0,0 +1,101 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include "param.h"
#include "types.h"
#include "line.h"
#include "proinf.h"
#include "alloc.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_mes.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
regvar(ap) register arg_p ap; {
register reg_p rp;
register i;
rp = newreg();
i=0;
while (ap!=(arg_p)0 && ap->a_typ==ARGOFF && i<4) {
rp->r_par[i++]=ap->a_a.a_offset;
ap=ap->a_next;
}
/*
* Omit incomplete messages
*/
switch(i) {
default:assert(FALSE);
case 0:
case 1:
case 2: oldreg(rp); return;
case 3: rp->r_par[3]= (offset) 0; break;
case 4: break;
}
rp->r_next = curpro.freg;
curpro.freg = rp;
}
inreg(off) offset off; {
register reg_p rp;
for (rp=curpro.freg; rp != (reg_p) 0; rp=rp->r_next)
if( rp->r_par[0] == off)
return(TRUE);
return(FALSE);
}
outregs() {
register reg_p rp,tp;
register i;
for(rp=curpro.freg; rp != (reg_p) 0; rp = tp) {
tp = rp->r_next;
if (rp->r_par[3] != 0) {
outinst(ps_mes);
outoff((offset)ms_reg);
for(i=0;i<4;i++)
outoff(rp->r_par[i]);
outinst(sp_cend);
}
oldreg(rp);
}
/* List of register messages is followed by an empty ms_reg
* unless an ms_gto was in this procedure, then the ms_gto
* will be output. Kludgy.
*/
outinst(ps_mes);
outoff((offset)(curpro.gtoproc? ms_gto : ms_reg));
outinst(sp_cend);
curpro.freg = (reg_p) 0;
}
incregusage(off) offset off; {
register reg_p rp;
for(rp=curpro.freg; rp != (reg_p) 0; rp=rp->r_next)
if (rp->r_par[0]==off) {
rp->r_par[3]++;
return;
}
}

76
util/opt/scan.l Normal file
View File

@@ -0,0 +1,76 @@
%{
#ifndef NORCSID
static char rcsid2[] = "$Header$";
#endif
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
extern long atol();
%}
%%
notreg return(NOTREG);
sfit return(SFIT);
ufit return(UFIT);
rotate return(ROTATE);
p return(PSIZE);
w return(WSIZE);
defined return(DEFINED);
samesign return(SAMESIGN);
rom return(ROM);
[a-zA-Z]{3} {
int m;
m = mlookup(yytext);
if (m==0) {
REJECT;
} else {
yylval.y_int = m;
return(MNEM);
}
}
"&&" return(AND2);
"||" return(OR2);
"&" return(AND1);
"|" return(OR1);
"^" return(XOR1);
"+" return(ARPLUS);
"-" return(ARMINUS);
"*" return(ARTIMES);
"/" return(ARDIVIDE);
"%" return(ARMOD);
"==" return(CMPEQ);
"!=" return(CMPNE);
"<" return(CMPLT);
"<=" return(CMPLE);
">" return(CMPGT);
">=" return(CMPGE);
"!" return(NOT);
"~" return(COMP);
"<<" return(LSHIFT);
">>" return(RSHIFT);
[0-9]+ { long l= atol(yytext);
if (l>32767) yyerror("Number too big");
yylval.y_int= (int) l;
return(NUMBER);
}
[ \t] ;
. return(yytext[0]);
\n { lino++; return(yytext[0]); }
:[ \t]*\n[ \t]+ { lino++; return(':'); }
^"# "[0-9]+.*\n { lino=atoi(yytext+2); }
^\#.*\n { lino++; }

33
util/opt/special.c Normal file
View File

@@ -0,0 +1,33 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
bool special(lpp,bp,patlen)
line_p *lpp;
byte *bp;
int patlen;
{
return(FALSE);
}

8
util/opt/testopt Executable file
View File

@@ -0,0 +1,8 @@
: '$Header$'
while true
do
(echo ' mes 2,2,2
pro $foo,0';cat;echo ' end') >t.e
npc -2=${1-opt} -O -2 t.e;npc -D t.m
cat t.e
done

21
util/opt/types.h Normal file
View File

@@ -0,0 +1,21 @@
/* $Header$ */
typedef char byte;
typedef char bool;
typedef struct line line_t;
typedef struct line *line_p;
typedef struct sym sym_t;
typedef struct sym *sym_p;
typedef struct num num_t;
typedef struct num *num_p;
typedef struct arg arg_t;
typedef struct arg *arg_p;
typedef struct argbytes argb_t;
typedef struct argbytes *argb_p;
typedef struct regs reg_t;
typedef struct regs *reg_p;
#ifdef LONGOFF
typedef long offset;
#else
typedef short offset;
#endif

62
util/opt/util.c Normal file
View File

@@ -0,0 +1,62 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "lookup.h"
#include "proinf.h"
#include "optim.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
/* VARARGS1 */
error(s,a) char *s,*a; {
fprintf(stderr,"%s: error on line %u",progname,linecount);
if (prodepth != 0)
fprintf(stderr,"(%.*s)",IDL,curpro.symbol->s_name);
fprintf(stderr,": ");
fprintf(stderr,s,a);
fprintf(stderr,"\n");
abort();
exit(-1);
}
#ifndef NDEBUG
badassertion(file,line) char *file; unsigned line; {
fprintf(stderr,"assertion failed file %s, line %u\n",file,line);
error("assertion");
}
#endif
#ifdef DIAGOPT
optim(n) {
fprintf(stderr,"Made optimization %d",n);
if (inpro)
fprintf(stderr," (%.*s)",IDL,curpro.symbol->s_name);
fprintf(stderr,"\n");
}
#endif

40
util/opt/var.c Normal file
View File

@@ -0,0 +1,40 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "lookup.h"
#include "proinf.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
unsigned linecount = 0; /* "line"number for errormessages */
int prodepth = 0; /* Level of nesting */
bool Lflag = 0; /* make library module */
bool nflag = 0; /* do not optimize */
line_p instrs,pseudos; /* pointers to chains */
sym_p symhash[NSYMHASH]; /* array of pointers to chains */
FILE *outfile;
char template[] = "/usr/tmp/emoptXXXXXX";
offset wordsize = 0;
offset pointersize = 0;
char *progname;
proinf curpro; /* collected information about current pro */