@@ -12,7 +12,7 @@ use rustc_middle::middle::exported_symbols::{
1212use rustc_middle:: ty:: query:: { ExternProviders , Providers } ;
1313use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
1414use rustc_middle:: ty:: Instance ;
15- use rustc_middle:: ty:: { SymbolName , TyCtxt } ;
15+ use rustc_middle:: ty:: { self , SymbolName , TyCtxt } ;
1616use rustc_session:: config:: CrateType ;
1717use rustc_target:: spec:: SanitizerSet ;
1818
@@ -493,6 +493,76 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
493493 }
494494}
495495
496+ /// This is the symbol name of the given instance as seen by the linker.
497+ ///
498+ /// On 32-bit Windows symbols are decorated according to their calling conventions.
499+ pub fn linking_symbol_name_for_instance_in_crate < ' tcx > (
500+ tcx : TyCtxt < ' tcx > ,
501+ symbol : ExportedSymbol < ' tcx > ,
502+ instantiating_crate : CrateNum ,
503+ ) -> String {
504+ use rustc_target:: abi:: call:: Conv ;
505+
506+ let mut undecorated = symbol_name_for_instance_in_crate ( tcx, symbol, instantiating_crate) ;
507+
508+ let target = & tcx. sess . target ;
509+ if !target. is_like_windows {
510+ // Mach-O has a global "_" suffix and `object` crate will handle it.
511+ // ELF does not have any symbol decorations.
512+ return undecorated;
513+ }
514+
515+ let x86 = match & target. arch [ ..] {
516+ "x86" => true ,
517+ "x86_64" => false ,
518+ // Only x86/64 use symbol decorations.
519+ _ => return undecorated,
520+ } ;
521+
522+ let instance = match symbol {
523+ ExportedSymbol :: NonGeneric ( def_id) | ExportedSymbol :: Generic ( def_id, _)
524+ if tcx. is_static ( def_id) =>
525+ {
526+ None
527+ }
528+ ExportedSymbol :: NonGeneric ( def_id) => Some ( Instance :: mono ( tcx, def_id) ) ,
529+ ExportedSymbol :: Generic ( def_id, substs) => Some ( Instance :: new ( def_id, substs) ) ,
530+ // DropGlue always use the Rust calling convention and thus follow the target's default
531+ // symbol decoration scheme.
532+ ExportedSymbol :: DropGlue ( ..) => None ,
533+ // NoDefId always follow the target's default symbol decoration scheme.
534+ ExportedSymbol :: NoDefId ( ..) => None ,
535+ } ;
536+
537+ let ( conv, args) = instance
538+ . map ( |i| {
539+ tcx. fn_abi_of_instance ( ty:: ParamEnv :: reveal_all ( ) . and ( ( i, ty:: List :: empty ( ) ) ) )
540+ . unwrap_or_else ( |_| bug ! ( "fn_abi_of_instance({i:?}) failed" ) )
541+ } )
542+ . map ( |fnabi| ( fnabi. conv , & fnabi. args [ ..] ) )
543+ . unwrap_or ( ( Conv :: Rust , & [ ] ) ) ;
544+
545+ // Decorate symbols with prefices, suffices and total number of bytes of arguments.
546+ // Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170
547+ let ( prefix, suffix) = match conv {
548+ Conv :: X86Fastcall => ( "@" , "@" ) ,
549+ Conv :: X86Stdcall => ( "_" , "@" ) ,
550+ Conv :: X86VectorCall => ( "" , "@@" ) ,
551+ _ => {
552+ if x86 {
553+ undecorated. insert ( 0 , '_' ) ;
554+ }
555+ return undecorated;
556+ }
557+ } ;
558+
559+ let args_in_bytes: u64 = args
560+ . iter ( )
561+ . map ( |abi| abi. layout . size . bytes ( ) . next_multiple_of ( target. pointer_width as u64 / 8 ) )
562+ . sum ( ) ;
563+ format ! ( "{prefix}{undecorated}{suffix}{args_in_bytes}" )
564+ }
565+
496566fn wasm_import_module_map ( tcx : TyCtxt < ' _ > , cnum : CrateNum ) -> FxHashMap < DefId , String > {
497567 // Build up a map from DefId to a `NativeLib` structure, where
498568 // `NativeLib` internally contains information about
0 commit comments