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