rust/compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

2633 lines
80 KiB
Rust
Raw Normal View History

//! Bindings to the LLVM-C API (`LLVM*`), and to our own `extern "C"` wrapper
//! functions around the unstable LLVM C++ API (`LLVMRust*`).
//!
//! ## Passing pointer/length strings as `*const c_uchar`
//!
//! Normally it's a good idea for Rust-side bindings to match the corresponding
//! C-side function declarations as closely as possible. But when passing `&str`
//! or `&[u8]` data as a pointer/length pair, it's more convenient to declare
//! the Rust-side pointer as `*const c_uchar` instead of `*const c_char`.
//! Both pointer types have the same ABI, and using `*const c_uchar` avoids
//! the need for an extra cast from `*const u8` on the Rust side.
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
use std::fmt::Debug;
use std::marker::PhantomData;
2024-10-28 06:25:40 +00:00
use std::ptr;
2025-02-01 02:43:30 +00:00
use bitflags::bitflags;
use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong, c_void, size_t};
use rustc_macros::TryFromU32;
use rustc_target::spec::SymbolVisibility;
use super::RustString;
use super::debuginfo::{
DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
DIFile, DIFlags, DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram,
DISubrange, DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DebugNameTableKind,
};
2025-02-01 02:43:30 +00:00
use crate::llvm;
2016-08-02 21:25:19 +00:00
/// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
/// which has a different ABI from Rust or C++ `bool`.
pub type Bool = c_int;
pub const True: Bool = 1 as Bool;
pub const False: Bool = 0 as Bool;
/// Wrapper for a raw enum value returned from LLVM's C APIs.
///
/// For C enums returned by LLVM, it's risky to use a Rust enum as the return
/// type, because it would be UB if a later version of LLVM adds a new enum
/// value and returns it. Instead, return this raw wrapper, then convert to the
/// Rust-side enum explicitly.
#[repr(transparent)]
pub struct RawEnum<T> {
value: u32,
/// We don't own or consume a `T`, but we can produce one.
_rust_side_type: PhantomData<fn() -> T>,
}
impl<T: TryFrom<u32>> RawEnum<T> {
#[track_caller]
pub(crate) fn to_rust(self) -> T
where
T::Error: Debug,
{
// If this fails, the Rust-side enum is out of sync with LLVM's enum.
T::try_from(self.value).expect("enum value returned by LLVM should be known")
}
}
#[derive(Copy, Clone, PartialEq)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
#[allow(dead_code)] // Variants constructed by C++.
pub enum LLVMRustResult {
Success,
Failure,
}
/// Must match the layout of `LLVMRustModuleFlagMergeBehavior`.
///
/// When merging modules (e.g. during LTO), their metadata flags are combined. Conflicts are
/// resolved according to the merge behaviors specified here. Flags differing only in merge
/// behavior are still considered to be in conflict.
///
/// In order for Rust-C LTO to work, we must specify behaviors compatible with Clang. Notably,
/// 'Error' and 'Warning' cannot be mixed for a given flag.
///
/// There is a stable LLVM-C version of this enum (`LLVMModuleFlagBehavior`),
/// but as of LLVM 19 it does not support all of the enum values in the unstable
/// C++ API.
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum ModuleFlagMergeBehavior {
Error = 1,
Warning = 2,
Require = 3,
Override = 4,
Append = 5,
AppendUnique = 6,
Max = 7,
Min = 8,
}
// Consts for the LLVM CallConv type, pre-cast to usize.
/// LLVM CallingConv::ID. Should we wrap this?
///
/// See <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/CallingConv.h>
#[derive(Copy, Clone, PartialEq, Debug, TryFromU32)]
#[repr(C)]
pub enum CallConv {
CCallConv = 0,
FastCallConv = 8,
ColdCallConv = 9,
PreserveMost = 14,
PreserveAll = 15,
Tail = 18,
X86StdcallCallConv = 64,
X86FastcallCallConv = 65,
ArmAapcsCallConv = 67,
Msp430Intr = 69,
X86_ThisCall = 70,
PtxKernel = 71,
X86_64_SysV = 78,
X86_64_Win64 = 79,
2016-10-22 13:07:35 +00:00
X86_VectorCall = 80,
X86_Intr = 83,
2016-05-06 13:32:10 +00:00
AvrNonBlockingInterrupt = 84,
AvrInterrupt = 85,
AmdgpuKernel = 91,
}
/// Must match the layout of `LLVMLinkage`.
#[derive(Copy, Clone, PartialEq, TryFromU32)]
#[repr(C)]
pub enum Linkage {
ExternalLinkage = 0,
AvailableExternallyLinkage = 1,
LinkOnceAnyLinkage = 2,
LinkOnceODRLinkage = 3,
#[deprecated = "marked obsolete by LLVM"]
LinkOnceODRAutoHideLinkage = 4,
WeakAnyLinkage = 5,
WeakODRLinkage = 6,
AppendingLinkage = 7,
InternalLinkage = 8,
PrivateLinkage = 9,
#[deprecated = "marked obsolete by LLVM"]
DLLImportLinkage = 10,
#[deprecated = "marked obsolete by LLVM"]
DLLExportLinkage = 11,
ExternalWeakLinkage = 12,
#[deprecated = "marked obsolete by LLVM"]
GhostLinkage = 13,
CommonLinkage = 14,
LinkerPrivateLinkage = 15,
LinkerPrivateWeakLinkage = 16,
}
/// Must match the layout of `LLVMVisibility`.
#[repr(C)]
#[derive(Copy, Clone, PartialEq, TryFromU32)]
pub enum Visibility {
Default = 0,
Hidden = 1,
Protected = 2,
}
impl Visibility {
pub(crate) fn from_generic(visibility: SymbolVisibility) -> Self {
match visibility {
SymbolVisibility::Hidden => Visibility::Hidden,
SymbolVisibility::Protected => Visibility::Protected,
SymbolVisibility::Interposable => Visibility::Default,
}
}
}
/// LLVMUnnamedAddr
#[repr(C)]
pub enum UnnamedAddr {
No,
Local,
Global,
}
2016-08-02 21:25:19 +00:00
/// LLVMDLLStorageClass
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum DLLStorageClass {
#[allow(dead_code)]
2016-10-22 13:07:35 +00:00
Default = 0,
DllImport = 1, // Function to be imported from DLL.
#[allow(dead_code)]
2016-10-22 13:07:35 +00:00
DllExport = 2, // Function to be accessible from DLL.
}
/// Must match the layout of `LLVMRustAttributeKind`.
/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
/// though it is not ABI compatible (since it's a C++ enum)
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub enum AttributeKind {
AlwaysInline = 0,
ByVal = 1,
Cold = 2,
InlineHint = 3,
MinSize = 4,
Naked = 5,
NoAlias = 6,
NoCapture = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
NoReturn = 11,
NoUnwind = 12,
OptimizeForSize = 13,
ReadOnly = 14,
SExt = 15,
StructRet = 16,
UWTable = 17,
ZExt = 18,
InReg = 19,
2016-12-30 04:28:11 +00:00
SanitizeThread = 20,
SanitizeAddress = 21,
2016-12-30 04:28:11 +00:00
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
2020-02-17 21:36:01 +00:00
ReadNone = 26,
2021-01-23 02:32:38 +00:00
SanitizeHWAddress = 28,
2021-02-20 16:02:23 +00:00
WillReturn = 29,
add rustc option for using LLVM stack smash protection LLVM has built-in heuristics for adding stack canaries to functions. These heuristics can be selected with LLVM function attributes. This patch adds a rustc option `-Z stack-protector={none,basic,strong,all}` which controls the use of these attributes. This gives rustc the same stack smash protection support as clang offers through options `-fno-stack-protector`, `-fstack-protector`, `-fstack-protector-strong`, and `-fstack-protector-all`. The protection this can offer is demonstrated in test/ui/abi/stack-protector.rs. This fills a gap in the current list of rustc exploit mitigations (https://doc.rust-lang.org/rustc/exploit-mitigations.html), originally discussed in #15179. Stack smash protection adds runtime overhead and is therefore still off by default, but now users have the option to trade performance for security as they see fit. An example use case is adding Rust code in an existing C/C++ code base compiled with stack smash protection. Without the ability to add stack smash protection to the Rust code, the code base artifacts could be exploitable in ways not possible if the code base remained pure C/C++. Stack smash protection support is present in LLVM for almost all the current tier 1/tier 2 targets: see test/assembly/stack-protector/stack-protector-target-support.rs. The one exception is nvptx64-nvidia-cuda. This patch follows clang's example, and adds a warning message printed if stack smash protection is used with this target (see test/ui/stack-protector/warn-stack-protector-unsupported.rs). Support for tier 3 targets has not been checked. Since the heuristics are applied at the LLVM level, the heuristics are expected to add stack smash protection to a fraction of functions comparable to C/C++. Some experiments demonstrating how Rust code is affected by the different heuristics can be found in test/assembly/stack-protector/stack-protector-heuristics-effect.rs. There is potential for better heuristics using Rust-specific safety information. For example it might be reasonable to skip stack smash protection in functions which transitively only use safe Rust code, or which uses only a subset of functions the user declares safe (such as anything under `std.*`). Such alternative heuristics could be added at a later point. LLVM also offers a "safestack" sanitizer as an alternative way to guard against stack smashing (see #26612). This could possibly also be included as a stack-protection heuristic. An alternative is to add it as a sanitizer (#39699). This is what clang does: safestack is exposed with option `-fsanitize=safe-stack`. The options are only supported by the LLVM backend, but as with other codegen options it is visible in the main codegen option help menu. The heuristic names "basic", "strong", and "all" are hopefully sufficiently generic to be usable in other backends as well. Reviewed-by: Nikita Popov <nikic@php.net> Extra commits during review: - [address-review] make the stack-protector option unstable - [address-review] reduce detail level of stack-protector option help text - [address-review] correct grammar in comment - [address-review] use compiler flag to avoid merging functions in test - [address-review] specify min LLVM version in fortanix stack-protector test Only for Fortanix test, since this target specifically requests the `--x86-experimental-lvi-inline-asm-hardening` flag. - [address-review] specify required LLVM components in stack-protector tests - move stack protector option enum closer to other similar option enums - rustc_interface/tests: sort debug option list in tracking hash test - add an explicit `none` stack-protector option Revert "set LLVM requirements for all stack protector support test revisions" This reverts commit a49b74f92a4e7d701d6f6cf63d207a8aff2e0f68.
2021-04-06 19:37:49 +00:00
StackProtectReq = 30,
StackProtectStrong = 31,
StackProtect = 32,
NoUndef = 33,
SanitizeMemTag = 34,
NoCfCheck = 35,
ShadowCallStack = 36,
AllocSize = 37,
AllocatedPointer = 38,
AllocAlign = 39,
SanitizeSafeStack = 40,
FnRetThunkExtern = 41,
Writable = 42,
DeadOnUnwind = 43,
}
/// LLVMIntPredicate
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum IntPredicate {
IntEQ = 32,
IntNE = 33,
IntUGT = 34,
IntUGE = 35,
IntULT = 36,
IntULE = 37,
IntSGT = 38,
IntSGE = 39,
IntSLT = 40,
IntSLE = 41,
}
impl IntPredicate {
pub(crate) fn from_generic(intpre: rustc_codegen_ssa::common::IntPredicate) -> Self {
use rustc_codegen_ssa::common::IntPredicate as Common;
match intpre {
Common::IntEQ => Self::IntEQ,
Common::IntNE => Self::IntNE,
Common::IntUGT => Self::IntUGT,
Common::IntUGE => Self::IntUGE,
Common::IntULT => Self::IntULT,
Common::IntULE => Self::IntULE,
Common::IntSGT => Self::IntSGT,
Common::IntSGE => Self::IntSGE,
Common::IntSLT => Self::IntSLT,
Common::IntSLE => Self::IntSLE,
}
}
}
/// LLVMRealPredicate
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum RealPredicate {
RealPredicateFalse = 0,
RealOEQ = 1,
RealOGT = 2,
RealOGE = 3,
RealOLT = 4,
RealOLE = 5,
RealONE = 6,
RealORD = 7,
RealUNO = 8,
RealUEQ = 9,
RealUGT = 10,
RealUGE = 11,
RealULT = 12,
RealULE = 13,
RealUNE = 14,
RealPredicateTrue = 15,
}
impl RealPredicate {
pub(crate) fn from_generic(realp: rustc_codegen_ssa::common::RealPredicate) -> Self {
use rustc_codegen_ssa::common::RealPredicate as Common;
match realp {
Common::RealPredicateFalse => Self::RealPredicateFalse,
Common::RealOEQ => Self::RealOEQ,
Common::RealOGT => Self::RealOGT,
Common::RealOGE => Self::RealOGE,
Common::RealOLT => Self::RealOLT,
Common::RealOLE => Self::RealOLE,
Common::RealONE => Self::RealONE,
Common::RealORD => Self::RealORD,
Common::RealUNO => Self::RealUNO,
Common::RealUEQ => Self::RealUEQ,
Common::RealUGT => Self::RealUGT,
Common::RealUGE => Self::RealUGE,
Common::RealULT => Self::RealULT,
Common::RealULE => Self::RealULE,
Common::RealUNE => Self::RealUNE,
Common::RealPredicateTrue => Self::RealPredicateTrue,
}
}
}
2016-08-02 21:25:19 +00:00
/// LLVMTypeKind
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C)]
pub enum TypeKind {
2016-10-22 13:07:35 +00:00
Void = 0,
Half = 1,
Float = 2,
Double = 3,
X86_FP80 = 4,
FP128 = 5,
2018-09-28 10:18:03 +00:00
PPC_FP128 = 6,
2016-10-22 13:07:35 +00:00
Label = 7,
Integer = 8,
Function = 9,
Struct = 10,
Array = 11,
Pointer = 12,
Vector = 13,
Metadata = 14,
Token = 16,
2020-06-26 01:52:41 +00:00
ScalableVector = 17,
BFloat = 18,
2020-11-03 21:47:16 +00:00
X86_AMX = 19,
}
2018-09-07 20:25:50 +00:00
impl TypeKind {
pub(crate) fn to_generic(self) -> rustc_codegen_ssa::common::TypeKind {
use rustc_codegen_ssa::common::TypeKind as Common;
2018-09-07 20:25:50 +00:00
match self {
Self::Void => Common::Void,
Self::Half => Common::Half,
Self::Float => Common::Float,
Self::Double => Common::Double,
Self::X86_FP80 => Common::X86_FP80,
Self::FP128 => Common::FP128,
Self::PPC_FP128 => Common::PPC_FP128,
Self::Label => Common::Label,
Self::Integer => Common::Integer,
Self::Function => Common::Function,
Self::Struct => Common::Struct,
Self::Array => Common::Array,
Self::Pointer => Common::Pointer,
Self::Vector => Common::Vector,
Self::Metadata => Common::Metadata,
Self::Token => Common::Token,
Self::ScalableVector => Common::ScalableVector,
Self::BFloat => Common::BFloat,
Self::X86_AMX => Common::X86_AMX,
2018-09-07 20:25:50 +00:00
}
}
}
/// LLVMAtomicRmwBinOp
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum AtomicRmwBinOp {
AtomicXchg = 0,
2016-10-22 13:07:35 +00:00
AtomicAdd = 1,
AtomicSub = 2,
AtomicAnd = 3,
AtomicNand = 4,
2016-10-22 13:07:35 +00:00
AtomicOr = 5,
AtomicXor = 6,
AtomicMax = 7,
AtomicMin = 8,
AtomicUMax = 9,
AtomicUMin = 10,
}
impl AtomicRmwBinOp {
pub(crate) fn from_generic(op: rustc_codegen_ssa::common::AtomicRmwBinOp) -> Self {
use rustc_codegen_ssa::common::AtomicRmwBinOp as Common;
match op {
Common::AtomicXchg => Self::AtomicXchg,
Common::AtomicAdd => Self::AtomicAdd,
Common::AtomicSub => Self::AtomicSub,
Common::AtomicAnd => Self::AtomicAnd,
Common::AtomicNand => Self::AtomicNand,
Common::AtomicOr => Self::AtomicOr,
Common::AtomicXor => Self::AtomicXor,
Common::AtomicMax => Self::AtomicMax,
Common::AtomicMin => Self::AtomicMin,
Common::AtomicUMax => Self::AtomicUMax,
Common::AtomicUMin => Self::AtomicUMin,
}
}
}
/// LLVMAtomicOrdering
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum AtomicOrdering {
#[allow(dead_code)]
NotAtomic = 0,
Unordered = 1,
Monotonic = 2,
// Consume = 3, // Not specified yet.
Acquire = 4,
Release = 5,
AcquireRelease = 6,
2016-10-22 13:07:35 +00:00
SequentiallyConsistent = 7,
}
impl AtomicOrdering {
pub(crate) fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
use rustc_codegen_ssa::common::AtomicOrdering as Common;
match ao {
Common::Unordered => Self::Unordered,
Common::Relaxed => Self::Monotonic,
Common::Acquire => Self::Acquire,
Common::Release => Self::Release,
Common::AcquireRelease => Self::AcquireRelease,
Common::SequentiallyConsistent => Self::SequentiallyConsistent,
}
}
}
/// LLVMRustFileType
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum FileType {
AssemblyFile,
ObjectFile,
}
/// LLVMMetadataType
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum MetadataType {
MD_dbg = 0,
MD_tbaa = 1,
MD_prof = 2,
MD_fpmath = 3,
MD_range = 4,
MD_tbaa_struct = 5,
MD_invariant_load = 6,
MD_alias_scope = 7,
MD_noalias = 8,
MD_nontemporal = 9,
MD_mem_parallel_loop_access = 10,
MD_nonnull = 11,
MD_unpredictable = 15,
MD_align = 17,
MD_type = 19,
Add metadata generation for vtables when using VFE This adds the typeid and `vcall_visibility` metadata to vtables when the -Cvirtual-function-elimination flag is set. The typeid is generated in the same way as for the `llvm.type.checked.load` intrinsic from the trait_ref. The offset that is added to the typeid is always 0. This is because LLVM assumes that vtables are constructed according to the definition in the Itanium ABI. This includes an "address point" of the vtable. In C++ this is the offset in the vtable where information for RTTI is placed. Since there is no RTTI information in Rust's vtables, this "address point" is always 0. This "address point" in combination with the offset passed to the `llvm.type.checked.load` intrinsic determines the final function that should be loaded from the vtable in the `WholeProgramDevirtualization` pass in LLVM. That's why the `llvm.type.checked.load` intrinsics are generated with the typeid of the trait, rather than with that of the function that is called. This matches what `clang` does for C++. The vcall_visibility metadata depends on three factors: 1. LTO level: Currently this is always fat LTO, because LLVM only supports this optimization with fat LTO. 2. Visibility of the trait: If the trait is publicly visible, VFE can only act on its vtables after linking. 3. Number of CGUs: if there is more than one CGU, also vtables with restricted visibility could be seen outside of the CGU, so VFE can only act on them after linking. To reflect this, there are three visibility levels: Public, LinkageUnit, and TranslationUnit.
2022-04-21 13:02:54 +00:00
MD_vcall_visibility = 28,
MD_noundef = 29,
MD_kcfi_type = 36,
}
2016-08-02 21:25:19 +00:00
/// LLVMRustAsmDialect
#[derive(Copy, Clone, PartialEq)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum AsmDialect {
2016-08-02 21:25:19 +00:00
Att,
Intel,
}
/// LLVMRustCodeGenOptLevel
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum CodeGenOptLevel {
None,
Less,
Default,
Aggressive,
}
/// LLVMRustPassBuilderOptLevel
#[repr(C)]
pub enum PassBuilderOptLevel {
O0,
O1,
O2,
O3,
Os,
Oz,
}
/// LLVMRustOptStage
#[derive(PartialEq)]
#[repr(C)]
pub enum OptStage {
PreLinkNoLTO,
PreLinkThinLTO,
PreLinkFatLTO,
ThinLTO,
FatLTO,
}
/// LLVMRustSanitizerOptions
#[repr(C)]
pub struct SanitizerOptions {
pub sanitize_address: bool,
pub sanitize_address_recover: bool,
pub sanitize_cfi: bool,
pub sanitize_dataflow: bool,
pub sanitize_dataflow_abilist: *const *const c_char,
pub sanitize_dataflow_abilist_len: size_t,
pub sanitize_kcfi: bool,
pub sanitize_memory: bool,
pub sanitize_memory_recover: bool,
pub sanitize_memory_track_origins: c_int,
pub sanitize_thread: bool,
2021-01-23 02:32:38 +00:00
pub sanitize_hwaddress: bool,
pub sanitize_hwaddress_recover: bool,
pub sanitize_kernel_address: bool,
pub sanitize_kernel_address_recover: bool,
}
/// LLVMRustRelocModel
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum RelocModel {
Static,
PIC,
DynamicNoPic,
ROPI,
RWPI,
ROPI_RWPI,
}
/// LLVMRustFloatABI
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum FloatAbi {
Default,
Soft,
Hard,
}
/// LLVMRustCodeModel
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum CodeModel {
Tiny,
Small,
Kernel,
Medium,
Large,
None,
}
/// LLVMRustDiagnosticKind
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
#[allow(dead_code)] // Variants constructed by C++.
pub enum DiagnosticKind {
Other,
InlineAsm,
StackSize,
DebugMetadataVersion,
SampleProfile,
OptimizationRemark,
OptimizationRemarkMissed,
OptimizationRemarkAnalysis,
OptimizationRemarkAnalysisFPCommute,
OptimizationRemarkAnalysisAliasing,
OptimizationRemarkOther,
OptimizationFailure,
PGOProfile,
Linker,
Unsupported,
SrcMgr,
}
2020-06-09 13:37:59 +00:00
/// LLVMRustDiagnosticLevel
#[derive(Copy, Clone)]
#[repr(C)]
#[allow(dead_code)] // Variants constructed by C++.
pub enum DiagnosticLevel {
Error,
Warning,
Note,
Remark,
}
/// LLVMRustArchiveKind
#[derive(Copy, Clone)]
2016-08-02 21:25:19 +00:00
#[repr(C)]
pub enum ArchiveKind {
K_GNU,
K_BSD,
K_DARWIN,
K_COFF,
2023-01-11 03:27:29 +00:00
K_AIXBIG,
}
2016-08-02 21:25:19 +00:00
unsafe extern "C" {
// LLVMRustThinLTOData
pub type ThinLTOData;
rustc: Implement ThinLTO This commit is an implementation of LLVM's ThinLTO for consumption in rustc itself. Currently today LTO works by merging all relevant LLVM modules into one and then running optimization passes. "Thin" LTO operates differently by having more sharded work and allowing parallelism opportunities between optimizing codegen units. Further down the road Thin LTO also allows *incremental* LTO which should enable even faster release builds without compromising on the performance we have today. This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then also implements two forms of ThinLTO: * In one mode we'll *only* perform ThinLTO over the codegen units produced in a single compilation. That is, we won't load upstream rlibs, but we'll instead just perform ThinLTO amongst all codegen units produced by the compiler for the local crate. This is intended to emulate a desired end point where we have codegen units turned on by default for all crates and ThinLTO allows us to do this without performance loss. * In anther mode, like full LTO today, we'll optimize all upstream dependencies in "thin" mode. Unlike today, however, this LTO step is fully parallelized so should finish much more quickly. There's a good bit of comments about what the implementation is doing and where it came from, but the tl;dr; is that currently most of the support here is copied from upstream LLVM. This code duplication is done for a number of reasons: * Controlling parallelism means we can use the existing jobserver support to avoid overloading machines. * We will likely want a slightly different form of incremental caching which integrates with our own incremental strategy, but this is yet to be determined. * This buys us some flexibility about when/where we run ThinLTO, as well as having it tailored to fit our needs for the time being. * Finally this allows us to reuse some artifacts such as our `TargetMachine` creation, where all our options we used today aren't necessarily supported by upstream LLVM yet. My hope is that we can get some experience with this copy/paste in tree and then eventually upstream some work to LLVM itself to avoid the duplication while still ensuring our needs are met. Otherwise I fear that maintaining these bindings may be quite costly over the years with LLVM updates!
2017-07-23 15:14:38 +00:00
// LLVMRustThinLTOBuffer
pub type ThinLTOBuffer;
}
rustc: Implement ThinLTO This commit is an implementation of LLVM's ThinLTO for consumption in rustc itself. Currently today LTO works by merging all relevant LLVM modules into one and then running optimization passes. "Thin" LTO operates differently by having more sharded work and allowing parallelism opportunities between optimizing codegen units. Further down the road Thin LTO also allows *incremental* LTO which should enable even faster release builds without compromising on the performance we have today. This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then also implements two forms of ThinLTO: * In one mode we'll *only* perform ThinLTO over the codegen units produced in a single compilation. That is, we won't load upstream rlibs, but we'll instead just perform ThinLTO amongst all codegen units produced by the compiler for the local crate. This is intended to emulate a desired end point where we have codegen units turned on by default for all crates and ThinLTO allows us to do this without performance loss. * In anther mode, like full LTO today, we'll optimize all upstream dependencies in "thin" mode. Unlike today, however, this LTO step is fully parallelized so should finish much more quickly. There's a good bit of comments about what the implementation is doing and where it came from, but the tl;dr; is that currently most of the support here is copied from upstream LLVM. This code duplication is done for a number of reasons: * Controlling parallelism means we can use the existing jobserver support to avoid overloading machines. * We will likely want a slightly different form of incremental caching which integrates with our own incremental strategy, but this is yet to be determined. * This buys us some flexibility about when/where we run ThinLTO, as well as having it tailored to fit our needs for the time being. * Finally this allows us to reuse some artifacts such as our `TargetMachine` creation, where all our options we used today aren't necessarily supported by upstream LLVM yet. My hope is that we can get some experience with this copy/paste in tree and then eventually upstream some work to LLVM itself to avoid the duplication while still ensuring our needs are met. Otherwise I fear that maintaining these bindings may be quite costly over the years with LLVM updates!
2017-07-23 15:14:38 +00:00
/// LLVMRustThinLTOModule
#[repr(C)]
pub struct ThinLTOModule {
pub identifier: *const c_char,
pub data: *const u8,
pub len: usize,
}
/// LLVMThreadLocalMode
#[derive(Copy, Clone)]
#[repr(C)]
pub enum ThreadLocalMode {
NotThreadLocal,
GeneralDynamic,
LocalDynamic,
InitialExec,
LocalExec,
}
/// LLVMRustChecksumKind
#[derive(Copy, Clone)]
#[repr(C)]
pub enum ChecksumKind {
None,
MD5,
SHA1,
SHA256,
}
2022-11-04 16:20:42 +00:00
/// LLVMRustMemoryEffects
#[derive(Copy, Clone)]
#[repr(C)]
pub enum MemoryEffects {
None,
ReadOnly,
InaccessibleMemOnly,
}
2025-01-02 12:10:11 +00:00
/// LLVMOpcode
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub enum Opcode {
Ret = 1,
Br = 2,
Switch = 3,
IndirectBr = 4,
Invoke = 5,
Unreachable = 7,
CallBr = 67,
FNeg = 66,
Add = 8,
FAdd = 9,
Sub = 10,
FSub = 11,
Mul = 12,
FMul = 13,
UDiv = 14,
SDiv = 15,
FDiv = 16,
URem = 17,
SRem = 18,
FRem = 19,
Shl = 20,
LShr = 21,
AShr = 22,
And = 23,
Or = 24,
Xor = 25,
Alloca = 26,
Load = 27,
Store = 28,
GetElementPtr = 29,
Trunc = 30,
ZExt = 31,
SExt = 32,
FPToUI = 33,
FPToSI = 34,
UIToFP = 35,
SIToFP = 36,
FPTrunc = 37,
FPExt = 38,
PtrToInt = 39,
IntToPtr = 40,
BitCast = 41,
AddrSpaceCast = 60,
ICmp = 42,
FCmp = 43,
PHI = 44,
Call = 45,
Select = 46,
UserOp1 = 47,
UserOp2 = 48,
VAArg = 49,
ExtractElement = 50,
InsertElement = 51,
ShuffleVector = 52,
ExtractValue = 53,
InsertValue = 54,
Freeze = 68,
Fence = 55,
AtomicCmpXchg = 56,
AtomicRMW = 57,
Resume = 58,
LandingPad = 59,
CleanupRet = 61,
CatchRet = 62,
CatchPad = 63,
CleanupPad = 64,
CatchSwitch = 65,
}
unsafe extern "C" {
type Opaque;
}
#[repr(C)]
struct InvariantOpaque<'a> {
_marker: PhantomData<&'a mut &'a ()>,
_opaque: Opaque,
}
// Opaque pointer types
unsafe extern "C" {
pub type Module;
pub type Context;
pub type Type;
pub type Value;
2019-10-13 10:19:14 +00:00
pub type ConstantInt;
pub type Attribute;
pub type Metadata;
pub type BasicBlock;
pub type Comdat;
}
#[repr(C)]
pub struct Builder<'a>(InvariantOpaque<'a>);
#[repr(C)]
pub struct PassManager<'a>(InvariantOpaque<'a>);
unsafe extern "C" {
pub type TargetMachine;
pub type Archive;
}
#[repr(C)]
pub struct ArchiveIterator<'a>(InvariantOpaque<'a>);
#[repr(C)]
pub struct ArchiveChild<'a>(InvariantOpaque<'a>);
unsafe extern "C" {
pub type Twine;
pub type DiagnosticInfo;
pub type SMDiagnostic;
}
#[repr(C)]
pub struct RustArchiveMember<'a>(InvariantOpaque<'a>);
2024-10-28 06:25:40 +00:00
/// Opaque pointee of `LLVMOperandBundleRef`.
#[repr(C)]
2024-10-28 06:25:40 +00:00
pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>);
#[repr(C)]
pub struct Linker<'a>(InvariantOpaque<'a>);
unsafe extern "C" {
pub type DiagnosticHandler;
}
pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
pub mod debuginfo {
use std::ptr;
rustc: Link LLVM directly into rustc again This commit builds on #65501 continue to simplify the build system and compiler now that we no longer have multiple LLVM backends to ship by default. Here this switches the compiler back to what it once was long long ago, which is linking LLVM directly to the compiler rather than dynamically loading it at runtime. The `codegen-backends` directory of the sysroot no longer exists and all relevant support in the build system is removed. Note that `rustc` still supports a dynamically loaded codegen backend as it did previously, it just no longer supports dynamically loaded codegen backends in its own sysroot. Additionally as part of this the `librustc_codegen_llvm` crate now once again explicitly depends on all of its crates instead of implicitly loading them through the sysroot. This involved filling out its `Cargo.toml` and deleting all the now-unnecessary `extern crate` annotations in the header of the crate. (this in turn required adding a number of imports for names of macros too). The end results of this change are: * Rustbuild's build process for the compiler as all the "oh don't forget the codegen backend" checks can be easily removed. * Building `rustc_codegen_llvm` is much simpler since it's simply another compiler crate. * Managing the dependencies of `rustc_codegen_llvm` is much simpler since it's "just another `Cargo.toml` to edit" * The build process should be a smidge faster because there's more parallelism in the main rustc build step rather than splitting `librustc_codegen_llvm` out to its own step. * The compiler is expected to be slightly faster by default because the codegen backend does not need to be dynamically loaded. * Disabling LLVM as part of rustbuild is still supported, supporting multiple codegen backends is still supported, and dynamic loading of a codegen backend is still supported.
2019-10-22 15:51:35 +00:00
use bitflags::bitflags;
use super::{InvariantOpaque, Metadata};
use crate::llvm::{self, Module};
/// Opaque target type for references to an LLVM debuginfo builder.
///
/// `&'_ DIBuilder<'ll>` corresponds to `LLVMDIBuilderRef`, which is the
/// LLVM-C wrapper for `DIBuilder *`.
///
/// Debuginfo builders are created and destroyed during codegen, so the
/// builder reference typically has a shorter lifetime than the LLVM
/// session (`'ll`) that it participates in.
#[repr(C)]
pub struct DIBuilder<'ll>(InvariantOpaque<'ll>);
/// Owning pointer to a `DIBuilder<'ll>` that will dispose of the builder
/// when dropped. Use `.as_ref()` to get the underlying `&DIBuilder`
/// needed for debuginfo FFI calls.
pub(crate) struct DIBuilderBox<'ll> {
raw: ptr::NonNull<DIBuilder<'ll>>,
}
impl<'ll> DIBuilderBox<'ll> {
pub(crate) fn new(llmod: &'ll Module) -> Self {
let raw = unsafe { llvm::LLVMCreateDIBuilder(llmod) };
let raw = ptr::NonNull::new(raw).unwrap();
Self { raw }
}
pub(crate) fn as_ref(&self) -> &DIBuilder<'ll> {
// SAFETY: This is an owning pointer, so `&DIBuilder` is valid
// for as long as `&self` is.
unsafe { self.raw.as_ref() }
}
}
impl<'ll> Drop for DIBuilderBox<'ll> {
fn drop(&mut self) {
unsafe { llvm::LLVMDisposeDIBuilder(self.raw) };
}
}
pub type DIDescriptor = Metadata;
pub type DILocation = Metadata;
pub type DIScope = DIDescriptor;
pub type DIFile = DIScope;
pub type DILexicalBlock = DIScope;
pub type DISubprogram = DIScope;
pub type DIType = DIDescriptor;
pub type DIBasicType = DIType;
pub type DIDerivedType = DIType;
pub type DICompositeType = DIDerivedType;
pub type DIVariable = DIDescriptor;
2018-09-14 16:06:45 +00:00
pub type DIGlobalVariableExpression = DIDescriptor;
pub type DIArray = DIDescriptor;
pub type DISubrange = DIDescriptor;
pub type DIEnumerator = DIDescriptor;
pub type DITemplateTypeParameter = DIDescriptor;
bitflags! {
/// Must match the layout of `LLVMDIFlags` in the LLVM-C API.
///
/// Each value declared here must also be covered by the static
/// assertions in `RustWrapper.cpp` used by `fromRust(LLVMDIFlags)`.
#[repr(transparent)]
#[derive(Clone, Copy, Default)]
pub struct DIFlags: u32 {
const FlagZero = 0;
const FlagPrivate = 1;
const FlagProtected = 2;
const FlagPublic = 3;
const FlagFwdDecl = (1 << 2);
const FlagAppleBlock = (1 << 3);
const FlagReservedBit4 = (1 << 4);
const FlagVirtual = (1 << 5);
const FlagArtificial = (1 << 6);
const FlagExplicit = (1 << 7);
const FlagPrototyped = (1 << 8);
const FlagObjcClassComplete = (1 << 9);
const FlagObjectPointer = (1 << 10);
const FlagVector = (1 << 11);
const FlagStaticMember = (1 << 12);
const FlagLValueReference = (1 << 13);
const FlagRValueReference = (1 << 14);
const FlagReserved = (1 << 15);
const FlagSingleInheritance = (1 << 16);
const FlagMultipleInheritance = (2 << 16);
const FlagVirtualInheritance = (3 << 16);
const FlagIntroducedVirtual = (1 << 18);
const FlagBitField = (1 << 19);
const FlagNoReturn = (1 << 20);
// The bit at (1 << 21) is unused, but was `LLVMDIFlagMainSubprogram`.
const FlagTypePassByValue = (1 << 22);
const FlagTypePassByReference = (1 << 23);
const FlagEnumClass = (1 << 24);
const FlagThunk = (1 << 25);
const FlagNonTrivial = (1 << 26);
const FlagBigEndian = (1 << 27);
const FlagLittleEndian = (1 << 28);
}
}
// These values **must** match with LLVMRustDISPFlags!!
bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Default)]
pub struct DISPFlags: u32 {
const SPFlagZero = 0;
const SPFlagVirtual = 1;
const SPFlagPureVirtual = 2;
const SPFlagLocalToUnit = (1 << 2);
const SPFlagDefinition = (1 << 3);
const SPFlagOptimized = (1 << 4);
const SPFlagMainSubprogram = (1 << 5);
}
}
2019-01-22 21:01:14 +00:00
/// LLVMRustDebugEmissionKind
#[derive(Copy, Clone)]
#[repr(C)]
pub enum DebugEmissionKind {
NoDebug,
FullDebug,
LineTablesOnly,
DebugDirectivesOnly,
2019-01-22 21:01:14 +00:00
}
impl DebugEmissionKind {
pub(crate) fn from_generic(kind: rustc_session::config::DebugInfo) -> Self {
// We should be setting LLVM's emission kind to `LineTablesOnly` if
// we are compiling with "limited" debuginfo. However, some of the
// existing tools relied on slightly more debuginfo being generated than
// would be the case with `LineTablesOnly`, and we did not want to break
// these tools in a "drive-by fix", without a good idea or plan about
// what limited debuginfo should exactly look like. So for now we are
// instead adding a new debuginfo option "line-tables-only" so as to
// not break anything and to allow users to have 'limited' debug info.
//
// See https://github.com/rust-lang/rust/issues/60020 for details.
use rustc_session::config::DebugInfo;
2019-01-22 21:01:14 +00:00
match kind {
DebugInfo::None => DebugEmissionKind::NoDebug,
DebugInfo::LineDirectivesOnly => DebugEmissionKind::DebugDirectivesOnly,
DebugInfo::LineTablesOnly => DebugEmissionKind::LineTablesOnly,
DebugInfo::Limited | DebugInfo::Full => DebugEmissionKind::FullDebug,
2019-01-22 21:01:14 +00:00
}
}
}
/// LLVMRustDebugNameTableKind
#[derive(Clone, Copy)]
#[repr(C)]
pub enum DebugNameTableKind {
Default,
Gnu,
None,
}
}
// These values **must** match with LLVMRustAllocKindFlags
bitflags! {
#[repr(transparent)]
#[derive(Default)]
pub struct AllocKindFlags : u64 {
const Unknown = 0;
const Alloc = 1;
const Realloc = 1 << 1;
const Free = 1 << 2;
const Uninitialized = 1 << 3;
const Zeroed = 1 << 4;
const Aligned = 1 << 5;
}
}
unsafe extern "C" {
pub type ModuleBuffer;
}
pub type SelfProfileBeforePassCallback =
unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char);
pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void);
pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void;
unsafe extern "C" {
2016-10-22 13:07:35 +00:00
// Create and destroy contexts.
pub(crate) fn LLVMContextDispose(C: &'static mut Context);
pub(crate) fn LLVMGetMDKindIDInContext(
C: &Context,
Name: *const c_char,
SLen: c_uint,
) -> c_uint;
// Create modules.
pub(crate) fn LLVMModuleCreateWithNameInContext(
ModuleID: *const c_char,
C: &Context,
) -> &Module;
pub(crate) fn LLVMCloneModule(M: &Module) -> &Module;
/// Data layout. See Module::getDataLayout.
pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
pub(crate) fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
/// See Module::setModuleInlineAsm.
pub(crate) fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t);
2016-10-22 13:07:35 +00:00
// Operations on integer types
pub(crate) fn LLVMInt1TypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMInt8TypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMInt16TypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMInt32TypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMInt64TypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type;
pub(crate) fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint;
2016-10-22 13:07:35 +00:00
// Operations on real types
pub(crate) fn LLVMHalfTypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMFloatTypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMFP128TypeInContext(C: &Context) -> &Type;
2016-10-22 13:07:35 +00:00
// Operations on function types
pub(crate) fn LLVMFunctionType<'a>(
ReturnType: &'a Type,
ParamTypes: *const &'a Type,
ParamCount: c_uint,
IsVarArg: Bool,
) -> &'a Type;
pub(crate) fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint;
pub(crate) fn LLVMGetParamTypes<'a>(FunctionTy: &'a Type, Dest: *mut &'a Type);
2016-10-22 13:07:35 +00:00
// Operations on struct types
pub(crate) fn LLVMStructTypeInContext<'a>(
C: &'a Context,
ElementTypes: *const &'a Type,
ElementCount: c_uint,
Packed: Bool,
) -> &'a Type;
2016-10-22 13:07:35 +00:00
// Operations on array, pointer, and vector types (sequence types)
pub(crate) fn LLVMPointerTypeInContext(C: &Context, AddressSpace: c_uint) -> &Type;
pub(crate) fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
pub(crate) fn LLVMGetElementType(Ty: &Type) -> &Type;
pub(crate) fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint;
2016-10-22 13:07:35 +00:00
// Operations on other types
pub(crate) fn LLVMVoidTypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMTokenTypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMMetadataTypeInContext(C: &Context) -> &Type;
2016-10-22 13:07:35 +00:00
// Operations on all values
pub(crate) fn LLVMIsUndef(Val: &Value) -> Bool;
pub(crate) fn LLVMTypeOf(Val: &Value) -> &Type;
pub(crate) fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
pub(crate) fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value);
pub(crate) fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value);
pub(crate) fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
pub(crate) fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
2016-10-22 13:07:35 +00:00
// Operations on constants of any type
pub(crate) fn LLVMConstNull(Ty: &Type) -> &Value;
pub(crate) fn LLVMGetUndef(Ty: &Type) -> &Value;
pub(crate) fn LLVMGetPoison(Ty: &Type) -> &Value;
2016-10-22 13:07:35 +00:00
// Operations on metadata
pub(crate) fn LLVMMDStringInContext2(
C: &Context,
Str: *const c_char,
SLen: size_t,
) -> &Metadata;
pub(crate) fn LLVMMDNodeInContext2<'a>(
Add metadata generation for vtables when using VFE This adds the typeid and `vcall_visibility` metadata to vtables when the -Cvirtual-function-elimination flag is set. The typeid is generated in the same way as for the `llvm.type.checked.load` intrinsic from the trait_ref. The offset that is added to the typeid is always 0. This is because LLVM assumes that vtables are constructed according to the definition in the Itanium ABI. This includes an "address point" of the vtable. In C++ this is the offset in the vtable where information for RTTI is placed. Since there is no RTTI information in Rust's vtables, this "address point" is always 0. This "address point" in combination with the offset passed to the `llvm.type.checked.load` intrinsic determines the final function that should be loaded from the vtable in the `WholeProgramDevirtualization` pass in LLVM. That's why the `llvm.type.checked.load` intrinsics are generated with the typeid of the trait, rather than with that of the function that is called. This matches what `clang` does for C++. The vcall_visibility metadata depends on three factors: 1. LTO level: Currently this is always fat LTO, because LLVM only supports this optimization with fat LTO. 2. Visibility of the trait: If the trait is publicly visible, VFE can only act on its vtables after linking. 3. Number of CGUs: if there is more than one CGU, also vtables with restricted visibility could be seen outside of the CGU, so VFE can only act on them after linking. To reflect this, there are three visibility levels: Public, LinkageUnit, and TranslationUnit.
2022-04-21 13:02:54 +00:00
C: &'a Context,
Vals: *const &'a Metadata,
Count: size_t,
) -> &'a Metadata;
pub(crate) fn LLVMAddNamedMetadataOperand<'a>(
M: &'a Module,
Name: *const c_char,
Val: &'a Value,
);
2016-10-22 13:07:35 +00:00
// Operations on scalar constants
pub(crate) fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
pub(crate) fn LLVMConstIntOfArbitraryPrecision(
IntTy: &Type,
Wn: c_uint,
Ws: *const u64,
) -> &Value;
pub(crate) fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
2016-10-22 13:07:35 +00:00
// Operations on composite constants
pub(crate) fn LLVMConstArray2<'a>(
ElementTy: &'a Type,
ConstantVals: *const &'a Value,
Length: u64,
) -> &'a Value;
pub(crate) fn LLVMArrayType2(ElementType: &Type, ElementCount: u64) -> &Type;
pub(crate) fn LLVMConstStringInContext2(
C: &Context,
Str: *const c_char,
Length: size_t,
DontNullTerminate: Bool,
) -> &Value;
pub(crate) fn LLVMConstStructInContext<'a>(
C: &'a Context,
ConstantVals: *const &'a Value,
Count: c_uint,
Packed: Bool,
) -> &'a Value;
pub(crate) fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value;
2016-10-22 13:07:35 +00:00
// Constant expressions
pub(crate) fn LLVMConstInBoundsGEP2<'a>(
ty: &'a Type,
ConstantVal: &'a Value,
ConstantIndices: *const &'a Value,
2018-01-16 08:31:48 +00:00
NumIndices: c_uint,
) -> &'a Value;
pub(crate) fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub(crate) fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub(crate) fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub(crate) fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub(crate) fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>;
pub(crate) fn LLVMGetConstOpcode(ConstantVal: &Value) -> Opcode;
pub(crate) fn LLVMIsAConstantExpr(Val: &Value) -> Option<&Value>;
2016-10-22 13:07:35 +00:00
// Operations on global variables, functions, and aliases (globals)
pub(crate) fn LLVMIsDeclaration(Global: &Value) -> Bool;
pub(crate) fn LLVMGetLinkage(Global: &Value) -> RawEnum<Linkage>;
pub(crate) fn LLVMSetLinkage(Global: &Value, RustLinkage: Linkage);
pub(crate) fn LLVMSetSection(Global: &Value, Section: *const c_char);
pub(crate) fn LLVMGetVisibility(Global: &Value) -> RawEnum<Visibility>;
pub(crate) fn LLVMSetVisibility(Global: &Value, Viz: Visibility);
pub(crate) fn LLVMGetAlignment(Global: &Value) -> c_uint;
pub(crate) fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
pub(crate) fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
pub(crate) fn LLVMGlobalGetValueType(Global: &Value) -> &Type;
2016-10-22 13:07:35 +00:00
// Operations on global variables
pub(crate) fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
pub(crate) fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
pub(crate) fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
pub(crate) fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
pub(crate) fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
pub(crate) fn LLVMDeleteGlobal(GlobalVar: &Value);
pub(crate) fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
pub(crate) fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value);
pub(crate) fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
pub(crate) fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
pub(crate) fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
// Operations on attributes
pub(crate) fn LLVMCreateStringAttribute(
C: &Context,
Name: *const c_char,
NameLen: c_uint,
Value: *const c_char,
ValueLen: c_uint,
) -> &Attribute;
2016-10-22 13:07:35 +00:00
// Operations on functions
pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
2016-10-22 13:07:35 +00:00
// Operations on parameters
pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>;
pub(crate) fn LLVMCountParams(Fn: &Value) -> c_uint;
pub(crate) fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value;
2016-10-22 13:07:35 +00:00
// Operations on basic blocks
pub(crate) fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value;
pub(crate) fn LLVMAppendBasicBlockInContext<'a>(
C: &'a Context,
Fn: &'a Value,
Name: *const c_char,
) -> &'a BasicBlock;
2016-10-22 13:07:35 +00:00
// Operations on instructions
pub(crate) fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>;
pub(crate) fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
pub(crate) fn LLVMGetOperand(Val: &Value, Index: c_uint) -> Option<&Value>;
2016-10-22 13:07:35 +00:00
// Operations on call sites
pub(crate) fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
2016-10-22 13:07:35 +00:00
// Operations on load/store instructions (only)
pub(crate) fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
2016-10-22 13:07:35 +00:00
// Operations on phi nodes
pub(crate) fn LLVMAddIncoming<'a>(
PhiNode: &'a Value,
IncomingValues: *const &'a Value,
IncomingBlocks: *const &'a BasicBlock,
Count: c_uint,
);
2016-10-22 13:07:35 +00:00
// Instruction builders
pub(crate) fn LLVMCreateBuilderInContext(C: &Context) -> &mut Builder<'_>;
pub(crate) fn LLVMPositionBuilderAtEnd<'a>(Builder: &Builder<'a>, Block: &'a BasicBlock);
pub(crate) fn LLVMGetInsertBlock<'a>(Builder: &Builder<'a>) -> &'a BasicBlock;
pub(crate) fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>);
2016-10-22 13:07:35 +00:00
// Metadata
pub(crate) fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: *const Metadata);
pub(crate) fn LLVMGetCurrentDebugLocation2<'a>(Builder: &Builder<'a>) -> Option<&'a Metadata>;
2016-10-22 13:07:35 +00:00
// Terminators
pub(crate) fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value;
pub(crate) fn LLVMBuildRet<'a>(B: &Builder<'a>, V: &'a Value) -> &'a Value;
pub(crate) fn LLVMBuildBr<'a>(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value;
pub(crate) fn LLVMBuildCondBr<'a>(
B: &Builder<'a>,
If: &'a Value,
Then: &'a BasicBlock,
Else: &'a BasicBlock,
) -> &'a Value;
pub(crate) fn LLVMBuildSwitch<'a>(
B: &Builder<'a>,
V: &'a Value,
Else: &'a BasicBlock,
NumCases: c_uint,
) -> &'a Value;
pub(crate) fn LLVMBuildLandingPad<'a>(
B: &Builder<'a>,
Ty: &'a Type,
PersFn: Option<&'a Value>,
NumClauses: c_uint,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value;
pub(crate) fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value;
pub(crate) fn LLVMBuildCleanupPad<'a>(
B: &Builder<'a>,
ParentPad: Option<&'a Value>,
Args: *const &'a Value,
NumArgs: c_uint,
2016-10-22 13:07:35 +00:00
Name: *const c_char,
) -> Option<&'a Value>;
pub(crate) fn LLVMBuildCleanupRet<'a>(
B: &Builder<'a>,
CleanupPad: &'a Value,
BB: Option<&'a BasicBlock>,
) -> Option<&'a Value>;
pub(crate) fn LLVMBuildCatchPad<'a>(
B: &Builder<'a>,
ParentPad: &'a Value,
Args: *const &'a Value,
NumArgs: c_uint,
2016-10-22 13:07:35 +00:00
Name: *const c_char,
) -> Option<&'a Value>;
pub(crate) fn LLVMBuildCatchRet<'a>(
B: &Builder<'a>,
CatchPad: &'a Value,
2018-07-17 15:26:58 +00:00
BB: &'a BasicBlock,
) -> Option<&'a Value>;
pub(crate) fn LLVMBuildCatchSwitch<'a>(
Builder: &Builder<'a>,
ParentPad: Option<&'a Value>,
UnwindBB: Option<&'a BasicBlock>,
NumHandlers: c_uint,
2016-10-22 13:07:35 +00:00
Name: *const c_char,
) -> Option<&'a Value>;
pub(crate) fn LLVMAddHandler<'a>(CatchSwitch: &'a Value, Dest: &'a BasicBlock);
pub(crate) fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value);
2016-10-22 13:07:35 +00:00
// Add a case to the switch instruction
pub(crate) fn LLVMAddCase<'a>(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock);
2016-10-22 13:07:35 +00:00
// Add a clause to the landing pad instruction
pub(crate) fn LLVMAddClause<'a>(LandingPad: &'a Value, ClauseVal: &'a Value);
2016-10-22 13:07:35 +00:00
// Set the cleanup on a landing pad instruction
pub(crate) fn LLVMSetCleanup(LandingPad: &Value, Val: Bool);
2016-10-22 13:07:35 +00:00
// Arithmetic
pub(crate) fn LLVMBuildAdd<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFAdd<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildSub<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFSub<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildMul<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFMul<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildUDiv<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildExactUDiv<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildSDiv<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildExactSDiv<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFDiv<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildURem<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildSRem<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFRem<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildShl<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildLShr<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildAShr<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNSWAdd<'a>(
2019-06-03 10:59:17 +00:00
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNUWAdd<'a>(
2019-06-03 10:59:17 +00:00
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNSWSub<'a>(
2019-06-03 10:59:17 +00:00
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNUWSub<'a>(
2019-06-03 10:59:17 +00:00
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNSWMul<'a>(
2019-06-03 10:59:17 +00:00
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNUWMul<'a>(
2019-06-03 10:59:17 +00:00
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildAnd<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildOr<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildXor<'a>(
B: &Builder<'a>,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char)
-> &'a Value;
pub(crate) fn LLVMBuildFNeg<'a>(
B: &Builder<'a>,
V: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char)
-> &'a Value;
// Extra flags on arithmetic
pub(crate) fn LLVMSetIsDisjoint(Instr: &Value, IsDisjoint: Bool);
pub(crate) fn LLVMSetNUW(ArithInst: &Value, HasNUW: Bool);
pub(crate) fn LLVMSetNSW(ArithInst: &Value, HasNSW: Bool);
2016-10-22 13:07:35 +00:00
// Memory
pub(crate) fn LLVMBuildAlloca<'a>(
B: &Builder<'a>,
Ty: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildArrayAlloca<'a>(
2018-05-28 15:07:23 +00:00
B: &Builder<'a>,
Ty: &'a Type,
Val: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildLoad2<'a>(
B: &Builder<'a>,
Ty: &'a Type,
PointerVal: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildStore<'a>(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
pub(crate) fn LLVMBuildGEP2<'a>(
B: &Builder<'a>,
Ty: &'a Type,
Pointer: &'a Value,
Indices: *const &'a Value,
NumIndices: c_uint,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildInBoundsGEP2<'a>(
B: &Builder<'a>,
Ty: &'a Type,
Pointer: &'a Value,
Indices: *const &'a Value,
NumIndices: c_uint,
Name: *const c_char,
) -> &'a Value;
2016-10-22 13:07:35 +00:00
// Casts
pub(crate) fn LLVMBuildTrunc<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildZExt<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildSExt<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFPToUI<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFPToSI<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildUIToFP<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildSIToFP<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFPTrunc<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFPExt<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildPtrToInt<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildIntToPtr<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildBitCast<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildPointerCast<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildIntCast2<'a>(
B: &Builder<'a>,
Val: &'a Value,
DestTy: &'a Type,
2023-04-08 09:15:26 +00:00
IsSigned: Bool,
Name: *const c_char,
) -> &'a Value;
2016-10-22 13:07:35 +00:00
// Comparisons
pub(crate) fn LLVMBuildICmp<'a>(
B: &Builder<'a>,
Op: c_uint,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildFCmp<'a>(
B: &Builder<'a>,
Op: c_uint,
LHS: &'a Value,
RHS: &'a Value,
Name: *const c_char,
) -> &'a Value;
2016-10-22 13:07:35 +00:00
// Miscellaneous instructions
pub(crate) fn LLVMBuildPhi<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char)
-> &'a Value;
pub(crate) fn LLVMBuildSelect<'a>(
B: &Builder<'a>,
If: &'a Value,
Then: &'a Value,
Else: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildVAArg<'a>(
B: &Builder<'a>,
list: &'a Value,
Ty: &'a Type,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildExtractElement<'a>(
B: &Builder<'a>,
VecVal: &'a Value,
Index: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildInsertElement<'a>(
B: &Builder<'a>,
VecVal: &'a Value,
EltVal: &'a Value,
Index: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildShuffleVector<'a>(
B: &Builder<'a>,
V1: &'a Value,
V2: &'a Value,
Mask: &'a Value,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildExtractValue<'a>(
B: &Builder<'a>,
AggVal: &'a Value,
Index: c_uint,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildInsertValue<'a>(
B: &Builder<'a>,
AggVal: &'a Value,
EltVal: &'a Value,
Index: c_uint,
Name: *const c_char,
) -> &'a Value;
2019-12-22 22:42:04 +00:00
// Atomic Operations
pub(crate) fn LLVMBuildAtomicCmpXchg<'a>(
B: &Builder<'a>,
LHS: &'a Value,
CMP: &'a Value,
RHS: &'a Value,
Order: AtomicOrdering,
FailureOrder: AtomicOrdering,
SingleThreaded: Bool,
) -> &'a Value;
pub(crate) fn LLVMSetWeak(CmpXchgInst: &Value, IsWeak: Bool);
pub(crate) fn LLVMBuildAtomicRMW<'a>(
B: &Builder<'a>,
Op: AtomicRmwBinOp,
LHS: &'a Value,
RHS: &'a Value,
Order: AtomicOrdering,
SingleThreaded: Bool,
) -> &'a Value;
pub(crate) fn LLVMBuildFence<'a>(
B: &Builder<'a>,
Order: AtomicOrdering,
SingleThreaded: Bool,
Name: *const c_char,
) -> &'a Value;
/// Writes a module to the specified path. Returns 0 on success.
pub(crate) fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
/// Creates a legacy pass manager -- only used for final codegen.
pub(crate) fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
pub(crate) fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>);
pub(crate) fn LLVMGetHostCPUFeatures() -> *mut c_char;
pub(crate) fn LLVMDisposeMessage(message: *mut c_char);
pub(crate) fn LLVMIsMultithreaded() -> Bool;
pub(crate) fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type;
pub(crate) fn LLVMStructSetBody<'a>(
StructTy: &'a Type,
ElementTypes: *const &'a Type,
ElementCount: c_uint,
Packed: Bool,
);
pub(crate) fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
pub(crate) fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
pub(crate) fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>;
pub(crate) fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat;
pub(crate) fn LLVMSetComdat(V: &Value, C: &Comdat);
2024-10-28 06:25:40 +00:00
pub(crate) fn LLVMCreateOperandBundle(
Tag: *const c_char,
TagLen: size_t,
Args: *const &'_ Value,
NumArgs: c_uint,
) -> *mut OperandBundle<'_>;
pub(crate) fn LLVMDisposeOperandBundle(Bundle: ptr::NonNull<OperandBundle<'_>>);
pub(crate) fn LLVMBuildCallWithOperandBundles<'a>(
B: &Builder<'a>,
Ty: &'a Type,
Fn: &'a Value,
Args: *const &'a Value,
NumArgs: c_uint,
Bundles: *const &OperandBundle<'a>,
NumBundles: c_uint,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildInvokeWithOperandBundles<'a>(
B: &Builder<'a>,
Ty: &'a Type,
Fn: &'a Value,
Args: *const &'a Value,
NumArgs: c_uint,
Then: &'a BasicBlock,
Catch: &'a BasicBlock,
Bundles: *const &OperandBundle<'a>,
NumBundles: c_uint,
Name: *const c_char,
) -> &'a Value;
pub(crate) fn LLVMBuildCallBr<'a>(
B: &Builder<'a>,
Ty: &'a Type,
Fn: &'a Value,
DefaultDest: &'a BasicBlock,
IndirectDests: *const &'a BasicBlock,
NumIndirectDests: c_uint,
Args: *const &'a Value,
NumArgs: c_uint,
Bundles: *const &OperandBundle<'a>,
NumBundles: c_uint,
Name: *const c_char,
) -> &'a Value;
}
// FFI bindings for `DIBuilder` functions in the LLVM-C API.
// Try to keep these in the same order as in `llvm/include/llvm-c/DebugInfo.h`.
//
// FIXME(#134001): Audit all `Option` parameters, especially in lists, to check
// that they really are nullable on the C/C++ side. LLVM doesn't appear to
// actually document which ones are nullable.
unsafe extern "C" {
pub(crate) fn LLVMCreateDIBuilder<'ll>(M: &'ll Module) -> *mut DIBuilder<'ll>;
pub(crate) fn LLVMDisposeDIBuilder<'ll>(Builder: ptr::NonNull<DIBuilder<'ll>>);
2025-02-01 02:38:12 +00:00
pub(crate) fn LLVMDIBuilderFinalize<'ll>(Builder: &DIBuilder<'ll>);
2025-02-01 02:43:30 +00:00
pub(crate) fn LLVMDIBuilderCreateNameSpace<'ll>(
Builder: &DIBuilder<'ll>,
ParentScope: Option<&'ll Metadata>,
Name: *const c_uchar,
NameLen: size_t,
ExportSymbols: llvm::Bool,
) -> &'ll Metadata;
2025-02-01 02:50:01 +00:00
pub(crate) fn LLVMDIBuilderCreateLexicalBlock<'ll>(
Builder: &DIBuilder<'ll>,
Scope: &'ll Metadata,
File: &'ll Metadata,
Line: c_uint,
Column: c_uint,
) -> &'ll Metadata;
pub(crate) fn LLVMDIBuilderCreateLexicalBlockFile<'ll>(
Builder: &DIBuilder<'ll>,
Scope: &'ll Metadata,
File: &'ll Metadata,
Discriminator: c_uint, // (optional "DWARF path discriminator"; default is 0)
) -> &'ll Metadata;
pub(crate) fn LLVMDIBuilderCreateDebugLocation<'ll>(
Ctx: &'ll Context,
Line: c_uint,
Column: c_uint,
Scope: &'ll Metadata,
InlinedAt: Option<&'ll Metadata>,
) -> &'ll Metadata;
}
#[link(name = "llvm-wrapper", kind = "static")]
unsafe extern "C" {
pub(crate) fn LLVMRustInstallErrorHandlers();
pub(crate) fn LLVMRustDisableSystemDialogsOnCrash();
// Create and destroy contexts.
pub(crate) fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;
/// See llvm::LLVMTypeKind::getTypeID.
pub(crate) fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
// Operations on all values
pub(crate) fn LLVMRustGlobalAddMetadata<'a>(
Val: &'a Value,
KindID: c_uint,
Metadata: &'a Metadata,
);
pub(crate) fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool;
// Operations on scalar constants
pub(crate) fn LLVMRustConstIntGetZExtValue(ConstantVal: &ConstantInt, Value: &mut u64) -> bool;
pub(crate) fn LLVMRustConstInt128Get(
ConstantVal: &ConstantInt,
SExt: bool,
high: &mut u64,
low: &mut u64,
) -> bool;
// Operations on global variables, functions, and aliases (globals)
pub(crate) fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
// Operations on global variables
pub(crate) fn LLVMRustGetOrInsertGlobal<'a>(
M: &'a Module,
Name: *const c_char,
NameLen: size_t,
T: &'a Type,
) -> &'a Value;
pub(crate) fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value;
pub(crate) fn LLVMRustGetNamedValue(
M: &Module,
Name: *const c_char,
NameLen: size_t,
) -> Option<&Value>;
// Operations on attributes
pub(crate) fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute;
pub(crate) fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute;
pub(crate) fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute;
pub(crate) fn LLVMRustCreateDereferenceableOrNullAttr(C: &Context, bytes: u64) -> &Attribute;
pub(crate) fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
pub(crate) fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
pub(crate) fn LLVMRustCreateElementTypeAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute;
pub(crate) fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute;
pub(crate) fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute;
pub(crate) fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute;
pub(crate) fn LLVMRustCreateMemoryEffectsAttr(
C: &Context,
effects: MemoryEffects,
) -> &Attribute;
pub(crate) fn LLVMRustCreateRangeAttribute(
C: &Context,
num_bits: c_uint,
lower_words: *const u64,
upper_words: *const u64,
) -> &Attribute;
// Operations on functions
pub(crate) fn LLVMRustGetOrInsertFunction<'a>(
M: &'a Module,
Name: *const c_char,
NameLen: size_t,
FunctionTy: &'a Type,
) -> &'a Value;
pub(crate) fn LLVMRustAddFunctionAttributes<'a>(
Fn: &'a Value,
index: c_uint,
Attrs: *const &'a Attribute,
AttrsLen: size_t,
);
// Operations on call sites
pub(crate) fn LLVMRustAddCallSiteAttributes<'a>(
Instr: &'a Value,
index: c_uint,
Attrs: *const &'a Attribute,
AttrsLen: size_t,
);
pub(crate) fn LLVMRustSetFastMath(Instr: &Value);
pub(crate) fn LLVMRustSetAlgebraicMath(Instr: &Value);
pub(crate) fn LLVMRustSetAllowReassoc(Instr: &Value);
// Miscellaneous instructions
pub(crate) fn LLVMRustBuildMemCpy<'a>(
B: &Builder<'a>,
Dst: &'a Value,
DstAlign: c_uint,
Src: &'a Value,
SrcAlign: c_uint,
Size: &'a Value,
IsVolatile: bool,
) -> &'a Value;
pub(crate) fn LLVMRustBuildMemMove<'a>(
B: &Builder<'a>,
Dst: &'a Value,
DstAlign: c_uint,
Src: &'a Value,
SrcAlign: c_uint,
Size: &'a Value,
IsVolatile: bool,
) -> &'a Value;
pub(crate) fn LLVMRustBuildMemSet<'a>(
B: &Builder<'a>,
Dst: &'a Value,
DstAlign: c_uint,
Val: &'a Value,
Size: &'a Value,
IsVolatile: bool,
) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceFAdd<'a>(
B: &Builder<'a>,
Acc: &'a Value,
Src: &'a Value,
) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceFMul<'a>(
B: &Builder<'a>,
Acc: &'a Value,
Src: &'a Value,
) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceAdd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceMul<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceAnd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceOr<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceXor<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceMin<'a>(
B: &Builder<'a>,
Src: &'a Value,
IsSigned: bool,
) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceMax<'a>(
B: &Builder<'a>,
Src: &'a Value,
IsSigned: bool,
) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceFMin<'a>(
B: &Builder<'a>,
Src: &'a Value,
IsNaN: bool,
) -> &'a Value;
pub(crate) fn LLVMRustBuildVectorReduceFMax<'a>(
B: &Builder<'a>,
Src: &'a Value,
IsNaN: bool,
) -> &'a Value;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustBuildMinNum<'a>(
B: &Builder<'a>,
LHS: &'a Value,
LHS: &'a Value,
) -> &'a Value;
pub(crate) fn LLVMRustBuildMaxNum<'a>(
B: &Builder<'a>,
LHS: &'a Value,
LHS: &'a Value,
) -> &'a Value;
2019-12-22 22:42:04 +00:00
2016-10-22 13:07:35 +00:00
// Atomic Operations
pub(crate) fn LLVMRustBuildAtomicLoad<'a>(
B: &Builder<'a>,
ElementType: &'a Type,
PointerVal: &'a Value,
Name: *const c_char,
Order: AtomicOrdering,
) -> &'a Value;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustBuildAtomicStore<'a>(
B: &Builder<'a>,
Val: &'a Value,
Ptr: &'a Value,
Order: AtomicOrdering,
) -> &'a Value;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustTimeTraceProfilerInitialize();
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustTimeTraceProfilerFinishThread();
pub(crate) fn LLVMRustTimeTraceProfilerFinish(FileName: *const c_char);
/// Returns a string describing the last error caused by an LLVMRust* call.
pub(crate) fn LLVMRustGetLastError() -> *const c_char;
/// Prints the timing information collected by `-Ztime-llvm-passes`.
pub(crate) fn LLVMRustPrintPassTimings(OutStr: &RustString);
/// Prints the statistics collected by `-Zprint-codegen-stats`.
pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString);
/// Prepares inline assembly.
pub(crate) fn LLVMRustInlineAsm(
Ty: &Type,
AsmString: *const c_char,
AsmStringLen: size_t,
Constraints: *const c_char,
ConstraintsLen: size_t,
SideEffects: Bool,
AlignStack: Bool,
2016-08-02 21:25:19 +00:00
Dialect: AsmDialect,
CanThrow: Bool,
) -> &Value;
pub(crate) fn LLVMRustInlineAsmVerify(
Ty: &Type,
Constraints: *const c_char,
ConstraintsLen: size_t,
) -> bool;
pub(crate) fn LLVMRustCoverageWriteFilenamesToBuffer(
Filenames: *const *const c_char,
FilenamesLen: size_t,
Lengths: *const size_t,
LengthsLen: size_t,
BufferOut: &RustString,
);
pub(crate) fn LLVMRustCoverageWriteFunctionMappingsToBuffer(
VirtualFileMappingIDs: *const c_uint,
NumVirtualFileMappingIDs: size_t,
Expressions: *const crate::coverageinfo::ffi::CounterExpression,
NumExpressions: size_t,
CodeRegions: *const crate::coverageinfo::ffi::CodeRegion,
NumCodeRegions: size_t,
BranchRegions: *const crate::coverageinfo::ffi::BranchRegion,
NumBranchRegions: size_t,
MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion,
NumMCDCBranchRegions: size_t,
MCDCDecisionRegions: *const crate::coverageinfo::ffi::MCDCDecisionRegion,
NumMCDCDecisionRegions: size_t,
BufferOut: &RustString,
);
pub(crate) fn LLVMRustCoverageCreatePGOFuncNameVar(
F: &Value,
FuncName: *const c_char,
FuncNameLen: size_t,
) -> &Value;
pub(crate) fn LLVMRustCoverageHashBytes(Bytes: *const c_char, NumBytes: size_t) -> u64;
pub(crate) fn LLVMRustCoverageWriteCovmapSectionNameToString(M: &Module, OutStr: &RustString);
pub(crate) fn LLVMRustCoverageWriteCovfunSectionNameToString(M: &Module, OutStr: &RustString);
pub(crate) fn LLVMRustCoverageWriteCovmapVarNameToString(OutStr: &RustString);
pub(crate) fn LLVMRustCoverageMappingVersion() -> u32;
pub(crate) fn LLVMRustDebugMetadataVersion() -> u32;
pub(crate) fn LLVMRustVersionMajor() -> u32;
pub(crate) fn LLVMRustVersionMinor() -> u32;
pub(crate) fn LLVMRustVersionPatch() -> u32;
/// Add LLVM module flags.
///
/// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
/// "compatible" means depends on the merge behaviors involved.
pub(crate) fn LLVMRustAddModuleFlagU32(
M: &Module,
MergeBehavior: ModuleFlagMergeBehavior,
Name: *const c_char,
NameLen: size_t,
Value: u32,
);
pub(crate) fn LLVMRustAddModuleFlagString(
M: &Module,
MergeBehavior: ModuleFlagMergeBehavior,
Name: *const c_char,
NameLen: size_t,
Value: *const c_char,
ValueLen: size_t,
);
pub(crate) fn LLVMRustDIBuilderCreateCompileUnit<'a>(
Builder: &DIBuilder<'a>,
Lang: c_uint,
File: &'a DIFile,
Producer: *const c_char,
ProducerLen: size_t,
isOptimized: bool,
Flags: *const c_char,
RuntimeVer: c_uint,
2019-01-22 21:01:14 +00:00
SplitName: *const c_char,
SplitNameLen: size_t,
2019-01-22 21:01:14 +00:00
kind: DebugEmissionKind,
DWOId: u64,
SplitDebugInlining: bool,
DebugNameTableKind: DebugNameTableKind,
) -> &'a DIDescriptor;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateFile<'a>(
Builder: &DIBuilder<'a>,
Filename: *const c_char,
FilenameLen: size_t,
Directory: *const c_char,
DirectoryLen: size_t,
CSKind: ChecksumKind,
Checksum: *const c_char,
ChecksumLen: size_t,
Source: *const c_char,
SourceLen: size_t,
) -> &'a DIFile;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateSubroutineType<'a>(
Builder: &DIBuilder<'a>,
ParameterTypes: &'a DIArray,
) -> &'a DICompositeType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateFunction<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIDescriptor,
Name: *const c_char,
NameLen: size_t,
LinkageName: *const c_char,
LinkageNameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
Ty: &'a DIType,
ScopeLine: c_uint,
Flags: DIFlags,
SPFlags: DISPFlags,
MaybeFn: Option<&'a Value>,
TParam: &'a DIArray,
Decl: Option<&'a DIDescriptor>,
) -> &'a DISubprogram;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateMethod<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIDescriptor,
Name: *const c_char,
NameLen: size_t,
LinkageName: *const c_char,
LinkageNameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
Ty: &'a DIType,
Flags: DIFlags,
SPFlags: DISPFlags,
TParam: &'a DIArray,
) -> &'a DISubprogram;
pub(crate) fn LLVMRustDIBuilderCreateBasicType<'a>(
Builder: &DIBuilder<'a>,
Name: *const c_char,
NameLen: size_t,
SizeInBits: u64,
Encoding: c_uint,
) -> &'a DIBasicType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateTypedef<'a>(
Builder: &DIBuilder<'a>,
Type: &'a DIBasicType,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
Scope: Option<&'a DIScope>,
) -> &'a DIDerivedType;
pub(crate) fn LLVMRustDIBuilderCreatePointerType<'a>(
Builder: &DIBuilder<'a>,
PointeeTy: &'a DIType,
2016-10-22 13:07:35 +00:00
SizeInBits: u64,
AlignInBits: u32,
AddressSpace: c_uint,
2016-10-22 13:07:35 +00:00
Name: *const c_char,
NameLen: size_t,
) -> &'a DIDerivedType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateStructType<'a>(
Builder: &DIBuilder<'a>,
Scope: Option<&'a DIDescriptor>,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNumber: c_uint,
SizeInBits: u64,
AlignInBits: u32,
Flags: DIFlags,
DerivedFrom: Option<&'a DIType>,
Elements: &'a DIArray,
RunTimeLang: c_uint,
VTableHolder: Option<&'a DIType>,
UniqueId: *const c_char,
UniqueIdLen: size_t,
) -> &'a DICompositeType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateMemberType<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIDescriptor,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
SizeInBits: u64,
AlignInBits: u32,
OffsetInBits: u64,
Flags: DIFlags,
Ty: &'a DIType,
) -> &'a DIDerivedType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateVariantMemberType<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIScope,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNumber: c_uint,
SizeInBits: u64,
AlignInBits: u32,
OffsetInBits: u64,
Discriminant: Option<&'a Value>,
Flags: DIFlags,
Ty: &'a DIType,
) -> &'a DIType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateStaticMemberType<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIDescriptor,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
Ty: &'a DIType,
Flags: DIFlags,
val: Option<&'a Value>,
AlignInBits: u32,
) -> &'a DIDerivedType;
pub(crate) fn LLVMRustDIBuilderCreateQualifiedType<'a>(
Builder: &DIBuilder<'a>,
Tag: c_uint,
Type: &'a DIType,
) -> &'a DIDerivedType;
pub(crate) fn LLVMRustDIBuilderCreateStaticVariable<'a>(
Builder: &DIBuilder<'a>,
Context: Option<&'a DIScope>,
Name: *const c_char,
NameLen: size_t,
LinkageName: *const c_char,
LinkageNameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
Ty: &'a DIType,
isLocalToUnit: bool,
Val: &'a Value,
Decl: Option<&'a DIDescriptor>,
AlignInBits: u32,
2018-09-14 16:06:45 +00:00
) -> &'a DIGlobalVariableExpression;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateVariable<'a>(
Builder: &DIBuilder<'a>,
Tag: c_uint,
Scope: &'a DIDescriptor,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
Ty: &'a DIType,
AlwaysPreserve: bool,
Flags: DIFlags,
ArgNo: c_uint,
AlignInBits: u32,
) -> &'a DIVariable;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateArrayType<'a>(
Builder: &DIBuilder<'a>,
Size: u64,
AlignInBits: u32,
Ty: &'a DIType,
Subscripts: &'a DIArray,
) -> &'a DIType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderGetOrCreateSubrange<'a>(
Builder: &DIBuilder<'a>,
Lo: i64,
Count: i64,
) -> &'a DISubrange;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderGetOrCreateArray<'a>(
Builder: &DIBuilder<'a>,
Ptr: *const Option<&'a DIDescriptor>,
Count: c_uint,
) -> &'a DIArray;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderInsertDeclareAtEnd<'a>(
Builder: &DIBuilder<'a>,
Val: &'a Value,
VarInfo: &'a DIVariable,
AddrOps: *const u64,
AddrOpsCount: c_uint,
DL: &'a DILocation,
InsertAtEnd: &'a BasicBlock,
);
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateEnumerator<'a>(
Builder: &DIBuilder<'a>,
Name: *const c_char,
NameLen: size_t,
Value: *const u64,
SizeInBits: c_uint,
IsUnsigned: bool,
) -> &'a DIEnumerator;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateEnumerationType<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIScope,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNumber: c_uint,
SizeInBits: u64,
AlignInBits: u32,
Elements: &'a DIArray,
ClassType: &'a DIType,
IsScoped: bool,
) -> &'a DIType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateUnionType<'a>(
Builder: &DIBuilder<'a>,
Scope: Option<&'a DIScope>,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNumber: c_uint,
SizeInBits: u64,
AlignInBits: u32,
Flags: DIFlags,
Elements: Option<&'a DIArray>,
RunTimeLang: c_uint,
UniqueId: *const c_char,
UniqueIdLen: size_t,
) -> &'a DIType;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDIBuilderCreateVariantPart<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIScope,
Name: *const c_char,
NameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
SizeInBits: u64,
AlignInBits: u32,
Flags: DIFlags,
Discriminator: Option<&'a DIDerivedType>,
Elements: &'a DIArray,
UniqueId: *const c_char,
UniqueIdLen: size_t,
) -> &'a DIDerivedType;
pub(crate) fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>(
Builder: &DIBuilder<'a>,
Scope: Option<&'a DIScope>,
Name: *const c_char,
NameLen: size_t,
Ty: &'a DIType,
) -> &'a DITemplateTypeParameter;
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDICompositeTypeReplaceArrays<'a>(
Builder: &DIBuilder<'a>,
CompositeType: &'a DIType,
Elements: Option<&'a DIArray>,
Params: Option<&'a DIArray>,
);
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
Location: &'a DILocation,
BD: c_uint,
) -> Option<&'a DILocation>;
pub(crate) fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString);
pub(crate) fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
pub(crate) fn LLVMRustGetTargetFeature(
T: &TargetMachine,
Index: size_t,
Feature: &mut *const c_char,
Desc: &mut *const c_char,
);
2016-08-06 05:50:48 +00:00
pub(crate) fn LLVMRustGetHostCPUName(LenOut: &mut size_t) -> *const u8;
// This function makes copies of pointed to data, so the data's lifetime may end after this
// function returns.
pub(crate) fn LLVMRustCreateTargetMachine(
Triple: *const c_char,
CPU: *const c_char,
Features: *const c_char,
Abi: *const c_char,
Model: CodeModel,
Reloc: RelocModel,
Level: CodeGenOptLevel,
FloatABIType: FloatAbi,
FunctionSections: bool,
DataSections: bool,
UniqueSectionNames: bool,
std: Add a new wasm32-unknown-unknown target This commit adds a new target to the compiler: wasm32-unknown-unknown. This target is a reimagining of what it looks like to generate WebAssembly code from Rust. Instead of using Emscripten which can bring with it a weighty runtime this instead is a target which uses only the LLVM backend for WebAssembly and a "custom linker" for now which will hopefully one day be direct calls to lld. Notable features of this target include: * There is zero runtime footprint. The target assumes nothing exists other than the wasm32 instruction set. * There is zero toolchain footprint beyond adding the target. No custom linker is needed, rustc contains everything. * Very small wasm modules can be generated directly from Rust code using this target. * Most of the standard library is stubbed out to return an error, but anything related to allocation works (aka `HashMap`, `Vec`, etc). * Naturally, any `#[no_std]` crate should be 100% compatible with this new target. This target is currently somewhat janky due to how linking works. The "linking" is currently unconditional whole program LTO (aka LLVM is being used as a linker). Naturally that means compiling programs is pretty slow! Eventually though this target should have a linker. This target is also intended to be quite experimental. I'm hoping that this can act as a catalyst for further experimentation in Rust with WebAssembly. Breaking changes are very likely to land to this target, so it's not recommended to rely on it in any critical capacity yet. We'll let you know when it's "production ready". --- Currently testing-wise this target is looking pretty good but isn't complete. I've got almost the entire `run-pass` test suite working with this target (lots of tests ignored, but many passing as well). The `core` test suite is still getting LLVM bugs fixed to get that working and will take some time. Relatively simple programs all seem to work though! --- It's worth nothing that you may not immediately see the "smallest possible wasm module" for the input you feed to rustc. For various reasons it's very difficult to get rid of the final "bloat" in vanilla rustc (again, a real linker should fix all this). For now what you'll have to do is: cargo install --git https://github.com/alexcrichton/wasm-gc wasm-gc foo.wasm bar.wasm And then `bar.wasm` should be the smallest we can get it! --- In any case for now I'd love feedback on this, particularly on the various integration points if you've got better ideas of how to approach them!
2017-10-23 03:01:00 +00:00
TrapUnreachable: bool,
Singlethread: bool,
VerboseAsm: bool,
EmitStackSizeSection: bool,
RelaxELFRelocations: bool,
UseInitArray: bool,
SplitDwarfFile: *const c_char,
OutputObjFile: *const c_char,
DebugInfoCompression: *const c_char,
UseEmulatedTls: bool,
ArgsCstrBuff: *const c_char,
ArgsCstrBuffLen: usize,
) -> *mut TargetMachine;
pub(crate) fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
pub(crate) fn LLVMRustAddLibraryInfo<'a>(
PM: &PassManager<'a>,
M: &'a Module,
DisableSimplifyLibCalls: bool,
);
pub(crate) fn LLVMRustWriteOutputFile<'a>(
T: &'a TargetMachine,
PM: *mut PassManager<'a>,
M: &'a Module,
Output: *const c_char,
DwoOutput: *const c_char,
FileType: FileType,
VerifyIR: bool,
) -> LLVMRustResult;
pub(crate) fn LLVMRustOptimize<'a>(
M: &'a Module,
TM: &'a TargetMachine,
OptLevel: PassBuilderOptLevel,
OptStage: OptStage,
IsLinkerPluginLTO: bool,
NoPrepopulatePasses: bool,
VerifyIR: bool,
2024-08-29 10:12:31 +00:00
LintIR: bool,
UseThinLTOBuffers: bool,
MergeFunctions: bool,
UnrollLoops: bool,
SLPVectorize: bool,
LoopVectorize: bool,
DisableSimplifyLibCalls: bool,
EmitLifetimeMarkers: bool,
2025-02-08 03:27:46 +00:00
RunEnzyme: bool,
SanitizerOptions: Option<&SanitizerOptions>,
PGOGenPath: *const c_char,
PGOUsePath: *const c_char,
InstrumentCoverage: bool,
InstrProfileOutput: *const c_char,
PGOSampleUsePath: *const c_char,
DebugInfoForProfiling: bool,
llvm_selfprofiler: *mut c_void,
begin_callback: SelfProfileBeforePassCallback,
end_callback: SelfProfileAfterPassCallback,
ExtraPasses: *const c_char,
ExtraPassesLen: size_t,
LLVMPlugins: *const c_char,
LLVMPluginsLen: size_t,
) -> LLVMRustResult;
pub(crate) fn LLVMRustPrintModule(
M: &Module,
Output: *const c_char,
Demangle: extern "C" fn(*const c_char, size_t, *mut c_char, size_t) -> size_t,
) -> LLVMRustResult;
pub(crate) fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
pub(crate) fn LLVMRustPrintPasses();
pub(crate) fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
pub(crate) fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
pub(crate) fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>;
pub(crate) fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>;
pub(crate) fn LLVMRustArchiveIteratorNext<'a>(
2018-07-17 15:26:58 +00:00
AIR: &ArchiveIterator<'a>,
) -> Option<&'a mut ArchiveChild<'a>>;
pub(crate) fn LLVMRustArchiveChildName(
ACR: &ArchiveChild<'_>,
size: &mut size_t,
) -> *const c_char;
pub(crate) fn LLVMRustArchiveChildFree<'a>(ACR: &'a mut ArchiveChild<'a>);
pub(crate) fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>);
pub(crate) fn LLVMRustDestroyArchive(AR: &'static mut Archive);
pub(crate) fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
pub(crate) fn LLVMRustUnpackOptimizationDiagnostic<'a>(
DI: &'a DiagnosticInfo,
pass_name_out: &RustString,
function_out: &mut Option<&'a Value>,
loc_line_out: &mut c_uint,
loc_column_out: &mut c_uint,
loc_filename_out: &RustString,
message_out: &RustString,
);
2019-12-22 22:42:04 +00:00
pub(crate) fn LLVMRustUnpackInlineAsmDiagnostic<'a>(
DI: &'a DiagnosticInfo,
2020-06-09 13:37:59 +00:00
level_out: &mut DiagnosticLevel,
cookie_out: &mut u64,
message_out: &mut Option<&'a Twine>,
);
pub(crate) fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
pub(crate) fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
pub(crate) fn LLVMRustGetSMDiagnostic<'a>(
DI: &'a DiagnosticInfo,
cookie_out: &mut u64,
) -> &'a SMDiagnostic;
pub(crate) fn LLVMRustUnpackSMDiagnostic(
2020-05-26 19:07:59 +00:00
d: &SMDiagnostic,
message_out: &RustString,
buffer_out: &RustString,
2020-06-09 13:37:59 +00:00
level_out: &mut DiagnosticLevel,
2020-05-26 19:07:59 +00:00
loc_out: &mut c_uint,
ranges_out: *mut c_uint,
num_ranges: &mut usize,
) -> bool;
pub(crate) fn LLVMRustWriteArchive(
Dst: *const c_char,
NumMembers: size_t,
Members: *const &RustArchiveMember<'_>,
WriteSymbtab: bool,
2016-10-22 13:07:35 +00:00
Kind: ArchiveKind,
isEC: bool,
2016-10-22 13:07:35 +00:00
) -> LLVMRustResult;
pub(crate) fn LLVMRustArchiveMemberNew<'a>(
Filename: *const c_char,
Name: *const c_char,
Child: Option<&ArchiveChild<'a>>,
) -> &'a mut RustArchiveMember<'a>;
pub(crate) fn LLVMRustArchiveMemberFree<'a>(Member: &'a mut RustArchiveMember<'a>);
pub(crate) fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
pub(crate) fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
pub(crate) fn LLVMRustSetModulePICLevel(M: &Module);
pub(crate) fn LLVMRustSetModulePIELevel(M: &Module);
pub(crate) fn LLVMRustSetModuleCodeModel(M: &Module, Model: CodeModel);
pub(crate) fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer;
pub(crate) fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8;
pub(crate) fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
pub(crate) fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
pub(crate) fn LLVMRustModuleCost(M: &Module) -> u64;
pub(crate) fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
rustc: Implement ThinLTO This commit is an implementation of LLVM's ThinLTO for consumption in rustc itself. Currently today LTO works by merging all relevant LLVM modules into one and then running optimization passes. "Thin" LTO operates differently by having more sharded work and allowing parallelism opportunities between optimizing codegen units. Further down the road Thin LTO also allows *incremental* LTO which should enable even faster release builds without compromising on the performance we have today. This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then also implements two forms of ThinLTO: * In one mode we'll *only* perform ThinLTO over the codegen units produced in a single compilation. That is, we won't load upstream rlibs, but we'll instead just perform ThinLTO amongst all codegen units produced by the compiler for the local crate. This is intended to emulate a desired end point where we have codegen units turned on by default for all crates and ThinLTO allows us to do this without performance loss. * In anther mode, like full LTO today, we'll optimize all upstream dependencies in "thin" mode. Unlike today, however, this LTO step is fully parallelized so should finish much more quickly. There's a good bit of comments about what the implementation is doing and where it came from, but the tl;dr; is that currently most of the support here is copied from upstream LLVM. This code duplication is done for a number of reasons: * Controlling parallelism means we can use the existing jobserver support to avoid overloading machines. * We will likely want a slightly different form of incremental caching which integrates with our own incremental strategy, but this is yet to be determined. * This buys us some flexibility about when/where we run ThinLTO, as well as having it tailored to fit our needs for the time being. * Finally this allows us to reuse some artifacts such as our `TargetMachine` creation, where all our options we used today aren't necessarily supported by upstream LLVM yet. My hope is that we can get some experience with this copy/paste in tree and then eventually upstream some work to LLVM itself to avoid the duplication while still ensuring our needs are met. Otherwise I fear that maintaining these bindings may be quite costly over the years with LLVM updates!
2017-07-23 15:14:38 +00:00
pub(crate) fn LLVMRustThinLTOBufferCreate(
2024-05-23 19:10:04 +00:00
M: &Module,
is_thin: bool,
emit_summary: bool,
) -> &'static mut ThinLTOBuffer;
pub(crate) fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
pub(crate) fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
pub(crate) fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
pub(crate) fn LLVMRustThinLTOBufferThinLinkDataPtr(M: &ThinLTOBuffer) -> *const c_char;
pub(crate) fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t;
pub(crate) fn LLVMRustCreateThinLTOData(
rustc: Implement ThinLTO This commit is an implementation of LLVM's ThinLTO for consumption in rustc itself. Currently today LTO works by merging all relevant LLVM modules into one and then running optimization passes. "Thin" LTO operates differently by having more sharded work and allowing parallelism opportunities between optimizing codegen units. Further down the road Thin LTO also allows *incremental* LTO which should enable even faster release builds without compromising on the performance we have today. This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then also implements two forms of ThinLTO: * In one mode we'll *only* perform ThinLTO over the codegen units produced in a single compilation. That is, we won't load upstream rlibs, but we'll instead just perform ThinLTO amongst all codegen units produced by the compiler for the local crate. This is intended to emulate a desired end point where we have codegen units turned on by default for all crates and ThinLTO allows us to do this without performance loss. * In anther mode, like full LTO today, we'll optimize all upstream dependencies in "thin" mode. Unlike today, however, this LTO step is fully parallelized so should finish much more quickly. There's a good bit of comments about what the implementation is doing and where it came from, but the tl;dr; is that currently most of the support here is copied from upstream LLVM. This code duplication is done for a number of reasons: * Controlling parallelism means we can use the existing jobserver support to avoid overloading machines. * We will likely want a slightly different form of incremental caching which integrates with our own incremental strategy, but this is yet to be determined. * This buys us some flexibility about when/where we run ThinLTO, as well as having it tailored to fit our needs for the time being. * Finally this allows us to reuse some artifacts such as our `TargetMachine` creation, where all our options we used today aren't necessarily supported by upstream LLVM yet. My hope is that we can get some experience with this copy/paste in tree and then eventually upstream some work to LLVM itself to avoid the duplication while still ensuring our needs are met. Otherwise I fear that maintaining these bindings may be quite costly over the years with LLVM updates!
2017-07-23 15:14:38 +00:00
Modules: *const ThinLTOModule,
NumModules: size_t,
rustc: Implement ThinLTO This commit is an implementation of LLVM's ThinLTO for consumption in rustc itself. Currently today LTO works by merging all relevant LLVM modules into one and then running optimization passes. "Thin" LTO operates differently by having more sharded work and allowing parallelism opportunities between optimizing codegen units. Further down the road Thin LTO also allows *incremental* LTO which should enable even faster release builds without compromising on the performance we have today. This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then also implements two forms of ThinLTO: * In one mode we'll *only* perform ThinLTO over the codegen units produced in a single compilation. That is, we won't load upstream rlibs, but we'll instead just perform ThinLTO amongst all codegen units produced by the compiler for the local crate. This is intended to emulate a desired end point where we have codegen units turned on by default for all crates and ThinLTO allows us to do this without performance loss. * In anther mode, like full LTO today, we'll optimize all upstream dependencies in "thin" mode. Unlike today, however, this LTO step is fully parallelized so should finish much more quickly. There's a good bit of comments about what the implementation is doing and where it came from, but the tl;dr; is that currently most of the support here is copied from upstream LLVM. This code duplication is done for a number of reasons: * Controlling parallelism means we can use the existing jobserver support to avoid overloading machines. * We will likely want a slightly different form of incremental caching which integrates with our own incremental strategy, but this is yet to be determined. * This buys us some flexibility about when/where we run ThinLTO, as well as having it tailored to fit our needs for the time being. * Finally this allows us to reuse some artifacts such as our `TargetMachine` creation, where all our options we used today aren't necessarily supported by upstream LLVM yet. My hope is that we can get some experience with this copy/paste in tree and then eventually upstream some work to LLVM itself to avoid the duplication while still ensuring our needs are met. Otherwise I fear that maintaining these bindings may be quite costly over the years with LLVM updates!
2017-07-23 15:14:38 +00:00
PreservedSymbols: *const *const c_char,
PreservedSymbolsLen: size_t,
) -> Option<&'static mut ThinLTOData>;
pub(crate) fn LLVMRustPrepareThinLTORename(
2020-06-26 01:52:41 +00:00
Data: &ThinLTOData,
Module: &Module,
Target: &TargetMachine,
);
pub(crate) fn LLVMRustPrepareThinLTOResolveWeak(Data: &ThinLTOData, Module: &Module) -> bool;
pub(crate) fn LLVMRustPrepareThinLTOInternalize(Data: &ThinLTOData, Module: &Module) -> bool;
pub(crate) fn LLVMRustPrepareThinLTOImport(
2020-06-26 01:52:41 +00:00
Data: &ThinLTOData,
Module: &Module,
Target: &TargetMachine,
) -> bool;
pub(crate) fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData);
pub(crate) fn LLVMRustParseBitcodeForLTO(
Context: &Context,
rustc: Implement ThinLTO This commit is an implementation of LLVM's ThinLTO for consumption in rustc itself. Currently today LTO works by merging all relevant LLVM modules into one and then running optimization passes. "Thin" LTO operates differently by having more sharded work and allowing parallelism opportunities between optimizing codegen units. Further down the road Thin LTO also allows *incremental* LTO which should enable even faster release builds without compromising on the performance we have today. This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then also implements two forms of ThinLTO: * In one mode we'll *only* perform ThinLTO over the codegen units produced in a single compilation. That is, we won't load upstream rlibs, but we'll instead just perform ThinLTO amongst all codegen units produced by the compiler for the local crate. This is intended to emulate a desired end point where we have codegen units turned on by default for all crates and ThinLTO allows us to do this without performance loss. * In anther mode, like full LTO today, we'll optimize all upstream dependencies in "thin" mode. Unlike today, however, this LTO step is fully parallelized so should finish much more quickly. There's a good bit of comments about what the implementation is doing and where it came from, but the tl;dr; is that currently most of the support here is copied from upstream LLVM. This code duplication is done for a number of reasons: * Controlling parallelism means we can use the existing jobserver support to avoid overloading machines. * We will likely want a slightly different form of incremental caching which integrates with our own incremental strategy, but this is yet to be determined. * This buys us some flexibility about when/where we run ThinLTO, as well as having it tailored to fit our needs for the time being. * Finally this allows us to reuse some artifacts such as our `TargetMachine` creation, where all our options we used today aren't necessarily supported by upstream LLVM yet. My hope is that we can get some experience with this copy/paste in tree and then eventually upstream some work to LLVM itself to avoid the duplication while still ensuring our needs are met. Otherwise I fear that maintaining these bindings may be quite costly over the years with LLVM updates!
2017-07-23 15:14:38 +00:00
Data: *const u8,
len: usize,
Identifier: *const c_char,
) -> Option<&Module>;
pub(crate) fn LLVMRustGetSliceFromObjectDataByName(
data: *const u8,
len: usize,
name: *const u8,
name_len: usize,
out_len: &mut usize,
) -> *const u8;
pub(crate) fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
pub(crate) fn LLVMRustLinkerAdd(
linker: &Linker<'_>,
bytecode: *const c_char,
bytecode_len: usize,
) -> bool;
pub(crate) fn LLVMRustLinkerFree<'a>(linker: &'a mut Linker<'a>);
pub(crate) fn LLVMRustComputeLTOCacheKey(
Use llvm::computeLTOCacheKey to determine post-ThinLTO CGU reuse During incremental ThinLTO compilation, we attempt to re-use the optimized (post-ThinLTO) bitcode file for a module if it is 'safe' to do so. Up until now, 'safe' has meant that the set of modules that our current modules imports from/exports to is unchanged from the previous compilation session. See PR #67020 and PR #71131 for more details. However, this turns out be insufficient to guarantee that it's safe to reuse the post-LTO module (i.e. that optimizing the pre-LTO module would produce the same result). When LLVM optimizes a module during ThinLTO, it may look at other information from the 'module index', such as whether a (non-imported!) global variable is used. If this information changes between compilation runs, we may end up re-using an optimized module that (for example) had dead-code elimination run on a function that is now used by another module. Fortunately, LLVM implements its own ThinLTO module cache, which is used when ThinLTO is performed by a linker plugin (e.g. when clang is used to compile a C proect). Using this cache directly would require extensive refactoring of our code - but fortunately for us, LLVM provides a function that does exactly what we need. The function `llvm::computeLTOCacheKey` is used to compute a SHA-1 hash from all data that might influence the result of ThinLTO on a module. In addition to the module imports/exports that we manually track, it also hashes information about global variables (e.g. their liveness) which might be used during optimization. By using this function, we shouldn't have to worry about new LLVM passes breaking our module re-use behavior. In LLVM, the output of this function forms part of the filename used to store the post-ThinLTO module. To keep our current filename structure intact, this PR just writes out the mapping 'CGU name -> Hash' to a file. To determine if a post-LTO module should be reused, we compare hashes from the previous session. This should unblock PR #75199 - by sheer chance, it seems to have hit this issue due to the particular CGU partitioning and optimization decisions that end up getting made.
2020-09-17 21:36:13 +00:00
key_out: &RustString,
mod_id: *const c_char,
data: &ThinLTOData,
);
pub(crate) fn LLVMRustContextGetDiagnosticHandler(
Context: &Context,
) -> Option<&DiagnosticHandler>;
pub(crate) fn LLVMRustContextSetDiagnosticHandler(
context: &Context,
diagnostic_handler: Option<&DiagnosticHandler>,
);
pub(crate) fn LLVMRustContextConfigureDiagnosticHandler(
context: &Context,
diagnostic_handler_callback: DiagnosticHandlerTy,
diagnostic_handler_context: *mut c_void,
remark_all_passes: bool,
remark_passes: *const *const c_char,
remark_passes_len: usize,
remark_file: *const c_char,
pgo_available: bool,
);
pub(crate) fn LLVMRustGetMangledName(V: &Value, out: &RustString);
pub(crate) fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32;
pub(crate) fn LLVMRustLLVMHasZlibCompressionForDebugSymbols() -> bool;
pub(crate) fn LLVMRustLLVMHasZstdCompressionForDebugSymbols() -> bool;
pub(crate) fn LLVMRustGetSymbols(
buf_ptr: *const u8,
buf_len: usize,
state: *mut c_void,
callback: GetSymbolsCallback,
error_callback: GetSymbolsErrorCallback,
) -> *mut c_void;
pub(crate) fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
pub(crate) fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
pub(crate) fn LLVMRustSetNoSanitizeAddress(Global: &Value);
pub(crate) fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
}