aya_rustc_llvm_proxy/
init.rs

1use super::SHARED_LIB;
2use llvm_sys::prelude::LLVMBool;
3
4use std::io::{BufRead, BufReader, Result};
5use std::process::Command;
6
7const POSSIBLE_BACKENDS: &[&str] = &[
8    "AArch64", "AMDGPU", "ARM", "BPF", "Hexagon", "Lanai", "Mips", "MSP430", "NVPTX", "PowerPC",
9    "Sparc", "SystemZ", "X86", "XCore",
10];
11
12fn get_native_arch() -> Result<String> {
13    let output = Command::new("rustc").args(["--print", "cfg"]).output()?;
14    let buf = BufReader::new(output.stdout.as_slice());
15    for line in buf.lines() {
16        let line = line?;
17        if !line.starts_with("target_arch") {
18            continue;
19        }
20        // line should be like: target_arch="x86_64"
21        return Ok(line.split('"').nth(1).unwrap().into());
22    }
23    unreachable!("`rustc --print cfg` result is wrong");
24}
25
26fn arch2backend(arch: &str) -> String {
27    match arch {
28        "aarch64" => "AArch64".into(),
29        "arm" => "ARM".into(),
30        "mips" | "mips64" => "Mips".into(),
31        "powerpc" | "powerpc64" => "PowerPC".into(),
32        "sparc" | "sparc64" => "Sparc".into(),
33        "x86" | "x86_64" => "X86".into(),
34        _ => panic!("Unknown backend: {}", arch),
35    }
36}
37
38fn get_native_backend() -> String {
39    let arch = get_native_arch().expect("Fail to get native arch");
40    arch2backend(&arch)
41}
42
43unsafe fn init_all(postfix: &str) {
44    for backend in POSSIBLE_BACKENDS {
45        let name = format!("LLVMInitialize{}{}", backend, postfix);
46        if let Ok(entrypoint) = SHARED_LIB.get::<unsafe extern "C" fn()>(name.as_bytes()) {
47            entrypoint();
48        }
49    }
50}
51
52#[no_mangle]
53pub unsafe extern "C" fn LLVM_InitializeAllTargetInfos() {
54    init_all("TargetInfo");
55}
56#[no_mangle]
57pub unsafe extern "C" fn LLVM_InitializeAllTargets() {
58    init_all("Target");
59}
60#[no_mangle]
61pub unsafe extern "C" fn LLVM_InitializeAllTargetMCs() {
62    init_all("TargetMC");
63}
64#[no_mangle]
65pub unsafe extern "C" fn LLVM_InitializeAllAsmParsers() {
66    init_all("AsmParser");
67}
68#[no_mangle]
69pub unsafe extern "C" fn LLVM_InitializeAllAsmPrinters() {
70    init_all("AsmPrinter");
71}
72
73unsafe fn init_native(postfix: &str) -> LLVMBool {
74    let backend = get_native_backend();
75    let name = format!("LLVMInitialize{}{}", backend, postfix);
76    if let Ok(entrypoint) = SHARED_LIB.get::<unsafe extern "C" fn()>(name.as_bytes()) {
77        entrypoint();
78        0
79    } else {
80        1
81    }
82}
83
84#[no_mangle]
85pub unsafe extern "C" fn LLVM_InitializeNativeTarget() -> LLVMBool {
86    init_native("Target")
87}
88#[no_mangle]
89pub unsafe extern "C" fn LLVM_InitializeNativeAsmParser() -> LLVMBool {
90    init_native("AsmParser")
91}
92#[no_mangle]
93pub unsafe extern "C" fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool {
94    init_native("AsmPrinter")
95}
96#[no_mangle]
97pub unsafe extern "C" fn LLVM_InitializeNativeDisassembler() -> LLVMBool {
98    init_native("Disassembler")
99}