@@ -10,6 +10,7 @@ use rustc_span::symbol::Symbol;
1010use rustc_target:: spec:: { MergeFunctions , PanicStrategy } ;
1111use std:: ffi:: { CStr , CString } ;
1212
13+ use std:: ptr;
1314use std:: slice;
1415use std:: str;
1516use std:: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -192,15 +193,77 @@ pub fn print_passes() {
192193 }
193194}
194195
196+ fn llvm_target_features ( tm : & llvm:: TargetMachine ) -> Vec < ( & str , & str ) > {
197+ let len = unsafe { llvm:: LLVMRustGetTargetFeaturesCount ( tm) } ;
198+ let mut ret = Vec :: with_capacity ( len) ;
199+ for i in 0 ..len {
200+ unsafe {
201+ let mut feature = ptr:: null ( ) ;
202+ let mut desc = ptr:: null ( ) ;
203+ llvm:: LLVMRustGetTargetFeature ( tm, i, & mut feature, & mut desc) ;
204+ if feature. is_null ( ) || desc. is_null ( ) {
205+ bug ! ( "LLVM returned a `null` target feature string" ) ;
206+ }
207+ let feature = CStr :: from_ptr ( feature) . to_str ( ) . unwrap_or_else ( |e| {
208+ bug ! ( "LLVM returned a non-utf8 feature string: {}" , e) ;
209+ } ) ;
210+ let desc = CStr :: from_ptr ( desc) . to_str ( ) . unwrap_or_else ( |e| {
211+ bug ! ( "LLVM returned a non-utf8 feature string: {}" , e) ;
212+ } ) ;
213+ ret. push ( ( feature, desc) ) ;
214+ }
215+ }
216+ ret
217+ }
218+
219+ fn print_target_features ( sess : & Session , tm : & llvm:: TargetMachine ) {
220+ let mut target_features = llvm_target_features ( tm) ;
221+ let mut rustc_target_features = supported_target_features ( sess)
222+ . iter ( )
223+ . filter_map ( |( feature, _gate) | {
224+ let llvm_feature = to_llvm_feature ( sess, * feature) ;
225+ // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
226+ target_features. binary_search_by_key ( & llvm_feature, |( f, _d) | * f) . ok ( ) . map ( |index| {
227+ let ( _f, desc) = target_features. remove ( index) ;
228+ ( * feature, desc)
229+ } )
230+ } )
231+ . collect :: < Vec < _ > > ( ) ;
232+ rustc_target_features. extend_from_slice ( & [ (
233+ "crt-static" ,
234+ "Enables C Run-time Libraries to be statically linked" ,
235+ ) ] ) ;
236+ let max_feature_len = target_features
237+ . iter ( )
238+ . chain ( rustc_target_features. iter ( ) )
239+ . map ( |( feature, _desc) | feature. len ( ) )
240+ . max ( )
241+ . unwrap_or ( 0 ) ;
242+
243+ println ! ( "Features supported by rustc for this target:" ) ;
244+ for ( feature, desc) in & rustc_target_features {
245+ println ! ( " {1:0$} - {2}." , max_feature_len, feature, desc) ;
246+ }
247+ println ! ( "\n Code-generation features supported by LLVM for this target:" ) ;
248+ for ( feature, desc) in & target_features {
249+ println ! ( " {1:0$} - {2}." , max_feature_len, feature, desc) ;
250+ }
251+ if target_features. len ( ) == 0 {
252+ println ! ( " Target features listing is not supported by this LLVM version." ) ;
253+ }
254+ println ! ( "\n Use +feature to enable a feature, or -feature to disable it." ) ;
255+ println ! ( "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n " ) ;
256+ println ! ( "Code-generation features cannot be used in cfg or #[target_feature]," ) ;
257+ println ! ( "and may be renamed or removed in a future version of LLVM or rustc.\n " ) ;
258+ }
259+
195260pub ( crate ) fn print ( req : PrintRequest , sess : & Session ) {
196261 require_inited ( ) ;
197262 let tm = create_informational_target_machine ( sess) ;
198- unsafe {
199- match req {
200- PrintRequest :: TargetCPUs => llvm:: LLVMRustPrintTargetCPUs ( tm) ,
201- PrintRequest :: TargetFeatures => llvm:: LLVMRustPrintTargetFeatures ( tm) ,
202- _ => bug ! ( "rustc_codegen_llvm can't handle print request: {:?}" , req) ,
203- }
263+ match req {
264+ PrintRequest :: TargetCPUs => unsafe { llvm:: LLVMRustPrintTargetCPUs ( tm) } ,
265+ PrintRequest :: TargetFeatures => print_target_features ( sess, tm) ,
266+ _ => bug ! ( "rustc_codegen_llvm can't handle print request: {:?}" , req) ,
204267 }
205268}
206269
0 commit comments