@@ -166,25 +166,32 @@ pub fn time_trace_profiler_finish(file_name: &str) {
166166// Though note that Rust can also be build with an external precompiled version of LLVM
167167// which might lead to failures if the oldest tested / supported LLVM version
168168// doesn't yet support the relevant intrinsics
169- pub fn to_llvm_feature < ' a > ( sess : & Session , s : & ' a str ) -> & ' a str {
169+ pub fn to_llvm_feature < ' a > ( sess : & Session , s : & ' a str ) -> Vec < & ' a str > {
170170 let arch = if sess. target . arch == "x86_64" { "x86" } else { & * sess. target . arch } ;
171171 match ( arch, s) {
172- ( "x86" , "pclmulqdq" ) => "pclmul" ,
173- ( "x86" , "rdrand" ) => "rdrnd" ,
174- ( "x86" , "bmi1" ) => "bmi" ,
175- ( "x86" , "cmpxchg16b" ) => "cx16" ,
176- ( "x86" , "avx512vaes" ) => "vaes" ,
177- ( "x86" , "avx512gfni" ) => "gfni" ,
178- ( "x86" , "avx512vpclmulqdq" ) => "vpclmulqdq" ,
179- ( "aarch64" , "fp" ) => "fp-armv8" ,
180- ( "aarch64" , "fp16" ) => "fullfp16" ,
181- ( "aarch64" , "fhm" ) => "fp16fml" ,
182- ( "aarch64" , "rcpc2" ) => "rcpc-immo" ,
183- ( "aarch64" , "dpb" ) => "ccpp" ,
184- ( "aarch64" , "dpb2" ) => "ccdp" ,
185- ( "aarch64" , "frintts" ) => "fptoint" ,
186- ( "aarch64" , "fcma" ) => "complxnum" ,
187- ( _, s) => s,
172+ ( "x86" , "sse4.2" ) => {
173+ if get_version ( ) >= ( 14 , 0 , 0 ) {
174+ vec ! [ "sse4.2" , "crc32" ]
175+ } else {
176+ vec ! [ "sse4.2" ]
177+ }
178+ }
179+ ( "x86" , "pclmulqdq" ) => vec ! [ "pclmul" ] ,
180+ ( "x86" , "rdrand" ) => vec ! [ "rdrnd" ] ,
181+ ( "x86" , "bmi1" ) => vec ! [ "bmi" ] ,
182+ ( "x86" , "cmpxchg16b" ) => vec ! [ "cx16" ] ,
183+ ( "x86" , "avx512vaes" ) => vec ! [ "vaes" ] ,
184+ ( "x86" , "avx512gfni" ) => vec ! [ "gfni" ] ,
185+ ( "x86" , "avx512vpclmulqdq" ) => vec ! [ "vpclmulqdq" ] ,
186+ ( "aarch64" , "fp" ) => vec ! [ "fp-armv8" ] ,
187+ ( "aarch64" , "fp16" ) => vec ! [ "fullfp16" ] ,
188+ ( "aarch64" , "fhm" ) => vec ! [ "fp16fml" ] ,
189+ ( "aarch64" , "rcpc2" ) => vec ! [ "rcpc-immo" ] ,
190+ ( "aarch64" , "dpb" ) => vec ! [ "ccpp" ] ,
191+ ( "aarch64" , "dpb2" ) => vec ! [ "ccdp" ] ,
192+ ( "aarch64" , "frintts" ) => vec ! [ "fptoint" ] ,
193+ ( "aarch64" , "fcma" ) => vec ! [ "complxnum" ] ,
194+ ( _, s) => vec ! [ s] ,
188195 }
189196}
190197
@@ -198,9 +205,13 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
198205 } ,
199206 )
200207 . filter ( |feature| {
201- let llvm_feature = to_llvm_feature ( sess, feature) ;
202- let cstr = CString :: new ( llvm_feature) . unwrap ( ) ;
203- unsafe { llvm:: LLVMRustHasFeature ( target_machine, cstr. as_ptr ( ) ) }
208+ for llvm_feature in to_llvm_feature ( sess, feature) {
209+ let cstr = CString :: new ( llvm_feature) . unwrap ( ) ;
210+ if unsafe { llvm:: LLVMRustHasFeature ( target_machine, cstr. as_ptr ( ) ) } {
211+ return true ;
212+ }
213+ }
214+ false
204215 } )
205216 . map ( |feature| Symbol :: intern ( feature) )
206217 . collect ( )
@@ -253,12 +264,19 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
253264 let mut rustc_target_features = supported_target_features ( sess)
254265 . iter ( )
255266 . filter_map ( |( feature, _gate) | {
256- let llvm_feature = to_llvm_feature ( sess, * feature) ;
257- // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
258- target_features. binary_search_by_key ( & llvm_feature, |( f, _d) | * f) . ok ( ) . map ( |index| {
259- let ( _f, desc) = target_features. remove ( index) ;
260- ( * feature, desc)
261- } )
267+ for llvm_feature in to_llvm_feature ( sess, * feature) {
268+ // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
269+ match target_features. binary_search_by_key ( & llvm_feature, |( f, _d) | ( * f) ) . ok ( ) . map (
270+ |index| {
271+ let ( _f, desc) = target_features. remove ( index) ;
272+ ( * feature, desc)
273+ } ,
274+ ) {
275+ Some ( v) => return Some ( v) ,
276+ None => { }
277+ }
278+ }
279+ None
262280 } )
263281 . collect :: < Vec < _ > > ( ) ;
264282 rustc_target_features. extend_from_slice ( & [ (
@@ -373,30 +391,30 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
373391
374392 let filter = |s : & str | {
375393 if s. is_empty ( ) {
376- return None ;
394+ return vec ! [ ] ;
377395 }
378396 let feature = if s. starts_with ( '+' ) || s. starts_with ( '-' ) {
379397 & s[ 1 ..]
380398 } else {
381- return Some ( s. to_string ( ) ) ;
399+ return vec ! [ s. to_string( ) ] ;
382400 } ;
383401 // Rustc-specific feature requests like `+crt-static` or `-crt-static`
384402 // are not passed down to LLVM.
385403 if RUSTC_SPECIFIC_FEATURES . contains ( & feature) {
386- return None ;
404+ return vec ! [ ] ;
387405 }
388406 // ... otherwise though we run through `to_llvm_feature` feature when
389407 // passing requests down to LLVM. This means that all in-language
390408 // features also work on the command line instead of having two
391409 // different names when the LLVM name and the Rust name differ.
392- Some ( format ! ( "{}{}" , & s[ ..1 ] , to_llvm_feature ( sess , feature ) ) )
410+ to_llvm_feature ( sess , feature ) . iter ( ) . map ( |f| format ! ( "{}{}" , & s[ ..1 ] , f ) ) . collect ( )
393411 } ;
394412
395413 // Features implied by an implicit or explicit `--target`.
396- features. extend ( sess. target . features . split ( ',' ) . filter_map ( & filter) ) ;
414+ features. extend ( sess. target . features . split ( ',' ) . flat_map ( & filter) ) ;
397415
398416 // -Ctarget-features
399- features. extend ( sess. opts . cg . target_feature . split ( ',' ) . filter_map ( & filter) ) ;
417+ features. extend ( sess. opts . cg . target_feature . split ( ',' ) . flat_map ( & filter) ) ;
400418
401419 features
402420}
0 commit comments