📄 trees.c
字号:
* (int op= real) where the real is getting converted where * it should not. The ASSIGN is unchanged by this fix. Only * the op= is effected. */ if ( ( (dope[o]&ASGOPFLG) && /* vdp014*/ o != CAST && o != RETURN) && ( (t == DOUBLE || t==FLOAT) ) ) /* vdp009 slr002 slr001 */ { tu = t; /* slr001 */ } else /* slr001 */ { tu = p->in.left->in.type; /* slr001 */ } t = t1; /* slr001 */ } else { tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; } /* because expressions have values that are at least as wide as INT or UNSIGNED, the only conversions needed are those involving FLOAT/DOUBLE, and those from LONG to INT and ULONG to UNSIGNED */ if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu ); if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); if( asgop(o) ){ /* * The mode of the operation is based on the right * side if (int op= real ) */ if ( ( (dope[o]&ASGOPFLG) && o != CAST && o != RETURN) && (tu == DOUBLE || tu == FLOAT) ) /* vdp009 slr002 */ { p->in.type = p->in.right->in.type; /* slr002 */ p->fn.cdim = p->in.right->fn.cdim; /* slr002 */ p->fn.csiz = p->in.right->fn.csiz; /* slr002 */ } else { p->in.type = p->in.left->in.type; /* slr002 */ p->fn.cdim = p->in.left->fn.cdim; /* slr002 */ p->fn.csiz = p->in.left->fn.csiz; /* slr002 */ } } else if( !logop(o) ){ p->in.type = tu; p->fn.cdim = 0; p->fn.csiz = t; }# ifndef BUG1 if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );# endif return(p); }NODE *makety( p, t, d, s ) register NODE *p; TWORD t; { /* make p into type t by inserting a conversion */ if ((p->in.type == ENUMTY) && (p->in.op == ICON)){ /* * Go ahead and convert to an integer type (CHAR, SHORT, etc). * and then see if we can do any further conversion at compile * time. */ econvert(p); } if( t == p->in.type ){ p->fn.cdim = d; p->fn.csiz = s; return( p ); } if( t & TMASK ){ /* non-simple type */ return( block( PCONV, p, NIL, t, d, s ) ); } /* vdp009 Separate Floating constant from Double */ if( p->in.op == ICON ){ if( t==DOUBLE ){ p->in.op = DCON; if( ISUNSIGNED(p->in.type) ){ p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval; } else { p->dpn.dval = p->tn.lval; } p->in.type = p->fn.csiz = t; return( clocal(p) ); } if (t==FLOAT) { p->in.op = FCON; if ( ISUNSIGNED(p->in.type) ) { p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval; } else { p->fpn.fval = p->tn.lval ; } p->in.type = p->fn.csiz = t; return (clocal(p) ); } /* dlb015 * Insert a node to do a scalar conversion, and call clocal * to let it perform the conversion/cast of the integer * constant at compile time if possible. */ return( clocal(block( SCONV, p, NIL, t, d, s ) ) ); } else if (p->in.op == FCON && t == DOUBLE ) { double db; p->in.op = DCON; db = p->fpn.fval; p->dpn.dval = db; p->in.type = p->fn.csiz = t; return (clocal(p)); } else if (p->in.op == DCON && t == FLOAT ) { if (fflag) { /*vdp014*/ float fl; p->in.op = FCON; fl = p->dpn.dval; if (fl != p->dpn.dval) werror("float conversion loses precision"); p->fpn.fval=fl; p->in.type = p->fn.csiz = t; return (clocal(p)); } } /* dlb015 * Insert a node to indicate that a scalar conversion/cast will need * to be done at some point. However, clocal can't be called now to * do the conversion, since that might lose needed information. */ return( block( SCONV, p, NIL, t, d, s ) ); }NODE *block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { register NODE *p; p = talloc(); p->in.op = o; p->in.left = l; p->in.right = r; p->in.type = t; p->fn.cdim = d; p->fn.csiz = s; if (l != NIL) { p->in.typattr = l->in.typattr; } else { p->in.typattr = UNDEF; } return(p); }icons(p) register NODE *p; { /* if p is an integer constant, return its value */ int val; if( p->in.op != ICON ){ uerror( "constant expected"); val = 1; } else { val = p->tn.lval; if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); } tfree( p ); return(val); }/* the intent of this table is to examine the operators, and to check them for correctness. The table is searched for the op and the modified type (where this is one of the types INT (includes char and short), LONG, DOUBLE (includes FLOAT), and POINTER The default action is to make the node type integer The actions taken include: PUN check for puns CVTL convert the left operand CVTR convert the right operand TYPL the type is determined by the left operand TYPR the type is determined by the right operand TYMATCH force type of left and right to match, by inserting conversions PTMATCH like TYMATCH, but for pointers LVAL left operand must be lval CVTO convert the op NCVT do not convert the operands OTHER handled by code NCVTR convert the left operand, not the right... */# define MINT 01 /* integer */# define MDBI 02 /* integer or double */# define MSTR 04 /* structure */# define MPTR 010 /* pointer */# define MPTI 020 /* pointer or integer */# define MENU 040 /* enumeration variable or member */# define MVOID 0100000 /* void type */opact( p ) NODE *p; { register mt12, mt1, mt2, o; mt1 = mt2 = mt12 = 0; switch( optype(o=p->in.op) ){ case BITYPE: mt2 = moditype( p->in.right->in.type ); case UTYPE: mt1 = moditype( p->in.left->in.type ); } if( ((mt1 | mt2) & MVOID) && o != COMOP && !(o == CAST && (mt1 & MVOID)) ){ /* if lhs of RETURN is void, grammar will complain */ if( o != RETURN ) uerror( "value of void expression used" ); return( NCVT ); } mt1 &= ~MVOID; mt2 &= ~MVOID; mt12 = mt1 & mt2; switch( o ){ case NAME : case STRING : case ICON : case FCON : case DCON : /*vdp009*/ case CALL : case UNARY CALL: case UNARY MUL: { return( OTHER ); } case UNARY MINUS: if( mt1 & MDBI ) return( TYPL ); break; case COMPL: if( mt1 & MINT ) return( TYPL ); break; case UNARY AND: { return( NCVT+OTHER ); } case INIT: case CM: return( 0 ); case NOT: case CBRANCH: case ANDAND: case OROR: /*RAP004 Don't allow expressions involving structures or unions. */ if (o==NOT || o==CBRANCH){ /*Catch void type RAP005 */ if (mt1 == 0){ uerror("void or undef used in value required context"); return(NCVT); } if (mt1 != MSTR) return(0); } else { /* RAP005 */ if (mt1==0 || mt2 ==0){ uerror("void or undef used in value required context"); return(NCVT); } if ( mt1 != MSTR && mt2 != MSTR) return( 0 ); } uerror("illegal use of union or structure in conditional expression"); return( NCVT); case MUL: case DIV: if( mt12 & MDBI ) return( TYMATCH ); /* jpm: spr 873 */ if ( (mt1 & MPTI) && (mt2 & MENU)) return( TYMATCH ); if ( (mt2 & MPTI) && (mt1 & MENU)) return( TYMATCH ); break; case MOD: case AND: case OR: case ER: if( mt12 & MINT ) return( TYMATCH ); break; case LS: case RS: if( mt12 & MINT ) return( TYMATCH+OTHER ); break; case EQ: case NE: case LT: case LE: case GT: case GE: if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); if( mt12 & MDBI ) return( TYMATCH+CVTO ); else if( mt12 & MPTR ) return( PTMATCH+PUN ); else if( mt12 & MPTI ) return( PTMATCH+PUN ); else break; case QUEST: case COMOP: if (o==QUEST && mt1 == MSTR){ /*RAP004*/ uerror("illegal use of union or structure in conditional expression"); return( NCVT); } if( mt2&MENU ) return( TYPR+NCVTR ); return( TYPR ); case STREF: return( NCVTR+OTHER ); case FORCE: return( TYPL ); case COLON: if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); else if( mt12 & MDBI ) return( TYMATCH ); else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); break; case ASSIGN: case RETURN: if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); case CAST: if(o==CAST && mt1==0)return(TYPL+TYMATCH); if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); else if(( mt2 == 0 ) && /* void (*func)() ? */ (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL)) break; else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); break; case ASG LS: case ASG RS: if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); break; case ASG MUL: case ASG DIV: if( mt12 & MDBI ) return( LVAL+TYMATCH ); break; case ASG MOD: case ASG AND: case ASG OR: case ASG ER: if( mt12 & MINT ) return( LVAL+TYMATCH ); break; case ASG PLUS: case ASG MINUS: case INCR: case DECR: if( mt12 & MDBI ) return( TYMATCH+LVAL ); else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); break; case MINUS: if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); if( mt2 & MPTR ) break; case PLUS: if( mt12 & MDBI ) return( TYMATCH );/* jpm: Fix spr 873; MINT|MENU Allow enums to index an array per K&R */ else if( (mt1&MPTR) && (mt2&(MINT|MENU)) ) return( TYPL+CVTR ); else if( (mt1&(MINT|MENU)) && (mt2&MPTR) ) return( TYPR+CVTL ); } uerror( "operands of %s have incompatible types", opst[o] ); return( NCVT ); }moditype( ty ) TWORD ty; { switch(ty){ case TVOID: return( MPTR ); case UNDEF: return( MVOID ); case ENUMTY: case MOETY: return( MENU ); case STRTY: case UNIONTY: return( MSTR ); case CHAR: case SHORT: case UCHAR: case USHORT: return( MINT|MPTI|MDBI ); case UNSIGNED: case ULONG: case INT: case LONG: return( MINT|MDBI|MPTI ); case FLOAT: case DOUBLE: return( MDBI ); default: return( MPTR|MPTI ); } }NODE *doszof( p ) register NODE *p; { /* do sizeof p */ int i; /* whatever is the meaning of this if it is a bitfield? */ i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; tfree(p); if( i <= 0 ) werror( "sizeof returns 0" ); return( bcon( i ) ); }# ifndef BUG2eprint( p, down, a, b ) register NODE *p; int *a, *b; { register ty; *a = *b = down+1; while( down > 1 ){ printf( "\t" ); down -= 2; } if( down ) printf( " " ); ty = optype( p->in.op ); printf("%o) %s, ", p, opst[p->in.op] ); if( ty == LTYPE ){ printf( CONFMT, p->tn.lval ); printf( ", %d, ", p->tn.rval ); } tprint( p->in.type ); printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); }# endifprtdcon( p ) register NODE *p; { int i; int o = p->in.op; /* print floating point constant, make a distingtion between * single precision and double precision floating point vdp009 */ if( o == FCON || o ==DCON ){ locctr( DATA ); defalign( o == DCON ? ALDOUBLE : ALFLOAT ); deflab( i = getlab() ); if (o == FCON) fincode( p->fpn.fval, SZFLOAT ); else fincode( p->dpn.dval, SZDOUBLE ); p->tn.lval = 0; p->tn.rval = -i; p->in.type = (o == DCON ? DOUBLE : FLOAT); p->in.op = NAME; } }int edebug = 0;ecomp( p ) register NODE *p; {# ifndef BUG2 if( edebug ) fwalk( p, eprint, 0 );# endif if( !reached ){ werror( "statement not reached" ); reached = 1; } p = optim(p); walkf( p, prtdcon ); locctr( PROG ); ecode( p ); tfree(p); }# ifdef STDPRTREE# ifndef ONEPASSprtree(p) register NODE *p; { register struct symtab *q; register ty;# ifdef MYPRTREE MYPRTREE(p); /* local action can be taken here; then return... */#endif ty = optype(p->in.op); printf( "%d\t", p->in.op ); if( ty == LTYPE ) { printf( CONFMT, p->tn.lval ); printf( "\t" ); } if( ty != BITYPE ) { if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); else printf( "%d\t", p->tn.rval ); } printf( "%o\t", p->in.type ); /* handle special cases */ switch( p->in.op ){ case NAME: case ICON: /* print external name */ if( p->tn.rval == NONAME ) printf( "\n" ); else if( p->tn.rval >= 0 ){ q = &stab[p->tn.rval]; printf( "%s\n", exname(q->sname) ); } else { /* label */ printf( LABFMT, -p->tn.rval ); } break; case STARG: case STASG: case STCALL: case UNARY STCALL: /* print out size */ /* use lhs size, in order to avoid hassles with the structure `.' operator */ /* note: p->in.left not a field... */ printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); break; default: printf( "\n" ); } if( ty != LTYPE ) prtree( p->in.left ); if( ty == BITYPE ) prtree( p->in.right ); }# elsep2tree(p) register NODE *p; { register ty;# ifdef MYP2TREE MYP2TREE(p); /* local action can be taken here; then return... */# endif ty = optype(p->in.op); switch( p->in.op ){ case NAME: case ICON:#ifndef FLEXNAMES if( p->tn.rval == NONAME ) p->in.name[0] = '\0';#else if( p->tn.rval == NONAME ) p->in.name = "";#endif else if( p->tn.rval >= 0 ){ /* copy name from exname */ register char *cp; register i; cp = exname( stab[p->tn.rval].sname );#ifndef FLEXNAMES for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;#else p->in.name = tstr(cp);#endif }#ifndef FLEXNAMES else sprintf( p->in.name, LABFMT, -p->tn.rval );#else else { char temp[32]; sprintf( temp, LABFMT, -p->tn.rval ); p->in.name = tstr(temp); }#endif break; case STARG: case STASG: case STCALL: case UNARY STCALL: /* set up size parameters */ p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; break; case REG: rbusy( p->tn.rval, p->in.type ); default:#ifndef FLEXNAMES p->in.name[0] = '\0';#else p->in.name = "";#endif } p->in.rall = NOPREF; if( ty != LTYPE ) p2tree( p->in.left ); if( ty == BITYPE ) p2tree( p->in.right ); }# endif# endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -