@@ -78,10 +78,9 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
7878 let reachable_non_generics = tcx
7979 . exported_symbols ( LOCAL_CRATE )
8080 . iter ( )
81- . filter_map ( |& ( exported_symbol, _ ) | {
81+ . filter_map ( |& ( exported_symbol, level ) | {
8282 if let ExportedSymbol :: NonGeneric ( def_id) = exported_symbol {
83- if tcx. symbol_export_level ( def_id)
84- . is_below_threshold ( export_threshold) {
83+ if level. is_below_threshold ( export_threshold) {
8584 return Some ( def_id)
8685 }
8786 }
@@ -110,6 +109,16 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
110109 return Arc :: new ( vec ! [ ] )
111110 }
112111
112+ // Check to see if this crate is a "special runtime crate". These
113+ // crates, implementation details of the standard library, typically
114+ // have a bunch of `pub extern` and `#[no_mangle]` functions as the
115+ // ABI between them. We don't want their symbols to have a `C`
116+ // export level, however, as they're just implementation details.
117+ // Down below we'll hardwire all of the symbols to the `Rust` export
118+ // level instead.
119+ let special_runtime_crate = tcx. is_panic_runtime ( LOCAL_CRATE ) ||
120+ tcx. is_compiler_builtins ( LOCAL_CRATE ) ;
121+
113122 let mut reachable_non_generics: DefIdSet = tcx. reachable_set ( LOCAL_CRATE ) . 0
114123 . iter ( )
115124 . filter_map ( |& node_id| {
@@ -176,7 +185,25 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
176185 let mut symbols: Vec < _ > = reachable_non_generics
177186 . iter ( )
178187 . map ( |& def_id| {
179- let export_level = tcx. symbol_export_level ( def_id) ;
188+ let export_level = if special_runtime_crate {
189+ let name = tcx. symbol_name ( Instance :: mono ( tcx, def_id) ) ;
190+ // We can probably do better here by just ensuring that
191+ // it has hidden visibility rather than public
192+ // visibility, as this is primarily here to ensure it's
193+ // not stripped during LTO.
194+ //
195+ // In general though we won't link right if these
196+ // symbols are stripped, and LTO currently strips them.
197+ if & * name == "rust_eh_personality" ||
198+ & * name == "rust_eh_register_frames" ||
199+ & * name == "rust_eh_unregister_frames" {
200+ SymbolExportLevel :: C
201+ } else {
202+ SymbolExportLevel :: Rust
203+ }
204+ } else {
205+ tcx. symbol_export_level ( def_id)
206+ } ;
180207 debug ! ( "EXPORTED SYMBOL (local): {} ({:?})" ,
181208 tcx. symbol_name( Instance :: mono( tcx, def_id) ) ,
182209 export_level) ;
@@ -222,70 +249,7 @@ pub fn provide(providers: &mut Providers) {
222249 providers. symbol_export_level = symbol_export_level_provider;
223250}
224251
225- fn exported_symbols_provider_extern < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
226- cnum : CrateNum )
227- -> Arc < Vec < ( ExportedSymbol ,
228- SymbolExportLevel ) > >
229- {
230- // If this crate is a plugin and/or a custom derive crate, then
231- // we're not even going to link those in so we skip those crates.
232- if tcx. plugin_registrar_fn ( cnum) . is_some ( ) ||
233- tcx. derive_registrar_fn ( cnum) . is_some ( ) {
234- return Arc :: new ( Vec :: new ( ) )
235- }
236-
237- // Check to see if this crate is a "special runtime crate". These
238- // crates, implementation details of the standard library, typically
239- // have a bunch of `pub extern` and `#[no_mangle]` functions as the
240- // ABI between them. We don't want their symbols to have a `C`
241- // export level, however, as they're just implementation details.
242- // Down below we'll hardwire all of the symbols to the `Rust` export
243- // level instead.
244- let special_runtime_crate =
245- tcx. is_panic_runtime ( cnum) || tcx. is_compiler_builtins ( cnum) ;
246-
247- let mut crate_exports: Vec < _ > = tcx
248- . reachable_non_generics ( cnum)
249- . iter ( )
250- . map ( |& def_id| {
251- let export_level = if special_runtime_crate {
252- let name = tcx. symbol_name ( Instance :: mono ( tcx, def_id) ) ;
253- // We can probably do better here by just ensuring that
254- // it has hidden visibility rather than public
255- // visibility, as this is primarily here to ensure it's
256- // not stripped during LTO.
257- //
258- // In general though we won't link right if these
259- // symbols are stripped, and LTO currently strips them.
260- if & * name == "rust_eh_personality" ||
261- & * name == "rust_eh_register_frames" ||
262- & * name == "rust_eh_unregister_frames" {
263- SymbolExportLevel :: C
264- } else {
265- SymbolExportLevel :: Rust
266- }
267- } else {
268- tcx. symbol_export_level ( def_id)
269- } ;
270-
271- debug ! ( "EXPORTED SYMBOL (re-export): {} ({:?})" ,
272- tcx. symbol_name( Instance :: mono( tcx, def_id) ) ,
273- export_level) ;
274-
275- ( ExportedSymbol :: NonGeneric ( def_id) , export_level)
276- } )
277- . collect ( ) ;
278-
279- // Sort so we get a stable incr. comp. hash.
280- crate_exports. sort_unstable_by ( |& ( ref symbol1, ..) , & ( ref symbol2, ..) | {
281- symbol1. compare_stable ( tcx, symbol2)
282- } ) ;
283-
284- Arc :: new ( crate_exports)
285- }
286-
287252pub fn provide_extern ( providers : & mut Providers ) {
288- providers. exported_symbols = exported_symbols_provider_extern;
289253 providers. is_reachable_non_generic = is_reachable_non_generic_provider;
290254 providers. symbol_export_level = symbol_export_level_provider;
291255}
0 commit comments