// tidy-alphabetical-start #![allow(internal_features)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(extern_types)] #![feature(rustdoc_internals)] #![warn(unreachable_pub)] // tidy-alphabetical-end use std::cell::RefCell; use std::{ptr, slice}; use libc::size_t; unsafe extern "C" { /// Opaque type that allows C++ code to write bytes to a Rust-side buffer, /// in conjunction with `RawRustStringOstream`. Use this as `&RustString` /// (Rust) and `RustStringRef` (C++) in FFI signatures. pub type RustString; } impl RustString { pub fn build_byte_buffer(closure: impl FnOnce(&Self)) -> Vec { let buf = RustStringInner::default(); closure(buf.as_opaque()); buf.into_inner() } } /// Underlying implementation of [`RustString`]. /// /// Having two separate types makes it possible to use the opaque [`RustString`] /// in FFI signatures without `improper_ctypes` warnings. This is a workaround /// for the fact that there is no way to opt out of `improper_ctypes` when /// _declaring_ a type (as opposed to using that type). #[derive(Default)] struct RustStringInner { bytes: RefCell>, } impl RustStringInner { fn as_opaque(&self) -> &RustString { let ptr: *const RustStringInner = ptr::from_ref(self); // We can't use `ptr::cast` here because extern types are `!Sized`. let ptr = ptr as *const RustString; unsafe { &*ptr } } fn from_opaque(opaque: &RustString) -> &Self { // SAFETY: A valid `&RustString` must have been created via `as_opaque`. let ptr: *const RustString = ptr::from_ref(opaque); let ptr: *const RustStringInner = ptr.cast(); unsafe { &*ptr } } fn into_inner(self) -> Vec { self.bytes.into_inner() } } /// Appends the contents of a byte slice to a [`RustString`]. /// /// This function is implemented in `rustc_llvm` so that the C++ code in this /// crate can link to it directly, without an implied link-time dependency on /// `rustc_codegen_llvm`. #[unsafe(no_mangle)] pub unsafe extern "C" fn LLVMRustStringWriteImpl( buf: &RustString, slice_ptr: *const u8, // Same ABI as `*const c_char` slice_len: size_t, ) { let slice = unsafe { slice::from_raw_parts(slice_ptr, slice_len) }; RustStringInner::from_opaque(buf).bytes.borrow_mut().extend_from_slice(slice); } /// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`. /// N.B., this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s. pub fn initialize_available_targets() { macro_rules! init_target( ($cfg:meta, $($method:ident),*) => { { #[cfg($cfg)] fn init() { unsafe extern "C" { $(fn $method();)* } unsafe { $($method();)* } } #[cfg(not($cfg))] fn init() { } init(); } } ); init_target!( llvm_component = "x86", LLVMInitializeX86TargetInfo, LLVMInitializeX86Target, LLVMInitializeX86TargetMC, LLVMInitializeX86AsmPrinter, LLVMInitializeX86AsmParser ); init_target!( llvm_component = "arm", LLVMInitializeARMTargetInfo, LLVMInitializeARMTarget, LLVMInitializeARMTargetMC, LLVMInitializeARMAsmPrinter, LLVMInitializeARMAsmParser ); init_target!( llvm_component = "aarch64", LLVMInitializeAArch64TargetInfo, LLVMInitializeAArch64Target, LLVMInitializeAArch64TargetMC, LLVMInitializeAArch64AsmPrinter, LLVMInitializeAArch64AsmParser ); init_target!( llvm_component = "amdgpu", LLVMInitializeAMDGPUTargetInfo, LLVMInitializeAMDGPUTarget, LLVMInitializeAMDGPUTargetMC, LLVMInitializeAMDGPUAsmPrinter, LLVMInitializeAMDGPUAsmParser ); init_target!( llvm_component = "avr", LLVMInitializeAVRTargetInfo, LLVMInitializeAVRTarget, LLVMInitializeAVRTargetMC, LLVMInitializeAVRAsmPrinter, LLVMInitializeAVRAsmParser ); init_target!( llvm_component = "m68k", LLVMInitializeM68kTargetInfo, LLVMInitializeM68kTarget, LLVMInitializeM68kTargetMC, LLVMInitializeM68kAsmPrinter, LLVMInitializeM68kAsmParser ); init_target!( llvm_component = "csky", LLVMInitializeCSKYTargetInfo, LLVMInitializeCSKYTarget, LLVMInitializeCSKYTargetMC, LLVMInitializeCSKYAsmPrinter, LLVMInitializeCSKYAsmParser ); init_target!( llvm_component = "loongarch", LLVMInitializeLoongArchTargetInfo, LLVMInitializeLoongArchTarget, LLVMInitializeLoongArchTargetMC, LLVMInitializeLoongArchAsmPrinter, LLVMInitializeLoongArchAsmParser ); init_target!( llvm_component = "mips", LLVMInitializeMipsTargetInfo, LLVMInitializeMipsTarget, LLVMInitializeMipsTargetMC, LLVMInitializeMipsAsmPrinter, LLVMInitializeMipsAsmParser ); init_target!( llvm_component = "powerpc", LLVMInitializePowerPCTargetInfo, LLVMInitializePowerPCTarget, LLVMInitializePowerPCTargetMC, LLVMInitializePowerPCAsmPrinter, LLVMInitializePowerPCAsmParser ); init_target!( llvm_component = "systemz", LLVMInitializeSystemZTargetInfo, LLVMInitializeSystemZTarget, LLVMInitializeSystemZTargetMC, LLVMInitializeSystemZAsmPrinter, LLVMInitializeSystemZAsmParser ); init_target!( llvm_component = "jsbackend", LLVMInitializeJSBackendTargetInfo, LLVMInitializeJSBackendTarget, LLVMInitializeJSBackendTargetMC ); init_target!( llvm_component = "msp430", LLVMInitializeMSP430TargetInfo, LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetMC, LLVMInitializeMSP430AsmPrinter, LLVMInitializeMSP430AsmParser ); init_target!( llvm_component = "riscv", LLVMInitializeRISCVTargetInfo, LLVMInitializeRISCVTarget, LLVMInitializeRISCVTargetMC, LLVMInitializeRISCVAsmPrinter, LLVMInitializeRISCVAsmParser ); init_target!( llvm_component = "sparc", LLVMInitializeSparcTargetInfo, LLVMInitializeSparcTarget, LLVMInitializeSparcTargetMC, LLVMInitializeSparcAsmPrinter, LLVMInitializeSparcAsmParser ); init_target!( llvm_component = "nvptx", LLVMInitializeNVPTXTargetInfo, LLVMInitializeNVPTXTarget, LLVMInitializeNVPTXTargetMC, LLVMInitializeNVPTXAsmPrinter ); init_target!( llvm_component = "hexagon", LLVMInitializeHexagonTargetInfo, LLVMInitializeHexagonTarget, LLVMInitializeHexagonTargetMC, LLVMInitializeHexagonAsmPrinter, LLVMInitializeHexagonAsmParser ); init_target!( llvm_component = "xtensa", LLVMInitializeXtensaTargetInfo, LLVMInitializeXtensaTarget, LLVMInitializeXtensaTargetMC, LLVMInitializeXtensaAsmParser ); init_target!( llvm_component = "webassembly", LLVMInitializeWebAssemblyTargetInfo, LLVMInitializeWebAssemblyTarget, LLVMInitializeWebAssemblyTargetMC, LLVMInitializeWebAssemblyAsmPrinter, LLVMInitializeWebAssemblyAsmParser ); init_target!( llvm_component = "bpf", LLVMInitializeBPFTargetInfo, LLVMInitializeBPFTarget, LLVMInitializeBPFTargetMC, LLVMInitializeBPFAsmPrinter, LLVMInitializeBPFAsmParser ); }