bldcall.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 910 行 · 第 1/3 页
C
910 行
if( addr->flags & ADDR_CROSSED_BLOCKS ) {
ins->result->v.usage |= USE_IN_ANOTHER_BLOCK;
}
curr = ins->result;
#if _TARGET & _TARG_AXP
if( 1 ) {
#else
if( addr->tipe->length == reg->n.size ) {
#endif
ins = MakeMove( curr, reg, TypeClass( addr->tipe ) );
AddIns( ins );
} else if( !CvtOk( TypeClass(addr->tipe), reg->n.name_class ) ) {
ins = NULL;
FEMessage( MSG_BAD_PARM_REGISTER, (pointer) parm->num );
#if _TARGET & ( _TARG_IAPX86 | _TARG_80386 )
} else if( HW_CEqual( reg->r.reg, HW_ABCD ) ) {
ins = NULL;
FEMessage( MSG_BAD_PARM_REGISTER, (pointer) parm->num );
#endif
} else {
ins = MakeConvert( curr, reg,
reg->n.name_class, TypeClass( addr->tipe ) );
AddIns( ins );
}
addr->format = NF_ADDR;
#if _TARGET & _TARG_80386
if( state->attr & ROUTINE_STACK_RESERVE ) {
// this is for the stupid OS/2 _Optlink calling convention
ReserveStack( state, ins, addr->tipe->length );
}
#else
state = state;
#endif
BGDone( addr );
parm->ins = ins;
parm = parm->next;
}
}
extern void BGZapBase( name *base, type_def *tipe ) {
/********************************************************
for FORTRAN. Generate a NOP with result of base[temp], so that we
know that a pass by reference argument can be modified by the
call. The NOP instruction right after the call.
*/
instruction *ins;
if( base == NULL ) return;
if( _IsntModel( FORTRAN_ALIASING ) ) return;
if( !( tipe->attr & TYPE_POINTER ) ) return;
ins = MakeNop();
if( DummyIndex == NULL ) DummyIndex = AllocTemp( WD );
ins->result = ScaleIndex( DummyIndex, base, 0, XX, tipe->length,
0, X_FAKE_BASE );
ins->flags.nop_flags |= NOP_ZAP_INFO;
AddIns( ins );
}
extern void BGReturn( an retval, type_def *tipe ) {
/******************************************************
generate the instructions to return the value 'retval', then
go off and call generate to optimize the whole routine and
spew it out into the object file.
*/
instruction *ins;
instruction *last_ins;
instruction *ret_ins;
name *name;
type_class_def class;
type_class_def aclass;
ins = MakeNop();
last_ins = NULL;
if( retval != NULL ) {
class = TypeClass( tipe );
aclass = ReturnClass( tipe, CurrProc->state.attr );
UpdateReturn( & CurrProc->state, tipe, aclass,
FEAuxInfo( AskForLblSym(CurrProc->label), AUX_LOOKUP ) );
if( _IsModel( DBG_LOCALS ) ){ // d1+ or d2
DbgRetLoc();
}
if( aclass == XX ) {
name = StReturn( retval, tipe, &last_ins );
AddIns( MakeMove( GenIns( retval ), name, class ) );
} else {
if( HW_CEqual( CurrProc->state.return_reg, HW_EMPTY ) ) {
name = StReturn( retval, tipe, &last_ins );
} else {
name = AllocRegName( CurrProc->state.return_reg );
}
#if _TARGET & _TARG_AXP
if( class == U4 && aclass == I8 ) {
ret_ins = MakeConvert( GenIns( retval ), name, I8, I4 );
} else {
#endif
if( tipe->length == name->n.size ) {
ret_ins = MakeMove( GenIns( retval ),
name, name->n.name_class );
} else {
ret_ins = MakeConvert( GenIns( retval ), name,
name->n.name_class, class );
}
// BBB - we can get a situation where we are returning
// a float in eax (when compiling -3s) and we don't want
// to do a convert - ack.
// ret_ins = MakeConvert( GenIns( retval ), name,
// name->n.name_class, class );
#if _TARGET & _TARG_AXP
}
#endif
AddIns( ret_ins );
}
BGDone( retval );
} else {
ins->zap = &AllocRegName( CurrProc->state.return_reg )->r;
ins->flags.nop_flags |= NOP_ZAP_INFO;
}
AddIns( ins );
if( last_ins != NULL ) AddIns( last_ins );
GenBlock( RETURN, 0 );
if( AddrList != NULL ) {
_Zoiks( ZOIKS_003 );
}
Generate( TRUE );
TargetModel = SaveModel;
}
#if _TARGET & _TARG_RISC
static pn BustUpStruct( pn parm, type_class_def from, type_class_def using ) {
/******************************************************************************/
pn curr;
pn last;
type_length len;
type_length offset;
type_length size;
name *temp;
instruction *ins;
size = TypeClassSize[ using ];
len = _RoundUp( parm->name->tipe->length, size );
offset = len - size;
temp = AllocTemp( from );
temp->n.size = len;
last = parm->next;
parm->name->u.ins->result = temp;
while( offset >= 0 ) {
// create a parm node for this part of the struct
_Alloc( curr, sizeof( parm_node ) );
ins = MakeMove( STempOffset( temp, offset, using, size ), NULL, using );
AddIns( ins );
curr->next = last;
curr->name = InsName( ins, ClassType( using ) );
curr->name->flags = parm->name->flags;
curr->alignment = 4;
last = curr;
offset -= size;
}
// only needed for first parm (PPC hack - doubles skip registers)
curr->alignment = parm->alignment;
return( curr );
}
static void SplitStructParms( pn *parm_list, call_state *state ) {
/*****************************************************************
Split up any structures being passed as parms into
smaller, independant chunks (system dependant).
*/
pn parm;
pn *last_parm;
an name;
type_class_def tipe;
type_class_def class;
#if _TARGET & _TARG_PPC
if( _IsTargetModel( CG_OS2_CC ) ) return;
tipe = U4;
#elif _TARGET & _TARG_AXP
state = state;
tipe = U8;
#elif _TARGET & _TARG_MIPS
tipe = U4;
#else
#error Unknown RISC CPU
#endif
last_parm = parm_list;
parm = *last_parm;
while( parm != NULL ) {
name = parm->name;
parm->alignment = ParmAlignment( name->tipe );
class = TypeClass( name->tipe );
if( class == XX
#if _TARGET & _TARG_PPC
|| ( ( class == FD ) && ( state->attr & ROUTINE_HAS_VARARGS ) )
#endif
) {
if( ( class == FD ) || ( name->tipe->length > 7 ) ) {
parm->alignment = 8;
}
*last_parm = BustUpStruct( parm, class, tipe );
name->format = NF_ADDR;
BGDone( name );
_Free( parm, sizeof( parm_node ) );
parm = *last_parm;
}
last_parm = &parm->next;
parm = parm->next;
}
}
#endif
extern bool AssgnParms( cn call, bool in_line ) {
/********************************************************
Decide what registers the parms should go in.
Assign registers to first parm first, etc. Also, assign a congolmeration
of all the parameter registers to one of the operands of the call
so that the dataflow knows that the registers are live between the
move into them and the call.
*/
pn parm;
call_state *state;
bool push_no_pop;
int parms;
instruction *call_ins;
type_class_def parm_tipe;
type_class_def reg_tipe;
push_no_pop = FALSE;
parm = call->parms;
state = call->state;
call_ins = call->ins;
parms = 0;
#if _TARGET & _TARG_RISC
SplitStructParms( &call->parms, state );
parm = call->parms;
#endif
while( parm != NULL ) {
if( in_line ) {
parm->regs = ParmInLineReg( &state->parm );
if( HW_CEqual( parm->regs, HW_EMPTY ) ) {
if( !HW_CEqual( *(state->parm.curr_entry), HW_EMPTY ) ) {
FEMessage( MSG_ERROR,
"More parameters than registers in pragma" );
} else {
parm->offset = ParmMem( parm->name->tipe->length, ParmAlignment( parm->name->tipe ), state );
push_no_pop = TRUE;
}
} else {
parm_tipe = TypeClass( parm->name->tipe );
reg_tipe = AllocRegName( parm->regs )->n.name_class;
if( parm_tipe != FD || reg_tipe != U8 ) {
if( !CvtOk( parm_tipe, reg_tipe ) ) {
FEMessage( MSG_BAD_PARM_REGISTER, (pointer)(parms + 1));
}
}
}
} else {
#if ( _TARGET & _TARG_PPC ) == 0
parm->alignment = 1;
#endif
parm->regs = ParmReg( TypeClass( parm->name->tipe ),
parm->name->tipe->length,
parm->alignment,
state );
if( HW_CEqual( parm->regs, HW_EMPTY ) ) {
parm->offset = ParmMem( parm->name->tipe->length, parm->alignment, state );
push_no_pop = TRUE;
}
}
++parms;
parm->num = parms;
parm->ins = NULL;
parm = parm->next;
}
ReverseParmNodeList( &call->parms );
PushParms( call->parms, state );
FPPushParms( call->parms, state );
ParmIns( call->parms, state );
ReverseParmNodeList( &call->parms );
LinkParms( call_ins, &call->parms );
if( call_ins->head.opcode == OP_CALL ) {
call_ins->num_operands = 2; /* special case for call so we*/
/* ignore address in dataflow*/
call_ins->operands[CALL_OP_USED] = AllocRegName( state->parm.used );
} else {
call_ins->operands[CALL_OP_USED] = AllocRegName( state->parm.used );
}
call_ins->operands[CALL_OP_POPS] = AllocS32Const( state->parm.offset );
call_ins->zap = &AllocRegName( CallZap( state ) )->r;
return( push_no_pop );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?