Skip to main content

dxil_reader/
module.rs

1//! LLVM 3.7 IR as DXIL stores it, read from the bitstream tree: the type table, module values (globals, functions,
2//! constants), metadata, value names and function bodies. Only what DXIL programs use is decoded; any other record in a
3//! function body is refused by name. A program built with debug information (`-Zi`) keeps it as debug metadata nodes
4//! ([`Metadata::Debug`], [`crate::debug_info`]), each instruction's source location ([`Instruction::debug_loc`]), a
5//! body's own metadata ([`Function::metadata`]) and the metadata its debug intrinsics are passed ([`Value::Metadata`]).
6//! The use-list orders of a body's values are skipped. The metadata attached to an instruction or a function is kept as
7//! the pairs the file stores ([`Instruction::attachments`], [`Function::attachments`], with the kind names in
8//! [`Module::kinds`]), `dx.precise` also as [`Instruction::precise`]; the attribute groups and lists are kept as stored
9//! ([`Module::attribute_groups`], [`Module::attribute_lists`]) and each function value names its list.
10use crate::bitstream::{Block, Record};
11pub use crate::debug_info::{DebugLoc, DebugNode};
12use crate::{Result, error};
13
14const MODULE: u64 = 8;
15const PARAMATTR: u64 = 9;
16const PARAMATTR_GROUP: u64 = 10;
17const CONSTANTS: u64 = 11;
18const FUNCTION: u64 = 12;
19const VALUE_SYMTAB: u64 = 14;
20const METADATA: u64 = 15;
21const METADATA_ATTACHMENT: u64 = 16;
22const TYPES: u64 = 17;
23const USELIST: u64 = 18;
24const BLOCKINFO: u64 = 0;
25
26/// Values a module may hold (globals, constants and function-body values together).
27const MAX_VALUES: usize = 1 << 22;
28const MAX_TYPES: usize = 1 << 16;
29
30/// An index into [`Module::types`].
31pub type TypeId = usize;
32/// An index into the values: the module's [`Module::values`], then a function body's own [`Function::locals`].
33pub type ValueId = usize;
34/// An index into [`Module::metadata`].
35pub type MetadataId = usize;
36
37/// A type of the module's type table.
38#[derive(Clone, Debug, PartialEq, Eq)]
39pub enum Type {
40    /// `void`.
41    Void,
42    /// `label`, the type of a basic block.
43    Label,
44    /// `metadata`.
45    Metadata,
46    /// `half`.
47    Half,
48    /// `float`.
49    Float,
50    /// `double`.
51    Double,
52    /// An integer of this many bits (1 to 64).
53    Integer(u32),
54    /// A pointer to the type, in this LLVM address space (the `TYPE_CODE_POINTER` record's second operand). Pointers to
55    /// one type in two spaces are two types.
56    Pointer(TypeId, u32),
57    /// An array of this many elements of the type.
58    Array(u64, TypeId),
59    /// A vector of this many lanes of the type.
60    Vector(u64, TypeId),
61    /// A structure.
62    Struct {
63        /// Its name, where it has one.
64        name: Option<String>,
65        /// The types of its fields, in order.
66        elements: Vec<TypeId>,
67        /// Its fields are laid out without padding (`<{ ... }>`).
68        packed: bool,
69        /// A literal structure (`TYPE_CODE_STRUCT_ANON`), which is its body: two literal structures of the same fields
70        /// are one type. An identified one (`TYPE_CODE_STRUCT_NAMED`) is a type of its own, named or numbered.
71        literal: bool,
72    },
73    /// A named structure without a body.
74    Opaque(Option<String>),
75    /// A function type.
76    Function {
77        /// Whether it takes a variable argument list.
78        vararg: bool,
79        /// The return type.
80        ret: TypeId,
81        /// The parameter types.
82        params: Vec<TypeId>,
83    },
84}
85
86/// A module-level constant.
87#[derive(Clone, Debug, PartialEq)]
88pub enum Constant {
89    /// The null value of the constant's type (zero).
90    Null,
91    /// An undefined value.
92    Undef,
93    /// An integer's bits, sign-extended from its width.
94    Integer(i64),
95    /// A float's bits (half, float or double by its type).
96    Float(u64),
97    /// An array, structure or vector of other constants (value ids).
98    Aggregate(Vec<ValueId>),
99    /// A constant array or vector of numbers, as stored (the bits of each element).
100    Data(Vec<u64>),
101    /// An array of `i8` given as text: its bytes, with the terminating zero a `CST_CODE_CSTRING` record implies.
102    String(Vec<u8>),
103    /// A constant `getelementptr`: the base (a global) and its indices (module constants).
104    Gep {
105        /// The base global.
106        base: ValueId,
107        /// The index constants.
108        indices: Vec<ValueId>,
109        /// The type the first index steps over: the base's pointee.
110        source: TypeId,
111        /// `inbounds` (`CST_CODE_CE_INBOUNDS_GEP`).
112        inbounds: bool,
113    },
114    /// A constant cast of a module value (to the type of the constant).
115    Cast {
116        /// The cast.
117        op: CastOp,
118        /// The value cast.
119        value: ValueId,
120    },
121    /// A constant binary operation on module values.
122    Binary {
123        /// The operation.
124        op: BinaryOp,
125        /// The left operand.
126        lhs: ValueId,
127        /// The right operand.
128        rhs: ValueId,
129        /// The record's flags, as [`Instruction::flags`].
130        flags: u64,
131    },
132    /// A constant comparison of module values, by its LLVM predicate (as [`Op::Compare`]).
133    Compare {
134        /// The predicate.
135        predicate: u64,
136        /// The left operand.
137        lhs: ValueId,
138        /// The right operand.
139        rhs: ValueId,
140    },
141}
142
143/// How a global value links (LLVM's `LinkageTypes`, decoded from the bitcode's linkage codes).
144#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
145pub enum Linkage {
146    /// Visible to other modules (codes 0, 5, 6 and 15).
147    #[default]
148    External,
149    /// Appended to the same-named array of other modules (2).
150    Appending,
151    /// Local to the module (3).
152    Internal,
153    /// Weak, kept even where unreferenced (16).
154    WeakAny,
155    /// Weak, every definition equivalent (17).
156    WeakOdr,
157    /// Merged with other definitions, dropped where unreferenced (18).
158    LinkOnceAny,
159    /// As `LinkOnceAny`, every definition equivalent (19).
160    LinkOnceOdr,
161    /// A weak reference to an external symbol (7).
162    ExternWeak,
163    /// A tentative definition (8).
164    Common,
165    /// Local to the module and left out of its symbol table (9, 13 and 14).
166    Private,
167    /// Defined elsewhere, given here for optimisation (12).
168    AvailableExternally,
169}
170
171/// What the module states of a function or a global variable beyond its type: how it links, and the other properties
172/// of its `MODULE_CODE_FUNCTION` or `MODULE_CODE_GLOBALVAR` record.
173#[derive(Clone, Debug, Default, PartialEq, Eq)]
174pub struct GlobalProperties {
175    /// How it links.
176    pub linkage: Linkage,
177    /// Its visibility: 0 default, 1 hidden, 2 protected.
178    pub visibility: u8,
179    /// Its DLL storage class: 0 default, 1 `dllimport`, 2 `dllexport`.
180    pub dll_storage: u8,
181    /// Its address is not significant (`unnamed_addr`).
182    pub unnamed_addr: bool,
183    /// The section it is placed in, where the record names one.
184    pub section: Option<String>,
185    /// Its alignment in bytes; 0 where it states none.
186    pub alignment: u64,
187}
188
189/// A value the module numbers.
190#[derive(Clone, Debug, PartialEq)]
191pub enum Value {
192    /// A function, defined or declared.
193    Function {
194        /// Its function type.
195        ty: TypeId,
196        /// Whether it is only declared (it has no body).
197        declaration: bool,
198        /// The attribute list it names (an index into [`Module::attribute_lists`]), where it names one.
199        attributes: Option<usize>,
200        /// Its linkage and the other properties of its record.
201        properties: GlobalProperties,
202        /// Its calling convention (LLVM's `CallingConv::ID`; 0 is C's).
203        calling_conv: u64,
204        /// The garbage collector it names, where it names one.
205        gc: Option<String>,
206    },
207    /// A global variable.
208    Global {
209        /// The global's type: a pointer to `value_ty`.
210        ty: TypeId,
211        /// The type of the value it holds.
212        value_ty: TypeId,
213        /// Its initial value (a module constant), if it has one.
214        init: Option<ValueId>,
215        /// Whether it is a constant (read only).
216        constant: bool,
217        /// LLVM's address space: 0 the default, 3 group shared. No other space occurs in the programs of the games read.
218        address_space: u32,
219        /// Its linkage and the other properties of its record.
220        properties: GlobalProperties,
221        /// Its thread-local model: 0 none, 1 general dynamic, 2 local dynamic, 3 initial exec, 4 local exec.
222        thread_local: u8,
223        /// Its initial value may be set outside the module (`externally_initialized`).
224        externally_initialized: bool,
225    },
226    /// A constant.
227    Constant(Constant),
228    /// A function argument or an instruction's result.
229    Local,
230    /// Metadata a call passes to a parameter of type `metadata` (LLVM's `MetadataAsValue`: the debug intrinsics'
231    /// variables, expressions and the values they describe). These are a function body's own, after its other values:
232    /// they have no place in the bitcode's value numbering.
233    Metadata(MetadataId),
234}
235
236/// A metadata record.
237#[derive(Clone, Debug, PartialEq)]
238pub enum Metadata {
239    /// A metadata string, as stored (not checked to be UTF-8 here).
240    String(Vec<u8>),
241    /// A value as metadata.
242    Value {
243        /// The value's type.
244        ty: TypeId,
245        /// The value.
246        value: ValueId,
247    },
248    /// Operands; `None` is a null operand.
249    Node(Vec<Option<MetadataId>>),
250    /// A node of its own, never merged with a node of the same operands (`METADATA_DISTINCT_NODE`: the loop
251    /// identifiers `llvm.loop` names, whose first operand is the node itself).
252    Distinct(Vec<Option<MetadataId>>),
253    /// A debug-information node (a program built with `-Zi`), and whether it is distinct.
254    Debug {
255        /// The node is distinct (never merged with one of the same fields).
256        distinct: bool,
257        /// The node.
258        node: DebugNode,
259    },
260}
261
262impl Metadata {
263    /// The operands of a node of generic operands, distinct or not; `None` for a string, a value or a debug node (whose
264    /// operands [`DebugNode::operands`] gives).
265    pub fn operands(&self) -> Option<&[Option<MetadataId>]> {
266        match self {
267            Metadata::Node(ops) | Metadata::Distinct(ops) => Some(ops),
268            Metadata::String(_) | Metadata::Value { .. } | Metadata::Debug { .. } => None,
269        }
270    }
271}
272
273/// A binary operator code (LLVM's `BinaryOpcodes`).
274#[derive(Clone, Copy, Debug, PartialEq, Eq)]
275pub enum BinaryOp {
276    /// Addition.
277    Add,
278    /// Subtraction.
279    Sub,
280    /// Multiplication.
281    Mul,
282    /// Unsigned division.
283    UDiv,
284    /// Signed division.
285    SDiv,
286    /// Unsigned remainder.
287    URem,
288    /// Signed remainder.
289    SRem,
290    /// Shift left.
291    Shl,
292    /// Logical shift right.
293    LShr,
294    /// Arithmetic shift right.
295    AShr,
296    /// Bitwise and.
297    And,
298    /// Bitwise or.
299    Or,
300    /// Bitwise exclusive or.
301    Xor,
302}
303/// A cast opcode (LLVM's `CastOpcodes`).
304#[derive(Clone, Copy, Debug, PartialEq, Eq)]
305pub enum CastOp {
306    /// Truncate an integer.
307    Trunc,
308    /// Zero-extend an integer.
309    ZExt,
310    /// Sign-extend an integer.
311    SExt,
312    /// Float to unsigned integer.
313    FpToUi,
314    /// Float to signed integer.
315    FpToSi,
316    /// Unsigned integer to float.
317    UiToFp,
318    /// Signed integer to float.
319    SiToFp,
320    /// Truncate a float.
321    FpTrunc,
322    /// Extend a float.
323    FpExt,
324    /// Pointer to integer.
325    PtrToInt,
326    /// Integer to pointer.
327    IntToPtr,
328    /// Reinterpret the bits as another type.
329    BitCast,
330    /// A pointer into another address space.
331    AddrSpaceCast,
332}
333
334/// An instruction, with the value ids (absolute) and block numbers it names.
335#[derive(Clone, Debug, PartialEq)]
336pub enum Op {
337    /// Integer opcodes apply to integers; for floating types Add, Sub, Mul, (S)Div, (S)Rem are the float forms.
338    Binary {
339        /// The operation.
340        op: BinaryOp,
341        /// The left operand.
342        lhs: ValueId,
343        /// The right operand.
344        rhs: ValueId,
345    },
346    /// A conversion.
347    Cast {
348        /// The conversion.
349        op: CastOp,
350        /// The value converted; the instruction's result type is the target.
351        value: ValueId,
352    },
353    /// A comparison by its LLVM predicate (0..15 float, 32..41 integer).
354    Compare {
355        /// The predicate.
356        predicate: u64,
357        /// The left operand.
358        lhs: ValueId,
359        /// The right operand.
360        rhs: ValueId,
361    },
362    /// `select`: one of two values by a condition.
363    Select {
364        /// The condition (an `i1`).
365        condition: ValueId,
366        /// The value when the condition is true.
367        then: ValueId,
368        /// The value when it is false.
369        otherwise: ValueId,
370    },
371    /// A field or element of an aggregate.
372    ExtractValue {
373        /// The aggregate.
374        aggregate: ValueId,
375        /// The indices into it, outermost first.
376        indices: Vec<u64>,
377    },
378    /// An aggregate with one field or element replaced.
379    InsertValue {
380        /// The aggregate.
381        aggregate: ValueId,
382        /// The new field or element.
383        value: ValueId,
384        /// The indices of the replaced one, outermost first.
385        indices: Vec<u64>,
386    },
387    /// One lane of a vector.
388    ExtractElement {
389        /// The vector.
390        vector: ValueId,
391        /// The lane number.
392        index: ValueId,
393    },
394    /// A vector with one lane replaced.
395    InsertElement {
396        /// The vector.
397        vector: ValueId,
398        /// The new lane.
399        value: ValueId,
400        /// The lane number.
401        index: ValueId,
402    },
403    /// The lanes of two vectors the mask (a constant vector of lane numbers) picks.
404    ShuffleVector {
405        /// The first vector.
406        first: ValueId,
407        /// The second vector.
408        second: ValueId,
409        /// The constant vector of lane numbers.
410        mask: ValueId,
411    },
412    /// A call.
413    Call {
414        /// The callee.
415        function: ValueId,
416        /// The arguments, one per parameter.
417        args: Vec<ValueId>,
418        /// The attribute list of the call site (an index into [`Module::attribute_lists`]), where it names one.
419        attributes: Option<usize>,
420        /// The calling convention (0 is C's).
421        calling_conv: u64,
422        /// Whether it is marked a tail call.
423        tail: TailCall,
424    },
425    /// The value from the predecessor block control came from: (value, block) pairs.
426    Phi {
427        /// The (value, predecessor block) pairs.
428        incoming: Vec<(ValueId, usize)>,
429    },
430    /// `ret`, with the value returned where there is one.
431    Return(Option<ValueId>),
432    /// An unconditional branch.
433    Branch {
434        /// The block branched to.
435        target: usize,
436    },
437    /// A conditional branch.
438    CondBranch {
439        /// The condition (an `i1`).
440        condition: ValueId,
441        /// The block when it is true.
442        then: usize,
443        /// The block when it is false.
444        otherwise: usize,
445    },
446    /// A multi-way branch: the value, the default block and the (case constant, block) pairs.
447    Switch {
448        /// The value switched on.
449        value: ValueId,
450        /// The block when no case matches.
451        default: usize,
452        /// The (case constant, block) pairs.
453        cases: Vec<(ValueId, usize)>,
454    },
455    /// `unreachable`.
456    Unreachable,
457    /// A local variable of this type (the result is a pointer to it).
458    Alloca {
459        /// The type of the variable.
460        ty: TypeId,
461        /// The number of variables (an integer value; the compilers write the constant `i32 1`).
462        size: ValueId,
463        /// The alignment in bytes; 0 where the record states none.
464        align: u64,
465        /// The variable is an argument passed in memory (`inalloca`).
466        inalloca: bool,
467    },
468    /// A load.
469    Load {
470        /// The pointer loaded from; the result type is the loaded type.
471        pointer: ValueId,
472        /// The alignment in bytes; 0 where the record states none.
473        align: u64,
474        /// `volatile`.
475        volatile: bool,
476        /// The ordering of an atomic load (`FUNC_CODE_INST_LOADATOMIC`).
477        atomic: Option<Atomic>,
478    },
479    /// A store.
480    Store {
481        /// The pointer stored to.
482        pointer: ValueId,
483        /// The value stored.
484        value: ValueId,
485        /// The alignment in bytes; 0 where the record states none.
486        align: u64,
487        /// `volatile`.
488        volatile: bool,
489        /// The ordering of an atomic store (`FUNC_CODE_INST_STOREATOMIC`).
490        atomic: Option<Atomic>,
491    },
492    /// `getelementptr`: the base pointer and its indices (the first steps over the pointer itself).
493    Gep {
494        /// The base pointer.
495        base: ValueId,
496        /// The indices.
497        indices: Vec<ValueId>,
498        /// The type the first index steps over: the base's pointee, which the record states.
499        source: TypeId,
500        /// `inbounds`.
501        inbounds: bool,
502    },
503    /// `atomicrmw`: the operation (LLVM's code: 0 xchg, 1 add, 2 sub, 3 and, 4 nand, 5 or, 6 xor, 7 max, 8 min, 9 umax,
504    /// 10 umin); the result is the value the pointer held.
505    AtomicRmw {
506        /// The pointer.
507        pointer: ValueId,
508        /// The value operated with.
509        value: ValueId,
510        /// The operation code.
511        op: u64,
512        /// `volatile`.
513        volatile: bool,
514        /// Its ordering.
515        atomic: Atomic,
516    },
517    /// `cmpxchg`: the result is the pair (the value the pointer held, whether it was swapped).
518    CmpXchg {
519        /// The pointer.
520        pointer: ValueId,
521        /// The value compared with.
522        compare: ValueId,
523        /// The new value stored where the comparison holds.
524        value: ValueId,
525        /// `volatile`.
526        volatile: bool,
527        /// `weak`: it may fail even where the comparison holds.
528        weak: bool,
529        /// The ordering where it swaps, and the scope of both.
530        success: Atomic,
531        /// The ordering where it does not.
532        failure: Ordering,
533    },
534    /// `fence`: ordering between invocations, which a lockstep reading does not have.
535    Fence(Atomic),
536}
537
538/// The ordering of an atomic operation (LLVM's `AtomicOrdering`, by its bitcode code 0 to 6).
539#[derive(Clone, Copy, Debug, PartialEq, Eq)]
540pub enum Ordering {
541    /// Not atomic (0).
542    NotAtomic,
543    /// `unordered` (1).
544    Unordered,
545    /// `monotonic` (2).
546    Monotonic,
547    /// `acquire` (3).
548    Acquire,
549    /// `release` (4).
550    Release,
551    /// `acq_rel` (5).
552    AcquireRelease,
553    /// `seq_cst` (6).
554    SequentiallyConsistent,
555}
556
557/// The ordering of an atomic operation and the invocations it orders against.
558#[derive(Clone, Copy, Debug, PartialEq, Eq)]
559pub struct Atomic {
560    /// The ordering.
561    pub ordering: Ordering,
562    /// Only against the invocation itself (`singlethread`); otherwise against all.
563    pub single_thread: bool,
564}
565
566/// Whether a call is marked a tail call.
567#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
568pub enum TailCall {
569    /// Not marked.
570    #[default]
571    None,
572    /// `tail`.
573    Tail,
574    /// `musttail`.
575    MustTail,
576}
577
578impl Op {
579    /// The values the operation reads (a call's arguments, not its callee; a phi's incoming values).
580    pub fn operands(&self) -> Vec<ValueId> {
581        match self {
582            Op::Binary { lhs, rhs, .. } | Op::Compare { lhs, rhs, .. } => vec![*lhs, *rhs],
583            Op::Cast { value, .. } => vec![*value],
584            Op::Select {
585                condition,
586                then,
587                otherwise,
588            } => vec![*condition, *then, *otherwise],
589            Op::ExtractValue { aggregate, .. } => vec![*aggregate],
590            Op::InsertValue { aggregate, value, .. } => vec![*aggregate, *value],
591            Op::ExtractElement { vector, index } => vec![*vector, *index],
592            Op::InsertElement { vector, value, index } => vec![*vector, *value, *index],
593            Op::ShuffleVector { first, second, mask } => vec![*first, *second, *mask],
594            Op::Call { args, .. } => args.clone(),
595            Op::Phi { incoming } => incoming.iter().map(|(v, _)| *v).collect(),
596            Op::Return(value) => value.iter().copied().collect(),
597            Op::CondBranch { condition, .. } => vec![*condition],
598            Op::Switch { value, cases, .. } => std::iter::once(*value)
599                .chain(cases.iter().map(|(c, _)| *c))
600                .collect(),
601            Op::Load { pointer, .. } => vec![*pointer],
602            Op::Store { pointer, value, .. } | Op::AtomicRmw { pointer, value, .. } => vec![*pointer, *value],
603            Op::Gep { base, indices, .. } => std::iter::once(*base).chain(indices.iter().copied()).collect(),
604            Op::CmpXchg {
605                pointer,
606                compare,
607                value,
608                ..
609            } => vec![*pointer, *compare, *value],
610            Op::Alloca { size, .. } => vec![*size],
611            Op::Branch { .. } | Op::Unreachable | Op::Fence(_) => Vec::new(),
612        }
613    }
614
615    /// The basic blocks the operation names (a branch's targets, a phi's predecessors).
616    pub fn blocks(&self) -> Vec<usize> {
617        match self {
618            Op::Branch { target } => vec![*target],
619            Op::CondBranch { then, otherwise, .. } => vec![*then, *otherwise],
620            Op::Switch { default, cases, .. } => std::iter::once(*default)
621                .chain(cases.iter().map(|(_, b)| *b))
622                .collect(),
623            Op::Phi { incoming } => incoming.iter().map(|(_, b)| *b).collect(),
624            _ => Vec::new(),
625        }
626    }
627}
628
629/// An instruction of a function body.
630#[derive(Clone, Debug, PartialEq)]
631pub struct Instruction {
632    /// What it does.
633    pub op: Op,
634    /// The result's value id and type, when the instruction produces one.
635    pub result: Option<(ValueId, TypeId)>,
636    /// The basic block it belongs to.
637    pub block: usize,
638    /// Bit offset of its record.
639    pub at: usize,
640    /// The optimisation flags its record states (0 for none): for an integer `add`, `sub`, `mul` or `shl` bit 0 is
641    /// `nuw` and bit 1 `nsw`; for `udiv`, `sdiv`, `lshr` and `ashr` bit 0 is `exact`; for a float operation or
642    /// comparison they are the fast-math flags (bit 0 `fast`, then `nnan`, `ninf`, `nsz` and `arcp`).
643    pub flags: u64,
644    /// The instruction carries the `dx.precise` attachment, which the compiler writes for HLSL's `precise`: the value
645    /// is not to be fused or reassociated. In skate.'s stock programs it is on calls only: 88,541 `tertiary` (mad),
646    /// 13,005 `loadInput`, 3,546 `unary`, 1,421 `dot3`, 331 `legacyF16ToF32`, 307 `binary`, 213 `dot4` and 105 `dot2`,
647    /// in vertex programs (107,109 instructions in 3,185 of 3,341) and compute programs (360 in 12), in no pixel
648    /// program; none of Elden Ring's has it.
649    pub precise: bool,
650    /// The metadata attached to the instruction, in the order the file stores the pairs (`dx.precise` among them).
651    pub attachments: Vec<Attachment>,
652    /// The instruction's source location, in a program with debug information.
653    pub debug_loc: Option<DebugLoc>,
654}
655
656/// A metadata node attached to an instruction or a function: the kind (the id [`Module::kinds`] names) and the node.
657/// In the games' programs the kinds are `dx.controlflow.hints`, `llvm.loop`, `tbaa`, `noalias`, `alias.scope`, `range`
658/// and `dx.precise`.
659#[derive(Clone, Copy, Debug, PartialEq, Eq)]
660pub struct Attachment {
661    /// The metadata kind id (`dx.precise`, `tbaa`, ... by [`Module::kind_name`]).
662    pub kind: u64,
663    /// The attached node, an id into [`Module::metadata`].
664    pub node: MetadataId,
665}
666
667/// An attribute of an attribute group, as the bitcode stores it.
668#[derive(Clone, Debug, PartialEq, Eq)]
669pub enum Attribute {
670    /// A flag attribute, by LLVM's bitcode kind number (see [`attribute_name`]).
671    Enum(u64),
672    /// An attribute with an integer value: its kind number and the value.
673    Integer(u64, u64),
674    /// A string attribute: the key and the value (empty where the attribute has none).
675    String(String, String),
676}
677
678/// A group of attributes, which an attribute list names by its id.
679#[derive(Clone, Debug, PartialEq, Eq)]
680pub struct AttributeGroup {
681    /// The group's id, as the lists name it.
682    pub id: u64,
683    /// The slot the attributes apply to: [`FUNCTION_SLOT`] the function itself, 0 its result, 1 and up its parameters.
684    pub slot: u64,
685    /// The attributes, in the order stored.
686    pub attributes: Vec<Attribute>,
687}
688
689/// The slot of an [`AttributeGroup`] that holds a function's own attributes (`0xFFFFFFFF`).
690pub const FUNCTION_SLOT: u64 = 0xFFFF_FFFF;
691
692/// The name of an LLVM 3.7 enum attribute's bitcode kind number (`nounwind` for 18), for the kinds whose number dxc's own
693/// listing confirms: 9 `noalias`, 11 `nocapture`, 12 `noduplicate`, 17 `noreturn`, 18 `nounwind`, 20 `readnone`, 21
694/// `readonly`, 39 `nonnull`. They are the kinds the games' programs and the test compilations use.
695pub fn attribute_name(kind: u64) -> Option<&'static str> {
696    Some(match kind {
697        9 => "noalias",
698        11 => "nocapture",
699        12 => "noduplicate",
700        17 => "noreturn",
701        18 => "nounwind",
702        20 => "readnone",
703        21 => "readonly",
704        39 => "nonnull",
705        _ => return None,
706    })
707}
708
709/// A function body.
710#[derive(Clone, Debug, PartialEq)]
711pub struct Function {
712    /// The function's module value id.
713    pub value: ValueId,
714    /// The number of basic blocks.
715    pub blocks: usize,
716    /// The instructions of all blocks, in order.
717    pub instructions: Vec<Instruction>,
718    /// The body's own values (arguments, constants, instruction results) and their types; their ids start at
719    /// `first`, after the module's values.
720    pub first: ValueId,
721    /// The values of the body.
722    pub locals: Vec<Value>,
723    /// The types of [`Function::locals`].
724    pub local_types: Vec<TypeId>,
725    /// The metadata attached to the function itself (the attachment records of the body that name no instruction).
726    pub attachments: Vec<Attachment>,
727    /// The body's own metadata (in a program with debug information, the values its debug intrinsics describe, each a
728    /// [`Metadata::Value`] of one of its values): their ids continue the module's, from `first_metadata`.
729    pub metadata: Vec<Metadata>,
730    /// The id of the body's first own metadata: the module's metadata count.
731    pub first_metadata: MetadataId,
732    /// The body's symbol table: the names of its values (arguments and instruction results, by absolute id).
733    pub names: Vec<(ValueId, String)>,
734    /// The names of its basic blocks that have one.
735    pub block_names: Vec<(usize, String)>,
736    /// The use-list orders of its basic blocks (`USELIST_CODE_BB`): each block and the position its uses take, in the
737    /// order LLVM would otherwise keep them (the most recent first). They are the order of its predecessors.
738    pub block_use_orders: Vec<(usize, Vec<u64>)>,
739}
740
741impl Function {
742    /// The body's name for one of its values, where its symbol table has one.
743    pub fn name(&self, value: ValueId) -> Option<&str> {
744        self.names
745            .iter()
746            .find(|(v, _)| *v == value)
747            .map(|(_, n)| n.as_str())
748    }
749    /// The name of a basic block, where it has one.
750    pub fn block_name(&self, block: usize) -> Option<&str> {
751        self.block_names
752            .iter()
753            .find(|(b, _)| *b == block)
754            .map(|(_, n)| n.as_str())
755    }
756}
757
758/// A module: its types, values, metadata and function bodies.
759#[derive(Clone, Debug, Default, PartialEq)]
760pub struct Module {
761    /// The type table.
762    pub types: Vec<Type>,
763    /// The module's values by id (globals, functions, module constants); a function body's own values continue the
764    /// numbering in its [`Function`].
765    pub values: Vec<Value>,
766    /// Each value's type.
767    pub value_types: Vec<TypeId>,
768    /// The module's symbol table: the names of the module values that have one (a function body's own are in its
769    /// [`Function::names`]).
770    pub names: Vec<(ValueId, String)>,
771    /// The target triple (`dxil-ms-dx`), where the module states one.
772    pub triple: Option<String>,
773    /// The data layout, where the module states one.
774    pub datalayout: Option<String>,
775    /// The module's inline assembly, where it has any.
776    pub asm: Option<String>,
777    /// The metadata records, by [`MetadataId`].
778    pub metadata: Vec<Metadata>,
779    /// The bit of the bitcode each metadata record (by id) starts at, for the locations of reflection errors.
780    pub metadata_at: Vec<usize>,
781    /// The named metadata (`dx.entryPoints`, ...): the name and the records it lists.
782    pub named_metadata: Vec<(String, Vec<MetadataId>)>,
783    /// The bit each named metadata record (by index in `named_metadata`) starts at.
784    pub named_metadata_at: Vec<usize>,
785    /// The bit of the bitcode the module block starts at: where a record the module lacks would be.
786    pub at: usize,
787    /// The function bodies, in the order of their definitions.
788    pub functions: Vec<Function>,
789    /// The id of the module's `dx.precise` metadata kind (the kind [`Instruction::precise`] reads), where it names one.
790    pub precise_kind: Option<u64>,
791    /// The module's metadata kinds: each id and its name, in the order stored.
792    pub kinds: Vec<(u64, String)>,
793    /// The attribute groups, in the order stored.
794    pub attribute_groups: Vec<AttributeGroup>,
795    /// The attribute lists, in the order stored: the ids of the groups each lists. A function value's `attributes` is an
796    /// index into this.
797    pub attribute_lists: Vec<Vec<u64>>,
798}
799
800fn op(r: &Record, i: usize) -> Result<u64> {
801    r.operands
802        .get(i)
803        .copied()
804        .ok_or_else(|| error(r.at, format!("record {} lacks operand {i}", r.code)))
805}
806fn text(ops: &[u64], at: usize) -> Result<Vec<u8>> {
807    ops.iter()
808        .map(|&c| u8::try_from(c).map_err(|_| error(at, "character above 255")))
809        .collect()
810}
811/// The zero-terminated string starting at operand `from` of an attribute record, and the index after its terminator.
812fn c_string(r: &Record, from: usize) -> Result<(String, usize)> {
813    let rest = r.operands.get(from..).unwrap_or_default();
814    let n = rest
815        .iter()
816        .position(|&c| c == 0)
817        .ok_or_else(|| error(r.at, "an attribute string without its terminator"))?;
818    let bytes = text(rest.get(..n).unwrap_or_default(), r.at)?;
819    Ok((
820        String::from_utf8_lossy(&bytes).into_owned(),
821        from.saturating_add(n).saturating_add(1),
822    ))
823}
824fn utf8(bytes: Vec<u8>, at: usize) -> Result<String> {
825    String::from_utf8(bytes).map_err(|_| error(at, "name is not UTF-8"))
826}
827fn signed_vbr(v: u64) -> i64 {
828    if v & 1 == 0 {
829        i64::try_from(v >> 1).unwrap_or(i64::MAX)
830    } else if v == 1 {
831        i64::MIN
832    } else {
833        i64::try_from(v >> 1).map_or(i64::MIN, i64::wrapping_neg)
834    }
835}
836
837impl Module {
838    fn ty(&self, id: u64, at: usize) -> Result<TypeId> {
839        let id = usize::try_from(id).map_err(|_| error(at, "type id"))?;
840        if id < self.types.len() {
841            Ok(id)
842        } else {
843            Err(error(at, format!("type {id} undefined")))
844        }
845    }
846    /// The type `id`, which an earlier record has already checked against the table (an error where it has not).
847    fn type_at(&self, id: TypeId, at: usize) -> Result<&Type> {
848        self.types
849            .get(id)
850            .ok_or_else(|| error(at, format!("type {id} of {} types", self.types.len())))
851    }
852    /// The id of the type `ty`, appended to the table where it is not there yet.
853    fn intern(&mut self, ty: Type) -> TypeId {
854        match self.types.iter().position(|x| *x == ty) {
855            Some(p) => p,
856            None => {
857                self.types.push(ty);
858                self.types.len().saturating_sub(1)
859            }
860        }
861    }
862    /// The module's name for a value, where its symbol table has one.
863    pub fn name(&self, value: ValueId) -> Option<&str> {
864        self.names
865            .iter()
866            .find(|(v, _)| *v == value)
867            .map(|(_, n)| n.as_str())
868    }
869    fn push(&mut self, value: Value, ty: TypeId, at: usize) -> Result<ValueId> {
870        if self.values.len() >= MAX_VALUES {
871            return Err(error(at, "too many values"));
872        }
873        self.values.push(value);
874        self.value_types.push(ty);
875        Ok(self.values.len().saturating_sub(1))
876    }
877
878    fn read_types(&mut self, block: &Block) -> Result<()> {
879        let mut struct_name: Option<String> = None;
880        for r in block.records() {
881            if self.types.len() >= MAX_TYPES {
882                return Err(error(r.at, "too many types"));
883            }
884            let t = match r.code {
885                1 => continue, // NUMENTRY
886                2 => Type::Void,
887                3 => Type::Float,
888                4 => Type::Double,
889                5 => Type::Label,
890                6 => Type::Opaque(struct_name.take()),
891                7 => Type::Integer(
892                    u32::try_from(op(r, 0)?)
893                        .ok()
894                        .filter(|w| (1..=64).contains(w))
895                        .ok_or_else(|| error(r.at, "integer width"))?,
896                ),
897                8 => Type::Pointer(
898                    self.ty(op(r, 0)?, r.at)?,
899                    u32::try_from(op(r, 1)?).map_err(|_| error(r.at, "pointer address space"))?,
900                ),
901                10 => Type::Half,
902                11 => Type::Array(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
903                12 => Type::Vector(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
904                16 => Type::Metadata,
905                // STRUCT_ANON and STRUCT_NAMED: [packed, element types...]
906                18 | 20 => Type::Struct {
907                    name: if r.code == 20 { struct_name.take() } else { None },
908                    packed: op(r, 0)? != 0,
909                    literal: r.code == 18,
910                    elements: r
911                        .operands
912                        .get(1..)
913                        .unwrap_or_default()
914                        .iter()
915                        .map(|&t| self.ty(t, r.at))
916                        .collect::<Result<_>>()?,
917                },
918                19 => {
919                    struct_name = Some(utf8(text(&r.operands, r.at)?, r.at)?);
920                    continue;
921                }
922                21 => Type::Function {
923                    vararg: op(r, 0)? != 0,
924                    ret: self.ty(op(r, 1)?, r.at)?,
925                    params: r
926                        .operands
927                        .get(2..)
928                        .unwrap_or_default()
929                        .iter()
930                        .map(|&t| self.ty(t, r.at))
931                        .collect::<Result<_>>()?,
932                },
933                other => return Err(error(r.at, format!("type record {other}"))),
934            };
935            self.types.push(t);
936        }
937        Ok(())
938    }
939
940    /// Read a constants block, appending its values. Value ids inside aggregates are absolute.
941    fn read_constants(&mut self, block: &Block) -> Result<()> {
942        let mut ty: Option<TypeId> = None;
943        for r in block.records() {
944            let id = |v: u64| usize::try_from(v).map_err(|_| error(r.at, "value id"));
945            if r.code == 1 {
946                ty = Some(self.ty(op(r, 0)?, r.at)?);
947                continue;
948            }
949            let t = ty.ok_or_else(|| error(r.at, "constant before SETTYPE"))?;
950            let c = match r.code {
951                2 => Constant::Null,
952                3 => Constant::Undef,
953                4 => Constant::Integer(signed_vbr(op(r, 0)?)),
954                6 => Constant::Float(op(r, 0)?),
955                7 => Constant::Aggregate(
956                    r.operands
957                        .iter()
958                        .map(|&v| usize::try_from(v).map_err(|_| error(r.at, "value id")))
959                        .collect::<Result<_>>()?,
960                ),
961                // STRING and CSTRING, whose terminating zero is not stored
962                8 => Constant::String(text(&r.operands, r.at)?),
963                9 => {
964                    let mut bytes = text(&r.operands, r.at)?;
965                    bytes.push(0);
966                    Constant::String(bytes)
967                }
968                22 => Constant::Data(r.operands.clone()),
969                // CE_GEP and CE_INBOUNDS_GEP: [source type,] then (type, value) pairs, the first the base
970                12 | 20 => {
971                    let explicit = r.operands.len() % 2 == 1;
972                    let ops = r.operands.get(usize::from(explicit)..).unwrap_or_default();
973                    let (pairs, rest) = ops.as_chunks::<2>();
974                    let ([base_ty, base], true) = (
975                        pairs.first().unwrap_or(&[0, 0]),
976                        rest.is_empty() && !pairs.is_empty(),
977                    ) else {
978                        return Err(error(r.at, "constant getelementptr operands"));
979                    };
980                    let source = if explicit {
981                        self.ty(op(r, 0)?, r.at)?
982                    } else {
983                        match self.type_at(self.ty(*base_ty, r.at)?, r.at)? {
984                            Type::Pointer(pointee, _) => *pointee,
985                            _ => {
986                                return Err(error(
987                                    r.at,
988                                    "a constant getelementptr of a value that is not a pointer",
989                                ));
990                            }
991                        }
992                    };
993                    Constant::Gep {
994                        base: id(*base)?,
995                        indices: pairs
996                            .iter()
997                            .skip(1)
998                            .map(|[_, index]| id(*index))
999                            .collect::<Result<_>>()?,
1000                        source,
1001                        inbounds: r.code == 20,
1002                    }
1003                }
1004                // CE_BINOP: [opcode, lhs, rhs, flags?]
1005                10 => Constant::Binary {
1006                    op: binary(op(r, 0)?, r.at)?,
1007                    lhs: id(op(r, 1)?)?,
1008                    rhs: id(op(r, 2)?)?,
1009                    flags: r.operands.get(3).copied().unwrap_or(0),
1010                },
1011                // CE_CMP: [operand type, lhs, rhs, predicate]
1012                17 => Constant::Compare {
1013                    lhs: id(op(r, 1)?)?,
1014                    rhs: id(op(r, 2)?)?,
1015                    predicate: op(r, 3)?,
1016                },
1017                // CE_CAST: [opcode, operand type, operand]
1018                11 => Constant::Cast {
1019                    op: cast(op(r, 0)?, r.at)?,
1020                    value: id(op(r, 2)?)?,
1021                },
1022                other => {
1023                    return Err(error(
1024                        r.at,
1025                        format!(
1026                            "constant record {other} ({} is not supported)",
1027                            constant_record(other)
1028                        ),
1029                    ));
1030                }
1031            };
1032            self.push(Value::Constant(c), t, r.at)?;
1033        }
1034        Ok(())
1035    }
1036
1037    fn read_metadata(&mut self, block: &Block) -> Result<()> {
1038        let mut name: Option<String> = None;
1039        let md = |v: u64, at: usize| usize::try_from(v).map_err(|_| error(at, "metadata id"));
1040        for r in block.records() {
1041            match r.code {
1042                1 => {
1043                    self.metadata.push(Metadata::String(text(&r.operands, r.at)?));
1044                    self.metadata_at.push(r.at);
1045                }
1046                2 => {
1047                    self.metadata.push(Metadata::Value {
1048                        ty: self.ty(op(r, 0)?, r.at)?,
1049                        value: md(op(r, 1)?, r.at)?,
1050                    });
1051                    self.metadata_at.push(r.at);
1052                }
1053                // NODE and DISTINCT_NODE: [metadata id + 1, or 0 for null...]
1054                3 | 5 => {
1055                    let ops = r
1056                        .operands
1057                        .iter()
1058                        .map(|&v| {
1059                            if v == 0 {
1060                                Ok(None)
1061                            } else {
1062                                md(v.saturating_sub(1), r.at).map(Some)
1063                            }
1064                        })
1065                        .collect::<Result<_>>()?;
1066                    self.metadata.push(if r.code == 3 {
1067                        Metadata::Node(ops)
1068                    } else {
1069                        Metadata::Distinct(ops)
1070                    });
1071                    self.metadata_at.push(r.at);
1072                }
1073                4 => name = Some(utf8(text(&r.operands, r.at)?, r.at)?),
1074                10 => {
1075                    let n = name
1076                        .take()
1077                        .ok_or_else(|| error(r.at, "named node without a name"))?;
1078                    let nodes = r.operands.iter().map(|&v| md(v, r.at)).collect::<Result<_>>()?;
1079                    self.named_metadata.push((n, nodes));
1080                    self.named_metadata_at.push(r.at);
1081                }
1082                6 => {
1083                    // KIND: [kind id, name]
1084                    let id = op(r, 0)?;
1085                    let bytes = text(r.operands.get(1..).unwrap_or_default(), r.at)?;
1086                    if bytes == b"dx.precise" {
1087                        self.precise_kind = Some(id);
1088                    }
1089                    self.kinds
1090                        .push((id, String::from_utf8_lossy(&bytes).into_owned()));
1091                }
1092                7 | 12..=32 => {
1093                    let code = u32::try_from(r.code).unwrap_or(u32::MAX);
1094                    let (distinct, node) = crate::debug_info::read(code, &r.operands, r.at)?;
1095                    self.metadata.push(Metadata::Debug { distinct, node });
1096                    self.metadata_at.push(r.at);
1097                }
1098                other => return Err(error(r.at, format!("metadata record {other}"))),
1099            }
1100        }
1101        Ok(())
1102    }
1103
1104    /// The attribute groups: records `[group id, slot, attribute...]`, an attribute being `[0, kind]` (a flag), `[1, kind,
1105    /// value]`, `[3, key..., 0]` or `[4, key..., 0, value..., 0]`.
1106    fn read_attribute_groups(&mut self, block: &Block) -> Result<()> {
1107        for r in block.records().filter(|r| r.code == 3) {
1108            let mut attributes = Vec::new();
1109            let mut i = 2;
1110            while i < r.operands.len() {
1111                match op(r, i)? {
1112                    0 => {
1113                        attributes.push(Attribute::Enum(op(r, i.saturating_add(1))?));
1114                        i = i.saturating_add(2);
1115                    }
1116                    1 => {
1117                        attributes.push(Attribute::Integer(
1118                            op(r, i.saturating_add(1))?,
1119                            op(r, i.saturating_add(2))?,
1120                        ));
1121                        i = i.saturating_add(3);
1122                    }
1123                    form @ (3 | 4) => {
1124                        let (key, next) = c_string(r, i.saturating_add(1))?;
1125                        let (value, next) = if form == 4 {
1126                            c_string(r, next)?
1127                        } else {
1128                            (String::new(), next)
1129                        };
1130                        attributes.push(Attribute::String(key, value));
1131                        i = next;
1132                    }
1133                    other => return Err(error(r.at, format!("attribute encoding {other}"))),
1134                }
1135            }
1136            self.attribute_groups.push(AttributeGroup {
1137                id: op(r, 0)?,
1138                slot: op(r, 1)?,
1139                attributes,
1140            });
1141        }
1142        Ok(())
1143    }
1144
1145    /// The attribute lists: records `[group id...]`.
1146    fn read_attribute_lists(&mut self, block: &Block) {
1147        for r in block.records().filter(|r| r.code == 2) {
1148            self.attribute_lists.push(r.operands.clone());
1149        }
1150    }
1151
1152    /// The name of a metadata kind id, where the module names it.
1153    pub fn kind_name(&self, kind: u64) -> Option<&str> {
1154        self.kinds
1155            .iter()
1156            .find(|(k, _)| *k == kind)
1157            .map(|(_, n)| n.as_str())
1158    }
1159
1160    /// The node of the attachment among `attachments` whose kind is called `name`.
1161    pub fn attachment(&self, attachments: &[Attachment], name: &str) -> Option<MetadataId> {
1162        attachments
1163            .iter()
1164            .find(|a| self.kind_name(a.kind) == Some(name))
1165            .map(|a| a.node)
1166    }
1167
1168    /// The attributes a function value carries on itself (the groups of its list whose slot is [`FUNCTION_SLOT`]); none
1169    /// for a value that is not a function or names no list.
1170    pub fn function_attributes(&self, function: ValueId) -> Vec<&Attribute> {
1171        let Some(Value::Function {
1172            attributes: Some(list),
1173            ..
1174        }) = self.values.get(function)
1175        else {
1176            return Vec::new();
1177        };
1178        let Some(groups) = self.attribute_lists.get(*list) else {
1179            return Vec::new();
1180        };
1181        groups
1182            .iter()
1183            .filter_map(|id| {
1184                self.attribute_groups
1185                    .iter()
1186                    .find(|g| g.id == *id && g.slot == FUNCTION_SLOT)
1187            })
1188            .flat_map(|g| g.attributes.iter())
1189            .collect()
1190    }
1191
1192    /// The value of the string attribute `key` on a function (empty where the attribute has no value), if it carries it.
1193    pub fn string_attribute(&self, function: ValueId, key: &str) -> Option<&str> {
1194        self.function_attributes(function)
1195            .into_iter()
1196            .find_map(|a| match a {
1197                Attribute::String(k, v) if k == key => Some(v.as_str()),
1198                _ => None,
1199            })
1200    }
1201}
1202
1203/// A symbol table's names: of values `[value id, name...]` (`VST_ENTRY`, and `VST_FNENTRY` with an offset before the
1204/// name) and of basic blocks `[block, name...]` (`VST_BBENTRY`).
1205type Symbols = (Vec<(ValueId, String)>, Vec<(usize, String)>);
1206
1207fn read_symbols(block: &Block) -> Result<Symbols> {
1208    let (mut values, mut blocks) = (Vec::new(), Vec::new());
1209    for r in block.records() {
1210        let id = usize::try_from(op(r, 0)?).map_err(|_| error(r.at, "value id"))?;
1211        let skip = if r.code == 3 { 2 } else { 1 };
1212        let name = utf8(text(r.operands.get(skip..).unwrap_or_default(), r.at)?, r.at)?;
1213        match r.code {
1214            1 | 3 => values.push((id, name)),
1215            2 => blocks.push((id, name)),
1216            other => return Err(error(r.at, format!("symbol record {other}"))),
1217        }
1218    }
1219    Ok((values, blocks))
1220}
1221
1222/// Function-body decoding state: relative value numbering (module version 1).
1223struct Body<'m> {
1224    m: &'m mut Module,
1225    block: usize,
1226    blocks: usize,
1227}
1228impl Body<'_> {
1229    fn next(&self) -> usize {
1230        self.m.values.len()
1231    }
1232    /// A relative operand (absolute = next - operand), with its explicit type following when it is a forward
1233    /// reference (a value defined later in the function's layout). Returns the value id and its type, and advances `i`.
1234    fn value_type(&self, r: &Record, i: &mut usize) -> Result<(ValueId, TypeId)> {
1235        let id = self.absolute(op(r, *i)?, r.at)?;
1236        *i = i.saturating_add(1);
1237        if id < self.next() {
1238            let t = self
1239                .m
1240                .value_types
1241                .get(id)
1242                .copied()
1243                .ok_or_else(|| error(r.at, format!("value {id} has no type")))?;
1244            Ok((id, t))
1245        } else {
1246            let t = self.m.ty(op(r, *i)?, r.at)?;
1247            *i = i.saturating_add(1);
1248            Ok((id, t))
1249        }
1250    }
1251    /// A relative operand whose type is known from another operand: a forward reference carries none.
1252    fn value(&self, r: &Record, i: &mut usize) -> Result<ValueId> {
1253        let id = self.absolute(op(r, *i)?, r.at)?;
1254        *i = i.saturating_add(1);
1255        Ok(id)
1256    }
1257    /// The absolute id a relative operand names: the next id minus the operand, in 32 bits as LLVM writes it (a value
1258    /// defined later is a forward reference, which wraps).
1259    fn absolute(&self, relative: u64, at: usize) -> Result<ValueId> {
1260        let relative = u32::try_from(relative)
1261            .map_err(|_| error(at, format!("relative value id {relative} wider than 32 bits")))?;
1262        let next = u32::try_from(self.next()).map_err(|_| error(at, "too many values"))?;
1263        Ok(next.wrapping_sub(relative) as usize)
1264    }
1265    /// The pointer to `t` in address space `space`.
1266    fn pointer_to(&mut self, t: TypeId, space: u32) -> TypeId {
1267        self.m.intern(Type::Pointer(t, space))
1268    }
1269    /// The index a constant integer value stands for, if it is one defined in the module or this function.
1270    fn constant_index(&self, v: ValueId) -> Option<usize> {
1271        match self.m.values.get(v) {
1272            Some(Value::Constant(Constant::Integer(i))) => usize::try_from(*i).ok(),
1273            Some(Value::Constant(Constant::Null)) => Some(0),
1274            _ => None,
1275        }
1276    }
1277    fn result(&mut self, ty: TypeId, at: usize) -> Result<Option<(ValueId, TypeId)>> {
1278        if *self.m.type_at(ty, at)? == Type::Void {
1279            return Ok(None);
1280        }
1281        Ok(Some((self.m.push(Value::Local, ty, at)?, ty)))
1282    }
1283}
1284
1285/// An alignment as records store it: 0 for none, otherwise the log2 of the bytes plus one.
1286fn alignment(stored: u64, at: usize) -> Result<u64> {
1287    match stored {
1288        0 => Ok(0),
1289        n if n <= 30 => Ok(1u64.wrapping_shl(u32::try_from(n).unwrap_or(0).wrapping_sub(1))),
1290        _ => Err(error(at, "alignment")),
1291    }
1292}
1293fn ordering(code: u64, at: usize) -> Result<Ordering> {
1294    Ok(match code {
1295        0 => Ordering::NotAtomic,
1296        1 => Ordering::Unordered,
1297        2 => Ordering::Monotonic,
1298        3 => Ordering::Acquire,
1299        4 => Ordering::Release,
1300        5 => Ordering::AcquireRelease,
1301        6 => Ordering::SequentiallyConsistent,
1302        other => return Err(error(at, format!("atomic ordering {other}"))),
1303    })
1304}
1305/// An ordering and a scope (0 single thread, 1 all).
1306fn atomic(ordering_code: u64, scope: u64, at: usize) -> Result<Atomic> {
1307    Ok(Atomic {
1308        ordering: ordering(ordering_code, at)?,
1309        single_thread: match scope {
1310            0 => true,
1311            1 => false,
1312            other => return Err(error(at, format!("synchronisation scope {other}"))),
1313        },
1314    })
1315}
1316fn binary(code: u64, at: usize) -> Result<BinaryOp> {
1317    Ok(match code {
1318        0 => BinaryOp::Add,
1319        1 => BinaryOp::Sub,
1320        2 => BinaryOp::Mul,
1321        3 => BinaryOp::UDiv,
1322        4 => BinaryOp::SDiv,
1323        5 => BinaryOp::URem,
1324        6 => BinaryOp::SRem,
1325        7 => BinaryOp::Shl,
1326        8 => BinaryOp::LShr,
1327        9 => BinaryOp::AShr,
1328        10 => BinaryOp::And,
1329        11 => BinaryOp::Or,
1330        12 => BinaryOp::Xor,
1331        other => return Err(error(at, format!("binary opcode {other}"))),
1332    })
1333}
1334fn cast(code: u64, at: usize) -> Result<CastOp> {
1335    Ok(match code {
1336        0 => CastOp::Trunc,
1337        1 => CastOp::ZExt,
1338        2 => CastOp::SExt,
1339        3 => CastOp::FpToUi,
1340        4 => CastOp::FpToSi,
1341        5 => CastOp::UiToFp,
1342        6 => CastOp::SiToFp,
1343        7 => CastOp::FpTrunc,
1344        8 => CastOp::FpExt,
1345        9 => CastOp::PtrToInt,
1346        10 => CastOp::IntToPtr,
1347        11 => CastOp::BitCast,
1348        12 => CastOp::AddrSpaceCast,
1349        other => return Err(error(at, format!("cast opcode {other}"))),
1350    })
1351}
1352/// The linkage and other properties of a global variable's or function's record, from the operands at the indices given
1353/// (they differ between the two records). A field past the record's end is its default; a comdat is refused, and so
1354/// is a linkage code that implies one (1, 4, 10 and 11, in a record without the comdat field).
1355#[expect(clippy::too_many_arguments, reason = "the field positions of the two records")]
1356fn global_properties(
1357    r: &Record,
1358    linkage: usize,
1359    alignment_at: usize,
1360    section: usize,
1361    visibility: usize,
1362    unnamed_addr: usize,
1363    dll_storage: usize,
1364    comdat: usize,
1365    sections: &[String],
1366) -> Result<GlobalProperties> {
1367    let raw = op(r, linkage)?;
1368    let decoded = match raw {
1369        0 | 5 | 6 | 15 => Linkage::External,
1370        2 => Linkage::Appending,
1371        3 => Linkage::Internal,
1372        7 => Linkage::ExternWeak,
1373        8 => Linkage::Common,
1374        9 | 13 | 14 => Linkage::Private,
1375        12 => Linkage::AvailableExternally,
1376        1 | 16 => Linkage::WeakAny,
1377        10 | 17 => Linkage::WeakOdr,
1378        4 | 18 => Linkage::LinkOnceAny,
1379        11 | 19 => Linkage::LinkOnceOdr,
1380        _ => Linkage::External,
1381    };
1382    let field = |i: usize| r.operands.get(i).copied();
1383    if field(comdat).map_or(matches!(raw, 1 | 4 | 10 | 11), |c| c != 0) {
1384        return Err(error(r.at, "a global value in a comdat is not supported"));
1385    }
1386    let local = matches!(decoded, Linkage::Internal | Linkage::Private);
1387    Ok(GlobalProperties {
1388        linkage: decoded,
1389        // local linkage has the default visibility, whatever the record says
1390        visibility: match field(visibility).unwrap_or(0) {
1391            _ if local => 0,
1392            v @ 0..=2 => u8::try_from(v).unwrap_or(0),
1393            _ => 0,
1394        },
1395        // a record without the field says it by the old linkage codes 5 (dllimport) and 6 (dllexport)
1396        dll_storage: match field(dll_storage) {
1397            Some(v @ 0..=2) => u8::try_from(v).unwrap_or(0),
1398            Some(_) => 0,
1399            None => match raw {
1400                5 => 1,
1401                6 => 2,
1402                _ => 0,
1403            },
1404        },
1405        unnamed_addr: field(unnamed_addr).is_some_and(|v| v != 0),
1406        section: match op(r, section)? {
1407            0 => None,
1408            n => Some(
1409                usize::try_from(n.saturating_sub(1))
1410                    .ok()
1411                    .and_then(|n| sections.get(n))
1412                    .cloned()
1413                    .ok_or_else(|| error(r.at, "a global value names a section the module lacks"))?,
1414            ),
1415        },
1416        alignment: alignment(op(r, alignment_at)?, r.at)?,
1417    })
1418}
1419
1420/// What a constants record this reader refuses holds.
1421fn constant_record(code: u64) -> &'static str {
1422    match code {
1423        5 => "an integer wider than 64 bits",
1424        13 => "a constant select",
1425        14 => "a constant extractelement",
1426        15 => "a constant insertelement",
1427        16 | 19 => "a constant shufflevector",
1428        18 => "inline assembly (old form)",
1429        21 => "a block address",
1430        23 | 30 => "inline assembly",
1431        _ => "an unknown constant",
1432    }
1433}
1434
1435/// The name of a function-body record code this reader refuses.
1436fn refused(code: u64) -> &'static str {
1437    match code {
1438        4 | 30 => "getelementptr (old form)",
1439        13 => "invoke",
1440        23 => "va_arg",
1441        31 => "indirectbr",
1442        37 => "cmpxchg (old form)",
1443        59 => "atomicrmw (new form)",
1444        39 => "resume",
1445        40 | 47 => "landingpad",
1446        _ => "unknown instruction record",
1447    }
1448}
1449
1450/// Reads a function's attachment block: a record `[instruction, (kind, node)...]` (an odd number of operands) attaches
1451/// the pairs to that instruction, a record of an even number of operands, `(kind, node)...`, to the function itself.
1452/// An instruction given the `dx.precise` kind is also marked [`Instruction::precise`].
1453fn read_attachments(
1454    precise: Option<u64>,
1455    block: &Block,
1456    instructions: &mut [Instruction],
1457    function: &mut Vec<Attachment>,
1458) -> Result<()> {
1459    for r in block.records().filter(|r| r.code == 11) {
1460        let per_instruction = r.operands.len() % 2 == 1;
1461        let mut attachments = Vec::new();
1462        let (pairs, _) = r
1463            .operands
1464            .get(usize::from(per_instruction)..)
1465            .unwrap_or_default()
1466            .as_chunks::<2>();
1467        for &[kind, node] in pairs {
1468            attachments.push(Attachment {
1469                kind,
1470                node: usize::try_from(node).map_err(|_| error(r.at, "attachment node"))?,
1471            });
1472        }
1473        if !per_instruction {
1474            function.extend(attachments);
1475            continue;
1476        }
1477        let at = usize::try_from(op(r, 0)?).map_err(|_| error(r.at, "attachment instruction"))?;
1478        let instruction = instructions.get_mut(at).ok_or_else(|| {
1479            error(
1480                r.at,
1481                format!("an attachment names instruction {at} of a shorter body"),
1482            )
1483        })?;
1484        if precise.is_some_and(|kind| attachments.iter().any(|a| a.kind == kind)) {
1485            instruction.precise = true;
1486        }
1487        instruction.attachments.extend(attachments);
1488    }
1489    Ok(())
1490}
1491
1492impl Module {
1493    fn read_function(&mut self, block: &Block, value: ValueId) -> Result<Function> {
1494        let fty = match self.value_types.get(value).and_then(|&t| self.types.get(t)) {
1495            Some(Type::Pointer(t, _)) => *t,
1496            _ => return Err(error(block.at, "function value is not a function pointer")),
1497        };
1498        let params = match self.type_at(fty, block.at)? {
1499            Type::Function { params, .. } => params.clone(),
1500            _ => return Err(error(block.at, "function type")),
1501        };
1502        let base = self.values.len();
1503        for p in params {
1504            self.push(Value::Local, p, block.at)?;
1505        }
1506        let mut body = Body {
1507            m: self,
1508            block: 0,
1509            blocks: 0,
1510        };
1511        let mut instructions: Vec<Instruction> = Vec::new();
1512        let mut function_attachments = Vec::new();
1513        let mut local_metadata = Vec::new();
1514        // the metadata each call passes (instruction, argument, metadata id), and the last debug location
1515        let mut metadata_args: Vec<(usize, usize, MetadataId)> = Vec::new();
1516        let mut last_loc: Option<DebugLoc> = None;
1517        let (mut names, mut block_names, mut block_use_orders) = (Vec::new(), Vec::new(), Vec::new());
1518        for e in &block.elements {
1519            let r = match e {
1520                crate::bitstream::Element::Block(b) => {
1521                    match b.id {
1522                        CONSTANTS => body.m.read_constants(b)?,
1523                        VALUE_SYMTAB => {
1524                            let (values, blocks) = read_symbols(b)?;
1525                            names.extend(values);
1526                            block_names.extend(blocks);
1527                        }
1528                        METADATA_ATTACHMENT => read_attachments(
1529                            body.m.precise_kind,
1530                            b,
1531                            &mut instructions,
1532                            &mut function_attachments,
1533                        )?,
1534                        // function-local metadata: values of the body as metadata, `[type, absolute value id]`
1535                        METADATA => {
1536                            for r in b.records() {
1537                                if r.code != 2 {
1538                                    return Err(error(
1539                                        r.at,
1540                                        format!("metadata record {} in a function body", r.code),
1541                                    ));
1542                                }
1543                                let ty = body.m.ty(op(r, 0)?, r.at)?;
1544                                let value =
1545                                    usize::try_from(op(r, 1)?).map_err(|_| error(r.at, "value id"))?;
1546                                local_metadata.push(Metadata::Value { ty, value });
1547                            }
1548                        }
1549                        // the use-list orders: of basic blocks [position..., block] (they order its predecessors),
1550                        // and of values [position..., value], which say nothing a listing shows
1551                        USELIST => {
1552                            for r in b.records() {
1553                                let (last, order) = r
1554                                    .operands
1555                                    .split_last()
1556                                    .filter(|(_, order)| order.len() >= 2)
1557                                    .ok_or_else(|| error(r.at, "use-list order"))?;
1558                                match r.code {
1559                                    1 => {}
1560                                    2 => block_use_orders.push((
1561                                        usize::try_from(*last).map_err(|_| error(r.at, "use-list block"))?,
1562                                        order.to_vec(),
1563                                    )),
1564                                    other => return Err(error(r.at, format!("use-list record {other}"))),
1565                                }
1566                            }
1567                        }
1568                        other => return Err(error(b.at, format!("block {other} in a function"))),
1569                    }
1570                    continue;
1571                }
1572                crate::bitstream::Element::Record(r) => r,
1573            };
1574            let mut i = 0;
1575            let mut flags = 0;
1576            let (op, ty): (Op, Option<TypeId>) = match r.code {
1577                1 => {
1578                    body.blocks = usize::try_from(op(r, 0)?)
1579                        .ok()
1580                        .filter(|&n| n > 0 && n <= 1 << 16)
1581                        .ok_or_else(|| error(r.at, "basic block count"))?;
1582                    continue;
1583                }
1584                // DEBUG_LOC: [line, column, scope id + 1 or 0, inlined-at id + 1 or 0], of the last instruction
1585                35 => {
1586                    let node = |i: usize| -> Result<Option<MetadataId>> {
1587                        match op(r, i)? {
1588                            0 => Ok(None),
1589                            v => usize::try_from(v.saturating_sub(1))
1590                                .map(Some)
1591                                .map_err(|_| error(r.at, "metadata id")),
1592                        }
1593                    };
1594                    let loc = DebugLoc {
1595                        line: crate::debug_info::unsigned(op(r, 0)?),
1596                        column: crate::debug_info::column(crate::debug_info::unsigned(op(r, 1)?)),
1597                        scope: node(2)?,
1598                        inlined_at: node(3)?,
1599                    };
1600                    let last = instructions
1601                        .last_mut()
1602                        .ok_or_else(|| error(r.at, "a debug location before any instruction"))?;
1603                    last.debug_loc = Some(loc);
1604                    last_loc = Some(loc);
1605                    continue;
1606                }
1607                // DEBUG_LOC_AGAIN: the last instruction is where the last located one is
1608                33 => {
1609                    let last = instructions
1610                        .last_mut()
1611                        .ok_or_else(|| error(r.at, "a debug location before any instruction"))?;
1612                    last.debug_loc = last_loc;
1613                    continue;
1614                }
1615                // BINOP: [lhs with its type, rhs, opcode, flags?]
1616                2 => {
1617                    let (lhs, t) = body.value_type(r, &mut i)?;
1618                    let rhs = body.value(r, &mut i)?;
1619                    let o = binary(op(r, i)?, r.at)?;
1620                    flags = r.operands.get(i.saturating_add(1)).copied().unwrap_or(0);
1621                    (Op::Binary { op: o, lhs, rhs }, Some(t))
1622                }
1623                // CAST: [value with its type, target type, opcode]
1624                3 => {
1625                    let (value, _) = body.value_type(r, &mut i)?;
1626                    let to = body.m.ty(op(r, i)?, r.at)?;
1627                    let o = cast(op(r, i.saturating_add(1))?, r.at)?;
1628                    (Op::Cast { op: o, value }, Some(to))
1629                }
1630                // CMP and CMP2: [lhs with its type, rhs, predicate, fast-math flags?]
1631                9 | 28 => {
1632                    let (lhs, t) = body.value_type(r, &mut i)?;
1633                    let rhs = body.value(r, &mut i)?;
1634                    let predicate = op(r, i)?;
1635                    flags = r.operands.get(i.saturating_add(1)).copied().unwrap_or(0);
1636                    // i1, or a vector of i1 for vectors
1637                    let lanes = match body.m.type_at(t, r.at)? {
1638                        Type::Vector(n, _) => Some(*n),
1639                        _ => None,
1640                    };
1641                    let flag = body.m.intern(Type::Integer(1));
1642                    let bool_ty = match lanes {
1643                        Some(n) => body.m.intern(Type::Vector(n, flag)),
1644                        None => flag,
1645                    };
1646                    (Op::Compare { predicate, lhs, rhs }, Some(bool_ty))
1647                }
1648                29 => {
1649                    let (then, t) = body.value_type(r, &mut i)?;
1650                    let otherwise = body.value(r, &mut i)?;
1651                    let condition = body.value(r, &mut i)?;
1652                    (
1653                        Op::Select {
1654                            condition,
1655                            then,
1656                            otherwise,
1657                        },
1658                        Some(t),
1659                    )
1660                }
1661                26 => {
1662                    let (aggregate, mut t) = body.value_type(r, &mut i)?;
1663                    let indices = r.operands.get(i..).unwrap_or_default().to_vec();
1664                    for &k in &indices {
1665                        t = match body.m.type_at(t, r.at)? {
1666                            Type::Struct { elements, .. } => *usize::try_from(k)
1667                                .ok()
1668                                .and_then(|k| elements.get(k))
1669                                .ok_or_else(|| error(r.at, "extractvalue index"))?,
1670                            Type::Array(n, e) if k < *n => *e,
1671                            _ => return Err(error(r.at, "extractvalue index")),
1672                        };
1673                    }
1674                    (Op::ExtractValue { aggregate, indices }, Some(t))
1675                }
1676                6 => {
1677                    let (vector, t) = body.value_type(r, &mut i)?;
1678                    let (index, _) = body.value_type(r, &mut i)?;
1679                    let Type::Vector(_, element) = *body.m.type_at(t, r.at)? else {
1680                        return Err(error(r.at, "extractelement of something that is not a vector"));
1681                    };
1682                    (Op::ExtractElement { vector, index }, Some(element))
1683                }
1684                7 => {
1685                    let (vector, t) = body.value_type(r, &mut i)?;
1686                    let value = body.value(r, &mut i)?;
1687                    let (index, _) = body.value_type(r, &mut i)?;
1688                    (Op::InsertElement { vector, value, index }, Some(t))
1689                }
1690                8 => {
1691                    let (first, t) = body.value_type(r, &mut i)?;
1692                    let second = body.value(r, &mut i)?;
1693                    let (mask, mask_ty) = body.value_type(r, &mut i)?;
1694                    let (Type::Vector(_, element), Type::Vector(lanes, _)) = (
1695                        body.m.type_at(t, r.at)?.clone(),
1696                        body.m.type_at(mask_ty, r.at)?.clone(),
1697                    ) else {
1698                        return Err(error(r.at, "shufflevector of something that is not a vector"));
1699                    };
1700                    let result = body
1701                        .m
1702                        .types
1703                        .iter()
1704                        .position(|x| *x == Type::Vector(lanes, element))
1705                        .ok_or_else(|| error(r.at, "no type for the shuffled vector"))?;
1706                    (Op::ShuffleVector { first, second, mask }, Some(result))
1707                }
1708                27 => {
1709                    let (aggregate, t) = body.value_type(r, &mut i)?;
1710                    let value = body.value(r, &mut i)?;
1711                    let indices = r.operands.get(i..).unwrap_or_default().to_vec();
1712                    (
1713                        Op::InsertValue {
1714                            aggregate,
1715                            value,
1716                            indices,
1717                        },
1718                        Some(t),
1719                    )
1720                }
1721                // CALL: [attribute list + 1 or 0, calling convention and flags, function type if explicit, callee with
1722                // its type, arguments]
1723                34 => {
1724                    let attributes = usize::try_from(op(r, 0)?)
1725                        .map_err(|_| error(r.at, "call attribute list"))?
1726                        .checked_sub(1);
1727                    if attributes.is_some_and(|a| a >= body.m.attribute_lists.len()) {
1728                        return Err(error(r.at, "a call names an attribute list the module lacks"));
1729                    }
1730                    i = 1;
1731                    let cc = op(r, i)?;
1732                    i = i.saturating_add(1);
1733                    // bit 0 tail, bit 14 musttail, bit 15 an explicit function type, the convention from bit 1
1734                    let tail = if cc & (1 << 14) != 0 {
1735                        TailCall::MustTail
1736                    } else if cc & 1 != 0 {
1737                        TailCall::Tail
1738                    } else {
1739                        TailCall::None
1740                    };
1741                    let calling_conv = (cc >> 1) & 0x1FFF;
1742                    let explicit = if cc & (1 << 15) != 0 {
1743                        let t = body.m.ty(op(r, i)?, r.at)?;
1744                        i = i.saturating_add(1);
1745                        Some(t)
1746                    } else {
1747                        None
1748                    };
1749                    let (function, callee_ty) = body.value_type(r, &mut i)?;
1750                    let fty = match (explicit, body.m.type_at(callee_ty, r.at)?) {
1751                        (Some(t), _) => t,
1752                        (None, Type::Pointer(t, _)) => *t,
1753                        _ => return Err(error(r.at, "callee is not a function pointer")),
1754                    };
1755                    let (ret, params, vararg) = match body.m.type_at(fty, r.at)? {
1756                        Type::Function { ret, params, vararg } => (*ret, params.clone(), *vararg),
1757                        _ => return Err(error(r.at, "call through a non-function type")),
1758                    };
1759                    if vararg {
1760                        return Err(error(r.at, "vararg call"));
1761                    }
1762                    let mut args = Vec::with_capacity(params.len());
1763                    for (n, p) in params.iter().enumerate() {
1764                        // a fixed parameter carries no type, even for a value defined later in the layout
1765                        let a = body.value(r, &mut i)?;
1766                        // a `metadata` parameter's operand is a metadata id, relative as a value's is; the argument is
1767                        // given its value once the body is read
1768                        if *body.m.type_at(*p, r.at)? == Type::Metadata {
1769                            metadata_args.push((instructions.len(), n, a));
1770                            args.push(usize::MAX);
1771                            continue;
1772                        }
1773                        if a < body.next() && body.m.value_types.get(a) != Some(p) {
1774                            return Err(error(r.at, "call argument type"));
1775                        }
1776                        args.push(a);
1777                    }
1778                    if i != r.operands.len() {
1779                        return Err(error(r.at, "call operands left over"));
1780                    }
1781                    (
1782                        Op::Call {
1783                            function,
1784                            args,
1785                            attributes,
1786                            calling_conv,
1787                            tail,
1788                        },
1789                        Some(ret),
1790                    )
1791                }
1792                16 => {
1793                    let t = body.m.ty(op(r, 0)?, r.at)?;
1794                    let pairs = r.operands.get(1..).unwrap_or_default();
1795                    if pairs.is_empty() || pairs.len() % 2 != 0 {
1796                        return Err(error(r.at, "phi operands"));
1797                    }
1798                    let next = i64::try_from(body.next()).map_err(|_| error(r.at, "too many values"))?;
1799                    let mut incoming = Vec::with_capacity(pairs.len() / 2);
1800                    for pair in pairs.as_chunks::<2>().0 {
1801                        // Signed and relative to the phi itself; it may name a value defined later.
1802                        let id = next
1803                            .checked_sub(signed_vbr(pair[0]))
1804                            .and_then(|v| usize::try_from(v).ok())
1805                            .ok_or_else(|| error(r.at, "phi value"))?;
1806                        let block = usize::try_from(pair[1])
1807                            .ok()
1808                            .filter(|&b| b < body.blocks)
1809                            .ok_or_else(|| error(r.at, "phi block"))?;
1810                        incoming.push((id, block));
1811                    }
1812                    (Op::Phi { incoming }, Some(t))
1813                }
1814                10 => {
1815                    if r.operands.is_empty() {
1816                        (Op::Return(None), None)
1817                    } else {
1818                        (Op::Return(Some(body.value(r, &mut i)?)), None)
1819                    }
1820                }
1821                11 => {
1822                    let target = |v: u64| -> Result<usize> {
1823                        usize::try_from(v)
1824                            .ok()
1825                            .filter(|&b| b < body.blocks)
1826                            .ok_or_else(|| error(r.at, "branch target"))
1827                    };
1828                    if r.operands.len() == 1 {
1829                        (
1830                            Op::Branch {
1831                                target: target(op(r, 0)?)?,
1832                            },
1833                            None,
1834                        )
1835                    } else {
1836                        let then = target(op(r, 0)?)?;
1837                        let otherwise = target(op(r, 1)?)?;
1838                        i = 2;
1839                        let condition = body.value(r, &mut i)?;
1840                        (
1841                            Op::CondBranch {
1842                                condition,
1843                                then,
1844                                otherwise,
1845                            },
1846                            None,
1847                        )
1848                    }
1849                }
1850                12 => {
1851                    // [type, value, default block, (case constant, block)*]; case constants are absolute ids
1852                    let block = |v: u64| -> Result<usize> {
1853                        usize::try_from(v)
1854                            .ok()
1855                            .filter(|&b| b < body.blocks)
1856                            .ok_or_else(|| error(r.at, "switch target"))
1857                    };
1858                    if op(r, 0)? >> 16 == 0x4B5 {
1859                        return Err(error(r.at, "switch with case ranges is not supported"));
1860                    }
1861                    i = 1;
1862                    let value = body.value(r, &mut i)?;
1863                    let default = block(op(r, i)?)?;
1864                    let pairs = r.operands.get(i.saturating_add(1)..).unwrap_or_default();
1865                    if pairs.len() % 2 != 0 {
1866                        return Err(error(r.at, "switch cases"));
1867                    }
1868                    let cases = pairs
1869                        .as_chunks::<2>()
1870                        .0
1871                        .iter()
1872                        .map(|p| {
1873                            Ok((
1874                                usize::try_from(p[0]).map_err(|_| error(r.at, "case value"))?,
1875                                block(p[1])?,
1876                            ))
1877                        })
1878                        .collect::<Result<Vec<_>>>()?;
1879                    (
1880                        Op::Switch {
1881                            value,
1882                            default,
1883                            cases,
1884                        },
1885                        None,
1886                    )
1887                }
1888                15 => (Op::Unreachable, None),
1889                // ALLOCA: [type, size type, size (an absolute id), alignment with flags: bit 5 inalloca, bit 6 the
1890                // type is the allocated one rather than a pointer to it]
1891                19 => {
1892                    let stated = body.m.ty(op(r, 0)?, r.at)?;
1893                    let packed = op(r, 3)?;
1894                    let ty = if packed & (1 << 6) != 0 {
1895                        stated
1896                    } else {
1897                        match body.m.type_at(stated, r.at)? {
1898                            Type::Pointer(t, _) => *t,
1899                            _ => {
1900                                return Err(error(
1901                                    r.at,
1902                                    "an alloca of the old form whose type is not a pointer",
1903                                ));
1904                            }
1905                        }
1906                    };
1907                    let size = usize::try_from(op(r, 2)?).map_err(|_| error(r.at, "alloca size"))?;
1908                    (
1909                        Op::Alloca {
1910                            ty,
1911                            size,
1912                            align: alignment(packed & !((1 << 5) | (1 << 6)), r.at)?,
1913                            inalloca: packed & (1 << 5) != 0,
1914                        },
1915                        Some(body.pointer_to(ty, 0)),
1916                    )
1917                }
1918                // LOAD: [pointer with its type, loaded type if explicit, alignment, volatile], and LOADATOMIC with the
1919                // ordering and scope after them
1920                20 | 41 => {
1921                    let (pointer, pt) = body.value_type(r, &mut i)?;
1922                    let tail = if r.code == 20 { 2 } else { 4 };
1923                    let ty = if r.operands.len() == i.saturating_add(tail).saturating_add(1) {
1924                        let t = body.m.ty(op(r, i)?, r.at)?;
1925                        i = i.saturating_add(1);
1926                        t
1927                    } else {
1928                        match body.m.type_at(pt, r.at)? {
1929                            Type::Pointer(t, _) => *t,
1930                            _ => return Err(error(r.at, "a load from a value that is not a pointer")),
1931                        }
1932                    };
1933                    if r.operands.len() != i.saturating_add(tail) {
1934                        return Err(error(r.at, "load operands"));
1935                    }
1936                    let atomic = if r.code == 41 {
1937                        Some(atomic(
1938                            op(r, i.saturating_add(2))?,
1939                            op(r, i.saturating_add(3))?,
1940                            r.at,
1941                        )?)
1942                    } else {
1943                        None
1944                    };
1945                    (
1946                        Op::Load {
1947                            pointer,
1948                            align: alignment(op(r, i)?, r.at)?,
1949                            volatile: op(r, i.saturating_add(1))? != 0,
1950                            atomic,
1951                        },
1952                        Some(ty),
1953                    )
1954                }
1955                // STORE: [pointer with its type, value with its type, alignment, volatile], STOREATOMIC with the
1956                // ordering and scope after them; the old forms (24, 42) give the value without a type
1957                24 | 42 | 44 | 45 => {
1958                    let (pointer, _) = body.value_type(r, &mut i)?;
1959                    let value = if matches!(r.code, 44 | 45) {
1960                        body.value_type(r, &mut i)?.0
1961                    } else {
1962                        body.value(r, &mut i)?
1963                    };
1964                    let tail = if matches!(r.code, 24 | 44) { 2 } else { 4 };
1965                    if r.operands.len() != i.saturating_add(tail) {
1966                        return Err(error(r.at, "store operands"));
1967                    }
1968                    let atomic = if matches!(r.code, 42 | 45) {
1969                        Some(atomic(
1970                            op(r, i.saturating_add(2))?,
1971                            op(r, i.saturating_add(3))?,
1972                            r.at,
1973                        )?)
1974                    } else {
1975                        None
1976                    };
1977                    (
1978                        Op::Store {
1979                            pointer,
1980                            value,
1981                            align: alignment(op(r, i)?, r.at)?,
1982                            volatile: op(r, i.saturating_add(1))? != 0,
1983                            atomic,
1984                        },
1985                        None,
1986                    )
1987                }
1988                // ATOMICRMW: [pointer with its type, value, operation, volatile, ordering, scope]
1989                38 => {
1990                    let (pointer, pt) = body.value_type(r, &mut i)?;
1991                    let value = body.value(r, &mut i)?;
1992                    let ty = match body.m.type_at(pt, r.at)? {
1993                        Type::Pointer(t, _) => *t,
1994                        _ => return Err(error(r.at, "an atomicrmw on a value that is not a pointer")),
1995                    };
1996                    (
1997                        Op::AtomicRmw {
1998                            pointer,
1999                            value,
2000                            op: op(r, i)?,
2001                            volatile: op(r, i.saturating_add(1))? != 0,
2002                            atomic: atomic(op(r, i.saturating_add(2))?, op(r, i.saturating_add(3))?, r.at)?,
2003                        },
2004                        Some(ty),
2005                    )
2006                }
2007                // CMPXCHG: [pointer with its type, compare with its type, new value, volatile, success ordering, scope,
2008                // failure ordering, weak]; the result is a structure of the value and a flag
2009                46 => {
2010                    let (pointer, _) = body.value_type(r, &mut i)?;
2011                    let (compare, ty) = body.value_type(r, &mut i)?;
2012                    let value = body.value(r, &mut i)?;
2013                    if r.operands.len() != i.saturating_add(5) {
2014                        return Err(error(
2015                            r.at,
2016                            "cmpxchg without its failure ordering and weak flag (an old form)",
2017                        ));
2018                    }
2019                    let success = atomic(op(r, i.saturating_add(1))?, op(r, i.saturating_add(2))?, r.at)?;
2020                    let failure = ordering(op(r, i.saturating_add(3))?, r.at)?;
2021                    let flag = body.m.intern(Type::Integer(1));
2022                    let pair = Type::Struct {
2023                        name: None,
2024                        elements: vec![ty, flag],
2025                        packed: false,
2026                        literal: true,
2027                    };
2028                    let result = body.m.intern(pair);
2029                    (
2030                        Op::CmpXchg {
2031                            pointer,
2032                            compare,
2033                            value,
2034                            volatile: op(r, i)? != 0,
2035                            weak: op(r, i.saturating_add(4))? != 0,
2036                            success,
2037                            failure,
2038                        },
2039                        Some(result),
2040                    )
2041                }
2042                // FENCE: [ordering, scope]
2043                36 => (Op::Fence(atomic(op(r, 0)?, op(r, 1)?, r.at)?), None),
2044                43 => {
2045                    // [inbounds, source element type, then each operand with its type when a forward reference]
2046                    i = 2;
2047                    let inbounds = op(r, 0)? != 0;
2048                    let source = body.m.ty(op(r, 1)?, r.at)?;
2049                    let (base, base_ty) = body.value_type(r, &mut i)?;
2050                    // the result points into the base's address space
2051                    let space = match body.m.type_at(base_ty, r.at)? {
2052                        Type::Pointer(_, space) => *space,
2053                        _ => return Err(error(r.at, "getelementptr of a value that is not a pointer")),
2054                    };
2055                    let mut indices = Vec::new();
2056                    while i < r.operands.len() {
2057                        indices.push(body.value_type(r, &mut i)?.0);
2058                    }
2059                    // the result points at what the indices reach: the first steps over the pointer, the rest into
2060                    // arrays, vectors and structures
2061                    let mut t = source;
2062                    for &index in indices.iter().skip(1) {
2063                        t = match body.m.type_at(t, r.at)?.clone() {
2064                            Type::Array(_, e) | Type::Vector(_, e) => e,
2065                            Type::Struct { elements, .. } => {
2066                                let k = match body.constant_index(index) {
2067                                    Some(k) => k,
2068                                    None => {
2069                                        return Err(error(r.at, "a structure index that is not constant"));
2070                                    }
2071                                };
2072                                *elements
2073                                    .get(k)
2074                                    .ok_or_else(|| error(r.at, "getelementptr structure index"))?
2075                            }
2076                            _ => return Err(error(r.at, "getelementptr into a scalar")),
2077                        };
2078                    }
2079                    (
2080                        Op::Gep {
2081                            base,
2082                            indices,
2083                            source,
2084                            inbounds,
2085                        },
2086                        Some(body.pointer_to(t, space)),
2087                    )
2088                }
2089                other => {
2090                    return Err(error(
2091                        r.at,
2092                        format!("instruction {} (record {other}) is not supported", refused(other)),
2093                    ));
2094                }
2095            };
2096            let result = match ty {
2097                Some(t) => body.result(t, r.at)?,
2098                None => None,
2099            };
2100            let terminator = matches!(
2101                op,
2102                Op::Return(_)
2103                    | Op::Branch { .. }
2104                    | Op::CondBranch { .. }
2105                    | Op::Switch { .. }
2106                    | Op::Unreachable
2107            );
2108            instructions.push(Instruction {
2109                op,
2110                result,
2111                block: body.block,
2112                at: r.at,
2113                flags,
2114                precise: false,
2115                attachments: Vec::new(),
2116                debug_loc: None,
2117            });
2118            if terminator {
2119                body.block = body.block.saturating_add(1);
2120            }
2121        }
2122        if body.block != body.blocks {
2123            return Err(error(block.at, "basic blocks without terminators"));
2124        }
2125        let end = body.next();
2126        let blocks = body.blocks;
2127        // each metadata a call passes is a value of the body, after its others, once per metadata id
2128        let metadata_type = self.intern(Type::Metadata);
2129        let first_metadata = self.metadata.len();
2130        let mut metadata_values: Vec<(MetadataId, ValueId)> = Vec::new();
2131        for (inst, arg, md) in metadata_args {
2132            let at = instructions.get(inst).map_or(block.at, |i| i.at);
2133            if md >= first_metadata.saturating_add(local_metadata.len()) {
2134                return Err(error(
2135                    at,
2136                    format!("a call passes metadata {md}, which the module lacks"),
2137                ));
2138            }
2139            let value = match metadata_values.iter().find(|(m, _)| *m == md) {
2140                Some((_, v)) => *v,
2141                None => {
2142                    let v = self.push(Value::Metadata(md), metadata_type, at)?;
2143                    metadata_values.push((md, v));
2144                    v
2145                }
2146            };
2147            if let Some(Op::Call { args, .. }) = instructions.get_mut(inst).map(|i| &mut i.op)
2148                && let Some(a) = args.get_mut(arg)
2149            {
2150                *a = value;
2151            }
2152        }
2153        let metadata_value = |v: ValueId| metadata_values.iter().any(|(_, m)| *m == v);
2154        // everything an instruction names is something the function has: a value (an earlier one, or a later one a phi
2155        // or a loop reads), a basic block, and a callee taking the arguments it is given
2156        for inst in &instructions {
2157            if inst.block >= blocks {
2158                return Err(error(inst.at, "an instruction after the last terminator"));
2159            }
2160            if let Some(v) = inst
2161                .op
2162                .operands()
2163                .into_iter()
2164                .find(|v| *v >= end && !metadata_value(*v))
2165            {
2166                return Err(error(inst.at, format!("value {v} of {end} values")));
2167            }
2168            if let Some(b) = inst.op.blocks().into_iter().find(|b| *b >= blocks) {
2169                return Err(error(inst.at, format!("basic block {b} of {blocks}")));
2170            }
2171            if let Op::Call { function, args, .. } = &inst.op {
2172                if *function >= end {
2173                    return Err(error(inst.at, format!("callee {function} of {end} values")));
2174                }
2175                if let Some(Value::Function { ty, .. }) = self.values.get(*function)
2176                    && let Some(Type::Function {
2177                        vararg: false,
2178                        params,
2179                        ..
2180                    }) = self.types.get(*ty)
2181                    && params.len() != args.len()
2182                {
2183                    return Err(error(
2184                        inst.at,
2185                        format!(
2186                            "a call of {} arguments to a function of {} parameters",
2187                            args.len(),
2188                            params.len()
2189                        ),
2190                    ));
2191                }
2192            }
2193        }
2194        let locals = self.values.split_off(base);
2195        let local_types = self.value_types.split_off(base);
2196        Ok(Function {
2197            value,
2198            blocks,
2199            instructions,
2200            first: base,
2201            locals,
2202            local_types,
2203            attachments: function_attachments,
2204            metadata: local_metadata,
2205            first_metadata,
2206            names,
2207            block_names,
2208            block_use_orders,
2209        })
2210    }
2211
2212    /// Read a module from the bitcode's top-level blocks.
2213    pub fn read(top: &[Block]) -> Result<Self> {
2214        let module = match top {
2215            [m] if m.id == MODULE => m,
2216            _ => return Err(error(0, "bitcode is not one module block")),
2217        };
2218        let mut m = Module {
2219            at: module.at,
2220            ..Module::default()
2221        };
2222        let mut bodies: Vec<ValueId> = Vec::new();
2223        let mut version = None;
2224        let (mut sections, mut gcs) = (Vec::new(), Vec::new());
2225        for e in &module.elements {
2226            match e {
2227                crate::bitstream::Element::Record(r) => match r.code {
2228                    1 => version = Some(op(r, 0)?),
2229                    2 => m.triple = Some(utf8(text(&r.operands, r.at)?, r.at)?),
2230                    3 => m.datalayout = Some(utf8(text(&r.operands, r.at)?, r.at)?),
2231                    4 => m.asm = Some(utf8(text(&r.operands, r.at)?, r.at)?),
2232                    5 => sections.push(utf8(text(&r.operands, r.at)?, r.at)?),
2233                    11 => gcs.push(utf8(text(&r.operands, r.at)?, r.at)?),
2234                    6 | 13 | 16 => {} // deplib, the symbol table's offset, source file
2235                    7 => {
2236                        // GLOBALVAR: [type, flags (bit 0 constant, bit 1 explicit type, from bit 2 the address space),
2237                        // initial value + 1 or 0, linkage, alignment, section, visibility, thread local, unnamed_addr,
2238                        // externally initialized, DLL storage, comdat]
2239                        let t = m.ty(op(r, 0)?, r.at)?;
2240                        let flags = op(r, 1)?;
2241                        let (ty, value_ty, address_space) = if flags & 2 != 0 {
2242                            let space =
2243                                u32::try_from(flags >> 2).map_err(|_| error(r.at, "address space"))?;
2244                            (m.intern(Type::Pointer(t, space)), t, space)
2245                        } else {
2246                            match m.type_at(t, r.at)? {
2247                                Type::Pointer(inner, space) => (t, *inner, *space),
2248                                _ => return Err(error(r.at, "a global whose type is not a pointer")),
2249                            }
2250                        };
2251                        let init = match op(r, 2)? {
2252                            0 => None,
2253                            n => Some(
2254                                usize::try_from(n.saturating_sub(1))
2255                                    .map_err(|_| error(r.at, "initial value id"))?,
2256                            ),
2257                        };
2258                        let properties = global_properties(r, 3, 4, 5, 6, 8, 10, 11, &sections)?;
2259                        m.push(
2260                            Value::Global {
2261                                ty,
2262                                value_ty,
2263                                init,
2264                                constant: flags & 1 != 0,
2265                                address_space,
2266                                properties,
2267                                thread_local: u8::try_from(r.operands.get(7).copied().unwrap_or(0))
2268                                    .ok()
2269                                    .filter(|&t| t <= 4)
2270                                    .ok_or_else(|| error(r.at, "thread-local model"))?,
2271                                externally_initialized: r.operands.get(9).is_some_and(|&v| v != 0),
2272                            },
2273                            ty,
2274                            r.at,
2275                        )?;
2276                    }
2277                    8 => {
2278                        // FUNCTION: [function type, calling convention, declaration, linkage, attribute list + 1 or 0,
2279                        // alignment, section, visibility, gc, unnamed_addr, prologue, DLL storage, comdat, prefix,
2280                        // personality]
2281                        let t = m.ty(op(r, 0)?, r.at)?;
2282                        let pointer = m.intern(Type::Pointer(t, 0));
2283                        let declaration = op(r, 2)? != 0;
2284                        // the attribute list is named by its 1-based index (0 for none)
2285                        let attributes = r
2286                            .operands
2287                            .get(4)
2288                            .and_then(|&n| usize::try_from(n).ok())
2289                            .and_then(|n| n.checked_sub(1));
2290                        for (field, what) in [
2291                            (10, "prologue data"),
2292                            (13, "prefix data"),
2293                            (14, "a personality function"),
2294                        ] {
2295                            if r.operands.get(field).is_some_and(|&v| v != 0) {
2296                                return Err(error(r.at, format!("a function with {what} is not supported")));
2297                            }
2298                        }
2299                        let gc = match r.operands.get(8).copied().unwrap_or(0) {
2300                            0 => None,
2301                            n => Some(
2302                                usize::try_from(n.saturating_sub(1))
2303                                    .ok()
2304                                    .and_then(|n| gcs.get(n))
2305                                    .cloned()
2306                                    .ok_or_else(|| {
2307                                        error(r.at, "a function names a garbage collector the module lacks")
2308                                    })?,
2309                            ),
2310                        };
2311                        let v = m.push(
2312                            Value::Function {
2313                                ty: t,
2314                                declaration,
2315                                attributes,
2316                                properties: global_properties(r, 3, 5, 6, 7, 9, 11, 12, &sections)?,
2317                                calling_conv: op(r, 1)?,
2318                                gc,
2319                            },
2320                            pointer,
2321                            r.at,
2322                        )?;
2323                        if !declaration {
2324                            bodies.push(v);
2325                        }
2326                    }
2327                    other => return Err(error(r.at, format!("module record {other}"))),
2328                },
2329                crate::bitstream::Element::Block(b) => match b.id {
2330                    BLOCKINFO | USELIST => {}
2331                    PARAMATTR_GROUP => m.read_attribute_groups(b)?,
2332                    PARAMATTR => m.read_attribute_lists(b),
2333                    TYPES => m.read_types(b)?,
2334                    CONSTANTS => m.read_constants(b)?,
2335                    METADATA => m.read_metadata(b)?,
2336                    VALUE_SYMTAB => {
2337                        let (values, blocks) = read_symbols(b)?;
2338                        if let Some((_, name)) = blocks.first() {
2339                            return Err(error(
2340                                b.at,
2341                                format!("a basic block name ({name}) in the module's symbol table"),
2342                            ));
2343                        }
2344                        m.names.extend(values);
2345                    }
2346                    FUNCTION => {
2347                        if version != Some(1) {
2348                            return Err(error(b.at, "only relative value ids (module version 1)"));
2349                        }
2350                        // Bodies are stored in the order of their definitions (a hull program has two).
2351                        if bodies.is_empty() {
2352                            return Err(error(b.at, "function body without a definition"));
2353                        }
2354                        let value = bodies.remove(0);
2355                        // A body's values are its own; the next body numbers from the module's values again.
2356                        let f = m.read_function(b, value)?;
2357                        m.functions.push(f);
2358                    }
2359                    other => return Err(error(b.at, format!("module block {other}"))),
2360                },
2361            }
2362        }
2363        if !bodies.is_empty() {
2364            return Err(error(module.at, "a defined function has no body"));
2365        }
2366        Ok(m)
2367    }
2368}