188188//! this is not implemented however: a translation item will be produced
189189//! regardless of whether it is actually needed or not.
190190
191+ use rustc_data_structures:: bitvec:: BitVector ;
192+
191193use rustc:: hir;
192194use rustc:: hir:: intravisit as hir_visit;
193195
@@ -252,12 +254,74 @@ impl<'tcx> Hash for TransItem<'tcx> {
252254 }
253255}
254256
255- pub type InliningMap < ' tcx > = FnvHashMap < TransItem < ' tcx > , FnvHashSet < TransItem < ' tcx > > > ;
257+ /// Maps every translation item to all translation items it references in its
258+ /// body.
259+ pub struct ReferenceMap < ' tcx > {
260+ index : FnvHashMap < TransItem < ' tcx > , ( usize , usize ) > ,
261+ targets : Vec < TransItem < ' tcx > > ,
262+ inlined : BitVector
263+ }
264+
265+ impl < ' tcx > ReferenceMap < ' tcx > {
266+
267+ fn new ( ) -> ReferenceMap < ' tcx > {
268+ ReferenceMap {
269+ index : FnvHashMap ( ) ,
270+ targets : Vec :: new ( ) ,
271+ inlined : BitVector :: new ( 64 * 256 ) ,
272+ }
273+ }
274+
275+ fn record_references < I > ( & mut self , source : TransItem < ' tcx > , targets : I )
276+ where I : Iterator < Item =( TransItem < ' tcx > , bool ) >
277+ {
278+ assert ! ( !self . index. contains_key( & source) ) ;
279+
280+ let start_index = self . targets . len ( ) ;
281+
282+ for ( target, inlined) in targets {
283+ let index = self . targets . len ( ) ;
284+ self . targets . push ( target) ;
285+ self . inlined . grow ( index + 1 ) ;
286+
287+ if inlined {
288+ self . inlined . insert ( index) ;
289+ }
290+ }
291+
292+ let end_index = self . targets . len ( ) ;
293+ self . index . insert ( source, ( start_index, end_index) ) ;
294+ }
295+
296+ // Internally iterate over all items referenced by `source` which will be
297+ // made available for inlining.
298+ pub fn with_inlining_candidates < F > ( & self , source : TransItem < ' tcx > , mut f : F )
299+ where F : FnMut ( TransItem < ' tcx > )
300+ {
301+ if let Some ( & ( start_index, end_index) ) = self . index . get ( & source)
302+ {
303+ for index in start_index .. end_index {
304+ if self . inlined . contains ( index) {
305+ f ( self . targets [ index] )
306+ }
307+ }
308+ }
309+ }
310+
311+ pub fn get_direct_references_from ( & self , source : TransItem < ' tcx > ) -> & [ TransItem < ' tcx > ]
312+ {
313+ if let Some ( & ( start_index, end_index) ) = self . index . get ( & source) {
314+ & self . targets [ start_index .. end_index]
315+ } else {
316+ & self . targets [ 0 .. 0 ]
317+ }
318+ }
319+ }
256320
257321pub fn collect_crate_translation_items < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
258322 mode : TransItemCollectionMode )
259323 -> ( FnvHashSet < TransItem < ' tcx > > ,
260- InliningMap < ' tcx > ) {
324+ ReferenceMap < ' tcx > ) {
261325 // We are not tracking dependencies of this pass as it has to be re-executed
262326 // every time no matter what.
263327 ccx. tcx ( ) . dep_graph . with_ignore ( || {
@@ -266,17 +330,17 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
266330 debug ! ( "Building translation item graph, beginning at roots" ) ;
267331 let mut visited = FnvHashSet ( ) ;
268332 let mut recursion_depths = DefIdMap ( ) ;
269- let mut inlining_map = FnvHashMap ( ) ;
333+ let mut reference_map = ReferenceMap :: new ( ) ;
270334
271335 for root in roots {
272336 collect_items_rec ( ccx,
273337 root,
274338 & mut visited,
275339 & mut recursion_depths,
276- & mut inlining_map ) ;
340+ & mut reference_map ) ;
277341 }
278342
279- ( visited, inlining_map )
343+ ( visited, reference_map )
280344 } )
281345}
282346
@@ -307,7 +371,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
307371 starting_point : TransItem < ' tcx > ,
308372 visited : & mut FnvHashSet < TransItem < ' tcx > > ,
309373 recursion_depths : & mut DefIdMap < usize > ,
310- inlining_map : & mut InliningMap < ' tcx > ) {
374+ reference_map : & mut ReferenceMap < ' tcx > ) {
311375 if !visited. insert ( starting_point. clone ( ) ) {
312376 // We've been here already, no need to search again.
313377 return ;
@@ -351,9 +415,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
351415 }
352416 }
353417
418+ record_references ( ccx, starting_point, & neighbors[ ..] , reference_map) ;
419+
354420 for neighbour in neighbors {
355- record_inlined_use ( ccx, starting_point, neighbour, inlining_map) ;
356- collect_items_rec ( ccx, neighbour, visited, recursion_depths, inlining_map) ;
421+ collect_items_rec ( ccx, neighbour, visited, recursion_depths, reference_map) ;
357422 }
358423
359424 if let Some ( ( def_id, depth) ) = recursion_depth_reset {
@@ -363,16 +428,17 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
363428 debug ! ( "END collect_items_rec({})" , starting_point. to_string( ccx) ) ;
364429}
365430
366- fn record_inlined_use < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
367- caller : TransItem < ' tcx > ,
368- callee : TransItem < ' tcx > ,
369- inlining_map : & mut InliningMap < ' tcx > ) {
370- if callee. is_from_extern_crate ( ) ||
371- callee. requests_inline ( ccx. tcx ( ) ) {
372- inlining_map. entry ( caller)
373- . or_insert_with ( || FnvHashSet ( ) )
374- . insert ( callee) ;
375- }
431+ fn record_references < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
432+ caller : TransItem < ' tcx > ,
433+ callees : & [ TransItem < ' tcx > ] ,
434+ reference_map : & mut ReferenceMap < ' tcx > ) {
435+ let iter = callees. into_iter ( )
436+ . map ( |callee| {
437+ let is_inlining_candidate = callee. is_from_extern_crate ( ) ||
438+ callee. requests_inline ( ccx. tcx ( ) ) ;
439+ ( * callee, is_inlining_candidate)
440+ } ) ;
441+ reference_map. record_references ( caller, iter) ;
376442}
377443
378444fn check_recursion_limit < ' a , ' tcx : ' a > ( ccx : & CrateContext < ' a , ' tcx > ,
0 commit comments