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