type_class_def CallState( aux_handle aux, type_def *tipe, call_state *state ) /****************************************************************************/ { type_class_def class; uint i; hw_reg_set parms[24]; hw_reg_set *parm_src; hw_reg_set *parm_dst; state->unalterable = FixedRegs(); HW_CAsgn( state->modify, HW_FULL ); HW_TurnOff( state->modify, SavedRegs() ); HW_CTurnOff( state->modify, HW_UNUSED ); state->used = state->modify; /* anything not saved is used*/ state->attr = 0; i = 0; parm_src = ParmRegs(); parm_dst = &parms[0]; for(;;) { *parm_dst = *parm_src; if( HW_CEqual( *parm_dst, HW_EMPTY ) ) break; if( HW_Ovlap( *parm_dst, state->unalterable ) ) { FEMessage( MSG_BAD_SAVE, aux ); } HW_CTurnOff( *parm_dst, HW_UNUSED ); parm_dst++; parm_src++; i++; } i++; state->parm.table = CGAlloc( i*sizeof( hw_reg_set ) ); Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) ); HW_CAsgn( state->parm.used, HW_EMPTY ); state->parm.curr_entry = state->parm.table; state->parm.offset = 0; InitPPCParmState( state ); class = ReturnClass( tipe, state->attr ); if( *(call_class *)FEAuxInfo( aux, CALL_CLASS ) & HAS_VARARGS ) { state->attr |= ROUTINE_HAS_VARARGS; } UpdateReturn( state, tipe, class, aux ); return( class ); }
extern type_class_def CallState( aux_handle aux, type_def *tipe, call_state *state ) /*******************************************************************/ { type_class_def class; uint i; hw_reg_set parms[20]; hw_reg_set *parm_src; hw_reg_set *parm_dst; hw_reg_set *pregs; call_class cclass; call_class *pcclass; risc_byte_seq *code; bool have_aux_code = FALSE; state->unalterable = FixedRegs(); if( FEAttr( AskForLblSym( CurrProc->label ) ) & FE_VARARGS ) { HW_TurnOn( state->unalterable, VarargsHomePtr() ); } // For code bursts only, query the #pragma aux instead of using // hardcoded calling convention. If it ever turns out that we need // to support more than a single calling convention, this will need // to change to work more like x86 if( !AskIfRTLabel( CurrProc->label ) ) { code = FEAuxInfo( aux, CALL_BYTES ); if( code != NULL ) { have_aux_code = TRUE; } } pregs = FEAuxInfo( aux, SAVE_REGS ); HW_CAsgn( state->modify, HW_FULL ); if( have_aux_code ) { HW_TurnOff( state->modify, *pregs ); } else { HW_TurnOff( state->modify, SavedRegs() ); } HW_CTurnOff( state->modify, HW_UNUSED ); state->used = state->modify; /* anything not saved is used */ state->attr = 0; pcclass = FEAuxInfo( aux, CALL_CLASS ); cclass = *pcclass; if( cclass & SETJMP_KLUGE ) { state->attr |= ROUTINE_IS_SETJMP; } if( cclass & SUICIDAL ) { state->attr |= ROUTINE_NEVER_RETURNS; } if( cclass & NO_MEMORY_CHANGED ) { state->attr |= ROUTINE_MODIFIES_NO_MEMORY; } if( cclass & NO_MEMORY_READ ) { state->attr |= ROUTINE_READS_NO_MEMORY; } i = 0; if( have_aux_code ) { parm_src = FEAuxInfo( aux, PARM_REGS ); } else { parm_src = ParmRegs(); } parm_dst = &parms[0]; for( ;; ) { *parm_dst = *parm_src; if( HW_CEqual( *parm_dst, HW_EMPTY ) ) break; if( HW_Ovlap( *parm_dst, state->unalterable ) ) { FEMessage( MSG_BAD_SAVE, aux ); } HW_CTurnOff( *parm_dst, HW_UNUSED ); parm_dst++; parm_src++; i++; } i++; state->parm.table = CGAlloc( i * sizeof( hw_reg_set ) ); Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) ); HW_CAsgn( state->parm.used, HW_EMPTY ); state->parm.curr_entry = state->parm.table; state->parm.offset = 0; class = ReturnClass( tipe, state->attr ); UpdateReturn( state, tipe, class, aux ); return( class ); }