00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "output_func_start_profiler.h"
00026 #include "sections.h"
00027 #include "stblock.h"
00028
00029 #define ROUNDUP(val,align) ( (-(INT64)align) & (INT64)(val+align-1) )
00030 static ST* Get_Section_ST(SECTION_IDX sec, UINT align, ST_SCLASS sclass);
00031
00032 extern WN * Gen_Call( const char *name, TYPE_ID rtype = MTYPE_V );
00033 extern WN * Gen_Call( const char *name, WN *arg1, TYPE_ID rtype = MTYPE_V);
00034 extern WN * Gen_Call( const char *name, WN *arg1, WN *arg2, TYPE_ID rtype = MTYPE_V );
00035 extern WN * Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, TYPE_ID rtype= MTYPE_V);
00036 extern WN * Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, WN *arg4, TYPE_ID rtype = MTYPE_V);
00037 extern WN * Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, WN *arg4, WN *arg5, TYPE_ID rtype = MTYPE_V );
00038 extern WN * Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, WN *arg4, WN *arg5, WN *arg6, TYPE_ID rtype = MTYPE_V );
00039
00040
00041 const char* OUTPUT_FUNC_START_PROFILER::_prefix = "_GLOBAL__GCOV_";
00042 #ifdef GCC_303
00043 const char* OUTPUT_FUNC_START_PROFILER::_init_proc = "__gcov_init";
00044 #else
00045 const char* OUTPUT_FUNC_START_PROFILER::_init_proc = "__bb_init_func";
00046 #endif
00047 const char* OUTPUT_FUNC_START_PROFILER::_lpbx_0 = "LPBX0";
00048
00049 OUTPUT_FUNC_START_PROFILER Output_Func_Start_Profiler;
00050
00051 OUTPUT_FUNC_START_PROFILER::OUTPUT_FUNC_START_PROFILER(const char* src_file_name, PU_Info** pu_tree_p)
00052 : _file_name(src_file_name),
00053 _pu_tree_p(pu_tree_p),
00054 _func_st(NULL),
00055 _func_entry(NULL),
00056 _func_body(NULL),
00057 _pu_info(NULL),
00058 _func_level(0),
00059 _func_name(NULL) {}
00060
00061 char*
00062 OUTPUT_FUNC_START_PROFILER::Construct_Func_Name(const char *name)
00063 {
00064 char* func_name = TYPE_MEM_POOL_ALLOC_N(char, &_mem_pool, strlen(name) + strlen(_file_name) + 1);
00065 sprintf(func_name, "%s%s", name, _file_name);
00066 for(INT i = 0; func_name[i]; i++){
00067 if( !( func_name[i] == '_'
00068 || ('0' <= func_name[i] && func_name[i] <= '9')
00069 || ('A' <= func_name[i] && func_name[i] <= 'Z')
00070 || ('a' <= func_name[i] && func_name[i] <= 'z')) )
00071 func_name[i] = '_';
00072 }
00073 return func_name;
00074 }
00075
00076 void
00077 OUTPUT_FUNC_START_PROFILER::Generate_Func_Start_Profiler_PU(void)
00078 {
00079 if(*_pu_tree_p == NULL)
00080 return;
00081
00082
00083 TY_IDX func_ty_idx;
00084 TY& func_ty = New_TY(func_ty_idx);
00085 TY_Init(func_ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, STR_IDX_ZERO);
00086
00087
00088 TYLIST_IDX parm_idx;
00089 TYLIST& parm_list = New_TYLIST(parm_idx);
00090 Set_TY_tylist(func_ty, parm_idx);
00091 Set_TYLIST_type(parm_list, Be_Type_Tbl(MTYPE_V));
00092 Set_TYLIST_type(New_TYLIST(parm_idx), MTYPE_To_TY(MTYPE_V));
00093
00094
00095 _func_name = Construct_Func_Name(_prefix);
00096
00097
00098 PU_IDX pu_idx;
00099 PU& new_pu = New_PU(pu_idx);
00100 PU_Init(new_pu, func_ty_idx, GLOBAL_SYMTAB + 1);
00101
00102 Set_PU_no_inline(new_pu);
00103
00104
00105 _func_st = New_ST(GLOBAL_SYMTAB);
00106 ST_Init(_func_st,
00107 Save_Str(_func_name),
00108 CLASS_FUNC,
00109 SCLASS_TEXT,
00110 EXPORT_INTERNAL,
00111 pu_idx);
00112 Allocate_Object(_func_st);
00113
00114
00115 New_Scope(GLOBAL_SYMTAB + 1, &_mem_pool, TRUE);
00116 _func_level = CURRENT_SYMTAB;
00117 Scope_tab[_func_level].st = _func_st;
00118 Set_PU_lexical_level(new_pu, _func_level);
00119
00120
00121 _func_body = WN_CreateBlock();
00122 _func_entry = WN_CreateEntry(0, _func_st,
00123 _func_body,
00124 WN_CreateBlock(),
00125 WN_CreateBlock());
00126
00127
00128 _pu_info = CXX_NEW(PU_Info, &_mem_pool);
00129 PU_Info_init(_pu_info);
00130
00131 Set_PU_Info_tree_ptr(_pu_info, _func_entry);
00132 Set_PU_Info_state(_pu_info, WT_SYMTAB, Subsect_InMem);
00133 Set_PU_Info_state(_pu_info, WT_TREE, Subsect_InMem);
00134 Set_PU_Info_state(_pu_info, WT_PROC_SYM, Subsect_InMem);
00135 Set_PU_Info_flags(_pu_info, PU_IS_COMPILER_GENERATED | PU_IS_PROFILER);
00136
00137
00138 PU_Info_proc_sym(_pu_info) = ST_st_idx(_func_st);
00139
00140
00141 PU_Info_maptab(_pu_info) = WN_MAP_TAB_Create(&_mem_pool);
00142
00143 PU_Info_pu_dst (_pu_info) = DST_INVALID_IDX;
00144 PU_Info_cu_dst (_pu_info) = DST_INVALID_IDX;
00145
00146
00147 Set_PU_Info_symtab_ptr(_pu_info, NULL);
00148 Save_Local_Symtab(_func_level, _pu_info);
00149
00150
00151 if(PU_c_lang(PU_Info_pu(*_pu_tree_p)))
00152 Set_PU_c_lang(new_pu);
00153 if(PU_cxx_lang(PU_Info_pu(*_pu_tree_p)))
00154 Set_PU_cxx_lang(new_pu);
00155 if(PU_f77_lang(PU_Info_pu(*_pu_tree_p)))
00156 Set_PU_f77_lang(new_pu);
00157 if(PU_f90_lang(PU_Info_pu(*_pu_tree_p)))
00158 Set_PU_f90_lang(new_pu);
00159
00160
00161
00162
00163
00164
00165
00166
00167 PU_Info_next(_pu_info) = *_pu_tree_p;
00168 *_pu_tree_p = _pu_info;
00169
00170
00171 TY_IDX func_ptr_ty_idx = Make_Pointer_Type(func_ty_idx);
00172 ST* _ctor_st = New_ST(GLOBAL_SYMTAB);
00173 ST_Init(_ctor_st, Save_Str(Construct_Func_Name("__ctors_")),
00174 CLASS_VAR, SCLASS_FSTATIC, EXPORT_LOCAL, func_ptr_ty_idx);
00175 Set_ST_is_initialized(_ctor_st);
00176 Clear_ST_gprel(_ctor_st);
00177
00178
00179 ST *newblk = NULL;
00180 ST *st;
00181 INT i;
00182 FOREACH_SYMBOL (GLOBAL_SYMTAB,st,i) {
00183 if (ST_class(st) != CLASS_BLOCK) continue;
00184 if (STB_section_idx(st) == _SEC_DATA && strcmp(ST_name(st), ".ctors") ==0){
00185 newblk = st;
00186 break;
00187 }
00188 }
00189 if (newblk == NULL) {
00190 ST *blk = Get_Section_ST(_SEC_DATA, 0, SCLASS_UNKNOWN);
00191 newblk = Copy_ST_Block(blk);
00192
00193 Set_STB_size(newblk, 0);
00194 Set_ST_name_idx(newblk, Save_Str(".ctors"));
00195 }
00196 Set_ST_base(_ctor_st, newblk);
00197
00198 INT64 old_offset;
00199 INT64 size = 8;
00200 old_offset = STB_size(newblk);
00201 Set_ST_ofst(_ctor_st, ROUNDUP(old_offset, 8));
00202 Set_STB_size(newblk, ROUNDUP(ST_ofst(_ctor_st) + size, 8));
00203
00204 INITO_IDX inito_ctor = New_INITO(_ctor_st);
00205 INITV_IDX initv_ctor;
00206 initv_ctor = New_INITV();
00207 INITV_Init_Symoff(initv_ctor, _func_st, 0);
00208 Append_INITV(initv_ctor, inito_ctor, INITV_IDX_ZERO);
00209
00210 return;
00211 }
00212
00213
00214 void
00215 OUTPUT_FUNC_START_PROFILER::Fill_In_Func_Body(void)
00216 {
00217
00218
00219 TY_IDX func_ty_idx;
00220 TY& func_ty = New_TY(func_ty_idx);
00221 TY_Init(func_ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, TY_IDX_ZERO);
00222
00223
00224 TYLIST_IDX parm_idx;
00225 TYLIST& parm_list = New_TYLIST(parm_idx);
00226 Set_TY_tylist(func_ty, parm_idx);
00227 Set_TYLIST_type(parm_list, Be_Type_Tbl(MTYPE_V));
00228 Set_TYLIST_type(New_TYLIST(parm_idx), MTYPE_To_TY(MTYPE_V));
00229
00230
00231 PU_IDX pu_idx;
00232 PU& new_pu = New_PU(pu_idx);
00233 PU_Init(new_pu, func_ty_idx, GLOBAL_SYMTAB + 1);
00234
00235 Set_PU_no_inline(new_pu);
00236
00237
00238 _func_st = New_ST(GLOBAL_SYMTAB);
00239 ST_Init(_func_st,
00240 Save_Str(_init_proc),
00241 CLASS_FUNC,
00242 SCLASS_TEXT,
00243 EXPORT_PROTECTED,
00244 pu_idx);
00245 #ifdef GCC_303
00246 UINT32 magic_size = 8;
00247 UINT32 zero_word_size = 8;
00248 UINT32 filename_size = 8;
00249 UINT32 counts_size = 8;
00250 UINT32 ncounts_size = 8;
00251 UINT32 next_size = 8;
00252 UINT32 sizeofbb_size = 8;
00253 UINT32 bb_function_info_size = 8;
00254 UINT32 size = zero_word_size + filename_size + counts_size + ncounts_size + next_size + sizeofbb_size + bb_function_info_size;
00255 #else
00256 UINT32 size;
00257 #ifdef TARG_X8664
00258 if (Is_Target_32bit())
00259 size = 7*4;
00260 else
00261 #endif // TARG_X8664
00262 size = 7*8;
00263 #endif
00264
00265 TY_IDX tyi;
00266 TY& ty = New_TY(tyi);
00267 TY_Init(ty, size, KIND_STRUCT, MTYPE_M,
00268 STR_IDX_ZERO);
00269 #ifdef TARG_X8664
00270 Set_TY_align(tyi, Is_Target_32bit()? 4 : 32);
00271 #else
00272 Set_TY_align(tyi, 32);
00273 #endif
00274 _lpbx_st = New_ST(GLOBAL_SYMTAB);
00275 ST_Init(_lpbx_st, Save_Str(Construct_Func_Name(_lpbx_0)),
00276 CLASS_VAR, SCLASS_PSTATIC, EXPORT_PREEMPTIBLE, tyi);
00277 Set_ST_is_initialized(_lpbx_st);
00278 Set_ST_is_not_used(_lpbx_st);
00279 #ifdef TARG_X8664
00280 WN* parm_var_addr =
00281 WN_CreateLda (OPCODE_make_op(OPR_LDA, Pointer_type, MTYPE_V),
00282 0,
00283 Make_Pointer_Type(Is_Target_32bit() ?
00284 MTYPE_To_TY(MTYPE_I4) :
00285 MTYPE_To_TY(MTYPE_I8),
00286 FALSE),
00287 _lpbx_st);
00288 #else
00289 WN* parm_var_addr =
00290 WN_CreateLda (OPCODE_make_op(OPR_LDA, Pointer_type, MTYPE_V),
00291 0,
00292 Make_Pointer_Type(MTYPE_I8, FALSE),
00293 _lpbx_st);
00294 #endif
00295 WN* call_stmt;
00296 call_stmt = Gen_Call(_init_proc,
00297 parm_var_addr
00298 );
00299 WN_INSERT_BlockBefore(_func_body, NULL, call_stmt);
00300
00301 WN* ret_stmt = WN_CreateReturn();
00302 WN_INSERT_BlockBefore(_func_body, NULL, ret_stmt);
00303
00304 return;
00305 }
00306
00307 static ST*
00308 Get_Section_ST(SECTION_IDX sec, UINT align, ST_SCLASS sclass)
00309 {
00310 if (SEC_block(sec) == NULL) {
00311 ST *new_blk = New_ST_Block (Save_Str(SEC_name(sec)),
00312 TRUE, sclass, align, 0);
00313 Set_STB_section_idx(new_blk, sec);
00314 SEC_block(sec) = new_blk;
00315 Set_STB_section(new_blk);
00316 Set_STB_root_base(new_blk);
00317 if (SEC_is_gprel(sec)) {
00318 Set_STB_is_basereg(new_blk);
00319 Set_ST_gprel(new_blk);
00320 }
00321 if (SEC_is_merge(sec))
00322 Set_STB_merge(new_blk);
00323 if (SEC_is_exec(sec))
00324 Set_STB_exec(new_blk);
00325 if (SEC_is_nobits(sec))
00326 Set_STB_nobits(new_blk);
00327 Enter_ST(new_blk);
00328 }
00329 return SEC_block(sec);
00330 }
00331