static void PreOptimize( void ) /*****************************************/ { bool change; if( _IsntModel( NO_OPTIMIZATION ) ) { // CharsAndShortsToInts(); MakeMovAddrConsts(); PushPostOps(); DeadTemps(); InsDead(); MakeFlowGraph(); BlockTrim(); CommonSex( _IsModel( LOOP_OPTIMIZATION ) ); SetOnCondition(); BlockTrim(); AddANop(); if( _IsModel( LOOP_OPTIMIZATION ) ) { change = FALSE; if( TransLoops( FALSE ) ) { change = TRUE; } if( LoopInvariant() ) { change = TRUE; } if( change ) { CommonSex(TRUE); InsDead(); CommonInvariant(); } if( IndVars() ) { CommonSex(FALSE); InsDead(); change = TRUE; } BlockTrim(); if( TransLoops( TRUE ) ) { BlockTrim(); CommonSex( FALSE ); change = TRUE; } if( change ) { ReConstFold(); } LoopEnregister(); if( change ) { BlockTrim(); } } MulToShiftAdd(); KillMovAddrConsts(); FindReferences(); } else { MakeFlowGraph(); AddANop(); FindReferences(); } }
extern void CVDefSegs( void ){ /**************************/ if( _IsModel( DBG_LOCALS ) ) { CVSyms = DbgSegDef( "$$SYMBOLS", "DEBSYM", SEG_COMB_PRIVATE+SEG_USE_32 ); } if( _IsModel( DBG_TYPES ) ) { CVTypes = DbgSegDef( "$$TYPES", "DEBTYP", SEG_COMB_PRIVATE+SEG_USE_32 ); } }
extern void CVDefSegs( void ){ /**************************/ if( _IsModel( DBG_LOCALS ) ) { CVSyms = DbgSegDef( ".debug$S" ); CVSymMain = FindSection( CVSyms ); owlCVSym = CVSymMain->owl_handle; } if( _IsModel( DBG_TYPES ) ) { CVTypes = DbgSegDef( ".debug$T" ); } }
extern void DFDefSegs( void ){ /*************************************************/ int i; if( _IsModel( DBG_LOCALS | DBG_TYPES ) ) { for( i = 0; i < DW_DEBUG_MAX; ++i ){ DwarfSegs[i].seg = DbgSegDef( DwarfSegNames[i].seg_name ); DwarfSegs[i].bck = NULL; } } else if( _IsModel( NUMBERS ) ) { DwarfSegs[DW_DEBUG_LINE].seg = DbgSegDef( DwarfSegNames[DW_DEBUG_LINE].seg_name ); DwarfSegs[DW_DEBUG_LINE].bck = NULL; } }
extern void CVDefSymComdat( owl_section_handle depof ){ /**********************************/ if( _IsModel( DBG_LOCALS ) ) { CVSymMain->owl_handle = DbgSectDefComdat( ".debug$S" ); OWLComdatDep( CVSymMain->owl_handle, depof ); } }
static bool ZapsMemory( name *result, name *op, bool for_index ) { /********************************************************************* Could redefining "result" redefine N_MEMORY name "op"? */ switch( result->n.class ) { case N_TEMP: return( false ); case N_MEMORY: if( result->v.symbol != op->v.symbol ) return( false ); /* can be used for memory ops as well */ if( for_index ) return( true ); return( TempsOverlap( result, op ) ); case N_INDEXED: if( result->i.base == NULL ) { if( _IsModel( FORTRAN_ALIASING ) ) return( false ); if( op->v.usage & USE_ADDRESS ) return( true ); return( _IsntModel( RELAX_ALIAS ) ); } if( result->i.base->n.class == N_TEMP ) { return( _IsntModel( RELAX_ALIAS ) ); } else { /* it must be N_MEMORY*/ return( ZapsMemory( result->i.base, op, true ) ); } case N_REGISTER: return( false ); default: _Zoiks( ZOIKS_023 ); return( false ); }
static void InitSegBck( void ) /********************************/ { segment_id old_segid; if( _IsModel( DBG_LOCALS ) ) { old_segid = SetOP( CVSyms ); DataLong( CV_OMF_SIG ); SetOP( old_segid ); } if( _IsModel( DBG_TYPES ) ) { old_segid = SetOP( CVTypes ); DataLong( CV_OMF_SIG ); SetOP( old_segid ); } }
extern void DFObjFiniDbgInfo( offset codesize ) { /******************************/ segment_id old; offset here; back_handle bck; if( _IsModel( DBG_LOCALS | DBG_TYPES ) ) { bck = Comp_High; if( bck != NULL ){ old = SetOP( AskCodeSeg() ); OutLabel( bck->lbl ); SetOP( old ); BEFreeBack( bck ); Comp_High = NULL; } DWEndCompileUnit( Client ); DWFini( Client ); old = SetOP( UnitSize->segment ); here = AskLocation(); SetLocation( UnitSize->offset ); DataLong( codesize ); SetLocation( here ); SetOP( old ); FiniSegBck(); } }
static bool ChkMemLimit( pointer_int limit ) /**********************************************/ { if( _IsModel( MEMORY_LOW_FAILS ) ) return( FALSE ); if( MemInUse() - FrlSize <= limit ) return( FALSE ); FlushSomeOpt( MemInUse() - limit - FrlSize ); if( MemInUse() - FrlSize <= limit ) return( FALSE ); return( TRUE ); }
static void InitVisitedTemps( void ) /*************************************** Mark all N_TEMP and N_MEMORY names as Not visited. If NO_OPTIMIZATION is on, mark them all as visited. */ { name *op; name *alias; op = Names[ N_TEMP ]; while( op != NULL ) { op->t.temp_flags &= ~VISITED; op = op->n.next_name; } op = Names[ N_TEMP ]; while( op != NULL ) { if( op->v.usage & (USE_ADDRESS|VAR_VOLATILE) ) { alias = op; do { alias->t.temp_flags |= VISITED; alias = alias->t.alias; } while( alias != op ); } op = op->n.next_name; } if( _IsModel( NO_OPTIMIZATION ) ) { op = Names[ N_TEMP ]; while( op != NULL ) { if( _FrontEndTmp( op ) ) { op->t.temp_flags |= VISITED; } op = op->n.next_name; } } if( BlockByBlock || _IsModel ( NO_OPTIMIZATION ) ) { op = Names[ N_TEMP ]; while( op != NULL ) { if( op->v.usage & USE_IN_ANOTHER_BLOCK ) { op->t.temp_flags |= VISITED; } op = op->n.next_name; } } }
extern void DFSymRange( cg_sym_handle sym, offset size ) { /*********************************************************/ // I don't see what this is good for. The aranges for any // comdat symbols will be taken care of by DFSegRange(). // Running this code may produce overlapping aranges that // confuse the hell out of the debugger. However, not running // this may cause debug information to be missing... call it // a FIXME if( !_IsModel( DBG_LOCALS | DBG_TYPES ) )return; ARange = FEBack( sym ); DWAddress( Client, size ); }
static source_line_number DumpLineNum( source_line_number n, source_line_number last, bool label_line ) { /*************************************************************************/ if( _IsModel( NUMBERS ) ) { if( n > 0 && n != last ) { last = n; CodeLineNum( n, label_line ); } } return( last ); }
extern void DFSegRange( void ) { /****************************/ /* do arange for the current segment */ back_handle bck; offset off; offset size; if( !_IsModel( DBG_LOCALS | DBG_TYPES ) )return; size = AskMaxSize(); if( size > 0 ) { bck = MakeLabel(); off = AskLocation(); SetLocation( 0 ); DataLabel( bck->lbl ); SetLocation( off ); ARange = bck; DWAddress( Client, size ); BEFreeBack( bck ); } }
static void BlockToCode( bool partly_done ) /*********************************************/ { block_num inputs; block_num targets; block_edge *input_edges; conflict_node *curr; conflict_node **owner; conflict_node *conflist; block_num id; /* try to get back some memory*/ _MemLow; /* make the block look like an entire procedure*/ HeadBlock = CurrBlock; BlockList = CurrBlock; HeadBlock->prev_block = NULL; if( HeadBlock->next_block != NULL ) { HeadBlock->next_block->prev_block = NULL; } /* Kludge - need a pointer to the next block for CALL_LABEL - puke! */ if( HeadBlock->class & CALL_LABEL ) { HeadBlock->v.next = HeadBlock->next_block; } HeadBlock->next_block = NULL; /* force anything that spans blocks to memory */ HeadBlock->u.partition = HeadBlock; ConstFold( HeadBlock ); HeadBlock->u.partition = NULL; ForceTempsMemory(); if( partly_done == FALSE ) { FixMemRefs(); HaveLiveInfo = FALSE; if( _IsntModel( NO_OPTIMIZATION | FORTRAN_ALIASING ) ) { FindReferences(); CommonSex(FALSE); PushPostOps(); } FindReferences(); DeadTemps(); if( _IsModel( NO_OPTIMIZATION ) ) { SetInOut( HeadBlock ); } else { MakeConflicts(); } MakeLiveInfo(); HaveLiveInfo = TRUE; AxeDeadCode(); FixIndex(); FixSegments(); FPRegAlloc(); RegAlloc( TRUE ); FreeConflicts(); HaveLiveInfo = FALSE; } else { conflist = NULL; owner = &ConfList; for( ;; ) { curr = *owner; if( curr == NULL ) break; if( curr->start_block == HeadBlock ) { *owner = curr->next_conflict; curr->next_conflict = conflist; conflist = curr; } else { owner = &curr->next_conflict; } } curr = ConfList; ConfList = conflist; RegAlloc( TRUE ); FreeConflicts(); ConfList = curr; } input_edges = HeadBlock->input_edges; inputs = HeadBlock->inputs; targets = HeadBlock->targets; HeadBlock->inputs = 0; HeadBlock->input_edges = NULL; HeadBlock->targets = 0; FPParms(); PostOptimize(); HeadBlock->input_edges = input_edges; HeadBlock->inputs = inputs; HeadBlock->targets = targets; /* generate a prolog that saves all registers*/ if( ( CurrProc->prolog_state & GENERATED_PROLOG ) == 0 ) { CurrProc->state.used = AllCacheRegs(); GenProlog(); } id = CurrBlock->id; AssgnMoreTemps( id ); OptSegs(); /* generate the code for the block*/ if( CurrBlock->class & RETURN ) { GenObject(); FiniStackMap(); FreeProc(); } else {
static bool ScoreStomp( score_info *x, score_info *y ) { /**********************************************************/ score_info *tmp; /* get the 'free' index into x if there is one*/ if( y->class == N_INDEXED && y->base == NULL ) { tmp = x; x = y; y = tmp; } if( x->class == N_INDEXED && x->base == NULL ) { switch( y->class ) { case N_MEMORY: if( _IsModel( RELAX_ALIAS ) ) return( FALSE ); /* fall through */ case N_INDEXED: return( TRUE ); case N_TEMP: if( y->symbol.v->usage & USE_ADDRESS ) return( TRUE ); return( FALSE ); } } /* get the 'bound' index into x if there is one*/ if( y->class == N_INDEXED ) { tmp = x; x = y; y = tmp; } if( x->class == N_INDEXED && x->base != NULL ) { switch( y->class ) { case N_TEMP: if( x->base->n.class == N_TEMP ) { if( y->symbol.t->v.id == x->base->t.v.id ) return( TRUE ); } break; case N_MEMORY: if( x->base->n.class == N_MEMORY ) { if( y->symbol.p == x->base->v.symbol ) return( TRUE ); } break; case N_INDEXED: if( y->base == NULL ) return( TRUE ); if( y->base->n.class != x->base->n.class ) return( FALSE ); switch( x->base->n.class ) { case N_TEMP: return( y->base->t.v.id == x->base->t.v.id ); case N_MEMORY: return( y->base->v.symbol == x->base->v.symbol ); } break; } } return( FALSE ); }
static void PostOptimize( void ) /******************************************/ { if( _IsntModel( NO_OPTIMIZATION ) ) { // Run peephole optimizer again. Important: It is critical that the // new instructions can be directly generated because RegAlloc is // done by now. PeepOpt() is responsible for verifying that. if( PeepOpt( HeadBlock, NextBlock, NULL, TRUE ) ) { LiveInfoUpdate(); } // this is important as BuildIndex cannot handle instructions with no operands DeadInstructions(); BuildIndex(); DeadInstructions(); } MergeIndex(); if( _IsntModel( NO_OPTIMIZATION ) ) { #if !(_TARGET & _TARG_RISC) // // Calling Conditions() at this point has nice optimization effect, // but doesn't working correctly right now. It optimizes conditions // making them dependent from previous conditions codes, but riscifier // generates XOR's which will trash cond. codes. Either Conditions() // either riscifier must be fixed to handle this situation. // #if 0 // Get rid of unused conditions on variables level // to decrease number of referenced vars in LdStAlloc() and Score() if( _IsntTargetModel( STATEMENT_COUNTING ) ) { Conditions(); DeadInstructions(); // cleanup junk after Conditions() } #endif #endif // OptCloseMoves(); // todo: merge constant moves before riscifier LdStAlloc(); Score(); DeadInstructions(); // cleanup junk after Score() // deRISCify before LoopRegInvariant() or Shedule() are run: // they're moving RISCified pair. LdStCompress(); // Reuse registers freed by deriscifier Score(); DeadInstructions(); // cleanup junk after Score() if( !BlockByBlock ) LoopRegInvariant(); #if !(_TARGET & _TARG_RISC) // Get rid of remaining unused conditions on register level. if( _IsntTargetModel( STATEMENT_COUNTING ) ) { Conditions(); } #endif } FPExpand(); if( _IsntModel( NO_OPTIMIZATION ) ) { DeadInstructions(); // cleanup junk after Conditions() // Run scheduler last, when all instructions are stable if( _IsModel( INS_SCHEDULING ) ) { HaveLiveInfo = FALSE; Schedule(); /* NOTE: Schedule messes up live information */ LiveInfoUpdate(); HaveLiveInfo = TRUE; } // run this again in case Scheduler messed around with indices if( PeepOpt( HeadBlock, NextBlock, NULL, TRUE ) ) { LiveInfoUpdate(); } } FPOptimize(); }
void CVObjInitDbgInfo( void ) /******************************/ /* called by objinit to init segments and for codeview */ { cv_out out[1]; cs_objname *optr; cs_compile *cptr; char *name; InitSegBck(); if( _IsModel( DBG_LOCALS ) ) { NewBuff( out, CVSyms ); optr = StartSym( out, SG_OBJNAME ); optr->signature = 0; name = FEAuxInfo( NULL, OBJECT_FILE_NAME ); CVPutStr( out, name ); EndSym( out ); buffEnd( out ); NewBuff( out, CVSyms ); cptr = StartSym( out, SG_COMPILE ); cptr->language = SetLang(); cptr->flags.s = 0; /* set default */ #if _TARGET & _TARG_IAPX86 cptr->flags.f.Mode32 = false; cptr->machine = MACH_INTEL_8080; #elif _TARGET & _TARG_80386 cptr->machine = MACH_INTEL_80386; cptr->flags.f.Mode32 = true; #elif _TARGET & _TARG_AXP cptr->machine = MACH_DECALPHA; cptr->flags.f.Mode32 = true; cptr->flags.f.FloatPrecision = 1; #endif switch( GetMemModel() ){ case 'h': cptr->flags.f.AmbientData = AMBIENT_HUGE; cptr->flags.f.AmbientCode = AMBIENT_FAR; break; case 'l': cptr->flags.f.AmbientData = AMBIENT_FAR; cptr->flags.f.AmbientCode = AMBIENT_FAR; break; case 'f': case 's': cptr->flags.f.AmbientData = AMBIENT_NEAR; cptr->flags.f.AmbientCode = AMBIENT_NEAR; break; case 'c': cptr->flags.f.AmbientData = AMBIENT_FAR; cptr->flags.f.AmbientCode = AMBIENT_NEAR; break; case 'm': cptr->flags.f.AmbientData = AMBIENT_NEAR; cptr->flags.f.AmbientCode = AMBIENT_FAR; break; default: break; } CVPutStr( out, "WATCOM CV 10.5 " ); EndSym( out ); buffEnd( out ); } }
extern void CVDefSymNormal( void ){ /**********************************/ if( _IsModel( DBG_LOCALS ) ) { CVSymMain->owl_handle = owlCVSym; } }
extern void DFBegCCU( segment_id code, dw_sym_handle dbg_pch ) /****************************************************************/ // Call when codeseg hase been defined { dw_cu_info cu; back_handle bck; segment_id old; type_def *tipe_addr; if( !_IsModel( DBG_LOCALS | DBG_TYPES ) ) { return; } if( CcuDef ) { cu.source_filename = FEAuxInfo( NULL, SOURCE_NAME ); cu.directory = ""; cu.dbg_pch = dbg_pch; cu.inc_list = NULL; cu.inc_list_len = 0; old = SetOP( code ); #if _TARGET & ( _TARG_IAPX86 | _TARG_80386 ) if( _IsTargetModel( FLAT_MODEL ) ) { bck = MakeLabel(); OutLabel( bck->lbl ); Pc_Low = bck; Pc_High = MakeLabel(); // Emitting DW_AT_low_pc and DW_AT_high_pc is valid *only* if the // compilation unit's code is in a single contiguous block (see // DWARF 2, section 3.1). // I don't know how to find out at the time of this call if there's // only one code segment or not, hence these attributes are always // disabled. The low/high pc attribs should probably be handled by // the linker. cu.flags = FALSE; cu.segment_size = 0; } else { bck = NULL; cu.flags = FALSE; Pc_Low = NULL; Pc_High = NULL; cu.segment_size = 2; } #else bck = MakeLabel(); OutLabel( bck->lbl ); Pc_Low = bck; Pc_High = MakeLabel(); cu.flags = TRUE; cu.segment_size = 0; #endif SetOP( old ); Comp_High = Pc_High; tipe_addr = TypeAddress( TY_NEAR_POINTER ); cu.offset_size = tipe_addr->length; switch( GetMemModel() ) { case 'h': cu.model = DW_MODEL_HUGE; break; case 'l': cu.model = DW_MODEL_LARGE; break; case 'f': cu.model = DW_MODEL_FLAT; break; case 's': cu.model = DW_MODEL_SMALL; break; default: cu.model = DW_MODEL_NONE; break; } DWBeginCompileUnit( Client, &cu ); if( cu.flags ) { BEFreeBack( bck ); } } else { CcuDef = TRUE; } }
extern void DFObjInitDbgInfo( void ) { /*****************************************************/ /* called by objinit to init segments and dwarf writing library */ static const dw_funcs cli_funcs = { CLIReloc, CLIWrite, CLISeek, CLITell, CLIAlloc, CLIFree }; dw_init_info info; cg_sym_handle abbrev_sym; cg_sym_handle debug_pch; fe_attr attr; if( _IsntModel( DBG_LOCALS | DBG_TYPES ) ){ return; } info.compiler_options = DW_CM_DEBUGGER; info.abbrev_sym = 0; info.producer_name = SetDwarfProducer(); info.language = SetLang(); if( setjmp( info.exception_handler ) == 0 ) { info.funcs = cli_funcs; InitSegBck(); // start each seg with a ref label if( _IsModel( DBG_PREDEF ) ) { abbrev_sym = FEAuxInfo( NULL, DBG_PREDEF_SYM ); info.abbrev_sym = (dw_sym_handle)abbrev_sym; attr = FEAttr( abbrev_sym ); if( (attr & FE_IMPORT) ) { info.compiler_options |= DW_CM_ABBREV_PRE; }else{ back_handle bck; segment_id old; info.compiler_options |= DW_CM_ABBREV_GEN; bck = FEBack( abbrev_sym ); // dump out export label bck->seg = DwarfSegs[DW_DEBUG_ABBREV].seg; old = SetOP( DwarfSegs[DW_DEBUG_ABBREV].seg ); DataLabel( bck->lbl ); SetOP( old ); } } debug_pch = FEAuxInfo( NULL, DBG_PCH_SYM ); if( debug_pch != NULL ){ attr = FEAttr( debug_pch ); if( !(attr & FE_IMPORT) ) { back_handle bck; segment_id old; bck = FEBack( debug_pch ); bck->seg = DwarfSegs[DW_DEBUG_INFO].seg; old = SetOP( DwarfSegs[DW_DEBUG_INFO].seg ); DataLabel( bck->lbl ); SetOP( old ); debug_pch = NULL; } } Client = DWInit( &info ); if( Client == NULL ) { Zoiks( ZOIKS_107 ); /* Bad */ } DFBegCCU( AskCodeSeg(), (dw_sym_handle)debug_pch ); } else { Zoiks( ZOIKS_107 ); /* Big Error */ } }