📄 trees.c
字号:
# include "mfile1"/* some special actions, used in finding the type of nodes */# define NCVT 01# define PUN 02# define TYPL 04# define TYPR 010# define TYMATCH 040# define LVAL 0100# define CVTO 0200# define CVTL 0400# define CVTR 01000# define PTMATCH 02000# define OTHER 04000# define NCVTR 010000/* node conventions: NAME: rval>0 is stab index for external rval<0 is -inlabel number lval is offset in bits ICON: lval has the value rval has the STAB index, or - label number, if a name whose address is in the constant rval = NONAME means no name REG: rval is reg. identification cookie */int bdebug = 0;NODE *buildtree( o, l, r ) register NODE *l, *r; { register NODE *p, *q; register actions; register opty; register struct symtab *sp; register NODE *lr, *ll; int i; extern int eprint(); if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); opty = optype(o); /* check for constants */ if( opty == UTYPE && l->op == ICON ){ switch( o ){ case NOT: if( hflag ) werror( "constant argument to NOT" ); case UNARY MINUS: case COMPL: if( conval( l, o, l ) ) return(l); break; } } else if( o==UNARY MINUS && l->op==FCON ){ l->dval = -l->dval; return(l); } else if( o==QUEST && l->op==ICON ) { l->op = FREE; r->op = FREE; if( l->lval ){ tfree( r->right ); return( r->left ); } else { tfree( r->left ); return( r->right ); } } else if( (o==ANDAND || o==OROR) && (l->op==ICON||r->op==ICON) ) goto ccwarn; else if( opty == BITYPE && l->op == ICON && r->op == ICON ){ switch( o ){ case ULT: case UGT: case ULE: case UGE: case LT: case GT: case LE: case GE: case EQ: case NE: case ANDAND: case OROR: case CBRANCH: ccwarn: if( hflag ) werror( "constant in conditional context" ); case PLUS: case MINUS: case MUL: case DIV: case MOD: case AND: case OR: case ER: case LS: case RS: if( conval( l, o, r ) ) { r->op = FREE; return(l); } break; } } else if( opty == BITYPE && (l->op==FCON||l->op==ICON) && (r->op==FCON||r->op==ICON) ){ switch(o){ case PLUS: case MINUS: case MUL: case DIV: if( l->op == ICON ){ l->dval = l->lval; } if( r->op == ICON ){ r->dval = r->lval; } l->op = FCON; l->type = l->csiz = DOUBLE; r->op = FREE; switch(o){ case PLUS: l->dval += r->dval; return(l); case MINUS: l->dval -= r->dval; return(l); case MUL: l->dval *= r->dval; return(l); case DIV: if( r->dval == 0 ) uerror( "division by 0." ); else l->dval /= r->dval; return(l); } } } /* its real; we must make a new node */ p = block( o, l, r, INT, 0, INT ); actions = opact(p); if( actions&LVAL ){ /* check left descendent */ if( notlval(p->left) ) { uerror( "lvalue required" ); } } if( actions & NCVTR ){ p->left = pconvert( p->left ); } else if( !(actions & NCVT ) ){ switch( opty ){ case BITYPE: p->right = pconvert( p->right ); case UTYPE: p->left = pconvert( p->left ); } } if( (actions&PUN) && (o!=CAST||cflag) ){ chkpun(p); } if( actions & (TYPL|TYPR) ){ q = (actions&TYPL) ? p->left : p->right; p->type = q->type; p->cdim = q->cdim; p->csiz = q->csiz; } if( actions & CVTL ) p = convert( p, CVTL ); if( actions & CVTR ) p = convert( p, CVTR ); if( actions & TYMATCH ) p = tymatch(p); if( actions & PTMATCH ) p = ptmatch(p); if( actions & OTHER ){ l = p->left; r = p->right; switch(o){ case NAME: sp = &stab[idname]; if( sp->stype == UNDEF ){ uerror( "%.8s undefined", sp->sname ); /* make p look reasonable */ p->type = p->cdim = p->csiz = INT; p->rval = idname; p->lval = 0; defid( p, SNULL ); break; } p->type = sp->stype; p->cdim = sp->dimoff; p->csiz = sp->sizoff; p->lval = 0; p->rval = idname; /* special case: MOETY is really an ICON... */ if( p->type == MOETY ){ p->rval = NONAME; p->lval = sp->offset; p->cdim = 0; p->type = ENUMTY; p->op = ICON; } break; case ICON: p->type = INT; p->cdim = 0; p->csiz = INT; break; case STRING: p->op = NAME; p->type = CHAR+ARY; p->lval = 0; p->rval = NOLAB; p->cdim = curdim; p->csiz = CHAR; break; case FCON: p->lval = 0; p->rval = 0; p->type = DOUBLE; p->cdim = 0; p->csiz = DOUBLE; break; case STREF: /* p->x turned into *(p+offset) */ /* rhs must be a name; check correctness */ i = r->rval; if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ uerror( "member of structure or union required" ); } else { register j; if( l->type != PTR+STRTY && l->type != PTR+UNIONTY ){ werror( "struct/union or struct/union pointer required" ); } else if( (j=l->csiz+1)<0 ) cerror( "undefined structure or union" ); else if( !chkstr( i, dimtab[j], DECREF(l->type) ) ){ werror( "illegal member use: %.8s", stab[i].sname ); } } p = stref( p ); break; case UNARY MUL: if( l->op == UNARY AND ){ p->op = l->op = FREE; p = l->left; } if( !ISPTR(l->type))uerror("illegal indirection"); p->type = DECREF(l->type); p->cdim = l->cdim; p->csiz = l->csiz; break; case UNARY AND: switch( l->op ){ case UNARY MUL: p->op = l->op = FREE; p = l->left; case NAME: p->type = INCREF( l->type ); p->cdim = l->cdim; p->csiz = l->csiz; break; case COMOP: lr = buildtree( UNARY AND, l->right, NIL ); p->op = l->op = FREE; p = buildtree( COMOP, l->left, lr ); break; case QUEST: lr = buildtree( UNARY AND, l->right->right, NIL ); ll = buildtree( UNARY AND, l->right->left, NIL ); p->op = l->op = l->right->op = FREE; p = buildtree( QUEST, l->left, buildtree( COLON, ll, lr ) ); break; default: uerror( "unacceptable operand of &" ); break; } break; case LS: case RS: case ASG LS: case ASG RS: if(tsize(p->right->type, p->right->cdim, p->right->csiz) > SZINT) p->right = makety(p->right, INT, 0, INT ); break; case RETURN: case ASSIGN: case CAST: /* structure assignment */ /* take the addresses of the two sides; then make an /* operator using STASG and /* the addresses of left and right */ { register TWORD t; register d, s; if( l->csiz != r->csiz ) uerror( "assignment of different structures" ); r = buildtree( UNARY AND, r, NIL ); t = r->type; d = r->cdim; s = r->csiz; l = block( STASG, l, r, t, d, s ); if( o == RETURN ){ p->op = FREE; p = l; break; } p->op = UNARY MUL; p->left = l; p->right = NIL; break; } case COLON: /* structure colon */ if( l->csiz != r->csiz ) uerror( "type clash in conditional" ); break; case CALL: p->right = r = strargs( p->right ); case UNARY CALL: if( !ISPTR(l->type)) uerror("illegal function"); p->type = DECREF(l->type); if( !ISFTN(p->type)) uerror("illegal function"); p->type = DECREF( p->type ); p->cdim = l->cdim; p->csiz = l->csiz; if( l->op == UNARY AND && l->left->op == NAME && l->left->rval >= 0 && l->left->rval != NONAME && ( (i=stab[l->left->rval].sclass) == FORTRAN || i==UFORTRAN ) ){ p->op += (FORTCALL-CALL); } if( p->type == STRTY || p->type == UNIONTY ){ /* function returning structure */ /* make function really return ptr to str., with * */ p->op += STCALL-CALL; p->type = INCREF( p->type ); p = buildtree( UNARY MUL, p, NIL ); } break; default: cerror( "other code %d", o ); } } if( actions & CVTO ) p = oconvert(p); p = clocal(p); if( bdebug ) fwalk( p, eprint, 0 ); return(p); }NODE *strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */ if( p->op == CM ){ p->left = strargs( p->left ); p->right = strargs( p->right ); return( p ); } if( p->type == STRTY || p->type == UNIONTY ){ p = block( STARG, p, NIL, p->type, p->cdim, p->csiz ); p->left = buildtree( UNARY AND, p->left, NIL ); p = clocal(p); } return( p ); }chkstr( i, j, type ) TWORD type; { /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ /* i has been checked to contain a MOS or MOU */ /* j is the index in dimtab of the members... */ int k, kk; extern int ddebug; if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); if( (k = j) < 0 ) uerror( "undefined structure or union" ); else { for( ; (kk = dimtab[k] ) >= 0; ++k ){ if( kk >= SYMTSZ ){ cerror( "gummy structure" ); return(1); } if( kk == i ) return( 1 ); switch( stab[kk].stype ){ case STRTY: case UNIONTY: if( type == STRTY ) continue; /* no recursive looking for strs */ if( chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ) return(1); } } } return( 0 ); }conval( p, o, q ) register NODE *p, *q; { /* apply the op o to the lval part of p; if binary, rhs is val */ int i, u; CONSZ val; val = q->lval; u = ISUNSIGNED(p->type) || ISUNSIGNED(q->type); if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); if( p->rval != NONAME && q->rval != NONAME ) return(0); if( q->rval != NONAME && o!=PLUS ) return(0); if( p->rval != NONAME && o!=PLUS && o!=MINUS ) return(0); switch( o ){ case PLUS: p->lval += val; if( p->rval == NONAME ){ p->rval = q->rval; p->type = q->type; } break; case MINUS: p->lval -= val; break; case MUL: p->lval *= val; break; case DIV: if( val == 0 ) uerror( "division by 0" ); else p->lval /= val; break; case MOD: if( val == 0 ) uerror( "division by 0" ); else p->lval %= val; break; case AND: p->lval &= val; break; case OR: p->lval |= val; break; case ER: p->lval ^= val; break; case LS: i = val; p->lval = p->lval << i; break; case RS: i = val; p->lval = p->lval >> i; break; case UNARY MINUS: p->lval = - p->lval; break; case COMPL: p->lval = ~p->lval; break; case NOT: p->lval = !p->lval; break; case LT: p->lval = p->lval < val; break; case LE: p->lval = p->lval <= val; break; case GT: p->lval = p->lval > val; break; case GE: p->lval = p->lval >= val; break; case ULT: p->lval = (p->lval-val)<0; break; case ULE: p->lval = (p->lval-val)<=0; break; case UGE: p->lval = (p->lval-val)>=0; break; case UGT: p->lval = (p->lval-val)>0; break; case EQ: p->lval = p->lval == val; break; case NE: p->lval = p->lval != val; break; default: return(0); } return(1); }chkpun(p) register NODE *p; { /* checks p for the existance of a pun */ /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ /* one case is when enumerations are used: this applies only to lint */ /* in the other case, one operand is a pointer, the other integer type */ /* we check that this integer is in fact a constant zero... */ /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ /* this falls out, because the LHS is never 0 */ register NODE *q; register t1, t2; register d1, d2; t1 = p->left->type; t2 = p->right->type; if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ if( logop( p->op ) && p->op != EQ && p->op != NE ) { uerror( "illegal comparison of enums" ); return; } if( t1==ENUMTY && t2==ENUMTY && p->left->csiz==p->right->csiz ) return; werror( "enumeration type clash, operator %s", opst[p->op] ); return; } if( ISPTR(t1) || ISARY(t1) ) q = p->right; else q = p->left; if( !ISPTR(q->type) && !ISARY(q->type) ){ if( q->op != ICON || q->lval != 0 ){ werror( "illegal combination of pointer and integer"); } } else { d1 = p->left->cdim; d2 = p->right->cdim; for( ;; ){ if( t1 == t2 ) {; if( p->left->csiz != p->right->csiz ) { werror( "illegal structure pointer combination" ); } return; } if( ISARY(t1) || ISPTR(t1) ){ if( !ISARY(t2) && !ISPTR(t2) ) break; if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ werror( "illegal array size combination" ); return; } if( ISARY(t1) ) ++d1; if( ISARY(t2) ) ++d2; } else break; t1 = DECREF(t1); t2 = DECREF(t2); } werror( "illegal pointer combination" ); } }NODE *stref( p ) register NODE *p; { TWORD t; int d, s, dsc; OFFSZ off; register struct symtab *q; /* make p->x */ /* this is also used to reference automatic variables */ q = &stab[p->right->rval]; p->right->op = FREE; p->op = FREE; p = pconvert( p->left ); /* make p look like ptr to x */ if( !ISPTR(p->type)){ p->type = PTR+UNIONTY; } t = INCREF( q->stype ); d = q->dimoff; s = q->sizoff; p = makety( p, t, d, s ); /* compute the offset to be added */ off = q->offset; dsc = q->sclass; if( dsc & FIELD ){ /* make fields look like ints */ off = (off/ALINT)*ALINT; s = INT; } if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); p = buildtree( UNARY MUL, p, NIL ); /* if field, build field info */ if( dsc & FIELD ){ p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); p->rval = PKFIELD( dsc&FLDSIZ, q->offset%ALINT ); } return( clocal(p) ); }notlval(p) register NODE *p; { /* return 0 if p an lvalue, 1 otherwise */ again: switch( p->op ){ case FLD: p = p->left; goto again; case NAME: case OREG: case UNARY MUL: if( ISARY(p->type) || ISFTN(p->type) ) return(1); case REG: return(0); default: return(1); } }NODE *bcon( i ){ /* make a constant node with value i */ register NODE *p; p = block( ICON, NIL, NIL, INT, 0, INT );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -