bldcall.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 910 行 · 第 1/3 页
C
910 行
extern name *DoParmDecl( sym_handle sym, type_def *tipe, hw_reg_set reg ) {
/******************************************************************************
Declare a parameter of type "tipe" for the current routine. This
routine determines whether the parameter is coming in in a register
or on the stack and generates a temporary to hold the parm (temp) and
PARMDEF => x
MOV x => temp
and links these two instructions together. (x may be a register or
a temporary that is pre-allocated to a location on the stack)
in the current basic block. If the parm is coming in on the stack,
it sets the location field of the temp to be the same as the location it
arrives in on the stack, so if we do assign the
parm to memory, it gets its incoming location on the stack.
*/
instruction *ins;
instruction *parm_def;
name *temp;
name *parm_name;
type_class_def class;
type_def *ptipe;
ptipe = QParmType( AskForLblSym( CurrProc->label ), sym, tipe );
class = TypeClass( ptipe );
if( sym == NULL ) {
temp = AllocTemp( TypeClass( tipe ) );
} else {
temp = SAllocUserTemp( sym, TypeClass( tipe ), tipe->length );
BGDone( MakeAddrName( CG_FE, sym, tipe ) );
}
temp->v.usage |= USE_IN_ANOTHER_BLOCK;
#if _TARGET & _TARG_RISC
if( class == XX ) {
return( DoAlphaParmDecl( reg, sym, tipe, temp ) );
}
#endif
if( HW_CEqual( reg, HW_EMPTY ) ) {
if( class == XX ) {
parm_name = temp;
parm_name->t.location = ParmMem( tipe->length, ParmAlignment( ptipe ), &CurrProc->state );
} else {
parm_name = AllocTemp( class );
parm_name->t.location = ParmMem( ptipe->length, ParmAlignment( ptipe ), &CurrProc->state );
}
parm_name->t.temp_flags |= STACK_PARM;
// parm_name->n.size = tipe->length;
parm_name->n.size = ptipe->length;
parm_name->v.usage |= NEEDS_MEMORY | HAS_MEMORY | USE_MEMORY;
} else {
parm_name = AllocRegName( ActualParmReg( reg ) );
#if _TARGET & _TARG_80386
if( CurrProc->state.attr & ROUTINE_STACK_RESERVE ) {
// Just make sure we are taking up some space
ParmMem( ptipe->length, ParmAlignment( ptipe ), &CurrProc->state );
}
#endif
}
if( _IsModel( DBG_LOCALS ) ){ // d1+ or d2
if( sym != NULL ) {
DbgParmLoc( &(parm_name->n), sym );
}
}
parm_def = DoParmDef( parm_name, class );
if( class != XX ) {
ins = MakeConvert( parm_name, temp, TypeClass( tipe ), class );
LinkParmIns( parm_def, ins );
AddIns( ins );
TRDeclareParm( ins );
if( temp->n.class == N_TEMP && parm_name->n.class == N_TEMP ) {
temp->t.location = parm_name->t.location;
} else {
#if (_TARGET & _TARG_PPC) || (_TARGET & _TARG_MIPS)
// for PowerPC varargs routines, ensure that taking the address
// of a parm coming in in a register will force that parm into the
// correct home location in the caller's frame (yes - it sucks)
// For MIPS, ensure that taking the address of a parm passed in
// register will always force it to the right home location,
// varargs or not. All this is done basically so that crappy code
// that doesn't use stdarg.h properly would work - we have some
// in our own clib ;-)
temp->t.location = CurrProc->state.parm.offset - ptipe->length;
#endif
}
}
MaxStack = 0;
return( temp );
}
extern void BGParmDecl( sym_handle sym, type_def *tipe ) {
/************************************************************/
hw_reg_set reg;
type_def *t;
t = QParmType( AskForLblSym( CurrProc->label ), sym, tipe );
reg = ParmReg( TypeClass( t ), t->length, ParmAlignment( tipe ), &CurrProc->state );
DoParmDecl( sym, tipe, reg );
}
static void LinkParms( instruction *call_ins, pn *owner ) {
/**************************************************************
call TRAddParm for each parm in order and delete the parm nodes
*/
pn next;
pn parm;
parm = *owner;
*owner = NULL;
while( parm != NULL ) {
// because of FPPushParms and delayed stuff
// if( parm->ins == NULL ) _Zoiks( ZOIKS_XXX );
TRAddParm( call_ins, parm->ins );
next = parm->next;
_Free( parm, sizeof( parm_node ) );
parm = next;
}
}
extern void AddCallIns( instruction *ins, cn call ) {
/********************************************************
stick the call instruction into the current basic block
*/
name *call_name;
fe_attr attr;
type_class_def addr_type;
name *temp;
instruction *new_ins;
#if _TARGET & (_TARG_80386|_TARG_IAPX86)
call_class class;
#endif
PreCall( call );
if( ins->head.opcode == OP_CALL ) {
call_name = call->name->u.name;
attr = 0;
if( call_name->m.memory_type == CG_FE ) {
attr = FEAttr( call_name->v.symbol );
#if _TARGET & _TARG_RISC
// in case the inline assembly code references a local variable
if( FEAuxInfo( call_name->v.symbol, CALL_BYTES ) != NULL ) {
CurrProc->targ.base_is_fp = TRUE;
}
#endif
}
// don't do this for far16 functions since they are handled
// in a weird manner by Far16Parms and will not call data labels
if( ( ( attr & FE_PROC ) == 0 )
#if _TARGET & (_TARG_80386|_TARG_IAPX86)
&& ( ( ins->flags.call_flags & CALL_FAR16 ) == 0 )
#endif
) {
// indirect since calling data labels directly
// screws up the back end
addr_type = WD;
#if _TARGET & (_TARG_80386|_TARG_IAPX86)
class = *(call_class *)FindAuxInfo( call_name, CALL_CLASS );
if( class & FAR ) {
addr_type = CP;
}
#endif
temp = AllocTemp( addr_type );
new_ins = MakeUnary( OP_LA, call_name, temp, addr_type );
AddIns( new_ins );
call_name = temp;
ins->head.opcode = OP_CALL_INDIRECT;
ins->num_operands = 3;
}
ins->operands[CALL_OP_ADDR] = call_name;
} else {
ins->operands[CALL_OP_ADDR] = GenIns( call->name );
}
AddIns( ins );
TNZapParms();
PostCall( call );
}
extern void ReverseParmNodeList( pn *owner ) {
/*************************************************
reverse a linked list of parm_nodes.
*/
pn parm;
pn next;
parm = *owner;
*owner = NULL;
while( parm != NULL ) {
next = parm->next;
parm->next = *owner;
*owner = parm;
parm = next;
}
}
extern void PushParms( pn parm, call_state *state ) {
/***************************************************************
Run through the list of parameters, generating pushes
for the ones that are being passed on the stack. Unhook them
from the list, but leave the others (register parms) alone.
Add pointers to push instructions to the call instruction.
*/
instruction *ins;
instruction *push_ins;
an addr;
pn next;
while( parm != NULL ) {
next = parm->next;
if( parm->ins != NULL ) {
parm = next;
continue;
}
if( HW_CEqual( parm->regs, HW_EMPTY ) ) {
addr = parm->name;
if( addr->format != NF_INS ) {
_Zoiks( ZOIKS_043 );
}
ins = addr->u.ins;
PushInSameBlock( ins );
if( ins->head.opcode == OP_MOV && !IsVolatile( ins->operands[0] ) &&
!( addr->flags & VOLATILE ) ) {
push_ins = PushOneParm( ins, ins->operands[0],
ins->type_class, parm->offset, state );
// ins->result = ins->operands[0]; -- was this useful? BBB
FreeIns( ins );
} else {
ins->result = BGNewTemp( addr->tipe );
FPNotStack( ins->result );
if( addr->flags & ADDR_CROSSED_BLOCKS ) {
ins->result->v.usage |= USE_IN_ANOTHER_BLOCK;
}
push_ins = PushOneParm( ins, ins->result,
ins->result->n.name_class, parm->offset, state );
}
addr->format = NF_ADDR;
BGDone( addr );
parm->ins = push_ins;
}
parm = next;
}
}
#if _TARGET & _TARG_80386
extern void ReserveStack( call_state *state, instruction *prev, type_length len ) {
/**************************************************************************************
grab len bytes off the stack - doesn't matter what goes in there
as long as the space is allocated. Guaranteed that len is a multiple
of 4 bytes in size.
*/
name *reg;
instruction *ins;
CurrProc->targ.never_sp_frame = TRUE;
reg = AllocRegName( HW_EAX );
switch( len ) {
case 8:
ins = MakeUnary( OP_PUSH, reg, NULL, WD );
SuffixIns( prev, ins );
/* fall through */
case 4:
ins = MakeUnary( OP_PUSH, reg, NULL, WD );
SuffixIns( prev, ins );
break;
default:
_Zoiks( ZOIKS_133 );
}
state->parm.offset += len;
if( state->parm.offset > MaxStack ) {
MaxStack = state->parm.offset;
}
}
#endif
extern void ParmIns( pn parm, call_state *state ) {
/******************************************************
generate the move instructions for parameters that are passed in registers.
This should be all that's left on the list by now. The rest have all
been pushed on the stack.
*/
name *reg;
name *curr;
instruction *ins;
an addr;
while( parm != NULL ) {
if( parm->ins != NULL ) {
parm = parm->next;
continue;
}
addr = parm->name;
if( addr->format != NF_INS ) {
_Zoiks( ZOIKS_043 );
}
reg = AllocRegName( ActualParmReg( parm->regs ) );
ins = addr->u.ins;
ins->result = BGNewTemp( addr->tipe );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?