@@ -12,7 +12,7 @@ use rustc_middle::middle::exported_symbols::{
12
12
use rustc_middle:: ty:: query:: { ExternProviders , Providers } ;
13
13
use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
14
14
use rustc_middle:: ty:: Instance ;
15
- use rustc_middle:: ty:: { SymbolName , TyCtxt } ;
15
+ use rustc_middle:: ty:: { self , SymbolName , TyCtxt } ;
16
16
use rustc_session:: config:: CrateType ;
17
17
use rustc_target:: spec:: SanitizerSet ;
18
18
@@ -493,6 +493,76 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
493
493
}
494
494
}
495
495
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
+
496
566
fn wasm_import_module_map ( tcx : TyCtxt < ' _ > , cnum : CrateNum ) -> FxHashMap < DefId , String > {
497
567
// Build up a map from DefId to a `NativeLib` structure, where
498
568
// `NativeLib` internally contains information about
0 commit comments