⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rval.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
#		endif PC	/*	 * Unary plus and minus	 */	case T_PLUS:	case T_MINUS:		q = rvalue(r->un_expr.expr, NLNIL , RREQ );		if (q == NLNIL)			return (NLNIL);		if (isnta(q, "id")) {			error("Operand of %s must be integer or real, not %s", opname, nameof(q));			return (NLNIL);		}		if (r->tag == T_MINUS) {#		    ifdef OBJ			(void) put(1, O_NEG2 + (width(q) >> 2));			return (isa(q, "d") ? q : nl+T4INT);#		    endif OBJ#		    ifdef PC			if (isa(q, "i")) {			    sconv(p2type(q), PCCT_INT);			    putop( PCCOM_UNARY PCC_MINUS, PCCT_INT);			    return nl+T4INT;			}			putop( PCCOM_UNARY PCC_MINUS, PCCT_DOUBLE);			return nl+TDOUBLE;#		    endif PC		}		return (q);	case T_NOT:		q = rvalue(r->un_expr.expr, NLNIL , RREQ );		if (q == NLNIL)			return (NLNIL);		if (isnta(q, "b")) {			error("not must operate on a Boolean, not %s", nameof(q));			return (NLNIL);		}#		ifdef OBJ		    (void) put(1, O_NOT);#		endif OBJ#		ifdef PC		    sconv(p2type(q), PCCT_INT);		    putop( PCC_NOT , PCCT_INT);		    sconv(PCCT_INT, p2type(q));#		endif PC		return (nl+T1BOOL);	case T_AND:	case T_OR:		p = rvalue(r->expr_node.lhs, NLNIL , RREQ );#		ifdef PC		    sconv(p2type(p),PCCT_INT);#		endif PC		p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );#		ifdef PC		    sconv(p2type(p1),PCCT_INT);#		endif PC		if (p == NLNIL || p1 == NLNIL)			return (NLNIL);		if (isnta(p, "b")) {			error("Left operand of %s must be Boolean, not %s", opname, nameof(p));			return (NLNIL);		}		if (isnta(p1, "b")) {			error("Right operand of %s must be Boolean, not %s", opname, nameof(p1));			return (NLNIL);		}#		ifdef OBJ		    (void) put(1, r->tag == T_AND ? O_AND : O_OR);#		endif OBJ#		ifdef PC			/*			 * note the use of & and | rather than && and ||			 * to force evaluation of all the expressions.			 */		    putop( r->tag == T_AND ? PCC_AND : PCC_OR , PCCT_INT );		    sconv(PCCT_INT, p2type(p));#		endif PC		return (nl+T1BOOL);	case T_DIVD:#		ifdef OBJ		    p = rvalue(r->expr_node.lhs, NLNIL , RREQ );		    p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );#		endif OBJ#		ifdef PC			/*			 *	force these to be doubles for the divide			 */		    p = rvalue( r->expr_node.lhs , NLNIL , RREQ );		    sconv(p2type(p), PCCT_DOUBLE);		    p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ );		    sconv(p2type(p1), PCCT_DOUBLE);#		endif PC		if (p == NLNIL || p1 == NLNIL)			return (NLNIL);		if (isnta(p, "id")) {			error("Left operand of / must be integer or real, not %s", nameof(p));			return (NLNIL);		}		if (isnta(p1, "id")) {			error("Right operand of / must be integer or real, not %s", nameof(p1));			return (NLNIL);		}#		ifdef OBJ		    return gen(NIL, r->tag, width(p), width(p1));#		endif OBJ#		ifdef PC		    putop( PCC_DIV , PCCT_DOUBLE );		    return nl + TDOUBLE;#		endif PC	case T_MULT:	case T_ADD:	case T_SUB:#		ifdef OBJ		    /*		     * get the type of the right hand side.		     * if it turns out to be a set,		     * use that type when getting		     * the type of the left hand side.		     * and then use the type of the left hand side		     * when generating code.		     * this will correctly decide the type of any		     * empty sets in the tree, since if the empty set 		     * is on the left hand side it will inherit		     * the type of the right hand side,		     * and if it's on the right hand side, its type (intset)		     * will be overridden by the type of the left hand side.		     * this is an awful lot of tree traversing, 		     * but it works.		     */		    codeoff();		    p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ );		    codeon();		    if ( p1 == NLNIL ) {			return NLNIL;		    }		    if (isa(p1, "t")) {			codeoff();			contype = rvalue(r->expr_node.lhs, p1, RREQ);			codeon();			if (contype == NLNIL) {			    return NLNIL;			}		    }		    p = rvalue( r->expr_node.lhs , contype , RREQ );		    p1 = rvalue( r->expr_node.rhs , p , RREQ );		    if ( p == NLNIL || p1 == NLNIL )			    return NLNIL;		    if (isa(p, "id") && isa(p1, "id"))			return (gen(NIL, r->tag, width(p), width(p1)));		    if (isa(p, "t") && isa(p1, "t")) {			    if (p != p1) {				    error("Set types of operands of %s must be identical", opname);				    return (NLNIL);			    }			    (void) gen(TSET, r->tag, width(p), 0);			    return (p);		    }#		endif OBJ#		ifdef PC			/*			 * the second pass can't do			 *	long op double  or  double op long			 * so we have to know the type of both operands.			 * also, see the note for obj above on determining			 * the type of empty sets.			 */		    codeoff();		    p1 = rvalue(r->expr_node.rhs, NLNIL, RREQ);		    codeon();		    if ( isa( p1 , "id" ) ) {			p = rvalue( r->expr_node.lhs , contype , RREQ );			if ( ( p == NLNIL ) || ( p1 == NLNIL ) ) {			    return NLNIL;			}			tuac(p, p1, &rettype, (int *) (&ctype));			p1 = rvalue( r->expr_node.rhs , contype , RREQ );			tuac(p1, p, &rettype, (int *) (&ctype));			if ( isa( p , "id" ) ) {			    putop( (int) mathop[r->tag - T_MULT], (int) ctype);			    return rettype;			}		    }		    if ( isa( p1 , "t" ) ) {			putleaf( PCC_ICON , 0 , 0			    , PCCM_ADDTYPE( PCCM_ADDTYPE( PCCTM_PTR | PCCT_STRTY , PCCTM_FTN )					, PCCTM_PTR )			    , setop[ r->tag - T_MULT ] );			codeoff();			contype = rvalue( r->expr_node.lhs, p1 , LREQ );			codeon();			if ( contype == NLNIL ) {			    return NLNIL;			}			    /*			     *	allocate a temporary and use it			     */			tempnlp = tmpalloc(lwidth(contype), contype, NOREG);			putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,				tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY );			p = rvalue( r->expr_node.lhs , contype , LREQ );			if ( isa( p , "t" ) ) {			    putop( PCC_CM , PCCT_INT );			    if ( p == NLNIL || p1 == NLNIL ) {				return NLNIL;			    }			    p1 = rvalue( r->expr_node.rhs , p , LREQ );			    if ( p != p1 ) {				error("Set types of operands of %s must be identical", opname);				return NLNIL;			    }			    putop( PCC_CM , PCCT_INT );			    putleaf( PCC_ICON , (int) (lwidth(p1)) / sizeof( long ) , 0				    , PCCT_INT , (char *) 0 );			    putop( PCC_CM , PCCT_INT );			    putop( PCC_CALL , PCCTM_PTR | PCCT_STRTY );			    return p;			}		    }		    if ( isnta( p1 , "idt" ) ) {			    /*			     *	find type of left operand for error message.			     */			p = rvalue( r->expr_node.lhs , contype , RREQ );		    }			/*			 *	don't give spurious error messages.			 */		    if ( p == NLNIL || p1 == NLNIL ) {			return NLNIL;		    }#		endif PC		if (isnta(p, "idt")) {			error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p));			return (NLNIL);		}		if (isnta(p1, "idt")) {			error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1));			return (NLNIL);		}		error("Cannot mix sets with integers and reals as operands of %s", opname);		return (NLNIL);	case T_MOD:	case T_DIV:		p = rvalue(r->expr_node.lhs, NLNIL , RREQ );#		ifdef PC		    sconv(p2type(p), PCCT_INT);#		ifdef tahoe		    /* prepare for ediv workaround, see below. */		    if (r->tag == T_MOD) {			(void) rvalue(r->expr_node.lhs, NLNIL, RREQ);			sconv(p2type(p), PCCT_INT);		    }#		endif tahoe#		endif PC		p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );#		ifdef PC		    sconv(p2type(p1), PCCT_INT);#		endif PC		if (p == NLNIL || p1 == NLNIL)			return (NLNIL);		if (isnta(p, "i")) {			error("Left operand of %s must be integer, not %s", opname, nameof(p));			return (NLNIL);		}		if (isnta(p1, "i")) {			error("Right operand of %s must be integer, not %s", opname, nameof(p1));			return (NLNIL);		}#		ifdef OBJ		    return (gen(NIL, r->tag, width(p), width(p1)));#		endif OBJ#		ifdef PC#		ifndef tahoe		    putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT );		    return ( nl + T4INT );#		else tahoe		    putop( PCC_DIV , PCCT_INT );		    if (r->tag == T_MOD) {		    /*		     * avoid f1 bug: PCC_MOD would generate an 'ediv',		     * which would reuire too many registers to evaluate		     * things like		     * var i:boolean;j:integer; i := (j+1) = (j mod 2);		     * so, instead of		     *                PCC_MOD		     *		        / \		     *	               p   p1		     * we put		     *                  PCC_MINUS		     *                    /   \		     *			 p   PCC_MUL               		     *			      /   \		     *			  PCC_DIV  p1		     *                      / \		     *                     p  p1		     *		     * we already have put p, p, p1, PCC_DIV. and now...		     */			    rvalue(r->expr_node.rhs, NLNIL , RREQ );			    sconv(p2type(p1), PCCT_INT);			    putop( PCC_MUL, PCCT_INT );			    putop( PCC_MINUS, PCCT_INT );		    }		    return ( nl + T4INT );#		endif tahoe#		endif PC	case T_EQ:	case T_NE:	case T_LT:	case T_GT:	case T_LE:	case T_GE:		/*		 * Since there can be no, a priori, knowledge		 * of the context type should a constant string		 * or set arise, we must poke around to find such		 * a type if possible.  Since constant strings can		 * always masquerade as identifiers, this is always		 * necessary.		 * see the note in the obj section of case T_MULT above		 * for the determination of the base type of empty sets.		 */		codeoff();		p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );		codeon();		if (p1 == NLNIL)			return (NLNIL);		contype = p1;#		ifdef OBJ		    if (p1->class == STR) {			    /*			     * For constant strings we want			     * the longest type so as to be			     * able to do padding (more importantly			     * avoiding truncation). For clarity,			     * we get this length here.			     */			    codeoff();			    p = rvalue(r->expr_node.lhs, NLNIL , RREQ );			    codeon();			    if (p == NLNIL)				    return (NLNIL);			    if (width(p) > width(p1))				    contype = p;		    }		    if (isa(p1, "t")) {			codeoff();			contype = rvalue(r->expr_node.lhs, p1, RREQ);			codeon();			if (contype == NLNIL) {			    return NLNIL;			}		    }		    /*		     * Now we generate code for		     * the operands of the relational		     * operation.		     */		    p = rvalue(r->expr_node.lhs, contype , RREQ );		    if (p == NLNIL)			    return (NLNIL);		    p1 = rvalue(r->expr_node.rhs, p , RREQ );		    if (p1 == NLNIL)			    return (NLNIL);#		endif OBJ#		ifdef PC		    c1 = classify( p1 );		    if ( c1 == TSET || c1 == TSTR || c1 == TREC ) {			putleaf( PCC_ICON , 0 , 0				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )				, c1 == TSET  ? relts[ r->tag - T_EQ ]					      : relss[ r->tag - T_EQ ] );			    /*			     *	for [] and strings, comparisons are done on			     *	the maximum width of the two sides.			     *	for other sets, we have to ask the left side			     *	what type it is based on the type of the right.			     *	(this matters for intsets).			     */			if ( c1 == TSTR ) {			    codeoff();			    p = rvalue( r->expr_node.lhs , NLNIL , LREQ );			    codeon();			    if ( p == NLNIL ) {				return NLNIL;			    }			    if ( lwidth( p ) > lwidth( p1 ) ) {				contype = p;			    }			} else if ( c1 == TSET ) {			    codeoff();			    contype = rvalue(r->expr_node.lhs, p1, LREQ);			    codeon();			    if (contype == NLNIL) {				return NLNIL;			    }			} 			    /*			     *	put out the width of the comparison.			     */			putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0);			    /*			     *	and the left hand side,			     *	for sets, strings, records			     */			p = rvalue( r->expr_node.lhs , contype , LREQ );			if ( p == NLNIL ) {			    return NLNIL;			}			putop( PCC_CM , PCCT_INT );			p1 = rvalue( r->expr_node.rhs , p , LREQ );			if ( p1 == NLNIL ) {			    return NLNIL;			}			putop( PCC_CM , PCCT_INT );			putop( PCC_CALL , PCCT_INT );		    } else {			    /*			     *	the easy (scalar or error) case

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -