void CVOutSym( cv_out *out, cg_sym_handle sym ) /*** Put a sym in out ***************************/ { dbg_type tipe; fe_attr attr; const char *nm; attr = FEAttr( sym ); tipe = FEDbgType( sym ); nm = FEName( sym ); if( attr & FE_STATIC ) { cs_gdata *ptr; sg_index kind; if( attr & FE_GLOBAL ) { kind = SG_GDATA; } else { kind = SG_LDATA; } ptr = StartSym( out, kind ); ptr->offset = 0; ptr->segment = 0; ptr->type = tipe; CVPutStr( out, nm ); EndSym( out ); } else { FrameVar( out, nm, tipe, 0 ); } }
extern void GenObject( void ) /*******************************/ { block *blk; block *next_blk; instruction *ins; source_line_number last_line; block_num targets; block_num i; segment_id old; label_handle lbl; unsigned align; fe_attr attr; old = SetOP( AskCodeSeg() ); InitZeroPage(); last_line = 0; attr = FEAttr( AskForLblSym( CurrProc->label ) ); for( blk = HeadBlock; blk != NULL; blk = next_blk ) { if( blk->label != CurrProc->label && blk->label != NULL ) { last_line = DumpLineNum( blk->ins.hd.line_num, last_line, TRUE ); if( ( blk->class & ITERATIONS_KNOWN ) && blk->iterations >= 10 ) { align = DepthAlign( DEEP_LOOP_ALIGN ); } else { align = DepthAlign( blk->depth ); } CodeLabel( blk->label, align ); if( ( blk->edge[ 0 ].flags & BLOCK_LABEL_DIES ) != 0 && BlocksUnTrimmed ) { TellCondemnedLabel( blk->label ); } }
void CVProEnd( dbg_rtn *rtn, offset lc ) /*****************************************/ { cg_sym_handle sym; dbg_type tipe; fe_attr attr; const char *name; cs_gproc *ptr; sg_index kind; cv_out out[1]; /* unused parameters */ (void)lc; sym = AskForLblSym( CurrProc->label ); attr = FEAttr( sym ); if( attr & FE_GLOBAL ){ kind = SG_GPROC; }else{ kind = SG_LPROC; } NewBuff( out, CVSyms ); ptr = StartSym( out, kind ); ptr->pParent = 0; ptr->pEnd = 0; ptr->pNext = 0; ptr->proc_length = 0; ptr->debug_start = rtn->pro_size; ptr->debug_end = 0; ptr->offset = 0; ptr->segment = 0; tipe = FEDbgType( sym ); ptr->proctype = tipe; ptr->flags.s = 0; #if _TARGET & ( _TARG_IAPX86 | _TARG_80386 ) if( *(call_class *)FindAuxInfoSym( sym, CALL_CLASS ) & FAR_CALL ) { ptr->flags.f.far_ret = true; } #endif if( rtn->obj_type != DBG_NIL_TYPE ) { name = FEAuxInfo( sym, CLASS_APPENDED_NAME ); } else { name = FEName( sym ); } CVPutStr( out, name ); EndSym( out ); BuffPatchSet( CVSyms, RtnPatch ); BuffWrite( out, &ptr->offset ); SymReloc( CVSyms, sym, 0 ); BuffSkip( out, &ptr->proctype ); buffEnd( out ); DBLocFini( rtn->reeturn ); DBLocFini( rtn->obj_loc ); if( rtn->parms != NULL ){ DumpParms( rtn->parms, &rtn->rtn_blk->locals ); } DumpLocals( rtn->rtn_blk->locals ); }
void CVGenStatic( cg_sym_handle sym, dbg_loc loc, bool mem ) /*************************************************************/ { dbg_type tipe; cv_out out[1]; fe_attr attr; cs_gdata *ptr; sg_index kind; const char *name; attr = FEAttr( sym ); tipe = FEDbgType( sym ); NewBuff( out, CVSyms ); attr = FEAttr( sym ); if( attr & FE_GLOBAL ) { kind = SG_GDATA; } else { kind = SG_LDATA; } ptr = StartSym( out, kind ); ptr->offset = 0; ptr->segment = 0; ptr->type = tipe; if( mem ){ name = FEAuxInfo( sym, CLASS_APPENDED_NAME ); } else { name = FEName( sym ); } CVPutStr( out, name ); EndSym( out ); if( LocSimpStatic( loc ) == sym ) { BuffWrite( out, &ptr->offset ); SymReloc( CVSyms, sym, 0 ); BuffSkip( out, &ptr->type ); } else { /*TODO:can't handle locs */ } buffEnd( out ); }
extern bool SymIsExported( cg_sym_handle sym ) { /*******************************************/ bool exported; exported = FALSE; if( sym != NULL ) { if( FEAttr( sym ) & FE_DLLEXPORT ) { exported = TRUE; } else if( *(call_class*)FindAuxInfoSym( sym, CALL_CLASS ) & DLL_EXPORT ) { exported = TRUE; } } return( exported ); }
extern void DFGenStatic( cg_sym_handle sym, dbg_loc loc ) { /*******************************************************************/ uint flags; fe_attr attr; const char *name; dw_loc_handle dw_loc; dw_loc_handle dw_segloc; dw_handle obj; dbg_type dbtype; attr = FEAttr( sym ); if( attr & FE_GLOBAL ){ flags = DW_FLAG_GLOBAL; }else{ flags = 0; } name = FEName( sym ); if( attr & FE_STATIC ){ #if _TARGET & ( _TARG_IAPX86 | _TARG_80386 ) if( _IsTargetModel( FLAT_MODEL ) ) { dw_segloc = NULL; }else{ dw_segloc = SegLoc( sym ); } #else dw_segloc = NULL; #endif }else{ dw_segloc = NULL; } dbtype = FEDbgType( sym ); /* causes name side effects */ dw_loc = DBGLoc2DF( loc ); obj = DWVariable( Client, dbtype, dw_loc, 0, dw_segloc, name, 0, flags ); if( attr & FE_GLOBAL ){ name = FEName( sym ); DWPubname( Client, obj, name ); } if( dw_loc != NULL ){ DWLocTrash( Client, dw_loc ); } if( dw_segloc != NULL ){ DWLocTrash( Client, dw_segloc ); } }
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 */ } }
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 ); }
static void ExpandTlsOp( instruction *ins, name **pop ) /********************************************************** If *pop is a ref to a piece of thread-local data, replace it by a ref to an index [t1] and prepend the magic sequence to get the address of a piece of tls data to the instruction. Here is the sequence to access variable foo: mov fs:__tls_array -> t1 mov __tls_index -> t2 mov t2 * 4 -> t2 add t1, t2 -> t1 mov [ t1 ] -> t3 mov foo[ t3 ] -> result */ { fe_attr attr; name *op; name *temp; name *tls_data; name *index; name *base; instruction *new_ins; op = *pop; switch( op->n.class ) { case N_MEMORY: if( op->m.memory_type == CG_FE ) { attr = FEAttr( op->v.symbol ); if( ( attr & FE_THREAD_DATA ) != 0 ) { *pop = GetTLSDataRef( ins, op, _OpClass(ins) ); } } break; case N_INDEXED: // gotta check for the base being one of these stupid TLS things if( op->i.base != NULL && ( op->i.index_flags & X_FAKE_BASE ) == 0 ) { base = op->i.base; if( base->n.class != N_MEMORY || base->m.memory_type != CG_FE ) break; attr = FEAttr( base->v.symbol ); if( ( attr & FE_THREAD_DATA ) == 0 ) break; tls_data = GetTLSDataRef( ins, base, _OpClass(ins) ); temp = AllocTemp( WD ); new_ins = MakeUnary( OP_LA, tls_data, temp, WD ); PrefixIns( ins, new_ins ); index = op->i.index; if( op->i.scale != 0 ) { const signed_32 values[] = { 1, 2, 4, 8, 16 }; if( op->i.scale > 4 ) _Zoiks( ZOIKS_134 ); index = AllocTemp( WD ); new_ins = MakeBinary( OP_MUL, op->i.index, AllocS32Const( values[ op->i.scale ] ), index, WD ); PrefixIns( ins, new_ins ); } new_ins = MakeBinary( OP_ADD, temp, index, temp, WD ); PrefixIns( ins, new_ins ); *pop = ScaleIndex( temp, NULL, 0, _OpClass(ins), TypeClassSize[ _OpClass(ins) ], 0, 0 ); } break; }