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 ;
15
1
use rustc_span:: symbol:: sym;
16
2
use rustc_span:: symbol:: Symbol ;
17
- use rustc_span:: Span ;
18
3
19
4
/// Features that control behaviour of rustc, rather than the codegen.
20
5
pub const RUSTC_SPECIFIC_FEATURES : & [ & str ] = & [ "crt-static" ] ;
@@ -32,7 +17,7 @@ pub enum Stability {
32
17
use Stability :: * ;
33
18
34
19
impl Stability {
35
- fn as_feature_name ( self ) -> Option < Symbol > {
20
+ pub fn as_feature_name ( self ) -> Option < Symbol > {
36
21
match self {
37
22
Stable => None ,
38
23
Unstable ( s) => Some ( s) ,
@@ -417,7 +402,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> {
417
402
. cloned ( )
418
403
}
419
404
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 ) ] {
421
406
match & * sess. target . arch {
422
407
"arm" => ARM_ALLOWED_FEATURES ,
423
408
"aarch64" => AARCH64_ALLOWED_FEATURES ,
@@ -434,143 +419,9 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Sta
434
419
}
435
420
}
436
421
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 ] ] {
438
423
match & * sess. target . arch {
439
424
"aarch64" => AARCH64_TIED_FEATURES ,
440
425
_ => & [ ] ,
441
426
}
442
427
}
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