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