void UpdateReturn( call_state *state, type_def *tipe, type_class_def type_class, aux_handle aux ) /**************************************************************************************************/ { hw_reg_set normal; if( _FPULevel( FPU_87 ) && _NPX( state->attr ) && (tipe->attr & TYPE_FLOAT) ) { HW_COnlyOn( state->return_reg, HW_ST0 ); } else { HW_CTurnOff( state->return_reg, HW_FLTS ); } if( tipe == TypeNone ) { if( HW_CEqual( state->return_reg, HW_EMPTY ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); HW_CAsgn( state->return_reg, HW_EMPTY ); state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } else if( type_class == XX ) { normal = ReturnReg( WD, _NPX( state->attr ) ); if( HW_Equal( state->return_reg, normal ) ) return; if( HW_CEqual( state->return_reg, HW_EMPTY ) ) return; // if( !HW_Ovlap( state->return_reg, state->unalterable ) && // IsRegClass( state->return_reg, WD ) ) // return; if( IsRegClass( state->return_reg, WD ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); state->return_reg = normal; state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } else { normal = ReturnReg( type_class, _NPX( state->attr ) ); if( HW_Equal( state->return_reg, normal ) ) return; // if( !HW_Ovlap( state->return_reg, state->unalterable ) && // IsRegClass( state->return_reg, type_class ) ) // return; if( IsRegClass( state->return_reg, type_class ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); state->return_reg = normal; state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } }
void Zoiks( int msg ) /*********************** put out an internal compiler error. 2 is chunks unfreed which we may want to hide. 1 is unfreed code labels which we always hide. */ { if( ( msg == ZOIKS_001 ) ) return; if( ( msg == ZOIKS_002 ) && ( !WantZoiks2() ) ) return; if( ( msg == ZOIKS_040 ) && ( ++Zoiks40 < MAX_ZOIKS_40 ) ) return; FEMessage( MSG_BACK_END_ERROR, (pointer)(pointer_int)msg ); }
static void CheckEvents( void ) /*********************************/ { uint ticks; ticks = GetTickCnt(); if( ticks < LastBlipCount || ticks >= NextTickCount ) { OSCall(); /* force a DOS call to get version number */ if( ticks < LastBlipCount || ticks >= NextBlipCount ) { FEMessage( MSG_BLIP, NULL ); LastBlipCount = ticks; SetNextBlipCount(); } SetNextTickCount(); } if( TBreak() ) { FatalError( "Program interrupted from keyboard" ); } }
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 ); }
static bool FlushSomeOpt( pointer_int size ) /**********************************************/ { seg_id old; bool freed; if( InOptimizer == 0 && HaveCodeSeg() ) { old = SetOP( AskCodeSeg() ); freed = ShrinkQueue( size ); SetOP( old ); if( _IsntModel( NO_OPTIMIZATION ) && IckyWicky == FALSE ) { IckyWicky = TRUE; FEMessage( MSG_PEEPHOLE_FLUSHED, NULL ); } } else { freed = FALSE; } return( freed ); }
static int GetExtName( cg_sym_handle sym, char *buffer, int max_len ) /*******************************************************************/ { const char *src; char *dst; const char *p; const char *prefix; const char *sufix; char *dst_basename; char *tmp_suffix; char c; int base_len; int dst_len; const char *pattern; pattern = FEExtName( sym, EXTN_PATTERN ); c = '\0'; base_len = 0; prefix = pattern; for( p = pattern; *p != '\0'; p++ ) { if(( *p == '*' ) || ( *p == '!' ) || ( *p == '^' )) { if( c == '\0' ) { prefix = p; c = *p; } } else if( ( c != '\0' ) || ( *p == '#' ) ) { break; } else if( *p == '\\' ) { p++; } } if( c == '\0' ) base_len = p - pattern; sufix = p; // add prefix to output buffer dst = buffer; for( src = pattern; src != prefix; ++src ) { if( *src != '\\' ) { *(dst++) = *src; } } *dst = '\0'; // add sufix to output buffer dst_basename = dst; for( src = sufix; *src != '\0'; ++src ) { if( *src == '#' ) { unsigned size; size = (unsigned)(pointer_int)FEExtName( sym, EXTN_PRMSIZE ); if( size != (unsigned)-1 ) { *(dst++) = '@'; dst = xtoa( dst, size ); } } else { if( *src == '\\' ) ++src; *(dst++) = *src; } } *dst = '\0'; // max base name length dst_len = max_len - ( dst - buffer ); if( dst_len > 0 ) { int sufix_len; int len; if( base_len != 0 ) { // alias src = pattern; } else { src = FEExtName( sym, EXTN_BASENAME ); base_len = strlen( src ); } // shift sufix to the end of buffer sufix_len = dst - dst_basename; tmp_suffix = buffer + max_len - sufix_len; memmove( tmp_suffix, dst_basename, sufix_len + 1 ); // copy + truncate base symbol name len = copyBaseName( c, dst_basename, dst_len, src, base_len ); if( len < 0 ) { FEMessage( MSG_SYMBOL_TOO_LONG, sym ); } else { // shift sufix to the end of symbol name memcpy( dst_basename + len, tmp_suffix, sufix_len + 1 ); } } else { // TODO: error prefix + sufix >= max_len assert( 0 ); } return( 0 ); }
type_class_def CallState( aux_handle aux, type_def *tipe, call_state *state ) /****************************************************************************/ { call_class cclass; type_class_def type_class; uint i; hw_reg_set parms[10]; hw_reg_set *parm_src; hw_reg_set *parm_dst; hw_reg_set *pregs; hw_reg_set tmp; state->unalterable = FixedRegs(); pregs = FEAuxInfo( aux, SAVE_REGS ); HW_CAsgn( state->modify, HW_FULL ); HW_TurnOff( state->modify, *pregs ); HW_CTurnOff( state->modify, HW_UNUSED ); state->used = state->modify; /* anything not saved is used*/ tmp = state->used; HW_TurnOff( tmp, StackReg() ); HW_CTurnOff( tmp, HW_BP ); // should be able to call routine which modifies BP if( HW_Ovlap( state->unalterable, tmp ) ) { FEMessage( MSG_BAD_SAVE, aux ); } state->attr = ROUTINE_REMOVES_PARMS; cclass = *(call_class *)FEAuxInfo( aux, CALL_CLASS ); if( cclass & INTERRUPT ) { state->attr |= ROUTINE_INTERRUPT; } else if( cclass & FAR_CALL ) { state->attr |= ROUTINE_LONG; } else if( cclass & FAR16_CALL ) { state->attr |= ROUTINE_FAR16; } if( cclass & CALLER_POPS ) { state->attr &= ~ROUTINE_REMOVES_PARMS; } if( cclass & SUICIDAL ) { state->attr |= ROUTINE_NEVER_RETURNS; } if( cclass & ROUTINE_RETURN ) { state->attr |= ROUTINE_ALLOCS_RETURN; } if( cclass & NO_STRUCT_REG_RETURNS ) { state->attr |= ROUTINE_NO_STRUCT_REG_RETURNS; } if( cclass & NO_FLOAT_REG_RETURNS ) { state->attr |= ROUTINE_NO_FLOAT_REG_RETURNS; state->attr |= ROUTINE_NO_8087_RETURNS; } if( cclass & NO_8087_RETURNS ) { state->attr |= ROUTINE_NO_8087_RETURNS; } if( cclass & MODIFY_EXACT ) { state->attr |= ROUTINE_MODIFY_EXACT; } if( cclass & NO_MEMORY_CHANGED ) { state->attr |= ROUTINE_MODIFIES_NO_MEMORY; } if( cclass & NO_MEMORY_READ ) { state->attr |= ROUTINE_READS_NO_MEMORY; } if( cclass & LOAD_DS_ON_ENTRY ) { state->attr |= ROUTINE_LOADS_DS; } if( cclass & LOAD_DS_ON_CALL ) { state->attr |= ROUTINE_NEEDS_DS_LOADED; } if( cclass & PARMS_STACK_RESERVE ) { state->attr |= ROUTINE_STACK_RESERVE; } if( cclass & PARMS_PREFER_REGS ) { state->attr |= ROUTINE_PREFER_REGS; } if( cclass & FARSS ) { state->attr |= ROUTINE_FARSS; } if( state == &CurrProc->state ) { if( cclass & ( GENERATE_STACK_FRAME | PROLOG_HOOKS | EPILOG_HOOKS ) ) { CurrProc->prolog_state |= GENERATE_FAT_PROLOG; state->attr |= ROUTINE_NEEDS_PROLOG; } if( cclass & PROLOG_HOOKS ) { CurrProc->prolog_state |= GENERATE_PROLOG_HOOKS; } if( cclass & EPILOG_HOOKS ) { CurrProc->prolog_state |= GENERATE_EPILOG_HOOKS; } if( cclass & FAT_WINDOWS_PROLOG ) { CurrProc->prolog_state |= GENERATE_FAT_PROLOG; } if( cclass & EMIT_FUNCTION_NAME ) { CurrProc->prolog_state |= GENERATE_FUNCTION_NAME; } if( cclass & THUNK_PROLOG ) { CurrProc->prolog_state |= GENERATE_THUNK_PROLOG; } if( cclass & GROW_STACK ) { CurrProc->prolog_state |= GENERATE_GROW_STACK; } if( cclass & TOUCH_STACK ) { CurrProc->prolog_state |= GENERATE_TOUCH_STACK; } if( cclass & LOAD_RDOSDEV_ON_ENTRY ) { CurrProc->prolog_state |= GENERATE_RDOSDEV_PROLOG; } } type_class = ReturnClass( tipe, state->attr ); i = 0; parm_dst = &parms[0]; for( parm_src = FEAuxInfo( aux, PARM_REGS ); !HW_CEqual( *parm_src, HW_EMPTY ); ++parm_src ) { *parm_dst = *parm_src; if( HW_Ovlap( *parm_dst, state->unalterable ) ) { FEMessage( MSG_BAD_SAVE, aux ); } HW_CTurnOff( *parm_dst, HW_UNUSED ); parm_dst++; i++; } *parm_dst = *parm_src; 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; if( tipe == TypeNone ) { HW_CAsgn( state->return_reg, HW_EMPTY ); } else if( type_class == XX ) { if( cclass & SPECIAL_STRUCT_RETURN ) { pregs = FEAuxInfo( aux, STRETURN_REG ); state->return_reg = *pregs; state->attr |= ROUTINE_HAS_SPECIAL_RETURN; } else { state->return_reg = StructReg(); } if( (state->attr & ROUTINE_ALLOCS_RETURN) == 0 ) { tmp = ReturnReg( WD, false ); HW_TurnOn( state->modify, tmp ); } } else { if( cclass & SPECIAL_RETURN ) { pregs = FEAuxInfo( aux, RETURN_REG ); state->return_reg = *pregs; state->attr |= ROUTINE_HAS_SPECIAL_RETURN; } else { state->return_reg = ReturnReg( type_class, _NPX( state->attr ) ); } } UpdateReturn( state, tipe, type_class, aux ); return( type_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 ); }
void FatalError( char * str ) { /*****************************/ FEMessage( MSG_FATAL, str ); }