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 #define __STDC_LIMIT_MACROS
00043 #include <stdint.h>
00044 #include <dwarf.h>
00045 #include <vector>
00046 #include <algorithm>
00047
00048 #include <ext/hash_map>
00049
00050 #include "mempool.h"
00051 #include "mempool_allocator.h"
00052 #define USE_STANDARD_TYPES
00053 #define USE_DST_INTERNALS
00054 #include "dwarf_DST_mem.h"
00055 #include "dwarf_DST.h"
00056 #include "pu_info.h"
00057 #include "ipc_dst_utils.h"
00058 #include "ipc_file.h"
00059 #include "ipa_cg.h"
00060
00061 #include "ipc_dst_merge.h"
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 typedef std::pair<DST_IDX, DST_IDX> idx_pair;
00093 struct idx_pair_less {
00094 bool operator()(const idx_pair& x, const idx_pair& y) const {
00095 return x.first < y.first;
00096 }
00097 };
00098 typedef mempool_allocator<idx_pair> idx_pair_allocator;
00099 typedef std::vector<idx_pair, idx_pair_allocator> idx_pair_vector;
00100
00101 typedef std::pair<const DST_TYPE, idx_pair_vector> dst_hash_value_type;
00102 typedef mempool_allocator<dst_hash_value_type> dst_hash_allocator;
00103 struct DST_TYPE_hash {
00104 size_t operator()(DST_TYPE p) const {
00105 return reinterpret_cast<size_t>(p);
00106 }
00107 };
00108 typedef __gnu_cxx::hash_map<DST_TYPE, idx_pair_vector,
00109 DST_TYPE_hash, std::equal_to<DST_TYPE>,
00110 dst_hash_allocator>
00111 dst_hash_map;
00112
00113
00114 namespace {
00115
00116
00117
00118
00119
00120
00121
00122 void initialize_dst_map(dst_hash_map& M, pu_info* pu)
00123 {
00124 Is_True(pu != 0, ("No pu"));
00125
00126 while (pu) {
00127 IPA_NODE* cg_node = Get_Node_From_PU(pu);
00128
00129 #ifdef KEY
00130
00131 if (cg_node->Is_Builtin()) {
00132 pu = PU_Info_next(pu);
00133 continue;
00134 }
00135 #endif
00136
00137 DST_TYPE dst = IP_FILE_HDR_dst(cg_node->File_Header());
00138 Is_True(dst != 0, ("No dst"));
00139
00140
00141
00142 if (M.find(dst) == M.end())
00143 M.insert(std::make_pair(dst, idx_pair_vector(M.get_allocator())));
00144
00145 if( !DST_IS_NULL(PU_Info_pu_dst(pu) ))
00146 M[dst].push_back(idx_pair(PU_Info_pu_dst(pu), DST_INVALID_IDX));
00147
00148 if (PU_Info_child(pu))
00149 initialize_dst_map(M, PU_Info_child(pu));
00150
00151 pu = PU_Info_next(pu);
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160 void construct_transitive_closure(dst_hash_map& M)
00161 {
00162 for (dst_hash_map::iterator map_iter = M.begin();
00163 map_iter != M.end();
00164 ++map_iter) {
00165
00166 DST_TYPE dst = map_iter->first;
00167 idx_pair_vector& V = map_iter->second;
00168 idx_pair_vector tmp(V.get_allocator());
00169
00170 std::sort(V.begin(), V.end(), idx_pair_less());
00171 do {
00172 tmp.clear();
00173
00174 for (idx_pair_vector::const_iterator i = V.begin();
00175 i != V.end();
00176 ++i) {
00177 Is_True( !DST_IS_NULL(i->first) ,
00178 ("DST index vector contains an invalid index"));
00179 DST_INFO* info = DST_get_info(dst, i->first);
00180 DST_SUBPROGRAM* subpr = DST_get_subprogram_attr(dst, info);
00181
00182 if (DST_SUBPROGRAM_has_spec(info)) {
00183 DST_IDX spec = DST_SUBPROGRAM_spec(info, subpr);
00184 if( !DST_IS_NULL(spec) ) {
00185 idx_pair spec_pair(spec, DST_INVALID_IDX);
00186 if (!std::binary_search(V.begin(), V.end(), spec_pair,
00187 idx_pair_less()))
00188 tmp.push_back(spec_pair);
00189 }
00190 }
00191 if (DST_SUBPROGRAM_has_origin(info)) {
00192 DST_IDX origin = DST_SUBPROGRAM_origin(info, subpr);
00193 if( !DST_IS_NULL(origin) ) {
00194 idx_pair origin_pair(origin, DST_INVALID_IDX);
00195 if (!std::binary_search(V.begin(), V.end(), origin_pair,
00196 idx_pair_less()))
00197 tmp.push_back(origin_pair);
00198 }
00199 }
00200 }
00201 std::sort(tmp.begin(), tmp.end(), idx_pair_less());
00202 idx_pair_vector::size_type N = V.size();
00203 V.insert(V.end(), tmp.begin(), tmp.end());
00204 std::inplace_merge(V.begin(), V.begin() + N, V.end(),
00205 idx_pair_less());
00206 } while (!tmp.empty());
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 void merge_directories_and_files(dst_hash_map& M, MEM_POOL* p,
00217 DST_TYPE output)
00218 {
00219 Is_True( DST_IS_NULL(DST_get_include_dirs(output)),
00220 ("Output DST already has include dirs"));
00221 Is_True( DST_IS_NULL(DST_get_file_names(output)),
00222 ("Output DST already has file names"));
00223
00224 UINT16 prev_include_dirs = 0;
00225 DST_IDX cur_include_dir = DST_INVALID_IDX;
00226 DST_IDX cur_filename = DST_INVALID_IDX;
00227
00228 for (dst_hash_map::iterator i = M.begin(); i != M.end(); ++i) {
00229 DST_TYPE src = i->first;
00230 UINT16 include_dirs_this_dst = 0;
00231
00232
00233 DST_IDX old_dir = DST_get_include_dirs(src);
00234 while( !DST_IS_NULL(old_dir) ) {
00235 ++include_dirs_this_dst;
00236 cur_include_dir =
00237 DST_copy_include_dir(src, output, p, cur_include_dir, old_dir);
00238 old_dir = DST_INCLUDE_DIR_next(DST_get_include_dir(src, old_dir));
00239 }
00240
00241
00242 DST_IDX old_file = DST_get_file_names(src);
00243 while( !DST_IS_NULL(old_file) ) {
00244 cur_filename = DST_copy_filename(src, output, p, cur_filename, old_file,
00245 prev_include_dirs);
00246 old_file = DST_INCLUDE_DIR_next(DST_get_file_name(src, old_file));
00247 }
00248
00249
00250 prev_include_dirs += include_dirs_this_dst;
00251 }
00252 }
00253
00254
00255 void merge_subprograms(dst_hash_map& M, MEM_POOL* p, DST_TYPE output)
00256 {
00257 using std::binary_search;
00258 using std::lower_bound;
00259
00260 DST_IDX cu_idx = DST_INVALID_IDX;
00261
00262 for (dst_hash_map::iterator dst_iter = M.begin();
00263 dst_iter != M.end();
00264 ++dst_iter) {
00265 DST_TYPE src = dst_iter->first;
00266 idx_pair_vector& V = dst_iter->second;
00267
00268 DST_IDX src_cu_idx = DST_get_compile_unit(src);
00269 Is_True( DST_IS_NULL( DST_INFO_sibling(DST_get_info(src, src_cu_idx)) ),
00270 ("Input dst should have only one compile unit"));
00271
00272
00273 cu_idx = DST_copy_compile_unit(src, output, p, cu_idx, src_cu_idx);
00274
00275
00276 DST_IDX subpr_idx = DST_INVALID_IDX;
00277 idx_pair_vector::iterator i;
00278
00279 for (i = V.begin(); i < V.end(); ++i) {
00280 i->second = subpr_idx =
00281 DST_copy_subprogram(src, output, p, cu_idx, subpr_idx, i->first);
00282 Is_True( !DST_IS_NULL(subpr_idx),
00283 ("Index of new subprogram unit is invalid"));
00284 }
00285
00286
00287 for (i = V.begin(); i < V.end(); ++i) {
00288 DST_INFO* src_sub_info = DST_get_info(src, i->first);
00289 DST_INFO* sub_info = DST_get_info(output, i->second);
00290 DST_SUBPROGRAM* src_sub = DST_get_subprogram_attr(src, src_sub_info);
00291 DST_SUBPROGRAM* sub = DST_get_subprogram_attr(output, sub_info);
00292
00293 if (DST_SUBPROGRAM_has_spec(src_sub_info)) {
00294 DST_IDX src_spec = DST_SUBPROGRAM_spec(src_sub_info, src_sub);
00295 if( !DST_IS_NULL(src_spec) ) {
00296 idx_pair p(src_spec, DST_INVALID_IDX);
00297 Is_True(binary_search(V.begin(), V.end(), p, idx_pair_less()),
00298 ("Input spec index not found in index vector"));
00299 Is_True( DST_ARE_EQUAL( lower_bound(V.begin(), V.end(), p,
00300 idx_pair_less())->first,
00301 src_spec),
00302 ("Inconsistent index vector"));
00303 Is_True( !DST_ARE_EQUAL( lower_bound(V.begin(), V.end(), p,
00304 idx_pair_less())->second,
00305 DST_INVALID_IDX),
00306 ("Input spec index maps to invalid index"));
00307 DST_SUBPROGRAM_spec(sub_info, sub) =
00308 lower_bound(V.begin(), V.end(), p, idx_pair_less())->second;
00309 }
00310 }
00311
00312 if (DST_SUBPROGRAM_has_origin(src_sub_info)) {
00313 DST_IDX src_origin = DST_SUBPROGRAM_origin(src_sub_info, src_sub);
00314 if( !DST_IS_NULL(src_origin) ) {
00315 idx_pair p(src_origin, DST_INVALID_IDX);
00316 Is_True(binary_search(V.begin(), V.end(), p, idx_pair_less()),
00317 ("Input origin index not found in index vector"));
00318 Is_True( DST_ARE_EQUAL( lower_bound(V.begin(), V.end(), p,
00319 idx_pair_less())->first,
00320 src_origin),
00321 ("Inconsistent index vector"));
00322 Is_True( !DST_ARE_EQUAL( lower_bound(V.begin(), V.end(), p,
00323 idx_pair_less())->second,
00324 DST_INVALID_IDX),
00325 ("Input origin index maps to invalid index"));
00326 DST_SUBPROGRAM_origin(sub_info, sub) =
00327 lower_bound(V.begin(), V.end(), p, idx_pair_less())->second;
00328 }
00329 }
00330 }
00331 }
00332 }
00333
00334 void update_pu_dst_indices(dst_hash_map& M, pu_info* pu)
00335 {
00336 Is_True(pu != 0, ("No pu"));
00337
00338 while (pu) {
00339 if( !DST_IS_NULL(PU_Info_pu_dst(pu)) ) {
00340 IPA_NODE* cg_node = Get_Node_From_PU(pu);
00341 DST_TYPE dst = IP_FILE_HDR_dst(cg_node->File_Header());
00342 Is_True(dst != 0, ("No dst"));
00343
00344 Is_True(M.find(dst) != M.end() && M.find(dst)->first == dst,
00345 ("DST not present in map"));
00346
00347 idx_pair_vector& V = M.find(dst)->second;
00348 idx_pair p(PU_Info_pu_dst(pu), DST_INVALID_IDX);
00349 Is_True(std::binary_search(V.begin(), V.end(), p, idx_pair_less()),
00350 ("DST index not present in map"));
00351 Is_True( DST_ARE_EQUAL( std::lower_bound(V.begin(), V.end(), p,
00352 idx_pair_less())->first,
00353 PU_Info_pu_dst(pu) ),
00354 ("DST index not present in map"));
00355 Is_True( !DST_ARE_EQUAL( std::lower_bound(V.begin(), V.end(), p,
00356 idx_pair_less())->second,
00357 DST_INVALID_IDX ),
00358 ("DST index maps to incorrect value"));
00359 PU_Info_pu_dst(pu) = std::lower_bound(V.begin(), V.end(), p,
00360 idx_pair_less())->second;
00361 }
00362
00363 if (PU_Info_child(pu))
00364 update_pu_dst_indices(M, PU_Info_child(pu));
00365
00366 pu = PU_Info_next(pu);
00367 }
00368 }
00369
00370 }
00371
00372
00373 DST_TYPE IPC_merge_DSTs(pu_info* pu_tree, MEM_POOL* p)
00374
00375 {
00376 dst_hash_map M(100, DST_TYPE_hash(), std::equal_to<DST_TYPE>(),
00377 dst_hash_allocator(p));
00378
00379
00380
00381 initialize_dst_map(M, pu_tree);
00382 construct_transitive_closure(M);
00383
00384
00385 DST_TYPE output = DST_create(p);
00386
00387
00388 merge_directories_and_files(M, p, output);
00389
00390
00391
00392 merge_subprograms(M, p, output);
00393
00394
00395 update_pu_dst_indices(M, pu_tree);
00396
00397 return output;
00398 }