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

📄 op.c

📁 一个c语言写做的编译器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    }

abort:
    release_value( v2 );			/* discard the other value */
    return v1;
}

/*----------------------------------------------------------------------*/

PRIVATE int make_types_match( v1p, v2p )
value	**v1p, **v2p;
{
    /* Takes care of type conversion. If the types are the same, do nothing;
     * otherwise, apply the standard type-conversion rules to the smaller
     * of the two operands. Return 1 on success or if the objects started out
     * the same type. Return 0 (and don't do any conversions) if either operand
     * is a pointer and the operands aren't the same type.
     */

    value *v1 = *v1p;
    value *v2 = *v2p;

    link  *t1 = v1->type;
    link  *t2 = v2->type;

    if( the_same_type(t1, t2, 0)  &&  !IS_CHAR(t1) )
	return 1;

    if( IS_POINTER(t1) || IS_POINTER(t2) )
	return 0;

    if( IS_CHAR(t1) ) { v1 = tmp_gen(t1, v1);  t1 = v1->type; }
    if( IS_CHAR(t2) ) { v2 = tmp_gen(t2, v2);  t2 = v2->type; }

    if( IS_ULONG(t1) && !IS_ULONG(t2) )
    {
	if( IS_LONG(t2) )
	    v2->type->UNSIGNED = 1;
	else
	    v2 = tmp_gen( t1, v2 );
    }
    else if( !IS_ULONG(t1) && IS_ULONG(t2) )
    {
	if( IS_LONG(t1) )
	    v1->type->UNSIGNED = 1;
	else
	    v1 = tmp_gen( v2->type, v1 );
    }
    else if(  IS_LONG(t1) && !IS_LONG(t2) ) v2 = tmp_gen (t1, v2);
    else if( !IS_LONG(t1) &&  IS_LONG(t2) ) v1 = tmp_gen (t2, v1);
    else if(  IS_UINT(t1) && !IS_UINT(t2) ) v2->type->UNSIGNED = 1;
    else if( !IS_UINT(t1) &&  IS_UINT(t2) ) v1->type->UNSIGNED = 1;

    /* else they're both normal ints, do nothing */

    *v1p = v1;
    *v2p = v2;
    return 1;
}
value	*binary_op( v1, op, v2 )
value	*v1;
int	op;
value	*v2;
{
    char *str_op ;
    int  commutative = 0;	/* operator is commutative */

    if( do_binary_const( &v1, op, &v2 ) )
    {
	release_value( v2 );
	return v1;
    }

    v1 = gen_rvalue( v1 );
    v2 = gen_rvalue( v2 );

    if( !make_types_match( &v1, &v2 ) )
	yyerror("%c%c: Illegal type conversion\n",
					(op=='>' || op =='<') ? op : ' ', op);
    else
    {
	switch( op )
	{
	case '*':
	case '&':
	case '|':
	case '^':   commutative = 1;
	case '/':
	case '%':
	case '<':						/* << */
	case '>':						/* >> */
		    dst_opt( &v1, &v2, commutative );

		    if( op == '<' )
			str_op = "<<=" ;
		    else if( op == '>' )
			str_op = IS_UNSIGNED(v1->type) ? ">L=" : ">>=" ;
		    else
		    {
			str_op = "X=";
			*str_op = op ;
		    }

		    gen( str_op, v1->name, v2->name );
		    break;
	}
    }
    release_value( v2 );
    return v1;
}

/*----------------------------------------------------------------------*/

PRIVATE int	do_binary_const( v1p, op, v2p )
value	**v1p;
int	op;
value	**v2p;
{
    /* If both operands are constants, do the arithmetic. On exit, *v1p
     * is modified to point at the longer of the two incoming types
     * and the result will be in the last link of *v1p's type chain.
     */

    long  x;
    link  *t1 = (*v1p)->type ;
    link  *t2 = (*v2p)->type ;
    value *tmp;

    /* Note that this code assumes that all fields in the union start at the
     * same address.
     */

    if( IS_CONSTANT(t1) && IS_CONSTANT(t2) )
    {
	if( IS_INT(t1) && IS_INT(t2) )
	{
	    switch( op )
	    {
	    case '+':	t1->V_INT +=  t2->V_INT;	break;
	    case '-':	t1->V_INT -=  t2->V_INT;	break;
	    case '*':	t1->V_INT *=  t2->V_INT;	break;
	    case '&':	t1->V_INT &=  t2->V_INT;	break;
	    case '|':	t1->V_INT |=  t2->V_INT;	break;
	    case '^':	t1->V_INT ^=  t2->V_INT;	break;
	    case '/':	t1->V_INT /=  t2->V_INT;	break;
	    case '%':	t1->V_INT %=  t2->V_INT;	break;
	    case '<':	t1->V_INT <<= t2->V_INT;	break;

	    case '>':	if( IS_UNSIGNED(t1) ) t1->V_UINT >>= t2->V_INT;

			else		      t1->V_INT  >>= t2->V_INT;

			break;
	    }
	    return 1;
	}
	else if( IS_LONG(t1) && IS_LONG(t2) )
	{
	    switch( op )
	    {
	    case '+':	t1->V_LONG +=  t2->V_LONG;	break;
	    case '-':	t1->V_LONG -=  t2->V_LONG;	break;
	    case '*':	t1->V_LONG *=  t2->V_LONG;	break;
	    case '&':	t1->V_LONG &=  t2->V_LONG;	break;
	    case '|':	t1->V_LONG |=  t2->V_LONG;	break;
	    case '^':	t1->V_LONG ^=  t2->V_LONG;	break;
	    case '/':	t1->V_LONG /=  t2->V_LONG;	break;
	    case '%':	t1->V_LONG %=  t2->V_LONG;	break;
	    case '<':	t1->V_LONG <<= t2->V_LONG;	break;

	    case '>':	if( IS_UNSIGNED(t1) ) t1->V_ULONG >>= t2->V_LONG;
			else		      t1->V_LONG  >>= t2->V_LONG;
			break;
	    }
	    return 1;
	}
	else if( IS_LONG(t1) && IS_INT(t2) )
	{
	    switch( op )
	    {
	    case '+':	t1->V_LONG +=  t2->V_INT;	break;
	    case '-':	t1->V_LONG -=  t2->V_INT;	break;
	    case '*':	t1->V_LONG *=  t2->V_INT;	break;
	    case '&':	t1->V_LONG &=  t2->V_INT;	break;
	    case '|':	t1->V_LONG |=  t2->V_INT;	break;
	    case '^':	t1->V_LONG ^=  t2->V_INT;	break;
	    case '/':	t1->V_LONG /=  t2->V_INT;	break;
	    case '%':	t1->V_LONG %=  t2->V_INT;	break;
	    case '<':	t1->V_LONG <<= t2->V_INT;	break;

	    case '>':	if( IS_UNSIGNED(t1) ) t1->V_ULONG >>= t2->V_INT;
			else		      t1->V_LONG  >>= t2->V_INT;
			break;
	    }
	    return 1;
	}
	else if( IS_INT(t1) && IS_LONG(t2) )
	{
	    /* Avoid commutativity problems by doing the arithmetic first,
	     * then swapping the operand values.
	     */

	    switch( op )
	    {

	    case '+':	x = t1->V_INT +  t2->V_LONG;

	    case '-':	x = t1->V_INT -  t2->V_LONG;

	    case '*':	x = t1->V_INT *  t2->V_LONG;

	    case '&':	x = t1->V_INT &  t2->V_LONG;

	    case '|':	x = t1->V_INT |  t2->V_LONG;

	    case '^':	x = t1->V_INT ^  t2->V_LONG;

	    case '/':	x = t1->V_INT /  t2->V_LONG;

	    case '%':	x = t1->V_INT %  t2->V_LONG;

	    case '<':	x = t1->V_INT << t2->V_LONG;

	    case '>':	if( IS_UINT(t1) ) x = t1->V_UINT >> t2->V_LONG;

			else              x = t1->V_INT  >> t2->V_LONG;
			break;
	    }

	    t2->V_LONG = x;	/* Modify v1 to point at the larger   */
	    tmp  = *v1p ;	/* operand by swapping *v1p and *v2p. */
	    *v1p = *v2p ;
	    *v2p = tmp  ;
	    return 1;
	}
    }
    return 0;
}
/*----------------------------------------------------------------------*/

PRIVATE void	dst_opt( leftp, rightp, commutative )
value	**leftp;
value	**rightp;
int	commutative;
{
    /* Optimizes various sources and destination as follows:
     *
     * operation is not commutative:
     *		if *left is a temporary:  do nothing
     *		else:   		   create a temporary and
     *					   initialize it to *left,
     *					   freeing *left
     *					   *left = new temporary
     * operation is commutative:
     *		if *left is a temporary	   do nothing
     *	   else if *right is a temporary   swap *left and *right
     *     else			           precede as if commutative.
     */

    value  *tmp;

    if( ! (*leftp)->is_tmp )
    {
	if( commutative && (*rightp)->is_tmp )
	{
	    tmp     = *leftp;
	    *leftp  = *rightp;
	    *rightp = tmp;
	}
	else
	    *leftp = tmp_gen( (*leftp)->type, *leftp );
    }
}
value	*plus_minus( v1, op, v2 )
value	*v1;
int	op;
value	*v2;
{
    value *tmp;
    int   v1_is_ptr;
    int   v2_is_ptr;
    char  *scratch;
    char  *gen_op;

    gen_op    = (op == '+') ? "+=" : "-=";
    v1	      = gen_rvalue( v1 );
    v2	      = gen_rvalue( v2 );
    v2_is_ptr = IS_POINTER(v2->type);
    v1_is_ptr = IS_POINTER(v1->type);

    /* First, get all the error checking out of the way and return if
     * an error is detected.
     */

    if( v1_is_ptr && v2_is_ptr )
    {
	if( op == '+' || !the_same_type(v1->type, v2->type, 1) )
	{
	    yyerror( "Illegal types (%c)\n", op );
	    release_value( v2 );
	    return v1;
	}
    }
    else if( !v1_is_ptr && v2_is_ptr )
    {
	yyerror( "%c: left operand must be pointer", op );
	release_value( v1 );
	return v2;
    }

    /* Now do the work. At this point one of the following cases exist:
     *
     *     v1:    op:   v2:
     *    number [+-] number
     *     ptr   [+-] number
     *     ptr    -    ptr		(types must match)
     */

    if( !(v1_is_ptr || v2_is_ptr) )		/* normal arithmetic */
    {
	if( !do_binary_const( &v1, op, &v2 ) )
	{
	    make_types_match( &v1, &v2 );
	    dst_opt( &v1, &v2, op == '+' );
	    gen( gen_op, v1->name, v2->name );
	}
	release_value( v2 );
	return v1;
    }
    else
    {
	if( v1_is_ptr && v2_is_ptr )		 /* ptr-ptr */
	{
	    if( !v1->is_tmp )
		v1 = tmp_gen( v1->type, v1 );

	    gen( gen_op, v1->name, v2->name );

	    if( IS_AGGREGATE(  v1->type->next ) )
		gen( "/=%s%d", v1->name, get_sizeof(v1->type->next) );
	}
	else if( !IS_AGGREGATE( v1->type->next ) )
	{
					   /* ptr_to_nonaggregate [+-] number */
	    if( !v1->is_tmp )
		v1 = tmp_gen( v1->type, v1 );

	    gen( gen_op, v1->name, v2->name );
	}
	else				    /* ptr_to_aggregate [+-] number */
	{				    /* do pointer arithmetic        */

	    scratch = IS_LONG(v2->type) ? "r0.l" : "r0.w.low" ;

	    gen( "=",      "r1.pp", v1->name			);
	    gen( "=",      scratch, v2->name			);
	    gen( "*=%s%d", scratch, get_sizeof(v1->type->next)	);
	    gen( gen_op,   "r1.pp", scratch			);

	    if( !v1->is_tmp )
	    {
		tmp = tmp_create( v1->type, 0 );
		release_value( v1 );
		v1 = tmp;
	    }

	    gen( "=", v1->name, "r1.pp" );
	}
    }
    release_value( v2 );
    return v1;
}
rlabel( incr )			/* Return the numeric component of the next */
int incr;			/* return label, postincrementing it by one */
{				/* if incr is true.			    */
    static int num;
    return incr ? num++ : num;
}

⌨️ 快捷键说明

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