diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index a637ae8184b4f..85cb7499cca4e 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -1,4 +1,7 @@ -codegen_llvm_autodiff_component_unavailable = failed to load our autodiff backend. Did you install it via rustup? +codegen_llvm_autodiff_component_missing = autodiff backend not found in the sysroot: {$err} + .note = it will be distributed via rustup in the future + +codegen_llvm_autodiff_component_unavailable = failed to load our autodiff backend: {$err} codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable codegen_llvm_autodiff_without_lto = using the autodiff feature requires setting `lto="fat"` in your Cargo.toml diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index c73140e041b60..bd42cf5569664 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -34,7 +34,16 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { #[derive(Diagnostic)] #[diag(codegen_llvm_autodiff_component_unavailable)] -pub(crate) struct AutoDiffComponentUnavailable; +pub(crate) struct AutoDiffComponentUnavailable { + pub err: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_autodiff_component_missing)] +#[note] +pub(crate) struct AutoDiffComponentMissing { + pub err: String, +} #[derive(Diagnostic)] #[diag(codegen_llvm_autodiff_without_lto)] diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 0952747449932..438a74e0a0912 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -249,8 +249,14 @@ impl CodegenBackend for LlvmCodegenBackend { use crate::back::lto::enable_autodiff_settings; if sess.opts.unstable_opts.autodiff.contains(&AutoDiff::Enable) { - if let Err(_) = llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot) { - sess.dcx().emit_fatal(crate::errors::AutoDiffComponentUnavailable); + match llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot) { + Ok(_) => {} + Err(llvm::EnzymeLibraryError::NotFound { err }) => { + sess.dcx().emit_fatal(crate::errors::AutoDiffComponentMissing { err }); + } + Err(llvm::EnzymeLibraryError::LoadFailed { err }) => { + sess.dcx().emit_fatal(crate::errors::AutoDiffComponentUnavailable { err }); + } } enable_autodiff_settings(&sess.opts.unstable_opts.autodiff); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index b11310b970d03..67fbc0f53adc9 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -153,7 +153,7 @@ pub(crate) mod Enzyme_AD { fn load_ptr_by_symbol_mut_void( lib: &libloading::Library, bytes: &[u8], - ) -> Result<*mut c_void, Box> { + ) -> Result<*mut c_void, libloading::Error> { unsafe { let s: libloading::Symbol<'_, *mut c_void> = lib.get(bytes)?; // libloading = 0.9.0: try_as_raw_ptr always succeeds and returns Some @@ -192,15 +192,27 @@ pub(crate) mod Enzyme_AD { static ENZYME_INSTANCE: OnceLock> = OnceLock::new(); + #[derive(Debug)] + pub(crate) enum EnzymeLibraryError { + NotFound { err: String }, + LoadFailed { err: String }, + } + + impl From for EnzymeLibraryError { + fn from(err: libloading::Error) -> Self { + Self::LoadFailed { err: format!("{err:?}") } + } + } + impl EnzymeWrapper { /// Initialize EnzymeWrapper with the given sysroot if not already initialized. /// Safe to call multiple times - subsequent calls are no-ops due to OnceLock. pub(crate) fn get_or_init( sysroot: &rustc_session::config::Sysroot, - ) -> Result, Box> { + ) -> Result, EnzymeLibraryError> { let mtx: &'static Mutex = ENZYME_INSTANCE.get_or_try_init(|| { let w = Self::call_dynamic(sysroot)?; - Ok::<_, Box>(Mutex::new(w)) + Ok::<_, EnzymeLibraryError>(Mutex::new(w)) })?; Ok(mtx.lock().unwrap()) @@ -351,7 +363,7 @@ pub(crate) mod Enzyme_AD { #[allow(non_snake_case)] fn call_dynamic( sysroot: &rustc_session::config::Sysroot, - ) -> Result> { + ) -> Result { let enzyme_path = Self::get_enzyme_path(sysroot)?; let lib = unsafe { libloading::Library::new(enzyme_path)? }; @@ -416,7 +428,7 @@ pub(crate) mod Enzyme_AD { }) } - fn get_enzyme_path(sysroot: &Sysroot) -> Result { + fn get_enzyme_path(sysroot: &Sysroot) -> Result { let llvm_version_major = unsafe { LLVMRustVersionMajor() }; let path_buf = sysroot @@ -434,15 +446,19 @@ pub(crate) mod Enzyme_AD { .map(|p| p.join("lib").display().to_string()) .collect::>() .join("\n* "); - format!( - "failed to find a `libEnzyme-{llvm_version_major}` folder \ + EnzymeLibraryError::NotFound { + err: format!( + "failed to find a `libEnzyme-{llvm_version_major}` folder \ in the sysroot candidates:\n* {candidates}" - ) + ), + } })?; Ok(path_buf .to_str() - .ok_or_else(|| format!("invalid UTF-8 in path: {}", path_buf.display()))? + .ok_or_else(|| EnzymeLibraryError::LoadFailed { + err: format!("invalid UTF-8 in path: {}", path_buf.display()), + })? .to_string()) } }