Skip to content

Commit bdabbbe

Browse files
committed
Port most of LLVMRustPrintTargetCPUs to Rust
1 parent c642e39 commit bdabbbe

File tree

3 files changed

+67
-76
lines changed

3 files changed

+67
-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(T: &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

+58-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,62 @@ 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+
let target = &sess.target.llvm_target;
415+
format!(
416+
" - This is the default target CPU for the current build target (currently {target})."
417+
)
418+
} else {
419+
"".to_owned()
420+
}
421+
};
422+
let mut cpus = cpu_names
423+
.lines()
424+
.map(|cpu_name| Cpu { cpu_name, remark: make_remark(cpu_name) })
425+
.collect::<VecDeque<_>>();
426+
427+
// Only print the "native" entry when host and target are the same arch,
428+
// since otherwise it could be wrong or misleading.
429+
if sess.host.arch == sess.target.arch {
430+
let host = get_host_cpu_name();
431+
cpus.push_front(Cpu {
432+
cpu_name: "native",
433+
remark: format!(" - Select the CPU of the current host (currently {host})."),
434+
});
435+
}
436+
437+
let max_name_width = cpus.iter().map(|cpu| cpu.cpu_name.len()).max().unwrap_or(0);
438+
writeln!(out, "Available CPUs for this target:").unwrap();
439+
for Cpu { cpu_name, remark } in cpus {
440+
// Only pad the CPU name if there's a remark to print after it.
441+
let width = if remark.is_empty() { 0 } else { max_name_width };
442+
writeln!(out, " {cpu_name:<width$}{remark}").unwrap();
443+
}
444+
}
445+
446+
fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut String) {
391447
let mut llvm_target_features = llvm_target_features(tm);
392448
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
393449
let mut rustc_target_features = sess
@@ -447,35 +503,6 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
447503
writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n").unwrap();
448504
}
449505

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(resolve_native_cpu(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-
479506
#[track_caller]
480507
fn get_host_cpu_name() -> &'static str {
481508
let mut len = 0;

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

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

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

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

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

0 commit comments

Comments
 (0)