📄 cgen2.c
字号:
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
return( CGInitCall( name, CGenType( typ->object ), node->sym_handle ) );
}
local void DoSwitch( OPNODE *node, cg_name name )
{
sel_handle table;
SWITCHPTR sw;
CASEPTR ce;
table = CGSelInit();
sw = node->switch_info;
for( ce = sw->case_list; ce; ce = ce->next_case ) {
CGSelCase( table, CGLabelHandles[ ce->label ], ce->value );
}
CGSelOther( table, CGLabelHandles[ sw->default_label ] );
CGSelect( table, name );
}
static bool IsStruct( TYPEPTR typ ){
/*********************************/
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type == TYPE_STRUCT ||
typ->decl_type == TYPE_FCOMPLEX ||
typ->decl_type == TYPE_DCOMPLEX ||
typ->decl_type == TYPE_LDCOMPLEX ||
typ->decl_type == TYPE_UNION ) {
return( TRUE );
}
return( FALSE );
}
local void EmitNodes( TREEPTR tree )
{
cg_name op1;
cg_name op2;
cg_name expr;
call_handle call_list;
cg_name *cgnames;
unsigned index;
OPNODE *node;
index = 0;
cgnames = (cg_name *)&ValueStack[0];
for( ; tree != NULL; tree = tree->thread ) {
node = &tree->op;
switch( node->opr ) {
case OPR_FUNCTION: // start of function
StartFunction( node );
break;
case OPR_NEWBLOCK: // start of new block { vars; }
DBBegBlock();
DoAutoDecl( node->sym_handle );
break;
case OPR_ENDBLOCK: // end of new block { vars; }
DBEndBlock();
LocalVarList = ReleaseVars( node->sym_handle, LocalVarList );
break;
case OPR_LABELCOUNT: // number of labels used in function
DefineLabels( node );
break;
case OPR_RETURN: // return( expression );
op1 = PopCGName(); // - get expression
ReturnExpression( node, op1 );
break;
case OPR_FUNCEND: // end of function
EndFunction( node );
break;
case OPR_EQUALS: // =
{
cg_type dtype;
op2 = PopCGName(); // get right opnd
op1 = PopCGName(); // get lvalue
if( node->flags & OPFLAG_VOLATILE ) { // is lvalue volatile
op1 = CGVolatile( op1 );
}
if( IsStruct( node->result_type ) ){
dtype = DataPointerType( node );
op1 = CGLVAssign( op1, op2, CGenType( node->result_type ));
op1 = PushRValue( node, op1 );
}else{
dtype = CGenType( node->result_type );
op1 = CGAssign( op1, op2, CGenType( node->result_type ));
}
PushCGName( op1 );
} break;
case OPR_ADD: // +
case OPR_SUB: // -
op2 = PopCGName();
op1 = PopCGName();
PushCGName( DoAddSub( op1, node, op2 ) );
break;
case OPR_MUL: // *
case OPR_DIV: // /
case OPR_MOD: // %
case OPR_OR: // |
case OPR_AND: // &
case OPR_XOR: // ^
case OPR_RSHIFT: // >>
case OPR_LSHIFT: // <<
op2 = PopCGName();
op1 = PopCGName();
PushCGName( CGBinary( CGOperator[node->opr], op1, op2,
CGenType( node->result_type ) ) );
break;
case OPR_COMMA: // expr , expr
{
cg_type dtype;
op2 = PopCGName();
op1 = PopCGName();
dtype = IsStruct( node->result_type ) ?
DataPointerType( node ) : CGenType( node->result_type );
op1 = CGBinary( O_COMMA, op1, op2, dtype );
PushCGName( PushRValue( node, op1 ) );
} break;
case OPR_PLUS_EQUAL:
case OPR_MINUS_EQUAL:
case OPR_TIMES_EQUAL:
case OPR_DIV_EQUAL:
case OPR_MOD_EQUAL:
case OPR_XOR_EQUAL:
case OPR_AND_EQUAL:
case OPR_OR_EQUAL:
case OPR_RSHIFT_EQUAL:
case OPR_LSHIFT_EQUAL:
op2 = PopCGName(); // get right opnd
op1 = PopCGName(); // get lvalue
if( node->flags & OPFLAG_VOLATILE ) { // is lvalue volatile
op1 = CGVolatile( op1 );
}
PushCGName( CGPreGets( CGOperator[node->opr], op1, op2,
CGenType( node->result_type ) ) );
break;
case OPR_NEG: // negate
op1 = PopCGName();
PushCGName( CGUnary( O_UMINUS, op1,
CGenType( node->result_type ) ) );
break;
case OPR_CMP: // compare
op2 = PopCGName();
op1 = PopCGName();
PushCGName( CGCompare( CC2CGOp[ node->cc ], op1, op2,
CGenType( node->compare_type ) ) );
break;
case OPR_COM: // ~
op1 = PopCGName();
PushCGName( CGUnary( O_COMPLEMENT, op1,
CGenType( node->result_type ) ) );
break;
case OPR_NOT: // !
op1 = PopCGName();
PushCGName( CGFlow( O_FLOW_NOT, op1, NULL ) );
break;
case OPR_QUESTION: // ?
{
cg_type dtype;
op2 = PopCGName(); // false_part
op1 = PopCGName(); // true_part
expr = PopCGName(); // test expr
dtype = IsStruct( node->result_type ) ?
DataPointerType( node ) : CGenType( node->result_type );
op1 = CGChoose( expr, op1, op2, dtype );
PushCGName( PushRValue( node, op1 ) );
} break;
case OPR_COLON: // :
// do nothing, wait for OPR_QUESTION to come along
break;
case OPR_OR_OR: // ||
case OPR_AND_AND: // &&
op2 = PopCGName();
op1 = PopCGName();
PushCGName( CGFlow( CGOperator[ node->opr ], op1, op2 ) );
break;
case OPR_POINTS: // *ptr
op1 = PopCGName();
PushCGName( DoIndirection( node, op1 ) );
break;
case OPR_POSTINC: // lvalue++
case OPR_POSTDEC: // lvalue--
op2 = PopCGName(); // get amount to inc/dec by
op1 = PopCGName(); // get lvalue
if( node->flags & OPFLAG_VOLATILE ) { // is lvalue volatile
op1 = CGVolatile( op1 );
}
PushCGName( CGPostGets( CGOperator[node->opr], op1, op2,
CGenType( node->result_type ) ) );
break;
case OPR_PUSHSYM: // push sym_handle
PushCGName( PushSym( node ) );
break;
case OPR_PUSHADDR: // push address of sym_handle
PushCGName( PushSymAddr( node ) );
break;
case OPR_PUSHINT: // push integer constant
case OPR_PUSHFLOAT: // push floating-point constant
PushCGName( PushConstant( node ) );
break;
case OPR_PUSHSTRING: // push address of string literal
PushCGName( PushString( node ) );
break;
case OPR_PUSHSEG: // push seg of sym
PushCGName( PushSymSeg( node ) );
break;
case OPR_DUPE: // push seg of sym
{
temp_handle temp_name;
cg_name name;
cg_name left;
op1 = PopCGName(); // - get expression
temp_name = CGTemp( T_LONG_POINTER );
name = CGTempName( temp_name, T_LONG_POINTER );
left = CGAssign( name, op1, T_LONG_POINTER );
name = CGTempName( temp_name, T_LONG_POINTER );
PushCGName( left );
PushCGName( PushRValue( node, name ) );
} break;
case OPR_CONVERT:
if( node->result_type->decl_type != TYPE_VOID ) {
op1 = PopCGName(); // - get expression
PushCGName( CGUnary( O_CONVERT, op1,
CGenType(node->result_type)) );
}
break;
case OPR_CONVERT_PTR: // convert pointer
op1 = PopCGName(); // - get expression
PushCGName( ConvertPointer( node, op1 ) );
break;
case OPR_MATHFUNC: // intrinsic math func with 1 parm
op1 = PopCGName(); // - get expression
PushCGName( CGUnary( node->mathfunc, op1, TY_DOUBLE ) );
break;
case OPR_MATHFUNC2: // intrinsic math func with 2 parms
op2 = PopCGName(); // - get expression
op1 = PopCGName(); // - get expression
PushCGName( CGBinary( node->mathfunc, op1, op2, TY_DOUBLE ) );
break;
case OPR_DOT: // sym.field
op2 = PopCGName(); // - get offset of field
op1 = PopCGName(); // - get address of sym
PushCGName( DotOperator( op1, node, op2 ) );
break;
case OPR_ARROW: // ptr->field
op2 = PopCGName(); // - get offset of field
op1 = PopCGName(); // - get pointer
PushCGName( ArrowOperator( op1, node, op2 ) );
break;
case OPR_INDEX: // array[index]
op2 = PopCGName(); // - get index
op1 = PopCGName(); // - get address of array
PushCGName( IndexOperator( op1, node, op2 ) );
break;
case OPR_ADDROF: // & expr
case OPR_NOP: // nop
break;
case OPR_FARPTR: // segment :> offset
op2 = PopCGName(); // - get offset
op1 = PopCGName(); // - get segment
PushCGName( CGBinary( O_CONVERT, op2, op1, T_LONG_POINTER ) );
break;
case OPR_FUNCNAME: // function name
PushCGName( InitFuncCall( node ) ); // - push call_handle
break;
case OPR_CALL_INDIRECT: // indirect function call
op1 = PopCGName(); // - get name
PushCGName( InitIndFuncCall( node, op1 ) ); // - push call_handle
break;
case OPR_CALL: // function call
call_list = PopCGName(); // - get call_handle
op1 = CGCall( call_list );
if( node->flags & OPFLAG_RVALUE ) {
op1 = CGUnary( O_POINTS, op1, CGenType( node->result_type ) );
}
PushCGName( op1 );
break;
case OPR_PARM: // function parm
op1 = PopCGName(); // - get parm
call_list = PopCGName(); // - get call_handle
CGAddParm( call_list, op1, CGenType( node->result_type ) );
PushCGName( call_list );
break;
case OPR_LABEL: // label
case OPR_CASE: // case label
CGControl( O_LABEL, NULL, CGLabelHandles[ node->label_index ] );
break;
case OPR_JUMP: // jump
CGControl( O_GOTO, NULL, CGLabelHandles[ node->label_index ] );
break;
case OPR_JUMPTRUE: // jump if true
op1 = PopCGName();
CGControl( O_IF_TRUE, op1, CGLabelHandles[ node->label_index ] );
break;
case OPR_JUMPFALSE: // jump if false
op1 = PopCGName();
CGControl( O_IF_FALSE, op1, CGLabelHandles[ node->label_index ] );
break;
case OPR_SWITCH: // switch
op1 = PopCGName();
DoSwitch( node, op1 );
break;
#ifdef __SEH__
case OPR_TRY: // start of try block
SetTryScope( node->parent_scope );
break;
case OPR_EXCEPT:
case OPR_FINALLY:
CGBigLabel( FEBack( node->sym_handle ) );
break;
case OPR_END_FINALLY:
EndFinally();
break;
case OPR_UNWIND:
TryUnwind( node->try_index );
break;
case OPR_EXCEPT_CODE:
op1 = TryExceptionInfoAddr();
op1 = CGUnary( O_POINTS, op1, T_POINTER );
PushCGName( CGUnary( O_POINTS, op1, T_INTEGER ) );
break;
case OPR_EXCEPT_INFO:
PushCGName( TryExceptionInfoAddr() );
break;
case OPR_ABNORMAL_TERMINATION:
PushCGName( TryAbnormalTermination() );
break;
#endif
#if _MACHINE == _ALPHA || _MACHINE == _PPC
case OPR_VASTART:
op2 = PopCGName(); // - get offset of parm
op1 = PopCGName(); // - get address of va_list
GenVaStart( op1, op2 );
break;
case OPR_ALLOCA:
op1 = PopCGName(); // - get size
PushCGName( CGUnary( O_STACK_ALLOC, op1, T_POINTER ) );
break;
#endif
default:
{
char msgbuf[MAX_MSG_LEN];
sprintf( msgbuf, "opr=%d not handled\n", node->opr );
DebugMsg( msgbuf );
}
break;
}
}
if( index != 0 ) {
CGDone( PopCGName() );
}
}
local void ThreadNode( TREEPTR node )
{
if( FirstNode == NULL ) FirstNode = node;
if( LastNode != NULL ) LastNode->thread = node;
LastNode = node;
}
local TREEPTR LinearizeTree( TREEPTR tree )
{
FirstNode = NULL;
LastNode = NULL;
WalkExprTree( tree, ThreadNode, NoOp, NoOp, ThreadNode );
LastNode->thread = NULL;
return( FirstNode );
}
void EmitInit()
{
SegListHead = NULL;
SegImport = SegData-1;
Refno = T_FIRST_FREE;
}
local int NewRefno()
{
return( Refno++ );
}
void EmitAbort()
{
}
local TREEPTR GenOptimizedCode( TREEPTR tree )
{
unsigned unroll_count;
unroll_count = 0;
while( tree != NULL ) {
SrcFno = tree->op.source_fno;
SrcLineNum = tree->srclinenum;
if( SrcLineNum != SrcLineCount ) {
if( Saved_CurFunc == 0 ) { /* 24-nov-91 */
DBSrcCue( SrcFno, SrcLineNum, 1 );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -