Skip to content

Commit e258a5b

Browse files
committed
Categorize and explain target features support
1 parent 361bfce commit e258a5b

File tree

3 files changed

+91
-25
lines changed

3 files changed

+91
-25
lines changed

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -2128,7 +2128,13 @@ extern "C" {
21282128
pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
21292129

21302130
pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine);
2131-
pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine);
2131+
pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
2132+
pub fn LLVMRustGetTargetFeature(
2133+
T: &TargetMachine,
2134+
Index: size_t,
2135+
Feature: &mut *const c_char,
2136+
Desc: &mut *const c_char,
2137+
);
21322138

21332139
pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char;
21342140
pub fn LLVMRustCreateTargetMachine(

compiler/rustc_codegen_llvm/src/llvm_util.rs

+69-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_span::symbol::Symbol;
1010
use rustc_target::spec::{MergeFunctions, PanicStrategy};
1111
use std::ffi::{CStr, CString};
1212

13+
use std::ptr;
1314
use std::slice;
1415
use std::str;
1516
use 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!("\nCode-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!("\nUse +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+
195260
pub(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

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+15-18
Original file line numberDiff line numberDiff line change
@@ -404,26 +404,21 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
404404
printf("\n");
405405
}
406406

407-
extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
407+
extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
408408
const TargetMachine *Target = unwrap(TM);
409409
const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
410410
const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
411-
unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
412-
413-
printf("Available features for this target:\n");
414-
for (auto &Feature : FeatTable)
415-
printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
416-
printf("\nRust-specific features:\n");
417-
printf(" %-*s - %s.\n",
418-
MaxFeatLen,
419-
"crt-static",
420-
"Enables libraries with C Run-time Libraries(CRT) to be statically linked"
421-
);
422-
printf("\n");
411+
return FeatTable.size();
412+
}
423413

424-
printf("Use +feature to enable a feature, or -feature to disable it.\n"
425-
"For example, rustc -C -target-cpu=mycpu -C "
426-
"target-feature=+feature1,-feature2\n\n");
414+
extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
415+
const char** Feature, const char** Desc) {
416+
const TargetMachine *Target = unwrap(TM);
417+
const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
418+
const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
419+
const SubtargetFeatureKV Feat = FeatTable[Index];
420+
*Feature = Feat.Key;
421+
*Desc = Feat.Desc;
427422
}
428423

429424
#else
@@ -432,9 +427,11 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
432427
printf("Target CPU help is not supported by this LLVM version.\n\n");
433428
}
434429

435-
extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
436-
printf("Target features help is not supported by this LLVM version.\n\n");
430+
extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) {
431+
return 0;
437432
}
433+
434+
extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {}
438435
#endif
439436

440437
extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {

0 commit comments

Comments
 (0)