|
1 |
| -use std::ffi::{CStr, CString, c_char, c_void}; |
| 1 | +use std::collections::VecDeque; |
| 2 | +use std::ffi::{CStr, CString}; |
2 | 3 | use std::fmt::Write;
|
3 | 4 | use std::path::Path;
|
4 | 5 | use std::sync::Once;
|
@@ -387,7 +388,64 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> {
|
387 | 388 | ret
|
388 | 389 | }
|
389 | 390 |
|
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) { |
391 | 449 | let mut llvm_target_features = llvm_target_features(tm);
|
392 | 450 | let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
|
393 | 451 | let mut rustc_target_features = sess
|
@@ -447,35 +505,6 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
|
447 | 505 | writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n").unwrap();
|
448 | 506 | }
|
449 | 507 |
|
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 |
| - |
479 | 508 | /// Returns the host CPU name, according to LLVM.
|
480 | 509 | fn get_host_cpu_name() -> &'static str {
|
481 | 510 | let mut len = 0;
|
|
0 commit comments