@@ -12,12 +12,16 @@ const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
1212
1313#[ derive( Default ,  Debug ) ]  
1414struct  RevisionInfo < ' a >  { 
15-     target_arch :  Option < & ' a  str > , 
15+     target_arch :  Option < Option < & ' a  str > > , 
1616    llvm_components :  Option < Vec < & ' a  str > > , 
1717} 
1818
1919pub  fn  check ( tests_path :  & Path ,  bad :  & mut  bool )  { 
2020    crate :: walk:: walk ( tests_path,  |path,  _is_dir| filter_not_rust ( path) ,  & mut  |entry,  content| { 
21+         if  content. contains ( "// ignore-tidy-target-specific-tests" )  { 
22+             return ; 
23+         } 
24+ 
2125        let  file = entry. path ( ) . display ( ) ; 
2226        let  mut  header_map = BTreeMap :: new ( ) ; 
2327        iter_header ( content,  & mut  |HeaderLine  {  revision,  directive,  .. } | { 
@@ -33,10 +37,11 @@ pub fn check(tests_path: &Path, bad: &mut bool) {
3337            }  else  if  let  Some ( compile_flags)  = directive. strip_prefix ( COMPILE_FLAGS_HEADER )  { 
3438                if  let  Some ( ( _,  v) )  = compile_flags. split_once ( "--target" )  { 
3539                    let  v = v. trim_start_matches ( [ ' ' ,  '=' ] ) ; 
36-                     let  v = if  v == "{{target}}"  {  Some ( ( v,  v) )  }  else  {  v. split_once ( "-" )  } ; 
37-                     if  let  Some ( ( arch,  _) )  = v { 
38-                         let  info = header_map. entry ( revision) . or_insert ( RevisionInfo :: default ( ) ) ; 
39-                         info. target_arch . replace ( arch) ; 
40+                     let  info = header_map. entry ( revision) . or_insert ( RevisionInfo :: default ( ) ) ; 
41+                     if  v. starts_with ( "{{" )  { 
42+                         info. target_arch . replace ( None ) ; 
43+                     }  else  if  let  Some ( ( arch,  _) )  = v. split_once ( "-" )  { 
44+                         info. target_arch . replace ( Some ( arch) ) ; 
4045                    }  else  { 
4146                        eprintln ! ( "{file}: seems to have a malformed --target value" ) ; 
4247                        * bad = true ; 
@@ -54,9 +59,11 @@ pub fn check(tests_path: &Path, bad: &mut bool) {
5459            let  rev = rev. unwrap_or ( "[unspecified]" ) ; 
5560            match  ( target_arch,  llvm_components)  { 
5661                ( None ,  None )  => { } 
57-                 ( Some ( _) ,  None )  => { 
62+                 ( Some ( target_arch) ,  None )  => { 
63+                     let  llvm_component =
64+                         target_arch. map_or_else ( || "<arch>" . to_string ( ) ,  arch_to_llvm_component) ; 
5865                    eprintln ! ( 
59-                         "{file}: revision {rev} should specify `{LLVM_COMPONENTS_HEADER}` as it has `--target` set" 
66+                         "{file}: revision {rev} should specify `{LLVM_COMPONENTS_HEADER} {llvm_component} ` as it has `--target` set" 
6067                    ) ; 
6168                    * bad = true ; 
6269                } 
@@ -66,11 +73,45 @@ pub fn check(tests_path: &Path, bad: &mut bool) {
6673                    ) ; 
6774                    * bad = true ; 
6875                } 
69-                 ( Some ( _) ,  Some ( _) )  => { 
70-                     // FIXME: check specified components against the target architectures we 
71-                     // gathered. 
76+                 ( Some ( target_arch) ,  Some ( llvm_components) )  => { 
77+                     if  let  Some ( target_arch)  = target_arch { 
78+                         let  llvm_component = arch_to_llvm_component ( target_arch) ; 
79+                         if  !llvm_components. contains ( & llvm_component. as_str ( ) )  { 
80+                             eprintln ! ( 
81+                                 "{file}: revision {rev} should specify `{LLVM_COMPONENTS_HEADER} {llvm_component}` as it has `--target` set" 
82+                             ) ; 
83+                             * bad = true ; 
84+                         } 
85+                     } 
7286                } 
7387            } 
7488        } 
7589    } ) ; 
7690} 
91+ 
92+ fn  arch_to_llvm_component ( arch :  & str )  -> String  { 
93+     // NOTE: This is an *approximate* mapping of Rust's `--target` architecture to LLVM component 
94+     // names. It is not intended to be an authoritative source, but rather a best-effort that's good 
95+     // enough for the purpose of this tidy check. 
96+     match  arch { 
97+         "amdgcn"  => "amdgpu" . into ( ) , 
98+         "aarch64_be"  | "arm64_32"  | "arm64e"  | "arm64ec"  => "aarch64" . into ( ) , 
99+         "i386"  | "i586"  | "i686"  | "x86"  | "x86_64"  | "x86_64h"  => "x86" . into ( ) , 
100+         "loongarch32"  | "loongarch64"  => "loongarch" . into ( ) , 
101+         "nvptx64"  => "nvptx" . into ( ) , 
102+         "s390x"  => "systemz" . into ( ) , 
103+         "sparc64"  | "sparcv9"  => "sparc" . into ( ) , 
104+         "wasm32"  | "wasm32v1"  | "wasm64"  => "webassembly" . into ( ) , 
105+         _ if  arch. starts_with ( "armeb" ) 
106+             || arch. starts_with ( "armv" ) 
107+             || arch. starts_with ( "thumbv" )  =>
108+         { 
109+             "arm" . into ( ) 
110+         } 
111+         _ if  arch. starts_with ( "bpfe" )  => "bpf" . into ( ) , 
112+         _ if  arch. starts_with ( "mips" )  => "mips" . into ( ) , 
113+         _ if  arch. starts_with ( "powerpc" )  => "powerpc" . into ( ) , 
114+         _ if  arch. starts_with ( "riscv" )  => "riscv" . into ( ) , 
115+         _ => arch. to_ascii_lowercase ( ) , 
116+     } 
117+ } 
0 commit comments