Skip to content

Commit 64d4573

Browse files
committed
Port most of LLVMRustPrintTargetCPUs to Rust
1 parent 58387a0 commit 64d4573

File tree

3 files changed

+69
-76
lines changed

3 files changed

+69
-76
lines changed

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -2190,12 +2190,8 @@ unsafe extern "C" {
21902190

21912191
pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
21922192

2193-
pub fn LLVMRustPrintTargetCPUs(
2194-
T: &TargetMachine,
2195-
cpu: *const c_char,
2196-
print: unsafe extern "C" fn(out: *mut c_void, string: *const c_char, len: usize),
2197-
out: *mut c_void,
2198-
);
2193+
#[allow(improper_ctypes)]
2194+
pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString);
21992195
pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
22002196
pub fn LLVMRustGetTargetFeature(
22012197
T: &TargetMachine,

compiler/rustc_codegen_llvm/src/llvm_util.rs

+60-31
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::ffi::{CStr, CString, c_char, c_void};
1+
use std::collections::VecDeque;
2+
use std::ffi::{CStr, CString};
23
use std::fmt::Write;
34
use std::path::Path;
45
use std::sync::Once;
@@ -387,7 +388,64 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> {
387388
ret
388389
}
389390

390-
fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMachine) {
391+
pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) {
392+
require_inited();
393+
let tm = create_informational_target_machine(sess, false);
394+
match req.kind {
395+
PrintKind::TargetCPUs => print_target_cpus(sess, &tm, out),
396+
PrintKind::TargetFeatures => print_target_features(sess, &tm, out),
397+
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
398+
}
399+
}
400+
401+
fn print_target_cpus(sess: &Session, tm: &llvm::TargetMachine, out: &mut String) {
402+
let cpu_names = llvm::build_string(|s| unsafe {
403+
llvm::LLVMRustPrintTargetCPUs(&tm, s);
404+
})
405+
.unwrap();
406+
407+
struct Cpu<'a> {
408+
cpu_name: &'a str,
409+
remark: String,
410+
}
411+
// Compare CPU against current target to label the default.
412+
let make_remark = |cpu_name| {
413+
if cpu_name == sess.target.cpu {
414+
// FIXME(#132514): This prints the LLVM target string, which can be
415+
// different from the Rust target string. Is that intended?
416+
let target = &sess.target.llvm_target;
417+
format!(
418+
" - This is the default target CPU for the current build target (currently {target})."
419+
)
420+
} else {
421+
"".to_owned()
422+
}
423+
};
424+
let mut cpus = cpu_names
425+
.lines()
426+
.map(|cpu_name| Cpu { cpu_name, remark: make_remark(cpu_name) })
427+
.collect::<VecDeque<_>>();
428+
429+
// Only print the "native" entry when host and target are the same arch,
430+
// since otherwise it could be wrong or misleading.
431+
if sess.host.arch == sess.target.arch {
432+
let host = get_host_cpu_name();
433+
cpus.push_front(Cpu {
434+
cpu_name: "native",
435+
remark: format!(" - Select the CPU of the current host (currently {host})."),
436+
});
437+
}
438+
439+
let max_name_width = cpus.iter().map(|cpu| cpu.cpu_name.len()).max().unwrap_or(0);
440+
writeln!(out, "Available CPUs for this target:").unwrap();
441+
for Cpu { cpu_name, remark } in cpus {
442+
// Only pad the CPU name if there's a remark to print after it.
443+
let width = if remark.is_empty() { 0 } else { max_name_width };
444+
writeln!(out, " {cpu_name:<width$}{remark}").unwrap();
445+
}
446+
}
447+
448+
fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut String) {
391449
let mut llvm_target_features = llvm_target_features(tm);
392450
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
393451
let mut rustc_target_features = sess
@@ -447,35 +505,6 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
447505
writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n").unwrap();
448506
}
449507

450-
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
451-
require_inited();
452-
let tm = create_informational_target_machine(sess, false);
453-
match req.kind {
454-
PrintKind::TargetCPUs => {
455-
// SAFETY generate a C compatible string from a byte slice to pass
456-
// the target CPU name into LLVM, the lifetime of the reference is
457-
// at least as long as the C function
458-
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
459-
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
460-
unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) {
461-
let out = unsafe { &mut *(out as *mut &mut String) };
462-
let bytes = unsafe { slice::from_raw_parts(string as *const u8, len) };
463-
write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap();
464-
}
465-
unsafe {
466-
llvm::LLVMRustPrintTargetCPUs(
467-
&tm,
468-
cpu_cstring.as_ptr(),
469-
callback,
470-
(&raw mut out) as *mut c_void,
471-
);
472-
}
473-
}
474-
PrintKind::TargetFeatures => print_target_features(out, sess, &tm),
475-
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
476-
}
477-
}
478-
479508
/// Returns the host CPU name, according to LLVM.
480509
fn get_host_cpu_name() -> &'static str {
481510
let mut len = 0;

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+7-39
Original file line numberDiff line numberDiff line change
@@ -317,49 +317,17 @@ template <typename KV> static size_t getLongestEntryLength(ArrayRef<KV> Table) {
317317
return MaxLen;
318318
}
319319

320-
using PrintBackendInfo = void(void *, const char *Data, size_t Len);
321-
322320
extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM,
323-
const char *TargetCPU,
324-
PrintBackendInfo Print, void *Out) {
325-
const TargetMachine *Target = unwrap(TM);
326-
const Triple::ArchType HostArch =
327-
Triple(sys::getDefaultTargetTriple()).getArch();
328-
const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
321+
RustStringRef OutStr) {
322+
ArrayRef<SubtargetSubTypeKV> CPUTable =
323+
unwrap(TM)->getMCSubtargetInfo()->getAllProcessorDescriptions();
324+
auto OS = RawRustStringOstream(OutStr);
329325

330-
std::ostringstream Buf;
331-
332-
const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
333-
const ArrayRef<SubtargetSubTypeKV> CPUTable =
334-
MCInfo->getAllProcessorDescriptions();
335-
unsigned MaxCPULen = getLongestEntryLength(CPUTable);
336-
337-
Buf << "Available CPUs for this target:\n";
338-
// Don't print the "native" entry when the user specifies --target with a
339-
// different arch since that could be wrong or misleading.
340-
if (HostArch == TargetArch) {
341-
MaxCPULen = std::max(MaxCPULen, (unsigned)std::strlen("native"));
342-
const StringRef HostCPU = sys::getHostCPUName();
343-
Buf << " " << std::left << std::setw(MaxCPULen) << "native"
344-
<< " - Select the CPU of the current host "
345-
"(currently "
346-
<< HostCPU.str() << ").\n";
347-
}
326+
// Just print a bare list of target CPU names, and let Rust-side code handle
327+
// the full formatting of `--print=target-cpus`.
348328
for (auto &CPU : CPUTable) {
349-
// Compare cpu against current target to label the default
350-
if (strcmp(CPU.Key, TargetCPU) == 0) {
351-
Buf << " " << std::left << std::setw(MaxCPULen) << CPU.Key
352-
<< " - This is the default target CPU for the current build target "
353-
"(currently "
354-
<< Target->getTargetTriple().str() << ").";
355-
} else {
356-
Buf << " " << CPU.Key;
357-
}
358-
Buf << "\n";
329+
OS << CPU.Key << "\n";
359330
}
360-
361-
const auto &BufString = Buf.str();
362-
Print(Out, BufString.data(), BufString.size());
363331
}
364332

365333
extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {

0 commit comments

Comments
 (0)