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

📄 op.c

📁 一个c语言写做的编译器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    {
	if( !IS_INT(offset->type)  &&  !IS_CHAR(offset->type) )
	    yyerror( "Array index must be an integral type\n" );

	objsize = get_sizeof( ptr->type->next );      /* Size of dereferenced */
						      /* object.	      */

	if( !ptr->is_tmp )			      /* Generate a physical  */
	    ptr = tmp_gen( ptr->type, ptr );	      /* lvalue.              */

	if( IS_CONSTANT( offset->type ) )	      /* Offset is a constant.*/
	{
	    gen("+=%s%d", ptr->name, offset->type->V_INT * objsize );
	}
	else					      /* Offset is not a con- */
	{					      /* stant. Do the arith- */
						      /* metic at run time.   */

	    if( objsize != 1 )			      /* Multiply offset by   */
	    {					      /* size of one object.  */
		if( !offset->is_tmp )
		    offset = tmp_gen( offset->type, offset );

		gen( "*=%s%d", offset->name, objsize );
	    }

	    gen( "+=",  ptr->name, offset->name );    /* Add offset to base. */
	}

	release_value( offset );
    }

    /* The temporary just generated (or the input variable if no temporary
     * was generated) now holds the address of the desired cell. This command
     * must generate an lvalue unless the object pointed to is an aggregate,
     * whereupon it's n rvalue. In any event, you can just label the current
     * cell as an lvalue or rvalue as appropriate and continue. The type must
     * be advanced one notch to compensate for the indirection, however.
     */

    synth	= ptr;
    tmp	  	= ptr->type;			/* Advance type one notch. */
    ptr->type	= ptr->type->next;
    discard_link(tmp);

    if( !IS_AGGREGATE(ptr->type->next) )
	synth->lvalue = 1;		        /* Convert to lvalue.  */

    return synth;
}

value *do_struct( val, op, field_name )
value	*val;
int	op;		/* . or - (the last is for ->)  */
char	*field_name;
{
    symbol	*field;
    link	*lp;

    /* Structure names generate rvalues of type structure. The associated     */
    /* name evaluates to the structure's address, however. Pointers generate  */
    /* lvalues, but are otherwise the same.				      */

    if( IS_POINTER(val->type) )
    {
	if( op != '-' )
	{
	    yyerror("Object to left of -> must be a pointer\n");
	    return val;
	}
	lp	  = val->type;		/* Remove POINTER declarator from  */
	val->type = val->type->next;	/* the type chain and discard it.  */
	discard_link( lp );
    }

    if( !IS_STRUCT(val->type) )
    {
	yyerror("Not a structure.\n");
	return val;
    }				/* Look up the field in the structure table: */

    if( !(field = find_field(val->type->V_STRUCT, field_name)) )
    {
	yyerror("%s not a field\n", field_name );
	return val;
    }

    if( val->lvalue || !val->is_tmp )		/* Generate temporary for     */
	val = tmp_gen( val->type, val );	/* base address if necessary; */
						/* then add the offset to the */
    if( field->level > 0 )			/* desired field.	      */
	gen( "+=%s%d", val->name, field->level );

    if( !IS_AGGREGATE(field->type) )		/* If referenced object isn't */
	val->lvalue = 1;			/* an aggregate, use lvalue.  */

						/* Replace value's type chain */
						/* with type chain for the    */
						/* referenced object:	      */
    lp = val->type;
    if( !(val->type = clone_type( field->type, &val->etype)) )
    {
	yyerror("INTERNAL do_struct: Bad type chain\n" );
	exit(1);
    }
    discard_link_chain( lp );
    access_with( val );	     			/* Change the value's name    */
						/* field to access an object  */
    return val;					/* of the new type.           */
}

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

PRIVATE  symbol *find_field( s, field_name )
structdef	*s;
char		*field_name;
{
    /* Search for "field_name" in the linked list of fields for the input
     * structdef. Return a pointer to the associated "symbol" if the field
     * is there, otherwise return NULL.
     */

    symbol	*sym;
    for( sym = s->fields; sym; sym = sym->next )
    {
	if( !strcmp(field_name, sym->name) )
	    return sym;
    }
    return NULL;
}

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

PRIVATE char	*access_with( val )
value	*val;
{
    /* Modifies the name string in val so that it references the current type.
     * Returns a pointer to the modified string. Only the type part of the
     * name is changed. For example, if the input name is "WP(fp+4)", and the
     * type chain is for an int, the name is be changed to "W(fp+4). If val is
     * an lvalue, prefix an ampersand to the name as well.
     */

    char *p, buf[ VALNAME_MAX ] ;

    strcpy( buf, val->name );
    for( p = buf; *p && *p != '(' /*)*/ ; ++p )		/* find name */
	;

    if( !*p )
	yyerror( "INTERNAL, access_with: missing parenthesis\n" );
    else
	sprintf( val->name, "%s%s%s", val->lvalue ? "&" : "",
						      get_prefix(val->type), p);
    return val->name;
}


PUBLIC value *call( val, nargs )
value *val;
int   nargs;
{
    link   *lp;
    value  *synth;	/* synthesized attribute		*/

    /* The incoming attribute is an lvalue for a function if
     * 		funct()
     * or
     *		int (*p)() = funct;
     *		(*p)();
     *
     * is processed. It's a pointer to a function if p() is used directly.
     * In the case of a logical lvalue (with a leading &), the name will be a
     * function name, and the rvalue can be generated in the normal way by
     * removing the &. In the case of a physical lvalue the name of a variable
     * that holds the function's address is given. No star may be added.
     * If val is an rvalue, then it will never have a leading &.
     */

    if( val->sym  &&  val->sym->implicit  &&  !IS_FUNCT(val->type) )
    {
	/* Implicit symbols are not declared. This must be an implicit function
	 * declaration, so pretend that it's explicit. You have to modify both
	 * the value structure and the original symbol because the type in the
	 * value structure is a copy of the original. Once the modification is
	 * made, the implicit bit can be turned off.
	 */

	lp	    	   = new_link();
	lp->DCL_TYPE 	   = FUNCTION;
	lp->next    	   = val->type;
	val->type   	   = lp;

	lp	    	   = new_link();
	lp->DCL_TYPE 	   = FUNCTION;
	lp->next    	   = val->sym->type;
	val->sym->type 	   = lp;

	val->sym->implicit = 0;
	val->sym->level    = 0;

	yydata( "extern\t%s();\n", val->sym->rname );
    }

    if( !IS_FUNCT(val->type) )
    {
	yyerror( "%s not a function\n", val->name );
	synth = val;
    }
    else
    {
	lp    =  val->type->next;		/* return-value type */
	synth = tmp_create( lp, 0);

	gen( "call", *val->name == '&' ? &val->name[1] : val->name );
	gen(  "=",   synth->name, ret_reg(lp) );

	if( nargs )
	    gen( "+=%s%d" , "sp", nargs * SWIDTH );  /* sp is a byte pointer, */
						     /* so must translate to  */
	release_value( val );			     /* words with "* SWIDTH" */
    }

    return synth;
}

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

char	*ret_reg( p )
link	*p;
{
    /* Return a string representing the register used for a return value of
     * the given type.
     */

    if( IS_DECLARATOR( p ) )
	return "rF.pp";
    else
	switch( p->NOUN )
	{
	case INT:	return (p->LONG) ?  "rF.l" : "rF.w.low" ;
	case CHAR:	return "rF.w.low" ;
	default:	yyerror("INTERNAL ERROR: ret_reg, bad noun\n");
			return "AAAAAAAAAAAAAAAGH!";
	}
}

value *assignment( op, dst, src )
int   op;
value *dst, *src;
{
    char   *src_name;
    char   op_str[8], *p = op_str ;

    if( !dst->lvalue		 ) yyerror    ( "(=) lvalue required\n" );
    if( !dst->is_tmp && dst->sym ) gen_comment( "%s", dst->sym->name	);

    /* Assemble the operator string for gen(). A leading @ is translated by
     * gen() to a * at the far left of the output string. For example,
     * ("@=",x,y) is output as "*x = y".
     */

    if(  *dst->name != '&'	) *p++ =  '@' ;
    if(  op  			) *p++ =  op  ;
    if(  op == '<' || op == '>' ) *p++ =  op  ;		/* <<= or >>= */
    /*  do always        */	  *p++ =  '=' ;
			   	  *p++ = '\0' ;

    src_name = rvalue( src );

    if( IS_POINTER(dst->type) && IS_PTR_TYPE(src->type) )
    {
	if( op )
	    yyerror("Illegal operation (%c= on two pointers);\n", op);

	else if( !the_same_type( dst->type->next, src->type->next, 0) )
	    yyerror("Illegal pointer assignment (type mismatch)\n");

	else
	    gen( "=", dst->name + (*dst->name=='&' ? 1 : 0), src_name );
    }
    else
    {
	/* If the destination type is larger than the source type, perform an
	 * implicit cast (create a temporary of the correct type, otherwise
	 * just copy into the destination. convert_type() releases the source
	 * value.
	 */

	if( !the_same_type( dst->type, src->type, 1) )
	{
	    gen( op_str, dst->name + (*dst->name == '&' ? 1 : 0),
					     convert_type( dst->type, src ) );
	}
	else
	{
	    gen( op_str, dst->name + (*dst->name == '&' ? 1 : 0), src_name );
	    release_value( src );
	}
    }
    return dst;
}

void	or( val, label )
value	*val;
int	label;
{
    val = gen_rvalue( val );

    gen	( "NE",       val->name, "0" 	);
    gen	( "goto%s%d", L_TRUE,	 label	);
    release_value( val );
}
/*----------------------------------------------------------------------*/
value *gen_rvalue( val )
value *val;
{
    /* This function is like rvalue(), except that emits code to generate a
     * physical rvalue from a physical lvalue (instead of just messing with the
     * name). It returns the 'value' structure for the new rvalue rather than a
     * string.
     */

    if( !val->lvalue  || *(val->name) == '&' )  /* rvalue or logical lvalue */
	rvalue( val );				/* just change the name     */
    else
	val = tmp_gen( val->type, val );	/* actually do indirection  */

    return val;
}
void	and( val, label )
value	*val;
int	label;
{
    val = gen_rvalue( val );

    gen	( "EQ",       val->name, "0" 	);
    gen	( "goto%s%d", L_FALSE,	 label	);
    release_value( val );
}
value	*relop( v1, op, v2 )
value	*v1;
int	op;
value	*v2;
{
    char  *str_op ;
    value *tmp;
    int   label;

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

    if( !make_types_match( &v1, &v2 ) )
	yyerror( "Illegal comparison of dissimilar types\n" );
    else
    {
	switch( op )
	{
	case '>': /* >  */    str_op = "GT";   break;
	case '<': /* <  */    str_op = "LT";   break;
	case 'G': /* >= */    str_op = "GE";   break;
	case 'L': /* <= */    str_op = "LE";   break;
	case '!': /* != */    str_op = "NE";   break;
	case '=': /* == */    str_op = "EQ";   break;
	default:
	    yyerror("INTERNAL, relop(): Bad request: %c\n", op );
	    goto abort;
	}

	gen	( str_op,     v1->name,	v2->name		);
	gen	( "goto%s%d", L_TRUE,	label = tf_label()	);

	if( !(v1->is_tmp && IS_INT( v1->type )) )
	{
	    tmp = v1;			/* try to make v1 an int temporary */
	    v1  = v2;
	    v2  = tmp;
	}
	v1 = gen_false_true( label, v1 );

⌨️ 快捷键说明

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