@@ -85,6 +85,7 @@ use arena::TypedArena;
85
85
use libc:: { c_uint, uint64_t} ;
86
86
use std:: c_str:: ToCStr ;
87
87
use std:: cell:: { Cell , RefCell } ;
88
+ use std:: collections:: HashSet ;
88
89
use std:: rc:: Rc ;
89
90
use std:: { i8, i16, i32, i64} ;
90
91
use syntax:: abi:: { X86 , X86_64 , Arm , Mips , Mipsel , Rust , RustCall } ;
@@ -2891,6 +2892,84 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
2891
2892
return metadata;
2892
2893
}
2893
2894
2895
+ /// Find any symbols that are defined in one compilation unit, but not declared
2896
+ /// in any other compilation unit. Give these symbols internal linkage.
2897
+ fn internalize_symbols ( cx : & SharedCrateContext , reachable : & HashSet < String > ) {
2898
+ use std:: c_str:: CString ;
2899
+
2900
+ unsafe {
2901
+ let mut declared = HashSet :: new ( ) ;
2902
+
2903
+ let iter_globals = |llmod| {
2904
+ ValueIter {
2905
+ cur : llvm:: LLVMGetFirstGlobal ( llmod) ,
2906
+ step : llvm:: LLVMGetNextGlobal ,
2907
+ }
2908
+ } ;
2909
+
2910
+ let iter_functions = |llmod| {
2911
+ ValueIter {
2912
+ cur : llvm:: LLVMGetFirstFunction ( llmod) ,
2913
+ step : llvm:: LLVMGetNextFunction ,
2914
+ }
2915
+ } ;
2916
+
2917
+ // Collect all external declarations in all compilation units.
2918
+ for ccx in cx. iter ( ) {
2919
+ for val in iter_globals ( ccx. llmod ( ) ) . chain ( iter_functions ( ccx. llmod ( ) ) ) {
2920
+ let linkage = llvm:: LLVMGetLinkage ( val) ;
2921
+ // We only care about external declarations (not definitions)
2922
+ // and available_externally definitions.
2923
+ if !( linkage == llvm:: ExternalLinkage as c_uint &&
2924
+ llvm:: LLVMIsDeclaration ( val) != 0 ) &&
2925
+ !( linkage == llvm:: AvailableExternallyLinkage as c_uint ) {
2926
+ continue
2927
+ }
2928
+
2929
+ let name = CString :: new ( llvm:: LLVMGetValueName ( val) , false ) ;
2930
+ declared. insert ( name) ;
2931
+ }
2932
+ }
2933
+
2934
+ // Examine each external definition. If the definition is not used in
2935
+ // any other compilation unit, and is not reachable from other crates,
2936
+ // then give it internal linkage.
2937
+ for ccx in cx. iter ( ) {
2938
+ for val in iter_globals ( ccx. llmod ( ) ) . chain ( iter_functions ( ccx. llmod ( ) ) ) {
2939
+ // We only care about external definitions.
2940
+ if !( llvm:: LLVMGetLinkage ( val) == llvm:: ExternalLinkage as c_uint &&
2941
+ llvm:: LLVMIsDeclaration ( val) == 0 ) {
2942
+ continue
2943
+ }
2944
+
2945
+ let name = CString :: new ( llvm:: LLVMGetValueName ( val) , false ) ;
2946
+ if !declared. contains ( & name) &&
2947
+ !reachable. contains_equiv ( & name. as_str ( ) . unwrap ( ) ) {
2948
+ llvm:: SetLinkage ( val, llvm:: InternalLinkage ) ;
2949
+ }
2950
+ }
2951
+ }
2952
+ }
2953
+
2954
+
2955
+ struct ValueIter {
2956
+ cur : ValueRef ,
2957
+ step : unsafe extern "C" fn ( ValueRef ) -> ValueRef ,
2958
+ }
2959
+
2960
+ impl Iterator < ValueRef > for ValueIter {
2961
+ fn next ( & mut self ) -> Option < ValueRef > {
2962
+ let old = self . cur ;
2963
+ if !old. is_null ( ) {
2964
+ self . cur = unsafe { ( self . step ) ( old) } ;
2965
+ Some ( old)
2966
+ } else {
2967
+ None
2968
+ }
2969
+ }
2970
+ }
2971
+ }
2972
+
2894
2973
pub fn trans_crate ( krate : ast:: Crate ,
2895
2974
analysis : CrateAnalysis ) -> ( ty:: ctxt , CrateTranslation ) {
2896
2975
let CrateAnalysis { ty_cx : tcx, exp_map2, reachable, name, .. } = analysis;
@@ -3009,6 +3088,10 @@ pub fn trans_crate(krate: ast::Crate,
3009
3088
// referenced from rt/rust_try.ll
3010
3089
reachable. push ( "rust_eh_personality_catch" . to_string ( ) ) ;
3011
3090
3091
+ if codegen_units > 1 {
3092
+ internalize_symbols ( & shared_ccx, & reachable. iter ( ) . map ( |x| x. clone ( ) ) . collect ( ) ) ;
3093
+ }
3094
+
3012
3095
let metadata_module = ModuleTranslation {
3013
3096
llcx : shared_ccx. metadata_llcx ( ) ,
3014
3097
llmod : shared_ccx. metadata_llmod ( ) ,
0 commit comments