@@ -5,7 +5,7 @@ use rustc_errors::struct_span_err;
55use rustc_hir as hir;
66use rustc_hir:: def:: DefKind ;
77use rustc_middle:: ty:: { List , ParamEnv , ParamEnvAnd , Ty , TyCtxt } ;
8- use rustc_session:: cstore:: { DllCallingConvention , DllImport , NativeLib } ;
8+ use rustc_session:: cstore:: { DllCallingConvention , DllImport , NativeLib , PeImportNameType } ;
99use rustc_session:: parse:: feature_err;
1010use rustc_session:: utils:: NativeLibKind ;
1111use rustc_session:: Session ;
@@ -61,6 +61,7 @@ impl<'tcx> Collector<'tcx> {
6161 let mut modifiers = None ;
6262 let mut cfg = None ;
6363 let mut wasm_import_module = None ;
64+ let mut import_name_type = None ;
6465 for item in items. iter ( ) {
6566 match item. name_or_empty ( ) {
6667 sym:: name => {
@@ -199,9 +200,51 @@ impl<'tcx> Collector<'tcx> {
199200 } ;
200201 wasm_import_module = Some ( ( link_wasm_import_module, item. span ( ) ) ) ;
201202 }
203+ sym:: import_name_type => {
204+ if import_name_type. is_some ( ) {
205+ let msg = "multiple `import_name_type` arguments in a single `#[link]` attribute" ;
206+ sess. span_err ( item. span ( ) , msg) ;
207+ continue ;
208+ }
209+ let Some ( link_import_name_type) = item. value_str ( ) else {
210+ let msg = "import name type must be of the form `import_name_type = \" string\" `" ;
211+ sess. span_err ( item. span ( ) , msg) ;
212+ continue ;
213+ } ;
214+ if self . tcx . sess . target . arch != "x86" {
215+ let msg = "import name type is only supported on x86" ;
216+ sess. span_err ( item. span ( ) , msg) ;
217+ continue ;
218+ }
219+
220+ let link_import_name_type = match link_import_name_type. as_str ( ) {
221+ "decorated" => PeImportNameType :: Decorated ,
222+ "noprefix" => PeImportNameType :: NoPrefix ,
223+ "undecorated" => PeImportNameType :: Undecorated ,
224+ import_name_type => {
225+ let msg = format ! (
226+ "unknown import name type `{import_name_type}`, expected one of: \
227+ decorated, noprefix, undecorated"
228+ ) ;
229+ sess. span_err ( item. span ( ) , msg) ;
230+ continue ;
231+ }
232+ } ;
233+ if !features. raw_dylib {
234+ let span = item. name_value_literal_span ( ) . unwrap ( ) ;
235+ feature_err (
236+ & sess. parse_sess ,
237+ sym:: raw_dylib,
238+ span,
239+ "import name type is unstable" ,
240+ )
241+ . emit ( ) ;
242+ }
243+ import_name_type = Some ( ( link_import_name_type, item. span ( ) ) ) ;
244+ }
202245 _ => {
203246 let msg = "unexpected `#[link]` argument, expected one of: \
204- name, kind, modifiers, cfg, wasm_import_module";
247+ name, kind, modifiers, cfg, wasm_import_module, import_name_type ";
205248 sess. span_err ( item. span ( ) , msg) ;
206249 }
207250 }
@@ -315,6 +358,14 @@ impl<'tcx> Collector<'tcx> {
315358 . emit ( ) ;
316359 }
317360
361+ // Do this outside of the loop so that `import_name_type` can be specified before `kind`.
362+ if let Some ( ( _, span) ) = import_name_type {
363+ if kind != Some ( NativeLibKind :: RawDylib ) {
364+ let msg = "import name type can only be used with link kind `raw-dylib`" ;
365+ sess. span_err ( span, msg) ;
366+ }
367+ }
368+
318369 let dll_imports = match kind {
319370 Some ( NativeLibKind :: RawDylib ) => {
320371 if let Some ( ( name, span) ) = name && name. as_str ( ) . contains ( '\0' ) {
@@ -325,7 +376,13 @@ impl<'tcx> Collector<'tcx> {
325376 }
326377 foreign_mod_items
327378 . iter ( )
328- . map ( |child_item| self . build_dll_import ( abi, child_item) )
379+ . map ( |child_item| {
380+ self . build_dll_import (
381+ abi,
382+ import_name_type. map ( |( import_name_type, _) | import_name_type) ,
383+ child_item,
384+ )
385+ } )
329386 . collect ( )
330387 }
331388 _ => {
@@ -486,7 +543,12 @@ impl<'tcx> Collector<'tcx> {
486543 . sum ( )
487544 }
488545
489- fn build_dll_import ( & self , abi : Abi , item : & hir:: ForeignItemRef ) -> DllImport {
546+ fn build_dll_import (
547+ & self ,
548+ abi : Abi ,
549+ import_name_type : Option < PeImportNameType > ,
550+ item : & hir:: ForeignItemRef ,
551+ ) -> DllImport {
490552 let calling_convention = if self . tcx . sess . target . arch == "x86" {
491553 match abi {
492554 Abi :: C { .. } | Abi :: Cdecl { .. } => DllCallingConvention :: C ,
@@ -518,11 +580,18 @@ impl<'tcx> Collector<'tcx> {
518580 }
519581 } ;
520582
583+ let import_name_type = self
584+ . tcx
585+ . codegen_fn_attrs ( item. id . def_id )
586+ . link_ordinal
587+ . map_or ( import_name_type, |ord| Some ( PeImportNameType :: Ordinal ( ord) ) ) ;
588+
521589 DllImport {
522590 name : item. ident . name ,
523- ordinal : self . tcx . codegen_fn_attrs ( item . id . def_id ) . link_ordinal ,
591+ import_name_type ,
524592 calling_convention,
525593 span : item. span ,
594+ is_fn : self . tcx . def_kind ( item. id . def_id ) . is_fn_like ( ) ,
526595 }
527596 }
528597}
0 commit comments