rustc_llvm/
lib.rs

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