Skip to content

Commit dae9d6a

Browse files
committed
Auto merge of rust-lang#84004 - mattico:print-target-features-improvements, r=petrochenkov
Categorize and explain target features support There are 3 different uses of the `-C target-feature` args passed to rustc: 1. All of the features are passed to LLVM, which uses them to configure code-generation. This is sort-of stabilized since 1.0 though LLVM does change/add/remove target features regularly. 2. Target features which are in [the compiler's allowlist](https://github.com/rust-lang/rust/blob/69e1d22ddbc67b25141a735a22a8895a678b32ca/compiler/rustc_codegen_ssa/src/target_features.rs#L12-L34) can be used in `cfg!(target_feature)` etc. These may have different names than in LLVM and are renamed before passing them to LLVM. 3. Target features which are in the allowlist and which are stabilized or feature-gate-enabled can be used in `#[target_feature]`. It can be confusing that `rustc --print target-features` just prints out the LLVM features without separating out the rustc features or even mentioning that the dichotomy exists. This improves the situation by separating out the rustc and LLVM target features and adding a brief explanation about the difference. Abbreviated Example Output: ``` $ rustc --print target-features Features supported by rustc for this target: adx - Support ADX instructions. aes - Enable AES instructions. ... xsaves - Support xsaves instructions. crt-static - Enables libraries with C Run-time Libraries(CRT) to be statically linked. Code-generation features supported by LLVM for this target: 16bit-mode - 16-bit mode (i8086). 32bit-mode - 32-bit mode (80386). ... x87 - Enable X87 float instructions. xop - Enable XOP instructions. Use +feature to enable a feature, or -feature to disable it. For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2 Code-generation features cannot be used in cfg or #[target_feature], and may be renamed or removed in a future version of LLVM or rustc. ``` Motivated by rust-lang#83975. CC rust-lang#49653
2 parents 8513e78 + e258a5b commit dae9d6a

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)