home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / pcc / local.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  7.3 KB  |  338 lines

  1. # include "mfile1"
  2.  
  3.  
  4. /*    this file contains code which is dependent on the target machine */
  5.  
  6. NODE *
  7. cast( p, t ) register NODE *p; TWORD t; {
  8.     /* cast node p to type t */
  9.  
  10.     p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
  11.     p->left->op = FREE;
  12.     p->op = FREE;
  13.     return( p->right );
  14.     }
  15.  
  16. NODE *
  17. clocal(p) NODE *p; {
  18.  
  19.     /* this is called to do local transformations on
  20.        an expression tree preparitory to its being
  21.        written out in intermediate code.
  22.     */
  23.  
  24.     /* the major essential job is rewriting the
  25.        automatic variables and arguments in terms of
  26.        REG and OREG nodes */
  27.     /* conversion ops which are not necessary are also clobbered here */
  28.     /* in addition, any special features (such as rewriting
  29.        exclusive or) are easily handled here as well */
  30.  
  31.     register struct symtab *q;
  32.     register NODE *r;
  33.     register o;
  34.     register m, ml;
  35.  
  36.     switch( o = p->op ){
  37.  
  38.     case NAME:
  39.         if( p->rval < 0 ) { /* already processed; ignore... */
  40.             return(p);
  41.             }
  42.         q = &stab[p->rval];
  43.         switch( q->sclass ){
  44.  
  45.         case AUTO:
  46.         case PARAM:
  47.             /* fake up a structure reference */
  48.             r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
  49.             r->lval = 0;
  50.             r->rval = (q->sclass==AUTO?STKREG:ARGREG);
  51.             p = stref( block( STREF, r, p, 0, 0, 0 ) );
  52.             break;
  53.  
  54.         case ULABEL:
  55.         case LABEL:
  56.         case STATIC:
  57.             if( q->slevel == 0 ) break;
  58.             p->lval = 0;
  59.             p->rval = -q->offset;
  60.             break;
  61.  
  62.         case REGISTER:
  63.             p->op = REG;
  64.             p->lval = 0;
  65.             p->rval = q->offset;
  66.             break;
  67.  
  68.             }
  69.         break;
  70.     case LT:
  71.     case LE:
  72.     case GT:
  73.     case GE:
  74.         if( ISPTR( p->left->type ) || ISPTR( p->right->type ) ){
  75.             p->op += (ULT-LT);
  76.             }
  77.         break;
  78.  
  79.     case PCONV:
  80.         /* do pointer conversions for char and longs */
  81.         ml = p->left->type;
  82.         if( ( ml==CHAR || ml==UCHAR || ml==LONG || ml==ULONG ) && p->left->op != ICON ) break;
  83.  
  84.         /* pointers all have the same representation; the type is inherited */
  85.         p->left->type = p->type;
  86.         p->left->cdim = p->cdim;
  87.         p->left->csiz = p->csiz;
  88.         p->op = FREE;
  89.         return( p->left );
  90.  
  91.     case SCONV:
  92.         m = (p->type == FLOAT || p->type == DOUBLE );
  93.         ml = (p->left->type == FLOAT || p->left->type == DOUBLE );
  94.         if( m != ml ) break;
  95.  
  96.         /* now, look for conversions downwards */
  97.  
  98.         m = p->type;
  99.         ml = p->left->type;
  100.         if( p->left->op == ICON ){ /* simulate the conversion here */
  101.             CONSZ val;
  102.             val = p->left->lval;
  103.             switch( m ){
  104.             case CHAR:
  105.                 p->left->lval = (char) val;
  106.                 break;
  107.             case UCHAR:
  108.                 p->left->lval = val & 0XFF;
  109.                 break;
  110.             case UNSIGNED:
  111.                 p->left->lval = val & 0XFFFFL;
  112.                 break;
  113.             case INT:
  114.                 p->left->lval = (int)val;
  115.                 break;
  116.                 }
  117.             p->left->type = m;
  118.             }
  119.         else {
  120.             /* meaningful ones are conversion of int to char, int to short,
  121.                and short to char, and unsigned version of them */
  122.             if( m==CHAR || m==UCHAR ){
  123.                 if( ml==LONG || ml==ULONG ) break;
  124.                 }
  125.             else if( m==INT || m==UNSIGNED ){
  126.                 if( ml==LONG || ml==ULONG ) break;
  127.                 }
  128.             else if( m==LONG || m==ULONG ){
  129.                 if( ml!=LONG && ml!= ULONG ) break;
  130.                 }
  131.             }
  132.  
  133.         /* clobber conversion */
  134.         p->op = FREE;
  135.         return( p->left );  /* conversion gets clobbered */
  136.  
  137.     case ASSIGN:
  138.         /* get rid of SCONV for assignments
  139.            from LONG -> CHAR|INT    */
  140.         if( p->right->op == SCONV ) {
  141.             m = p->right->type;
  142.             ml = p->right->left->type;
  143.             if( ( m==LONG || m==ULONG ) &&
  144.                 ml!=FLOAT && ml!=DOUBLE ) {
  145.                 p->right->op = FREE;
  146.                 p->right = p->right->left;
  147.                 }
  148.             }
  149.         break;
  150.  
  151.     case PVCONV:
  152.     case PMCONV:
  153.         if( p->right->op != ICON ) cerror( "bad conversion", 0);
  154.         p->op = FREE;
  155.         return( buildtree( o==PMCONV?MUL:DIV, p->left, p->right ) );
  156.  
  157.     case PLUS:
  158.     case MINUS:
  159.     case LS:
  160.     case MUL:
  161.         /* optimize address calculations with long indexes */
  162.         if( ISPTR( p->type ) || ISARY( p->type ) ) {
  163.             if( p->left->type==LONG || p->left->type==ULONG )
  164.                 p->left = cast( p->left, INT );
  165.             if( p->right->type==LONG || p->right->type==ULONG )
  166.                 p->right = cast( p->right, INT );
  167.             }
  168.         break;
  169.  
  170.         }
  171.  
  172.     return(p);
  173.     }
  174.  
  175. andable( p ) NODE *p; {
  176.     return(1);  /* all names can have & taken on them */
  177.     }
  178.  
  179. cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
  180.     autooff = AUTOINIT;
  181.     }
  182.  
  183. cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
  184.  
  185.     if( t==INT || t==UNSIGNED || ISPTR(t) ) return(1);
  186.     return(0);
  187.     }
  188.  
  189. NODE *
  190. offcon( off, t, d, s ) OFFSZ off; TWORD t; {
  191.  
  192.     /* return a node, for structure references, which is suitable for
  193.        being added to a pointer of type t, in order to be off bits offset
  194.        into a structure */
  195.  
  196.     register NODE *p;
  197.  
  198.     /* t, d, and s are the type, dimension offset, and sizeoffset */
  199.     /* in general they  are necessary for offcon, but not on H'well */
  200.  
  201.     p = bcon(0);
  202.     p->lval = off/SZCHAR;
  203.     return(p);
  204.  
  205.     }
  206.  
  207. static inwd    /* current bit offsed in word */;
  208. static word    /* word being built from fields */;
  209.  
  210. incode( p, sz ) register NODE *p; {
  211.  
  212.     /* generate initialization code for assigning a constant c
  213.         to a field of width sz */
  214.     /* we assume that the proper alignment has been obtained */
  215.     /* inoff is updated to have the proper final value */
  216.     /* we also assume sz  < SZINT */
  217.  
  218.     if((sz+inwd) > SZINT) cerror("incode: field > int");
  219.     word |= p->lval<<inwd;
  220.     inwd += sz;
  221.     inoff += sz;
  222.     if(inoff%SZINT == 0) {
  223.         printf( "    %o\n", word);
  224.         word = inwd = 0;
  225.         }
  226.     }
  227.  
  228. fincode( d, sz ) double d; {
  229.     /* output code to initialize space of size sz to the value d */
  230.     /* the proper alignment has been obtained */
  231.     /* inoff is updated to have the proper final value */
  232.     /* on the target machine, write it out in octal! */
  233.  
  234.     register int *mi = (int *)&d;
  235.  
  236.     if( sz==SZDOUBLE )
  237.         printf( "    %o; %o; %o; %o\n", mi[0], mi[1], mi[2], mi[3] );
  238.     else
  239.         printf( "    %o; %o\n", mi[0], mi[1] );
  240.     inoff += sz;
  241.     }
  242.  
  243. cinit( p, sz ) NODE *p; {
  244.     /* arrange for the initialization of p into a space of
  245.     size sz */
  246.     /* the proper alignment has been opbtained */
  247.     /* inoff is updated to have the proper final value */
  248.     ecode( p );
  249.     inoff += sz;
  250.     }
  251.  
  252. vfdzero( n ){ /* define n bits of zeros in a vfd */
  253.  
  254.     if( n <= 0 ) return;
  255.  
  256.     inwd += n;
  257.     inoff += n;
  258.     if( inoff%ALINT ==0 ) {
  259.         printf( "    %o\n", word );
  260.         word = inwd = 0;
  261.         }
  262.     }
  263.  
  264.  
  265. char *
  266. exname( p ) char *p; {
  267.     /* make a name look like an external name in the local machine */
  268.  
  269.     static char text[NCHNAM+1];
  270.  
  271.     register i;
  272.  
  273.     text[0] = '_';
  274.     for( i=1; *p&&i<NCHNAM; ++i ){
  275.         text[i] = *p++;
  276.         }
  277.  
  278.     text[i] = '\0';
  279.     text[NCHNAM] = '\0';  /* truncate */
  280.  
  281.     return( text );
  282.     }
  283.  
  284. ctype( type ) TWORD type; { /* map types which are not defined on the local machine */
  285.     switch( BTYPE(type) ){
  286.     case SHORT:
  287.         MODTYPE(type,INT);
  288.         break;
  289.     case USHORT:
  290.         MODTYPE(type,UNSIGNED);
  291.         }
  292.     return( type );
  293.     }
  294.  
  295. noinit() { /* curid is a variable which is defined but
  296.     is not initialized (and not a function );
  297.     This routine returns the stroage class for an uninitialized declaration */
  298.  
  299.     return(EXTERN);
  300.  
  301.     }
  302.  
  303. commdec( id ){ /* make a common declaration for id, if reasonable */
  304.     register struct symtab *q;
  305.     OFFSZ off;
  306.  
  307.     q = &stab[id];
  308.     printf( "    .comm    %s,", exname( q->sname ) );
  309.     off = tsize( q->stype, q->dimoff, q->sizoff );
  310.     printf( CONFMT, off/SZCHAR );
  311.     printf( ".\n" );
  312.     }
  313.  
  314. isitlong( cb, ce ){ /* is lastcon to be long or short */
  315.     /* cb is the first character of the representation, ce the last */
  316.  
  317.     if( ce == 'l' || ce == 'L' ||
  318.         lastcon >= (1L << (SZINT-1) ) ) return (1);
  319.     return(0);
  320.     }
  321.  
  322.  
  323. isitfloat( s ) char *s; {
  324.     double atof();
  325.     dcon = atof(s);
  326.     return( FCON );
  327.     }
  328.  
  329. ecode( p ) NODE *p; {
  330.  
  331.     /* walk the tree and write out the nodes.. */
  332.  
  333.     if( nerrors ) return;
  334.     p2tree( p );
  335.     p2compile( p );
  336.     }
  337.  
  338.