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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "bb.h"
00044 #include "cg.h"
00045 #include "cg_region.h"
00046 #include "cg_flags.h"
00047 #include "cgexp.h"
00048 #include "cgexp_internals.h"
00049 #include "cxx_memory.h"
00050 #include "data_layout.h"
00051 #include "defs.h"
00052 #include "flags.h"
00053 #include "gcov-io.h"
00054 #include "glob.h"
00055 #include "ir_reader.h"
00056 #include "label_util.h"
00057 #include "mempool.h"
00058 #include "stblock.h"
00059 #include "symtab.h"
00060 #include "symtab_access.h"
00061 #include "unistd.h"
00062
00063 #ifdef TARG_MIPS
00064 #if defined(TARG_SL)
00065 static BOOL inline Is_Target_32bit (void) { return TRUE; }
00066 #else
00067
00068 static BOOL inline Is_Target_32bit (void) { return FALSE; }
00069 #endif
00070 #endif // TARG_MIPS
00071
00072 MEM_POOL name_pool, *name_pool_ptr = NULL;
00073 #define MAX_COUNTER_SECTIONS 4
00074 #define BB_TO_GCOV_INDEX(bb) BB_id(bb)
00075 #define MAXPATHLEN 100
00076
00077 struct function_list
00078 {
00079 struct function_list *next;
00080 char *name;
00081 long cfg_checksum;
00082 #ifdef GCC_303
00083 unsigned n_counter_sections;
00084 struct counter_section counter_sections[MAX_COUNTER_SECTIONS];
00085 #else
00086 long count_edges;
00087 #endif
00088 };
00089
00090 static struct function_list *functions_head = 0;
00091 static struct function_list **functions_tail = &functions_head;
00092
00093
00094
00095 static FILE *bbg_file;
00096 static char* bbg_file_name;
00097
00098 #ifndef GCC_303
00099 static FILE *bb_file;
00100 #endif
00101
00102
00103
00104 static FILE *da_file;
00105
00106
00107
00108 static int last_bb_file_num, last_bb_line_num;
00109 static int local_n_edges = 0;
00110 static int local_n_a_edges = 0;
00111 static int local_n_basic_blocks = 0;
00112 static int n_instr_edges = 0;
00113
00114
00115 static int pu_flag = -1;
00116 static int begin_id = -1, end_id = -1;
00117 static long chksum = 0;
00118
00119 # define DIR_SEPARATOR '/'
00120 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
00121 char *
00122 lbasename (char *name)
00123 {
00124 char *base;
00125 for (base = name; *name; name++)
00126 if (IS_DIR_SEPARATOR (*name))
00127 base = name + 1;
00128
00129 return base;
00130 }
00131 char *
00132 getpwd ()
00133 {
00134 static char *pwd = 0;
00135 if (!pwd)
00136 pwd = getcwd (CXX_NEW_ARRAY(char, MAXPATHLEN + 1, name_pool_ptr), MAXPATHLEN + 1);
00137 return pwd;
00138 }
00139 static ST * get_symbol(const char* sym_name)
00140 {
00141 ST *st;
00142 int i;
00143 FOREACH_SYMBOL (GLOBAL_SYMTAB, st, i) {
00144 if (ST_class(st) == CLASS_VAR && strncmp(ST_name(st), sym_name, strlen(sym_name))==0){
00145 return st;
00146 break;
00147 }
00148 }
00149 return NULL;
00150 }
00151
00152 void Gcov_BB_Prepend_Ops(BB *bb, OPS *ops)
00153 {
00154 #ifdef TARG_X8664
00155 if (OPS_first(ops) == NULL) return;
00156 OP *op = BB_first_op(bb);
00157 if (op && OP_opnds(op) > 0 &&
00158 TN_is_register(OP_opnd(op, 0)) &&
00159 TN_register(OP_opnd(op, 0)) == RAX)
00160 BB_Insert_Ops_After(bb, op, ops);
00161 else
00162 BB_Prepend_Ops(bb, ops);
00163 #else
00164
00165 return;
00166 #endif
00167 }
00168
00169 #ifdef GCC_303
00170 void
00171 CG_Init_Couner_Infos(ST *counter_section)
00172 {
00173 struct function_list *item = functions_head;
00174 ST *st = get_symbol("LPBX2");
00175 FmtAssert (st != NULL, ("Symbol LPBX2 should have generated before"));
00176
00177 TY_IDX tyi;
00178 TY& ty = New_TY(tyi);
00179 TY_Init(ty, n_instr_edges*8, KIND_STRUCT, MTYPE_M,
00180 STR_IDX_ZERO);
00181 Set_TY_align(tyi, 8);
00182 ST* new_st = New_ST(GLOBAL_SYMTAB);
00183 ST_Init(new_st, Save_Str("LPBX2_TMP"),
00184 CLASS_VAR, SCLASS_PSTATIC, EXPORT_LOCAL, tyi);
00185
00186 Allocate_Object(new_st);
00187 INITO_IDX inito_lpbx2 = New_INITO(st);
00188 INITV_IDX initv_lpbx2;
00189 initv_lpbx2 = New_INITV();
00190 INITV_Init_Symoff(initv_lpbx2, new_st, 0);
00191 Append_INITV(initv_lpbx2, inito_lpbx2, INITV_IDX_ZERO);
00192
00193
00194 INITV_IDX prev_initv = INITV_IDX_ZERO;
00195 INITO_IDX inito_counter = New_INITO(counter_section);
00196 INITV_IDX inv_counter;
00197 for (INT i = 0; i < item->n_counter_sections; i++)
00198 {
00199 inv_counter = New_INITV();
00200 INITV_Init_Integer(inv_counter, MTYPE_I4, GCOV_TAG_ARC_COUNTS);
00201 prev_initv = Append_INITV(inv_counter, inito_counter, prev_initv);
00202 inito_counter = INITO_IDX_ZERO;
00203 inv_counter = New_INITV();
00204 INITV_Init_Integer(inv_counter, MTYPE_I4, n_instr_edges);
00205 prev_initv = Append_INITV(inv_counter, inito_counter, prev_initv);
00206
00207 inv_counter = New_INITV();
00208 INITV_Init_Symoff(inv_counter, new_st, 0);
00209 prev_initv = Append_INITV(inv_counter, inito_counter, prev_initv);
00210 }
00211 }
00212 #endif
00213 void
00214 CG_Init_Func_Infos(ST *func_infos)
00215 {
00216 struct function_list *item = functions_head;
00217 TY_IDX table;
00218 ST *listvar;
00219 INITO_IDX ino;
00220 INITV_IDX inv;
00221 INITO_IDX inito;
00222 INITV_IDX last_aggregate_initv = INITV_IDX_ZERO;
00223 inito = New_INITO(func_infos);
00224 TYPE_ID rtype;
00225
00226 if (Is_Target_32bit())
00227 rtype = MTYPE_I4;
00228 else
00229 rtype = MTYPE_I8;
00230
00231
00232 for (; item != 0; item = item->next){
00233 #ifndef GCC_303
00234
00235 inv = New_INITV();
00236 INITV_Init_Integer(inv, rtype, item->cfg_checksum);
00237 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00238 inito = INITO_IDX_ZERO;
00239
00240 inv = New_INITV();
00241 INITV_Init_Integer(inv, MTYPE_I4, item->count_edges);
00242 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00243
00244 if (Is_Target_64bit()) {
00245 inv = New_INITV();
00246 INITV_Init_Pad(inv, 4);
00247 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00248 }
00249 #endif
00250
00251 table = Make_Array_Type(MTYPE_U2, 1, strlen(item->name)+1);
00252 listvar = Gen_Read_Only_Symbol(table, item->name);
00253 Set_ST_is_initialized(listvar);
00254 ino = New_INITO(listvar);
00255 inv = New_INITV();
00256 INITV_Init_String(inv, item->name, strlen(item->name)+1);
00257 Append_INITV (inv, ino, INITV_IDX_ZERO);
00258 Allocate_Object(listvar);
00259
00260 inv = New_INITV();
00261 INITV_Init_Symoff (inv, listvar, 0);
00262 last_aggregate_initv = Append_INITV (inv, inito, last_aggregate_initv);
00263
00264 inito = INITO_IDX_ZERO;
00265 #ifdef GCC_303
00266
00267 inv = New_INITV();
00268 INITV_Init_Integer(inv, MTYPE_I4, item->cfg_checksum);
00269 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00270
00271 inv = New_INITV();
00272 INITV_Init_Integer(inv, MTYPE_I4, item->n_counter_sections);
00273 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00274
00275
00276 UINT32 tag_size = 4;
00277 UINT32 n_counters_size = 4;
00278 UINT32 counter_section_size = tag_size + n_counters_size;
00279
00280 TY_IDX tyi_counter;
00281 ST *counter_section;
00282
00283 TY& ty_counter = New_TY(tyi_counter);
00284 TY_Init(ty_counter, counter_section_size*item->n_counter_sections, KIND_STRUCT, MTYPE_M, STR_IDX_ZERO);
00285 Set_TY_align(tyi_counter, 8);
00286 counter_section = New_ST(GLOBAL_SYMTAB);
00287 ST_Init(counter_section, STR_IDX_ZERO, CLASS_VAR, SCLASS_FSTATIC, EXPORT_LOCAL, tyi_counter);
00288 Set_ST_is_initialized(counter_section);
00289 Allocate_Object(counter_section);
00290
00291 INITV_IDX prev_initv = INITV_IDX_ZERO;
00292 INITO_IDX inito_counter = New_INITO(counter_section);
00293 INITV_IDX inv_counter;
00294 for (INT i = 0; i < item->n_counter_sections; i++)
00295 {
00296 inv_counter = New_INITV();
00297 INITV_Init_Integer(inv_counter, MTYPE_I4, GCOV_TAG_ARC_COUNTS);
00298 prev_initv = Append_INITV(inv_counter, inito_counter, prev_initv);
00299 inito_counter = INITO_IDX_ZERO;
00300 inv_counter = New_INITV();
00301 INITV_Init_Integer(inv_counter, MTYPE_I4, item->counter_sections[0].n_counters);
00302 prev_initv = Append_INITV(inv_counter, inito_counter, prev_initv);
00303 }
00304
00305 inv = New_INITV();
00306 INITV_Init_Symoff (inv, counter_section, 0);
00307 last_aggregate_initv = Append_INITV (inv, inito, last_aggregate_initv);
00308 #endif
00309 }
00310 #ifndef GCC_303
00311 inv = New_INITV();
00312 INITV_Init_Pad(inv, Is_Target_32bit() ? 4 : 8 );
00313 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00314 inito = INITO_IDX_ZERO;
00315 inv = New_INITV();
00316 INITV_Init_Integer(inv, MTYPE_I4, -1);
00317 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00318 inv = New_INITV();
00319 INITV_Init_Pad(inv, Is_Target_32bit() ? 4 : 12 );
00320 last_aggregate_initv = Append_INITV(inv, inito, last_aggregate_initv);
00321 #endif
00322 }
00323
00324 #if 0
00325
00326 struct counter_section
00327 {
00328 unsigned tag;
00329 unsigned n_counters;
00330 };
00331
00332
00333 struct counter_section_data
00334 {
00335 unsigned tag;
00336 unsigned n_counters;
00337 gcov_type *counters;
00338 };
00339
00340
00341 struct function_info
00342 {
00343 const char *name;
00344 unsigned checksum;
00345 unsigned n_counter_sections;
00346 const struct counter_section *counter_sections;
00347
00348 };
00349
00350
00351 struct gcov_info
00352 {
00353 unsigned long version;
00354 struct gcov_info *next;
00355
00356 const char *filename;
00357 long wkspc;
00358
00359 unsigned n_functions;
00360 const struct function_info *functions;
00361
00362 unsigned n_counter_sections;
00363 const struct counter_section_data *counter_sections;
00364
00365 };
00366
00367
00368
00369
00370 #endif
00371 void
00372 CG_End_Final()
00373 {
00374 int num_nodes = 0;
00375 struct function_list *item;
00376 for (item = functions_head; item != 0; item = item->next)
00377 {
00378 num_nodes++;
00379 }
00380 if (num_nodes == 0) return;
00381 ST *st = get_symbol("LPBX0");
00382 FmtAssert (st != NULL, ("Symbol LPBX0 should have generated before"));
00383 if ( ST_is_not_used(st) ){
00384 Clear_ST_is_not_used(st);
00385 Allocate_Object(st);
00386 }
00387
00388 #ifdef GCC_303
00389
00390 INITO_IDX aggregate_inito = New_INITO(st);
00391 INITV_IDX inv = New_INITV();
00392 INITV_Init_Integer(inv, MTYPE_U8, GCOV_VERSION);
00393 INITV_IDX last_aggregate_initv;
00394 last_aggregate_initv = Append_INITV (inv, aggregate_inito, INITV_IDX_ZERO);
00395
00396
00397 inv = New_INITV();
00398 INITV_Init_Integer(inv, MTYPE_U8, 0);
00399 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00400
00401
00402 char *cwd, *da_filename;
00403 int da_filename_len;
00404
00405 cwd = getpwd ();
00406 da_filename_len = strlen (Src_File_Name) + strlen (cwd) + 4 + 1;
00407 da_filename = CXX_NEW_ARRAY(char, da_filename_len, name_pool_ptr);
00408 strcpy (da_filename, cwd);
00409 strcat (da_filename, "/");
00410 strcat (da_filename, Src_File_Name);
00411 INT i;
00412 for (i = da_filename_len-1; i>0; i--)
00413 if (da_filename[i] == '.')
00414 break;
00415 FmtAssert (da_filename[i] == '.', ("Src_File_Name should associate with the prefix"));
00416 da_filename[i+1] = 'd';
00417 da_filename[i+3] = da_filename[i+2];
00418 da_filename[i+2] = 'a';
00419
00420
00421 TY_IDX table = Make_Array_Type(MTYPE_U2, 1, da_filename_len);
00422 ST *listvar = Gen_Read_Only_Symbol(table, "dafilename_table");
00423 Set_ST_is_initialized(listvar);
00424 INITO_IDX ino = New_INITO(listvar);
00425 INITV_IDX inv_local = New_INITV();
00426 INITV_Init_String(inv_local, da_filename, da_filename_len);
00427 Append_INITV (inv_local, ino, INITV_IDX_ZERO);
00428 Allocate_Object(listvar);
00429 inv = New_INITV();
00430 INITV_Init_Symoff (inv, listvar, 0);
00431 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00432
00433
00434 inv = New_INITV();
00435 INITV_Init_Integer(inv, MTYPE_U8, 0);
00436 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00437
00438
00439 inv = New_INITV();
00440 INITV_Init_Integer(inv, MTYPE_I4, num_nodes);
00441 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00442 inv = New_INITV();
00443 INITV_Init_Pad(inv, 4);
00444 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00445
00446
00447 UINT32 func_name_size = 8;
00448 UINT32 checksum_size = 4;
00449 UINT32 n_counter_sections_size = 4;
00450 UINT32 counter_section_size = 8;
00451 UINT32 function_info_size = func_name_size + checksum_size + n_counter_sections_size + counter_section_size;
00452 TY_IDX tyi_function;
00453 TY& ty_function = New_TY(tyi_function);
00454 TY_Init(ty_function, function_info_size * num_nodes, KIND_STRUCT, MTYPE_M,
00455 STR_IDX_ZERO);
00456 Set_TY_align(tyi_function, 8);
00457 ST *func_infos = New_ST(GLOBAL_SYMTAB);
00458 ST_Init(func_infos, Save_Str("function_infos"), CLASS_VAR, SCLASS_FSTATIC, EXPORT_LOCAL, tyi_function);
00459 Set_ST_is_initialized(func_infos);
00460 CG_Init_Func_Infos(func_infos);
00461 Allocate_Object(func_infos);
00462
00463 inv = New_INITV();
00464 INITV_Init_Symoff(inv, func_infos, 0);
00465 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00466
00467
00468 inv = New_INITV();
00469 INITV_Init_Integer(inv, MTYPE_I4, 1);
00470 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00471 inv = New_INITV();
00472 INITV_Init_Pad(inv, 4);
00473 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00474
00475
00476 UINT32 tag_size = 4;
00477 UINT32 n_counters_size = 4;
00478 UINT32 counters_size = 8;
00479 counter_section_size = tag_size + n_counters_size + counters_size;
00480
00481 TY_IDX tyi_counter;
00482 TY& ty_counter = New_TY(tyi_counter);
00483 TY_Init(ty_counter, counter_section_size * 3, KIND_STRUCT, MTYPE_M, STR_IDX_ZERO);
00484 Set_TY_align(tyi_counter, 8);
00485 ST *counter_section = New_ST(GLOBAL_SYMTAB);
00486 ST_Init(counter_section, Save_Str("counter_section"), CLASS_VAR, SCLASS_FSTATIC, EXPORT_LOCAL, tyi_counter);
00487 Set_ST_is_initialized(counter_section);
00488 Allocate_Object(counter_section);
00489
00490 inv = New_INITV();
00491 INITV_Init_Symoff(inv, counter_section, 0);
00492 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00493 CG_Init_Couner_Infos(counter_section);
00494 #else
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 #if 0
00505 struct bb_function_info {
00506 long checksum;
00507 int arc_count;
00508 const char *name;
00509 };
00510
00511
00512 struct bb
00513 {
00514 long zero_word;
00515 const char *filename;
00516 gcov_type *counts;
00517 long ncounts;
00518 struct bb *next;
00519
00520
00521 long sizeof_bb;
00522 struct bb_function_info *function_infos;
00523 };
00524 #endif
00525 TYPE_ID rtype;
00526 INT32 ty_size;
00527
00528 if (Is_Target_32bit()) {
00529 rtype = MTYPE_U4;
00530 ty_size = 4;
00531 }
00532 else {
00533 rtype = MTYPE_U8;
00534 ty_size = 8;
00535 }
00536
00537
00538 INITO_IDX aggregate_inito = New_INITO(st);
00539 INITV_IDX inv = New_INITV();
00540 INITV_Init_Integer(inv, rtype, 0);
00541 INITV_IDX last_aggregate_initv;
00542 last_aggregate_initv = Append_INITV (inv, aggregate_inito, INITV_IDX_ZERO);
00543
00544
00545 char *cwd, *da_filename;
00546 int da_filename_len,i;
00547
00548 cwd = getpwd ();
00549 da_filename_len = strlen (lbasename(Src_File_Name)) + strlen (cwd) + 4 + 1;
00550 da_filename = CXX_NEW_ARRAY(char, da_filename_len, name_pool_ptr);
00551 strcpy (da_filename, cwd);
00552 strcat (da_filename, "/");
00553 strcat (da_filename, lbasename(Src_File_Name));
00554 for (i = da_filename_len-1; i>0; i--)
00555 if (da_filename[i] == '.')
00556 break;
00557 FmtAssert (da_filename[i] == '.', ("Src_File_Name should associate with the prefix"));
00558 da_filename[i] = 0;
00559 strcat (da_filename, ".da");
00560
00561 TY_IDX table = Make_Array_Type(MTYPE_U2, 1, da_filename_len);
00562 ST *listvar = Gen_Read_Only_Symbol(table, "dafilename_table");
00563 Set_ST_is_initialized(listvar);
00564 INITO_IDX ino = New_INITO(listvar);
00565 INITV_IDX inv_local = New_INITV();
00566 INITV_Init_String(inv_local, da_filename, da_filename_len);
00567 Append_INITV (inv_local, ino, INITV_IDX_ZERO);
00568 Allocate_Object(listvar);
00569 inv = New_INITV();
00570 INITV_Init_Symoff (inv, listvar, 0);
00571 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00572
00573
00574 st = get_symbol("LPBX2");
00575 FmtAssert (st != NULL, ("Symbol LPBX2 should have generated before"));
00576 if ( ST_is_not_used(st) ){
00577 Clear_ST_is_not_used(st);
00578 Allocate_Object(st);
00579 }
00580
00581 TY_IDX tyi;
00582 TY& ty = New_TY(tyi);
00583 TY_Init(ty, n_instr_edges*8, KIND_STRUCT, MTYPE_M,
00584 STR_IDX_ZERO);
00585 Set_TY_align(tyi, Is_Target_32bit() ? 4 : 32);
00586 ST* new_st = New_ST(GLOBAL_SYMTAB);
00587 ST_Init(new_st, Save_Str("LPBX2_TMP"),
00588 CLASS_VAR, SCLASS_PSTATIC, EXPORT_LOCAL, tyi);
00589 Allocate_Object(new_st);
00590
00591 INITO_IDX inito_lpbx2 = New_INITO(st);
00592 INITV_IDX initv_lpbx2;
00593 initv_lpbx2 = New_INITV();
00594 INITV_Init_Symoff(initv_lpbx2, new_st, 0);
00595 Append_INITV(initv_lpbx2, inito_lpbx2, INITV_IDX_ZERO);
00596
00597 inv = New_INITV();
00598 INITV_Init_Symoff(inv, new_st, 0);
00599 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00600
00601
00602 inv = New_INITV();
00603 INITV_Init_Integer(inv, rtype, n_instr_edges);
00604 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv
00605 );
00606
00607
00608 inv = New_INITV();
00609 INITV_Init_Integer(inv, rtype, 0);
00610 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00611
00612
00613 inv = New_INITV();
00614 INITV_Init_Integer(inv, rtype, 7*ty_size);
00615 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00616
00617
00618 UINT32 checksum_size = ty_size;
00619 UINT32 n_arcs_size = 4;
00620 UINT32 func_name_size = ty_size;
00621 UINT32 function_info_size = checksum_size + n_arcs_size*(Is_Target_32bit()?1:2) + func_name_size;
00622 TY_IDX tyi_function;
00623 TY& ty_function = New_TY(tyi_function);
00624 TY_Init(ty_function, function_info_size * (num_nodes + 1), KIND_STRUCT, MTYPE_M,
00625 STR_IDX_ZERO);
00626 Set_TY_align(tyi_function, ty_size);
00627 ST *func_infos = New_ST(GLOBAL_SYMTAB);
00628 ST_Init(func_infos, Save_Str("function_infos"), CLASS_VAR, SCLASS_FSTATIC, EXPORT_LOCAL, tyi_function);
00629 Set_ST_is_initialized(func_infos);
00630 CG_Init_Func_Infos(func_infos);
00631 Allocate_Object(func_infos);
00632
00633 inv = New_INITV();
00634 INITV_Init_Symoff(inv, func_infos, 0);
00635 last_aggregate_initv = Append_INITV(inv, INITO_IDX_ZERO, last_aggregate_initv);
00636 #endif
00637 }
00638 void
00639 CG_Compute_Checksum ()
00640 {
00641 #define CHSUM_HASH 500000003
00642 #define CHSUM_SHIFT 2
00643 if (!Cur_PU_Name || strncmp(Cur_PU_Name, "_GLOBAL__GCOV_", strlen("_GLOBAL__GCOV_"))==0)
00644 return;
00645 local_n_edges = 0;
00646 local_n_a_edges = 0;
00647 local_n_basic_blocks = 0;
00648 chksum = 0;
00649 BB* bb;
00650 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00651 BBLIST* bb_succs = BB_succs( bb );
00652 if (!bb_succs) {
00653 local_n_a_edges ++;
00654 local_n_basic_blocks++;
00655 chksum = ((chksum==0?1:chksum) << CHSUM_SHIFT) % CHSUM_HASH;
00656 continue;
00657 }
00658 BBLIST *succ;
00659 FOR_ALL_BBLIST_ITEMS(bb_succs, succ){
00660 #ifdef GCC_303
00661 unsigned value = BB_TO_GCOV_INDEX (BBLIST_item(succ));
00662 unsigned ix;
00663 value ^= value << 16;
00664 value ^= value << 8;
00665 for (ix = 8; ix--; value <<= 1)
00666 {
00667 unsigned feedback;
00668 feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
00669 chksum <<= 1;
00670 chksum ^= feedback;
00671 }
00672 #else
00673 chksum = ((chksum << CHSUM_SHIFT) + (BB_TO_GCOV_INDEX (BBLIST_item(succ)) + 1)) % CHSUM_HASH;
00674 #endif
00675
00676 if (!BBLIST_on_tree(succ))
00677 local_n_edges ++;
00678 local_n_a_edges ++;
00679 chksum = (chksum << CHSUM_SHIFT) % CHSUM_HASH;
00680 }
00681
00682 local_n_basic_blocks++;
00683 }
00684 struct function_list *new_item = (struct function_list *)CXX_NEW_ARRAY(char, sizeof (struct function_list), name_pool_ptr);
00685
00686 *functions_tail = new_item;
00687 functions_tail = &new_item->next;
00688
00689 new_item->next = 0;
00690 new_item->name = CXX_NEW_ARRAY(char, strlen(Cur_PU_Name)+1, name_pool_ptr);
00691 strcpy (new_item->name, Cur_PU_Name);
00692 new_item->cfg_checksum = chksum;
00693 #ifdef GCC_303
00694 new_item->n_counter_sections = 1;
00695 new_item->counter_sections[0].n_counters = local_n_edges;
00696 new_item->counter_sections[0].tag = GCOV_TAG_ARC_COUNTS;
00697 #else
00698 new_item->count_edges = local_n_edges+1;
00699 n_instr_edges += local_n_edges+1;
00700 #endif
00701
00702 }
00703
00704
00705
00706
00707 static BB*
00708 find_group (BB* bb)
00709 {
00710 BB* group = bb, *bb1;
00711
00712 while (group != NULL && BB_aux(group) != group)
00713 group = BB_aux(group);
00714
00715
00716 while (bb && group && BB_aux(bb) != group)
00717 {
00718 bb1 = BB_aux(bb);
00719 BB_aux(bb) = group;
00720 bb = bb1;
00721 }
00722 return group;
00723 }
00724
00725 static void
00726 union_groups (BB* bb1, BB* bb2)
00727 {
00728 BB* bb1g = find_group (bb1);
00729 BB* bb2g = find_group (bb2);
00730
00731 FmtAssert (bb1g != bb2g, ("Two group should be in one spanning tree"));
00732 if (bb1g)
00733 BB_aux(bb1g) = bb2g;
00734 else
00735 BB_aux(bb2g) = bb1g;
00736 }
00737 static BOOL EDGE_CRITICAL_P(BB* src, BB *dest)
00738 {
00739 BBLIST* bb_succs = BB_succs( src );
00740 BBLIST* bb_preds = BB_preds( dest );
00741 return ( (BBlist_Len(bb_succs) > 1) && (BBlist_Len(bb_preds) > 1) );
00742 }
00743
00744
00745
00746
00747
00748
00749
00750 static void
00751 find_spanning_tree()
00752 {
00753 BBLIST* bb_succs;
00754 BBLIST *succ;
00755 BB *bb;
00756
00757 for (bb = REGION_First_BB; bb; bb = BB_next(bb))
00758 {
00759 if (BB_entry(bb) || BB_call(bb) || BB_exit(bb))
00760 BB_aux(bb) = NULL;
00761 else
00762 BB_aux(bb) = bb;
00763 }
00764
00765 for (bb = REGION_First_BB; bb; bb = BB_next(bb))
00766 {
00767 bb_succs = BB_succs( bb );
00768 if (!bb_succs) continue;
00769
00770 FOR_ALL_BBLIST_ITEMS(bb_succs, succ){
00771 if (EDGE_CRITICAL_P (bb, BBLIST_item(succ)) && find_group (bb) != find_group (BBLIST_item(succ))){
00772 Set_BBLIST_on_tree(succ);
00773 Set_BBLIST_on_tree(BB_Find_Pred(BBLIST_item(succ), bb));
00774 union_groups (bb, BBLIST_item(succ));
00775 }
00776 }
00777 }
00778
00779 for (bb = REGION_First_BB; bb; bb = BB_next(bb))
00780 {
00781 bb_succs = BB_succs( bb );
00782 if (!bb_succs) continue;
00783
00784 FOR_ALL_BBLIST_ITEMS(bb_succs, succ){
00785 if (find_group (bb) != find_group (BBLIST_item(succ))){
00786 Set_BBLIST_on_tree(succ);
00787 Set_BBLIST_on_tree(BB_Find_Pred(BBLIST_item(succ), bb));
00788 union_groups (bb, BBLIST_item(succ));
00789 }
00790 }
00791 }
00792 }
00793
00794 #ifndef GCC_303
00795 static void
00796 output_gcov_string (
00797 const char *string,
00798 long delimiter)
00799 {
00800 size_t temp;
00801
00802 __write_long (delimiter, bb_file, 4);
00803
00804 temp = strlen (string) + 1;
00805 fwrite (string, temp, 1, bb_file);
00806
00807 temp = temp & 0x3;
00808 if (temp)
00809 {
00810 char c[4];
00811 c[0] = c[1] = c[2] = c[3] = 0;
00812 fwrite (c, sizeof (char), 4 - temp, bb_file);
00813 }
00814
00815
00816 __write_long (delimiter, bb_file, 4);
00817 }
00818 #endif
00819
00820
00821
00822
00823 void
00824 CG_Init_Gcov ()
00825 {
00826 char *base_name = lbasename(Src_File_Name);
00827 int len = strlen (base_name);
00828 int i;
00829
00830 name_pool_ptr = &name_pool;
00831 MEM_POOL_Initialize (name_pool_ptr, "Names", FALSE);
00832 MEM_POOL_Push (name_pool_ptr);
00833
00834 if (flag_test_coverage == FALSE)
00835 return;
00836
00837 last_bb_file_num = -1;
00838 bbg_file_name = CXX_NEW_ARRAY(char, len + strlen (GCOV_GRAPH_SUFFIX) + 1, name_pool_ptr);
00839 strcpy (bbg_file_name, base_name);
00840 for (i = len + strlen (GCOV_GRAPH_SUFFIX); i>0; i--)
00841 if (bbg_file_name[i] == '.')
00842 break;
00843 FmtAssert (bbg_file_name[i] == '.', ("Src_File_Name should associate with the prefix"));
00844 bbg_file_name[i] = 0;
00845 strcat (bbg_file_name, GCOV_GRAPH_SUFFIX);
00846 bbg_file = fopen (bbg_file_name, "wb");
00847 if (!bbg_file)
00848 FmtAssert (bbg_file != 0, ("Gcov Error: can't open %s", bbg_file_name));
00849 #ifdef GCC_303
00850 if (gcov_write_unsigned (bbg_file, GCOV_GRAPH_MAGIC)
00851 || gcov_write_unsigned (bbg_file, GCOV_VERSION))
00852 {
00853 fclose (bbg_file);
00854 FmtAssert (0, ("cannot write `%s'", bbg_file_name));
00855 }
00856 #else
00857 char* data_file = CXX_NEW_ARRAY(char, len + 4, name_pool_ptr);
00858 strcpy (data_file, base_name);
00859 for (i = len + 3; i>0; i--)
00860 if (data_file[i] == '.')
00861 break;
00862 FmtAssert (data_file[i] == '.', ("Src_File_Name should associate with the prefix"));
00863 data_file[i] = 0;
00864 strcat (data_file, ".bb");
00865 if ((bb_file = fopen (data_file, "wb")) == 0)
00866 FmtAssert (bb_file != 0, ("Gcov Error: can't open %s", data_file));
00867 #endif
00868
00869 }
00870
00871
00872
00873 void
00874 CG_End_Gcov ()
00875 {
00876 if (name_pool_ptr != NULL) {
00877 MEM_POOL_Pop (name_pool_ptr);
00878 MEM_POOL_Delete (name_pool_ptr);
00879 name_pool_ptr = NULL;
00880 }
00881 if (flag_test_coverage == FALSE)
00882 return;
00883 fclose (bbg_file);
00884 #ifndef GCC_303
00885 fclose (bb_file);
00886 #endif
00887 }
00888
00889 void
00890 CG_Gcov_Generation ()
00891 {
00892 long offset;
00893 const char *name = Cur_PU_Name;
00894 int i;
00895 const char *fname = NULL;
00896 const char *dname;
00897 int cur_bb_file_num, cur_bb_line_num;
00898 BBLIST* bb_succs;
00899 BBLIST *succ;
00900 BB *bb;
00901 OP *op;
00902
00903 if (!Cur_PU_Name || strncmp(Cur_PU_Name, "_GLOBAL__GCOV_", strlen("_GLOBAL__GCOV_"))==0)
00904 return;
00905 find_spanning_tree();
00906 CG_Compute_Checksum();
00907 last_bb_line_num = -1;
00908 if (flag_test_coverage == FALSE)
00909 return;
00910 #ifdef GCC_303
00911
00912 if (gcov_write_unsigned (bbg_file, GCOV_TAG_FUNCTION)
00913 || !(offset = gcov_reserve_length (bbg_file))
00914 || gcov_write_string (bbg_file, name,
00915 strlen (name))
00916 || gcov_write_unsigned (bbg_file,
00917 chksum)
00918 || gcov_write_length (bbg_file, offset))
00919 goto bbg_error;
00920
00921 if (gcov_write_unsigned (bbg_file, GCOV_TAG_BLOCKS)
00922 || !(offset = gcov_reserve_length (bbg_file)))
00923 goto bbg_error;
00924 for (i = 0; i != (unsigned) (local_n_basic_blocks); i++)
00925 if (gcov_write_unsigned (bbg_file, 0))
00926 goto bbg_error;
00927 if (gcov_write_length (bbg_file, offset))
00928 goto bbg_error;
00929
00930
00931 for (bb = REGION_First_BB; bb; bb = BB_next(bb))
00932 {
00933 bb_succs = BB_succs( bb );
00934 if (!bb_succs) continue;
00935 if (gcov_write_unsigned (bbg_file, GCOV_TAG_ARCS)
00936 || !(offset = gcov_reserve_length (bbg_file))
00937 || gcov_write_unsigned (bbg_file, BB_TO_GCOV_INDEX (bb)))
00938 goto bbg_error;
00939
00940 FOR_ALL_BBLIST_ITEMS(bb_succs, succ){
00941 unsigned flag_bits = 0;
00942 if (BB_Fall_Thru_Successor(bb) == BBLIST_item(succ))
00943 flag_bits |= GCOV_ARC_FALLTHROUGH;
00944 else
00945 flag_bits |= GCOV_ARC_ON_TREE;
00946 if (gcov_write_unsigned (bbg_file, BB_TO_GCOV_INDEX (BBLIST_item(succ)))
00947 || gcov_write_unsigned (bbg_file, flag_bits))
00948 goto bbg_error;
00949 }
00950 if (gcov_write_length (bbg_file, offset))
00951 goto bbg_error;
00952 }
00953
00954
00955
00956
00957
00958 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00959 offset = 0;
00960 for (op = BB_first_op(bb); op != NULL; op = OP_next(op)){
00961 cur_bb_file_num = SRCPOS_filenum(OP_srcpos(op));
00962 cur_bb_line_num = Srcpos_To_Line(OP_srcpos(op));
00963
00964
00965
00966 if (last_bb_file_num == -1 || cur_bb_file_num != last_bb_file_num){
00967 IR_Srcpos_Filename(OP_srcpos(op), &fname, &dname);
00968 if (fname == NULL)
00969 continue;
00970 if (offset)
00971 ;
00972 else if (gcov_write_unsigned (bbg_file, GCOV_TAG_LINES)
00973 || !(offset = gcov_reserve_length (bbg_file))
00974 || gcov_write_unsigned (bbg_file,
00975 BB_TO_GCOV_INDEX (bb)))
00976 goto bbg_error;
00977
00978 last_bb_file_num = cur_bb_file_num;
00979 last_bb_line_num = -1;
00980 if (gcov_write_unsigned (bbg_file, 0)
00981 || gcov_write_string (bbg_file, fname,
00982 strlen (fname)))
00983 goto bbg_error;
00984 }
00985 else if (last_bb_line_num == -1 || cur_bb_line_num != last_bb_line_num){
00986 if (offset)
00987 ;
00988 else if (gcov_write_unsigned (bbg_file, GCOV_TAG_LINES)
00989 || !(offset = gcov_reserve_length (bbg_file))
00990 || gcov_write_unsigned (bbg_file,
00991 BB_TO_GCOV_INDEX (bb)))
00992 goto bbg_error;
00993 }
00994
00995 if (last_bb_line_num == -1 || cur_bb_line_num != last_bb_line_num){
00996 last_bb_line_num = cur_bb_line_num;
00997 if (gcov_write_unsigned (bbg_file, cur_bb_line_num))
00998 goto bbg_error;
00999 }
01000 }
01001 if (offset)
01002 {
01003 if (gcov_write_unsigned (bbg_file, 0)
01004 || gcov_write_string (bbg_file, NULL, 0)
01005 || gcov_write_length (bbg_file, offset))
01006 {
01007 bbg_error:;
01008 FmtAssert(0, ("error writing `%s'", bbg_file_name));
01009 fclose (bbg_file);
01010 bbg_file = NULL;
01011 }
01012 }
01013 }
01014 #else
01015
01016 output_gcov_string (name, (long) -2);
01017
01018
01019
01020 for (BB* bb = REGION_First_BB; bb; bb = BB_next(bb)) {
01021
01022
01023
01024
01025 __write_long (0, bb_file, 4);
01026 for (OP* op = BB_first_op(bb); op != NULL; op = OP_next(op)){
01027 cur_bb_file_num = SRCPOS_filenum(OP_srcpos(op));
01028 cur_bb_line_num = Srcpos_To_Line(OP_srcpos(op));
01029
01030 if (!cur_bb_line_num)
01031 continue;
01032
01033
01034
01035 if (last_bb_file_num == -1 || cur_bb_file_num != last_bb_file_num){
01036 IR_Srcpos_Filename(OP_srcpos(op), &fname, &dname);
01037 if (fname == NULL)
01038 continue;
01039 last_bb_file_num = cur_bb_file_num;
01040 last_bb_line_num = -1;
01041
01042
01043
01044
01045 output_gcov_string (fname,
01046 (long)-1);
01047 }
01048
01049 if (last_bb_line_num == -1 || cur_bb_line_num != last_bb_line_num){
01050 last_bb_line_num = cur_bb_line_num;
01051
01052
01053
01054
01055 __write_long (cur_bb_line_num, bb_file, 4);
01056 }
01057 }
01058 }
01059 __write_long (0, bb_file, 4);
01060
01061
01062
01063
01064
01065 int flag_bits;
01066
01067 __write_gcov_string (name, strlen (name), bbg_file, -1);
01068
01069
01070 __write_long (chksum, bbg_file, 4);
01071
01072
01073 __write_long (local_n_basic_blocks+2, bbg_file, 4);
01074 __write_long (local_n_a_edges+2, bbg_file, 4);
01075
01076 __write_long (1, bbg_file, 4);
01077 __write_long (BB_TO_GCOV_INDEX (REGION_First_BB), bbg_file, 4);
01078 __write_long (0x4, bbg_file, 4);
01079
01080 for (BB* bb = REGION_First_BB; bb; bb = BB_next(bb)) {
01081
01082 BBLIST* bb_succs = BB_succs( bb );
01083 long count = BBlist_Len( bb_succs );
01084 if (count == 0){
01085 __write_long (1, bbg_file, 4);
01086 __write_long (0, bbg_file, 4);
01087 __write_long (0x1, bbg_file, 4);
01088 continue;
01089 }
01090 __write_long (count, bbg_file, 4);
01091
01092 BBLIST *succ;
01093 FOR_ALL_BBLIST_ITEMS(bb_succs, succ){
01094 flag_bits = 0;
01095 if (BBLIST_on_tree(succ))
01096 flag_bits |= 0x1;
01097 else if (BB_Fall_Thru_Successor(bb) == BBLIST_item(succ))
01098 flag_bits |= 0x4;
01099 __write_long (BB_TO_GCOV_INDEX (BBLIST_item(succ)), bbg_file, 4);
01100 __write_long (flag_bits, bbg_file, 4);
01101 }
01102 }
01103
01104
01105
01106 __write_long (1, bbg_file, 4);
01107 __write_long (0, bbg_file, 4);
01108 __write_long (0x1, bbg_file, 4);
01109
01110
01111
01112 __write_long (-1, bbg_file, 4);
01113 #endif
01114 }
01115
01116 static BOOL
01117 Opnd_Tn_In_BB( BB* bb, REGISTER reg, unsigned char type )
01118 {
01119 OP* opcode = bb->ops.first;
01120 int i;
01121 for( ; opcode != NULL; opcode = OP_next( opcode ) )
01122 {
01123 for ( i = 0; i < OP_opnds( opcode ); i++ )
01124 {
01125 TN *tn = OP_opnd( opcode,i );
01126 if ( type == 0 && TN_register_class(tn) == ISA_REGISTER_CLASS_integer && TN_register(tn) == reg )
01127 return TRUE;
01128 else if ( type == 1 && TN_register_class(tn) == ISA_REGISTER_CLASS_float && TN_register(tn) == reg )
01129 return TRUE;
01130 }
01131 }
01132 return FALSE;
01133 }
01134
01135
01136 static INT32
01137 Get_Return_Reg_Sum(BB* bb)
01138 {
01139 #ifdef TARG_X8664
01140 if ( Opnd_Tn_In_BB( bb, RDX, 0 ) )
01141 return 2;
01142
01143 if ( Opnd_Tn_In_BB( bb, RAX, 0 ) )
01144 return 1;
01145 #endif
01146
01147 return 0;
01148 }
01149
01150
01151 static INT32
01152 Get_Float_Return_Reg_Sum(BB* bb)
01153 {
01154 #ifdef TARG_X8664
01155 for ( int i = 1 ; i >= 0; i-- )
01156 {
01157 if ( Opnd_Tn_In_BB( bb,XMM0 + i, 1) )
01158 return i + 1;
01159 }
01160 #endif
01161 return 0;
01162 }
01163 static BOOL
01164 Is_BB_Empty (BB *bb)
01165 {
01166 for (OP *op = BB_first_op(bb); op != NULL; op = OP_next(op)) {
01167 if (OP_Real_Ops(op) != 0) return FALSE;
01168 }
01169 return TRUE;
01170 }
01171
01172 static void
01173 BB_Mov_Ops(BB* dest_bb, BB *src_bb, REGISTER reg, unsigned char type)
01174 {
01175 int i;
01176 for (OP* op = BB_first_op(src_bb); op != NULL; op = OP_next(op))
01177 {
01178 for ( i = 0; i < OP_opnds( op ); i++ )
01179 {
01180 TN *tn = OP_opnd( op,i );
01181 if ( ((type == 0 && TN_register_class(tn) == ISA_REGISTER_CLASS_integer) || (type == 1 && TN_register_class(tn) == ISA_REGISTER_CLASS_float)) &&
01182 TN_register(tn) == reg )
01183 {
01184 BB_Remove_Op( src_bb, op);
01185 FmtAssert( !Is_BB_Empty(src_bb), ("BB can not be empty!"));
01186 BB_Prepend_Op (dest_bb, op);
01187 return;
01188 }
01189 }
01190 }
01191 }
01192
01193 static void
01194 Move_Save_Regs_OP(BB *instr_bb, BB *bb, INT32 ret_reg_num, INT32 f_ret_reg_num)
01195 {
01196 #ifdef TARG_X8664
01197 FmtAssert (ret_reg_num == 0 || f_ret_reg_num == 0, ("cannot be both integer and floating point at the same time"));
01198 if (ret_reg_num){
01199 BB_Mov_Ops(instr_bb, bb, RAX, 0);
01200 ret_reg_num --;
01201 if (ret_reg_num){
01202 BB_Mov_Ops(instr_bb, bb, RDX, 0);
01203 }
01204 }
01205 else if (f_ret_reg_num){
01206 int i = 0;
01207 while ( i<f_ret_reg_num ){
01208 BB_Mov_Ops(instr_bb, bb, XMM0+i++, 1);
01209 }
01210 }
01211 #endif
01212 }
01213
01214 static void
01215 Process_Arc_Profile_Region_Options ( void )
01216 {
01217 OPTION_LIST *ol;
01218
01219 for ( ol = Arc_Profile_Region; ol != NULL; ol = OLIST_next(ol) ) {
01220 if ( strcmp ( OLIST_opt(ol), "profile_proc" ) == 0 )
01221 if ( strcmp (Cur_PU_Name, OLIST_val(ol) ) ==0 )
01222 pu_flag = 1;
01223 else
01224 pu_flag = 0;
01225 if ( strcmp ( OLIST_opt(ol), "profile_id1" ) == 0 )
01226 begin_id = atoi ( OLIST_val (ol) );
01227 if ( strcmp ( OLIST_opt(ol), "profile_id2" ) == 0 )
01228 end_id = atoi ( OLIST_val (ol) );
01229 }
01230 }
01231 static BOOL
01232 Indirect_Branch(BB *bb)
01233 {
01234 OP *br_op = BB_branch_op(bb);
01235 if (br_op) {
01236 INT tfirst, tcount;
01237 CGTARG_Branch_Info(br_op, &tfirst, &tcount);
01238 if (tcount == 0)
01239 return TRUE;
01240 }
01241 return FALSE;
01242 }
01243
01244 static BOOL
01245 BB_Is_Unique_Instr_Predecessor(BB *src, BB *dest)
01246 {
01247 if (BB_Is_Unique_Predecessor(src, dest))
01248 return TRUE;
01249
01250 int instr_count = 0;
01251
01252 BBLIST* edge;
01253 FOR_ALL_BB_PREDS(src, edge) {
01254 if (!BBLIST_on_tree(edge))
01255 instr_count ++;
01256 }
01257 if (instr_count > 1){
01258 int instr_count_for_indirect_branch = 0;
01259 FOR_ALL_BB_PREDS(src, edge) {
01260 BB* bb_pred = BBLIST_item(edge);
01261 if (!BBLIST_on_tree(edge) && Indirect_Branch(bb_pred))
01262 instr_count_for_indirect_branch++;
01263 }
01264 FmtAssert(instr_count_for_indirect_branch <= 1, ("one indirect branch and one direct branch going to the same basic block need to be instrumented?"));
01265
01266
01267 if (instr_count_for_indirect_branch == 1){
01268 if (Indirect_Branch(dest))
01269 return TRUE;
01270 else
01271 return FALSE;
01272 }
01273 else
01274 return FALSE;
01275 }
01276 else
01277 return TRUE;
01278 }
01279
01280 void
01281 CG_Instrument_Arcs()
01282 {
01283 if (!Cur_PU_Name || strncmp(Cur_PU_Name, "_GLOBAL__GCOV_", strlen("_GLOBAL__GCOV_"))==0) return;
01284
01285 ST *st = get_symbol("LPBX2");
01286 if (st == NULL){
01287 st = New_ST(GLOBAL_SYMTAB);
01288 char* func_name = TYPE_MEM_POOL_ALLOC_N(char, name_pool_ptr, strlen("LPBX2") + strlen(lbasename(Src_File_Name)) + 1);
01289 sprintf(func_name, "%s%s", "LPBX2", lbasename(Src_File_Name));
01290 for(INT i = 0; func_name[i]; i++){
01291 if( !( func_name[i] == '_'
01292 || ('0' <= func_name[i] && func_name[i] <= '9')
01293 || ('A' <= func_name[i] && func_name[i] <= 'Z')
01294 || ('a' <= func_name[i] && func_name[i] <= 'z')) )
01295 func_name[i] = '_';
01296 }
01297
01298 ST_Init(st, Save_Str(func_name),
01299 CLASS_VAR, SCLASS_PSTATIC, EXPORT_PREEMPTIBLE, MTYPE_To_TY(Pointer_type));
01300 Set_ST_is_initialized(st);
01301 Set_ST_is_not_used(st);
01302 }
01303
01304 Process_Arc_Profile_Region_Options ();
01305 if (pu_flag == 0) return;
01306
01307 static int count = 0;
01308 BBLIST *bb_succs;
01309 BBLIST *succ;
01310 BB *bb_succ;
01311 BB *bb;
01312 OP *op;
01313 OPS new_ops;
01314 TN *ld_result_tn;
01315 TN *ld_2nd_result_tn;
01316 TN *const_tn;
01317 TN *result_tn;
01318 TYPE_ID rtype;
01319
01320 if (Is_Target_32bit())
01321 rtype = MTYPE_U4;
01322 else
01323 rtype = MTYPE_U8;
01324
01325 if ((begin_id == -1 && end_id == -1) || (begin_id <= count && count <= end_id)) {
01326 OPS_Init(&new_ops);
01327 ld_result_tn = Build_TN_Of_Mtype(rtype);
01328 Exp_Load (rtype, rtype, ld_result_tn, st, 0, &new_ops, 0);
01329 ld_2nd_result_tn = Build_TN_Of_Mtype(rtype);
01330 #if defined(TARG_MIPS) || defined(TARG_X8664)
01331 Expand_Load( OPCODE_make_op (OPR_LDID, rtype, rtype),ld_2nd_result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), &new_ops);
01332 #else
01333 Expand_Load( OPCODE_make_op (OPR_LDID, rtype, rtype),ld_2nd_result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), (VARIANT)0, &new_ops);
01334 #endif
01335 const_tn = Gen_Literal_TN(1,4);
01336 result_tn = Build_TN_Of_Mtype(rtype);
01337 Exp_OP2 (OPC_U4ADD, result_tn, ld_2nd_result_tn, const_tn, &new_ops);
01338 #if defined(TARG_MIPS) || defined(TARG_X8664)
01339 Expand_Store (OPCODE_desc(OPCODE_make_op(OPR_STID, MTYPE_V, rtype)),result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), &new_ops);
01340 #else
01341 Expand_Store (OPCODE_desc(OPCODE_make_op(OPR_STID, MTYPE_V, rtype)),result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), (VARIANT)0, &new_ops);
01342 #endif
01343 Gcov_BB_Prepend_Ops(REGION_First_BB, &new_ops);
01344 }
01345 count++;
01346
01347 BB *exit_bb = NULL;
01348 for (bb = REGION_First_BB; bb; bb = BB_next(bb)){
01349 if (BB_exit(bb))
01350 exit_bb = bb;
01351 }
01352
01353 if (!exit_bb){
01354 exit_bb = REGION_First_BB;
01355 while (BB_next(exit_bb)) exit_bb = BB_next(exit_bb);
01356 }
01357 FmtAssert(exit_bb, ("exit bb should exist!"));
01358
01359 for (bb = REGION_First_BB; bb; bb = BB_next(bb))
01360 {
01361 bb_succs = BB_succs( bb );
01362 if (!bb_succs) continue;
01363
01364 BBLIST *succ;
01365 BBLIST *old_succ;
01366 for (succ = bb_succs; succ!= NULL; succ = old_succ)
01367 {
01368 old_succ = BBLIST_next(succ);
01369 bb_succ = BBLIST_item(succ);
01370 if (!BBLIST_on_tree(succ))
01371 {
01372 if (begin_id != -1 && end_id != -1 && (begin_id > count || count > end_id)){
01373 count ++;
01374 continue;
01375 }
01376 OPS_Init(&new_ops);
01377 ld_result_tn = Build_TN_Of_Mtype(rtype);
01378 Exp_Load (rtype, rtype, ld_result_tn, st, 0, &new_ops, 0);
01379 ld_2nd_result_tn = Build_TN_Of_Mtype(rtype);
01380 #if defined(TARG_MIPS) || defined(TARG_X8664)
01381 Expand_Load( OPCODE_make_op (OPR_LDID, rtype, rtype),ld_2nd_result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), &new_ops);
01382 #else
01383 Expand_Load( OPCODE_make_op (OPR_LDID, rtype, rtype),ld_2nd_result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), (VARIANT)0, &new_ops);
01384 #endif
01385 const_tn = Gen_Literal_TN(1,4);
01386 result_tn = Build_TN_Of_Mtype(rtype);
01387 Exp_OP2 (OPC_U4ADD, result_tn, ld_2nd_result_tn, const_tn, &new_ops);
01388 #if defined(TARG_MIPS) || defined(TARG_X8664) || defined(TARG_SL)
01389 Expand_Store (OPCODE_desc(OPCODE_make_op(OPR_STID, MTYPE_V, rtype)),result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), &new_ops);
01390 #else
01391 Expand_Store (OPCODE_desc(OPCODE_make_op(OPR_STID, MTYPE_V, rtype)),result_tn, ld_result_tn, Gen_Literal_TN(count*8,4), (VARIANT)0, &new_ops);
01392 #endif
01393 if (BB_Is_Unique_Instr_Predecessor(bb_succ, bb))
01394 {
01395 Gcov_BB_Prepend_Ops(bb_succ, &new_ops);
01396 count ++;
01397 continue;
01398 }
01399
01400 BB* instr_bb;
01401 if (BB_Fall_Thru_Successor(bb) == bb_succ)
01402 instr_bb = Gen_And_Insert_BB_After(bb);
01403 else{
01404 instr_bb = Gen_And_Insert_BB_After(exit_bb);
01405 LABEL_IDX new_label = Gen_Label_For_BB(instr_bb);
01406 OP *branch_op = BB_branch_op (bb);
01407 INT tn_num = OP_opnds( branch_op );
01408 TN* tgt_tn;
01409 for( int i = 0; i<tn_num; i++ )
01410 {
01411 tgt_tn = OP_opnd( branch_op, i );
01412 if( TN_is_label( tgt_tn ) )
01413 {
01414 Set_TN_label( tgt_tn, new_label );
01415 break;
01416 }
01417 }
01418
01419 LABEL_IDX tgt_label;
01420 tgt_label = Gen_Label_For_BB( bb_succ );
01421 #ifdef TARG_X8664
01422 Build_OP( TOP_jmp, Gen_Label_TN(tgt_label, 0), &new_ops);
01423 #elif TARG_MIPS
01424
01425 Build_OP( TOP_j, Gen_Label_TN(tgt_label, 0), &new_ops);
01426 #else
01427
01428 Build_OP (TOP_br, Gen_Enum_TN(ECV_ph_few), Gen_Enum_TN(ECV_dh), Gen_Label_TN(tgt_label, 0), &new_ops);
01429 #endif
01430 FmtAssert(TN_is_label( tgt_tn ), ("should be branch target label"));
01431 }
01432
01433 Gcov_BB_Prepend_Ops(instr_bb, &new_ops);
01434 if (BB_call( bb )){
01435 int ret_reg_num = Get_Return_Reg_Sum( bb_succ );
01436 int f_ret_reg_num = Get_Float_Return_Reg_Sum( bb_succ );
01437 Move_Save_Regs_OP(instr_bb, bb_succ, ret_reg_num, f_ret_reg_num);
01438 }
01439 Unlink_Pred_Succ(bb, bb_succ);
01440 Link_Pred_Succ(bb, instr_bb);
01441 Set_BBLIST_on_tree( BBlist_Add_BB (&BB_succs(bb), instr_bb) );
01442 Set_BBLIST_on_tree( BBlist_Add_BB (&BB_preds(instr_bb), bb) );
01443 Link_Pred_Succ(instr_bb, bb_succ);
01444 Set_BBLIST_on_tree( BBlist_Add_BB (&BB_succs(instr_bb), bb_succ) );
01445 Set_BBLIST_on_tree( BBlist_Add_BB (&BB_preds(bb_succ), instr_bb) );
01446 count++;
01447 }
01448 }
01449 }
01450 }
01451