117747Sralph #ifndef lint
2*32828Sdonn static char *sccsid ="@(#)reader.c 4.8 (Berkeley) 12/10/87";
317747Sralph #endif lint
417747Sralph
518394Sralph # include "pass2.h"
617724Sralph
717724Sralph /* some storage declarations */
817724Sralph
917724Sralph # ifndef ONEPASS
1017724Sralph NODE node[TREESZ];
1117724Sralph char filename[100] = ""; /* the name of the file */
1217724Sralph int ftnno; /* number of current function */
1317724Sralph int lineno;
1417724Sralph # else
1517724Sralph # define NOMAIN
1617724Sralph #endif
1717724Sralph
1817724Sralph int nrecur;
1917724Sralph int lflag;
2017747Sralph #ifdef FORT
2117747Sralph int Oflag = 0;
2217747Sralph #endif
2317724Sralph extern int Wflag;
2417724Sralph int edebug = 0;
2517724Sralph int xdebug = 0;
2617724Sralph int udebug = 0;
2717724Sralph int vdebug = 0;
2817724Sralph
2917724Sralph OFFSZ tmpoff; /* offset for first temporary, in bits for current block */
3017724Sralph OFFSZ maxoff; /* maximum temporary offset over all blocks in current ftn, in bits */
3117724Sralph int maxtreg;
3217724Sralph
3317724Sralph NODE *stotree;
3417724Sralph int stocook;
3517724Sralph
3617724Sralph OFFSZ baseoff = 0;
3717724Sralph OFFSZ maxtemp = 0;
3817724Sralph
p2init(argc,argv)3917724Sralph p2init( argc, argv ) char *argv[];{
4017724Sralph /* set the values of the pass 2 arguments */
4117724Sralph
4217724Sralph register int c;
4317724Sralph register char *cp;
4417724Sralph register files;
4517724Sralph
4617724Sralph allo0(); /* free all regs */
4717724Sralph files = 0;
4817724Sralph
4917724Sralph for( c=1; c<argc; ++c ){
5017724Sralph if( *(cp=argv[c]) == '-' ){
5117724Sralph while( *++cp ){
5217724Sralph switch( *cp ){
5317724Sralph
5417724Sralph case 'X': /* pass1 flags */
5517724Sralph while( *++cp ) { /* VOID */ }
5617724Sralph --cp;
5717724Sralph break;
5817724Sralph
5917724Sralph case 'l': /* linenos */
6017724Sralph ++lflag;
6117724Sralph break;
6217724Sralph
6317724Sralph case 'e': /* expressions */
6417724Sralph ++edebug;
6517724Sralph break;
6617724Sralph
6717724Sralph case 'o': /* orders */
6817724Sralph ++odebug;
6917724Sralph break;
7017724Sralph
7117724Sralph case 'r': /* register allocation */
7217724Sralph ++rdebug;
7317724Sralph break;
7417724Sralph
7517724Sralph case 'a': /* rallo */
7617724Sralph ++radebug;
7717724Sralph break;
7817724Sralph
7917724Sralph case 'v':
8017724Sralph ++vdebug;
8117724Sralph break;
8217724Sralph
8317724Sralph case 't': /* ttype calls */
8417724Sralph ++tdebug;
8517724Sralph break;
8617724Sralph
8717724Sralph case 's': /* shapes */
8817724Sralph ++sdebug;
8917724Sralph break;
9017724Sralph
9117724Sralph case 'u': /* Sethi-Ullman testing (machine dependent) */
9217724Sralph ++udebug;
9317724Sralph break;
9417724Sralph
9517724Sralph case 'x': /* general machine-dependent debugging flag */
9617724Sralph ++xdebug;
9717724Sralph break;
9817724Sralph
9917724Sralph case 'w':
10017724Sralph case 'W': /* shut up warnings */
10117724Sralph
10217724Sralph ++Wflag;
10317724Sralph break;
10417724Sralph
10517747Sralph #ifdef FORT
10617747Sralph case 'O': /* optimizing */
10717747Sralph ++Oflag;
10817747Sralph break;
10917747Sralph #endif
11017747Sralph
11117724Sralph default:
11217724Sralph cerror( "bad option: %c", *cp );
11317724Sralph }
11417724Sralph }
11517724Sralph }
11617724Sralph else files = 1; /* assumed to be a filename */
11717724Sralph }
11817724Sralph
11917724Sralph mkdope();
12017724Sralph setrew();
12117724Sralph return( files );
12217724Sralph
12317724Sralph }
12417724Sralph
12517724Sralph # ifndef NOMAIN
12617724Sralph
12717724Sralph unsigned int caloff();
12817724Sralph unsigned int offsz;
mainp2(argc,argv)12917724Sralph mainp2( argc, argv ) char *argv[]; {
13017724Sralph register files;
13117724Sralph register temp;
13217724Sralph register c;
13317724Sralph register char *cp;
13417724Sralph register NODE *p;
13517724Sralph
13617724Sralph offsz = caloff();
13717724Sralph files = p2init( argc, argv );
13817724Sralph tinit();
13917724Sralph
14017724Sralph reread:
14117724Sralph
14217724Sralph if( files ){
14317724Sralph while( files < argc && argv[files][0] == '-' ) {
14417724Sralph ++files;
14517724Sralph }
14617724Sralph if( files > argc ) return( nerrors );
14717724Sralph freopen( argv[files], "r", stdin );
14817724Sralph }
14917724Sralph while( (c=getchar()) > 0 ) switch( c ){
15017724Sralph case ')':
15117724Sralph default:
15217724Sralph /* copy line unchanged */
15317724Sralph if ( c != ')' )
15417724Sralph PUTCHAR( c ); /* initial tab */
15517724Sralph while( (c=getchar()) > 0 ){
15617724Sralph PUTCHAR(c);
15717724Sralph if( c == '\n' ) break;
15817724Sralph }
15917724Sralph continue;
16017724Sralph
16117724Sralph case BBEG:
16217724Sralph /* beginning of a block */
16317724Sralph temp = rdin(10); /* ftnno */
16417724Sralph tmpoff = baseoff = (unsigned int) rdin(10); /* autooff for block gives max offset of autos in block */
16517724Sralph maxtreg = rdin(10);
16617724Sralph if( getchar() != '\n' ) cerror( "intermediate file format error");
16717724Sralph
16817724Sralph if( temp != ftnno ){ /* beginning of function */
16917724Sralph maxoff = baseoff;
17017724Sralph ftnno = temp;
17117724Sralph maxtemp = 0;
17217724Sralph }
17317724Sralph else {
17417724Sralph if( baseoff > maxoff ) maxoff = baseoff;
17517724Sralph /* maxoff at end of ftn is max of autos and temps
17617724Sralph over all blocks in the function */
17717724Sralph }
17817724Sralph setregs();
17917724Sralph continue;
18017724Sralph
18117724Sralph case BEND: /* end of block */
18217724Sralph SETOFF( maxoff, ALSTACK );
18317724Sralph eobl2();
18417724Sralph while( (c=getchar()) != '\n' ){
18517724Sralph if( c <= 0 ) cerror( "intermediate file format eof" );
18617724Sralph }
18717724Sralph continue;
18817724Sralph
18917724Sralph case EXPR:
19017724Sralph /* compile code for an expression */
19117724Sralph lineno = rdin( 10 );
19217724Sralph for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */
19317724Sralph *cp = '\0';
19417724Sralph if( lflag ) lineid( lineno, filename );
19517724Sralph
19617724Sralph tmpoff = baseoff; /* expression at top level reuses temps */
19717724Sralph p = eread();
19817724Sralph
19917724Sralph # ifndef BUG4
20017724Sralph if( edebug ) fwalk( p, eprint, 0 );
20117724Sralph # endif
20217724Sralph
20317724Sralph # ifdef MYREADER
20417724Sralph MYREADER(p); /* do your own laundering of the input */
20517724Sralph # endif
20617724Sralph
20717724Sralph nrecur = 0;
20817724Sralph delay( p ); /* expression statement throws out results */
20917724Sralph reclaim( p, RNULL, 0 );
21017724Sralph
21117724Sralph allchk();
21217724Sralph tcheck();
21317724Sralph continue;
21417724Sralph
21517724Sralph }
21617724Sralph
21717724Sralph /* EOF */
21817724Sralph if( files ) goto reread;
21917724Sralph return(nerrors);
22017724Sralph
22117724Sralph }
22217724Sralph
22317724Sralph # endif
22417724Sralph
22517724Sralph # ifdef ONEPASS
22617724Sralph
p2compile(p)22717724Sralph p2compile( p ) NODE *p; {
22817724Sralph
22917724Sralph if( lflag ) lineid( lineno, filename );
23017724Sralph tmpoff = baseoff; /* expression at top level reuses temps */
23117724Sralph /* generate code for the tree p */
23217724Sralph # ifndef BUG4
23317724Sralph if( edebug ) fwalk( p, eprint, 0 );
23417724Sralph # endif
23517724Sralph
23617724Sralph # ifdef MYREADER
23717724Sralph MYREADER(p); /* do your own laundering of the input */
23817724Sralph # endif
23917724Sralph nrecur = 0;
24017724Sralph delay( p ); /* do the code generation */
24117724Sralph reclaim( p, RNULL, 0 );
24217724Sralph allchk();
24317724Sralph /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
24417724Sralph /* first pass will do it... */
24517724Sralph }
24617724Sralph
p2bbeg(aoff,myreg)24717724Sralph p2bbeg( aoff, myreg ) {
24817724Sralph static int myftn = -1;
24917724Sralph
25017724Sralph tmpoff = baseoff = (unsigned int) aoff;
25117724Sralph maxtreg = myreg;
25217724Sralph if( myftn != ftnno ){ /* beginning of function */
25317724Sralph maxoff = baseoff;
25417724Sralph myftn = ftnno;
25517724Sralph maxtemp = 0;
25617724Sralph }
25717724Sralph else {
25817724Sralph if( baseoff > maxoff ) maxoff = baseoff;
25917724Sralph /* maxoff at end of ftn is max of autos and temps over all blocks */
26017724Sralph }
26117724Sralph setregs();
26217724Sralph }
26317724Sralph
p2bend()26417724Sralph p2bend(){
26517724Sralph SETOFF( maxoff, ALSTACK );
26617724Sralph eobl2();
26717724Sralph }
26817724Sralph
26917724Sralph # endif
27017724Sralph
27117724Sralph NODE *deltrees[DELAYS];
27217724Sralph int deli;
27317724Sralph
delay(p)27417724Sralph delay( p ) register NODE *p; {
27517724Sralph /* look in all legal places for COMOP's and ++ and -- ops to delay */
27617724Sralph /* note; don't delay ++ and -- within calls or things like
27717724Sralph /* getchar (in their macro forms) will start behaving strangely */
27817724Sralph register i;
27917724Sralph
28017724Sralph /* look for visible COMOPS, and rewrite repeatedly */
28117724Sralph
28217724Sralph while( delay1( p ) ) { /* VOID */ }
28317724Sralph
28417724Sralph /* look for visible, delayable ++ and -- */
28517724Sralph
28617724Sralph deli = 0;
28717724Sralph delay2( p );
28817724Sralph codgen( p, FOREFF ); /* do what is left */
28917724Sralph for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF ); /* do the rest */
29017724Sralph }
29117724Sralph
delay1(p)29217724Sralph delay1( p ) register NODE *p; { /* look for COMOPS */
29317724Sralph register o, ty;
29417724Sralph
29517724Sralph o = p->in.op;
29617724Sralph ty = optype( o );
29717724Sralph if( ty == LTYPE ) return( 0 );
29817724Sralph else if( ty == UTYPE ) return( delay1( p->in.left ) );
29917724Sralph
30017724Sralph switch( o ){
30117724Sralph
30217724Sralph case QUEST:
30317724Sralph case ANDAND:
30417724Sralph case OROR:
30517724Sralph /* don't look on RHS */
30617724Sralph return( delay1(p->in.left ) );
30717724Sralph
30817724Sralph case COMOP: /* the meat of the routine */
30917724Sralph delay( p->in.left ); /* completely evaluate the LHS */
31017724Sralph /* rewrite the COMOP */
31117724Sralph { register NODE *q;
31217724Sralph q = p->in.right;
31317724Sralph ncopy( p, p->in.right );
31417724Sralph q->in.op = FREE;
31517724Sralph }
31617724Sralph return( 1 );
31717724Sralph }
31817724Sralph
31917724Sralph return( delay1(p->in.left) || delay1(p->in.right ) );
32017724Sralph }
32117724Sralph
delay2(p)32217724Sralph delay2( p ) register NODE *p; {
32317724Sralph
32417724Sralph /* look for delayable ++ and -- operators */
32517724Sralph
32617724Sralph register o, ty;
32717724Sralph o = p->in.op;
32817724Sralph ty = optype( o );
32917724Sralph
33017724Sralph switch( o ){
33117724Sralph
33217724Sralph case NOT:
33317724Sralph case QUEST:
33417724Sralph case ANDAND:
33517724Sralph case OROR:
33617724Sralph case CALL:
33717724Sralph case UNARY CALL:
33817724Sralph case STCALL:
33917724Sralph case UNARY STCALL:
34017724Sralph case FORTCALL:
34117724Sralph case UNARY FORTCALL:
34217724Sralph case COMOP:
34317724Sralph case CBRANCH:
34424406Smckusick /* for the moment, don't delay past a conditional context, or
34517724Sralph /* inside of a call */
34617724Sralph return;
34717724Sralph
34817724Sralph case UNARY MUL:
34917724Sralph /* if *p++, do not rewrite */
35017724Sralph if( autoincr( p ) ) return;
35117724Sralph break;
35217724Sralph
35317724Sralph case INCR:
35417724Sralph case DECR:
35517724Sralph if( deltest( p ) ){
35617724Sralph if( deli < DELAYS ){
35717724Sralph register NODE *q;
35817724Sralph deltrees[deli++] = tcopy(p);
35917724Sralph q = p->in.left;
36017724Sralph p->in.right->in.op = FREE; /* zap constant */
36117724Sralph ncopy( p, q );
36217724Sralph q->in.op = FREE;
36317724Sralph return;
36417724Sralph }
36517724Sralph }
36617724Sralph
36717724Sralph }
36817724Sralph
36917724Sralph if( ty == BITYPE ) delay2( p->in.right );
37017724Sralph if( ty != LTYPE ) delay2( p->in.left );
37117724Sralph }
37217724Sralph
codgen(p,cookie)37317724Sralph codgen( p, cookie ) NODE *p; {
37417724Sralph
37517724Sralph /* generate the code for p;
37617724Sralph order may call codgen recursively */
37717724Sralph /* cookie is used to describe the context */
37817724Sralph
37917724Sralph for(;;){
38017724Sralph canon(p); /* creats OREG from * if possible and does sucomp */
38117724Sralph stotree = NIL;
38217724Sralph # ifndef BUG4
38317724Sralph if( edebug ){
38417724Sralph printf( "store called on:\n" );
38517724Sralph fwalk( p, eprint, 0 );
38617724Sralph }
38717724Sralph # endif
38817724Sralph store(p);
38917724Sralph if( stotree==NIL ) break;
39017724Sralph
39117724Sralph /* because it's minimal, can do w.o. stores */
39217724Sralph
39317724Sralph order( stotree, stocook );
39417724Sralph }
39517724Sralph
39617724Sralph order( p, cookie );
39717724Sralph
39817724Sralph }
39917724Sralph
40017724Sralph # ifndef BUG4
40117724Sralph char *cnames[] = {
40217724Sralph "SANY",
40317724Sralph "SAREG",
40417724Sralph "STAREG",
40517724Sralph "SBREG",
40617724Sralph "STBREG",
40717724Sralph "SCC",
40817724Sralph "SNAME",
40917724Sralph "SCON",
41017724Sralph "SFLD",
41117724Sralph "SOREG",
41217724Sralph # ifdef WCARD1
41317724Sralph "WCARD1",
41417724Sralph # else
41517724Sralph "STARNM",
41617724Sralph # endif
41717747Sralph # ifdef WCARD2
41817724Sralph "WCARD2",
41917724Sralph # else
42017724Sralph "STARREG",
42117724Sralph # endif
42217724Sralph "INTEMP",
42317724Sralph "FORARG",
42417724Sralph "SWADD",
42517724Sralph 0,
42617724Sralph };
42717724Sralph
prcook(cookie)42817724Sralph prcook( cookie ){
42917724Sralph
43017724Sralph /* print a nice-looking description of cookie */
43117724Sralph
43217724Sralph int i, flag;
43317724Sralph
43417724Sralph if( cookie & SPECIAL ){
43517724Sralph if( cookie == SZERO ) printf( "SZERO" );
43617724Sralph else if( cookie == SONE ) printf( "SONE" );
43717724Sralph else if( cookie == SMONE ) printf( "SMONE" );
43824406Smckusick else if( cookie == SCCON ) printf( "SCCON" );
43924406Smckusick else if( cookie == SSCON ) printf( "SSCON" );
44024406Smckusick else if( cookie == SSOREG ) printf( "SSOREG" );
44117724Sralph else printf( "SPECIAL+%d", cookie & ~SPECIAL );
44217724Sralph return;
44317724Sralph }
44417724Sralph
44517724Sralph flag = 0;
44617724Sralph for( i=0; cnames[i]; ++i ){
44717724Sralph if( cookie & (1<<i) ){
44817724Sralph if( flag ) printf( "|" );
44917724Sralph ++flag;
45017724Sralph printf( cnames[i] );
45117724Sralph }
45217724Sralph }
45317724Sralph
45417724Sralph }
45517724Sralph # endif
45617724Sralph
45717724Sralph int odebug = 0;
45817724Sralph
order(p,cook)45932827Sdonn order(p,cook) register NODE *p; {
46017724Sralph
46117724Sralph register o, ty, m;
46217724Sralph int m1;
46317724Sralph int cookie;
46432827Sdonn register NODE *p1, *p2;
46517724Sralph
46617724Sralph cookie = cook;
46717724Sralph rcount();
46817724Sralph canon(p);
46917724Sralph rallo( p, p->in.rall );
47017724Sralph goto first;
47117724Sralph /* by this time, p should be able to be generated without stores;
47217724Sralph the only question is how */
47317724Sralph
47417724Sralph again:
47517724Sralph
47617724Sralph if ( p->in.op == FREE )
47717724Sralph return; /* whole tree was done */
47817724Sralph cookie = cook;
47917724Sralph rcount();
48017724Sralph canon(p);
48117724Sralph rallo( p, p->in.rall );
48217724Sralph /* if any rewriting and canonicalization has put
48317724Sralph * the tree (p) into a shape that cook is happy
48417724Sralph * with (exclusive of FOREFF, FORREW, and INTEMP)
48517724Sralph * then we are done.
48617724Sralph * this allows us to call order with shapes in
48717724Sralph * addition to cookies and stop short if possible.
48817724Sralph */
48917724Sralph if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return;
49017724Sralph
49117724Sralph first:
49217724Sralph # ifndef BUG4
49317724Sralph if( odebug ){
49417724Sralph printf( "order( %o, ", p );
49517724Sralph prcook( cookie );
49617724Sralph printf( " )\n" );
49717724Sralph fwalk( p, eprint, 0 );
49817724Sralph }
49917724Sralph # endif
50017724Sralph
50117724Sralph o = p->in.op;
50217724Sralph ty = optype(o);
50317724Sralph
50417724Sralph /* first of all, for most ops, see if it is in the table */
50517724Sralph
50617724Sralph /* look for ops */
50717724Sralph
50817724Sralph switch( m = p->in.op ){
50917724Sralph
51017724Sralph default:
51117724Sralph /* look for op in table */
51217724Sralph for(;;){
51317724Sralph if( (m = match( p, cookie ) ) == MDONE ) goto cleanup;
51417724Sralph else if( m == MNOPE ){
51517724Sralph if( !(cookie = nextcook( p, cookie ) ) ) goto nomat;
51617724Sralph continue;
51717724Sralph }
51817724Sralph else break;
51917724Sralph }
52017724Sralph break;
52117724Sralph
52217724Sralph case COMOP:
52317724Sralph case FORCE:
52417724Sralph case CBRANCH:
52517724Sralph case QUEST:
52617724Sralph case ANDAND:
52717724Sralph case OROR:
52817724Sralph case NOT:
52917724Sralph case UNARY CALL:
53017724Sralph case CALL:
53117724Sralph case UNARY STCALL:
53217724Sralph case STCALL:
53317724Sralph case UNARY FORTCALL:
53417724Sralph case FORTCALL:
53517724Sralph /* don't even go near the table... */
53617724Sralph ;
53717724Sralph
53817724Sralph }
53917724Sralph /* get here to do rewriting if no match or
54017724Sralph fall through from above for hard ops */
54117724Sralph
54217724Sralph p1 = p->in.left;
54317724Sralph if( ty == BITYPE ) p2 = p->in.right;
54417724Sralph else p2 = NIL;
54517724Sralph
54617724Sralph # ifndef BUG4
54717724Sralph if( odebug ){
54817724Sralph printf( "order( %o, ", p );
54917724Sralph prcook( cook );
55017724Sralph printf( " ), cookie " );
55117724Sralph prcook( cookie );
55217724Sralph printf( ", rewrite %s\n", opst[m] );
55317724Sralph }
55417724Sralph # endif
55517724Sralph switch( m ){
55617724Sralph default:
55717724Sralph nomat:
55817724Sralph cerror( "no table entry for op %s", opst[p->in.op] );
55917724Sralph
56017724Sralph case COMOP:
56117724Sralph codgen( p1, FOREFF );
56217724Sralph p2->in.rall = p->in.rall;
56317724Sralph codgen( p2, cookie );
56417724Sralph ncopy( p, p2 );
56517724Sralph p2->in.op = FREE;
56617724Sralph goto cleanup;
56717724Sralph
56817724Sralph case FORCE:
56917724Sralph /* recurse, letting the work be done by rallo */
57017724Sralph p = p->in.left;
57117724Sralph cook = INTAREG|INTBREG;
57217724Sralph goto again;
57317724Sralph
57417724Sralph case CBRANCH:
57517724Sralph o = p2->tn.lval;
57617724Sralph cbranch( p1, -1, o );
57717724Sralph p2->in.op = FREE;
57817724Sralph p->in.op = FREE;
57917724Sralph return;
58017724Sralph
58117724Sralph case QUEST:
58217724Sralph cbranch( p1, -1, m=getlab() );
58317724Sralph p2->in.left->in.rall = p->in.rall;
58417724Sralph codgen( p2->in.left, INTAREG|INTBREG );
58517724Sralph /* force right to compute result into same reg used by left */
58617724Sralph p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO;
58717724Sralph reclaim( p2->in.left, RNULL, 0 );
58817724Sralph cbgen( 0, m1 = getlab(), 'I' );
58917724Sralph deflab( m );
59017724Sralph codgen( p2->in.right, INTAREG|INTBREG );
59117724Sralph deflab( m1 );
59217724Sralph p->in.op = REG; /* set up node describing result */
59317724Sralph p->tn.lval = 0;
59417724Sralph p->tn.rval = p2->in.right->tn.rval;
59517724Sralph p->in.type = p2->in.right->in.type;
59617724Sralph tfree( p2->in.right );
59717724Sralph p2->in.op = FREE;
59817724Sralph goto cleanup;
59917724Sralph
60017724Sralph case ANDAND:
60117724Sralph case OROR:
60217724Sralph case NOT: /* logical operators */
60317724Sralph /* if here, must be a logical operator for 0-1 value */
60417724Sralph cbranch( p, -1, m=getlab() );
60517724Sralph p->in.op = CCODES;
60617724Sralph p->bn.label = m;
60717724Sralph order( p, INTAREG );
60817724Sralph goto cleanup;
60917724Sralph
61017724Sralph case FLD: /* fields of funny type */
61117724Sralph if ( p1->in.op == UNARY MUL ){
61217747Sralph offstar( p1->in.left );
61317724Sralph goto again;
61417724Sralph }
61517724Sralph
61617724Sralph case UNARY MINUS:
61729887Ssam order( p1, INBREG|INAREG|SOREG );
61817724Sralph goto again;
61917724Sralph
62017724Sralph case NAME:
62117724Sralph /* all leaves end up here ... */
62217724Sralph if( o == REG ) goto nomat;
62317724Sralph order( p, INTAREG|INTBREG );
62417724Sralph goto again;
62517724Sralph
62617724Sralph case INIT:
62717724Sralph uerror( "illegal initialization" );
62817724Sralph return;
62917724Sralph
63017724Sralph case UNARY FORTCALL:
63117724Sralph p->in.right = NIL;
63217724Sralph case FORTCALL:
63317724Sralph o = p->in.op = UNARY FORTCALL;
63417724Sralph if( genfcall( p, cookie ) ) goto nomat;
63517724Sralph goto cleanup;
63617724Sralph
63717724Sralph case UNARY CALL:
63817724Sralph p->in.right = NIL;
63917724Sralph case CALL:
64017724Sralph o = p->in.op = UNARY CALL;
64117724Sralph if( gencall( p, cookie ) ) goto nomat;
64217724Sralph goto cleanup;
64317724Sralph
64417724Sralph case UNARY STCALL:
64517724Sralph p->in.right = NIL;
64617724Sralph case STCALL:
64717724Sralph o = p->in.op = UNARY STCALL;
64817724Sralph if( genscall( p, cookie ) ) goto nomat;
64917724Sralph goto cleanup;
65017724Sralph
65117724Sralph /* if arguments are passed in register, care must be taken that reclaim
65217724Sralph /* not throw away the register which now has the result... */
65317724Sralph
65417724Sralph case UNARY MUL:
65517724Sralph if( cook == FOREFF ){
65617724Sralph /* do nothing */
65717724Sralph order( p->in.left, FOREFF );
65817724Sralph p->in.op = FREE;
65917724Sralph return;
66017724Sralph }
66132827Sdonn #ifdef R2REGS
66232827Sdonn /* try to coax a tree into a doubly indexed OREG */
66332827Sdonn p1 = p->in.left;
66432827Sdonn if( p1->in.op == PLUS ) {
66532827Sdonn if( ISPTR(p1->in.left->in.type) &&
66632827Sdonn offset(p1->in.right, tlen(p)) >= 0 ) {
66732827Sdonn order( p1->in.left, INAREG|INTAREG );
66832827Sdonn goto again;
66932827Sdonn }
67032827Sdonn if( ISPTR(p1->in.right->in.type) &&
67132827Sdonn offset(p1->in.left, tlen(p)) >= 0 ) {
67232827Sdonn order( p1->in.right, INAREG|INTAREG );
67332827Sdonn goto again;
67432827Sdonn }
67532827Sdonn }
67632827Sdonn #endif
67717747Sralph offstar( p->in.left );
67817724Sralph goto again;
67917724Sralph
68017724Sralph case INCR: /* INCR and DECR */
68117747Sralph if( setincr(p) ) goto again;
68217724Sralph
68317724Sralph /* x++ becomes (x += 1) -1; */
68417724Sralph
68517724Sralph if( cook & FOREFF ){ /* result not needed so inc or dec and be done with it */
68617724Sralph /* x++ => x += 1 */
68717724Sralph p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
68817724Sralph goto again;
68917724Sralph }
69017724Sralph
69117724Sralph p1 = tcopy(p);
69217724Sralph reclaim( p->in.left, RNULL, 0 );
69317724Sralph p->in.left = p1;
69417724Sralph p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
69517724Sralph p->in.op = (p->in.op==INCR)?MINUS:PLUS;
69617724Sralph goto again;
69717724Sralph
69817724Sralph case STASG:
69917747Sralph if( setstr( p ) ) goto again;
70017724Sralph goto nomat;
70117724Sralph
70217724Sralph case ASG PLUS: /* and other assignment ops */
70317747Sralph if( setasop(p) ) goto again;
70417724Sralph
70517724Sralph /* there are assumed to be no side effects in LHS */
70617724Sralph
70717724Sralph p2 = tcopy(p);
70817724Sralph p->in.op = ASSIGN;
70917724Sralph reclaim( p->in.right, RNULL, 0 );
71017724Sralph p->in.right = p2;
71117724Sralph canon(p);
71217724Sralph rallo( p, p->in.rall );
71317724Sralph
71417724Sralph # ifndef BUG4
71517724Sralph if( odebug ) fwalk( p, eprint, 0 );
71617724Sralph # endif
71717724Sralph
71817724Sralph order( p2->in.left, INTBREG|INTAREG );
71917724Sralph order( p2, INTBREG|INTAREG );
72017724Sralph goto again;
72117724Sralph
72217724Sralph case ASSIGN:
72317747Sralph if( setasg( p ) ) goto again;
72417724Sralph goto nomat;
72517724Sralph
72617724Sralph
72717724Sralph case BITYPE:
72817747Sralph if( setbin( p ) ) goto again;
72917724Sralph /* try to replace binary ops by =ops */
73017724Sralph switch(o){
73117724Sralph
73217724Sralph case PLUS:
73317724Sralph case MINUS:
73417724Sralph case MUL:
73517724Sralph case DIV:
73617724Sralph case MOD:
73717724Sralph case AND:
73817724Sralph case OR:
73917724Sralph case ER:
74017724Sralph case LS:
74117724Sralph case RS:
74217724Sralph p->in.op = ASG o;
74317724Sralph goto again;
74417724Sralph }
74517724Sralph goto nomat;
74617724Sralph
74717724Sralph }
74817724Sralph
74917724Sralph cleanup:
75017724Sralph
75117724Sralph /* if it is not yet in the right state, put it there */
75217724Sralph
75317724Sralph if( cook & FOREFF ){
75417724Sralph reclaim( p, RNULL, 0 );
75517724Sralph return;
75617724Sralph }
75717724Sralph
75817724Sralph if( p->in.op==FREE ) return;
75917724Sralph
76017724Sralph if( tshape( p, cook ) ) return;
76117724Sralph
76217724Sralph if( (m=match(p,cook) ) == MDONE ) return;
76317724Sralph
76417724Sralph /* we are in bad shape, try one last chance */
76517724Sralph if( lastchance( p, cook ) ) goto again;
76617724Sralph
76717724Sralph goto nomat;
76817724Sralph }
76917724Sralph
77017724Sralph int callflag;
77117724Sralph int fregs;
77217724Sralph
store(p)77317724Sralph store( p ) register NODE *p; {
77417724Sralph
77517724Sralph /* find a subtree of p which should be stored */
77617724Sralph
77717724Sralph register o, ty;
77817724Sralph
77917724Sralph o = p->in.op;
78017724Sralph ty = optype(o);
78117724Sralph
78217724Sralph if( ty == LTYPE ) return;
78317724Sralph
78417724Sralph switch( o ){
78517724Sralph
78617724Sralph case UNARY CALL:
78717724Sralph case UNARY FORTCALL:
78817724Sralph case UNARY STCALL:
78917724Sralph ++callflag;
79017724Sralph break;
79117724Sralph
79217724Sralph case UNARY MUL:
79317724Sralph if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL );
79417724Sralph break;
79517724Sralph
79617724Sralph case CALL:
79717724Sralph case FORTCALL:
79817724Sralph case STCALL:
79917724Sralph store( p->in.left );
80017724Sralph stoarg( p->in.right, o );
80117724Sralph ++callflag;
80217724Sralph return;
80317724Sralph
80417724Sralph case COMOP:
80517724Sralph markcall( p->in.right );
80617724Sralph if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
80717724Sralph store( p->in.left );
80817724Sralph return;
80917724Sralph
81017724Sralph case ANDAND:
81117724Sralph case OROR:
81217724Sralph case QUEST:
81317724Sralph markcall( p->in.right );
81417724Sralph if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
81517724Sralph case CBRANCH: /* to prevent complicated expressions on the LHS from being stored */
81617724Sralph case NOT:
81717724Sralph constore( p->in.left );
81817724Sralph return;
81917724Sralph
82017724Sralph }
82117724Sralph
82217724Sralph if( ty == UTYPE ){
82317724Sralph store( p->in.left );
82417724Sralph return;
82517724Sralph }
82617724Sralph
82717724Sralph if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o );
82817724Sralph
82917724Sralph if( p->in.su>fregs ){ /* must store */
83017724Sralph mkadrs( p ); /* set up stotree and stocook to subtree
83117724Sralph that must be stored */
83217724Sralph }
83317724Sralph
83417724Sralph store( p->in.right );
83517724Sralph store( p->in.left );
83617724Sralph }
83717724Sralph
constore(p)83817724Sralph constore( p ) register NODE *p; {
83917724Sralph
84017724Sralph /* store conditional expressions */
84117724Sralph /* the point is, avoid storing expressions in conditional
84217724Sralph conditional context, since the evaluation order is predetermined */
84317724Sralph
84417724Sralph switch( p->in.op ) {
84517724Sralph
84617724Sralph case ANDAND:
84717724Sralph case OROR:
84817724Sralph case QUEST:
84917724Sralph markcall( p->in.right );
85017724Sralph case NOT:
85117724Sralph constore( p->in.left );
85217724Sralph return;
85317724Sralph
85417724Sralph }
85517724Sralph
85617724Sralph store( p );
85717724Sralph }
85817724Sralph
markcall(p)85917724Sralph markcall( p ) register NODE *p; { /* mark off calls below the current node */
86017724Sralph
86117724Sralph again:
86217724Sralph switch( p->in.op ){
86317724Sralph
86417724Sralph case UNARY CALL:
86517724Sralph case UNARY STCALL:
86617724Sralph case UNARY FORTCALL:
86717724Sralph case CALL:
86817724Sralph case STCALL:
86917724Sralph case FORTCALL:
87017724Sralph ++callflag;
87117724Sralph return;
87217724Sralph
87317724Sralph }
87417724Sralph
87517724Sralph switch( optype( p->in.op ) ){
87617724Sralph
87717724Sralph case BITYPE:
87817724Sralph markcall( p->in.right );
87917724Sralph case UTYPE:
88017724Sralph p = p->in.left;
88117724Sralph /* eliminate recursion (aren't I clever...) */
88217724Sralph goto again;
88317724Sralph case LTYPE:
88417724Sralph return;
88517724Sralph }
88617724Sralph
88717724Sralph }
88817724Sralph
stoarg(p,calltype)88917724Sralph stoarg( p, calltype ) register NODE *p; {
89017724Sralph /* arrange to store the args */
89117724Sralph
89217724Sralph if( p->in.op == CM ){
89317724Sralph stoarg( p->in.left, calltype );
89417724Sralph p = p->in.right ;
89517724Sralph }
89617724Sralph if( calltype == CALL ){
89717724Sralph STOARG(p);
89817724Sralph }
89917724Sralph else if( calltype == STCALL ){
90017724Sralph STOSTARG(p);
90117724Sralph }
90217724Sralph else {
90317724Sralph STOFARG(p);
90417724Sralph }
90517724Sralph callflag = 0;
90617724Sralph store(p);
90717724Sralph # ifndef NESTCALLS
90817724Sralph if( callflag ){ /* prevent two calls from being active at once */
90917724Sralph SETSTO(p,INTEMP);
91017724Sralph store(p); /* do again to preserve bottom up nature.... */
91117724Sralph }
91217724Sralph #endif
91317724Sralph }
91417724Sralph
91517724Sralph int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */
91617724Sralph
91717724Sralph cbranch( p, true, false ) NODE *p; {
91817724Sralph /* evaluate p for truth value, and branch to true or false
91917724Sralph /* accordingly: label <0 means fall through */
92017724Sralph
92117724Sralph register o, lab, flab, tlab;
92217724Sralph
92317724Sralph lab = -1;
92417724Sralph
92517724Sralph switch( o=p->in.op ){
92617724Sralph
92717724Sralph case ULE:
92817724Sralph case ULT:
92917724Sralph case UGE:
93017724Sralph case UGT:
93117724Sralph case EQ:
93217724Sralph case NE:
93317724Sralph case LE:
93417724Sralph case LT:
93517724Sralph case GE:
93617724Sralph case GT:
93717724Sralph if( true < 0 ){
93817724Sralph o = p->in.op = negrel[ o-EQ ];
93917724Sralph true = false;
94017724Sralph false = -1;
94117724Sralph }
94217724Sralph #ifndef NOOPT
94317724Sralph if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){
94417724Sralph switch( o ){
94517724Sralph
94617724Sralph case UGT:
94717724Sralph case ULE:
94817724Sralph o = p->in.op = (o==UGT)?NE:EQ;
94917724Sralph case EQ:
95017724Sralph case NE:
95117724Sralph case LE:
95217724Sralph case LT:
95317724Sralph case GE:
95417724Sralph case GT:
95517724Sralph if( logop(p->in.left->in.op) ){
95617724Sralph /* strange situation: e.g., (a!=0) == 0 */
95717724Sralph /* must prevent reference to p->in.left->lable, so get 0/1 */
95817724Sralph /* we could optimize, but why bother */
95917724Sralph codgen( p->in.left, INAREG|INBREG );
96017724Sralph }
96117724Sralph codgen( p->in.left, FORCC );
96217724Sralph cbgen( o, true, 'I' );
96317724Sralph break;
96417724Sralph
96517724Sralph case UGE:
96617724Sralph codgen(p->in.left, FORCC);
96717724Sralph cbgen( 0, true, 'I' ); /* unconditional branch */
96817724Sralph break;
96917724Sralph case ULT:
97017724Sralph codgen(p->in.left, FORCC);
97117724Sralph }
97217724Sralph }
97317724Sralph else
97417724Sralph #endif
97517724Sralph {
97617724Sralph p->bn.label = true;
97717724Sralph codgen( p, FORCC );
97817724Sralph }
97917724Sralph if( false>=0 ) cbgen( 0, false, 'I' );
98017724Sralph reclaim( p, RNULL, 0 );
98117724Sralph return;
98217724Sralph
98317724Sralph case ANDAND:
98417724Sralph lab = false<0 ? getlab() : false ;
98517724Sralph cbranch( p->in.left, -1, lab );
98617724Sralph cbranch( p->in.right, true, false );
98717724Sralph if( false < 0 ) deflab( lab );
98817724Sralph p->in.op = FREE;
98917724Sralph return;
99017724Sralph
99117724Sralph case OROR:
99217724Sralph lab = true<0 ? getlab() : true;
99317724Sralph cbranch( p->in.left, lab, -1 );
99417724Sralph cbranch( p->in.right, true, false );
99517724Sralph if( true < 0 ) deflab( lab );
99617724Sralph p->in.op = FREE;
99717724Sralph return;
99817724Sralph
99917724Sralph case NOT:
100017724Sralph cbranch( p->in.left, false, true );
100117724Sralph p->in.op = FREE;
100217724Sralph break;
100317724Sralph
100417724Sralph case COMOP:
100517724Sralph codgen( p->in.left, FOREFF );
100617724Sralph p->in.op = FREE;
100717724Sralph cbranch( p->in.right, true, false );
100817724Sralph return;
100917724Sralph
101017724Sralph case QUEST:
101117724Sralph flab = false<0 ? getlab() : false;
101217724Sralph tlab = true<0 ? getlab() : true;
101317724Sralph cbranch( p->in.left, -1, lab = getlab() );
101417724Sralph cbranch( p->in.right->in.left, tlab, flab );
101517724Sralph deflab( lab );
101617724Sralph cbranch( p->in.right->in.right, true, false );
101717724Sralph if( true < 0 ) deflab( tlab);
101817724Sralph if( false < 0 ) deflab( flab );
101917724Sralph p->in.right->in.op = FREE;
102017724Sralph p->in.op = FREE;
102117724Sralph return;
102217724Sralph
102317724Sralph case ICON:
102417724Sralph if( p->in.type != FLOAT && p->in.type != DOUBLE ){
102517724Sralph
102617724Sralph if( p->tn.lval || p->in.name[0] ){
102717724Sralph /* addresses of C objects are never 0 */
102817724Sralph if( true>=0 ) cbgen( 0, true, 'I' );
102917724Sralph }
103017724Sralph else if( false>=0 ) cbgen( 0, false, 'I' );
103117724Sralph p->in.op = FREE;
103217724Sralph return;
103317724Sralph }
103417724Sralph /* fall through to default with other strange constants */
103517724Sralph
103617724Sralph default:
103717724Sralph /* get condition codes */
103817724Sralph codgen( p, FORCC );
103917724Sralph if( true >= 0 ) cbgen( NE, true, 'I' );
104017724Sralph if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
104117724Sralph reclaim( p, RNULL, 0 );
104217724Sralph return;
104317724Sralph
104417724Sralph }
104517724Sralph
104617724Sralph }
104717724Sralph
rcount()104817724Sralph rcount(){ /* count recursions */
104917724Sralph if( ++nrecur > NRECUR ){
105017724Sralph cerror( "expression causes compiler loop: try simplifying" );
105117724Sralph }
105217724Sralph
105317724Sralph }
105417724Sralph
105517724Sralph # ifndef BUG4
eprint(p,down,a,b)105617724Sralph eprint( p, down, a, b ) NODE *p; int *a, *b; {
105717724Sralph
105817724Sralph *a = *b = down+1;
105917724Sralph while( down >= 2 ){
106017724Sralph printf( "\t" );
106117724Sralph down -= 2;
106217724Sralph }
106317724Sralph if( down-- ) printf( " " );
106417724Sralph
106517724Sralph
106617724Sralph printf( "%o) %s", p, opst[p->in.op] );
106717724Sralph switch( p->in.op ) { /* special cases */
106817724Sralph
106917724Sralph case REG:
107017724Sralph printf( " %s", rnames[p->tn.rval] );
107117724Sralph break;
107217724Sralph
107317724Sralph case ICON:
107417724Sralph case NAME:
107517724Sralph case OREG:
107617724Sralph printf( " " );
107717724Sralph adrput( p );
107817724Sralph break;
107917724Sralph
108017724Sralph case STCALL:
108117724Sralph case UNARY STCALL:
108217724Sralph case STARG:
108317724Sralph case STASG:
108417724Sralph printf( " size=%d", p->stn.stsize );
108517724Sralph printf( " align=%d", p->stn.stalign );
108617724Sralph break;
108717724Sralph }
108817724Sralph
108917724Sralph printf( ", " );
109017724Sralph tprint( p->in.type );
109117724Sralph printf( ", " );
109217724Sralph if( p->in.rall == NOPREF ) printf( "NOPREF" );
109317724Sralph else {
109417724Sralph if( p->in.rall & MUSTDO ) printf( "MUSTDO " );
109517724Sralph else printf( "PREF " );
109617724Sralph printf( "%s", rnames[p->in.rall&~MUSTDO]);
109717724Sralph }
109817724Sralph printf( ", SU= %d\n", p->in.su );
109917724Sralph
110017724Sralph }
110117724Sralph # endif
110217724Sralph
110317724Sralph # ifndef NOMAIN
110417724Sralph NODE *
eread()110517724Sralph eread(){
110617724Sralph
110717724Sralph /* call eread recursively to get subtrees, if any */
110817724Sralph
110917724Sralph register NODE *p;
111017724Sralph register i, c;
111117724Sralph register char *pc;
111217724Sralph register j;
111317724Sralph
111417724Sralph i = rdin( 10 );
111517724Sralph
111617724Sralph p = talloc();
111717724Sralph
111817724Sralph p->in.op = i;
111917724Sralph
112017724Sralph i = optype(i);
112117724Sralph
112217724Sralph if( i == LTYPE ) p->tn.lval = rdin( 10 );
112317724Sralph if( i != BITYPE ) p->tn.rval = rdin( 10 );
112417724Sralph
112517724Sralph p->in.type = rdin(8 );
112617724Sralph p->in.rall = NOPREF; /* register allocation information */
112717724Sralph
112817724Sralph if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){
112917724Sralph p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
113017724Sralph p->stn.stalign = rdin(10) / SZCHAR;
113117724Sralph if( getchar() != '\n' ) cerror( "illegal \n" );
113217724Sralph }
113317724Sralph else { /* usual case */
113417724Sralph if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type ); /* non usually, but sometimes justified */
113517724Sralph #ifndef FLEXNAMES
113617724Sralph for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){
113717724Sralph if( j < NCHNAM ) *pc++ = c;
113817724Sralph }
113917724Sralph if( j < NCHNAM ) *pc = '\0';
114017724Sralph #else
114117724Sralph { char buf[BUFSIZ];
114217724Sralph for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){
114317724Sralph if( j < BUFSIZ ) *pc++ = c;
114417724Sralph }
114517724Sralph if( j < BUFSIZ ) *pc = '\0';
114617724Sralph p->in.name = tstr(buf);
114717724Sralph }
114817724Sralph #endif
114917724Sralph }
115017724Sralph
115117724Sralph /* now, recursively read descendents, if any */
115217724Sralph
115317724Sralph if( i != LTYPE ) p->in.left = eread();
115417724Sralph if( i == BITYPE ) p->in.right = eread();
115517724Sralph
115617724Sralph return( p );
115717724Sralph
115817724Sralph }
115917724Sralph
116017724Sralph CONSZ
rdin(base)116117724Sralph rdin( base ){
116217724Sralph register sign, c;
116317724Sralph CONSZ val;
116417724Sralph
116517724Sralph sign = 1;
116617724Sralph val = 0;
116717724Sralph
116817724Sralph while( (c=getchar()) > 0 ) {
116917724Sralph if( c == '-' ){
117017724Sralph if( val != 0 ) cerror( "illegal -");
117117724Sralph sign = -sign;
117217724Sralph continue;
117317724Sralph }
117417724Sralph if( c == '\t' ) break;
117517724Sralph if( c>='0' && c<='9' ) {
117617724Sralph val *= base;
117717724Sralph if( sign > 0 )
117817724Sralph val += c-'0';
117917724Sralph else
118017724Sralph val -= c-'0';
118117724Sralph continue;
118217724Sralph }
118317724Sralph cerror( "illegal character `%c' on intermediate file", c );
118417724Sralph break;
118517724Sralph }
118617724Sralph
118717724Sralph if( c <= 0 ) {
118817724Sralph cerror( "unexpected EOF");
118917724Sralph }
119017724Sralph return( val );
119117724Sralph }
119217724Sralph # endif
119317724Sralph
119417724Sralph #ifndef FIELDOPS
119517724Sralph /* do this if there is no special hardware support for fields */
119617724Sralph
ffld(p,down,down1,down2)119717724Sralph ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
119817724Sralph /* look for fields that are not in an lvalue context, and rewrite them... */
119917724Sralph register NODE *shp;
120017724Sralph register s, o, v, ty;
120117724Sralph
120217724Sralph *down1 = asgop( p->in.op );
120317724Sralph *down2 = 0;
120417724Sralph
120517724Sralph if( !down && p->in.op == FLD ){ /* rewrite the node */
120617724Sralph
120717724Sralph if( !rewfld(p) ) return;
120817724Sralph
120917724Sralph ty = (szty(p->in.type) == 2)? LONG: INT;
121017724Sralph v = p->tn.rval;
121117724Sralph s = UPKFSZ(v);
121217724Sralph # ifdef RTOLBYTES
121317724Sralph o = UPKFOFF(v); /* amount to shift */
121417724Sralph # else
121517724Sralph o = szty(p->in.type)*SZINT - s - UPKFOFF(v); /* amount to shift */
121617724Sralph #endif
121717724Sralph
121817724Sralph /* make & mask part */
121917724Sralph
122017724Sralph p->in.left->in.type = ty;
122117724Sralph
122217724Sralph p->in.op = AND;
122317724Sralph p->in.right = talloc();
122417724Sralph p->in.right->in.op = ICON;
122517724Sralph p->in.right->in.rall = NOPREF;
122617724Sralph p->in.right->in.type = ty;
122717724Sralph p->in.right->tn.lval = 1;
122817724Sralph p->in.right->tn.rval = 0;
122917724Sralph #ifndef FLEXNAMES
123017724Sralph p->in.right->in.name[0] = '\0';
123117724Sralph #else
123217724Sralph p->in.right->in.name = "";
123317724Sralph #endif
123417724Sralph p->in.right->tn.lval <<= s;
123517724Sralph p->in.right->tn.lval--;
123617724Sralph
123717724Sralph /* now, if a shift is needed, do it */
123817724Sralph
123917724Sralph if( o != 0 ){
124017724Sralph shp = talloc();
124117724Sralph shp->in.op = RS;
124217724Sralph shp->in.rall = NOPREF;
124317724Sralph shp->in.type = ty;
124417724Sralph shp->in.left = p->in.left;
124517724Sralph shp->in.right = talloc();
124617724Sralph shp->in.right->in.op = ICON;
124717724Sralph shp->in.right->in.rall = NOPREF;
124817724Sralph shp->in.right->in.type = ty;
124917724Sralph shp->in.right->tn.rval = 0;
125017724Sralph shp->in.right->tn.lval = o; /* amount to shift */
125117724Sralph #ifndef FLEXNAMES
125217724Sralph shp->in.right->in.name[0] = '\0';
125317724Sralph #else
125417724Sralph shp->in.right->in.name = "";
125517724Sralph #endif
125617724Sralph p->in.left = shp;
125717724Sralph /* whew! */
125817724Sralph }
125917724Sralph }
126017724Sralph }
126117724Sralph #endif
126217724Sralph
oreg2(p)126317724Sralph oreg2( p ) register NODE *p; {
126417724Sralph
126517724Sralph /* look for situations where we can turn * into OREG */
126617724Sralph
126717724Sralph NODE *q;
126817724Sralph register i;
126917724Sralph register r;
127017724Sralph register char *cp;
127117724Sralph register NODE *ql, *qr;
127217724Sralph CONSZ temp;
127317724Sralph
127417724Sralph if( p->in.op == UNARY MUL ){
127517724Sralph q = p->in.left;
127617724Sralph if( q->in.op == REG ){
127717724Sralph temp = q->tn.lval;
127817724Sralph r = q->tn.rval;
127917724Sralph cp = q->in.name;
128017724Sralph goto ormake;
128117724Sralph }
128217724Sralph
128317724Sralph if( q->in.op != PLUS && q->in.op != MINUS ) return;
128417724Sralph ql = q->in.left;
128517724Sralph qr = q->in.right;
128617724Sralph
128717724Sralph #ifdef R2REGS
128817724Sralph
128917724Sralph /* look for doubly indexed expressions */
129017724Sralph
129117724Sralph if( q->in.op == PLUS) {
129217724Sralph if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
129317724Sralph makeor2(p, ql, r, i);
129417724Sralph return;
129517724Sralph } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
129617724Sralph makeor2(p, qr, r, i);
129717724Sralph return;
129817724Sralph }
129917724Sralph }
130017724Sralph
130117724Sralph
130217724Sralph #endif
130317724Sralph
130417724Sralph if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
130517724Sralph ql->in.op==REG && szty(qr->in.type)==1) {
130617724Sralph temp = qr->tn.lval;
130717724Sralph if( q->in.op == MINUS ) temp = -temp;
130817724Sralph r = ql->tn.rval;
130917724Sralph temp += ql->tn.lval;
131017724Sralph cp = qr->in.name;
131117724Sralph if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return;
131217724Sralph if( !*cp ) cp = ql->in.name;
131317724Sralph
131417724Sralph ormake:
131517724Sralph if( notoff( p->in.type, r, temp, cp ) ) return;
131617724Sralph p->in.op = OREG;
131717724Sralph p->tn.rval = r;
131817724Sralph p->tn.lval = temp;
131917724Sralph #ifndef FLEXNAMES
132017724Sralph for( i=0; i<NCHNAM; ++i )
132117724Sralph p->in.name[i] = *cp++;
132217724Sralph #else
132317724Sralph p->in.name = cp;
132417724Sralph #endif
132517724Sralph tfree(q);
132617724Sralph return;
132717724Sralph }
132817724Sralph }
132917724Sralph
133017724Sralph }
133117724Sralph
canon(p)133217724Sralph canon(p) NODE *p; {
133317724Sralph /* put p in canonical form */
133417724Sralph int oreg2(), sucomp();
133517724Sralph
133617724Sralph #ifndef FIELDOPS
133717724Sralph int ffld();
133817724Sralph fwalk( p, ffld, 0 ); /* look for field operators */
133917724Sralph # endif
134017724Sralph walkf( p, oreg2 ); /* look for and create OREG nodes */
134117724Sralph #ifdef MYCANON
134217724Sralph MYCANON(p); /* your own canonicalization routine(s) */
134317724Sralph #endif
134417724Sralph walkf( p, sucomp ); /* do the Sethi-Ullman computation */
134517724Sralph
134617724Sralph }
134717724Sralph
1348