@@ -10,6 +10,7 @@ use rustc_span::symbol::Symbol;
10
10
use rustc_target:: spec:: { MergeFunctions , PanicStrategy } ;
11
11
use std:: ffi:: { CStr , CString } ;
12
12
13
+ use std:: ptr;
13
14
use std:: slice;
14
15
use std:: str;
15
16
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -192,15 +193,77 @@ pub fn print_passes() {
192
193
}
193
194
}
194
195
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
+
195
260
pub ( crate ) fn print ( req : PrintRequest , sess : & Session ) {
196
261
require_inited ( ) ;
197
262
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) ,
204
267
}
205
268
}
206
269
0 commit comments