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 = "msp430",
184        LLVMInitializeMSP430TargetInfo,
185        LLVMInitializeMSP430Target,
186        LLVMInitializeMSP430TargetMC,
187        LLVMInitializeMSP430AsmPrinter,
188        LLVMInitializeMSP430AsmParser
189    );
190    init_target!(
191        llvm_component = "riscv",
192        LLVMInitializeRISCVTargetInfo,
193        LLVMInitializeRISCVTarget,
194        LLVMInitializeRISCVTargetMC,
195        LLVMInitializeRISCVAsmPrinter,
196        LLVMInitializeRISCVAsmParser
197    );
198    init_target!(
199        llvm_component = "sparc",
200        LLVMInitializeSparcTargetInfo,
201        LLVMInitializeSparcTarget,
202        LLVMInitializeSparcTargetMC,
203        LLVMInitializeSparcAsmPrinter,
204        LLVMInitializeSparcAsmParser
205    );
206    init_target!(
207        llvm_component = "nvptx",
208        LLVMInitializeNVPTXTargetInfo,
209        LLVMInitializeNVPTXTarget,
210        LLVMInitializeNVPTXTargetMC,
211        LLVMInitializeNVPTXAsmPrinter
212    );
213    init_target!(
214        llvm_component = "hexagon",
215        LLVMInitializeHexagonTargetInfo,
216        LLVMInitializeHexagonTarget,
217        LLVMInitializeHexagonTargetMC,
218        LLVMInitializeHexagonAsmPrinter,
219        LLVMInitializeHexagonAsmParser
220    );
221    init_target!(
222        llvm_component = "xtensa",
223        LLVMInitializeXtensaTargetInfo,
224        LLVMInitializeXtensaTarget,
225        LLVMInitializeXtensaTargetMC,
226        LLVMInitializeXtensaAsmPrinter,
227        LLVMInitializeXtensaAsmParser
228    );
229    init_target!(
230        llvm_component = "webassembly",
231        LLVMInitializeWebAssemblyTargetInfo,
232        LLVMInitializeWebAssemblyTarget,
233        LLVMInitializeWebAssemblyTargetMC,
234        LLVMInitializeWebAssemblyAsmPrinter,
235        LLVMInitializeWebAssemblyAsmParser
236    );
237    init_target!(
238        llvm_component = "bpf",
239        LLVMInitializeBPFTargetInfo,
240        LLVMInitializeBPFTarget,
241        LLVMInitializeBPFTargetMC,
242        LLVMInitializeBPFAsmPrinter,
243        LLVMInitializeBPFAsmParser
244    );
245}