diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index e1dfc1b2dd6fa..3b857164a27e1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2281,7 +2281,12 @@ extern "C" { pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; - pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine, cpu: *const c_char); + pub fn LLVMRustPrintTargetCPUs( + T: &TargetMachine, + cpu: *const c_char, + print: unsafe extern "C" fn(out: *mut c_void, string: *const c_char, len: usize), + out: *mut c_void, + ); pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; pub fn LLVMRustGetTargetFeature( T: &TargetMachine, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 2fd0e444e2cb1..e2d087e3deab0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -17,8 +17,8 @@ use rustc_session::config::PrintRequest; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; -use std::ffi::{CStr, CString}; +use std::ffi::{c_char, c_void, CStr, CString}; use std::path::Path; use std::ptr; use std::slice; @@ -401,7 +401,7 @@ fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &ll writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n"); } -pub(crate) fn print(req: PrintRequest, out: &mut dyn PrintBackendInfo, sess: &Session) { +pub(crate) fn print(req: PrintRequest, mut out: &mut dyn PrintBackendInfo, sess: &Session) { require_inited(); let tm = create_informational_target_machine(sess); match req { @@ -411,7 +411,19 @@ pub(crate) fn print(req: PrintRequest, out: &mut dyn PrintBackendInfo, sess: &Se // at least as long as the C function let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref())) .unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e)); - unsafe { llvm::LLVMRustPrintTargetCPUs(tm, cpu_cstring.as_ptr()) }; + unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) { + let out = &mut *(out as *mut &mut dyn PrintBackendInfo); + let bytes = slice::from_raw_parts(string as *const u8, len); + write!(out, "{}", String::from_utf8_lossy(bytes)); + } + unsafe { + llvm::LLVMRustPrintTargetCPUs( + tm, + cpu_cstring.as_ptr(), + callback, + &mut out as *mut &mut dyn PrintBackendInfo as *mut c_void, + ); + } } PrintRequest::TargetFeatures => print_target_features(out, sess, tm), _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index eb3d67e720f2d..e5fb6b0953f5a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -306,44 +307,55 @@ static size_t getLongestEntryLength(ArrayRef Table) { return MaxLen; } -extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM, const char* TargetCPU) { +using PrintBackendInfo = void(void*, const char* Data, size_t Len); + +extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM, + const char* TargetCPU, + PrintBackendInfo Print, + void* Out) { const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); const Triple::ArchType HostArch = Triple(sys::getDefaultTargetTriple()).getArch(); const Triple::ArchType TargetArch = Target->getTargetTriple().getArch(); + std::ostringstream Buf; + #if LLVM_VERSION_GE(17, 0) const ArrayRef CPUTable = MCInfo->getAllProcessorDescriptions(); #elif defined(LLVM_RUSTLLVM) const ArrayRef CPUTable = MCInfo->getCPUTable(); #else - printf("Full target CPU help is not supported by this LLVM version.\n\n"); + Buf << "Full target CPU help is not supported by this LLVM version.\n\n"; SubtargetSubTypeKV TargetCPUKV = { TargetCPU, {{}}, {{}} }; const ArrayRef CPUTable = TargetCPUKV; #endif unsigned MaxCPULen = getLongestEntryLength(CPUTable); - printf("Available CPUs for this target:\n"); + Buf << "Available CPUs for this target:\n"; // Don't print the "native" entry when the user specifies --target with a // different arch since that could be wrong or misleading. if (HostArch == TargetArch) { MaxCPULen = std::max(MaxCPULen, (unsigned) std::strlen("native")); const StringRef HostCPU = sys::getHostCPUName(); - printf(" %-*s - Select the CPU of the current host (currently %.*s).\n", - MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data()); + Buf << " " << std::left << std::setw(MaxCPULen) << "native" + << " - Select the CPU of the current host " + "(currently " << HostCPU.str() << ").\n"; } for (auto &CPU : CPUTable) { // Compare cpu against current target to label the default if (strcmp(CPU.Key, TargetCPU) == 0) { - printf(" %-*s - This is the default target CPU" - " for the current build target (currently %s).", - MaxCPULen, CPU.Key, Target->getTargetTriple().str().c_str()); + Buf << " " << std::left << std::setw(MaxCPULen) << CPU.Key + << " - This is the default target CPU for the current build target " + "(currently " << Target->getTargetTriple().str() << ")."; } else { - printf(" %-*s", MaxCPULen, CPU.Key); + Buf << " " << CPU.Key; } - printf("\n"); + Buf << "\n"; } + + const auto &BufString = Buf.str(); + Print(Out, BufString.data(), BufString.size()); } extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {