use crate::back::write::create_informational_target_machine;
use crate::{llvm, llvm_util};
use libc::c_int;
+use libloading::Library;
use rustc_codegen_ssa::target_features::supported_target_features;
use rustc_data_structures::fx::FxHashSet;
-use rustc_metadata::dynamic_lib::DynamicLibrary;
+use rustc_fs_util::path_to_c_string;
use rustc_middle::bug;
use rustc_session::config::PrintRequest;
use rustc_session::Session;
use std::ptr;
use std::slice;
use std::str;
-use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;
-static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();
pub(crate) fn init(sess: &Session) {
unsafe {
// Before we touch LLVM, make sure that multithreading is enabled.
+ if llvm::LLVMIsMultithreaded() != 1 {
+ bug!("LLVM compiled without support for threads");
+ }
INIT.call_once(|| {
- if llvm::LLVMStartMultithreaded() != 1 {
- // use an extra bool to make sure that all future usage of LLVM
- // cannot proceed despite the Once not running more than once.
- POISONED.store(true, Ordering::SeqCst);
- }
-
configure_llvm(sess);
});
-
- if POISONED.load(Ordering::SeqCst) {
- bug!("couldn't enable multi-threaded LLVM");
- }
}
}
fn require_inited() {
- INIT.call_once(|| bug!("llvm is not initialized"));
- if POISONED.load(Ordering::SeqCst) {
- bug!("couldn't enable multi-threaded LLVM");
+ if !INIT.is_completed() {
+ bug!("LLVM is not initialized");
}
}
if sess.print_llvm_passes() {
add("-debug-pass=Structure", false);
}
- if !sess.opts.debugging_opts.no_generate_arange_section {
+ if sess.target.generate_arange_section
+ && !sess.opts.debugging_opts.no_generate_arange_section
+ {
add("-generate-arange-section", false);
}
// Ref:
// - https://github.com/rust-lang/rust/issues/85351
// - https://reviews.llvm.org/D103167
- let llvm_version = llvm_util::get_version();
- if llvm_version >= (11, 0, 0) && llvm_version < (13, 0, 0) {
+ if llvm_util::get_version() < (13, 0, 0) {
add("-enable-machine-outliner=never", false);
}
}
if sess.opts.debugging_opts.llvm_time_trace {
- // time-trace is not thread safe and running it in parallel will cause seg faults.
- if !sess.opts.debugging_opts.no_parallel_llvm {
- bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
- }
-
llvm::LLVMTimeTraceProfilerInitialize();
}
llvm::LLVMInitializePasses();
+ // Register LLVM plugins by loading them into the compiler process.
for plugin in &sess.opts.debugging_opts.llvm_plugins {
- let path = Path::new(plugin);
- let res = DynamicLibrary::open(path);
- match res {
- Ok(_) => debug!("LLVM plugin loaded succesfully {} ({})", path.display(), plugin),
- Err(e) => bug!("couldn't load plugin: {}", e),
- }
- mem::forget(res);
+ let lib = Library::new(plugin).unwrap_or_else(|e| bug!("couldn't load plugin: {}", e));
+ debug!("LLVM plugin loaded successfully {:?} ({})", lib, plugin);
+
+ // Intentionally leak the dynamic library. We can't ever unload it
+ // since the library can make things that will live arbitrarily long.
+ mem::forget(lib);
}
rustc_llvm::initialize_available_targets();
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
}
-pub fn time_trace_profiler_finish(file_name: &str) {
+pub fn time_trace_profiler_finish(file_name: &Path) {
unsafe {
- let file_name = CString::new(file_name).unwrap();
+ let file_name = path_to_c_string(file_name);
llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr());
}
}
("aarch64", "dpb2") => vec!["ccdp"],
("aarch64", "frintts") => vec!["fptoint"],
("aarch64", "fcma") => vec!["complxnum"],
+ ("aarch64", "pmuv3") => vec!["perfmon"],
(_, s) => vec![s],
}
}
// -Ctarget-features
features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
- // FIXME: Move outline-atomics to target definition when earliest supported LLVM is 12.
- if get_version() >= (12, 0, 0) && sess.target.llvm_target.contains("aarch64-unknown-linux") {
- features.push("+outline-atomics".to_string());
- }
-
features
}