@@ -2560,6 +2560,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
25602560 let whitelist = tcx. target_features_whitelist ( LOCAL_CRATE ) ;
25612561
25622562 let mut inline_span = None ;
2563+ let mut link_ordinal_span = None ;
25632564 for attr in attrs. iter ( ) {
25642565 if attr. check_name ( sym:: cold) {
25652566 codegen_fn_attrs. flags |= CodegenFnAttrFlags :: COLD ;
@@ -2641,6 +2642,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
26412642 }
26422643 } else if attr. check_name ( sym:: link_name) {
26432644 codegen_fn_attrs. link_name = attr. value_str ( ) ;
2645+ } else if attr. check_name ( sym:: link_ordinal) {
2646+ link_ordinal_span = Some ( attr. span ) ;
2647+ if let ordinal @ Some ( _) = check_link_ordinal ( tcx, attr) {
2648+ codegen_fn_attrs. link_ordinal = ordinal;
2649+ }
26442650 }
26452651 }
26462652
@@ -2718,6 +2724,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
27182724 // purpose functions as they wouldn't have the right target features
27192725 // enabled. For that reason we also forbid #[inline(always)] as it can't be
27202726 // respected.
2727+
27212728 if codegen_fn_attrs. target_features . len ( ) > 0 {
27222729 if codegen_fn_attrs. inline == InlineAttr :: Always {
27232730 if let Some ( span) = inline_span {
@@ -2742,6 +2749,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
27422749 codegen_fn_attrs. export_name = Some ( name) ;
27432750 codegen_fn_attrs. link_name = Some ( name) ;
27442751 }
2752+ check_link_name_xor_ordinal ( tcx, & codegen_fn_attrs, link_ordinal_span) ;
27452753
27462754 // Internal symbols to the standard library all have no_mangle semantics in
27472755 // that they have defined symbol names present in the function name. This
@@ -2752,3 +2760,48 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
27522760
27532761 codegen_fn_attrs
27542762}
2763+
2764+ fn check_link_ordinal ( tcx : TyCtxt < ' _ > , attr : & ast:: Attribute ) -> Option < usize > {
2765+ use syntax:: ast:: { Lit , LitIntType , LitKind } ;
2766+ let meta_item_list = attr. meta_item_list ( ) ;
2767+ let meta_item_list: Option < & [ ast:: NestedMetaItem ] > = meta_item_list. as_ref ( ) . map ( Vec :: as_ref) ;
2768+ let sole_meta_list = match meta_item_list {
2769+ Some ( [ item] ) => item. literal ( ) ,
2770+ _ => None ,
2771+ } ;
2772+ if let Some ( Lit { kind : LitKind :: Int ( ordinal, LitIntType :: Unsuffixed ) , .. } ) = sole_meta_list {
2773+ if * ordinal <= std:: usize:: MAX as u128 {
2774+ Some ( * ordinal as usize )
2775+ } else {
2776+ let msg = format ! (
2777+ "ordinal value in `link_ordinal` is too large: `{}`" ,
2778+ & ordinal
2779+ ) ;
2780+ tcx. sess . struct_span_err ( attr. span , & msg)
2781+ . note ( "the value may not exceed `std::usize::MAX`" )
2782+ . emit ( ) ;
2783+ None
2784+ }
2785+ } else {
2786+ tcx. sess . struct_span_err ( attr. span , "illegal ordinal format in `link_ordinal`" )
2787+ . note ( "an unsuffixed integer value, e.g., `1`, is expected" )
2788+ . emit ( ) ;
2789+ None
2790+ }
2791+ }
2792+
2793+ fn check_link_name_xor_ordinal (
2794+ tcx : TyCtxt < ' _ > ,
2795+ codegen_fn_attrs : & CodegenFnAttrs ,
2796+ inline_span : Option < Span > ,
2797+ ) {
2798+ if codegen_fn_attrs. link_name . is_none ( ) || codegen_fn_attrs. link_ordinal . is_none ( ) {
2799+ return ;
2800+ }
2801+ let msg = "cannot use `#[link_name]` with `#[link_ordinal]`" ;
2802+ if let Some ( span) = inline_span {
2803+ tcx. sess . span_err ( span, msg) ;
2804+ } else {
2805+ tcx. sess . err ( msg) ;
2806+ }
2807+ }
0 commit comments