From b35e02396b8fe26764c9be38928a38ff8d1e131f Mon Sep 17 00:00:00 2001 From: Oliver Lehmann Date: Fri, 11 May 1990 13:39:11 +0000 Subject: [PATCH] add LCC - a better C-Compiler for WEGA --- WEGA/contrib/lcc/cmd/comp/common/sty.y | 1959 ++++++++++++++++++++++++ 1 file changed, 1959 insertions(+) create mode 100644 WEGA/contrib/lcc/cmd/comp/common/sty.y diff --git a/WEGA/contrib/lcc/cmd/comp/common/sty.y b/WEGA/contrib/lcc/cmd/comp/common/sty.y new file mode 100644 index 0000000..075e618 --- /dev/null +++ b/WEGA/contrib/lcc/cmd/comp/common/sty.y @@ -0,0 +1,1959 @@ +/* The input language uses many C conventions and notations */ +/* Types are represented as a shorthand: + c char + i int + s short + l long + p pointer + P alternate form of pointer + t structure + v void + ux unsigned x + f float + d double +/* There are a number of builtin cost names: + NONAME a constant with no name field (not an address) + CONVAL n the constant n + NCONVAL n the constant -n + POSRANGE n constants in the range [0,2**n -1] + SGRANGE n constants in the range [-2**n, 2**n - 1] + */ +/* There are also several incedental needs, etc, specified + 1,2,3,4 Number of needed registers + $P need pairs + $Q need quads + $< share left + $> share right + $L result left + $R result right + $1,2,3,4 result in reg 1, 2, 3, 4 + $C operation produces correct condition codes + $N no value produced: side effects only + $A need them all + $[ share left, RHS is preferred (if a temp register) + $] share right, RHS is preferred (if a temp register) + $l left side is referenced once more + $r right side is referenced once more + */ + +/* NOTE: + When several templates match with equal cost, the first is chosen. + Thus, when side-effects only are desired, the first template matching + is taken, if it is of lowest cost. + Moral: $N templates should be cheaper or should preceed $L, $1, etc. + */ + +%{ +# include +# include "mfile2.h" +# include "common" +# ifndef NHALF +# define NHALF 0x800 +# endif +# ifndef RKLET +# define RKLET 0x1000 +# endif +# ifndef RXLET +# define RXLET 0x2000 +#endif + +typedef struct { + int sha; /* shape */ + int ty; /* type */ +} SHTY; +SHTY lshty, /* left and right shape type */ + rshty; +static int dcost = 0; /* default cost */ +static int op, + tyop, + needs, + pcount; + qcount; + rewrite, + cost; +static int lcount, rcount; +static int opno; +static int ophd[DSIZE]; +static int optl[DSIZE]; +static int opsh[DSIZE]; + +struct optb { /* operation table */ + int op; /* what operation is to be matched */ + int tyop; /* the type associated with the op node */ + int nxop; /* index of the next op */ + int line; /* stin file line number */ + SHTY l, /* shapes of the left side */ + r; /* right side */ + int oneeds, /* needs */ + orew, /* rewrite info */ + ocost; /* op cost */ + char *string;/* the output */ + int strdef, + struse; + int olcount,/* usage count for left side */ + orcount;/* and right side */ +}; +typedef struct optb OPTB; + +# ifndef NOPTB +# define NOPTB 500 +# endif + +OPTB optb[NOPTB]; + +# ifndef NSTRING +# define NSTRING 15000 +# endif + +# ifndef NSTYSHPS +# define NSTYSHPS 1500 +# endif + +typedef struct { + int sop, + sleft, + sright, + ssh, + scost, + scnt; + char shname[8]; +} STYSHP; + +static int nshp = 0; +static int nmshp = NSTYSHPS - 1; +static STYSHP shp[NSTYSHPS]; +static char strng[NSTRING]; +static char *string; +static char *pstring = strng; +static char *asstring; + +%} + +%union { + int ival; + char *str; + SHTY shh; +}; + +%token STR DEF LPRF RPRF LSHR RSHR GOODCC NOVAL PNEED NHIGHT NLOW QNEED LRES RRES NALL LCOUNT RCOUNT THALF TKLET TXLET +%token USERCOST CONVAL NCONVAL POSRANGE SGRANGE NONAME DCOST SHAPES OPCODES +%token OP NM DIG STYPE RREG +%left OP +%left STYPE + +%type STR +%type opcost num slist nterm opop shape +%type costnexp nexp +%type cost cexpr cterm +%type sref + + /* + OP the ops <, <<, >, >>, <=, >=, +, -, *, /, %, &, ^, ~, ! + NM names (letter, followed by 0 or more letters or digits + STR a string in "" + DIG a digit, 0-9 + Other letters are returned: (, ), {, }, etc. + */ + +%% + +file : SHAPES lshapes OPCODES lops + { finished(); } + ; + +lshapes : /* EMPTY */ + | lshapes NM ':' slist ',' costnexp ';' + { shp[$2].sop = MANY; + shp[$2].sleft = $4; + shp[$2].sright = $6; + shp[$2].scost = 0; + shp[$2].ssh = 0; + } + | lshapes NM ':' costnexp ';' + { + shp[$2].sop = MANY; + shp[$2].sleft = $4; + shp[$2].sright = -1; + shp[$2].scost = 0; + shp[$2].ssh = 0; + } + | lshapes NM ':' opop shape opcost ';' + { shp[nshp].scost = $6; + shp[nshp].ssh = $5; + shp[nshp].sop = $4; + shp[nshp].sleft = -1; + shp[nshp].sright = -1; + ++nshp; + checkit( nshp-1 ); + shp[$2].sop = MANY; + shp[$2].sleft = nshp-1; + shp[$2].sright = -1; + shp[$2].scost = 0; + shp[$2].ssh = 0; + if( nshp >= nmshp ) { + yyerror( "out of node space" ); + exit( 1 ); + } + } + ; + +opop : /* EMPTY */ + { $$ = ICON; } + | OP + ; + +lops : /* EMPTY */ + { needs = op = rewrite = cost = 0; + pcount = qcount = 0; + lcount = rcount = 1; + } + + | lops lop + ; + +lop : OP sref ',' sref ltail + { lshty = $2; + rshty = $4; + op = $1; + tyop = TANY; + output(); + tyop = needs = op = rewrite = cost = 0; + pcount = qcount = 0; + lcount = rcount = 1; + } + | OP STYPE sref ',' sref ltail + { lshty = $3; + rshty = $5; + op = $1; + tyop = $2; + output(); + tyop = pcount = qcount = needs = op = rewrite = cost = 0; + lcount = rcount = 1; + } + | OP sref ltail + { lshty = $2; + rshty.sha = -1; + rshty.ty = TANY; + op = $1; + tyop = TANY; + output(); + tyop = pcount = qcount = needs = op = rewrite = cost = 0; + lcount = rcount = 1; + } + | OP STYPE sref ltail + { lshty = $3; + rshty.sha = -1; + rshty.ty = $2; + op = $1; + tyop = TANY; + output(); + tyop = pcount = qcount = needs = op = rewrite = cost = 0; + lcount = rcount = 1; + } + | sref ltail + { rshty = $1; + lshty.sha = -1; + lshty.ty = TANY; + loutput(); + tyop = pcount = qcount = needs = op = rewrite = cost = 0; + lcount = rcount = 1; + } + | DCOST {dcost=0;} opcost ';' + { dcost = $3; } + ; + +ltail : needs STR opcost ';' + { + cost = $3; + asstring = $2; + } + ; + +needs : /* EMPTY */ + { needs = pcount = qcount = 0;} + | '{' nlist '}' + ; + +nlist : /* EMPTY */ + { needs = pcount = qcount = 0;} + | nlist DIG + { needs = (needs&~NCOUNT) | $2; } + | nlist RPRF + { needs |= RSHARE|RPREF; } + | nlist LPRF + { needs |= LSHARE|LPREF; } + | nlist RSHR + { needs |= RSHARE; } + | nlist LSHR + { needs |= LSHARE; } + | nlist PNEED + { + pcount++; needs = (needs & ~PCOUNT)|(pcount << 4); } + | nlist QNEED + { qcount++; needs = (needs & ~QCOUNT)|(qcount << 8); } + | nlist THALF + { rewrite |= NHALF; } + | nlist TKLET + { rewrite |= RKLET; } + | nlist TXLET + { rewrite |= RXLET; } + | nlist NHIGHT + { rewrite |= RHIGHT; } + | nlist NLOW + { rewrite |= RLOW; } + | nlist GOODCC + { rewrite |= RESCC; } + | nlist NOVAL + { rewrite = RNULL; } + | nlist LRES + { rewrite |= RLEFT; } + | nlist NALL + { needs = + ( needs & ~NCOUNT )|( NRGS - 2 * pcount - 4 * qcount); + if ( ! qcount ) needs -= 2; + } + | nlist RRES + { rewrite |= RRIGHT; } + | nlist RREG + { if( !(needs&NCOUNT) && !pcount && !qcount ) needs |= $2; + switch($2) { + case 1: rewrite |= RESC1;break; + case 2: rewrite |= RESC2;break; + case 3: rewrite |= RESC3;break; + default: rewrite |= RESC4; + } + } + | nlist LCOUNT + { lcount += 1; } + | nlist RCOUNT + { rcount += 1; } + ; + +num : DIG + | num DIG + { $$ = 10*$1 + $2; } + ; + +opcost : cost + | /* EMPTY */ + { $$ = dcost; } + ; + +cost : ':' cexpr + { $$ = $2; } + ; + +cexpr : cterm + | OP cterm + { $$ = uopcost( $1, $2 ); } + | cterm OP cterm + { $$ = bopcost( $2, $1, $3 ); } + ; + +cterm : '(' cexpr ')' + { $$ = $2; } + | num + ; + +shape : /* EMPTY */ + { $$ = 0; } + | NONAME + { $$ = NACON; /* constant with no name */ } + | USERCOST num + { $$ = $2|SUSER; /* user's cost ftn */ } + | CONVAL num + { $$ = $2|SVAL; /* positive constant value */ } + | NCONVAL num + { $$ = $2|SNVAL; /* negative constant value */ } + | POSRANGE num + { $$ = $2|SRANGE0; /* positive range */ } + | SGRANGE num + { $$ = $2|SSRANGE; /* signed range */ } + ; + +sref : nterm + { $$.ty = 0; + $$.sha = $1; + } + | nterm STYPE /* do this before doing in nterm */ + { $$.sha = $1; + $$.ty = $2; } + ; + +slist : costnexp + | slist ',' costnexp + { $$ = bop( MANY, $1, $3, 0 ); } + ; + +costnexp: nexp opcost + { $$ = sharecost($1, $2); } + ; + +nexp : nterm + | OP nterm + { $$ = uop( $1, $2 ); } + | nterm OP nterm + { $$ = bop( $2, $1, $3, 0 ); } + ; + +nterm : '(' nexp ')' + { $$ = $2; } + | NM + | nterm STYPE + { $$ = top( $1, $2 ); } + ; + +%% +int lineno = 1; /* line number of stin file */ +static char filename[100] = ""; + +main(argc, argv) +int argc; +char **argv; +{ + register int i; + for( i=0; i=nshp && n<=nmshp || n>=NSTYSHPS ) { + yyerror( "out of range shape: %d", n ); + } + p = &shp[n]; + if( p->sop < 0 || p->sop > MANY ) { + fprintf(stderr,"n = %d vorher op = %d\n",n,shp[n-1].sop); + yyerror( "out of range op: %d", p->sop ); + } + + switch( optype(p->sop) ) { + + case BITYPE: + if( p->sright < 0 && p->sop != MANY ) { + yyerror( "right side empty" ); + } + checkit( p->sright ); + case UTYPE: + if( p->sleft < 0 ) { + yyerror( "left side empty" ); + } + checkit( p->sleft ); + } +} + + /* VARARGS */ +yyerror( s, a ) +char *s; +{ + fprintf( stderr, s, a ); + fprintf( stderr, ", file \"%s\", line %d\n", filename, lineno ); +/* abort(); +*/ + exit( 1 ); +} + + +static int otb[20]; /* ops that are part of the shape */ +static int notb; /* number of otb entries */ + +loutput() +{ + /* + * rhs has a leaf: output templates for all interesting + * operators in this leaf. + * An interesting operator is one that is NOT MANY. + * This allows us to access the table for each operator + * that this leaf may implement. + */ + register int i; + register int s; + register int ocost = cost; + + notb = 0; + lout1( s = rshty.sha ); + if( !notb ) yyerror( "lout1() error" ); + for( i = notb-1; i >= 0; --i ) + { + op = otb[i]; + tyop = TANY; + if( optype(op) == LTYPE ) { + lcount = 0; + cost = ocost + (rcount * refine(s)); + } + else if( optype(op) == BITYPE ) { + yyerror( "binary op in shape not done right" ); + } + else { /* op is unary */ + lcount = rcount; + rcount = 0; + cost = ocost + (lcount * urefine(s)); + } + output(); + } +} + +urefine( s ) { /* construct an entry for a unary op matching shape s */ + /* for now, punt on the costs */ + rcount = lcount; + lcount = 0; + return( refine( s ) ); +} + +smat(s) +register s; +{ + /* + * return 1 if we can find the op anyplace in the + * shape tree `s' + */ + if( s < 0 ) + return( 0 ); + if( shp[s].sop == MANY ) + { + if( shp[s].sleft>=0 && smat( shp[s].sleft ) ) return( 1 ); + if( shp[s].sright>=0 && smat( shp[s].sright ) ) return( 1 ); + return( 0 ); + } + return( shp[s].sop == op ); +} + +refine(s) +register s; +{ + /* + * find the largest subshape of `s' that contains + * the operator `op' (op is global). + * We descend MANY nodes until we run out, + * or until the operator `op' is found in both descendents. + * Since we are throwing away costs buried in the MANY nodes + * on the way down, we must keep track of those, to + * adjust the costs appropriately in the operator table. + */ + register int bc = 0; + + while( shp[s].sop == MANY ) + { + bc += shp[s].scost; + if( smat( shp[s].sleft ) ) + { + if( smat( shp[s].sright ) ) break; + else s = shp[s].sleft; + } + else s = shp[s].sright; + } + lshty.sha = -1; + rshty.sha = mkshp(s); + return( bc + shp[s].scost ); +} + +lout1( n ) +register n; +{ + register int i; + while( n >= 0 && shp[n].sop == MANY ) + { + lout1( shp[n].sleft ); + n = shp[n].sright; + } + if( n < 0 ) + return; + for( i=0; inmshp; --i ) { + if( shp[i].sright >= 0 ) continue; + if( shp[i].sleft == s ) goto foundit; + } + /* must make a MANY node */ + i = bop( MANY, s, -1, 0 ); + } + + /* now, make sure that i has a name, so it will be output */ + + foundit: ; + + if( !shp[i].shname[0] ) { + strcpy( shp[i].shname, "mkshp" ); + } + return(i); +} + +onebit(x) +register x; +{ + /* return 1 if x has at most 1 bit on, 0 otherwise */ + return( !(x&(x-1)) ); +} + +output() +{ + register OPTB *q; + register int j; + + if( lshty.ty == 0 ) lshty.ty = TANY; + if( rshty.ty == 0 ) rshty.ty = TANY; + + switch( op ) + { + + case 0: + yyerror( "0 op" ); + + case STAR: + case REG: + case UNARY MINUS: + case UNARY AND: + case FLD: + if( needs&(LSHARE|RSHARE) ) needs |= (LSHARE|RSHARE); + break; + + case ASSIGN: + case ASG PLUS: + case ASG MINUS: + case ASG MUL: + case ASG DIV: + case ASG MOD: + case ASG AND: + case ASG OR: + case ASG ER: + case ASG LS: + case ASG RS: + if( !(rewrite & (RNULL|RESC1|RESC2|RESC3|RESC4|RRIGHT)) ) + { + rewrite |= RLEFT; + } + } + if( !rewrite ) rewrite = RNULL; + + if( !onebit( rewrite & (RNULL|RLEFT|RRIGHT|RESC1|RESC2|RESC3|RESC4) ) ) + { + yyerror( "multiple results -- illegal (%o)", rewrite ); + } + if( ((rewrite&RLEFT)&&(needs&LSHARE)) || + ((rewrite&RRIGHT)&&(needs&RSHARE)) ) + { + if( asstring[0] != 'Y' ) + yyerror( "don't share on result side of tree" ); + } + if( needs && (needs&(LSHARE|RSHARE)) == needs ) + { + yyerror( "don't share without allocating something" ); + } + checkout(asstring); + + q = &optb[opno]; + if( opno >= NOPTB ) yyerror( "too many templates" ); + q->line = lineno; + q->op = op; + q->tyop = tyop; + if( ophd[op]>=0 ) + { + optb[optl[op]].nxop = opno; + optl[op] = opno; + } + else + { + optl[op] = ophd[op] = opno; + } + q->nxop = -1; + q->l = lshty; + q->r = rshty; + q->oneeds = needs; + q->orew = rewrite; + q->ocost = cost; + q->string = asstring; + q->olcount = lcount; +/* + q->orcount = rcount; +*/ + /* now, take care of special cases */ + if( optype(op) == LTYPE ) { /* leaf */ + int s; + if( (s=q->r.sha) >= 0 && trivial(s) ) { + q->r.sha = -1; /* clobber any right shape */ + } + } + else if( optype(op) == UTYPE ) { + if( q->r.sha >=0 ) { + /* someday, look for things below op */ + /* for now, we get the cost wrong so back up */ + } + } + ++opno; +} + +trivial( s ) { + /* is shape s a trivial match for op */ + if( shp[s].sop == MANY ) { + if( shp[s].sright >= 0 ) { + return( 0 ); /* nontrivial */ + } + s = shp[s].sleft; + } + if( shp[s].sop != op ) { + return( 0 ); + } + if( shp[s].ssh ) { + return( 0 ); + } + return( 1 ); /* ok to clobber */ +} + +checkout(string) +char *string; +{ + /* check out the string, looking at rewrite and needs */ + /* look for {U,I,C,A}{L,R,1,2,3} and \n */ + /* complain about: + *** 1, 2, 3 used, not allocated + *** shared side after \n after temp used + *** AL or AR used, w. side effect possible, more than once + */ + + /* flagl and flagr are 1 if L and R legal, 0 if not, -1 if + /* they will be illegal after the next \n */ + + register int flagl, flagr, prn, min, cond; + register char *s; + + flagl = flagr = 1; + cond = 0; + + for( s=string; *s; ++s ) + { + switch( *s ) + { + + case '\\': + ++s; + if( *s == '\\' ) ++s; + else if( *s == 'n' ) + { + if( flagl<0 ) flagl=0; + if( flagr<0 ) flagr=0; + } + break; + + case 'Z': + ++s; + if( *s=='(' ) + { + while( *++s != ')' ) {;} + } + break; + + case 'Y': + /* this string is asserted to be good; don't check */ + return; + + case 'R': + case 'D': + /* conditional; a lot of stuff no longer is true */ + cond = 1; + break; + + case 'A': + case 'C': + case 'U': + case 'I': + case 'P': + ++s; + if( *s == '-' ) + { + ++s; + min = 1; + } + else min = 0; + if( *s == '(' ) + { + ++s; + prn = 1; + } + else prn = 0; + switch( *s ) + { + + case 'L': + if( !flagl && !cond && !(NHALF & rewrite) ) + { + yyerror( " illegal L just at \"%x\"", + s ); + } + /* look for side-effects here */ + if( !min && seff(lshty.sha)) flagl = 0; + break; + + case 'R': + if( !flagr && !cond ) + { + yyerror( "illegal R just at \"%s\"", + s ); + } + /* look for side-effects here */ + if( !min && seff(rshty.sha)) flagr = 0; + break; + + case '1': + case '2': + case '3': + case '4': + if( (*s - '0') > + ( + (needs & NCOUNT) + + ((needs & QCOUNT) >> 8 ) + + ((needs & PCOUNT) >> 4 ) + ) + ) + { + yyerror( "reg %c used, not allocated", + *s ); + } + if( (needs&LSHARE) && flagl ) flagl = -1; + if( (needs&RSHARE) && flagr ) flagr = -1; + if( (needs&RPREF) && flagr ) flagr = -1; + if( (needs&LPREF) && flagr ) flagl = -1; + + case '.': + case 'W': + case 'B': + case 'J': + break; + + default: + yyerror( "illegal qualifier %c just at \"%s\"", + *(s - 1), s ); + } + if( prn ) while( *s != ')' ) ++s; + } + } +} + +seff( s ) +register s; +{ + if( shp[s].sop == INCR || shp[s].sop == DECR ) return( 1 ); + if( shp[s].sleft >= 0 && seff( shp[s].sleft ) ) return( 1 ); + if( shp[s].sright >= 0 && seff( shp[s].sright ) ) return( 1 ); + return( 0 ); +} + +uop( o, a ) +register o,a; +{ + if( o == MUL ) o = STAR; + else if( o == MINUS ) o = UNARY MINUS; + else if( o == AND ) o = UNARY AND; + return( bop( o, a, -1, 0 ) ); +} + +top( a, ty ) +register a,ty; +{ + /* build a type node over a */ + /* must be done differently than uop, since types must be copied */ + register STYSHP *p; + + if( a < 0 ) + return( a ); + checkit( a ); + if( shp[a].sop == MANY ) + { + register l, r; + l = shp[a].sleft; + r = shp[a].sright; + if( l >= 0 ) + l = top( l, ty ); + if( r >= 0 ) + r = top( r, ty ); + return( bop( MANY, l, r, 0 ) ); + } + if( shp[a].ssh ) + { + yyerror( "can't type a special node" ); + } + shp[nshp] = shp[a]; + shp[nshp].shname[0] = '\0'; + shp[nshp].ssh = ty|SPTYPE; + nshp++; + checkit( nshp-1 ); + return( nshp-1 ); +} + +bop( o, a, b, cst ) +register o, a, b, cst; +{ + register STYSHP *p; + register int l, r, ret; + + checkit( a ); + checkit( b ); + + if( o != MANY ) + { + while( shp[a].sop == MANY && shp[a].sright < 0 ) { + a = shp[a].sleft; + } + while( shp[b].sop == MANY && shp[b].sright < 0 ) { + b = shp[b].sleft; + } + if( a>=0 && shp[a].sop == MANY ) + { + /* distribute MANY nodes to top */ + l = bop( o, shp[a].sleft, b, cst + shp[a].scost ); + r = bop( o, shp[a].sright, b, cst + shp[a].scost ); + return( bop( MANY, l, r, 0 ) ); + } + if( b>=0 && shp[b].sop == MANY ) + { + /* distribute MANY nodes to top */ + l = bop( o, a, shp[b].sleft, cst + shp[b].scost ); + r = bop( o, a, shp[b].sright, cst + shp[b].scost ); + return( bop( MANY, l, r, 0 ) ); + } + } + + if( o == MANY ) + /* MANY nodes go at the end */ + p = &shp[ ret = nmshp-- ]; + else + p = &shp[ ret = nshp++ ]; + if( nshp >= nmshp ) { + yyerror( "out of node space" ); + exit( 1 ); + } + + p->sop = o; + p->sleft = a; + p->sright =b; + p->scost = cst; + p->ssh = 0; + p->shname[0] = '\0'; + checkit( ret ); + return( ret ); +} + +int olist[] = { PLUS, MINUS, MUL, DIV, MOD, LS, RS, OR, ER, AND, -1 }; + +struct nam +{ + char *tntn; + int tnty; +}; +#define NameV(x) "x", x /* name-value pairs */ +struct nam Tnam[] = { + NameV(TANY), + NameV(TCHAR), + NameV(TSHORT), + NameV(TINT), + NameV(TLONG), + NameV(TFLOAT), + NameV(TDOUBLE), + NameV(TUCHAR), + NameV(TUSHORT), + NameV(TUNSIGNED), + NameV(TULONG), + NameV(TSTRUCT), + NameV(TPOINT), + NameV(TPOINT2), + NameV(TVOID), + NameV(urTINT), + NameV(urTUNSIGNED), + 0, 0, +}; +struct nam Rwnam[] = { + NameV(RLEFT), + NameV(RRIGHT), + NameV(RESC1), + NameV(RESC2), + NameV(RESC3), + NameV(RESC4), + NameV(RESCC), + NameV(RNOP), + NameV(RNULL), + NameV(RHIGHT), + NameV(RLOW), + NameV(NHALF), + NameV(RKLET), + NameV(RXLET), + 0, 0 +}; +struct nam Ndnam[] = { + NameV(LSHARE), + NameV(RSHARE), + NameV(LPREF), + NameV(RPREF), + 0, 0, +}; +finished() +{ + register STYSHP *p; + register OPTB *q, *q1; + register int i, j; + + /* terminate the templates */ + printf( "# include \"mfile2.h\"\n\n" ); + printf("#ifndef NHALF\n#define NHALF 0x800\n#endif\n"); + printf("#ifndef RKLET\n#define RKLET 0x1000\n#endif\n"); + printf("#ifndef RXLET\n#define RXLET 0x2000\n#endif\n"); + + + /* chain binary ops together with the op= form */ + for( i=0; (op=olist[i])>=0; ++i ) + { + if( ophd[op]<0 ) + ophd[op] = ophd[ASG op]; + else + optb[optl[op]].nxop = ophd[ASG op]; + } + if( ophd[STCALL]<0 ) + ophd[STCALL] = ophd[CALL]; + if( ophd[UNARY STCALL]<0 ) + ophd[UNARY STCALL] = ophd[UNARY CALL]; + + optbck(); + + /* everything that gets used should be a MANY shape with name */ + /* mkshp is called to cause this to be true */ + + for( i=0; il.sha = mkshp(q->l.sha); + q->r.sha = mkshp(q->r.sha); + } + + /* avoid identical strings in optb[] by finding identical strings, + giving them names and putting them at the front of table.c */ + for( i=0; istruse = 1; + q->strdef = -1; + for(j = 0; j < i; j++) + { + q1 = &optb[j]; + if(!q1->struse) + continue; + if(strcmp(q->string,q1->string)==0) + { + q->strdef = j; + q1->struse++; + q->struse = 0; + break; + } + } + } + for(i=0; istruse>1) + { + printf("static char Str%d[] = \"%s\";\n", i, q->string); + q->struse = 0; + q->strdef = i; + } + } + + /* set the ssh flags in shp, but don't print yet */ + + for( j=0,i=NSTYSHPS-1; i>nmshp; --i ) { + if( !shp[i].shname[0] ) continue; + shp[i].ssh = j; + j += manycount( i ); + ++j; /* count the null */ + } + + printf( "\n# define SHNL ((SHAPE *)0)\n" ); + printf( "# define S(x) (&shapes[x])\n" ); + + printf( "\nSHAPE shapes[] = {\n" ); + for( i=0, p=shp; isop<0 ) + yyerror( "undefined shape: %.8s", p->shname ); + printf( "/*%4d */ ", i); + printf( "%4d,\t",p->sop ); + saaddr(p->sleft); + saaddr(p->sright); + printf( "%#o,\t%d,", p->ssh, p->scost ); + if( p->shname[0] ) + printf( "\t/* %.8s */\n", p->shname ); + else + putchar( '\n' ); + if(p->shname[0]) + chkdups(i); + } + printf( "\n};\n" ); + + printf( "\n# define PSHNL ((SHAPE **)0)\n" ); + printf( "# define P(x) (&pshape[x])\n" ); + + printf( "\nSHAPE *pshape[] = {\n" ); + for( j = 0, i = NSTYSHPS-1; i > nmshp; --i ) { + if( !shp[i].shname[0] ) + continue; + if( shp[i].ssh != j ) { + fprintf( stderr, "shape %d, ssh=%d, j=%d\n", + i, shp[i].ssh, j ); + } + printf( "/*%4d %.8s */\t", j, shp[i].shname ); + j = manylist( i, j ); + printf( "SHNL,\n"); + ++j; + } + printf( "};\n" ); + + printf( "struct optab table[] = {\n\n" ); + for( i=0; iline ); + prop( q->op ); + prnam( q->tyop, Tnam ); + if( q->nxop >= 0 ) + printf( "\t&table[%d],\n", q->nxop ); + else + printf( "\t0,\n" ); + + shpprint(q->l.sha, q->l.ty); + shpprint(q->r.sha, q->r.ty); + printf("\t\t"); + /* printf(" === q->oneeds === 0x%x\n", q->oneeds ); */ + prnam(q->oneeds, Ndnam); + printf("\t\t"); + prnam(q->orew, Rwnam); + if(q->strdef>=0) + printf("\t\tStr%d,\n", q->strdef); + else + printf("\t\t\"%s\",\n", q->string); +/* + printf("\t\t%d,%d,%d,%d,\n", q->ocost, q->olcount, q->orcount, +*/ + printf("\t\t%d,%d,%d,\n", q->ocost, q->olcount, + q->line ); + } + printf( "\n};\n" ); + + printf( "OPTAB *ophead[] = {\n" ); + + for( i=0; i= 0 ) c += manycount( shp[i].sleft ); + if( shp[i].sright >= 0 ) c += manycount( shp[i].sright ); + return( c ); + } + return( 1 ); +} + +manylist( i, j ) { + /* put out a list of S(x) for shp[i], starting at j */ + /* first, put out CCODES and FREE */ + /* next, put out REG and TEMP */ + /* next, everything else */ + int k; + int outcount = 0; + + if( i<0 ) return(j); + + setopsh( i ); /* set opsh[k] if op k is legal at head of i */ + if( opsh[FREE] ) { + j = manyop( i, j, FREE, &outcount ); + opsh[FREE] = 0; + } + if( opsh[CCODES] ) { + j = manyop( i, j, CCODES, &outcount ); + opsh[CCODES] = 0; + } + if( opsh[REG] ) { + j = manyop( i, j, REG, &outcount ); + opsh[REG] = 0; + } + if( opsh[TEMP] ) { + j = manyop( i, j, TEMP, &outcount ); + opsh[TEMP] = 0; + } + for( k=0; ksleft >= 0) && (p->sop==MANY)) chkdup1(p->sleft); + if((p->sright >= 0) && (p->sop==MANY)) chkdup1(p->sright); + p->scnt++; + nodcnt++; + treecnt += p->scnt; +} +clrcnt(nn) +register nn; +{ + register STYSHP *p; + + p = &shp[nn]; + if(p->sleft >= 0) clrcnt(p->sleft); + if(p->sright >= 0) clrcnt(p->sright); + p->scnt = 0; +} + +prtree(str,ii) +register ii; +char *str; +{ + register STYSHP *p; + p = &shp[ii]; + fprintf(stderr,"%s.%d = %d",str,ii,p->scnt); + if(p->shname[0]) fprintf(stderr," /* %s */",p->shname); + fprintf(stderr,"\n"); + if(p->sright>=0) prtree("R",p->sright); + if(p->sleft>=0) prtree("L",p->sleft); +} +shpprint(sha, ty) +register sha,ty; +{ + if( sha < 0 ) printf( "\tPSHNL,\t"); + else printf( "\tP(%d),\t", shp[sha].ssh ); + prnam( ty, Tnam ); +} + +prnam(tyo,src) +register struct nam *src; +register unsigned int tyo; +{ + unsigned long ty = tyo; + long jj; + register ii; + register flag = 0; + register struct nam *tn; + + if(!ty) + { + printf("0x0,\n"); + return; + } + for(tn = src; tn->tntn; tn++) + if( tn->tnty == (int)ty ) + { + printf( "%s,\n", tn->tntn ); + return; + } + for(ii = 0; ii < 17 ; ii++) + { + if((jj = (01l << ii))>ty) + { + printf(",\n"); + return; + } + if(!(jj & ty)) + continue; + for(tn = src; tn->tntn; tn++) + if(tn->tnty==(int)jj) + break; + if(flag++) + printf("|"); + if(tn->tntn) + printf("%s",tn->tntn); + else + printf("0x%x",(unsigned short)jj); + } +} + +static char name[100]; /* had better be long enough */ + +yylex() +{ + register int c, i; + + for(;;) + { + + c = getchar(); + if( c<0 ) return( -1 ); + switch( c ) + { + + case '\n': + ++lineno; + case ' ': + case '\b': + case '\f': + case '\v': + case '\t': + continue; + + case '<': + case '>': + case '+': + case '-': + case '=': + case '*': + case '%': + case '/': + case '&': + case '|': + case '^': + case '!': + name[0] = c; + name[1] = getchar(); + name[2] = '\0'; + if( oplook() ) + { + if( yylval.ival == LS || yylval.ival == RS ) + { + if( (c=getchar()) == '=' ) + yylval.ival = ASG yylval.ival; + else ungetc( c, stdin ); + } + return( OP ); + } + ungetc( name[1], stdin ); + name[1] = '\0'; + if( oplook() ) return( OP ); + yyerror( "cannot deal with %c", name[0] ); + return( OP ); + + case '~': + yylval.ival = COMPL; + return( OP ); + + case '"': + string = pstring; + while( pstring < &strng[NSTRING-2] ) + { + switch( c = getchar() ) { + case '\t': + *pstring++ = '\\'; + *pstring++ = 't'; + break; + case '\n': + *pstring++ = '\\'; + *pstring++ = 'n'; + ++lineno; + break; + case '\\': /* escape */ + *pstring++ = '\\'; + c = getchar(); + if( c == '\n' ) + ++lineno; + else if( c<0 ) + yyerror( "missing \"" ); + else if( isalpha(c) && isupper(c) ) + *pstring++ = '\\'; + *pstring++ = c; + break; + case '"': + *pstring++ = '\0'; + goto eos; + default: + if( c<0 ) + yyerror( "missing \"" ); + *pstring++ = c; + } + } + eos: + if( pstring >= &strng[NSTRING] ) + yyerror( "s_table overflow" ); + yylval.str = string; + return( STR ); + + case '\'': + for( i = 0; i < sizeof name - 1; ++i ) + { + c = getchar(); + if( c == '\'' ) break; + if( c == '\n' ) yyerror( "missing '" ); + name[i] = c; + } + name[i] = '\0'; + if( oplook() ) return( OP ); + yyerror( "bad op name: '%s'", name ); + + case '[': + for( i = 0; i < sizeof name - 1; ++i ) + { + c = getchar(); + if( c == ']' ) break; + if( c == '\n' ) yyerror( "missing ]" ); + name[i] = c; + } + name[i] = '\0'; + yylval.ival = tystr(name); + return( STYPE ); + + case '#': /* comment */ + while( (c = getchar()) != '\n' ) + { + if( c < 0 ) yyerror( "unexpected EOF" ); + } + ++lineno; + continue; + + case '$': + c = getchar(); + if( isdigit(c) ) + { + yylval.ival = c-'0'; + return( RREG ); + } + switch( c ) + { + case '[': return( LPRF ); + case ']': return( RPRF ); + case '<': return( LSHR ); + case '>': return( RSHR ); + case 'L': return( LRES ); + case 'R': return( RRES ); + case 'P': return( PNEED ); + case 'Q': return( QNEED ); + case 'O': return( NHIGHT ); + case 'U': return( NLOW ); + case 'C': return( GOODCC ); + case 'N': return( NOVAL ); + case 'H': return( THALF ); + case 'K': return( TKLET ); + case 'X': return( TXLET ); + case 'r': return( RCOUNT ); + case 'l': return( LCOUNT ); + case 'A': return( NALL ); + } + yyerror( "$%c illegal", c ); + + default: + if( isdigit(c) ) + { + yylval.ival = c-'0'; + return( DIG ); + } + if( isalpha(c) ) + { + /* collect the name */ + int i = 1; + name[0] = c; + while( isalpha( (c=getchar()) ) || isdigit(c) ) + { + name[i++] = c; + } + name[i] = '\0'; + ungetc( c, stdin ); + return( lookup() ); + } + return( c ); + } + } +} + +struct nlist { + char *shop; + int vop; +} ot[] = { + + "++", INCR, + "+", PLUS, + "--", DECR, + "-", MINUS, + "*", MUL, + "%", MOD, + "/", DIV, + "&", AND, + "^", ER, + "!=", NE, + "==", EQ, + "UMINUS", UNARY MINUS, + "UAND", UNARY AND, + "STAR", STAR, + "+=", ASG PLUS, + "-=", ASG MINUS, + "*=", ASG MUL, + "/=", ASG DIV, + "%=", ASG MOD, + "&=", ASG AND, + "|=", ASG OR, + "|", OR, + "^=", ASG ER, + "=", ASSIGN, + "<", LT, + "<=", LE, + "<<", LS, + ">", GT, + ">=", GE, + ">>", RS, + "FLD", FLD, + "CMP", CMP, + "COMOP", COMOP, + "CM", CM, + "GENLAB", GENLAB, + "GENUBR", GENUBR, + "GENBR", GENBR, + "ARG", FUNARG, + "STARG", STARG, + "STASG", STASG, + "INIT", INIT, + "GOTO", GOTO, + "CALL", CALL, + "UCALL", UNARY CALL, + "STCALL", STCALL, + "USTCALL", UNARY STCALL, + "CONV", CONV, + "PDIV", PDIV, + "PMUL", PMUL, + "REG", REG, + "CON", ICON, + "TEMP", TEMP, + "AUTO", VAUTO, + "PARAM", VPARAM, + "NAME", NAME, + "RNODE", RNODE, + "SNODE", SNODE, + "QNODE", QNODE, + "CC", CCODES, + "FREE", FREE, + "UOP0", UOP0, + "UOP1", UOP1, + "UOP2", UOP2, + "UOP3", UOP3, + "UOP4", UOP4, + "UOP5", UOP5, + "UOP6", UOP6, + "UOP7", UOP7, + "UOP8", UOP8, + "UOP9", UOP9, + "", -1 }; + +oplook() +{ + /* look up the first n chars of name in the above table */ + /* return 1 if it is an op, after setting yylval */ + register int i; + for( i=0; ot[i].vop >= 0; ++i ) + { + if( !strcmp( name, ot[i].shop ) ) + { + yylval.ival = ot[i].vop; + return( 1 ); + } + } + return( 0 ); +} + +tystr( p ) +register char *p; /* pointer to name */ +{ + register i; + + /* lookup the types in name */ + if( !*p ) + return( TANY ); + else + i = 0; + for(;;) + { + switch( *p++ ) + { + case '\0': + return( i ); + + case 'c': + i |= TCHAR; + case ' ': + case ',': + continue; + + case 's': + i |= TSHORT; + continue; + + case 'i': + i |= TINT; + continue; + + case 'l': + i |= TLONG; + continue; + + case 'f': + i |= TFLOAT; + continue; + + case 'd': + i |= TDOUBLE; + continue; + + case 'P': + i |= TPOINT2; + continue; + + case 'p': + i |= TPOINT; + continue; + + case 't': + i |= TSTRUCT; + continue; + + case 'v': + /* later.. + i |= TVOID; + */ + continue; + + case 'u': + switch( *p ) + { + case 'i': i |= TUNSIGNED; break; + case 's': i |= TUSHORT; break; + case 'c': i |= TUCHAR; break; + case 'l': i |= TULONG; break; + default: yyerror( "bad u%c type", *p ); + } + ++p; + continue; + + default: + yyerror( "illegal type: %c", p[-1] ); + } + } +} + +struct nlist resw[] = { + NameV(DCOST), + NameV(SHAPES), + NameV(OPCODES), + NameV(USERCOST), + NameV(CONVAL), + NameV(NCONVAL), + NameV(POSRANGE), + NameV(SGRANGE), + NameV(NONAME), + "", -1, +}; + +lookup() +{ + /* look up the shape name in name, and return the index */ + register STYSHP *p; + register int i; + for( i=0; resw[i].vop >= 0; ++i ) + { + if( !strcmp( name, resw[i].shop ) ) return( resw[i].vop ); + } + for( i=NSTYSHPS-1, p= &shp[NSTYSHPS-1]; i>nmshp; --i,--p ) + { + if( !strncmp( name, p->shname, 8 ) ) + { + /* match */ + yylval.ival = i; + return( NM ); + } + } + /* new entry */ +/* +fprintf(stderr,"neueintragen %s in %d op = %d\n",name,i,p->sop); +*/ + strncpy( p->shname, name, 8 ); + p->ssh = p->scost = 0; + p->sleft = p->sright = -1; + p->sop = -1; + yylval.ival = nmshp--; + if( nmshp <= nshp ) { + yyerror( "out of node space" ); + exit( 1 ); + } + return( NM ); +} + +sharecost ( sn, cst ) +register int sn,cst; +{ + if ( sn == nshp - 1 ) + { + shp[sn].scost = cst; + return(sn); + } + if ( cst == 0 ) + return( sn ); + + if (nshp >= NSTYSHPS) + yyerror("too many shapes"); + shp[nshp] = shp[sn]; + shp[nshp].scost += cst; + nshp++; + checkit( nshp-1 ); + return( nshp-1 ); +} + +uopcost (o, a) +register int o,a; +{ + switch(o) + { + default: + case MUL: + case AND: yyerror("Illegal unary cost operator"); + return(0); + case MINUS: + return(-a); + } +} + +bopcost (o, a, b) +register int o,a,b; +{ + switch(o) + { + case INCR: + case PLUS: return(a+b); + case DECR: + case MINUS: return(a-b); + case MUL: return(a*b); + case DIV: return(a/b); + case MOD: return(a%b); + case LS: return(a>>b); + case RS: return(a<b); + case LE: return(a<=b); + case GE: return(a>=b); + case NE: return(a!=b); + case EQ: return(a==b); + default: yyerror("Illegal binary operator"); + return(0); + } +} + +/* print operator name +*/ +static +prop( op ) +register int op; +{ + register struct nam *np; + static struct nam Opnam[] = { + NameV(INCR), + NameV(PLUS), + NameV(DECR), + NameV(MINUS), + NameV(MUL), + NameV(MOD), + NameV(DIV), + NameV(AND), + NameV(ER), + NameV(NE), + NameV(EQ), + NameV(UNARY MINUS), + NameV(UNARY AND), + NameV(STAR), + NameV(ASG PLUS), + NameV(ASG MINUS), + NameV(ASG MUL), + NameV(ASG DIV), + NameV(ASG MOD), + NameV(ASG AND), + NameV(ASG OR), + NameV(OR), + NameV(ASG ER), + NameV(ASSIGN), + NameV(LT), + NameV(LE), + NameV(LS), + NameV(GT), + NameV(GE), + NameV(RS), + NameV(FLD), + NameV(CMP), + NameV(COMOP), + NameV(CM), + NameV(GENLAB), + NameV(GENUBR), + NameV(GENBR), + NameV(FUNARG), + NameV(STARG), + NameV(STASG), + NameV(INIT), + NameV(GOTO), + NameV(CALL), + NameV(UNARY CALL), + NameV(STCALL), + NameV(UNARY STCALL), + NameV(CONV), + NameV(PDIV), + NameV(PMUL), + NameV(REG), + NameV(ICON), + NameV(TEMP), + NameV(VAUTO), + NameV(VPARAM), + NameV(NAME), + NameV(RNODE), + NameV(SNODE), + NameV(QNODE), + NameV(CCODES), + NameV(FREE), + 0, 0, + }; + for( np = Opnam; np->tnty; np++ ) + { + if( op == np->tnty ) + { + printf( "%s,", np->tntn ); + return; + } + } + printf( "%d,", op ); +} + + +/* + check the op table for duplicate or partially duplicate templates +*/ +static +optbck() +{ +#define EqOptb(a) (q->a == q1->a) + register int i; + register int j; + register OPTB *q; + register OPTB *q1; + + for( i = 0; i < opno; i++ ) + { + q = &optb[i]; + for( j = 0; j < i; j++ ) + { + q1 = &optb[j]; + if( + EqOptb(op) && + EqOptb(l.ty) && + EqOptb(r.ty) && + EqOptb(orew) && + EqOptb(oneeds) && + shapeshr(q->l.sha, q1->l.sha) && + shapeshr(q->r.sha, q1->r.sha) + ) + { + fprintf( stderr, + "line %d may be covered by line %d\n", + q->line, q1->line ); + break; + } + } + } +} + + +/* do the shape trees starting at s1 and s2 share any elements? +*/ +static +shapeshr( s1, s2 ) +register int s1; /* indexes into shape table */ +register int s2; +{ + register int i1; + + for( i1 = s1; shp[i1].sleft >= 0; i1 = shp[i1].sleft ) + { + if( i1 == s2 || shp[i1].sright == s2 ) + return 1; + } + return 0; +}