mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-02 04:57:35 +00:00
252 lines
7.7 KiB
Rust
252 lines
7.7 KiB
Rust
// 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<u8> {
|
|
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<Vec<u8>>,
|
|
}
|
|
|
|
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<u8> {
|
|
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
|
|
);
|
|
}
|