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