about summary refs log tree commit diff
path: root/compiler/rustc_llvm/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_llvm/src')
-rw-r--r--compiler/rustc_llvm/src/lib.rs251
1 files changed, 251 insertions, 0 deletions
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
new file mode 100644
index 00000000000..eda9b2b1fc0
--- /dev/null
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -0,0 +1,251 @@
+// 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
+    );
+}