1- use crate :: errors;
2- use rustc_ast:: ast;
3- use rustc_attr:: InstructionSetAttr ;
4- use rustc_data_structures:: fx:: FxHashMap ;
5- use rustc_data_structures:: fx:: FxIndexSet ;
6- use rustc_errors:: Applicability ;
7- use rustc_hir:: def:: DefKind ;
8- use rustc_hir:: def_id:: DefId ;
9- use rustc_hir:: def_id:: LocalDefId ;
10- use rustc_hir:: def_id:: LOCAL_CRATE ;
11- use rustc_middle:: query:: Providers ;
12- use rustc_middle:: ty:: TyCtxt ;
13- use rustc_session:: parse:: feature_err;
14- use rustc_session:: Session ;
151use rustc_span:: symbol:: sym;
162use rustc_span:: symbol:: Symbol ;
17- use rustc_span:: Span ;
183
194/// Features that control behaviour of rustc, rather than the codegen.
205pub const RUSTC_SPECIFIC_FEATURES : & [ & str ] = & [ "crt-static" ] ;
@@ -32,7 +17,7 @@ pub enum Stability {
3217use Stability :: * ;
3318
3419impl Stability {
35- fn as_feature_name ( self ) -> Option < Symbol > {
20+ pub fn as_feature_name ( self ) -> Option < Symbol > {
3621 match self {
3722 Stable => None ,
3823 Unstable ( s) => Some ( s) ,
@@ -417,7 +402,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> {
417402 . cloned ( )
418403}
419404
420- pub fn supported_target_features ( sess : & Session ) -> & ' static [ ( & ' static str , Stability ) ] {
405+ pub fn supported_target_features ( sess : & crate :: Session ) -> & ' static [ ( & ' static str , Stability ) ] {
421406 match & * sess. target . arch {
422407 "arm" => ARM_ALLOWED_FEATURES ,
423408 "aarch64" => AARCH64_ALLOWED_FEATURES ,
@@ -434,143 +419,9 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Sta
434419 }
435420}
436421
437- pub fn tied_target_features ( sess : & Session ) -> & ' static [ & ' static [ & ' static str ] ] {
422+ pub fn tied_target_features ( sess : & crate :: Session ) -> & ' static [ & ' static [ & ' static str ] ] {
438423 match & * sess. target . arch {
439424 "aarch64" => AARCH64_TIED_FEATURES ,
440425 _ => & [ ] ,
441426 }
442427}
443-
444- pub fn from_target_feature (
445- tcx : TyCtxt < ' _ > ,
446- attr : & ast:: Attribute ,
447- supported_target_features : & FxHashMap < String , Option < Symbol > > ,
448- target_features : & mut Vec < Symbol > ,
449- ) {
450- let Some ( list) = attr. meta_item_list ( ) else { return } ;
451- let bad_item = |span| {
452- let msg = "malformed `target_feature` attribute input" ;
453- let code = "enable = \" ..\" " ;
454- tcx. sess
455- . struct_span_err ( span, msg)
456- . span_suggestion ( span, "must be of the form" , code, Applicability :: HasPlaceholders )
457- . emit ( ) ;
458- } ;
459- let rust_features = tcx. features ( ) ;
460- for item in list {
461- // Only `enable = ...` is accepted in the meta-item list.
462- if !item. has_name ( sym:: enable) {
463- bad_item ( item. span ( ) ) ;
464- continue ;
465- }
466-
467- // Must be of the form `enable = "..."` (a string).
468- let Some ( value) = item. value_str ( ) else {
469- bad_item ( item. span ( ) ) ;
470- continue ;
471- } ;
472-
473- // We allow comma separation to enable multiple features.
474- target_features. extend ( value. as_str ( ) . split ( ',' ) . filter_map ( |feature| {
475- let Some ( feature_gate) = supported_target_features. get ( feature) else {
476- let msg = format ! ( "the feature named `{feature}` is not valid for this target" ) ;
477- let mut err = tcx. sess . struct_span_err ( item. span ( ) , msg) ;
478- err. span_label ( item. span ( ) , format ! ( "`{feature}` is not valid for this target" ) ) ;
479- if let Some ( stripped) = feature. strip_prefix ( '+' ) {
480- let valid = supported_target_features. contains_key ( stripped) ;
481- if valid {
482- err. help ( "consider removing the leading `+` in the feature name" ) ;
483- }
484- }
485- err. emit ( ) ;
486- return None ;
487- } ;
488-
489- // Only allow features whose feature gates have been enabled.
490- let allowed = match feature_gate. as_ref ( ) . copied ( ) {
491- Some ( sym:: arm_target_feature) => rust_features. arm_target_feature ,
492- Some ( sym:: hexagon_target_feature) => rust_features. hexagon_target_feature ,
493- Some ( sym:: powerpc_target_feature) => rust_features. powerpc_target_feature ,
494- Some ( sym:: mips_target_feature) => rust_features. mips_target_feature ,
495- Some ( sym:: riscv_target_feature) => rust_features. riscv_target_feature ,
496- Some ( sym:: avx512_target_feature) => rust_features. avx512_target_feature ,
497- Some ( sym:: sse4a_target_feature) => rust_features. sse4a_target_feature ,
498- Some ( sym:: tbm_target_feature) => rust_features. tbm_target_feature ,
499- Some ( sym:: wasm_target_feature) => rust_features. wasm_target_feature ,
500- Some ( sym:: rtm_target_feature) => rust_features. rtm_target_feature ,
501- Some ( sym:: ermsb_target_feature) => rust_features. ermsb_target_feature ,
502- Some ( sym:: bpf_target_feature) => rust_features. bpf_target_feature ,
503- Some ( sym:: aarch64_ver_target_feature) => rust_features. aarch64_ver_target_feature ,
504- Some ( sym:: csky_target_feature) => rust_features. csky_target_feature ,
505- Some ( sym:: loongarch_target_feature) => rust_features. loongarch_target_feature ,
506- Some ( name) => bug ! ( "unknown target feature gate {}" , name) ,
507- None => true ,
508- } ;
509- if !allowed {
510- feature_err (
511- & tcx. sess . parse_sess ,
512- feature_gate. unwrap ( ) ,
513- item. span ( ) ,
514- format ! ( "the target feature `{feature}` is currently unstable" ) ,
515- )
516- . emit ( ) ;
517- }
518- Some ( Symbol :: intern ( feature) )
519- } ) ) ;
520- }
521- }
522-
523- /// Computes the set of target features used in a function for the purposes of
524- /// inline assembly.
525- fn asm_target_features ( tcx : TyCtxt < ' _ > , did : DefId ) -> & FxIndexSet < Symbol > {
526- let mut target_features = tcx. sess . unstable_target_features . clone ( ) ;
527- if tcx. def_kind ( did) . has_codegen_attrs ( ) {
528- let attrs = tcx. codegen_fn_attrs ( did) ;
529- target_features. extend ( & attrs. target_features ) ;
530- match attrs. instruction_set {
531- None => { }
532- Some ( InstructionSetAttr :: ArmA32 ) => {
533- target_features. remove ( & sym:: thumb_mode) ;
534- }
535- Some ( InstructionSetAttr :: ArmT32 ) => {
536- target_features. insert ( sym:: thumb_mode) ;
537- }
538- }
539- }
540-
541- tcx. arena . alloc ( target_features)
542- }
543-
544- /// Checks the function annotated with `#[target_feature]` is not a safe
545- /// trait method implementation, reporting an error if it is.
546- pub fn check_target_feature_trait_unsafe ( tcx : TyCtxt < ' _ > , id : LocalDefId , attr_span : Span ) {
547- if let DefKind :: AssocFn = tcx. def_kind ( id) {
548- let parent_id = tcx. local_parent ( id) ;
549- if let DefKind :: Trait | DefKind :: Impl { of_trait : true } = tcx. def_kind ( parent_id) {
550- tcx. sess . emit_err ( errors:: TargetFeatureSafeTrait {
551- span : attr_span,
552- def : tcx. def_span ( id) ,
553- } ) ;
554- }
555- }
556- }
557-
558- pub ( crate ) fn provide ( providers : & mut Providers ) {
559- * providers = Providers {
560- supported_target_features : |tcx, cnum| {
561- assert_eq ! ( cnum, LOCAL_CRATE ) ;
562- if tcx. sess . opts . actually_rustdoc {
563- // rustdoc needs to be able to document functions that use all the features, so
564- // whitelist them all
565- all_known_features ( ) . map ( |( a, b) | ( a. to_string ( ) , b. as_feature_name ( ) ) ) . collect ( )
566- } else {
567- supported_target_features ( tcx. sess )
568- . iter ( )
569- . map ( |& ( a, b) | ( a. to_string ( ) , b. as_feature_name ( ) ) )
570- . collect ( )
571- }
572- } ,
573- asm_target_features,
574- ..* providers
575- }
576- }
0 commit comments