rustc_codegen_llvm/back/
owned_target_machine.rs

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