@@ -2198,34 +2198,17 @@ pub fn set_link_section(ccx: &CrateContext,
2198
2198
}
2199
2199
}
2200
2200
2201
- pub fn trans_item ( ccx : & CrateContext , item : & hir:: Item ) {
2201
+ fn trans_item ( ccx : & CrateContext , item : & hir:: Item ) {
2202
2202
let _icx = push_ctxt ( "trans_item" ) ;
2203
2203
2204
- let tcx = ccx. tcx ( ) ;
2205
2204
match item. node {
2206
- hir:: ItemFn ( _, _, _, _, _, _) => {
2207
- let def_id = tcx. map . local_def_id ( item. id ) ;
2208
- // check for the #[rustc_error] annotation, which forces an
2209
- // error in trans. This is used to write compile-fail tests
2210
- // that actually test that compilation succeeds without
2211
- // reporting an error.
2212
- if is_entry_fn ( ccx. sess ( ) , item. id ) {
2213
- let empty_substs = ccx. empty_substs_for_def_id ( def_id) ;
2214
- let llfn = Callee :: def ( ccx, def_id, empty_substs) . reify ( ccx) . val ;
2215
- create_entry_wrapper ( ccx, item. span , llfn) ;
2216
- if tcx. has_attr ( def_id, "rustc_error" ) {
2217
- tcx. sess . span_fatal ( item. span , "compilation successful" ) ;
2218
- }
2219
- }
2220
-
2221
- // Function is actually translated in trans_instance
2222
- }
2223
2205
hir:: ItemEnum ( ref enum_definition, ref gens) => {
2224
2206
if gens. ty_params . is_empty ( ) {
2225
2207
// sizes only make sense for non-generic types
2226
2208
enum_variant_size_lint ( ccx, enum_definition, item. span , item. id ) ;
2227
2209
}
2228
2210
}
2211
+ hir:: ItemFn ( ..) |
2229
2212
hir:: ItemImpl ( ..) |
2230
2213
hir:: ItemStatic ( ..) => {
2231
2214
// Don't do anything here. Translation has been moved to
@@ -2235,22 +2218,40 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
2235
2218
}
2236
2219
}
2237
2220
2238
- pub fn is_entry_fn ( sess : & Session , node_id : ast:: NodeId ) -> bool {
2239
- match * sess. entry_fn . borrow ( ) {
2240
- Some ( ( entry_id, _) ) => node_id == entry_id,
2241
- None => false ,
2221
+ /// Create the `main` function which will initialise the rust runtime and call
2222
+ /// users’ main function.
2223
+ pub fn maybe_create_entry_wrapper ( ccx : & CrateContext ) {
2224
+ let ( main_def_id, span) = match * ccx. sess ( ) . entry_fn . borrow ( ) {
2225
+ Some ( ( id, span) ) => {
2226
+ ( ccx. tcx ( ) . map . local_def_id ( id) , span)
2227
+ }
2228
+ None => return ,
2229
+ } ;
2230
+
2231
+ // check for the #[rustc_error] annotation, which forces an
2232
+ // error in trans. This is used to write compile-fail tests
2233
+ // that actually test that compilation succeeds without
2234
+ // reporting an error.
2235
+ if ccx. tcx ( ) . has_attr ( main_def_id, "rustc_error" ) {
2236
+ ccx. tcx ( ) . sess . span_fatal ( span, "compilation successful" ) ;
2237
+ }
2238
+
2239
+ let instance = Instance :: mono ( ccx. shared ( ) , main_def_id) ;
2240
+
2241
+ if !ccx. codegen_unit ( ) . items . contains_key ( & TransItem :: Fn ( instance) ) {
2242
+ // We want to create the wrapper in the same codegen unit as Rust's main
2243
+ // function.
2244
+ return ;
2242
2245
}
2243
- }
2244
2246
2245
- /// Create the `main` function which will initialise the rust runtime and call users’ main
2246
- /// function.
2247
- pub fn create_entry_wrapper ( ccx : & CrateContext , sp : Span , main_llfn : ValueRef ) {
2247
+ let main_llfn = Callee :: def ( ccx, main_def_id, instance. substs ) . reify ( ccx) . val ;
2248
+
2248
2249
let et = ccx. sess ( ) . entry_type . get ( ) . unwrap ( ) ;
2249
2250
match et {
2250
2251
config:: EntryMain => {
2251
- create_entry_fn ( ccx, sp , main_llfn, true ) ;
2252
+ create_entry_fn ( ccx, span , main_llfn, true ) ;
2252
2253
}
2253
- config:: EntryStart => create_entry_fn ( ccx, sp , main_llfn, false ) ,
2254
+ config:: EntryStart => create_entry_fn ( ccx, span , main_llfn, false ) ,
2254
2255
config:: EntryNone => { } // Do nothing.
2255
2256
}
2256
2257
@@ -2590,13 +2591,11 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2590
2591
} ;
2591
2592
let no_builtins = attr:: contains_name ( & krate. attrs , "no_builtins" ) ;
2592
2593
2593
- let ( codegen_units, symbol_map) =
2594
- collect_and_partition_translation_items ( & shared_ccx) ;
2594
+ // Run the translation item collector and partition the collected items into
2595
+ // codegen units.
2596
+ let ( codegen_units, symbol_map) = collect_and_partition_translation_items ( & shared_ccx) ;
2595
2597
let codegen_unit_count = codegen_units. len ( ) ;
2596
2598
2597
- assert ! ( tcx. sess. opts. cg. codegen_units == codegen_unit_count ||
2598
- tcx. sess. opts. debugging_opts. incremental. is_some( ) ) ;
2599
-
2600
2599
let symbol_map = Rc :: new ( symbol_map) ;
2601
2600
2602
2601
let crate_context_list = CrateContextList :: new ( & shared_ccx,
@@ -2642,35 +2641,39 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2642
2641
for ( trans_item, _) in trans_items {
2643
2642
trans_item. define ( & ccx) ;
2644
2643
}
2645
- }
2646
-
2647
- {
2648
- let ccx = crate_context_list. get_ccx ( 0 ) ;
2649
-
2650
- // Translate all items. See `TransModVisitor` for
2651
- // details on why we walk in this particular way.
2652
- {
2653
- let _icx = push_ctxt ( "text" ) ;
2654
- intravisit:: walk_mod ( & mut TransItemsWithinModVisitor { ccx : & ccx } , & krate. module ) ;
2655
- krate. visit_all_items ( & mut TransModVisitor { ccx : & ccx } ) ;
2656
- }
2657
2644
2658
- collector:: print_collection_results ( ccx. shared ( ) ) ;
2645
+ // If this codegen unit contains the main function, also create the
2646
+ // wrapper here
2647
+ maybe_create_entry_wrapper ( & ccx) ;
2659
2648
2660
- symbol_names_test:: report_symbol_names ( & ccx) ;
2661
- }
2662
-
2663
- for ccx in crate_context_list. iter ( ) {
2664
- if ccx. sess ( ) . opts . debuginfo != NoDebugInfo {
2665
- debuginfo:: finalize ( & ccx) ;
2666
- }
2649
+ // Run replace-all-uses-with for statics that need it
2667
2650
for & ( old_g, new_g) in ccx. statics_to_rauw ( ) . borrow ( ) . iter ( ) {
2668
2651
unsafe {
2669
2652
let bitcast = llvm:: LLVMConstPointerCast ( new_g, llvm:: LLVMTypeOf ( old_g) ) ;
2670
2653
llvm:: LLVMReplaceAllUsesWith ( old_g, bitcast) ;
2671
2654
llvm:: LLVMDeleteGlobal ( old_g) ;
2672
2655
}
2673
2656
}
2657
+
2658
+ // Finalize debuginfo
2659
+ if ccx. sess ( ) . opts . debuginfo != NoDebugInfo {
2660
+ debuginfo:: finalize ( & ccx) ;
2661
+ }
2662
+ }
2663
+
2664
+ collector:: print_collection_results ( & shared_ccx) ;
2665
+ symbol_names_test:: report_symbol_names ( & shared_ccx) ;
2666
+
2667
+ {
2668
+ let ccx = crate_context_list. get_ccx ( 0 ) ;
2669
+
2670
+ // At this point, we only walk the HIR for running
2671
+ // enum_variant_size_lint(). This should arguably be moved somewhere
2672
+ // else
2673
+ {
2674
+ intravisit:: walk_mod ( & mut TransItemsWithinModVisitor { ccx : & ccx } , & krate. module ) ;
2675
+ krate. visit_all_items ( & mut TransModVisitor { ccx : & ccx } ) ;
2676
+ }
2674
2677
}
2675
2678
2676
2679
if shared_ccx. sess ( ) . trans_stats ( ) {
@@ -2696,6 +2699,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2696
2699
}
2697
2700
}
2698
2701
}
2702
+
2699
2703
if shared_ccx. sess ( ) . count_llvm_insns ( ) {
2700
2704
for ( k, v) in shared_ccx. stats ( ) . llvm_insns . borrow ( ) . iter ( ) {
2701
2705
println ! ( "{:7} {}" , * v, * k) ;
@@ -2867,6 +2871,9 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
2867
2871
scx. reachable ( ) )
2868
2872
} ) ;
2869
2873
2874
+ assert ! ( scx. tcx( ) . sess. opts. cg. codegen_units == codegen_units. len( ) ||
2875
+ scx. tcx( ) . sess. opts. debugging_opts. incremental. is_some( ) ) ;
2876
+
2870
2877
if scx. sess ( ) . opts . debugging_opts . print_trans_items . is_some ( ) {
2871
2878
let mut item_to_cgus = HashMap :: new ( ) ;
2872
2879
0 commit comments