llvm_support/
lib.rs

1//! `llvm-support` provides support types to the other *mollusc* crates,
2//! in furtherance of the general task of parsing LLVM's bitcode.
3
4#![deny(rustdoc::broken_intra_doc_links)]
5#![deny(missing_docs)]
6#![allow(clippy::redundant_field_names)]
7#![forbid(unsafe_code)]
8
9pub mod align;
10pub mod attribute;
11pub mod bitcodes;
12pub mod ty;
13
14use num_enum::{IntoPrimitive, TryFromPrimitive};
15
16pub use self::align::*;
17pub use self::attribute::*;
18pub use self::ty::*;
19
20/// The 32-bit magic that indicates a raw LLVM IR bitcode stream.
21pub const LLVM_IR_MAGIC: u32 = 0xdec04342;
22
23/// The 32-bit magic that indicates a bitcode wrapper, which in
24/// turn points to the start of the actual bitcode stream.
25pub const BITCODE_WRAPPER_MAGIC: u32 = 0x0b17c0de;
26
27/// The initial abbreviation ID width in a bitstream.
28pub const INITIAL_ABBREV_ID_WIDTH: u64 = 2;
29
30/// All abbreviation IDs before this are defined by the bitstream format,
31/// rather than the stream itself.
32pub const FIRST_APPLICATION_ABBREV_ID: usize = 4;
33
34/// All block IDs before this have their semantics defined by the bitstream
35/// format, rather than the stream itself.
36pub const FIRST_APPLICATION_BLOCK_ID: u64 = 8;
37
38/// The lookup alphabet for the Char6 operand encoding.
39pub const CHAR6_ALPHABET: &[u8] =
40    b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._";
41
42/// The current toolchain's target triple.
43pub const TARGET_TRIPLE: &str = env!("TARGET_TRIPLE");
44
45/// An exact endianness.
46///
47/// For an inexact endianness model (i.e., one that supports a notion of "system" endianness),
48/// see [`InexactEndian`](InexactEndian)
49#[derive(Debug, PartialEq)]
50pub enum Endian {
51    /// Little-endian.
52    Little,
53    /// Big-endian.
54    Big,
55}
56
57/// An "inexact" endianness, i.e. one supports an unspecified system endianness.
58#[derive(Debug)]
59pub enum InexactEndian {
60    /// Either big-endian or little-endian.
61    Exact(Endian),
62    /// The host system's endianness, which may not be known immediately.
63    System,
64}
65
66/// Symbol mangling styles supported by LLVM.
67#[derive(Debug, PartialEq)]
68pub enum Mangling {
69    /// ELF-style mangling.
70    Elf,
71    /// MIPS-style mangling.
72    Mips,
73    /// Mach-O-style mangling.
74    Macho,
75    /// COFF on x86 Windows-style mangling.
76    WindowsX86Coff,
77    /// COFF on Windows-style mangling.
78    WindowsCoff,
79    /// XCOFF-style mangling.
80    XCoff,
81}
82
83/// Global value linkage types.
84///
85/// See: <https://llvm.org/docs/LangRef.html#linkage-types>
86#[non_exhaustive]
87#[derive(Debug, PartialEq)]
88#[repr(u64)]
89#[allow(missing_docs)]
90pub enum Linkage {
91    External,
92    AvailableExternally,
93    LinkOnceAny,
94    LinkOnceOdr,
95    WeakAny,
96    WeakOdr,
97    Appending,
98    Internal,
99    Private,
100    ExternalWeak,
101    Common,
102}
103
104impl From<u64> for Linkage {
105    fn from(value: u64) -> Self {
106        // See getDecodedLinkage in BitcodeReader.cpp.
107        match value {
108            0 | 5 | 6 | 15 => Linkage::External,
109            1 | 16 => Linkage::WeakAny,
110            2 => Linkage::Appending,
111            3 => Linkage::Internal,
112            4 | 18 => Linkage::LinkOnceAny,
113            7 => Linkage::ExternalWeak,
114            8 => Linkage::Common,
115            9 | 13 | 14 => Linkage::Private,
116            10 | 17 => Linkage::WeakOdr,
117            11 | 19 => Linkage::LinkOnceOdr,
118            12 => Linkage::AvailableExternally,
119            _ => Linkage::External,
120        }
121    }
122}
123
124/// An `(offset, size)` reference to a string within some string table.
125pub struct StrtabRef {
126    /// The string's offset within its string table.
127    pub offset: usize,
128    /// The string's size, in bytes.
129    pub size: usize,
130}
131
132impl From<(usize, usize)> for StrtabRef {
133    fn from(value: (usize, usize)) -> Self {
134        Self {
135            offset: value.0,
136            size: value.1,
137        }
138    }
139}
140
141impl From<(u64, u64)> for StrtabRef {
142    fn from(value: (u64, u64)) -> Self {
143        Self::from((value.0 as usize, value.1 as usize))
144    }
145}
146
147/// Valid visibility styles.
148///
149/// See: <https://llvm.org/docs/LangRef.html#visibility-styles>
150#[derive(Debug, PartialEq, IntoPrimitive, TryFromPrimitive)]
151#[repr(u64)]
152pub enum Visibility {
153    /// Default visibility.
154    Default = 0,
155
156    /// Hidden visibility.
157    Hidden,
158
159    /// Protected visibility.
160    Protected,
161}
162
163/// DLL storage classes.
164///
165/// See: <https://llvm.org/docs/LangRef.html#dllstorageclass>
166#[derive(Debug, PartialEq, IntoPrimitive, TryFromPrimitive)]
167#[repr(u64)]
168pub enum DllStorageClass {
169    /// The default storage class.
170    Default = 0,
171
172    /// The `dllimport` storage class.
173    Import,
174
175    /// The `dllexport` storage class.
176    Export,
177}
178
179/// Thread local storage modes.
180///
181/// See: <https://llvm.org/docs/LangRef.html#thread-local-storage-models>
182/// See also: <https://www.akkadia.org/drepper/tls.pdf>
183#[derive(Debug, PartialEq, IntoPrimitive)]
184#[repr(u64)]
185pub enum ThreadLocalMode {
186    /// Not thread local.
187    NotThreadLocal = 0,
188
189    /// The general dynamic TLS model.
190    GeneralDynamicTls,
191
192    /// The local dynamic TLS model.
193    LocalDynamicTls,
194
195    /// The initial exec TLS model.
196    InitialExecTls,
197
198    /// The local exec TLS model.
199    LocalExecTls,
200}
201
202impl From<u64> for ThreadLocalMode {
203    fn from(value: u64) -> ThreadLocalMode {
204        match value {
205            0 => ThreadLocalMode::NotThreadLocal,
206            1 => ThreadLocalMode::GeneralDynamicTls,
207            2 => ThreadLocalMode::LocalDynamicTls,
208            3 => ThreadLocalMode::InitialExecTls,
209            4 => ThreadLocalMode::LocalExecTls,
210            // Unknown values are treated as general dynamic.
211            _ => ThreadLocalMode::GeneralDynamicTls,
212        }
213    }
214}
215
216/// The `unnamed_addr` specifier.
217#[derive(Debug, PartialEq, IntoPrimitive)]
218#[repr(u64)]
219pub enum UnnamedAddr {
220    /// No `unnamed_addr`.
221    None = 0,
222
223    /// The address of this variable is not significant.
224    Global,
225
226    /// The address of this variable is not significant, but only within the module.
227    Local,
228}
229
230impl From<u64> for UnnamedAddr {
231    fn from(value: u64) -> UnnamedAddr {
232        match value {
233            0 => UnnamedAddr::None,
234            1 => UnnamedAddr::Global,
235            2 => UnnamedAddr::Local,
236            // Unknown values are treated as having no `unnamed_addr` specifier.
237            _ => UnnamedAddr::None,
238        }
239    }
240}
241
242/// The runtime preemption specifier.
243///
244/// See: <https://llvm.org/docs/LangRef.html#runtime-preemption-model>
245#[derive(Debug, PartialEq, IntoPrimitive)]
246#[repr(u64)]
247pub enum RuntimePreemption {
248    /// The function or variable may be replaced by a symbol from outside the linkage
249    /// unit at runtime.
250    DsoPreemptable,
251
252    /// The compiler may assume that the function or variable will resolve to a symbol within
253    /// the same linkage unit.
254    DsoLocal,
255}
256
257impl From<u64> for RuntimePreemption {
258    fn from(value: u64) -> RuntimePreemption {
259        match value {
260            0 => RuntimePreemption::DsoPreemptable,
261            1 => RuntimePreemption::DsoLocal,
262            // Unknown values are treated as `dso_preemptable`.
263            _ => RuntimePreemption::DsoPreemptable,
264        }
265    }
266}
267
268/// Calling conventions supported by LLVM.
269#[non_exhaustive]
270#[derive(Debug, PartialEq, TryFromPrimitive)]
271#[repr(u64)]
272#[allow(missing_docs)]
273pub enum CallingConvention {
274    C = 0,
275    Fast = 8,
276    Cold = 9,
277    GHC = 10,
278    HiPE = 11,
279    WebKitJS = 12,
280    AnyReg = 13,
281    PreserveMost = 14,
282    PreserveAll = 15,
283    Swift = 16,
284    CXXFASTTLS = 17,
285    X86Stdcall = 64,
286    X86Fastcall = 65,
287    ARMAPCS = 66,
288    ARMAAPCS = 67,
289    ARMAAPCSVFP = 68,
290    MSP430INTR = 69,
291    X86ThisCall = 70,
292    PTXKernel = 71,
293    PTXDevice = 72,
294    SPIRFUNC = 75,
295    SPIRKERNEL = 76,
296    IntelOCLBI = 77,
297    X8664SysV = 78,
298    Win64 = 79,
299    X86VectorCall = 80,
300    HHVM = 81,
301    HHVMC = 82,
302    X86INTR = 83,
303    AVRINTR = 84,
304    AVRSIGNAL = 85,
305    AVRBUILTIN = 86,
306    AMDGPUVS = 87,
307    AMDGPUGS = 88,
308    AMDGPUPS = 89,
309    AMDGPUCS = 90,
310    AMDGPUKERNEL = 91,
311    X86RegCall = 92,
312    AMDGPUHS = 93,
313    MSP430BUILTIN = 94,
314    AMDGPULS = 95,
315    AMDGPUES = 96,
316}
317
318#[cfg(test)]
319mod tests {
320    use super::*;
321
322    #[test]
323    fn test_target_triple() {
324        assert!(!TARGET_TRIPLE.is_empty());
325    }
326}