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
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #define __STDC_LIMIT_MACROS
00061 #include <stdint.h>
00062 #if defined(BUILD_OS_DARWIN)
00063 #include <darwin_elf.h>
00064 #else
00065 #include <elf.h>
00066 #endif
00067 #include <assert.h>
00068 #include <cmplrs/host.h>
00069 #define USE_STANDARD_TYPES
00070 #include "defs.h"
00071 #include "stab.h"
00072 #include "mempool.h"
00073 #include "cxx_template.h"
00074 #include "tracing.h"
00075 #include "mtypes.h"
00076 #include "const.h"
00077 #include "ipc_file.h"
00078 #include "ipa_option.h"
00079 #include "ipo_main.h"
00080 #include "ipa_cg.h"
00081 #include "ir_reader.h"
00082 #include "ipa_pad.h"
00083
00084 static BOOL trace_split_common = FALSE;
00085 static MEM_POOL IPO_split_pool;
00086
00087
00088
00089
00090 class FIELD_MAP
00091 {
00092 private:
00093 FLD_HANDLE _fld;
00094 INT _split_position;
00095
00096 public:
00097 void Set_fld(FLD_HANDLE f) { _fld = f;};
00098 FLD_HANDLE Get_fld() const { return _fld;};
00099
00100 INT Get_split_position() const { return _split_position;};
00101 void Set_split_position(INT s) { _split_position = s;};
00102
00103 FIELD_MAP() : _fld (), _split_position (0) {}
00104
00105 void Print(FILE* fp = stderr) {
00106 fprintf(fp, "field info %s : split_pos = %d \n", FLD_name(_fld),_split_position);
00107 };
00108 };
00109
00110 typedef DYN_ARRAY<FIELD_MAP> FIELD_MAP_DYN_ARRAY;
00111 static FIELD_MAP_DYN_ARRAY *Field_Map = NULL;
00112 static char Split_Name[1000];
00113
00114
00115
00116 static char*
00117 GetName(char *common_name, INT64 offset)
00118 {
00119 static INT Name_Count = 0;
00120
00121 sprintf(Split_Name, "%s.%lli", common_name, offset);
00122 ++Name_Count;
00123 return Split_Name;
00124 }
00125
00126
00127
00128
00129
00130 static INT64
00131 Get_Size(SPLIT_COMMON_DYN_ARRAY *common_split_array,
00132 INT split_number,
00133 INT current_split_position)
00134 {
00135 INT last_idx = common_split_array->Lastidx();
00136 BOOL done = FALSE;
00137 INT64 size = 0;
00138 for (INT i = current_split_position; i<= last_idx && !done; ++i)
00139 {
00140 SPLIT_COMMON *element = &(*common_split_array)[i];
00141 if (element->Get_split_position() > split_number)
00142 done = TRUE;
00143 else
00144 size = size + element->Get_size()*element->Get_element_size();
00145 }
00146 return size;
00147 }
00148
00149
00150
00151
00152 static INT
00153 Get_Align(SPLIT_COMMON_DYN_ARRAY *common_split_array,
00154 INT split_number,
00155 INT current_split_position)
00156 {
00157 INT last_idx = common_split_array->Lastidx();
00158 BOOL done = FALSE;
00159 INT align = 0;
00160 for (INT i = current_split_position; i<= last_idx && !done; ++i)
00161 {
00162 SPLIT_COMMON *element = &(*common_split_array)[i];
00163 if (element->Get_split_position() > split_number)
00164 done = TRUE;
00165
00166 else if (align < element->Get_element_size())
00167 {
00168 align = element->Get_element_size();
00169 }
00170 }
00171 return align;
00172 }
00173
00174
00175
00176
00177 static TY_IDX
00178 Create_Struct_Type(ST* split_st, INT align, INT64 size)
00179 {
00180 TY_IDX ty_idx;
00181 TY &ty = New_TY(ty_idx);
00182 TY_Init(ty, size, KIND_STRUCT, MTYPE_M, Save_Str(ST_name(split_st)));
00183 Set_TY_align(ty_idx, align);
00184 return ty_idx;
00185 }
00186
00187
00188
00189
00190 void
00191 Map_Field_To_STs(TY_IDX common_ty_idx,
00192 SPLIT_COMMON_DYN_ARRAY *split_common_array)
00193 {
00194 SPLIT_COMMON *element;
00195 BOOL done = FALSE;
00196 INT position = 0;
00197 INT64 ofst = 0;
00198
00199 const TY& common_ty = Ty_Table[common_ty_idx];
00200 FmtAssert((TY_kind(common_ty) == KIND_STRUCT), ("Invalid TY in Map_Field_To_STs \n"));
00201
00202 INT current_split = 0;
00203 INT current_split_position = 0;
00204
00205 INT last_idx = split_common_array->Lastidx();
00206 INT num_splits =
00207 (*split_common_array)[last_idx].Get_split_position() + 1;
00208
00209 if (num_splits == 1)
00210 {
00211 element = &(*split_common_array)[last_idx];
00212 ofst = element->Get_offset() +
00213 element->Get_size()*element->Get_element_size() - 1;
00214 }
00215 else
00216 {
00217 BOOL found = FALSE;
00218 while (!found)
00219 {
00220 element =
00221 &(*split_common_array)[current_split_position];
00222 if (element->Get_split_position() == 1)
00223 {
00224
00225
00226 ofst = element->Get_offset();
00227 found = TRUE;
00228 }
00229 else
00230 ++current_split_position;
00231 }
00232 }
00233
00234 FLD_ITER fld_iter = Make_fld_iter(TY_fld(common_ty));
00235 do {
00236 FLD_HANDLE fld1 (fld_iter);
00237
00238
00239
00240 if (FLD_ofst(fld1) >= ofst)
00241 {
00242 ++current_split;
00243 done = FALSE;
00244
00245
00246
00247 if (current_split == num_splits-1)
00248 {
00249 element = &(*split_common_array)[last_idx];
00250 ofst = element->Get_offset() +
00251 element->Get_size()*element->Get_element_size();
00252 }
00253
00254 else {
00255 while (!done)
00256 {
00257 ++current_split_position;
00258 if
00259 ((*split_common_array)[current_split_position].Get_split_position() == current_split+1)
00260 {
00261 element = &(*split_common_array)[current_split_position];
00262 done = TRUE;
00263
00264 ofst = element->Get_offset();
00265 }
00266 }
00267 }
00268 }
00269
00270 position = Field_Map->Newidx();
00271 FIELD_MAP *node = &(*Field_Map)[position];
00272
00273 node->Set_fld(fld1);
00274 node->Set_split_position(current_split);
00275 if (trace_split_common)
00276 fprintf(TFile, "fld1 %s is in split position %d \n", FLD_name(fld1), current_split);
00277 } while (!FLD_last_field(fld_iter++));
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 static void
00302 Split_Individual_Common(COMMON_SNODE_LIST *snode)
00303
00304 {
00305 ST *s;
00306 SPLIT_COMMON_DYN_ARRAY *split_common_array;
00307 FLD *last_field = NULL;
00308 Field_Map = NULL;
00309 ST* new_st;
00310
00311 MEM_POOL_Push(&IPO_split_pool);
00312 split_common_array = snode->Get_Split_Array();
00313 s = snode->Get_ST();
00314
00315 Field_Map = CXX_NEW(FIELD_MAP_DYN_ARRAY(&IPO_split_pool),&IPO_split_pool);
00316
00317
00318 INT current_split_position = 0;
00319
00320 TY_IDX orig_ty_idx = ST_type(s);
00321
00322 if (trace_split_common)
00323 fprintf(TFile, "Looking for commons %s \n", ST_name(s));
00324
00325
00326 Map_Field_To_STs(orig_ty_idx, split_common_array);
00327
00328
00329
00330 if (!split_common_array)
00331 Fail_FmtAssertion("Unable to find split common shape array \n");
00332
00333
00334 INT last_idx = split_common_array->Lastidx();
00335
00336 if (last_idx == -1)
00337 Fail_FmtAssertion("Unable to find elements of common %s \n", ST_name(s));
00338
00339 INT num_splits =
00340 (*split_common_array)[last_idx].Get_split_position() + 1;
00341
00342
00343 ST** temp_st = CXX_NEW_ARRAY(ST*, num_splits+1, &IPO_split_pool);
00344
00345
00346 if (trace_split_common)
00347 fprintf(TFile, "num_splits = %d for common %s \n", num_splits,ST_name(s));
00348
00349 for (INT i=0; i<num_splits;++i)
00350 {
00351 new_st = Copy_ST(s);
00352 INT64 ofst =
00353 (*split_common_array)[current_split_position].Get_offset();
00354
00355 INT align =
00356 Get_Align(split_common_array,i,
00357 current_split_position);
00358
00359 INT64 size =
00360 Get_Size(split_common_array,i,
00361 current_split_position);
00362 INT ty_idx = Create_Struct_Type(new_st, align, size);
00363 ST_Init(new_st, Save_Str(GetName(ST_name(s), ofst)), CLASS_VAR,
00364 ST_sclass(s), ST_export(s), ty_idx);
00365
00366 Set_TY_name_idx(Ty_Table[ty_idx], ST_name_idx(*new_st));
00367 Set_TY_split(Ty_Table[ty_idx]);
00368 Set_ST_is_split_common(new_st);
00369
00370
00371 if (Field_Map)
00372 {
00373 FLD_HANDLE current_fld;
00374 for (INT ii=0; ii<=Field_Map->Lastidx();++ii)
00375 {
00376 FIELD_MAP *node = &(*Field_Map)[ii];
00377 FIELD_MAP *node_next = NULL;
00378 if (ii != Field_Map->Lastidx())
00379 node_next = &(*Field_Map)[ii+1];
00380
00381 if (node->Get_split_position() == i)
00382 {
00383 if (current_fld.Is_Null ())
00384 {
00385 Set_TY_fld(Ty_Table[ty_idx],node->Get_fld());
00386 current_fld = node->Get_fld();
00387 Set_FLD_ofst(current_fld, (FLD_ofst(current_fld)
00388 - ofst));
00389 if (ii == Field_Map->Lastidx() ||
00390 (node_next->Get_split_position() == i+1))
00391 Set_FLD_last_field(current_fld);
00392 }
00393 else
00394 {
00395 current_fld = node->Get_fld();
00396 Set_FLD_ofst(current_fld,
00397 (FLD_ofst(current_fld)-ofst));
00398 if (ii == Field_Map->Lastidx() ||
00399 (node_next->Get_split_position() == i+1))
00400 Set_FLD_last_field(current_fld);
00401 }
00402 }
00403 if (node->Get_split_position() > i)
00404 break;
00405 }
00406 }
00407
00408 Set_ST_sclass(new_st, SCLASS_COMMON);
00409 if (ST_gprel(s)) {
00410 Set_ST_gprel(new_st);
00411
00412 }
00413 Set_ST_export(new_st, ST_export(s));
00414 Set_ST_full_idx(*new_st, ST_st_idx(s));
00415
00416
00417
00418
00419
00420 Set_ST_ofst(*new_st, 0);
00421
00422
00423
00424
00425
00426
00427 if (trace_split_common)
00428 fprintf(TFile, "entered new ST %s \n", ST_name(new_st));
00429
00430 temp_st[i] = new_st;
00431
00432
00433 FLD_HANDLE field = New_FLD ();
00434 FLD_Init(field,
00435 Save_Str(ST_name(new_st)), ST_type(new_st),
00436 (*split_common_array)[current_split_position].Get_offset());
00437 if (i==0)
00438 {
00439 Set_TY_fld(Ty_Table[orig_ty_idx], field);
00440
00441
00442 if (i== (num_splits-1))
00443 Set_FLD_last_field(field);
00444 }
00445 else
00446 {
00447 if (i==(num_splits-1))
00448 Set_FLD_last_field(field);
00449
00450
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 INT split_position = i;
00464 if (i != (num_splits-1))
00465 while (split_position != (i+1))
00466 {
00467 current_split_position++;
00468 if
00469 ((*split_common_array)[current_split_position].Get_split_position() == (i+1))
00470 split_position++;
00471
00472
00473 }
00474
00475 INT64 next_ofst;
00476 SPLIT_COMMON *element;
00477 if (i == num_splits-1)
00478 {
00479
00480 element =
00481 &(*split_common_array)[split_common_array->Lastidx()];
00482 next_ofst =
00483 element->Get_offset() +
00484 element->Get_size()*element->Get_element_size() - 1;
00485 }
00486 else
00487 {
00488 element =
00489 &(*split_common_array)[current_split_position];
00490 next_ofst = element->Get_offset() - 1;
00491 };
00492
00493
00494
00495
00496
00497
00498
00499
00500 COMMON_SNODE_LIST_ITER iter(snode);
00501 for (iter.First(); !iter.Is_Empty(); iter.Next())
00502 {
00503 COMMON_SNODE* common_snode = iter.Cur();
00504 ST* stbase = common_snode->Get_ST();
00505 if ((ST_ofst(*stbase) <= next_ofst) && (ST_ofst(*stbase) >=
00506 ofst) && (!ST_is_split_common(ST_base(*stbase))))
00507 {
00508
00509
00510
00511 Set_ST_base(*stbase, *new_st);
00512 Set_ST_ofst(*stbase, ST_ofst(*stbase) - ofst);
00513
00514 }
00515
00516 }
00517 }
00518
00519 MEM_POOL_Pop(&IPO_split_pool);
00520 }
00521
00522
00523
00524
00525
00526 void
00527 IPO_Split_Common()
00528 {
00529 STR_IDX common_name;
00530 COMMON_SNODE_LIST *snode_list;
00531
00532 MEM_POOL_Constructor split_pool (&IPO_split_pool, "IPO split pool", 0);
00533
00534 trace_split_common = Get_Trace(TP_IPA, IPA_TRACE_SPLIT_COMMON);
00535
00536 if (IPA_Common_Table) {
00537 COMMON_SNODE_TBL_ITER common_snode_tbl_iter(IPA_Common_Table);
00538 while (common_snode_tbl_iter.Step(&common_name, &snode_list)) {
00539 if (!ST_is_not_used(snode_list->Get_ST()) && !snode_list->No_Split()) {
00540 Split_Individual_Common(snode_list);
00541 }
00542 }
00543 }
00544 }