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;
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_feature(&self, feature: &CStr) -> bool {
32 // SAFETY: `new` ensures we have a valid pointer created by
33 // `llvm::LLVMRustCreateMCSubtargetInfo`.
34 unsafe {
35 llvm::LLVMRustMCSubtargetInfoHasFeature(self.info_unique.as_ref(), feature.as_ptr())
36 }
37 }
38}
39
40impl Drop for OwnedMCSubtargetInfo {
41 fn drop(&mut self) {
42 // SAFETY: `new` ensures we have a valid pointer created by
43 // `llvm::LLVMRustCreateMCSubtargetInfo` and `OwnedMCSubtargetInfo` is not copyable so
44 // there is no double free or use after free.
45 unsafe {
46 llvm::LLVMRustDisposeMCSubtargetInfo(self.info_unique);
47 }
48 }
49}