📄 reader.c
字号:
#ifndef lintstatic char *sccsid = "@(#)reader.c 1.6 (ULTRIX) 3/14/86";#endif lint# include "mfile2"/************************************************************************ * * * Copyright (c) 1983 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * Lu Anne Van de Pas * 002 Added -f flag which specifies that f floating arithmetic be done * in f and not to be promoted to d if it's not necessary. Also added * qdebug to print out the table entry that was matched. * * Stephen Reilly, 21-Oct-83: * 001- New -M flag is added that will indicate which float instruction * is required ( gfloat or dfloat). * ************************************************************************//* some storage declarations */# ifndef ONEPASSNODE node[TREESZ];char filename[100] = ""; /* the name of the file */int ftnno; /* number of current function */int lineno;# else# define NOMAIN#endifint nrecur;/* * If Mflag is set it indicates that user wants gfloat instructions */int Mflag; /* slr001 */int lflag;/* If fflag is set it indicates that the user doesn't want * floating point operations converted up to double precision */ extern int fflag; /* vdp002 */ extern int Wflag;int edebug = 0;int xdebug = 0;int udebug = 0;int vdebug = 0;int qdebug = 0; /*vdp002 print out the code template matched */ OFFSZ tmpoff; /* offset for first temporary, in bits for current block */OFFSZ maxoff; /* maximum temporary offset over all blocks in current ftn, in bits */int maxtreg;NODE *stotree;int stocook;OFFSZ baseoff = 0;OFFSZ maxtemp = 0;p2init( argc, argv ) char *argv[];{ /* set the values of the pass 2 arguments */ register int c; register char *cp; register files; allo0(); /* free all regs */ files = 0; for( c=1; c<argc; ++c ){ if( *(cp=argv[c]) == '-' ){ while( *++cp ){ switch( *cp ){ case 'X': /* pass1 flags */ while( *++cp ) { /* VOID */ } --cp; break; case 'l': /* linenos */ ++lflag; break; case 'q': /*vdp002 code template matched*/ ++qdebug; break; case 'e': /* expressions */ ++edebug; break; case 'o': /* orders */ ++odebug; break; case 'r': /* register allocation */ ++rdebug; break; case 'a': /* rallo */ ++radebug; break; case 'v': ++vdebug; break; case 't': /* ttype calls */ ++tdebug; break; case 's': /* shapes */ ++sdebug; break; case 'u': /* Sethi-Ullman testing (machine dependent) */ ++udebug; break; case 'x': /* general machine-dependent debugging flag */ ++xdebug; break; case 'w': case 'W': /* shut up warnings */ ++Wflag; break; case 'M': /* slr001 gfloat instruction? */ ++Mflag; /* slr001 */ break; /* slr001 */ case 'f': /* vdp002 floating point arithmetic */ ++fflag; break; default: cerror( "bad option: %c", *cp ); } } } else files = 1; /* assumed to be a filename */ } mkdope(); setrew(); return( files ); }# ifndef NOMAINunsigned int caloff();unsigned int offsz;mainp2( argc, argv ) char *argv[]; { register files; register temp; register c; register char *cp; register NODE *p; offsz = caloff(); files = p2init( argc, argv ); tinit(); reread: if( files ){ while( files < argc && argv[files][0] == '-' ) { ++files; } if( files > argc ) return( nerrors ); freopen( argv[files], "r", stdin ); } while( (c=getchar()) > 0 ) switch( c ){ case ')': default: /* copy line unchanged */ if ( c != ')' ) PUTCHAR( c ); /* initial tab */ while( (c=getchar()) > 0 ){ PUTCHAR(c); if( c == '\n' ) break; } continue; case BBEG: /* beginning of a block */ temp = rdin(10); /* ftnno */ tmpoff = baseoff = (unsigned int) rdin(10); /* autooff for block gives max offset of autos in block */ maxtreg = rdin(10); if( getchar() != '\n' ) cerror( "intermediate file format error"); if( temp != ftnno ){ /* beginning of function */ maxoff = baseoff; ftnno = temp; maxtemp = 0; } else { if( baseoff > maxoff ) maxoff = baseoff; /* maxoff at end of ftn is max of autos and temps over all blocks in the function */ } setregs(); continue; case BEND: /* end of block */ SETOFF( maxoff, ALSTACK ); eobl2(); while( (c=getchar()) != '\n' ){ if( c <= 0 ) cerror( "intermediate file format eof" ); } continue; case EXPR: /* compile code for an expression */ lineno = rdin( 10 ); for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */ *cp = '\0'; if( lflag ) lineid( lineno, filename ); tmpoff = baseoff; /* expression at top level reuses temps */ p = eread();# ifndef BUG4 if( edebug ) fwalk( p, eprint, 0 );# endif# ifdef MYREADER MYREADER(p); /* do your own laundering of the input */# endif nrecur = 0; delay( p ); /* expression statement throws out results */ reclaim( p, RNULL, 0 ); allchk(); tcheck(); continue; default: cerror( "intermediate file format error" ); } /* EOF */ if( files ) goto reread; return(nerrors); }# endif# ifdef ONEPASSp2compile( p ) NODE *p; { if( lflag ) lineid( lineno, filename ); tmpoff = baseoff; /* expression at top level reuses temps */ /* generate code for the tree p */# ifndef BUG4 if( edebug ) fwalk( p, eprint, 0 );# endif# ifdef MYREADER MYREADER(p); /* do your own laundering of the input */# endif nrecur = 0; delay( p ); /* do the code generation */ reclaim( p, RNULL, 0 ); allchk(); /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */ /* first pass will do it... */ }p2bbeg( aoff, myreg ) { static int myftn = -1; tmpoff = baseoff = (unsigned int) aoff; maxtreg = myreg; if( myftn != ftnno ){ /* beginning of function */ maxoff = baseoff; myftn = ftnno; maxtemp = 0; } else { if( baseoff > maxoff ) maxoff = baseoff; /* maxoff at end of ftn is max of autos and temps over all blocks */ } setregs(); }p2bend(){ SETOFF( maxoff, ALSTACK ); eobl2(); }# endifNODE *deltrees[DELAYS];int deli;delay( p ) register NODE *p; { /* look in all legal places for COMOP's and ++ and -- ops to delay */ /* note; don't delay ++ and -- within calls or things like /* getchar (in their macro forms) will start behaving strangely */ register i; /* look for visible COMOPS, and rewrite repeatedly */ while( delay1( p ) ) { /* VOID */ } /* look for visible, delayable ++ and -- */ deli = 0; delay2( p ); codgen( p, FOREFF ); /* do what is left */ for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF ); /* do the rest */ }delay1( p ) register NODE *p; { /* look for COMOPS */ register o, ty; o = p->in.op; ty = optype( o ); if( ty == LTYPE ) return( 0 ); else if( ty == UTYPE ) return( delay1( p->in.left ) ); switch( o ){ case QUEST: case ANDAND: case OROR: /* don't look on RHS */ return( delay1(p->in.left ) ); case COMOP: /* the meat of the routine */ delay( p->in.left ); /* completely evaluate the LHS */ /* rewrite the COMOP */ { register NODE *q; q = p->in.right; ncopy( p, p->in.right ); q->in.op = FREE; } return( 1 ); } return( delay1(p->in.left) || delay1(p->in.right ) ); }delay2( p ) register NODE *p; { /* look for delayable ++ and -- operators */ register o, ty; o = p->in.op; ty = optype( o ); switch( o ){ case NOT: case QUEST: case ANDAND: case OROR: case CALL: case UNARY CALL: case STCALL: case UNARY STCALL: case FORTCALL: case UNARY FORTCALL: case COMOP: case CBRANCH: /* for the moment, don7t delay past a conditional context, or /* inside of a call */ return; case UNARY MUL: /* if *p++, do not rewrite */ if( autoincr( p ) ) return; break; case INCR: case DECR: if( deltest( p ) ){ if( deli < DELAYS ){ register NODE *q; deltrees[deli++] = tcopy(p); q = p->in.left; p->in.right->in.op = FREE; /* zap constant */ ncopy( p, q ); q->in.op = FREE; return; } } } if( ty == BITYPE ) delay2( p->in.right ); if( ty != LTYPE ) delay2( p->in.left ); }codgen( p, cookie ) NODE *p; { /* generate the code for p; order may call codgen recursively */ /* cookie is used to describe the context */ for(;;){ canon(p); /* creats OREG from * if possible and does sucomp */ stotree = NIL;# ifndef BUG4 if( edebug ){ printf( "store called on:\n" ); fwalk( p, eprint, 0 ); }# endif store(p); if( stotree==NIL ) break; /* because it's minimal, can do w.o. stores */ order( stotree, stocook ); } order( p, cookie ); }# ifndef BUG4char *cnames[] = { "SANY", "SAREG", "STAREG", "SBREG", "STBREG", "SCC", "SNAME", "SCON", "SFLD", "SOREG",# ifdef WCARD1 "WCARD1",# else "STARNM",# endif# ifdef WCARD2" "WCARD2",# else "STARREG",# endif "INTEMP", "FORARG", "SWADD", 0, };extern prcook( cookie ){ /* print a nice-looking description of cookie */ int i, flag; if( cookie & SPECIAL ){ if( cookie == SZERO ) printf( "SZERO" ); else if( cookie == SONE ) printf( "SONE" ); else if( cookie == SMONE ) printf( "SMONE" ); else printf( "SPECIAL+%d", cookie & ~SPECIAL ); return; } flag = 0; for( i=0; cnames[i]; ++i ){ if( cookie & (1<<i) ){ if( flag ) printf( "|" ); ++flag; printf( cnames[i] ); } } }# endifint odebug = 0;order(p,cook) NODE *p; { register o, ty, m; int m1; int cookie; NODE *p1, *p2; cookie = cook; rcount(); canon(p); rallo( p, p->in.rall ); goto first; /* by this time, p should be able to be generated without stores; the only question is how */ again: if ( p->in.op == FREE ) return; /* whole tree was done */ cookie = cook; rcount(); canon(p); rallo( p, p->in.rall ); /* if any rewriting and canonicalization has put * the tree (p) into a shape that cook is happy * with (exclusive of FOREFF, FORREW, and INTEMP) * then we are done. * this allows us to call order with shapes in * addition to cookies and stop short if possible. */ if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return; first:# ifndef BUG4 if( odebug ){ printf( "order( %o, ", p ); prcook( cookie ); printf( " )\n" ); fwalk( p, eprint, 0 ); }# endif o = p->in.op; ty = optype(o); /* first of all, for most ops, see if it is in the table */ /* look for ops */ switch( m = p->in.op ){ default: /* look for op in table */ for(;;){ if( (m = match( p, cookie ) ) == MDONE ) goto cleanup; else if( m == MNOPE ){ if( !(cookie = nextcook( p, cookie ) ) ) goto nomat; continue; } else break; } break; case COMOP: case FORCE: case CBRANCH: case QUEST: case ANDAND: case OROR: case NOT: case UNARY CALL: case CALL: case UNARY STCALL: case STCALL: case UNARY FORTCALL: case FORTCALL: /* don't even go near the table... */ ; } /* get here to do rewriting if no match or fall through from above for hard ops */ p1 = p->in.left; if( ty == BITYPE ) p2 = p->in.right; else p2 = NIL; # ifndef BUG4 if( odebug ){ printf( "order( %o, ", p ); prcook( cook ); printf( " ), cookie " ); prcook( cookie ); printf( ", rewrite %s\n", opst[m] ); }# endif switch( m ){ default: nomat: cerror( "no table entry for op %s", opst[p->in.op] ); case COMOP: codgen( p1, FOREFF ); p2->in.rall = p->in.rall; codgen( p2, cookie ); ncopy( p, p2 ); p2->in.op = FREE; goto cleanup; case FORCE: /* recurse, letting the work be done by rallo */ p = p->in.left; cook = INTAREG|INTBREG; goto again; case CBRANCH: o = p2->tn.lval; cbranch( p1, -1, o ); p2->in.op = FREE; p->in.op = FREE; return; case QUEST: cbranch( p1, -1, m=getlab() ); p2->in.left->in.rall = p->in.rall; codgen( p2->in.left, INTAREG|INTBREG ); /* force right to compute result into same reg used by left */ p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO; reclaim( p2->in.left, RNULL, 0 ); cbgen( 0, m1 = getlab(), 'I' ); deflab( m ); codgen( p2->in.right, INTAREG|INTBREG ); deflab( m1 ); p->in.op = REG; /* set up node describing result */ p->tn.lval = 0; p->tn.rval = p2->in.right->tn.rval; p->in.type = p2->in.right->in.type; tfree( p2->in.right ); p2->in.op = FREE; goto cleanup; case ANDAND: case OROR: case NOT: /* logical operators */ /* if here, must be a logical operator for 0-1 value */ cbranch( p, -1, m=getlab() ); p->in.op = CCODES; p->bn.label = m; order( p, INTAREG ); goto cleanup; case FLD: /* fields of funny type */ if ( p1->in.op == UNARY MUL ){ offstar( p1->in.left, cook ); goto again; } case UNARY MINUS: order( p1, INBREG|INAREG ); goto again; case NAME: /* all leaves end up here ... */ if( o == REG ) goto nomat; order( p, INTAREG|INTBREG ); goto again; case INIT: uerror( "illegal initialization" ); return; case UNARY FORTCALL: p->in.right = NIL; case FORTCALL: o = p->in.op = UNARY FORTCALL; if( genfcall( p, cookie ) ) goto nomat; goto cleanup; case UNARY CALL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -