rustc_llvm/
lib.rs

1// tidy-alphabetical-start
2#![allow(internal_features)]
3#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
4#![doc(rust_logo)]
5#![feature(extern_types)]
6#![feature(rustdoc_internals)]
7// tidy-alphabetical-end
8
9use std::cell::RefCell;
10use std::{ptr, slice};
11
12use libc::size_t;
13
14unsafe extern "C" {
15    /// Opaque type that allows C++ code to write bytes to a Rust-side buffer,
16    /// in conjunction with `RawRustStringOstream`. Use this as `&RustString`
17    /// (Rust) and `RustStringRef` (C++) in FFI signatures.
18    pub type RustString;
19}
20
21impl RustString {
22    pub fn build_byte_buffer(closure: impl FnOnce(&Self)) -> Vec<u8> {
23        let buf = RustStringInner::default();
24        closure(buf.as_opaque());
25        buf.into_inner()
26    }
27}
28
29/// Underlying implementation of [`RustString`].
30///
31/// Having two separate types makes it possible to use the opaque [`RustString`]
32/// in FFI signatures without `improper_ctypes` warnings. This is a workaround
33/// for the fact that there is no way to opt out of `improper_ctypes` when
34/// _declaring_ a type (as opposed to using that type).
35#[derive(Default)]
36struct RustStringInner {
37    bytes: RefCell<Vec<u8>>,
38}
39
40impl RustStringInner {
41    fn as_opaque(&self) -> &RustString {
42        let ptr: *const RustStringInner = ptr::from_ref(self);
43        // We can't use `ptr::cast` here because extern types are `!Sized`.
44        let ptr = ptr as *const RustString;
45        unsafe { &*ptr }
46    }
47
48    fn from_opaque(opaque: &RustString) -> &Self {
49        // SAFETY: A valid `&RustString` must have been created via `as_opaque`.
50        let ptr: *const RustString = ptr::from_ref(opaque);
51        let ptr: *const RustStringInner = ptr.cast();
52        unsafe { &*ptr }
53    }
54
55    fn into_inner(self) -> Vec<u8> {
56        self.bytes.into_inner()
57    }
58}
59
60/// Appends the contents of a byte slice to a [`RustString`].
61///
62/// This function is implemented in `rustc_llvm` so that the C++ code in this
63/// crate can link to it directly, without an implied link-time dependency on
64/// `rustc_codegen_llvm`.
65#[unsafe(no_mangle)]
66pub unsafe extern "C" fn LLVMRustStringWriteImpl(
67    buf: &RustString,
68    slice_ptr: *const u8, // Same ABI as `*const c_char`
69    slice_len: size_t,
70) {
71    let slice = unsafe { slice::from_raw_parts(slice_ptr, slice_len) };
72    RustStringInner::from_opaque(buf).bytes.borrow_mut().extend_from_slice(slice);
73}
74
75/// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`.
76/// N.B., this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s.
77pub fn initialize_available_targets() {
78    macro_rules! init_target(
79        ($cfg:meta, $($method:ident),*) => { {
80            #[cfg($cfg)]
81            fn init() {
82                unsafe extern "C" {
83                    $(fn $method();)*
84                }
85                unsafe {
86                    $($method();)*
87                }
88            }
89            #[cfg(not($cfg))]
90            fn init() { }
91            init();
92        } }
93    );
94    init_target!(
95        llvm_component = "x86",
96        LLVMInitializeX86TargetInfo,
97        LLVMInitializeX86Target,
98        LLVMInitializeX86TargetMC,
99        LLVMInitializeX86AsmPrinter,
100        LLVMInitializeX86AsmParser
101    );
102    init_target!(
103        llvm_component = "arm",
104        LLVMInitializeARMTargetInfo,
105        LLVMInitializeARMTarget,
106        LLVMInitializeARMTargetMC,
107        LLVMInitializeARMAsmPrinter,
108        LLVMInitializeARMAsmParser
109    );
110    init_target!(
111        llvm_component = "aarch64",
112        LLVMInitializeAArch64TargetInfo,
113        LLVMInitializeAArch64Target,
114        LLVMInitializeAArch64TargetMC,
115        LLVMInitializeAArch64AsmPrinter,
116        LLVMInitializeAArch64AsmParser
117    );
118    init_target!(
119        llvm_component = "amdgpu",
120        LLVMInitializeAMDGPUTargetInfo,
121        LLVMInitializeAMDGPUTarget,
122        LLVMInitializeAMDGPUTargetMC,
123        LLVMInitializeAMDGPUAsmPrinter,
124        LLVMInitializeAMDGPUAsmParser
125    );
126    init_target!(
127        llvm_component = "avr",
128        LLVMInitializeAVRTargetInfo,
129        LLVMInitializeAVRTarget,
130        LLVMInitializeAVRTargetMC,
131        LLVMInitializeAVRAsmPrinter,
132        LLVMInitializeAVRAsmParser
133    );
134    init_target!(
135        llvm_component = "m68k",
136        LLVMInitializeM68kTargetInfo,
137        LLVMInitializeM68kTarget,
138        LLVMInitializeM68kTargetMC,
139        LLVMInitializeM68kAsmPrinter,
140        LLVMInitializeM68kAsmParser
141    );
142    init_target!(
143        llvm_component = "csky",
144        LLVMInitializeCSKYTargetInfo,
145        LLVMInitializeCSKYTarget,
146        LLVMInitializeCSKYTargetMC,
147        LLVMInitializeCSKYAsmPrinter,
148        LLVMInitializeCSKYAsmParser
149    );
150    init_target!(
151        llvm_component = "loongarch",
152        LLVMInitializeLoongArchTargetInfo,
153        LLVMInitializeLoongArchTarget,
154        LLVMInitializeLoongArchTargetMC,
155        LLVMInitializeLoongArchAsmPrinter,
156        LLVMInitializeLoongArchAsmParser
157    );
158    init_target!(
159        llvm_component = "mips",
160        LLVMInitializeMipsTargetInfo,
161        LLVMInitializeMipsTarget,
162        LLVMInitializeMipsTargetMC,
163        LLVMInitializeMipsAsmPrinter,
164        LLVMInitializeMipsAsmParser
165    );
166    init_target!(
167        llvm_component = "powerpc",
168        LLVMInitializePowerPCTargetInfo,
169        LLVMInitializePowerPCTarget,
170        LLVMInitializePowerPCTargetMC,
171        LLVMInitializePowerPCAsmPrinter,
172        LLVMInitializePowerPCAsmParser
173    );
174    init_target!(
175        llvm_component = "systemz",
176        LLVMInitializeSystemZTargetInfo,
177        LLVMInitializeSystemZTarget,
178        LLVMInitializeSystemZTargetMC,
179        LLVMInitializeSystemZAsmPrinter,
180        LLVMInitializeSystemZAsmParser
181    );
182    init_target!(
183        llvm_component = "jsbackend",
184        LLVMInitializeJSBackendTargetInfo,
185        LLVMInitializeJSBackendTarget,
186        LLVMInitializeJSBackendTargetMC
187    );
188    init_target!(
189        llvm_component = "msp430",
190        LLVMInitializeMSP430TargetInfo,
191        LLVMInitializeMSP430Target,
192        LLVMInitializeMSP430TargetMC,
193        LLVMInitializeMSP430AsmPrinter,
194        LLVMInitializeMSP430AsmParser
195    );
196    init_target!(
197        llvm_component = "riscv",
198        LLVMInitializeRISCVTargetInfo,
199        LLVMInitializeRISCVTarget,
200        LLVMInitializeRISCVTargetMC,
201        LLVMInitializeRISCVAsmPrinter,
202        LLVMInitializeRISCVAsmParser
203    );
204    init_target!(
205        llvm_component = "sparc",
206        LLVMInitializeSparcTargetInfo,
207        LLVMInitializeSparcTarget,
208        LLVMInitializeSparcTargetMC,
209        LLVMInitializeSparcAsmPrinter,
210        LLVMInitializeSparcAsmParser
211    );
212    init_target!(
213        llvm_component = "nvptx",
214        LLVMInitializeNVPTXTargetInfo,
215        LLVMInitializeNVPTXTarget,
216        LLVMInitializeNVPTXTargetMC,
217        LLVMInitializeNVPTXAsmPrinter
218    );
219    init_target!(
220        llvm_component = "hexagon",
221        LLVMInitializeHexagonTargetInfo,
222        LLVMInitializeHexagonTarget,
223        LLVMInitializeHexagonTargetMC,
224        LLVMInitializeHexagonAsmPrinter,
225        LLVMInitializeHexagonAsmParser
226    );
227    init_target!(
228        llvm_component = "xtensa",
229        LLVMInitializeXtensaTargetInfo,
230        LLVMInitializeXtensaTarget,
231        LLVMInitializeXtensaTargetMC,
232        LLVMInitializeXtensaAsmParser
233    );
234    init_target!(
235        llvm_component = "webassembly",
236        LLVMInitializeWebAssemblyTargetInfo,
237        LLVMInitializeWebAssemblyTarget,
238        LLVMInitializeWebAssemblyTargetMC,
239        LLVMInitializeWebAssemblyAsmPrinter,
240        LLVMInitializeWebAssemblyAsmParser
241    );
242    init_target!(
243        llvm_component = "bpf",
244        LLVMInitializeBPFTargetInfo,
245        LLVMInitializeBPFTarget,
246        LLVMInitializeBPFTargetMC,
247        LLVMInitializeBPFAsmPrinter,
248        LLVMInitializeBPFAsmParser
249    );
250}