Skip to main content

rustc_codegen_llvm/back/
owned_target_machine.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::TargetMachine via ffi functions.
10/// Not cloneable as there is no clone function for llvm::TargetMachine.
11pub struct OwnedTargetMachine {
12    tm_unique: NonNull<llvm::TargetMachine>,
13}
14
15impl OwnedTargetMachine {
16    pub(crate) fn new(
17        triple: &CStr,
18        cpu: &CStr,
19        features: &CStr,
20        abi: &CStr,
21        model: llvm::CodeModel,
22        reloc: llvm::RelocModel,
23        level: llvm::CodeGenOptLevel,
24        float_abi: llvm::FloatAbi,
25        function_sections: bool,
26        data_sections: bool,
27        unique_section_names: bool,
28        trap_unreachable: bool,
29        singlethread: bool,
30        verbose_asm: bool,
31        emit_stack_size_section: bool,
32        relax_elf_relocations: bool,
33        use_init_array: bool,
34        split_dwarf_file: &CStr,
35        output_obj_file: &CStr,
36        debug_info_compression: llvm::CompressionKind,
37        use_emulated_tls: bool,
38        use_wasm_eh: bool,
39        large_data_threshold: u64,
40    ) -> Result<Self, LlvmError<'static>> {
41        // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed-to data.
42        let tm_ptr = unsafe {
43            llvm::LLVMRustCreateTargetMachine(
44                triple.as_ptr(),
45                cpu.as_ptr(),
46                features.as_ptr(),
47                abi.as_ptr(),
48                model,
49                reloc,
50                level,
51                float_abi,
52                function_sections,
53                data_sections,
54                unique_section_names,
55                trap_unreachable,
56                singlethread,
57                verbose_asm,
58                emit_stack_size_section,
59                relax_elf_relocations,
60                use_init_array,
61                split_dwarf_file.as_ptr(),
62                output_obj_file.as_ptr(),
63                debug_info_compression,
64                use_emulated_tls,
65                use_wasm_eh,
66                large_data_threshold,
67            )
68        };
69
70        NonNull::new(tm_ptr)
71            .map(|tm_unique| Self { tm_unique })
72            .ok_or_else(|| LlvmError::CreateTargetMachine { triple: SmallCStr::from(triple) })
73    }
74
75    /// Returns inner `llvm::TargetMachine` type.
76    ///
77    /// This could be a `Deref` implementation, but `llvm::TargetMachine` is an extern type and
78    /// `Deref::Target: ?Sized`.
79    pub fn raw(&self) -> &llvm::TargetMachine {
80        // SAFETY: constructing ensures we have a valid pointer created by
81        // llvm::LLVMRustCreateTargetMachine.
82        unsafe { self.tm_unique.as_ref() }
83    }
84}
85
86impl Drop for OwnedTargetMachine {
87    fn drop(&mut self) {
88        // SAFETY: constructing ensures we have a valid pointer created by
89        // llvm::LLVMRustCreateTargetMachine OwnedTargetMachine is not copyable so there is no
90        // double free or use after free.
91        unsafe { llvm::LLVMDisposeTargetMachine(self.tm_unique) };
92    }
93}