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 + -
显示快捷键?