Skip to main content

rustc_codegen_llvm/back/
owned_mc_subtarget_info.rs

1use std::ffi::CStr;
2use std::ptr::NonNull;
3
4use rustc_data_structures::small_c_str::SmallCStr;
5
6use crate::diagnostics::LlvmError;
7use crate::{llvm, llvm_util};
8
9/// Responsible for safely creating and disposing llvm::MCSubtargetInfo via ffi functions.
10/// Not cloneable as there is no clone function for llvm::MCSubtargetInfo.
11pub(crate) struct OwnedMCSubtargetInfo {
12    info_unique: NonNull<llvm::MCSubtargetInfo>,
13}
14
15impl OwnedMCSubtargetInfo {
16    pub(crate) fn new(
17        triple: &CStr,
18        cpu: &CStr,
19        features: &CStr,
20    ) -> Result<Self, LlvmError<'static>> {
21        // SAFETY: llvm::LLVMRustCreateMCSubtargetInfo copies pointed-to data.
22        let info_ptr = unsafe {
23            llvm::LLVMRustCreateMCSubtargetInfo(triple.as_ptr(), cpu.as_ptr(), features.as_ptr())
24        };
25
26        NonNull::new(info_ptr)
27            .map(|info_unique| Self { info_unique })
28            .ok_or_else(|| LlvmError::CreateMCSubtargetInfo { triple: SmallCStr::from(triple) })
29    }
30
31    pub(crate) fn has_features(&self, features: llvm_util::LLVMFeature<'_>) -> bool {
32        // Convert to a feature string expected by LLVM's `SubtargetFeatures`.
33        // All of the required LLVM features must be enabled.
34        // (The trailing comma is OK, as `SubtargetFeatures::Split` discards empty substrings.)
35        let features = features.into_iter().flat_map(|feat| ["+", feat, ","]).collect::<String>();
36
37        // SAFETY: `info_unique` is a valid pointer created by
38        // `llvm::LLVMRustCreateMCSubtargetInfo`.
39        unsafe {
40            llvm::LLVMRustMCSubtargetInfoCheckFeatures(
41                self.info_unique.as_ref(),
42                features.as_ptr(),
43                features.len(),
44            )
45        }
46    }
47}
48
49impl Drop for OwnedMCSubtargetInfo {
50    fn drop(&mut self) {
51        // SAFETY: `new` ensures we have a valid pointer created by
52        // `llvm::LLVMRustCreateMCSubtargetInfo` and `OwnedMCSubtargetInfo` is not copyable so
53        // there is no double free or use after free.
54        unsafe {
55            llvm::LLVMRustDisposeMCSubtargetInfo(self.info_unique);
56        }
57    }
58}