@@ -194,11 +194,12 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
194
194
use rustc:: hir:: map as hir_map;
195
195
use rustc:: hir:: def_id:: DefId ;
196
196
use rustc:: middle:: const_val:: ConstVal ;
197
- use rustc:: middle:: lang_items:: { ExchangeMallocFnLangItem } ;
197
+ use rustc:: middle:: lang_items:: { ExchangeMallocFnLangItem , StartFnLangItem } ;
198
198
use rustc:: traits;
199
- use rustc:: ty:: subst:: Substs ;
199
+ use rustc:: ty:: subst:: { Substs , Kind } ;
200
200
use rustc:: ty:: { self , TypeFoldable , Ty , TyCtxt } ;
201
201
use rustc:: ty:: adjustment:: CustomCoerceUnsized ;
202
+ use rustc:: session:: config;
202
203
use rustc:: mir:: { self , Location } ;
203
204
use rustc:: mir:: visit:: Visitor as MirVisitor ;
204
205
use rustc:: mir:: mono:: MonoItem ;
@@ -212,6 +213,8 @@ use rustc_data_structures::bitvec::BitVector;
212
213
213
214
use syntax:: attr;
214
215
216
+ use std:: iter;
217
+
215
218
#[ derive( PartialEq , Eq , Hash , Clone , Copy , Debug ) ]
216
219
pub enum MonoItemCollectionMode {
217
220
Eager ,
@@ -329,6 +332,8 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
329
332
tcx. hir . local_def_id ( node_id)
330
333
} ) ;
331
334
335
+ debug ! ( "collect_roots: entry_fn = {:?}" , entry_fn) ;
336
+
332
337
let mut visitor = RootCollector {
333
338
tcx,
334
339
mode,
@@ -951,16 +956,8 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
951
956
// actually used somewhere. Just declaring them is insufficient.
952
957
}
953
958
hir:: ItemFn ( ..) => {
954
- let tcx = self . tcx ;
955
- let def_id = tcx. hir . local_def_id ( item. id ) ;
956
-
957
- if self . is_root ( def_id) {
958
- debug ! ( "RootCollector: ItemFn({})" ,
959
- def_id_to_string( tcx, def_id) ) ;
960
-
961
- let instance = Instance :: mono ( tcx, def_id) ;
962
- self . output . push ( MonoItem :: Fn ( instance) ) ;
963
- }
959
+ let def_id = self . tcx . hir . local_def_id ( item. id ) ;
960
+ self . push_if_root ( def_id) ;
964
961
}
965
962
}
966
963
}
@@ -973,16 +970,8 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
973
970
fn visit_impl_item ( & mut self , ii : & ' v hir:: ImplItem ) {
974
971
match ii. node {
975
972
hir:: ImplItemKind :: Method ( hir:: MethodSig { .. } , _) => {
976
- let tcx = self . tcx ;
977
- let def_id = tcx. hir . local_def_id ( ii. id ) ;
978
-
979
- if self . is_root ( def_id) {
980
- debug ! ( "RootCollector: MethodImplItem({})" ,
981
- def_id_to_string( tcx, def_id) ) ;
982
-
983
- let instance = Instance :: mono ( tcx, def_id) ;
984
- self . output . push ( MonoItem :: Fn ( instance) ) ;
985
- }
973
+ let def_id = self . tcx . hir . local_def_id ( ii. id ) ;
974
+ self . push_if_root ( def_id) ;
986
975
}
987
976
_ => { /* Nothing to do here */ }
988
977
}
@@ -1003,6 +992,56 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
1003
992
}
1004
993
}
1005
994
}
995
+
996
+ /// If `def_id` represents a root, then push it onto the list of
997
+ /// outputs. (Note that all roots must be monomorphic.)
998
+ fn push_if_root ( & mut self , def_id : DefId ) {
999
+ if self . is_root ( def_id) {
1000
+ debug ! ( "RootCollector::push_if_root: found root def_id={:?}" , def_id) ;
1001
+
1002
+ let instance = Instance :: mono ( self . tcx , def_id) ;
1003
+ self . output . push ( create_fn_mono_item ( instance) ) ;
1004
+
1005
+ self . push_extra_entry_roots ( def_id) ;
1006
+ }
1007
+ }
1008
+
1009
+ /// As a special case, when/if we encounter the
1010
+ /// `main()` function, we also have to generate a
1011
+ /// monomorphized copy of the start lang item based on
1012
+ /// the return type of `main`. This is not needed when
1013
+ /// the user writes their own `start` manually.
1014
+ fn push_extra_entry_roots ( & mut self , def_id : DefId ) {
1015
+ if self . entry_fn != Some ( def_id) {
1016
+ return ;
1017
+ }
1018
+
1019
+ if self . tcx . sess . entry_type . get ( ) != Some ( config:: EntryMain ) {
1020
+ return ;
1021
+ }
1022
+
1023
+ let start_def_id = match self . tcx . lang_items ( ) . require ( StartFnLangItem ) {
1024
+ Ok ( s) => s,
1025
+ Err ( err) => self . tcx . sess . fatal ( & err) ,
1026
+ } ;
1027
+ let main_ret_ty = self . tcx . fn_sig ( def_id) . output ( ) ;
1028
+
1029
+ // Given that `main()` has no arguments,
1030
+ // then its return type cannot have
1031
+ // late-bound regions, since late-bound
1032
+ // regions must appear in the argument
1033
+ // listing.
1034
+ let main_ret_ty = main_ret_ty. no_late_bound_regions ( ) . unwrap ( ) ;
1035
+
1036
+ let start_instance = Instance :: resolve (
1037
+ self . tcx ,
1038
+ ty:: ParamEnv :: empty ( traits:: Reveal :: All ) ,
1039
+ start_def_id,
1040
+ self . tcx . mk_substs ( iter:: once ( Kind :: from ( main_ret_ty) ) )
1041
+ ) . unwrap ( ) ;
1042
+
1043
+ self . output . push ( create_fn_mono_item ( start_instance) ) ;
1044
+ }
1006
1045
}
1007
1046
1008
1047
fn item_has_type_parameters < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> bool {
0 commit comments