| use std::ffi::CStr; | |
| use std::marker::PhantomData; | |
| use std::ptr::NonNull; | |
| use rustc_data_structures::small_c_str::SmallCStr; | |
| use crate::diagnostics::LlvmError; | |
| use crate::llvm; | |
| /// Responsible for safely creating and disposing llvm::TargetMachine via ffi functions. | |
| /// Not cloneable as there is no clone function for llvm::TargetMachine. | |
| #[repr(transparent)] | |
| pub struct OwnedTargetMachine { | |
| tm_unique: NonNull<llvm::TargetMachine>, | |
| phantom: PhantomData<llvm::TargetMachine>, | |
| } | |
| impl OwnedTargetMachine { | |
| pub(crate) fn new( | |
| triple: &CStr, | |
| cpu: &CStr, | |
| features: &CStr, | |
| abi: &CStr, | |
| model: llvm::CodeModel, | |
| reloc: llvm::RelocModel, | |
| level: llvm::CodeGenOptLevel, | |
| float_abi: llvm::FloatAbi, | |
| function_sections: bool, | |
| data_sections: bool, | |
| unique_section_names: bool, | |
| trap_unreachable: bool, | |
| singlethread: bool, | |
| verbose_asm: bool, | |
| emit_stack_size_section: bool, | |
| relax_elf_relocations: bool, | |
| use_init_array: bool, | |
| split_dwarf_file: &CStr, | |
| output_obj_file: &CStr, | |
| debug_info_compression: llvm::CompressionKind, | |
| use_emulated_tls: bool, | |
| use_wasm_eh: bool, | |
| large_data_threshold: u64, | |
| ) -> Result<Self, LlvmError<'static>> { | |
| // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data | |
| let tm_ptr = unsafe { | |
| llvm::LLVMRustCreateTargetMachine( | |
| triple.as_ptr(), | |
| cpu.as_ptr(), | |
| features.as_ptr(), | |
| abi.as_ptr(), | |
| model, | |
| reloc, | |
| level, | |
| float_abi, | |
| function_sections, | |
| data_sections, | |
| unique_section_names, | |
| trap_unreachable, | |
| singlethread, | |
| verbose_asm, | |
| emit_stack_size_section, | |
| relax_elf_relocations, | |
| use_init_array, | |
| split_dwarf_file.as_ptr(), | |
| output_obj_file.as_ptr(), | |
| debug_info_compression, | |
| use_emulated_tls, | |
| use_wasm_eh, | |
| large_data_threshold, | |
| ) | |
| }; | |
| NonNull::new(tm_ptr) | |
| .map(|tm_unique| Self { tm_unique, phantom: PhantomData }) | |
| .ok_or_else(|| LlvmError::CreateTargetMachine { triple: SmallCStr::from(triple) }) | |
| } | |
| /// Returns inner `llvm::TargetMachine` type. | |
| /// | |
| /// This could be a `Deref` implementation, but `llvm::TargetMachine` is an extern type and | |
| /// `Deref::Target: ?Sized`. | |
| pub fn raw(&self) -> &llvm::TargetMachine { | |
| // SAFETY: constructing ensures we have a valid pointer created by | |
| // llvm::LLVMRustCreateTargetMachine. | |
| unsafe { self.tm_unique.as_ref() } | |
| } | |
| } | |
| impl Drop for OwnedTargetMachine { | |
| fn drop(&mut self) { | |
| // SAFETY: constructing ensures we have a valid pointer created by | |
| // llvm::LLVMRustCreateTargetMachine OwnedTargetMachine is not copyable so there is no | |
| // double free or use after free. | |
| unsafe { llvm::LLVMDisposeTargetMachine(self.tm_unique) }; | |
| } | |
| } |