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