@@ -75,6 +75,7 @@ use debuginfo::{self, DebugLoc, ToDebugLoc};
75
75
use declare;
76
76
use expr;
77
77
use glue;
78
+ use inline;
78
79
use machine;
79
80
use machine:: { llalign_of_min, llsize_of, llsize_of_real} ;
80
81
use meth;
@@ -1948,6 +1949,49 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1948
1949
closure:: ClosureEnv :: NotClosure ) ;
1949
1950
}
1950
1951
1952
+ pub fn trans_instance < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > , instance : Instance < ' tcx > ) {
1953
+ let instance = inline:: maybe_inline_instance ( ccx, instance) ;
1954
+
1955
+ let fn_node_id = ccx. tcx ( ) . map . as_local_node_id ( instance. def ) . unwrap ( ) ;
1956
+
1957
+ let _s = StatRecorder :: new ( ccx, ccx. tcx ( ) . node_path_str ( fn_node_id) ) ;
1958
+ debug ! ( "trans_instance(instance={:?})" , instance) ;
1959
+ let _icx = push_ctxt ( "trans_instance" ) ;
1960
+
1961
+ let item = ccx. tcx ( ) . map . find ( fn_node_id) . unwrap ( ) ;
1962
+
1963
+ let fn_ty = ccx. tcx ( ) . lookup_item_type ( instance. def ) . ty ;
1964
+ let fn_ty = ccx. tcx ( ) . erase_regions ( & fn_ty) ;
1965
+ let fn_ty = monomorphize:: apply_param_substs ( ccx. tcx ( ) , instance. substs , & fn_ty) ;
1966
+
1967
+ let sig = ccx. tcx ( ) . erase_late_bound_regions ( fn_ty. fn_sig ( ) ) ;
1968
+ let sig = ccx. tcx ( ) . normalize_associated_type ( & sig) ;
1969
+ let abi = fn_ty. fn_abi ( ) ;
1970
+
1971
+ let lldecl = match ccx. instances ( ) . borrow ( ) . get ( & instance) {
1972
+ Some ( & val) => val,
1973
+ None => bug ! ( "Instance `{:?}` not already declared" , instance)
1974
+ } ;
1975
+
1976
+ match item {
1977
+ hir_map:: NodeItem ( & hir:: Item {
1978
+ node : hir:: ItemFn ( ref decl, _, _, _, _, ref body) , ..
1979
+ } ) |
1980
+ hir_map:: NodeTraitItem ( & hir:: TraitItem {
1981
+ node : hir:: MethodTraitItem (
1982
+ hir:: MethodSig { ref decl, .. } , Some ( ref body) ) , ..
1983
+ } ) |
1984
+ hir_map:: NodeImplItem ( & hir:: ImplItem {
1985
+ node : hir:: ImplItemKind :: Method (
1986
+ hir:: MethodSig { ref decl, .. } , ref body) , ..
1987
+ } ) => {
1988
+ trans_closure ( ccx, decl, body, lldecl, instance,
1989
+ fn_node_id, & sig, abi, closure:: ClosureEnv :: NotClosure ) ;
1990
+ }
1991
+ _ => bug ! ( "Instance is a {:?}?" , item)
1992
+ }
1993
+ }
1994
+
1951
1995
pub fn trans_named_tuple_constructor < ' blk , ' tcx > ( mut bcx : Block < ' blk , ' tcx > ,
1952
1996
ctor_ty : Ty < ' tcx > ,
1953
1997
disr : Disr ,
@@ -2267,79 +2311,33 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
2267
2311
let _icx = push_ctxt ( "trans_item" ) ;
2268
2312
2269
2313
let tcx = ccx. tcx ( ) ;
2270
- let from_external = ccx. external_srcs ( ) . borrow ( ) . contains_key ( & item. id ) ;
2271
-
2272
2314
match item. node {
2273
- hir:: ItemFn ( ref decl, _, _, _, ref generics, ref body) => {
2274
- if !generics. is_type_parameterized ( ) {
2275
- let trans_everywhere = attr:: requests_inline ( & item. attrs ) ;
2276
- // Ignore `trans_everywhere` for cross-crate inlined items
2277
- // (`from_external`). `trans_item` will be called once for each
2278
- // compilation unit that references the item, so it will still get
2279
- // translated everywhere it's needed.
2280
- for ( ref ccx, is_origin) in ccx. maybe_iter ( !from_external && trans_everywhere) {
2281
- let def_id = tcx. map . local_def_id ( item. id ) ;
2282
- let empty_substs = ccx. empty_substs_for_def_id ( def_id) ;
2283
- let llfn = Callee :: def ( ccx, def_id, empty_substs) . reify ( ccx) . val ;
2284
- trans_fn ( ccx, & decl, & body, llfn, empty_substs, item. id ) ;
2285
- set_link_section ( ccx, llfn, & item. attrs ) ;
2286
- update_linkage ( ccx,
2287
- llfn,
2288
- Some ( item. id ) ,
2289
- if is_origin {
2290
- OriginalTranslation
2291
- } else {
2292
- InlinedCopy
2293
- } ) ;
2294
-
2295
- if is_entry_fn ( ccx. sess ( ) , item. id ) {
2296
- create_entry_wrapper ( ccx, item. span , llfn) ;
2297
- // check for the #[rustc_error] annotation, which forces an
2298
- // error in trans. This is used to write compile-fail tests
2299
- // that actually test that compilation succeeds without
2300
- // reporting an error.
2301
- if tcx. has_attr ( def_id, "rustc_error" ) {
2302
- tcx. sess . span_fatal ( item. span , "compilation successful" ) ;
2303
- }
2304
- }
2315
+ hir:: ItemFn ( _, _, _, _, _, _) => {
2316
+ let def_id = tcx. map . local_def_id ( item. id ) ;
2317
+ // check for the #[rustc_error] annotation, which forces an
2318
+ // error in trans. This is used to write compile-fail tests
2319
+ // that actually test that compilation succeeds without
2320
+ // reporting an error.
2321
+ if is_entry_fn ( ccx. sess ( ) , item. id ) {
2322
+ let empty_substs = ccx. empty_substs_for_def_id ( def_id) ;
2323
+ let llfn = Callee :: def ( ccx, def_id, empty_substs) . reify ( ccx) . val ;
2324
+ create_entry_wrapper ( ccx, item. span , llfn) ;
2325
+ if tcx. has_attr ( def_id, "rustc_error" ) {
2326
+ tcx. sess . span_fatal ( item. span , "compilation successful" ) ;
2305
2327
}
2306
2328
}
2307
- }
2308
- hir:: ItemImpl ( _, _, ref generics, _, _, ref impl_items) => {
2309
- // Both here and below with generic methods, be sure to recurse and look for
2310
- // items that we need to translate.
2311
- if !generics. ty_params . is_empty ( ) {
2312
- return ;
2313
- }
2314
2329
2315
- for impl_item in impl_items {
2316
- if let hir:: ImplItemKind :: Method ( ref sig, ref body) = impl_item. node {
2317
- if sig. generics . ty_params . is_empty ( ) {
2318
- let trans_everywhere = attr:: requests_inline ( & impl_item. attrs ) ;
2319
- for ( ref ccx, is_origin) in ccx. maybe_iter ( trans_everywhere) {
2320
- let def_id = tcx. map . local_def_id ( impl_item. id ) ;
2321
- let empty_substs = ccx. empty_substs_for_def_id ( def_id) ;
2322
- let llfn = Callee :: def ( ccx, def_id, empty_substs) . reify ( ccx) . val ;
2323
- trans_fn ( ccx, & sig. decl , body, llfn, empty_substs, impl_item. id ) ;
2324
- update_linkage ( ccx, llfn, Some ( impl_item. id ) ,
2325
- if is_origin {
2326
- OriginalTranslation
2327
- } else {
2328
- InlinedCopy
2329
- } ) ;
2330
- }
2331
- }
2332
- }
2333
- }
2330
+ // Function is actually translated in trans_instance
2334
2331
}
2335
2332
hir:: ItemEnum ( ref enum_definition, ref gens) => {
2336
2333
if gens. ty_params . is_empty ( ) {
2337
2334
// sizes only make sense for non-generic types
2338
2335
enum_variant_size_lint ( ccx, enum_definition, item. span , item. id ) ;
2339
2336
}
2340
2337
}
2338
+ hir:: ItemImpl ( ..) |
2341
2339
hir:: ItemStatic ( ..) => {
2342
- // Don't do anything here. Translation of statics has been moved to
2340
+ // Don't do anything here. Translation has been moved to
2343
2341
// being "collector-driven".
2344
2342
}
2345
2343
_ => { }
@@ -2482,16 +2480,16 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
2482
2480
let linkage = llvm:: LLVMGetLinkage ( val) ;
2483
2481
// We only care about external declarations (not definitions)
2484
2482
// and available_externally definitions.
2485
- if !( linkage == llvm:: ExternalLinkage as c_uint &&
2486
- llvm:: LLVMIsDeclaration ( val) != 0 ) &&
2487
- !( linkage == llvm:: AvailableExternallyLinkage as c_uint ) {
2488
- continue ;
2483
+ let is_available_externally = linkage == llvm:: AvailableExternallyLinkage as c_uint ;
2484
+ let is_decl = llvm:: LLVMIsDeclaration ( val) != 0 ;
2485
+
2486
+ if is_decl || is_available_externally {
2487
+ let name = CStr :: from_ptr ( llvm:: LLVMGetValueName ( val) )
2488
+ . to_bytes ( )
2489
+ . to_vec ( ) ;
2490
+ declared. insert ( name) ;
2489
2491
}
2490
2492
2491
- let name = CStr :: from_ptr ( llvm:: LLVMGetValueName ( val) )
2492
- . to_bytes ( )
2493
- . to_vec ( ) ;
2494
- declared. insert ( name) ;
2495
2493
}
2496
2494
}
2497
2495
@@ -2501,21 +2499,27 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
2501
2499
for ccx in cx. iter ( ) {
2502
2500
for val in iter_globals ( ccx. llmod ( ) ) . chain ( iter_functions ( ccx. llmod ( ) ) ) {
2503
2501
let linkage = llvm:: LLVMGetLinkage ( val) ;
2502
+
2503
+ let is_external = linkage == llvm:: ExternalLinkage as c_uint ;
2504
+ let is_weak_odr = linkage == llvm:: WeakODRLinkage as c_uint ;
2505
+ let is_decl = llvm:: LLVMIsDeclaration ( val) != 0 ;
2506
+
2504
2507
// We only care about external definitions.
2505
- if !( ( linkage == llvm:: ExternalLinkage as c_uint ||
2506
- linkage == llvm:: WeakODRLinkage as c_uint ) &&
2507
- llvm:: LLVMIsDeclaration ( val) == 0 ) {
2508
- continue ;
2509
- }
2508
+ if ( is_external || is_weak_odr) && !is_decl {
2509
+
2510
+ let name = CStr :: from_ptr ( llvm:: LLVMGetValueName ( val) )
2511
+ . to_bytes ( )
2512
+ . to_vec ( ) ;
2513
+
2514
+ let is_declared = declared. contains ( & name) ;
2515
+ let reachable = reachable. contains ( str:: from_utf8 ( & name) . unwrap ( ) ) ;
2516
+
2517
+ if !is_declared && !reachable {
2518
+ llvm:: SetLinkage ( val, llvm:: InternalLinkage ) ;
2519
+ llvm:: SetDLLStorageClass ( val, llvm:: DefaultStorageClass ) ;
2520
+ llvm:: UnsetComdat ( val) ;
2521
+ }
2510
2522
2511
- let name = CStr :: from_ptr ( llvm:: LLVMGetValueName ( val) )
2512
- . to_bytes ( )
2513
- . to_vec ( ) ;
2514
- if !declared. contains ( & name) &&
2515
- !reachable. contains ( str:: from_utf8 ( & name) . unwrap ( ) ) {
2516
- llvm:: SetLinkage ( val, llvm:: InternalLinkage ) ;
2517
- llvm:: SetDLLStorageClass ( val, llvm:: DefaultStorageClass ) ;
2518
- llvm:: UnsetComdat ( val) ;
2519
2523
}
2520
2524
}
2521
2525
}
@@ -2744,6 +2748,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2744
2748
span_bug ! ( item. span, "Mismatch between hir::Item type and TransItem type" )
2745
2749
}
2746
2750
}
2751
+ TransItem :: Fn ( instance) => {
2752
+ trans_instance ( & ccx, instance) ;
2753
+ }
2747
2754
_ => { }
2748
2755
}
2749
2756
}
@@ -2980,7 +2987,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
2980
2987
let mut item_keys: Vec < _ > = items
2981
2988
. iter ( )
2982
2989
. map ( |i| {
2983
- let mut output = i. to_string ( scx. tcx ( ) ) ;
2990
+ let mut output = i. to_string ( scx) ;
2984
2991
output. push_str ( " @@" ) ;
2985
2992
let mut empty = Vec :: new ( ) ;
2986
2993
let mut cgus = item_to_cgus. get_mut ( i) . unwrap_or ( & mut empty) ;
0 commit comments