1use std::collections::hash_map::Entry::*;
2
3use rustc_abi::{CanonAbi, X86Call};
4use rustc_ast::expand::allocator::{AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
5use rustc_data_structures::unord::UnordMap;
6use rustc_hir as hir;
7use rustc_hir::def::DefKind;
8use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
9use rustc_middle::bug;
10use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
11use rustc_middle::middle::exported_symbols::{
12 ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
13};
14use rustc_middle::query::LocalCrate;
15use rustc_middle::ty::{
16 self, GenericArgKind, GenericArgsRef, Instance, ShimKind, SymbolName, Ty, TyCtxt,
17};
18use rustc_middle::util::Providers;
19use rustc_session::config::CrateType;
20use rustc_session::cstore::CrateDepKind;
21use rustc_span::Span;
22use rustc_symbol_mangling::mangle_internal_symbol;
23use rustc_target::spec::{Arch, Os, TlsModel};
24use tracing::debug;
25
26use crate::SymbolExport;
27use crate::back::symbol_export;
28use crate::base::allocator_shim_contents;
29
30fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
31 crates_export_threshold(tcx.crate_types())
32}
33
34fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel {
35 match crate_type {
36 CrateType::Executable | CrateType::StaticLib | CrateType::ProcMacro | CrateType::Cdylib => {
37 SymbolExportLevel::C
38 }
39 CrateType::Rlib | CrateType::Dylib | CrateType::Sdylib => SymbolExportLevel::Rust,
40 }
41}
42
43pub fn crates_export_threshold(crate_types: &[CrateType]) -> SymbolExportLevel {
44 if crate_types
45 .iter()
46 .any(|&crate_type| crate_export_threshold(crate_type) == SymbolExportLevel::Rust)
47 {
48 SymbolExportLevel::Rust
49 } else {
50 SymbolExportLevel::C
51 }
52}
53
54fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<SymbolExportInfo> {
55 if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() {
56 return Default::default();
57 }
58
59 reachable_non_generics_helper(tcx)
60}
61
62pub fn reachable_non_generics_helper(tcx: TyCtxt<'_>) -> DefIdMap<SymbolExportInfo> {
64 let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);
65
66 let mut reachable_non_generics: DefIdMap<_> = tcx
67 .reachable_set(())
68 .items()
69 .filter_map(|&def_id| {
70 if let Some(parent_id) = tcx.opt_local_parent(def_id)
84 && let DefKind::ForeignMod = tcx.def_kind(parent_id)
85 {
86 let library = tcx.native_library(def_id)?;
87 return library.kind.is_statically_included().then_some(def_id);
88 }
89
90 match tcx.def_kind(def_id) {
92 DefKind::Fn | DefKind::AssocFn
93 if tcx.constness(def_id) == hir::Constness::Const { always: true } =>
94 {
95 return None;
96 }
97 DefKind::Fn | DefKind::Static { .. } => {}
98 DefKind::AssocFn if tcx.impl_of_assoc(def_id.to_def_id()).is_some() => {}
99 _ => return None,
100 };
101
102 let generics = tcx.generics_of(def_id);
103 if generics.requires_monomorphization(tcx) {
104 return None;
105 }
106
107 if Instance::mono(tcx, def_id.into()).def.requires_inline(tcx) {
108 return None;
109 }
110
111 if tcx.cross_crate_inlinable(def_id) { None } else { Some(def_id) }
112 })
113 .map(|def_id| {
114 let export_level = if is_compiler_builtins {
115 SymbolExportLevel::Rust
121 } else {
122 symbol_export_level(tcx, def_id.to_def_id())
123 };
124 let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_def_id());
125 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/symbol_export.rs:125",
"rustc_codegen_ssa::back::symbol_export",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/symbol_export.rs"),
::tracing_core::__macro_support::Option::Some(125u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::symbol_export"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("EXPORTED SYMBOL (local): {0} ({1:?})",
tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())),
export_level) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
126 "EXPORTED SYMBOL (local): {} ({:?})",
127 tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())),
128 export_level
129 );
130 let info = SymbolExportInfo {
131 level: export_level,
132 kind: if tcx.is_static(def_id.to_def_id()) {
133 if codegen_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
134 SymbolExportKind::Tls
135 } else {
136 SymbolExportKind::Data
137 }
138 } else {
139 SymbolExportKind::Text
140 },
141 used: codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
142 || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER),
143 rustc_std_internal_symbol: codegen_attrs
144 .flags
145 .contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
146 || codegen_attrs
147 .flags
148 .contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM),
149 };
150 (def_id.to_def_id(), info)
151 })
152 .into();
153
154 if let Some(id) = tcx.proc_macro_decls_static(()) {
155 reachable_non_generics.insert(
156 id.to_def_id(),
157 SymbolExportInfo {
158 level: SymbolExportLevel::C,
159 kind: SymbolExportKind::Data,
160 used: false,
161 rustc_std_internal_symbol: false,
162 },
163 );
164 }
165
166 reachable_non_generics
167}
168
169fn is_reachable_non_generic_provider_local(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
170 let export_threshold = threshold(tcx);
171
172 if let Some(&info) = tcx.reachable_non_generics(LOCAL_CRATE).get(&def_id.to_def_id()) {
173 info.level.is_below_threshold(export_threshold)
174 } else {
175 false
176 }
177}
178
179fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
180 tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
181}
182
183fn exported_non_generic_symbols_provider_local<'tcx>(
184 tcx: TyCtxt<'tcx>,
185 _: LocalCrate,
186) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
187 if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() {
188 return &[];
189 }
190
191 exported_non_generic_symbols_helper(tcx)
192}
193
194pub fn exported_non_generic_symbols_helper<'tcx>(
196 tcx: TyCtxt<'tcx>,
197) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
198 let sorted = tcx.with_stable_hashing_context(|mut hcx| {
201 tcx.reachable_non_generics(LOCAL_CRATE).to_sorted(&mut hcx, true)
202 });
203
204 let mut symbols: Vec<_> =
205 sorted.iter().map(|&(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info)).collect();
206
207 if !tcx.sess.target.dll_tls_export {
209 symbols.extend(sorted.iter().filter_map(|&(&def_id, &info)| {
210 tcx.needs_thread_local_shim(def_id).then(|| {
211 (
212 ExportedSymbol::ThreadLocalShim(def_id),
213 SymbolExportInfo {
214 level: info.level,
215 kind: SymbolExportKind::Text,
216 used: info.used,
217 rustc_std_internal_symbol: info.rustc_std_internal_symbol,
218 },
219 )
220 })
221 }))
222 }
223
224 symbols.extend(sorted.iter().flat_map(|&(&def_id, &info)| {
225 tcx.codegen_fn_attrs(def_id).foreign_item_symbol_aliases.iter().map(
226 move |&(foreign_item, _linkage, _visibility)| {
227 (ExportedSymbol::NonGeneric(foreign_item), info)
228 },
229 )
230 }));
231
232 if tcx.entry_fn(()).is_some() {
233 let exported_symbol =
234 ExportedSymbol::NoDefId(SymbolName::new(tcx, tcx.sess.target.entry_name.as_ref()));
235
236 symbols.push((
237 exported_symbol,
238 SymbolExportInfo {
239 level: SymbolExportLevel::C,
240 kind: SymbolExportKind::Text,
241 used: false,
242 rustc_std_internal_symbol: false,
243 },
244 ));
245 }
246
247 symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
249
250 tcx.arena.alloc_from_iter(symbols)
251}
252
253fn exported_generic_symbols_provider_local<'tcx>(
254 tcx: TyCtxt<'tcx>,
255 _: LocalCrate,
256) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
257 if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() {
258 return &[];
259 }
260
261 let mut symbols: Vec<_> = ::alloc::vec::Vec::new()vec![];
262
263 if tcx.local_crate_exports_generics() {
264 use rustc_hir::attrs::Linkage;
265 use rustc_middle::mono::{MonoItem, Visibility};
266 use rustc_middle::ty::InstanceKind;
267
268 let need_visibility = tcx.sess.target.dynamic_linking && !tcx.sess.target.only_cdylib;
274
275 let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
276
277 let reachable_set = tcx.reachable_set(());
279 let is_local_to_current_crate = |ty: Ty<'_>| {
280 let no_refs = ty.peel_refs();
281 let root_def_id = match no_refs.kind() {
282 ty::Closure(closure, _) => *closure,
283 ty::FnDef(def_id, _) => *def_id,
284 ty::Coroutine(def_id, _) => *def_id,
285 ty::CoroutineClosure(def_id, _) => *def_id,
286 ty::CoroutineWitness(def_id, _) => *def_id,
287 _ => return false,
288 };
289 let Some(root_def_id) = root_def_id.as_local() else {
290 return false;
291 };
292
293 let is_local = !reachable_set.contains(&root_def_id);
294 is_local
295 };
296
297 let is_instantiable_downstream =
298 |did: Option<DefId>, generic_args: GenericArgsRef<'tcx>| {
299 generic_args
300 .types()
301 .chain(did.into_iter().map(move |did| tcx.type_of(did).skip_binder()))
302 .all(move |arg| {
303 arg.walk().all(|ty| {
304 ty.as_type().map_or(true, |ty| !is_local_to_current_crate(ty))
305 })
306 })
307 };
308
309 #[allow(rustc::potential_query_instability)]
311 for (mono_item, data) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
312 if data.linkage != Linkage::External {
313 continue;
316 }
317
318 if need_visibility && data.visibility == Visibility::Hidden {
319 continue;
322 }
323
324 if !tcx.sess.opts.share_generics() {
325 if tcx.codegen_fn_attrs(mono_item.def_id()).inline
326 == rustc_hir::attrs::InlineAttr::Never
327 {
328 } else {
331 continue;
332 }
333 }
334
335 match *mono_item {
338 MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => {
339 let has_generics = args.non_erasable_generics().next().is_some();
340
341 let should_export =
342 has_generics && is_instantiable_downstream(Some(def), &args);
343
344 if should_export {
345 let symbol = ExportedSymbol::Generic(def, args);
346 symbols.push((
347 symbol,
348 SymbolExportInfo {
349 level: SymbolExportLevel::Rust,
350 kind: SymbolExportKind::Text,
351 used: false,
352 rustc_std_internal_symbol: false,
353 },
354 ));
355 }
356 }
357 MonoItem::Fn(Instance {
358 def: InstanceKind::Shim(ShimKind::DropGlue(_, Some(ty))),
359 args,
360 }) => {
361 {
match (&args.non_erasable_generics().next(),
&Some(GenericArgKind::Type(ty))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(args.non_erasable_generics().next(), Some(GenericArgKind::Type(ty)));
363
364 let should_export = match ty.kind() {
366 ty::Adt(_, args) => is_instantiable_downstream(None, args),
367 ty::Closure(_, args) => is_instantiable_downstream(None, args),
368 _ => true,
369 };
370
371 if should_export {
372 symbols.push((
373 ExportedSymbol::DropGlue(ty),
374 SymbolExportInfo {
375 level: SymbolExportLevel::Rust,
376 kind: SymbolExportKind::Text,
377 used: false,
378 rustc_std_internal_symbol: false,
379 },
380 ));
381 }
382 }
383 MonoItem::Fn(Instance {
384 def: InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(_, ty)),
385 args,
386 }) => {
387 {
match (&args.non_erasable_generics().next(),
&Some(GenericArgKind::Type(ty))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(args.non_erasable_generics().next(), Some(GenericArgKind::Type(ty)));
389 symbols.push((
390 ExportedSymbol::AsyncDropGlueCtorShim(ty),
391 SymbolExportInfo {
392 level: SymbolExportLevel::Rust,
393 kind: SymbolExportKind::Text,
394 used: false,
395 rustc_std_internal_symbol: false,
396 },
397 ));
398 }
399 MonoItem::Fn(Instance {
400 def: InstanceKind::Shim(ShimKind::AsyncDropGlue(def, ty)),
401 args: _,
402 }) => {
403 symbols.push((
404 ExportedSymbol::AsyncDropGlue(def, ty),
405 SymbolExportInfo {
406 level: SymbolExportLevel::Rust,
407 kind: SymbolExportKind::Text,
408 used: false,
409 rustc_std_internal_symbol: false,
410 },
411 ));
412 }
413 _ => {
414 }
416 }
417 }
418 }
419
420 symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
422
423 tcx.arena.alloc_from_iter(symbols)
424}
425
426fn upstream_monomorphizations_provider(
427 tcx: TyCtxt<'_>,
428 (): (),
429) -> DefIdMap<UnordMap<GenericArgsRef<'_>, CrateNum>> {
430 let cnums = tcx.crates(());
431
432 let mut instances: DefIdMap<UnordMap<_, _>> = Default::default();
433
434 let drop_glue_fn_def_id = tcx.lang_items().drop_glue_fn();
435 let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
436
437 for &cnum in cnums.iter() {
438 if tcx.crate_dep_kind(cnum) == CrateDepKind::Conditional {
443 continue;
444 }
445
446 for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() {
447 let (def_id, args) = match *exported_symbol {
448 ExportedSymbol::Generic(def_id, args) => (def_id, args),
449 ExportedSymbol::DropGlue(ty) => {
450 if let Some(drop_in_place_fn_def_id) = drop_glue_fn_def_id {
451 (drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
452 } else {
453 continue;
455 }
456 }
457 ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
458 if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id {
459 (async_drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
460 } else {
461 continue;
462 }
463 }
464 ExportedSymbol::AsyncDropGlue(def_id, ty) => (def_id, tcx.mk_args(&[ty.into()])),
465 ExportedSymbol::NonGeneric(..)
466 | ExportedSymbol::ThreadLocalShim(..)
467 | ExportedSymbol::NoDefId(..) => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("{0:?}", exported_symbol)));
}unreachable!("{exported_symbol:?}"),
468 };
469
470 let args_map = instances.entry(def_id).or_default();
471
472 match args_map.entry(args) {
473 Occupied(mut e) => {
474 let other_cnum = *e.get();
477 if tcx.stable_crate_id(other_cnum) > tcx.stable_crate_id(cnum) {
478 e.insert(cnum);
479 }
480 }
481 Vacant(e) => {
482 e.insert(cnum);
483 }
484 }
485 }
486 }
487
488 instances
489}
490
491fn upstream_monomorphizations_for_provider(
492 tcx: TyCtxt<'_>,
493 def_id: DefId,
494) -> Option<&UnordMap<GenericArgsRef<'_>, CrateNum>> {
495 if !!def_id.is_local() {
::core::panicking::panic("assertion failed: !def_id.is_local()")
};assert!(!def_id.is_local());
496 tcx.upstream_monomorphizations(()).get(&def_id)
497}
498
499fn upstream_drop_glue_for_provider<'tcx>(
500 tcx: TyCtxt<'tcx>,
501 args: GenericArgsRef<'tcx>,
502) -> Option<CrateNum> {
503 let def_id = tcx.lang_items().drop_glue_fn()?;
504 tcx.upstream_monomorphizations_for(def_id)?.get(&args).cloned()
505}
506
507fn upstream_async_drop_glue_for_provider<'tcx>(
508 tcx: TyCtxt<'tcx>,
509 args: GenericArgsRef<'tcx>,
510) -> Option<CrateNum> {
511 let def_id = tcx.lang_items().async_drop_in_place_fn()?;
512 tcx.upstream_monomorphizations_for(def_id)?.get(&args).cloned()
513}
514
515fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
516 !tcx.reachable_set(()).contains(&def_id)
517}
518
519pub(crate) fn provide(providers: &mut Providers) {
520 providers.queries.reachable_non_generics = reachable_non_generics_provider;
521 providers.queries.is_reachable_non_generic = is_reachable_non_generic_provider_local;
522 providers.queries.exported_non_generic_symbols = exported_non_generic_symbols_provider_local;
523 providers.queries.exported_generic_symbols = exported_generic_symbols_provider_local;
524 providers.queries.upstream_monomorphizations = upstream_monomorphizations_provider;
525 providers.queries.is_unreachable_local_definition = is_unreachable_local_definition_provider;
526 providers.queries.upstream_drop_glue_for = upstream_drop_glue_for_provider;
527 providers.queries.upstream_async_drop_glue_for = upstream_async_drop_glue_for_provider;
528 providers.queries.wasm_import_module_map = wasm_import_module_map;
529 providers.extern_queries.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
530 providers.extern_queries.upstream_monomorphizations_for =
531 upstream_monomorphizations_for_provider;
532}
533
534pub(crate) fn allocator_shim_symbols(
535 tcx: TyCtxt<'_>,
536 kind: AllocatorKind,
537) -> impl Iterator<Item = (String, SymbolExportKind)> {
538 allocator_shim_contents(tcx, kind)
539 .into_iter()
540 .map(move |method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
541 .chain([mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)])
542 .map(move |symbol_name| {
543 let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
544
545 (
546 symbol_export::exporting_symbol_name_for_instance_in_crate(
547 tcx,
548 exported_symbol,
549 LOCAL_CRATE,
550 ),
551 SymbolExportKind::Text,
552 )
553 })
554}
555
556fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel {
557 let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
563 let is_extern = codegen_fn_attrs.contains_extern_indicator();
564 let std_internal =
565 codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
566 let eii = codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM);
567
568 if is_extern && !std_internal && !eii {
569 let target = &tcx.sess.target.llvm_target;
570 if target.contains("emscripten") {
573 if let DefKind::Static { .. } = tcx.def_kind(sym_def_id) {
574 return SymbolExportLevel::Rust;
575 }
576 }
577
578 SymbolExportLevel::C
579 } else {
580 SymbolExportLevel::Rust
581 }
582}
583
584pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
586 tcx: TyCtxt<'tcx>,
587 symbol: ExportedSymbol<'tcx>,
588 instantiating_crate: CrateNum,
589) -> String {
590 if instantiating_crate == LOCAL_CRATE {
593 return symbol.symbol_name_for_local_instance(tcx).to_string();
594 }
595
596 match symbol {
599 ExportedSymbol::NonGeneric(def_id) => {
600 rustc_symbol_mangling::symbol_name_for_instance_in_crate(
601 tcx,
602 Instance::mono(tcx, def_id),
603 instantiating_crate,
604 )
605 }
606 ExportedSymbol::Generic(def_id, args) => {
607 rustc_symbol_mangling::symbol_name_for_instance_in_crate(
608 tcx,
609 Instance::new_raw(def_id, args),
610 instantiating_crate,
611 )
612 }
613 ExportedSymbol::ThreadLocalShim(def_id) => {
614 rustc_symbol_mangling::symbol_name_for_instance_in_crate(
615 tcx,
616 ty::Instance {
617 def: ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(def_id)),
618 args: ty::GenericArgs::empty(),
619 },
620 instantiating_crate,
621 )
622 }
623 ExportedSymbol::DropGlue(ty) => rustc_symbol_mangling::symbol_name_for_instance_in_crate(
624 tcx,
625 Instance::resolve_drop_glue(tcx, ty),
626 instantiating_crate,
627 ),
628 ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
629 rustc_symbol_mangling::symbol_name_for_instance_in_crate(
630 tcx,
631 Instance::resolve_async_drop_in_place(tcx, ty),
632 instantiating_crate,
633 )
634 }
635 ExportedSymbol::AsyncDropGlue(def_id, ty) => {
636 rustc_symbol_mangling::symbol_name_for_instance_in_crate(
637 tcx,
638 Instance::resolve_async_drop_in_place_poll(tcx, def_id, ty),
639 instantiating_crate,
640 )
641 }
642 ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(),
643 }
644}
645
646fn calling_convention_for_symbol<'tcx>(
647 tcx: TyCtxt<'tcx>,
648 symbol: ExportedSymbol<'tcx>,
649) -> (CanonAbi, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) {
650 let instance = match symbol {
651 ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _)
652 if tcx.is_static(def_id) =>
653 {
654 None
655 }
656 ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
657 ExportedSymbol::Generic(def_id, args) => Some(Instance::new_raw(def_id, args)),
658 ExportedSymbol::DropGlue(..) => None,
661 ExportedSymbol::AsyncDropGlueCtorShim(..) => None,
664 ExportedSymbol::AsyncDropGlue(..) => None,
665 ExportedSymbol::NoDefId(..) => None,
667 ExportedSymbol::ThreadLocalShim(..) => None,
669 };
670
671 instance
672 .map(|i| {
673 tcx.fn_abi_of_instance(
674 ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())),
675 )
676 .unwrap_or_else(|_| ::rustc_middle::util::bug::bug_fmt(format_args!("fn_abi_of_instance({0:?}) failed",
i))bug!("fn_abi_of_instance({i:?}) failed"))
677 })
678 .map(|fnabi| (fnabi.conv, &fnabi.args[..]))
679 .unwrap_or((CanonAbi::Rust, &[]))
681}
682
683pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
687 tcx: TyCtxt<'tcx>,
688 symbol: ExportedSymbol<'tcx>,
689 export_kind: SymbolExportKind,
690 instantiating_crate: CrateNum,
691) -> String {
692 let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
693
694 if let Some(name) = maybe_emutls_symbol_name(tcx, symbol, &undecorated) {
697 return name;
698 }
699
700 let target = &tcx.sess.target;
701 if !target.is_like_windows {
702 return undecorated;
705 }
706
707 let prefix = match target.arch {
708 Arch::X86 => Some('_'),
709 Arch::X86_64 => None,
710 Arch::Arm64EC if export_kind == SymbolExportKind::Text => Some('#'),
712 _ => return undecorated,
714 };
715
716 let (callconv, args) = calling_convention_for_symbol(tcx, symbol);
717
718 let (prefix, suffix) = match callconv {
721 CanonAbi::X86(X86Call::Fastcall) => ("@", "@"),
722 CanonAbi::X86(X86Call::Stdcall) => ("_", "@"),
723 CanonAbi::X86(X86Call::Vectorcall) => ("", "@@"),
724 _ => {
725 if let Some(prefix) = prefix {
726 undecorated.insert(0, prefix);
727 }
728 return undecorated;
729 }
730 };
731
732 let args_in_bytes: u64 = args
733 .iter()
734 .map(|abi| abi.layout.size.bytes().next_multiple_of(target.pointer_width as u64 / 8))
735 .sum();
736 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}{2}{3}", prefix, undecorated,
suffix, args_in_bytes))
})format!("{prefix}{undecorated}{suffix}{args_in_bytes}")
737}
738
739pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>(
740 tcx: TyCtxt<'tcx>,
741 symbol: ExportedSymbol<'tcx>,
742 cnum: CrateNum,
743) -> String {
744 let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, cnum);
745 maybe_emutls_symbol_name(tcx, symbol, &undecorated).unwrap_or(undecorated)
746}
747
748pub(crate) fn extend_exported_symbols<'tcx>(
752 symbols: &mut Vec<SymbolExport>,
753 tcx: TyCtxt<'tcx>,
754 symbol: ExportedSymbol<'tcx>,
755 instantiating_crate: CrateNum,
756) {
757 let (callconv, _) = calling_convention_for_symbol(tcx, symbol);
758
759 if callconv != CanonAbi::GpuKernel || tcx.sess.target.os != Os::AmdHsa {
760 return;
761 }
762
763 let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
764
765 symbols.push(SymbolExport::new(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}.kd", undecorated))
})format!("{undecorated}.kd"), SymbolExportKind::Data));
769}
770
771fn maybe_emutls_symbol_name<'tcx>(
772 tcx: TyCtxt<'tcx>,
773 symbol: ExportedSymbol<'tcx>,
774 undecorated: &str,
775) -> Option<String> {
776 if #[allow(non_exhaustive_omitted_patterns)] match tcx.sess.tls_model() {
TlsModel::Emulated => true,
_ => false,
}matches!(tcx.sess.tls_model(), TlsModel::Emulated)
777 && let ExportedSymbol::NonGeneric(def_id) = symbol
778 && tcx.is_thread_local_static(def_id)
779 {
780 Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__emutls_v.{0}", undecorated))
})format!("__emutls_v.{undecorated}"))
783 } else {
784 None
785 }
786}
787
788fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<String> {
789 let native_libs = tcx.native_libraries(cnum);
793
794 let def_id_to_native_lib = native_libs
795 .iter()
796 .filter_map(|lib| lib.foreign_module.map(|id| (id, lib)))
797 .collect::<DefIdMap<_>>();
798
799 let mut ret = DefIdMap::default();
800 for (def_id, lib) in tcx.foreign_modules(cnum).iter() {
801 let module = def_id_to_native_lib.get(def_id).and_then(|s| s.wasm_import_module());
802 let Some(module) = module else { continue };
803 ret.extend(lib.foreign_items.iter().map(|id| {
804 {
match (&id.krate, &cnum) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(id.krate, cnum);
805 (*id, module.to_string())
806 }));
807 }
808
809 ret
810}
811
812pub fn escape_symbol_name(tcx: TyCtxt<'_>, symbol: &str, span: Span) -> String {
813 use rustc_target::spec::{Arch, BinaryFormat};
815 if !symbol.is_empty()
816 && symbol.chars().all(|c| #[allow(non_exhaustive_omitted_patterns)] match c {
'0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.' => true,
_ => false,
}matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.'))
817 {
818 return symbol.to_string();
819 }
820 if tcx.sess.target.binary_format == BinaryFormat::Xcoff {
821 tcx.sess.dcx().span_fatal(
822 span,
823 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("symbol escaping is not supported for the binary format {0}",
tcx.sess.target.binary_format))
})format!(
824 "symbol escaping is not supported for the binary format {}",
825 tcx.sess.target.binary_format
826 ),
827 );
828 }
829 if tcx.sess.target.arch == Arch::Nvptx64 {
830 tcx.sess.dcx().span_fatal(
831 span,
832 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("symbol escaping is not supported for the architecture {0}",
tcx.sess.target.arch))
})format!(
833 "symbol escaping is not supported for the architecture {}",
834 tcx.sess.target.arch
835 ),
836 );
837 }
838 let mut escaped_symbol = String::new();
839 escaped_symbol.push('\"');
840 for c in symbol.chars() {
841 match c {
842 '\n' => escaped_symbol.push_str("\\\n"),
843 '"' => escaped_symbol.push_str("\\\""),
844 '\\' => escaped_symbol.push_str("\\\\"),
845 c => escaped_symbol.push(c),
846 }
847 }
848 escaped_symbol.push('\"');
849 escaped_symbol
850}