From 75d7c935f6cfb5540b58a6817f359897c3fca76f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 13 Sep 2026 13:50:23 +1000 Subject: [PATCH] Make the LLVM version-check bindings safe --- compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 10 +++++++--- .../rustc_codegen_llvm/src/llvm/offload_ffi.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm_util.rs | 14 ++++++-------- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index 68ec7870811d2..94df0fc270255 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -97,7 +97,7 @@ pub(crate) mod Enzyme_AD { use rustc_session::filesearch; use super::{CConcreteType, CTypeTreeRef, Context}; - use crate::llvm::{EnzymeTypeTree, LLVMRustVersionMajor}; + use crate::llvm::{self, EnzymeTypeTree}; type EnzymeSetCLBoolFn = unsafe extern "C" fn(*mut c_void, u8); type EnzymeSetCLStringFn = unsafe extern "C" fn(*mut c_void, *const c_char); @@ -434,7 +434,7 @@ pub(crate) mod Enzyme_AD { } fn get_enzyme_path(sysroot: &Sysroot) -> Result { - let llvm_version_major = unsafe { LLVMRustVersionMajor() }; + let llvm_version_major = llvm::LLVMRustVersionMajor(); let path_buf = sysroot .all_paths() diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index c20b4ccd776da..abacef3710f4e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -894,7 +894,11 @@ unsafe extern "C" { SLen: c_uint, ) -> MetadataKindId; - pub(crate) fn LLVMGetVersion(major: &mut c_uint, minor: &mut c_uint, patch: &mut c_uint); + /// Gets the actual version of LLVM that we are linked to at runtime. + /// + /// # Safety + /// Can be called without initializing LLVM. + pub(crate) safe fn LLVMGetVersion(major: &mut c_uint, minor: &mut c_uint, patch: &mut c_uint); pub(crate) fn LLVMDisposeTargetMachine(T: ptr::NonNull); @@ -2176,9 +2180,9 @@ unsafe extern "C" { /// Returns the LLVM major version that the compiler was built with. /// /// Note that this is hard-coded as `LLVM_VERSION_MAJOR` when `RustWrapper.cpp` is built. This - /// could be different than what the runtime LLVM library reports in `LLVMGetVersion`, so we + /// could be different than what the runtime LLVM library reports in [`LLVMGetVersion`], so we /// assert their equality in `configure_llvm`. - pub(crate) fn LLVMRustVersionMajor() -> u32; + pub(crate) safe fn LLVMRustVersionMajor() -> u32; /// Add LLVM module flags. /// diff --git a/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs index 7ecf450ab1dba..fecb9e40eab88 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs @@ -14,7 +14,7 @@ use rustc_fs_util::path_to_c_string; use rustc_session::config::host_tuple; use rustc_session::filesearch; -use crate::llvm::LLVMRustVersionMajor; +use crate::llvm; pub(crate) struct RustOffloadWrapper { LLVMRustBundleImages: LLVMRustBundleImagesFn, @@ -119,7 +119,7 @@ impl RustOffloadWrapper { fn get_offload_and_lld_paths( sysroot: &rustc_session::config::Sysroot, ) -> Result<(PathBuf, Option), RustOffloadLibraryError> { - let llvm_version_major = unsafe { LLVMRustVersionMajor() }; + let llvm_version_major = llvm::LLVMRustVersionMajor(); let mut searched = Vec::new(); for root in sysroot.all_paths() { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index a5441b1ef1135..223cbf2aae31f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -459,15 +459,13 @@ pub(crate) fn print_version() { println!("LLVM version: {major}.{minor}.{patch}"); } +/// Returns the version of LLVM that we are actually linked to at runtime. pub(crate) fn get_version() -> (u32, u32, u32) { - // Can be called without initializing LLVM - unsafe { - let mut llvm_major = 0; - let mut llvm_minor = 0; - let mut llvm_patch = 0; - llvm::LLVMGetVersion(&mut llvm_major, &mut llvm_minor, &mut llvm_patch); - (llvm_major, llvm_minor, llvm_patch) - } + let mut llvm_major = 0; + let mut llvm_minor = 0; + let mut llvm_patch = 0; + llvm::LLVMGetVersion(&mut llvm_major, &mut llvm_minor, &mut llvm_patch); + (llvm_major, llvm_minor, llvm_patch) } pub(crate) fn print_passes() {