1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::{ffi, ptr};

use llvm_sys::core::*;
use llvm_sys::target_machine::*;

enum TripleString {
    Cross(ffi::CString),
    LlvmDefault(*mut libc::c_char),
}

impl TripleString {
    fn as_ptr(&self) -> *const libc::c_char {
        match self {
            TripleString::Cross(cross_triple) => cross_triple.as_ptr() as *const _,
            TripleString::LlvmDefault(llvm_default) => *llvm_default,
        }
    }
}

impl Drop for TripleString {
    fn drop(&mut self) {
        if let TripleString::LlvmDefault(llvm_default) = self {
            unsafe {
                LLVMDisposeMessage(*llvm_default);
            }
        }
    }
}

pub fn create_target_machine(
    cross_triple: Option<&str>,
    reloc_mode: LLVMRelocMode,
    code_model: LLVMCodeModel,
) -> LLVMTargetMachineRef {
    let cross_triple = cross_triple.map(|cross_triple| ffi::CString::new(cross_triple).unwrap());

    unsafe {
        let mut target: LLVMTargetRef = ptr::null_mut();

        let triple_string = cross_triple
            .map(|cross_triple| TripleString::Cross(ffi::CString::new(cross_triple).unwrap()))
            .unwrap_or_else(|| TripleString::LlvmDefault(LLVMGetDefaultTargetTriple()));

        let mut error: *mut libc::c_char = ptr::null_mut();
        if LLVMGetTargetFromTriple(triple_string.as_ptr(), &mut target, &mut error as *mut _) != 0 {
            panic!(
                "LLVMGetTargetFromTriple({:?}): {}",
                ffi::CStr::from_ptr(triple_string.as_ptr())
                    .to_str()
                    .unwrap(),
                ffi::CStr::from_ptr(error).to_str().unwrap()
            );
        }

        LLVMCreateTargetMachine(
            target,
            triple_string.as_ptr(),
            ptr::null(),
            ptr::null(),
            LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault,
            reloc_mode,
            code_model,
        )
    }
}