llvm_ir/
module.rs

1use crate::constant::ConstantRef;
2use crate::debugloc::*;
3use crate::function::{Function, FunctionAttribute, FunctionDeclaration, GroupID};
4use crate::llvm_sys::*;
5use crate::name::Name;
6use crate::types::{FPType, Type, TypeRef, Typed, Types, TypesBuilder};
7use std::collections::{BTreeMap, HashMap, HashSet};
8use std::path::Path;
9
10/// See [LLVM 14 docs on Module Structure](https://releases.llvm.org/14.0.0/docs/LangRef.html#module-structure)
11#[derive(Clone)]
12pub struct Module {
13    /// The name of the module
14    pub name: String,
15    /// See [LLVM 14 docs on Source Filename](https://releases.llvm.org/14.0.0/docs/LangRef.html#source-filename)
16    pub source_file_name: String,
17    /// See [LLVM 14 docs on Data Layout](https://releases.llvm.org/14.0.0/docs/LangRef.html#data-layout)
18    pub data_layout: DataLayout,
19    /// See [LLVM 14 docs on Target Triple](https://releases.llvm.org/14.0.0/docs/LangRef.html#target-triple)
20    pub target_triple: Option<String>,
21    /// Functions which are defined (not just declared) in this `Module`.
22    /// See [LLVM 14 docs on Functions](https://releases.llvm.org/14.0.0/docs/LangRef.html#functions)
23    pub functions: Vec<Function>,
24    /// Functions which are declared (but not defined) in this `Module`.
25    /// See [LLVM 14 docs on Functions](https://releases.llvm.org/14.0.0/docs/LangRef.html#functions)
26    pub func_declarations: Vec<FunctionDeclaration>,
27    /// See [LLVM 14 docs on Global Variables](https://releases.llvm.org/14.0.0/docs/LangRef.html#global-variables)
28    pub global_vars: Vec<GlobalVariable>,
29    /// See [LLVM 14 docs on Global Aliases](https://releases.llvm.org/14.0.0/docs/LangRef.html#aliases)
30    pub global_aliases: Vec<GlobalAlias>,
31    /// See [LLVM 14 docs on Global IFuncs](https://releases.llvm.org/14.0.0/docs/LangRef.html#ifuncs)
32    pub global_ifuncs: Vec<GlobalIFunc>,
33    // --TODO not yet implemented-- pub function_attribute_groups: Vec<FunctionAttributeGroup>,
34    /// See [LLVM 14 docs on Module-Level Inline Assembly](https://releases.llvm.org/14.0.0/docs/LangRef.html#moduleasm)
35    pub inline_assembly: String,
36    // --TODO not yet implemented-- pub metadata_nodes: Vec<(MetadataNodeID, MetadataNode)>,
37    // --TODO not yet implemented-- pub named_metadatas: Vec<NamedMetadata>,
38    // --TODO not yet implemented-- pub comdats: Vec<Comdat>,
39    /// Holds a reference to all of the `Type`s used in the `Module`, and
40    /// facilitates lookups so you can get a `TypeRef` to the `Type` you want.
41    pub types: Types,
42}
43
44impl Module {
45    /// Get the type of anything that is `Typed`.
46    pub fn type_of<T: Typed + ?Sized>(&self, t: &T) -> TypeRef {
47        self.types.type_of(t)
48    }
49
50    /// Get the `Function` having the given `name` (if any).
51    /// Note that functions are named with `String`s and not `Name`s.
52    ///
53    /// Note also that this will only find _fully defined_ functions, not
54    /// `FunctionDeclaration`s.
55    pub fn get_func_by_name(&self, name: &str) -> Option<&Function> {
56        self.functions.iter().find(|func| func.name == name)
57    }
58
59    /// Get the `FunctionDeclaration` having the given `name` (if any).
60    /// Note that functions are named with `String`s and not `Name`s.
61    ///
62    /// Note also that this will only find function _declarations_, and will not
63    /// find defined functions (use `get_func_by_name()` for that).
64    pub fn get_func_decl_by_name(&self, name: &str) -> Option<&FunctionDeclaration> {
65        self.func_declarations.iter().find(|decl| decl.name == name)
66    }
67
68    /// Get the `GlobalVariable` having the given `Name` (if any).
69    pub fn get_global_var_by_name(&self, name: &Name) -> Option<&GlobalVariable> {
70        self.global_vars.iter().find(|global| global.name == *name)
71    }
72
73    /// Get the `GlobalAlias` having the given `Name` (if any).
74    pub fn get_global_alias_by_name(&self, name: &Name) -> Option<&GlobalAlias> {
75        self.global_aliases.iter().find(|global| global.name == *name)
76    }
77
78    /// Get the `GlobalIFunc` having the given `Name` (if any).
79    pub fn get_global_ifunc_by_name(&self, name: &Name) -> Option<&GlobalIFunc> {
80        self.global_ifuncs.iter().find(|global| global.name == *name)
81    }
82
83    /// Parse the LLVM bitcode (.bc) file at the given path to create a `Module`
84    pub fn from_bc_path(path: impl AsRef<Path>) -> Result<Self, String> {
85        unsafe fn parse_bc(
86            context_ref: LLVMContextRef,
87            mem_buf: LLVMMemoryBufferRef,
88            out_module: *mut LLVMModuleRef,
89        ) -> Result<(), String> {
90            let result =
91                llvm_sys::bit_reader::LLVMParseBitcodeInContext2(context_ref, mem_buf, out_module);
92            LLVMDisposeMemoryBuffer(mem_buf);
93            match result {
94                0 => Ok(()),
95                _ => Err("Failed to parse bitcode".to_owned())
96            }
97        }
98        Self::from_path(path, parse_bc)
99    }
100
101    /// Parse the LLVM text IR (.ll) file at the given path to create a `Module`
102    pub fn from_ir_path(path: impl AsRef<Path>) -> Result<Self, String> {
103        Self::from_path(path, Self::parse_ir)
104    }
105
106    /// Parse the given string as LLVM text IR by copying to create a `Module`
107    pub fn from_ir_str(str: &str) -> Result<Self, String> {
108        let memory_buffer = unsafe {
109            LLVMCreateMemoryBufferWithMemoryRangeCopy(
110                str.as_ptr() as *const _,
111                str.len(),
112                std::ffi::CString::default().as_ptr(),
113            )
114        };
115        Self::from_buffer(memory_buffer, Self::parse_ir)
116    }
117
118    unsafe fn parse_ir(
119        context_ref: LLVMContextRef,
120        mem_buf: LLVMMemoryBufferRef,
121        out_module: *mut LLVMModuleRef,
122    ) -> Result<(), String> {
123        use std::ffi::CStr;
124        let mut err_string = std::mem::zeroed();
125        // This call takes ownership of the buffer, so we don't free it.
126        match llvm_sys::ir_reader::LLVMParseIRInContext(context_ref, mem_buf, out_module, &mut err_string) {
127            0 => Ok(()),
128            _ => Err(format!("Failed to parse IR: {}",
129                             CStr::from_ptr(err_string).to_str().expect("Failed to convert CStr")))
130        }
131    }
132
133    fn from_path(
134        path: impl AsRef<Path>,
135        parse: unsafe fn(
136            context_ref: LLVMContextRef,
137            mem_buf: LLVMMemoryBufferRef,
138            out_module: *mut LLVMModuleRef,
139        ) -> Result<(), String>,
140    ) -> Result<Self, String> {
141        // implementation here inspired by the `inkwell` crate's `Module::parse_bitcode_from_path`
142        use std::ffi::{CStr, CString};
143
144        let path = CString::new(
145            path.as_ref()
146                .to_str()
147                .expect("Did not find a valid Unicode path string"),
148        )
149        .expect("Failed to convert to CString");
150        debug!("Creating a Module from path {:?}", path);
151
152        let memory_buffer = unsafe {
153            let mut memory_buffer = std::ptr::null_mut();
154            let mut err_string = std::mem::zeroed();
155            let return_code = LLVMCreateMemoryBufferWithContentsOfFile(
156                path.as_ptr() as *const _,
157                &mut memory_buffer,
158                &mut err_string,
159            );
160            if return_code != 0 {
161                return Err(CStr::from_ptr(err_string)
162                    .to_str()
163                    .expect("Failed to convert CStr")
164                    .to_owned());
165            }
166            memory_buffer
167        };
168        debug!("Created a MemoryBuffer");
169
170        Self::from_buffer(memory_buffer, parse)
171    }
172
173    fn from_buffer(
174        memory_buffer: LLVMMemoryBufferRef,
175        parse: unsafe fn(
176            context_ref: LLVMContextRef,
177            mem_buf: LLVMMemoryBufferRef,
178            out_module: *mut LLVMModuleRef,
179        ) -> Result<(), String>,
180    ) -> Result<Self, String> {
181        let context = crate::from_llvm::Context::new();
182
183        let module = unsafe {
184            let mut module: std::mem::MaybeUninit<LLVMModuleRef> = std::mem::MaybeUninit::uninit();
185            parse(context.ctx, memory_buffer, module.as_mut_ptr())?;
186            module.assume_init()
187        };
188        debug!("Parsed bitcode to llvm_sys module");
189        Ok(Self::from_llvm_ref(module))
190    }
191}
192
193/// See [LLVM 14 docs on Global Variables](https://releases.llvm.org/14.0.0/docs/LangRef.html#global-variables)
194#[derive(PartialEq, Clone, Debug, Hash)]
195pub struct GlobalVariable {
196    pub name: Name,
197    pub linkage: Linkage,
198    pub visibility: Visibility,
199    pub is_constant: bool,
200    pub ty: TypeRef,
201    pub addr_space: AddrSpace,
202    pub dll_storage_class: DLLStorageClass,
203    pub thread_local_mode: ThreadLocalMode,
204    pub unnamed_addr: Option<UnnamedAddr>,
205    pub initializer: Option<ConstantRef>,
206    pub section: Option<String>,
207    pub comdat: Option<Comdat>, // llvm-hs-pure has Option<String> for some reason
208    pub alignment: u32,
209    pub debugloc: Option<DebugLoc>,
210    // --TODO not yet implemented-- pub metadata: Vec<(String, MetadataRef<MetadataNode>)>,
211}
212
213impl Typed for GlobalVariable {
214    fn get_type(&self, _types: &Types) -> TypeRef {
215        self.ty.clone()
216    }
217}
218
219impl HasDebugLoc for GlobalVariable {
220    fn get_debug_loc(&self) -> &Option<DebugLoc> {
221        &self.debugloc
222    }
223}
224
225/// See [LLVM 14 docs on Global Aliases](https://releases.llvm.org/14.0.0/docs/LangRef.html#aliases)
226#[derive(PartialEq, Clone, Debug, Hash)]
227pub struct GlobalAlias {
228    pub name: Name,
229    pub aliasee: ConstantRef,
230    pub linkage: Linkage,
231    pub visibility: Visibility,
232    pub ty: TypeRef,
233    pub addr_space: AddrSpace,
234    pub dll_storage_class: DLLStorageClass,
235    pub thread_local_mode: ThreadLocalMode,
236    pub unnamed_addr: Option<UnnamedAddr>,
237}
238
239impl Typed for GlobalAlias {
240    fn get_type(&self, _types: &Types) -> TypeRef {
241        self.ty.clone()
242    }
243}
244
245/// See [LLVM 14 docs on Global IFuncs](https://releases.llvm.org/14.0.0/docs/LangRef.html#ifuncs)
246#[derive(PartialEq, Clone, Debug, Hash)]
247pub struct GlobalIFunc {
248    pub name: Name,
249    pub linkage: Linkage,
250    pub visibility: Visibility,
251    pub ty: TypeRef,
252    pub resolver_fn: ConstantRef,
253}
254
255impl Typed for GlobalIFunc {
256    fn get_type(&self, _types: &Types) -> TypeRef {
257        self.ty.clone()
258    }
259}
260
261#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
262pub enum UnnamedAddr {
263    Local,
264    Global,
265}
266
267/// See [LLVM 14 docs on Linkage Types](https://releases.llvm.org/14.0.0/docs/LangRef.html#linkage)
268#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
269pub enum Linkage {
270    Private,
271    Internal,
272    External,
273    ExternalWeak,
274    AvailableExternally,
275    LinkOnceAny,
276    LinkOnceODR,
277    LinkOnceODRAutoHide,
278    WeakAny,
279    WeakODR,
280    Common,
281    Appending,
282    DLLImport,
283    DLLExport,
284    Ghost,
285    LinkerPrivate,
286    LinkerPrivateWeak,
287}
288
289/// See [LLVM 14 docs on Visibility Styles](https://releases.llvm.org/14.0.0/docs/LangRef.html#visibility-styles)
290#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
291pub enum Visibility {
292    Default,
293    Hidden,
294    Protected,
295}
296
297/// See [LLVM 14 docs on DLL Storage Classes](https://releases.llvm.org/14.0.0/docs/LangRef.html#dllstorageclass)
298#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
299pub enum DLLStorageClass {
300    Default,
301    Import,
302    Export,
303}
304
305/// See [LLVM 14 docs on Thread Local Storage Models](https://releases.llvm.org/14.0.0/docs/LangRef.html#thread-local-storage-models)
306#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
307pub enum ThreadLocalMode {
308    NotThreadLocal,
309    GeneralDynamic,
310    LocalDynamic,
311    InitialExec,
312    LocalExec,
313}
314
315/// For discussion of address spaces, see [LLVM 14 docs on Pointer Type](https://releases.llvm.org/14.0.0/docs/LangRef.html#pointer-type)
316pub type AddrSpace = u32;
317
318/// See [LLVM 14 docs on Attribute Groups](https://releases.llvm.org/14.0.0/docs/LangRef.html#attribute-groups)
319#[derive(PartialEq, Eq, Clone, Debug, Hash)]
320pub struct FunctionAttributeGroup {
321    pub group_id: GroupID,
322    pub attrs: Vec<FunctionAttribute>,
323}
324
325/* --TODO not yet implemented: metadata
326/// See [LLVM 14 docs on Named Metadata](https://releases.llvm.org/14.0.0/docs/LangRef.html#named-metadata)
327#[derive(PartialEq, Eq, Clone, Debug, Hash)]
328pub struct NamedMetadata {
329    pub name: String,
330    pub node_ids: Vec<MetadataNodeID>,
331}
332*/
333
334/// See [LLVM 14 docs on Comdats](https://releases.llvm.org/14.0.0/docs/LangRef.html#langref-comdats)
335#[derive(PartialEq, Eq, Clone, Debug, Hash)]
336pub struct Comdat {
337    pub name: String,
338    pub selection_kind: SelectionKind,
339}
340
341#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
342pub enum SelectionKind {
343    Any,
344    ExactMatch,
345    Largest,
346    NoDuplicates,
347    SameSize,
348}
349
350/// See [LLVM 14 docs on Data Layout](https://releases.llvm.org/14.0.0/docs/LangRef.html#data-layout)
351#[derive(Clone, Debug)]
352pub struct DataLayout {
353    /// The data layout in string form, as described in the Data Layout docs linked above
354    pub layout_str: String,
355    /// Little-endian or big-endian?
356    pub endianness: Endianness,
357    /// Natural alignment of the stack, in bits. For more, see the Data Layout docs linked above
358    pub stack_alignment: Option<u32>,
359    /// Address space for program memory
360    pub program_address_space: AddrSpace,
361    /// Address space for objects created by `alloca`
362    pub alloca_address_space: AddrSpace,
363    /// Alignment for various types in memory
364    pub alignments: Alignments,
365    /// What mangling will be applied when the LLVM module is compiled to machine code
366    pub mangling: Option<Mangling>,
367    /// Native integer width(s) for the target CPU
368    pub native_int_widths: Option<HashSet<u32>>,
369    /// Address spaces with non-integral pointer types
370    pub non_integral_ptr_types: HashSet<AddrSpace>,
371}
372
373impl PartialEq for DataLayout {
374    fn eq(&self, other: &Self) -> bool {
375        // The layout string fully specifies all the other information
376        self.layout_str == other.layout_str
377    }
378}
379
380impl Eq for DataLayout {}
381
382#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
383pub enum Endianness {
384    /// Least-significant bits are stored in the lowest address location
385    LittleEndian,
386    /// Most-significant bits are stored in the lowest address location
387    BigEndian,
388}
389
390/// Alignment details for a type.
391/// See [LLVM 14 docs on Data Layout](https://releases.llvm.org/14.0.0/docs/LangRef.html#data-layout)
392#[derive(Clone, PartialEq, Eq, Debug, Hash)]
393pub struct Alignment {
394    /// Minimum alignment (in bits) per the ABI
395    pub abi: u32,
396    /// Preferred alignment (in bits)
397    pub pref: u32,
398}
399
400/// Alignment details for function pointers.
401/// See [LLVM 14 docs on Data Layout](https://releases.llvm.org/14.0.0/docs/LangRef.html#data-layout)
402#[derive(Clone, PartialEq, Eq, Debug, Hash)]
403pub struct FunctionPtrAlignment {
404    /// If `true`, function pointer alignment is independent of function alignment.
405    /// If `false`, function pointer alignment is a multiple of function alignment.
406    pub independent: bool,
407    /// Minimum alignment (in bits) per the ABI
408    pub abi: u32,
409}
410
411/// Layout details for pointers (other than function pointers).
412/// See [LLVM 14 docs on Data Layout](https://releases.llvm.org/14.0.0/docs/LangRef.html#data-layout)
413#[derive(Clone, PartialEq, Eq, Debug, Hash)]
414pub struct PointerLayout {
415    /// Size of a pointer in bits
416    pub size: u32,
417    /// Alignment of a pointer
418    pub alignment: Alignment,
419    /// Size of an index used for address calculation, in bits
420    pub index_size: u32,
421}
422
423/// Alignment for various types in memory.
424/// See [LLVM 14 docs on Data Layout](https://releases.llvm.org/14.0.0/docs/LangRef.html#data-layout)
425#[derive(Clone, Debug)]
426pub struct Alignments {
427    /// Explicit alignments for various sizes of integers (in bits). Sizes not
428    /// specified here are determined according to the rules described in the
429    /// Data Layout docs.
430    int_alignments: BTreeMap<u32, Alignment>,
431    /// Explicit alignments for various sizes of vectors (in bits). Sizes not
432    /// specified here are determined according to the rules described in the
433    /// Data Layout docs.
434    vec_alignments: BTreeMap<u32, Alignment>,
435    /// Alignment for floating-point types, by size (in bits)
436    fp_alignments: HashMap<u32, Alignment>,
437    /// Alignment for aggregate types (structs, arrays)
438    agg_alignment: Alignment,
439    /// Alignment for function pointers
440    fptr_alignment: FunctionPtrAlignment,
441    /// Alignment for function pointers, as an `Alignment`
442    fptr_alignment_as_alignment: Alignment,
443    /// Layout details for (non-function-pointer) pointers, by address space
444    pointer_layouts: HashMap<AddrSpace, PointerLayout>,
445}
446
447impl Alignments {
448    /// Alignment of the given type (in bits)
449    pub fn type_alignment(&self, ty: &Type) -> &Alignment {
450        match ty {
451            Type::IntegerType { bits } => self.int_alignment(*bits),
452            Type::VectorType {
453                element_type,
454                num_elements,
455                ..
456            } => {
457                let element_size_bits = match element_type.as_ref() {
458                    Type::IntegerType { bits } => *bits,
459                    Type::FPType(fpt) => Self::fpt_size(*fpt),
460                    ty => panic!("Didn't expect a vector with element type {:?}", ty),
461                };
462                self.vec_alignment(element_size_bits * (*num_elements as u32))
463            },
464            Type::FPType(fpt) => self.fp_alignment(*fpt),
465            Type::StructType { .. } | Type::NamedStructType { .. } | Type::ArrayType { .. } => {
466                self.agg_alignment()
467            },
468            #[cfg(feature = "llvm-14-or-lower")]
469            Type::PointerType {
470                pointee_type,
471                addr_space,
472            } => match pointee_type.as_ref() {
473                Type::FuncType { .. } => &self.fptr_alignment_as_alignment,
474                _ => &self.ptr_alignment(*addr_space).alignment,
475            },
476            #[cfg(feature = "llvm-15-or-greater")]
477            Type::PointerType { addr_space } => &self.ptr_alignment(*addr_space).alignment,
478            _ => panic!("Don't know how to get the alignment of {:?}", ty),
479        }
480    }
481
482    /// Alignment of the integer type of the given size (in bits)
483    pub fn int_alignment(&self, size: u32) -> &Alignment {
484        // If we have an explicit entry for this size, use that
485        if let Some(alignment) = self.int_alignments.get(&size) {
486            return alignment;
487        }
488        // Find the next largest size that has an explicit entry and use that
489        let next_largest_entry = self.int_alignments.iter().find(|(&k, _)| k > size);
490        match next_largest_entry {
491            Some((_, alignment)) => alignment,
492            None => {
493                // `size` is larger than any explicit entry: use the largest explicit entry
494                self.int_alignments
495                    .values()
496                    .rev()
497                    .next()
498                    .expect("Should have at least one explicit entry")
499            },
500        }
501    }
502
503    /// Alignment of the vector type of the given total size (in bits)
504    pub fn vec_alignment(&self, size: u32) -> &Alignment {
505        // If we have an explicit entry for this size, use that
506        if let Some(alignment) = self.vec_alignments.get(&size) {
507            return alignment;
508        }
509        // Find the next smaller size that has an explicit entry and use that
510        let next_smaller_entry = self.vec_alignments.iter().find(|(&k, _)| k < size);
511        match next_smaller_entry {
512            Some((_, alignment)) => alignment,
513            None => {
514                // `size` is smaller than any explicit entry. LLVM docs seem to
515                // be not clear what happens here, I assume we just use the
516                // smallest explicit entry
517                self.vec_alignments
518                    .values()
519                    .next()
520                    .expect("Should have at least one explicit entry")
521            },
522        }
523    }
524
525    /// Alignment of the given floating-point type
526    pub fn fp_alignment(&self, fpt: FPType) -> &Alignment {
527        self.fp_alignments
528            .get(&Self::fpt_size(fpt))
529            .unwrap_or_else(|| {
530                panic!(
531                    "No alignment information for {:?} - does the target support that type?",
532                    fpt
533                )
534            })
535    }
536
537    /// Alignment of aggregate types (structs, arrays)
538    pub fn agg_alignment(&self) -> &Alignment {
539        &self.agg_alignment
540    }
541
542    /// Alignment of function pointers
543    pub fn fptr_alignment(&self) -> &FunctionPtrAlignment {
544        &self.fptr_alignment
545    }
546
547    /// Alignment of (non-function-pointer) pointers in the given address space
548    pub fn ptr_alignment(&self, addr_space: AddrSpace) -> &PointerLayout {
549        match self.pointer_layouts.get(&addr_space) {
550            Some(layout) => layout,
551            None => self
552                .pointer_layouts
553                .get(&0)
554                .expect("Should have a pointer layout for address space 0"),
555        }
556    }
557
558    /// for internal use: size of an `FPType`, in bits
559    fn fpt_size(fpt: FPType) -> u32 {
560        match fpt {
561            FPType::Half => 16,
562            #[cfg(feature = "llvm-11-or-greater")]
563            FPType::BFloat => 16,
564            FPType::Single => 32,
565            FPType::Double => 64,
566            FPType::FP128 => 128,
567            FPType::X86_FP80 => 80,
568            FPType::PPC_FP128 => 128,
569        }
570    }
571}
572
573/// See [LLVM 14 docs on Data Layout](https://releases.llvm.org/14.0.0/docs/LangRef.html#data-layout)
574#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
575pub enum Mangling {
576    ELF,
577    MIPS,
578    MachO,
579    WindowsX86COFF,
580    WindowsCOFF,
581    #[cfg(feature = "llvm-11-or-greater")]
582    XCOFF,
583}
584
585// ********* //
586// from_llvm //
587// ********* //
588
589use crate::constant::Constant;
590use crate::from_llvm::*;
591use crate::function::AttributesData;
592use llvm_sys::comdat::*;
593use llvm_sys::{
594    LLVMDLLStorageClass,
595    LLVMLinkage,
596    LLVMThreadLocalMode,
597    LLVMUnnamedAddr,
598    LLVMVisibility,
599};
600
601/// This struct contains data used when translating llvm-sys objects into our
602/// data structures
603pub(crate) struct ModuleContext<'a> {
604    pub types: TypesBuilder,
605    pub attrsdata: AttributesData,
606    /// Map from an llvm-sys constant to the corresponding llvm-ir `ConstantRef`
607    // We use LLVMValueRef as a *const, even though it's technically a *mut
608    #[allow(clippy::mutable_key_type)]
609    pub constants: HashMap<LLVMValueRef, ConstantRef>,
610    /// Map from an llvm-sys global to its `Name`
611    // We use LLVMValueRef as a *const, even though it's technically a *mut
612    #[allow(clippy::mutable_key_type)]
613    pub global_names: &'a HashMap<LLVMValueRef, Name>,
614}
615
616impl<'a> ModuleContext<'a> {
617    // We use LLVMValueRef as a *const, even though it's technically a *mut
618    #[allow(clippy::mutable_key_type)]
619    fn new(global_names: &'a HashMap<LLVMValueRef, Name>) -> Self {
620        Self {
621            types: TypesBuilder::new(),
622            attrsdata: AttributesData::create(),
623            constants: HashMap::new(),
624            global_names,
625        }
626    }
627}
628
629impl Module {
630    pub(crate) fn from_llvm_ref(module: LLVMModuleRef) -> Self {
631        debug!("Creating a Module from an LLVMModuleRef");
632        let mut global_ctr = 0; // this ctr is used to number global objects that aren't named
633
634        // Modules require two passes over their contents.
635        // First we make a pass just to map global objects -- in particular,
636        //   Functions, GlobalVariables, GlobalAliases, and GlobalIFuncs -- to
637        //   Names; then we do the actual detailed pass.
638        // This is necessary because these structures may reference each other in a
639        //   circular fashion, and we need to be able to fill in the Name of the
640        //   referenced object from having only its `LLVMValueRef`.
641        // We use LLVMValueRef as a *const, even though it's technically a *mut
642        #[allow(clippy::mutable_key_type)]
643        let global_names: HashMap<LLVMValueRef, Name> = get_defined_functions(module)
644            .chain(get_declared_functions(module))
645            .chain(get_globals(module))
646            .chain(get_global_aliases(module))
647            .chain(get_global_ifuncs(module))
648            .map(|g| {
649                (
650                    g,
651                    Name::name_or_num(unsafe { get_value_name(g) }, &mut global_ctr),
652                )
653            })
654            .collect();
655        global_ctr = 0; // reset the global_ctr; the second pass should number everything exactly the same though
656
657        let mut ctx = ModuleContext::new(&global_names);
658
659        Self {
660            name: unsafe { get_module_identifier(module) },
661            source_file_name: unsafe { get_source_file_name(module) },
662            data_layout: DataLayout::from_module_ref(module),
663            target_triple: unsafe { get_target(module) },
664            functions: get_defined_functions(module)
665                .map(|f| Function::from_llvm_ref(f, &mut ctx))
666                .collect(),
667            func_declarations: get_declared_functions(module)
668                .map(|f| FunctionDeclaration::from_llvm_ref(f, &mut ctx))
669                .collect(),
670            global_vars: get_globals(module)
671                .map(|g| GlobalVariable::from_llvm_ref(g, &mut global_ctr, &mut ctx))
672                .collect(),
673            global_aliases: get_global_aliases(module)
674                .map(|g| GlobalAlias::from_llvm_ref(g, &mut global_ctr, &mut ctx))
675                .collect(),
676            global_ifuncs: get_global_ifuncs(module)
677                .map(|g| GlobalIFunc::from_llvm_ref(g, &mut global_ctr, &mut ctx))
678                .collect(),
679            // function_attribute_groups: unimplemented!("function_attribute_groups"),  // llvm-hs collects these in the decoder monad or something
680            inline_assembly: unsafe { get_module_inline_asm(module) },
681            // metadata_nodes: unimplemented!("metadata_nodes"),
682            // named_metadatas: unimplemented!("named_metadatas"),
683            // comdats: unimplemented!("comdats"),  // I think llvm-hs also collects these along the way
684            types: ctx.types.build(),
685        }
686    }
687}
688
689impl GlobalVariable {
690    pub(crate) fn from_llvm_ref(
691        global: LLVMValueRef,
692        ctr: &mut usize,
693        ctx: &mut ModuleContext,
694    ) -> Self {
695        let ty = ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(global) });
696        let addr_space = match ty.as_ref() {
697            Type::PointerType { addr_space, .. } => *addr_space,
698            _ => panic!("GlobalVariable has a non-pointer type, {:?}", ty),
699        };
700        debug!("Processing a GlobalVariable with type {:?}", ty);
701        Self {
702            name: Name::name_or_num(unsafe { get_value_name(global) }, ctr),
703            linkage: Linkage::from_llvm(unsafe { LLVMGetLinkage(global) }),
704            visibility: Visibility::from_llvm(unsafe { LLVMGetVisibility(global) }),
705            is_constant: unsafe { LLVMIsGlobalConstant(global) } != 0,
706            ty,
707            addr_space,
708            dll_storage_class: DLLStorageClass::from_llvm(unsafe {
709                LLVMGetDLLStorageClass(global)
710            }),
711            thread_local_mode: ThreadLocalMode::from_llvm(unsafe {
712                LLVMGetThreadLocalMode(global)
713            }),
714            unnamed_addr: UnnamedAddr::from_llvm(unsafe { LLVMGetUnnamedAddress(global) }),
715            initializer: {
716                let it = unsafe { LLVMGetInitializer(global) };
717                if it.is_null() {
718                    None
719                } else {
720                    Some(Constant::from_llvm_ref(it, ctx))
721                }
722            },
723            section: unsafe { get_section(global) },
724            comdat: {
725                let comdat = unsafe { LLVMGetComdat(global) };
726                if comdat.is_null() {
727                    None
728                } else {
729                    Some(Comdat::from_llvm_ref(unsafe { LLVMGetComdat(global) }))
730                }
731            },
732            alignment: unsafe { LLVMGetAlignment(global) },
733            debugloc: DebugLoc::from_llvm_no_col(global),
734            // metadata: unimplemented!("metadata"),
735        }
736    }
737}
738
739impl GlobalAlias {
740    pub(crate) fn from_llvm_ref(
741        alias: LLVMValueRef,
742        ctr: &mut usize,
743        ctx: &mut ModuleContext,
744    ) -> Self {
745        let ty = ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(alias) });
746        let addr_space = match ty.as_ref() {
747            Type::PointerType { addr_space, .. } => *addr_space,
748            _ => panic!("GlobalAlias has a non-pointer type, {:?}", ty),
749        };
750        Self {
751            name: Name::name_or_num(unsafe { get_value_name(alias) }, ctr),
752            aliasee: Constant::from_llvm_ref(unsafe { LLVMAliasGetAliasee(alias) }, ctx),
753            linkage: Linkage::from_llvm(unsafe { LLVMGetLinkage(alias) }),
754            visibility: Visibility::from_llvm(unsafe { LLVMGetVisibility(alias) }),
755            ty,
756            addr_space,
757            dll_storage_class: DLLStorageClass::from_llvm(unsafe { LLVMGetDLLStorageClass(alias) }),
758            thread_local_mode: ThreadLocalMode::from_llvm(unsafe { LLVMGetThreadLocalMode(alias) }),
759            unnamed_addr: UnnamedAddr::from_llvm(unsafe { LLVMGetUnnamedAddress(alias) }),
760        }
761    }
762}
763
764impl GlobalIFunc {
765    pub(crate) fn from_llvm_ref(
766        ifunc: LLVMValueRef,
767        ctr: &mut usize,
768        ctx: &mut ModuleContext,
769    ) -> Self {
770        Self {
771            name: Name::name_or_num(unsafe { get_value_name(ifunc) }, ctr),
772            linkage: Linkage::from_llvm(unsafe { LLVMGetLinkage(ifunc) }),
773            visibility: Visibility::from_llvm(unsafe { LLVMGetVisibility(ifunc) }),
774            ty: ctx.types.type_from_llvm_ref(unsafe { LLVMTypeOf(ifunc) }),
775            resolver_fn: Constant::from_llvm_ref(unsafe { LLVMGetGlobalIFuncResolver(ifunc) }, ctx),
776        }
777    }
778}
779
780/* --TODO not yet implemented: metadata
781impl NamedMetadata {
782    pub(crate) fn from_llvm_ref(nm: LLVMNamedMDNodeRef) -> Self {
783        unimplemented!("NamedMetadata::from_llvm_ref")
784    }
785}
786*/
787
788impl UnnamedAddr {
789    pub(crate) fn from_llvm(ua: LLVMUnnamedAddr) -> Option<Self> {
790        use LLVMUnnamedAddr::*;
791        match ua {
792            LLVMNoUnnamedAddr => None,
793            LLVMLocalUnnamedAddr => Some(UnnamedAddr::Local),
794            LLVMGlobalUnnamedAddr => Some(UnnamedAddr::Global),
795        }
796    }
797}
798
799impl Linkage {
800    pub(crate) fn from_llvm(linkage: LLVMLinkage) -> Self {
801        use LLVMLinkage::*;
802        match linkage {
803            LLVMExternalLinkage => Linkage::External,
804            LLVMAvailableExternallyLinkage => Linkage::AvailableExternally,
805            LLVMLinkOnceAnyLinkage => Linkage::LinkOnceAny,
806            LLVMLinkOnceODRLinkage => Linkage::LinkOnceODR,
807            LLVMLinkOnceODRAutoHideLinkage => Linkage::LinkOnceODRAutoHide,
808            LLVMWeakAnyLinkage => Linkage::WeakAny,
809            LLVMWeakODRLinkage => Linkage::WeakODR,
810            LLVMAppendingLinkage => Linkage::Appending,
811            LLVMInternalLinkage => Linkage::Internal,
812            LLVMPrivateLinkage => Linkage::Private,
813            LLVMDLLImportLinkage => Linkage::DLLImport,
814            LLVMDLLExportLinkage => Linkage::DLLExport,
815            LLVMExternalWeakLinkage => Linkage::ExternalWeak,
816            LLVMGhostLinkage => Linkage::Ghost,
817            LLVMCommonLinkage => Linkage::Common,
818            LLVMLinkerPrivateLinkage => Linkage::LinkerPrivate,
819            LLVMLinkerPrivateWeakLinkage => Linkage::LinkerPrivateWeak,
820        }
821    }
822}
823
824impl Visibility {
825    pub(crate) fn from_llvm(visibility: LLVMVisibility) -> Self {
826        use LLVMVisibility::*;
827        match visibility {
828            LLVMDefaultVisibility => Visibility::Default,
829            LLVMHiddenVisibility => Visibility::Hidden,
830            LLVMProtectedVisibility => Visibility::Protected,
831        }
832    }
833}
834
835impl DLLStorageClass {
836    pub(crate) fn from_llvm(dllsc: LLVMDLLStorageClass) -> Self {
837        use LLVMDLLStorageClass::*;
838        match dllsc {
839            LLVMDefaultStorageClass => DLLStorageClass::Default,
840            LLVMDLLImportStorageClass => DLLStorageClass::Import,
841            LLVMDLLExportStorageClass => DLLStorageClass::Export,
842        }
843    }
844}
845
846impl ThreadLocalMode {
847    pub(crate) fn from_llvm(tlm: LLVMThreadLocalMode) -> Self {
848        use LLVMThreadLocalMode::*;
849        match tlm {
850            LLVMNotThreadLocal => ThreadLocalMode::NotThreadLocal,
851            LLVMGeneralDynamicTLSModel => ThreadLocalMode::GeneralDynamic,
852            LLVMLocalDynamicTLSModel => ThreadLocalMode::LocalDynamic,
853            LLVMInitialExecTLSModel => ThreadLocalMode::InitialExec,
854            LLVMLocalExecTLSModel => ThreadLocalMode::LocalExec,
855        }
856    }
857}
858
859impl Comdat {
860    pub(crate) fn from_llvm_ref(comdat: LLVMComdatRef) -> Self {
861        Self {
862            name: "error: not yet implemented: Comdat.name".to_owned(), // there appears to not be a getter for this in the LLVM C API?  I could be misunderstanding something
863            selection_kind: SelectionKind::from_llvm(unsafe { LLVMGetComdatSelectionKind(comdat) }),
864        }
865    }
866}
867
868impl SelectionKind {
869    pub(crate) fn from_llvm(sk: LLVMComdatSelectionKind) -> Self {
870        use LLVMComdatSelectionKind::*;
871        match sk {
872            LLVMAnyComdatSelectionKind => SelectionKind::Any,
873            LLVMExactMatchComdatSelectionKind => SelectionKind::ExactMatch,
874            LLVMLargestComdatSelectionKind => SelectionKind::Largest,
875            LLVMNoDuplicatesComdatSelectionKind => SelectionKind::NoDuplicates,
876            LLVMSameSizeComdatSelectionKind => SelectionKind::SameSize,
877        }
878    }
879}
880
881impl Default for DataLayout {
882    fn default() -> Self {
883        Self {
884            layout_str: String::new(),
885            endianness: Endianness::BigEndian,
886            stack_alignment: None,
887            program_address_space: 0,
888            alloca_address_space: 0,
889            alignments: Alignments::default(),
890            mangling: None,
891            native_int_widths: None,
892            non_integral_ptr_types: HashSet::new(),
893        }
894    }
895}
896
897impl DataLayout {
898    pub(crate) fn from_module_ref(module: LLVMModuleRef) -> Self {
899        let layout_str = unsafe { get_data_layout_str(module) };
900        let mut data_layout = DataLayout {
901            layout_str,
902            ..Default::default()
903        };
904        for spec in data_layout.layout_str.split('-') {
905            if spec == "E" {
906                data_layout.endianness = Endianness::BigEndian;
907            } else if spec == "e" {
908                data_layout.endianness = Endianness::LittleEndian;
909            } else if let Some(stripped) = spec.strip_prefix('S') {
910                data_layout.stack_alignment =
911                    Some(stripped.parse().expect("datalayout 'S': Failed to parse"));
912            } else if let Some(stripped) = spec.strip_prefix('P') {
913                data_layout.program_address_space =
914                    stripped.parse().expect("datalayout 'P': Failed to parse");
915            } else if let Some(stripped) = spec.strip_prefix('A') {
916                data_layout.alloca_address_space =
917                    stripped.parse().expect("datalayout 'A': Failed to parse");
918            } else if spec.starts_with('p') {
919                let mut chunks = spec.split(':');
920                let first_chunk = chunks.next().unwrap();
921                let addr_space: AddrSpace = if first_chunk == "p" {
922                    0
923                } else {
924                    first_chunk[1 ..]
925                        .parse()
926                        .expect("datalayout 'p': Failed to parse address space")
927                };
928                let second_chunk = chunks
929                    .next()
930                    .expect("datalayout 'p' spec should have a size chunk");
931                let size: u32 = second_chunk
932                    .parse()
933                    .expect("datalayout 'p': Failed to parse pointer size");
934                let third_chunk = chunks
935                    .next()
936                    .expect("datalayout 'p' spec should have an abi chunk");
937                let abi: u32 = third_chunk
938                    .parse()
939                    .expect("datalayout 'p': Failed to parse abi");
940                let pref: u32 = if let Some(fourth_chunk) = chunks.next() {
941                    fourth_chunk
942                        .parse()
943                        .expect("datalayout 'p': Failed to parse pref")
944                } else {
945                    abi
946                };
947                let idx: u32 = if let Some(fifth_chunk) = chunks.next() {
948                    fifth_chunk
949                        .parse()
950                        .expect("datalayout 'p': Failed to parse idx")
951                } else {
952                    size
953                };
954                assert!(chunks.next().is_none(), "datalayout 'p': Too many chunks");
955                data_layout.alignments.pointer_layouts.insert(
956                    addr_space,
957                    PointerLayout {
958                        size,
959                        alignment: Alignment { abi, pref },
960                        index_size: idx,
961                    },
962                );
963            } else if spec.starts_with('i') {
964                let mut chunks = spec.split(':');
965                let first_chunk = chunks.next().unwrap();
966                let size: u32 = first_chunk[1 ..]
967                    .parse()
968                    .expect("datalayout 'i': Failed to parse size");
969                let second_chunk = chunks
970                    .next()
971                    .expect("datalayout 'i' spec should have an abi chunk");
972                let abi: u32 = second_chunk
973                    .parse()
974                    .expect("datalayout 'i': Failed to parse abi");
975                let pref = if let Some(third_chunk) = chunks.next() {
976                    third_chunk
977                        .parse()
978                        .expect("datalayout 'i': Failed to parse pref")
979                } else {
980                    abi
981                };
982                assert!(chunks.next().is_none(), "datalayout 'i': Too many chunks");
983                data_layout
984                    .alignments
985                    .int_alignments
986                    .insert(size, Alignment { abi, pref });
987            } else if spec.starts_with('v') {
988                let mut chunks = spec.split(':');
989                let first_chunk = chunks.next().unwrap();
990                let size: u32 = first_chunk[1 ..]
991                    .parse()
992                    .expect("datalayout 'v': Failed to parse size");
993                let second_chunk = chunks
994                    .next()
995                    .expect("datalayout 'v' spec should have an abi chunk");
996                let abi: u32 = second_chunk
997                    .parse()
998                    .expect("datalayout 'v': Failed to parse abi");
999                let pref = if let Some(third_chunk) = chunks.next() {
1000                    third_chunk
1001                        .parse()
1002                        .expect("datalayout 'v': Failed to parse pref")
1003                } else {
1004                    abi
1005                };
1006                assert!(chunks.next().is_none(), "datalayout 'v': Too many chunks");
1007                data_layout
1008                    .alignments
1009                    .vec_alignments
1010                    .insert(size, Alignment { abi, pref });
1011            } else if spec.starts_with('f') {
1012                let mut chunks = spec.split(':');
1013                let first_chunk = chunks.next().unwrap();
1014                let size: u32 = first_chunk[1 ..]
1015                    .parse()
1016                    .expect("datalayout 'f': Failed to parse size");
1017                let second_chunk = chunks
1018                    .next()
1019                    .expect("datalayout 'f' spec should have an abi chunk");
1020                let abi: u32 = second_chunk
1021                    .parse()
1022                    .expect("datalayout 'f': Failed to parse abi");
1023                let pref = if let Some(third_chunk) = chunks.next() {
1024                    third_chunk
1025                        .parse()
1026                        .expect("datalayout 'f': Failed to parse pref")
1027                } else {
1028                    abi
1029                };
1030                assert!(chunks.next().is_none(), "datalayout 'f': Too many chunks");
1031                data_layout
1032                    .alignments
1033                    .fp_alignments
1034                    .insert(size, Alignment { abi, pref });
1035            } else if spec.starts_with('a') {
1036                let mut chunks = spec.split(':');
1037                let first_chunk = chunks.next().unwrap();
1038                assert!(first_chunk == "a" || first_chunk == "a0");
1039                let second_chunk = chunks
1040                    .next()
1041                    .expect("datalayout 'a' spec should have an abi chunk");
1042                let abi: u32 = second_chunk
1043                    .parse()
1044                    .expect("datalayout 'a': Failed to parse abi");
1045                let pref = if let Some(third_chunk) = chunks.next() {
1046                    third_chunk
1047                        .parse()
1048                        .expect("datalayout 'a': Failed to parse pref")
1049                } else {
1050                    abi
1051                };
1052                assert!(chunks.next().is_none(), "datalayout 'a': Too many chunks");
1053                data_layout.alignments.agg_alignment = Alignment { abi, pref };
1054            } else if let Some(stripped) = spec.strip_prefix("Fi") {
1055                let abi: u32 = stripped
1056                    .parse()
1057                    .expect("datalayout 'Fi': Failed to parse abi");
1058                data_layout.alignments.fptr_alignment = FunctionPtrAlignment {
1059                    independent: true,
1060                    abi,
1061                };
1062                data_layout.alignments.fptr_alignment_as_alignment =
1063                    Alignment { abi, pref: abi };
1064            } else if let Some(stripped) = spec.strip_prefix("Fn") {
1065                let abi: u32 = stripped
1066                    .parse()
1067                    .expect("datalayout 'Fn': Failed to parse abi");
1068                data_layout.alignments.fptr_alignment = FunctionPtrAlignment {
1069                    independent: false,
1070                    abi,
1071                };
1072                data_layout.alignments.fptr_alignment_as_alignment =
1073                    Alignment { abi, pref: abi };
1074            } else if spec.starts_with('m') {
1075                let mut chunks = spec.split(':');
1076                let first_chunk = chunks.next().unwrap();
1077                assert_eq!(first_chunk, "m");
1078                let second_chunk = chunks
1079                    .next()
1080                    .expect("datalayout 'm' spec should have a mangling chunk");
1081                let mangling = match second_chunk {
1082                    "e" => Mangling::ELF,
1083                    "m" => Mangling::MIPS,
1084                    "o" => Mangling::MachO,
1085                    "x" => Mangling::WindowsX86COFF,
1086                    "w" => Mangling::WindowsCOFF,
1087                    #[cfg(feature = "llvm-11-or-greater")]
1088                    "a" => Mangling::XCOFF,
1089                    _ => panic!("datalayout 'm': Unknown mangling {:?}", second_chunk),
1090                };
1091                assert!(chunks.next().is_none(), "datalayout 'm': Too many chunks");
1092                data_layout.mangling = Some(mangling);
1093            } else if spec.starts_with("ni") {
1094                let mut chunks = spec.split(':');
1095                let first_chunk = chunks.next().unwrap();
1096                assert_eq!(first_chunk, "ni");
1097                for chunk in chunks {
1098                    let addr_space: AddrSpace = chunk
1099                        .parse()
1100                        .expect("datalayout 'ni': Failed to parse addr space");
1101                    assert_ne!(addr_space, 0, "LLVM spec does not allow address space 0 to have non-integral pointer types");
1102                    data_layout.non_integral_ptr_types.insert(addr_space);
1103                }
1104            } else if spec.starts_with('n') {
1105                let native_int_widths = data_layout
1106                    .native_int_widths
1107                    .get_or_insert_with(HashSet::new);
1108                let mut chunks = spec.split(':');
1109                let first_chunk = chunks.next().unwrap();
1110                let size = first_chunk[1 ..]
1111                    .parse()
1112                    .expect("datalayout 'n': Failed to parse first size");
1113                native_int_widths.insert(size);
1114                for chunk in chunks {
1115                    let size = chunk.parse().expect("datalayout 'n': Failed to parse size");
1116                    native_int_widths.insert(size);
1117                }
1118            } else if spec.is_empty() {
1119                // do nothing
1120            } else {
1121                panic!("datalayout: Unknown spec {:?}", spec);
1122            }
1123        }
1124        data_layout
1125    }
1126}
1127
1128impl Default for Alignments {
1129    fn default() -> Self {
1130        Self {
1131            // Explicit alignments for various sizes of integers (in bits). Sizes not
1132            // specified here are determined according to the rules described in the
1133            // Data Layout docs.
1134            int_alignments: vec![
1135                (1, Alignment { abi: 8, pref: 8 }),
1136                (8, Alignment { abi: 8, pref: 8 }),
1137                (16, Alignment { abi: 16, pref: 16 }),
1138                (32, Alignment { abi: 32, pref: 32 }),
1139                (64, Alignment { abi: 32, pref: 64 }),
1140            ]
1141            .into_iter()
1142            .collect(),
1143            // Explicit alignments for various sizes of vectors (in bits). Sizes not
1144            // specified here are determined according to the rules described in the
1145            // Data Layout docs.
1146            vec_alignments: vec![
1147                (64, Alignment { abi: 64, pref: 64 }),
1148                (
1149                    128,
1150                    Alignment {
1151                        abi: 128,
1152                        pref: 128,
1153                    },
1154                ),
1155            ]
1156            .into_iter()
1157            .collect(),
1158            // Alignment for floating-point types, by size (in bits)
1159            fp_alignments: vec![
1160                (16, Alignment { abi: 16, pref: 16 }),
1161                (32, Alignment { abi: 32, pref: 32 }),
1162                (64, Alignment { abi: 64, pref: 64 }),
1163                (
1164                    128,
1165                    Alignment {
1166                        abi: 128,
1167                        pref: 128,
1168                    },
1169                ),
1170            ]
1171            .into_iter()
1172            .collect(),
1173            // Alignment for aggregate types (structs, arrays)
1174            agg_alignment: Alignment { abi: 0, pref: 64 },
1175            // Alignment for function pointers
1176            fptr_alignment: FunctionPtrAlignment {
1177                independent: true,
1178                abi: 64,
1179            },
1180            // Alignment for function pointers, as an `Alignment`
1181            fptr_alignment_as_alignment: Alignment { abi: 64, pref: 64 },
1182            // Layout details for (non-function-pointer) pointers, by address space
1183            pointer_layouts: vec![(
1184                0,
1185                PointerLayout {
1186                    size: 64,
1187                    alignment: Alignment { abi: 64, pref: 64 },
1188                    index_size: 64,
1189                },
1190            )]
1191            .into_iter()
1192            .collect(),
1193        }
1194    }
1195}