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. The blocks of a function body that say nothing a reader of the program's behaviour needs (its metadata and its
4//! use-list order) are the only things skipped. The metadata attached to an instruction or a function is kept as the
5//! pairs the file stores ([`Instruction::attachments`], [`Function::attachments`], with the kind names in
6//! [`Module::kinds`]), `dx.precise` also as [`Instruction::precise`]; the attribute groups and lists are kept as stored
7//! ([`Module::attribute_groups`], [`Module::attribute_lists`]) and each function value names its list.
8use crate::bitstream::{Block, Record};
9use crate::{Result, error};
10
11const MODULE: u64 = 8;
12const PARAMATTR: u64 = 9;
13const PARAMATTR_GROUP: u64 = 10;
14const CONSTANTS: u64 = 11;
15const FUNCTION: u64 = 12;
16const VALUE_SYMTAB: u64 = 14;
17const METADATA: u64 = 15;
18const METADATA_ATTACHMENT: u64 = 16;
19const TYPES: u64 = 17;
20const USELIST: u64 = 18;
21const BLOCKINFO: u64 = 0;
22
23/// Values a module may hold (globals, constants and function-body values together).
24const MAX_VALUES: usize = 1 << 22;
25const MAX_TYPES: usize = 1 << 16;
26
27/// An index into [`Module::types`].
28pub type TypeId = usize;
29/// An index into the values: the module's [`Module::values`], then a function body's own [`Function::locals`].
30pub type ValueId = usize;
31/// An index into [`Module::metadata`].
32pub type MetadataId = usize;
33
34/// A type of the module's type table.
35#[derive(Clone, Debug, PartialEq, Eq)]
36pub enum Type {
37    /// `void`.
38    Void,
39    /// `label`, the type of a basic block.
40    Label,
41    /// `metadata`.
42    Metadata,
43    /// `half`.
44    Half,
45    /// `float`.
46    Float,
47    /// `double`.
48    Double,
49    /// An integer of this many bits (1 to 64).
50    Integer(u32),
51    /// A pointer to the type, in this LLVM address space (the `TYPE_CODE_POINTER` record's second operand). Pointers to
52    /// one type in two spaces are two types.
53    Pointer(TypeId, u32),
54    /// An array of this many elements of the type.
55    Array(u64, TypeId),
56    /// A vector of this many lanes of the type.
57    Vector(u64, TypeId),
58    /// A structure.
59    Struct {
60        /// Its name, where it has one.
61        name: Option<String>,
62        /// The types of its fields, in order.
63        elements: Vec<TypeId>,
64    },
65    /// A named structure without a body.
66    Opaque(Option<String>),
67    /// A function type.
68    Function {
69        /// Whether it takes a variable argument list.
70        vararg: bool,
71        /// The return type.
72        ret: TypeId,
73        /// The parameter types.
74        params: Vec<TypeId>,
75    },
76}
77
78/// A module-level constant.
79#[derive(Clone, Debug, PartialEq)]
80pub enum Constant {
81    /// The null value of the constant's type (zero).
82    Null,
83    /// An undefined value.
84    Undef,
85    /// An integer's bits, sign-extended from its width.
86    Integer(i64),
87    /// A float's bits (half, float or double by its type).
88    Float(u64),
89    /// An array, structure or vector of other constants (value ids).
90    Aggregate(Vec<ValueId>),
91    /// A constant array or vector of numbers, as stored (the bits of each element).
92    Data(Vec<u64>),
93    /// A string constant, as stored.
94    String(Vec<u8>),
95    /// A constant `getelementptr`: the base (a global) and its indices (module constants).
96    Gep {
97        /// The base global.
98        base: ValueId,
99        /// The index constants.
100        indices: Vec<ValueId>,
101    },
102    /// A constant cast of a module value (to the type of the constant).
103    Cast {
104        /// The cast.
105        op: CastOp,
106        /// The value cast.
107        value: ValueId,
108    },
109    /// A constant binary operation on module values.
110    Binary {
111        /// The operation.
112        op: BinaryOp,
113        /// The left operand.
114        lhs: ValueId,
115        /// The right operand.
116        rhs: ValueId,
117    },
118}
119
120/// A value the module numbers.
121#[derive(Clone, Debug, PartialEq)]
122pub enum Value {
123    /// A function, defined or declared.
124    Function {
125        /// Its function type.
126        ty: TypeId,
127        /// Whether it is only declared (it has no body).
128        declaration: bool,
129        /// The attribute list it names (an index into [`Module::attribute_lists`]), where it names one.
130        attributes: Option<usize>,
131    },
132    /// A global variable.
133    Global {
134        /// The global's type: a pointer to `value_ty`.
135        ty: TypeId,
136        /// The type of the value it holds.
137        value_ty: TypeId,
138        /// Its initial value (a module constant), if it has one.
139        init: Option<ValueId>,
140        /// Whether it is a constant (read only).
141        constant: bool,
142        /// LLVM's address space: 0 the default, 3 group shared. No other space occurs in the programs of the games read.
143        address_space: u32,
144    },
145    /// A constant.
146    Constant(Constant),
147    /// A function argument or an instruction's result.
148    Local,
149}
150
151/// A metadata record.
152#[derive(Clone, Debug, PartialEq)]
153pub enum Metadata {
154    /// A metadata string, as stored (not checked to be UTF-8 here).
155    String(Vec<u8>),
156    /// A value as metadata.
157    Value {
158        /// The value's type.
159        ty: TypeId,
160        /// The value.
161        value: ValueId,
162    },
163    /// Operands; `None` is a null operand.
164    Node(Vec<Option<MetadataId>>),
165}
166
167/// A binary operator code (LLVM's `BinaryOpcodes`).
168#[derive(Clone, Copy, Debug, PartialEq, Eq)]
169pub enum BinaryOp {
170    /// Addition.
171    Add,
172    /// Subtraction.
173    Sub,
174    /// Multiplication.
175    Mul,
176    /// Unsigned division.
177    UDiv,
178    /// Signed division.
179    SDiv,
180    /// Unsigned remainder.
181    URem,
182    /// Signed remainder.
183    SRem,
184    /// Shift left.
185    Shl,
186    /// Logical shift right.
187    LShr,
188    /// Arithmetic shift right.
189    AShr,
190    /// Bitwise and.
191    And,
192    /// Bitwise or.
193    Or,
194    /// Bitwise exclusive or.
195    Xor,
196}
197/// A cast opcode (LLVM's `CastOpcodes`).
198#[derive(Clone, Copy, Debug, PartialEq, Eq)]
199pub enum CastOp {
200    /// Truncate an integer.
201    Trunc,
202    /// Zero-extend an integer.
203    ZExt,
204    /// Sign-extend an integer.
205    SExt,
206    /// Float to unsigned integer.
207    FpToUi,
208    /// Float to signed integer.
209    FpToSi,
210    /// Unsigned integer to float.
211    UiToFp,
212    /// Signed integer to float.
213    SiToFp,
214    /// Truncate a float.
215    FpTrunc,
216    /// Extend a float.
217    FpExt,
218    /// Pointer to integer.
219    PtrToInt,
220    /// Integer to pointer.
221    IntToPtr,
222    /// Reinterpret the bits as another type.
223    BitCast,
224}
225
226/// An instruction, with the value ids (absolute) and block numbers it names.
227#[derive(Clone, Debug, PartialEq)]
228pub enum Op {
229    /// Integer opcodes apply to integers; for floating types Add, Sub, Mul, (S)Div, (S)Rem are the float forms.
230    Binary {
231        /// The operation.
232        op: BinaryOp,
233        /// The left operand.
234        lhs: ValueId,
235        /// The right operand.
236        rhs: ValueId,
237    },
238    /// A conversion.
239    Cast {
240        /// The conversion.
241        op: CastOp,
242        /// The value converted; the instruction's result type is the target.
243        value: ValueId,
244    },
245    /// A comparison by its LLVM predicate (0..15 float, 32..41 integer).
246    Compare {
247        /// The predicate.
248        predicate: u64,
249        /// The left operand.
250        lhs: ValueId,
251        /// The right operand.
252        rhs: ValueId,
253    },
254    /// `select`: one of two values by a condition.
255    Select {
256        /// The condition (an `i1`).
257        condition: ValueId,
258        /// The value when the condition is true.
259        then: ValueId,
260        /// The value when it is false.
261        otherwise: ValueId,
262    },
263    /// A field or element of an aggregate.
264    ExtractValue {
265        /// The aggregate.
266        aggregate: ValueId,
267        /// The indices into it, outermost first.
268        indices: Vec<u64>,
269    },
270    /// An aggregate with one field or element replaced.
271    InsertValue {
272        /// The aggregate.
273        aggregate: ValueId,
274        /// The new field or element.
275        value: ValueId,
276        /// The indices of the replaced one, outermost first.
277        indices: Vec<u64>,
278    },
279    /// One lane of a vector.
280    ExtractElement {
281        /// The vector.
282        vector: ValueId,
283        /// The lane number.
284        index: ValueId,
285    },
286    /// A vector with one lane replaced.
287    InsertElement {
288        /// The vector.
289        vector: ValueId,
290        /// The new lane.
291        value: ValueId,
292        /// The lane number.
293        index: ValueId,
294    },
295    /// The lanes of two vectors the mask (a constant vector of lane numbers) picks.
296    ShuffleVector {
297        /// The first vector.
298        first: ValueId,
299        /// The second vector.
300        second: ValueId,
301        /// The constant vector of lane numbers.
302        mask: ValueId,
303    },
304    /// A call.
305    Call {
306        /// The callee.
307        function: ValueId,
308        /// The arguments, one per parameter.
309        args: Vec<ValueId>,
310    },
311    /// The value from the predecessor block control came from: (value, block) pairs.
312    Phi {
313        /// The (value, predecessor block) pairs.
314        incoming: Vec<(ValueId, usize)>,
315    },
316    /// `ret`, with the value returned where there is one.
317    Return(Option<ValueId>),
318    /// An unconditional branch.
319    Branch {
320        /// The block branched to.
321        target: usize,
322    },
323    /// A conditional branch.
324    CondBranch {
325        /// The condition (an `i1`).
326        condition: ValueId,
327        /// The block when it is true.
328        then: usize,
329        /// The block when it is false.
330        otherwise: usize,
331    },
332    /// A multi-way branch: the value, the default block and the (case constant, block) pairs.
333    Switch {
334        /// The value switched on.
335        value: ValueId,
336        /// The block when no case matches.
337        default: usize,
338        /// The (case constant, block) pairs.
339        cases: Vec<(ValueId, usize)>,
340    },
341    /// `unreachable`.
342    Unreachable,
343    /// A local variable of this type (the result is a pointer to it).
344    Alloca {
345        /// The type of the variable.
346        ty: TypeId,
347    },
348    /// A load.
349    Load {
350        /// The pointer loaded from; the result type is the loaded type.
351        pointer: ValueId,
352    },
353    /// A store.
354    Store {
355        /// The pointer stored to.
356        pointer: ValueId,
357        /// The value stored.
358        value: ValueId,
359    },
360    /// `getelementptr`: the base pointer and its indices (the first steps over the pointer itself).
361    Gep {
362        /// The base pointer.
363        base: ValueId,
364        /// The indices.
365        indices: Vec<ValueId>,
366    },
367    /// `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,
368    /// 10 umin); the result is the value the pointer held.
369    AtomicRmw {
370        /// The pointer.
371        pointer: ValueId,
372        /// The value operated with.
373        value: ValueId,
374        /// The operation code.
375        op: u64,
376    },
377    /// `cmpxchg`: the result is the pair (the value the pointer held, whether it was swapped).
378    CmpXchg {
379        /// The pointer.
380        pointer: ValueId,
381        /// The value compared with.
382        compare: ValueId,
383        /// The new value stored where the comparison holds.
384        value: ValueId,
385    },
386    /// `fence`: ordering between invocations, which a lockstep reading does not have.
387    Fence,
388}
389
390impl Op {
391    /// The values the operation reads (a call's arguments, not its callee; a phi's incoming values).
392    pub fn operands(&self) -> Vec<ValueId> {
393        match self {
394            Op::Binary { lhs, rhs, .. } | Op::Compare { lhs, rhs, .. } => vec![*lhs, *rhs],
395            Op::Cast { value, .. } => vec![*value],
396            Op::Select {
397                condition,
398                then,
399                otherwise,
400            } => vec![*condition, *then, *otherwise],
401            Op::ExtractValue { aggregate, .. } => vec![*aggregate],
402            Op::InsertValue { aggregate, value, .. } => vec![*aggregate, *value],
403            Op::ExtractElement { vector, index } => vec![*vector, *index],
404            Op::InsertElement { vector, value, index } => vec![*vector, *value, *index],
405            Op::ShuffleVector { first, second, mask } => vec![*first, *second, *mask],
406            Op::Call { args, .. } => args.clone(),
407            Op::Phi { incoming } => incoming.iter().map(|(v, _)| *v).collect(),
408            Op::Return(value) => value.iter().copied().collect(),
409            Op::CondBranch { condition, .. } => vec![*condition],
410            Op::Switch { value, cases, .. } => std::iter::once(*value)
411                .chain(cases.iter().map(|(c, _)| *c))
412                .collect(),
413            Op::Load { pointer } => vec![*pointer],
414            Op::Store { pointer, value } | Op::AtomicRmw { pointer, value, .. } => vec![*pointer, *value],
415            Op::Gep { base, indices } => std::iter::once(*base).chain(indices.iter().copied()).collect(),
416            Op::CmpXchg {
417                pointer,
418                compare,
419                value,
420            } => vec![*pointer, *compare, *value],
421            Op::Branch { .. } | Op::Unreachable | Op::Alloca { .. } | Op::Fence => Vec::new(),
422        }
423    }
424
425    /// The basic blocks the operation names (a branch's targets, a phi's predecessors).
426    pub fn blocks(&self) -> Vec<usize> {
427        match self {
428            Op::Branch { target } => vec![*target],
429            Op::CondBranch { then, otherwise, .. } => vec![*then, *otherwise],
430            Op::Switch { default, cases, .. } => std::iter::once(*default)
431                .chain(cases.iter().map(|(_, b)| *b))
432                .collect(),
433            Op::Phi { incoming } => incoming.iter().map(|(_, b)| *b).collect(),
434            _ => Vec::new(),
435        }
436    }
437}
438
439/// An instruction of a function body.
440#[derive(Clone, Debug, PartialEq)]
441pub struct Instruction {
442    /// What it does.
443    pub op: Op,
444    /// The result's value id and type, when the instruction produces one.
445    pub result: Option<(ValueId, TypeId)>,
446    /// The basic block it belongs to.
447    pub block: usize,
448    /// Bit offset of its record.
449    pub at: usize,
450    /// The instruction carries the `dx.precise` attachment, which the compiler writes for HLSL's `precise`: the value
451    /// is not to be fused or reassociated. In skate.'s stock programs it is on calls only: 88,541 `tertiary` (mad),
452    /// 13,005 `loadInput`, 3,546 `unary`, 1,421 `dot3`, 331 `legacyF16ToF32`, 307 `binary`, 213 `dot4` and 105 `dot2`,
453    /// in vertex programs (107,109 instructions in 3,185 of 3,341) and compute programs (360 in 12), in no pixel
454    /// program; none of Elden Ring's has it.
455    pub precise: bool,
456    /// The metadata attached to the instruction, in the order the file stores the pairs (`dx.precise` among them).
457    pub attachments: Vec<Attachment>,
458}
459
460/// A metadata node attached to an instruction or a function: the kind (the id [`Module::kinds`] names) and the node.
461/// In the games' programs the kinds are `dx.controlflow.hints`, `llvm.loop`, `tbaa`, `noalias`, `alias.scope`, `range`
462/// and `dx.precise`.
463#[derive(Clone, Copy, Debug, PartialEq, Eq)]
464pub struct Attachment {
465    /// The metadata kind id (`dx.precise`, `tbaa`, ... by [`Module::kind_name`]).
466    pub kind: u64,
467    /// The attached node, an id into [`Module::metadata`].
468    pub node: MetadataId,
469}
470
471/// An attribute of an attribute group, as the bitcode stores it.
472#[derive(Clone, Debug, PartialEq, Eq)]
473pub enum Attribute {
474    /// A flag attribute, by LLVM's bitcode kind number (see [`attribute_name`]).
475    Enum(u64),
476    /// An attribute with an integer value: its kind number and the value.
477    Integer(u64, u64),
478    /// A string attribute: the key and the value (empty where the attribute has none).
479    String(String, String),
480}
481
482/// A group of attributes, which an attribute list names by its id.
483#[derive(Clone, Debug, PartialEq, Eq)]
484pub struct AttributeGroup {
485    /// The group's id, as the lists name it.
486    pub id: u64,
487    /// The slot the attributes apply to: [`FUNCTION_SLOT`] the function itself, 0 its result, 1 and up its parameters.
488    pub slot: u64,
489    /// The attributes, in the order stored.
490    pub attributes: Vec<Attribute>,
491}
492
493/// The slot of an [`AttributeGroup`] that holds a function's own attributes (`0xFFFFFFFF`).
494pub const FUNCTION_SLOT: u64 = 0xFFFF_FFFF;
495
496/// The name of an LLVM 3.7 enum attribute's bitcode kind number (`nounwind` for 18), for the kinds whose number dxc's own
497/// listing confirms: 9 `noalias`, 11 `nocapture`, 12 `noduplicate`, 17 `noreturn`, 18 `nounwind`, 20 `readnone`, 21
498/// `readonly`, 39 `nonnull`. They are the kinds the games' programs and the test compilations use.
499pub fn attribute_name(kind: u64) -> Option<&'static str> {
500    Some(match kind {
501        9 => "noalias",
502        11 => "nocapture",
503        12 => "noduplicate",
504        17 => "noreturn",
505        18 => "nounwind",
506        20 => "readnone",
507        21 => "readonly",
508        39 => "nonnull",
509        _ => return None,
510    })
511}
512
513/// A function body.
514#[derive(Clone, Debug, PartialEq)]
515pub struct Function {
516    /// The function's module value id.
517    pub value: ValueId,
518    /// The number of basic blocks.
519    pub blocks: usize,
520    /// The instructions of all blocks, in order.
521    pub instructions: Vec<Instruction>,
522    /// The body's own values (arguments, constants, instruction results) and their types; their ids start at
523    /// `first`, after the module's values.
524    pub first: ValueId,
525    /// The values of the body.
526    pub locals: Vec<Value>,
527    /// The types of [`Function::locals`].
528    pub local_types: Vec<TypeId>,
529    /// The metadata attached to the function itself (the attachment records of the body that name no instruction).
530    pub attachments: Vec<Attachment>,
531}
532
533/// A module: its types, values, metadata and function bodies.
534#[derive(Clone, Debug, Default, PartialEq)]
535pub struct Module {
536    /// The type table.
537    pub types: Vec<Type>,
538    /// The module's values by id (globals, functions, module constants); a function body's own values continue the
539    /// numbering in its [`Function`].
540    pub values: Vec<Value>,
541    /// Each value's type.
542    pub value_types: Vec<TypeId>,
543    /// The symbol table: the name of the values that have one.
544    pub names: Vec<(ValueId, String)>,
545    /// The metadata records, by [`MetadataId`].
546    pub metadata: Vec<Metadata>,
547    /// The bit of the bitcode each metadata record (by id) starts at, for the locations of reflection errors.
548    pub metadata_at: Vec<usize>,
549    /// The named metadata (`dx.entryPoints`, ...): the name and the records it lists.
550    pub named_metadata: Vec<(String, Vec<MetadataId>)>,
551    /// The bit each named metadata record (by index in `named_metadata`) starts at.
552    pub named_metadata_at: Vec<usize>,
553    /// The bit of the bitcode the module block starts at: where a record the module lacks would be.
554    pub at: usize,
555    /// The function bodies, in the order of their definitions.
556    pub functions: Vec<Function>,
557    /// The id of the module's `dx.precise` metadata kind (the kind [`Instruction::precise`] reads), where it names one.
558    pub precise_kind: Option<u64>,
559    /// The module's metadata kinds: each id and its name, in the order stored.
560    pub kinds: Vec<(u64, String)>,
561    /// The attribute groups, in the order stored.
562    pub attribute_groups: Vec<AttributeGroup>,
563    /// The attribute lists, in the order stored: the ids of the groups each lists. A function value's `attributes` is an
564    /// index into this.
565    pub attribute_lists: Vec<Vec<u64>>,
566}
567
568fn op(r: &Record, i: usize) -> Result<u64> {
569    r.operands
570        .get(i)
571        .copied()
572        .ok_or_else(|| error(r.at, format!("record {} lacks operand {i}", r.code)))
573}
574fn text(ops: &[u64], at: usize) -> Result<Vec<u8>> {
575    ops.iter()
576        .map(|&c| u8::try_from(c).map_err(|_| error(at, "character above 255")))
577        .collect()
578}
579/// The zero-terminated string starting at operand `from` of an attribute record, and the index after its terminator.
580fn c_string(r: &Record, from: usize) -> Result<(String, usize)> {
581    let rest = r.operands.get(from..).unwrap_or_default();
582    let n = rest
583        .iter()
584        .position(|&c| c == 0)
585        .ok_or_else(|| error(r.at, "an attribute string without its terminator"))?;
586    let bytes = text(rest.get(..n).unwrap_or_default(), r.at)?;
587    Ok((
588        String::from_utf8_lossy(&bytes).into_owned(),
589        from.saturating_add(n).saturating_add(1),
590    ))
591}
592fn utf8(bytes: Vec<u8>, at: usize) -> Result<String> {
593    String::from_utf8(bytes).map_err(|_| error(at, "name is not UTF-8"))
594}
595fn signed_vbr(v: u64) -> i64 {
596    if v & 1 == 0 {
597        i64::try_from(v >> 1).unwrap_or(i64::MAX)
598    } else if v == 1 {
599        i64::MIN
600    } else {
601        i64::try_from(v >> 1).map_or(i64::MIN, i64::wrapping_neg)
602    }
603}
604
605impl Module {
606    fn ty(&self, id: u64, at: usize) -> Result<TypeId> {
607        let id = usize::try_from(id).map_err(|_| error(at, "type id"))?;
608        if id < self.types.len() {
609            Ok(id)
610        } else {
611            Err(error(at, format!("type {id} undefined")))
612        }
613    }
614    /// The type `id`, which an earlier record has already checked against the table (an error where it has not).
615    fn type_at(&self, id: TypeId, at: usize) -> Result<&Type> {
616        self.types
617            .get(id)
618            .ok_or_else(|| error(at, format!("type {id} of {} types", self.types.len())))
619    }
620    /// The id of the type `ty`, appended to the table where it is not there yet.
621    fn intern(&mut self, ty: Type) -> TypeId {
622        match self.types.iter().position(|x| *x == ty) {
623            Some(p) => p,
624            None => {
625                self.types.push(ty);
626                self.types.len().saturating_sub(1)
627            }
628        }
629    }
630    /// The module's name for a value, where its symbol table has one.
631    pub fn name(&self, value: ValueId) -> Option<&str> {
632        self.names
633            .iter()
634            .find(|(v, _)| *v == value)
635            .map(|(_, n)| n.as_str())
636    }
637    fn push(&mut self, value: Value, ty: TypeId, at: usize) -> Result<ValueId> {
638        if self.values.len() >= MAX_VALUES {
639            return Err(error(at, "too many values"));
640        }
641        self.values.push(value);
642        self.value_types.push(ty);
643        Ok(self.values.len().saturating_sub(1))
644    }
645
646    fn read_types(&mut self, block: &Block) -> Result<()> {
647        let mut struct_name: Option<String> = None;
648        for r in block.records() {
649            if self.types.len() >= MAX_TYPES {
650                return Err(error(r.at, "too many types"));
651            }
652            let t = match r.code {
653                1 => continue, // NUMENTRY
654                2 => Type::Void,
655                3 => Type::Float,
656                4 => Type::Double,
657                5 => Type::Label,
658                6 => Type::Opaque(struct_name.take()),
659                7 => Type::Integer(
660                    u32::try_from(op(r, 0)?)
661                        .ok()
662                        .filter(|w| (1..=64).contains(w))
663                        .ok_or_else(|| error(r.at, "integer width"))?,
664                ),
665                8 => Type::Pointer(
666                    self.ty(op(r, 0)?, r.at)?,
667                    u32::try_from(op(r, 1)?).map_err(|_| error(r.at, "pointer address space"))?,
668                ),
669                10 => Type::Half,
670                11 => Type::Array(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
671                12 => Type::Vector(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
672                16 => Type::Metadata,
673                18 | 20 => Type::Struct {
674                    name: if r.code == 20 { struct_name.take() } else { None },
675                    elements: r
676                        .operands
677                        .get(1..)
678                        .unwrap_or_default()
679                        .iter()
680                        .map(|&t| self.ty(t, r.at))
681                        .collect::<Result<_>>()?,
682                },
683                19 => {
684                    struct_name = Some(utf8(text(&r.operands, r.at)?, r.at)?);
685                    continue;
686                }
687                21 => Type::Function {
688                    vararg: op(r, 0)? != 0,
689                    ret: self.ty(op(r, 1)?, r.at)?,
690                    params: r
691                        .operands
692                        .get(2..)
693                        .unwrap_or_default()
694                        .iter()
695                        .map(|&t| self.ty(t, r.at))
696                        .collect::<Result<_>>()?,
697                },
698                other => return Err(error(r.at, format!("type record {other}"))),
699            };
700            self.types.push(t);
701        }
702        Ok(())
703    }
704
705    /// Read a constants block, appending its values. Value ids inside aggregates are absolute.
706    fn read_constants(&mut self, block: &Block) -> Result<()> {
707        let mut ty: Option<TypeId> = None;
708        for r in block.records() {
709            let id = |v: u64| usize::try_from(v).map_err(|_| error(r.at, "value id"));
710            if r.code == 1 {
711                ty = Some(self.ty(op(r, 0)?, r.at)?);
712                continue;
713            }
714            let t = ty.ok_or_else(|| error(r.at, "constant before SETTYPE"))?;
715            let c = match r.code {
716                2 => Constant::Null,
717                3 => Constant::Undef,
718                4 => Constant::Integer(signed_vbr(op(r, 0)?)),
719                6 => Constant::Float(op(r, 0)?),
720                7 => Constant::Aggregate(
721                    r.operands
722                        .iter()
723                        .map(|&v| usize::try_from(v).map_err(|_| error(r.at, "value id")))
724                        .collect::<Result<_>>()?,
725                ),
726                8 | 9 => Constant::String(text(&r.operands, r.at)?),
727                22 => Constant::Data(r.operands.clone()),
728                // CE_GEP and CE_INBOUNDS_GEP: [source type,] then (type, value) pairs, the first the base
729                12 | 20 => {
730                    let ops = r
731                        .operands
732                        .get(usize::from(r.operands.len() % 2 == 1)..)
733                        .unwrap_or_default();
734                    let (pairs, rest) = ops.as_chunks::<2>();
735                    let ([_, base], true) = (
736                        pairs.first().unwrap_or(&[0, 0]),
737                        rest.is_empty() && !pairs.is_empty(),
738                    ) else {
739                        return Err(error(r.at, "constant getelementptr operands"));
740                    };
741                    Constant::Gep {
742                        base: id(*base)?,
743                        indices: pairs
744                            .iter()
745                            .skip(1)
746                            .map(|[_, index]| id(*index))
747                            .collect::<Result<_>>()?,
748                    }
749                }
750                // CE_BINOP: [opcode, lhs, rhs, flags?]
751                10 => Constant::Binary {
752                    op: binary(op(r, 0)?, r.at)?,
753                    lhs: id(op(r, 1)?)?,
754                    rhs: id(op(r, 2)?)?,
755                },
756                // CE_CAST: [opcode, operand type, operand]
757                11 => Constant::Cast {
758                    op: cast(op(r, 0)?, r.at)?,
759                    value: id(op(r, 2)?)?,
760                },
761                other => {
762                    return Err(error(
763                        r.at,
764                        format!("constant record {other} (constant expressions are not supported)"),
765                    ));
766                }
767            };
768            self.push(Value::Constant(c), t, r.at)?;
769        }
770        Ok(())
771    }
772
773    fn read_metadata(&mut self, block: &Block) -> Result<()> {
774        let mut name: Option<String> = None;
775        let md = |v: u64, at: usize| usize::try_from(v).map_err(|_| error(at, "metadata id"));
776        for r in block.records() {
777            match r.code {
778                1 => {
779                    self.metadata.push(Metadata::String(text(&r.operands, r.at)?));
780                    self.metadata_at.push(r.at);
781                }
782                2 => {
783                    self.metadata.push(Metadata::Value {
784                        ty: self.ty(op(r, 0)?, r.at)?,
785                        value: md(op(r, 1)?, r.at)?,
786                    });
787                    self.metadata_at.push(r.at);
788                }
789                3 | 5 => {
790                    self.metadata.push(Metadata::Node(
791                        r.operands
792                            .iter()
793                            .map(|&v| {
794                                if v == 0 {
795                                    Ok(None)
796                                } else {
797                                    md(v.saturating_sub(1), r.at).map(Some)
798                                }
799                            })
800                            .collect::<Result<_>>()?,
801                    ));
802                    self.metadata_at.push(r.at);
803                }
804                4 => name = Some(utf8(text(&r.operands, r.at)?, r.at)?),
805                10 => {
806                    let n = name
807                        .take()
808                        .ok_or_else(|| error(r.at, "named node without a name"))?;
809                    let nodes = r.operands.iter().map(|&v| md(v, r.at)).collect::<Result<_>>()?;
810                    self.named_metadata.push((n, nodes));
811                    self.named_metadata_at.push(r.at);
812                }
813                6 => {
814                    // KIND: [kind id, name]
815                    let id = op(r, 0)?;
816                    let bytes = text(r.operands.get(1..).unwrap_or_default(), r.at)?;
817                    if bytes == b"dx.precise" {
818                        self.precise_kind = Some(id);
819                    }
820                    self.kinds
821                        .push((id, String::from_utf8_lossy(&bytes).into_owned()));
822                }
823                other => return Err(error(r.at, format!("metadata record {other}"))),
824            }
825        }
826        Ok(())
827    }
828
829    /// The attribute groups: records `[group id, slot, attribute...]`, an attribute being `[0, kind]` (a flag), `[1, kind,
830    /// value]`, `[3, key..., 0]` or `[4, key..., 0, value..., 0]`.
831    fn read_attribute_groups(&mut self, block: &Block) -> Result<()> {
832        for r in block.records().filter(|r| r.code == 3) {
833            let mut attributes = Vec::new();
834            let mut i = 2;
835            while i < r.operands.len() {
836                match op(r, i)? {
837                    0 => {
838                        attributes.push(Attribute::Enum(op(r, i.saturating_add(1))?));
839                        i = i.saturating_add(2);
840                    }
841                    1 => {
842                        attributes.push(Attribute::Integer(
843                            op(r, i.saturating_add(1))?,
844                            op(r, i.saturating_add(2))?,
845                        ));
846                        i = i.saturating_add(3);
847                    }
848                    form @ (3 | 4) => {
849                        let (key, next) = c_string(r, i.saturating_add(1))?;
850                        let (value, next) = if form == 4 {
851                            c_string(r, next)?
852                        } else {
853                            (String::new(), next)
854                        };
855                        attributes.push(Attribute::String(key, value));
856                        i = next;
857                    }
858                    other => return Err(error(r.at, format!("attribute encoding {other}"))),
859                }
860            }
861            self.attribute_groups.push(AttributeGroup {
862                id: op(r, 0)?,
863                slot: op(r, 1)?,
864                attributes,
865            });
866        }
867        Ok(())
868    }
869
870    /// The attribute lists: records `[group id...]`.
871    fn read_attribute_lists(&mut self, block: &Block) {
872        for r in block.records().filter(|r| r.code == 2) {
873            self.attribute_lists.push(r.operands.clone());
874        }
875    }
876
877    /// The name of a metadata kind id, where the module names it.
878    pub fn kind_name(&self, kind: u64) -> Option<&str> {
879        self.kinds
880            .iter()
881            .find(|(k, _)| *k == kind)
882            .map(|(_, n)| n.as_str())
883    }
884
885    /// The node of the attachment among `attachments` whose kind is called `name`.
886    pub fn attachment(&self, attachments: &[Attachment], name: &str) -> Option<MetadataId> {
887        attachments
888            .iter()
889            .find(|a| self.kind_name(a.kind) == Some(name))
890            .map(|a| a.node)
891    }
892
893    /// The attributes a function value carries on itself (the groups of its list whose slot is [`FUNCTION_SLOT`]); none
894    /// for a value that is not a function or names no list.
895    pub fn function_attributes(&self, function: ValueId) -> Vec<&Attribute> {
896        let Some(Value::Function {
897            attributes: Some(list),
898            ..
899        }) = self.values.get(function)
900        else {
901            return Vec::new();
902        };
903        let Some(groups) = self.attribute_lists.get(*list) else {
904            return Vec::new();
905        };
906        groups
907            .iter()
908            .filter_map(|id| {
909                self.attribute_groups
910                    .iter()
911                    .find(|g| g.id == *id && g.slot == FUNCTION_SLOT)
912            })
913            .flat_map(|g| g.attributes.iter())
914            .collect()
915    }
916
917    /// The value of the string attribute `key` on a function (empty where the attribute has no value), if it carries it.
918    pub fn string_attribute(&self, function: ValueId, key: &str) -> Option<&str> {
919        self.function_attributes(function)
920            .into_iter()
921            .find_map(|a| match a {
922                Attribute::String(k, v) if k == key => Some(v.as_str()),
923                _ => None,
924            })
925    }
926
927    fn read_symbols(&mut self, block: &Block, base: usize) -> Result<()> {
928        for r in block.records() {
929            match r.code {
930                1 | 3 => {
931                    let value = usize::try_from(op(r, 0)?).map_err(|_| error(r.at, "value id"))?;
932                    let skip = if r.code == 3 { 2 } else { 1 };
933                    let n = utf8(text(r.operands.get(skip..).unwrap_or_default(), r.at)?, r.at)?;
934                    let id = base.checked_add(value).ok_or_else(|| error(r.at, "value id"))?;
935                    self.names.push((id, n));
936                }
937                2 => {} // basic-block names
938                other => return Err(error(r.at, format!("symbol record {other}"))),
939            }
940        }
941        Ok(())
942    }
943}
944
945/// Function-body decoding state: relative value numbering (module version 1).
946struct Body<'m> {
947    m: &'m mut Module,
948    block: usize,
949    blocks: usize,
950}
951impl Body<'_> {
952    fn next(&self) -> usize {
953        self.m.values.len()
954    }
955    /// A relative operand (absolute = next - operand), with its explicit type following when it is a forward
956    /// reference (a value defined later in the function's layout). Returns the value id and its type, and advances `i`.
957    fn value_type(&self, r: &Record, i: &mut usize) -> Result<(ValueId, TypeId)> {
958        let id = self.absolute(op(r, *i)?, r.at)?;
959        *i = i.saturating_add(1);
960        if id < self.next() {
961            let t = self
962                .m
963                .value_types
964                .get(id)
965                .copied()
966                .ok_or_else(|| error(r.at, format!("value {id} has no type")))?;
967            Ok((id, t))
968        } else {
969            let t = self.m.ty(op(r, *i)?, r.at)?;
970            *i = i.saturating_add(1);
971            Ok((id, t))
972        }
973    }
974    /// A relative operand whose type is known from another operand: a forward reference carries none.
975    fn value(&self, r: &Record, i: &mut usize) -> Result<ValueId> {
976        let id = self.absolute(op(r, *i)?, r.at)?;
977        *i = i.saturating_add(1);
978        Ok(id)
979    }
980    /// The absolute id a relative operand names: the next id minus the operand, in 32 bits as LLVM writes it (a value
981    /// defined later is a forward reference, which wraps).
982    fn absolute(&self, relative: u64, at: usize) -> Result<ValueId> {
983        let relative = u32::try_from(relative)
984            .map_err(|_| error(at, format!("relative value id {relative} wider than 32 bits")))?;
985        let next = u32::try_from(self.next()).map_err(|_| error(at, "too many values"))?;
986        Ok(next.wrapping_sub(relative) as usize)
987    }
988    /// The type of a value defined before this point, or of a forward reference by the type given.
989    fn pointer_to(&mut self, t: TypeId) -> TypeId {
990        self.m.intern(Type::Pointer(t, 0))
991    }
992    /// The index a constant integer value stands for, if it is one defined in the module or this function.
993    fn constant_index(&self, v: ValueId) -> Option<usize> {
994        match self.m.values.get(v) {
995            Some(Value::Constant(Constant::Integer(i))) => usize::try_from(*i).ok(),
996            Some(Value::Constant(Constant::Null)) => Some(0),
997            _ => None,
998        }
999    }
1000    fn result(&mut self, ty: TypeId, at: usize) -> Result<Option<(ValueId, TypeId)>> {
1001        if *self.m.type_at(ty, at)? == Type::Void {
1002            return Ok(None);
1003        }
1004        Ok(Some((self.m.push(Value::Local, ty, at)?, ty)))
1005    }
1006}
1007
1008fn binary(code: u64, at: usize) -> Result<BinaryOp> {
1009    Ok(match code {
1010        0 => BinaryOp::Add,
1011        1 => BinaryOp::Sub,
1012        2 => BinaryOp::Mul,
1013        3 => BinaryOp::UDiv,
1014        4 => BinaryOp::SDiv,
1015        5 => BinaryOp::URem,
1016        6 => BinaryOp::SRem,
1017        7 => BinaryOp::Shl,
1018        8 => BinaryOp::LShr,
1019        9 => BinaryOp::AShr,
1020        10 => BinaryOp::And,
1021        11 => BinaryOp::Or,
1022        12 => BinaryOp::Xor,
1023        other => return Err(error(at, format!("binary opcode {other}"))),
1024    })
1025}
1026fn cast(code: u64, at: usize) -> Result<CastOp> {
1027    Ok(match code {
1028        0 => CastOp::Trunc,
1029        1 => CastOp::ZExt,
1030        2 => CastOp::SExt,
1031        3 => CastOp::FpToUi,
1032        4 => CastOp::FpToSi,
1033        5 => CastOp::UiToFp,
1034        6 => CastOp::SiToFp,
1035        7 => CastOp::FpTrunc,
1036        8 => CastOp::FpExt,
1037        9 => CastOp::PtrToInt,
1038        10 => CastOp::IntToPtr,
1039        11 => CastOp::BitCast,
1040        other => return Err(error(at, format!("cast opcode {other}"))),
1041    })
1042}
1043/// The name of a function-body record code this reader refuses.
1044fn refused(code: u64) -> &'static str {
1045    match code {
1046        4 | 30 => "getelementptr (old form)",
1047        13 => "invoke",
1048        41 => "load (atomic)",
1049        23 => "va_arg",
1050        24 | 42 | 45 => "store (atomic)",
1051        31 => "indirectbr",
1052        37 => "cmpxchg (old form)",
1053        59 => "atomicrmw (new form)",
1054        39 => "resume",
1055        40 | 47 => "landingpad",
1056        _ => "unknown instruction record",
1057    }
1058}
1059
1060/// Reads a function's attachment block: a record `[instruction, (kind, node)...]` (an odd number of operands) attaches
1061/// the pairs to that instruction, a record of an even number of operands, `(kind, node)...`, to the function itself.
1062/// An instruction given the `dx.precise` kind is also marked [`Instruction::precise`].
1063fn read_attachments(
1064    precise: Option<u64>,
1065    block: &Block,
1066    instructions: &mut [Instruction],
1067    function: &mut Vec<Attachment>,
1068) -> Result<()> {
1069    for r in block.records().filter(|r| r.code == 11) {
1070        let per_instruction = r.operands.len() % 2 == 1;
1071        let mut attachments = Vec::new();
1072        let (pairs, _) = r
1073            .operands
1074            .get(usize::from(per_instruction)..)
1075            .unwrap_or_default()
1076            .as_chunks::<2>();
1077        for &[kind, node] in pairs {
1078            attachments.push(Attachment {
1079                kind,
1080                node: usize::try_from(node).map_err(|_| error(r.at, "attachment node"))?,
1081            });
1082        }
1083        if !per_instruction {
1084            function.extend(attachments);
1085            continue;
1086        }
1087        let at = usize::try_from(op(r, 0)?).map_err(|_| error(r.at, "attachment instruction"))?;
1088        let instruction = instructions.get_mut(at).ok_or_else(|| {
1089            error(
1090                r.at,
1091                format!("an attachment names instruction {at} of a shorter body"),
1092            )
1093        })?;
1094        if precise.is_some_and(|kind| attachments.iter().any(|a| a.kind == kind)) {
1095            instruction.precise = true;
1096        }
1097        instruction.attachments.extend(attachments);
1098    }
1099    Ok(())
1100}
1101
1102impl Module {
1103    fn read_function(&mut self, block: &Block, value: ValueId) -> Result<Function> {
1104        let fty = match self.value_types.get(value).and_then(|&t| self.types.get(t)) {
1105            Some(Type::Pointer(t, _)) => *t,
1106            _ => return Err(error(block.at, "function value is not a function pointer")),
1107        };
1108        let params = match self.type_at(fty, block.at)? {
1109            Type::Function { params, .. } => params.clone(),
1110            _ => return Err(error(block.at, "function type")),
1111        };
1112        let base = self.values.len();
1113        for p in params {
1114            self.push(Value::Local, p, block.at)?;
1115        }
1116        let mut body = Body {
1117            m: self,
1118            block: 0,
1119            blocks: 0,
1120        };
1121        let mut instructions = Vec::new();
1122        let mut function_attachments = Vec::new();
1123        for e in &block.elements {
1124            let r = match e {
1125                crate::bitstream::Element::Block(b) => {
1126                    match b.id {
1127                        CONSTANTS => body.m.read_constants(b)?,
1128                        VALUE_SYMTAB => body.m.read_symbols(b, 0)?,
1129                        METADATA_ATTACHMENT => read_attachments(
1130                            body.m.precise_kind,
1131                            b,
1132                            &mut instructions,
1133                            &mut function_attachments,
1134                        )?,
1135                        METADATA | USELIST => {}
1136                        other => return Err(error(b.at, format!("block {other} in a function"))),
1137                    }
1138                    continue;
1139                }
1140                crate::bitstream::Element::Record(r) => r,
1141            };
1142            let mut i = 0;
1143            let (op, ty): (Op, Option<TypeId>) = match r.code {
1144                1 => {
1145                    body.blocks = usize::try_from(op(r, 0)?)
1146                        .ok()
1147                        .filter(|&n| n > 0 && n <= 1 << 16)
1148                        .ok_or_else(|| error(r.at, "basic block count"))?;
1149                    continue;
1150                }
1151                33 | 35 => continue, // debug locations
1152                2 => {
1153                    let (lhs, t) = body.value_type(r, &mut i)?;
1154                    let rhs = body.value(r, &mut i)?;
1155                    let o = binary(op(r, i)?, r.at)?;
1156                    (Op::Binary { op: o, lhs, rhs }, Some(t))
1157                }
1158                3 => {
1159                    let value = body.value(r, &mut i)?;
1160                    let to = body.m.ty(op(r, i)?, r.at)?;
1161                    let o = cast(op(r, i.saturating_add(1))?, r.at)?;
1162                    (Op::Cast { op: o, value }, Some(to))
1163                }
1164                9 | 28 => {
1165                    let (lhs, t) = body.value_type(r, &mut i)?;
1166                    let rhs = body.value(r, &mut i)?;
1167                    let predicate = op(r, i)?;
1168                    let bool_ty = match body.m.type_at(t, r.at)? {
1169                        Type::Vector(..) => {
1170                            return Err(error(r.at, "vector comparison"));
1171                        }
1172                        _ => body
1173                            .m
1174                            .types
1175                            .iter()
1176                            .position(|x| *x == Type::Integer(1))
1177                            .ok_or_else(|| error(r.at, "no i1 type for a comparison"))?,
1178                    };
1179                    (Op::Compare { predicate, lhs, rhs }, Some(bool_ty))
1180                }
1181                29 => {
1182                    let (then, t) = body.value_type(r, &mut i)?;
1183                    let otherwise = body.value(r, &mut i)?;
1184                    let condition = body.value(r, &mut i)?;
1185                    (
1186                        Op::Select {
1187                            condition,
1188                            then,
1189                            otherwise,
1190                        },
1191                        Some(t),
1192                    )
1193                }
1194                26 => {
1195                    let (aggregate, mut t) = body.value_type(r, &mut i)?;
1196                    let indices = r.operands.get(i..).unwrap_or_default().to_vec();
1197                    for &k in &indices {
1198                        t = match body.m.type_at(t, r.at)? {
1199                            Type::Struct { elements, .. } => *usize::try_from(k)
1200                                .ok()
1201                                .and_then(|k| elements.get(k))
1202                                .ok_or_else(|| error(r.at, "extractvalue index"))?,
1203                            Type::Array(n, e) if k < *n => *e,
1204                            _ => return Err(error(r.at, "extractvalue index")),
1205                        };
1206                    }
1207                    (Op::ExtractValue { aggregate, indices }, Some(t))
1208                }
1209                6 => {
1210                    let (vector, t) = body.value_type(r, &mut i)?;
1211                    let (index, _) = body.value_type(r, &mut i)?;
1212                    let Type::Vector(_, element) = *body.m.type_at(t, r.at)? else {
1213                        return Err(error(r.at, "extractelement of something that is not a vector"));
1214                    };
1215                    (Op::ExtractElement { vector, index }, Some(element))
1216                }
1217                7 => {
1218                    let (vector, t) = body.value_type(r, &mut i)?;
1219                    let value = body.value(r, &mut i)?;
1220                    let (index, _) = body.value_type(r, &mut i)?;
1221                    (Op::InsertElement { vector, value, index }, Some(t))
1222                }
1223                8 => {
1224                    let (first, t) = body.value_type(r, &mut i)?;
1225                    let second = body.value(r, &mut i)?;
1226                    let (mask, mask_ty) = body.value_type(r, &mut i)?;
1227                    let (Type::Vector(_, element), Type::Vector(lanes, _)) = (
1228                        body.m.type_at(t, r.at)?.clone(),
1229                        body.m.type_at(mask_ty, r.at)?.clone(),
1230                    ) else {
1231                        return Err(error(r.at, "shufflevector of something that is not a vector"));
1232                    };
1233                    let result = body
1234                        .m
1235                        .types
1236                        .iter()
1237                        .position(|x| *x == Type::Vector(lanes, element))
1238                        .ok_or_else(|| error(r.at, "no type for the shuffled vector"))?;
1239                    (Op::ShuffleVector { first, second, mask }, Some(result))
1240                }
1241                27 => {
1242                    let (aggregate, t) = body.value_type(r, &mut i)?;
1243                    let value = body.value(r, &mut i)?;
1244                    let indices = r.operands.get(i..).unwrap_or_default().to_vec();
1245                    (
1246                        Op::InsertValue {
1247                            aggregate,
1248                            value,
1249                            indices,
1250                        },
1251                        Some(t),
1252                    )
1253                }
1254                34 => {
1255                    i = 1; // paramattrs
1256                    let cc = op(r, i)?;
1257                    i = i.saturating_add(1);
1258                    if cc & (1 << 17) != 0 {
1259                        i = i.saturating_add(1); // fast-math flags
1260                    }
1261                    let explicit = if cc & (1 << 15) != 0 {
1262                        let t = body.m.ty(op(r, i)?, r.at)?;
1263                        i = i.saturating_add(1);
1264                        Some(t)
1265                    } else {
1266                        None
1267                    };
1268                    let (function, callee_ty) = body.value_type(r, &mut i)?;
1269                    let fty = match (explicit, body.m.type_at(callee_ty, r.at)?) {
1270                        (Some(t), _) => t,
1271                        (None, Type::Pointer(t, _)) => *t,
1272                        _ => return Err(error(r.at, "callee is not a function pointer")),
1273                    };
1274                    let (ret, params, vararg) = match body.m.type_at(fty, r.at)? {
1275                        Type::Function { ret, params, vararg } => (*ret, params.clone(), *vararg),
1276                        _ => return Err(error(r.at, "call through a non-function type")),
1277                    };
1278                    if vararg {
1279                        return Err(error(r.at, "vararg call"));
1280                    }
1281                    let mut args = Vec::with_capacity(params.len());
1282                    for p in &params {
1283                        // a fixed parameter carries no type, even for a value defined later in the layout
1284                        let a = body.value(r, &mut i)?;
1285                        if a < body.next() && body.m.value_types.get(a) != Some(p) {
1286                            return Err(error(r.at, "call argument type"));
1287                        }
1288                        args.push(a);
1289                    }
1290                    if i != r.operands.len() {
1291                        return Err(error(r.at, "call operands left over"));
1292                    }
1293                    (Op::Call { function, args }, Some(ret))
1294                }
1295                16 => {
1296                    let t = body.m.ty(op(r, 0)?, r.at)?;
1297                    let pairs = r.operands.get(1..).unwrap_or_default();
1298                    if pairs.is_empty() || pairs.len() % 2 != 0 {
1299                        return Err(error(r.at, "phi operands"));
1300                    }
1301                    let next = i64::try_from(body.next()).map_err(|_| error(r.at, "too many values"))?;
1302                    let mut incoming = Vec::with_capacity(pairs.len() / 2);
1303                    for pair in pairs.as_chunks::<2>().0 {
1304                        // Signed and relative to the phi itself; it may name a value defined later.
1305                        let id = next
1306                            .checked_sub(signed_vbr(pair[0]))
1307                            .and_then(|v| usize::try_from(v).ok())
1308                            .ok_or_else(|| error(r.at, "phi value"))?;
1309                        let block = usize::try_from(pair[1])
1310                            .ok()
1311                            .filter(|&b| b < body.blocks)
1312                            .ok_or_else(|| error(r.at, "phi block"))?;
1313                        incoming.push((id, block));
1314                    }
1315                    (Op::Phi { incoming }, Some(t))
1316                }
1317                10 => {
1318                    if r.operands.is_empty() {
1319                        (Op::Return(None), None)
1320                    } else {
1321                        (Op::Return(Some(body.value(r, &mut i)?)), None)
1322                    }
1323                }
1324                11 => {
1325                    let target = |v: u64| -> Result<usize> {
1326                        usize::try_from(v)
1327                            .ok()
1328                            .filter(|&b| b < body.blocks)
1329                            .ok_or_else(|| error(r.at, "branch target"))
1330                    };
1331                    if r.operands.len() == 1 {
1332                        (
1333                            Op::Branch {
1334                                target: target(op(r, 0)?)?,
1335                            },
1336                            None,
1337                        )
1338                    } else {
1339                        let then = target(op(r, 0)?)?;
1340                        let otherwise = target(op(r, 1)?)?;
1341                        i = 2;
1342                        let condition = body.value(r, &mut i)?;
1343                        (
1344                            Op::CondBranch {
1345                                condition,
1346                                then,
1347                                otherwise,
1348                            },
1349                            None,
1350                        )
1351                    }
1352                }
1353                12 => {
1354                    // [type, value, default block, (case constant, block)*]; case constants are absolute ids
1355                    let block = |v: u64| -> Result<usize> {
1356                        usize::try_from(v)
1357                            .ok()
1358                            .filter(|&b| b < body.blocks)
1359                            .ok_or_else(|| error(r.at, "switch target"))
1360                    };
1361                    i = 1;
1362                    let value = body.value(r, &mut i)?;
1363                    let default = block(op(r, i)?)?;
1364                    let pairs = r.operands.get(i.saturating_add(1)..).unwrap_or_default();
1365                    if pairs.len() % 2 != 0 {
1366                        return Err(error(r.at, "switch cases"));
1367                    }
1368                    let cases = pairs
1369                        .as_chunks::<2>()
1370                        .0
1371                        .iter()
1372                        .map(|p| {
1373                            Ok((
1374                                usize::try_from(p[0]).map_err(|_| error(r.at, "case value"))?,
1375                                block(p[1])?,
1376                            ))
1377                        })
1378                        .collect::<Result<Vec<_>>>()?;
1379                    (
1380                        Op::Switch {
1381                            value,
1382                            default,
1383                            cases,
1384                        },
1385                        None,
1386                    )
1387                }
1388                15 => (Op::Unreachable, None),
1389                19 => {
1390                    // [allocated type, size type, size (absolute id), alignment]
1391                    let ty = body.m.ty(op(r, 0)?, r.at)?;
1392                    (Op::Alloca { ty }, Some(body.pointer_to(ty)))
1393                }
1394                20 => {
1395                    let (pointer, pt) = body.value_type(r, &mut i)?;
1396                    let _ = pt;
1397                    let ty = body.m.ty(op(r, i)?, r.at)?;
1398                    (Op::Load { pointer }, Some(ty))
1399                }
1400                44 => {
1401                    let (pointer, _) = body.value_type(r, &mut i)?;
1402                    let (value, _) = body.value_type(r, &mut i)?;
1403                    (Op::Store { pointer, value }, None)
1404                }
1405                // atomicrmw (LLVM 3.7): [pointer with its type, value, operation, volatile, ordering, scope]
1406                38 => {
1407                    let (pointer, _) = body.value_type(r, &mut i)?;
1408                    let value = body.value(r, &mut i)?;
1409                    let op = op(r, i)?;
1410                    let ty = body.m.value_types.get(value).copied();
1411                    let ty = match ty {
1412                        Some(t) if value < body.next() => t,
1413                        _ => return Err(error(r.at, "an atomicrmw of a value defined later")),
1414                    };
1415                    (Op::AtomicRmw { pointer, value, op }, Some(ty))
1416                }
1417                // cmpxchg: [pointer with its type, compare with its type, new value, volatile, orderings, ...]; the
1418                // result is a structure of the value and a flag
1419                46 => {
1420                    let (pointer, _) = body.value_type(r, &mut i)?;
1421                    let (compare, ty) = body.value_type(r, &mut i)?;
1422                    let value = body.value(r, &mut i)?;
1423                    let flag = body
1424                        .m
1425                        .types
1426                        .iter()
1427                        .position(|t| *t == Type::Integer(1))
1428                        .ok_or_else(|| error(r.at, "a cmpxchg without a boolean type"))?;
1429                    let pair = Type::Struct {
1430                        name: None,
1431                        elements: vec![ty, flag],
1432                    };
1433                    let result = body.m.intern(pair);
1434                    (
1435                        Op::CmpXchg {
1436                            pointer,
1437                            compare,
1438                            value,
1439                        },
1440                        Some(result),
1441                    )
1442                }
1443                36 => (Op::Fence, None),
1444                43 => {
1445                    // [inbounds, source element type, then each operand with its type when a forward reference]
1446                    i = 2;
1447                    let source = body.m.ty(op(r, 1)?, r.at)?;
1448                    let (base, _) = body.value_type(r, &mut i)?;
1449                    let mut indices = Vec::new();
1450                    while i < r.operands.len() {
1451                        indices.push(body.value_type(r, &mut i)?.0);
1452                    }
1453                    // the result points at what the indices reach: the first steps over the pointer, the rest into
1454                    // arrays, vectors and structures
1455                    let mut t = source;
1456                    for &index in indices.iter().skip(1) {
1457                        t = match body.m.type_at(t, r.at)?.clone() {
1458                            Type::Array(_, e) | Type::Vector(_, e) => e,
1459                            Type::Struct { elements, .. } => {
1460                                let k = match body.constant_index(index) {
1461                                    Some(k) => k,
1462                                    None => {
1463                                        return Err(error(r.at, "a structure index that is not constant"));
1464                                    }
1465                                };
1466                                *elements
1467                                    .get(k)
1468                                    .ok_or_else(|| error(r.at, "getelementptr structure index"))?
1469                            }
1470                            _ => return Err(error(r.at, "getelementptr into a scalar")),
1471                        };
1472                    }
1473                    (Op::Gep { base, indices }, Some(body.pointer_to(t)))
1474                }
1475                other => {
1476                    return Err(error(
1477                        r.at,
1478                        format!("instruction {} (record {other}) is not supported", refused(other)),
1479                    ));
1480                }
1481            };
1482            let result = match ty {
1483                Some(t) => body.result(t, r.at)?,
1484                None => None,
1485            };
1486            let terminator = matches!(
1487                op,
1488                Op::Return(_)
1489                    | Op::Branch { .. }
1490                    | Op::CondBranch { .. }
1491                    | Op::Switch { .. }
1492                    | Op::Unreachable
1493            );
1494            instructions.push(Instruction {
1495                op,
1496                result,
1497                block: body.block,
1498                at: r.at,
1499                precise: false,
1500                attachments: Vec::new(),
1501            });
1502            if terminator {
1503                body.block = body.block.saturating_add(1);
1504            }
1505        }
1506        if body.block != body.blocks {
1507            return Err(error(block.at, "basic blocks without terminators"));
1508        }
1509        let end = body.next();
1510        let blocks = body.blocks;
1511        // everything an instruction names is something the function has: a value (an earlier one, or a later one a phi
1512        // or a loop reads), a basic block, and a callee taking the arguments it is given
1513        for inst in &instructions {
1514            if inst.block >= blocks {
1515                return Err(error(inst.at, "an instruction after the last terminator"));
1516            }
1517            if let Some(v) = inst.op.operands().into_iter().find(|v| *v >= end) {
1518                return Err(error(inst.at, format!("value {v} of {end} values")));
1519            }
1520            if let Some(b) = inst.op.blocks().into_iter().find(|b| *b >= blocks) {
1521                return Err(error(inst.at, format!("basic block {b} of {blocks}")));
1522            }
1523            if let Op::Call { function, args } = &inst.op {
1524                if *function >= end {
1525                    return Err(error(inst.at, format!("callee {function} of {end} values")));
1526                }
1527                if let Some(Value::Function { ty, .. }) = self.values.get(*function)
1528                    && let Some(Type::Function {
1529                        vararg: false,
1530                        params,
1531                        ..
1532                    }) = self.types.get(*ty)
1533                    && params.len() != args.len()
1534                {
1535                    return Err(error(
1536                        inst.at,
1537                        format!(
1538                            "a call of {} arguments to a function of {} parameters",
1539                            args.len(),
1540                            params.len()
1541                        ),
1542                    ));
1543                }
1544            }
1545        }
1546        let locals = self.values.split_off(base);
1547        let local_types = self.value_types.split_off(base);
1548        Ok(Function {
1549            value,
1550            blocks,
1551            instructions,
1552            first: base,
1553            locals,
1554            local_types,
1555            attachments: function_attachments,
1556        })
1557    }
1558
1559    /// Read a module from the bitcode's top-level blocks.
1560    pub fn read(top: &[Block]) -> Result<Self> {
1561        let module = match top {
1562            [m] if m.id == MODULE => m,
1563            _ => return Err(error(0, "bitcode is not one module block")),
1564        };
1565        let mut m = Module {
1566            at: module.at,
1567            ..Module::default()
1568        };
1569        let mut bodies: Vec<ValueId> = Vec::new();
1570        let mut version = None;
1571        for e in &module.elements {
1572            match e {
1573                crate::bitstream::Element::Record(r) => match r.code {
1574                    1 => version = Some(op(r, 0)?),
1575                    2..=6 | 11 | 13 | 16 => {} // triple, datalayout, asm, section, deplib, gc, source file
1576                    7 => {
1577                        // GLOBALVAR: [type, flags (bit 0 constant, bit 1 explicit type, from bit 2 the address space),
1578                        // initial value + 1 or 0, ...]
1579                        let t = m.ty(op(r, 0)?, r.at)?;
1580                        let flags = op(r, 1)?;
1581                        let address_space =
1582                            u32::try_from(flags >> 2).map_err(|_| error(r.at, "address space"))?;
1583                        let (ty, value_ty) = if flags & 2 != 0 {
1584                            let pointer = m.intern(Type::Pointer(t, address_space));
1585                            (pointer, t)
1586                        } else {
1587                            match m.type_at(t, r.at)? {
1588                                Type::Pointer(inner, _) => (t, *inner),
1589                                _ => return Err(error(r.at, "a global whose type is not a pointer")),
1590                            }
1591                        };
1592                        let init = match op(r, 2)? {
1593                            0 => None,
1594                            n => Some(
1595                                usize::try_from(n.saturating_sub(1))
1596                                    .map_err(|_| error(r.at, "initial value id"))?,
1597                            ),
1598                        };
1599                        m.push(
1600                            Value::Global {
1601                                ty,
1602                                value_ty,
1603                                init,
1604                                constant: flags & 1 != 0,
1605                                address_space,
1606                            },
1607                            ty,
1608                            r.at,
1609                        )?;
1610                    }
1611                    8 => {
1612                        // FUNCTION: [function type, cc, isproto, ...]
1613                        let t = m.ty(op(r, 0)?, r.at)?;
1614                        let pointer = m.intern(Type::Pointer(t, 0));
1615                        let declaration = op(r, 2)? != 0;
1616                        // the attribute list is named by its 1-based index (0 for none)
1617                        let attributes = r
1618                            .operands
1619                            .get(4)
1620                            .and_then(|&n| usize::try_from(n).ok())
1621                            .and_then(|n| n.checked_sub(1));
1622                        let v = m.push(
1623                            Value::Function {
1624                                ty: t,
1625                                declaration,
1626                                attributes,
1627                            },
1628                            pointer,
1629                            r.at,
1630                        )?;
1631                        if !declaration {
1632                            bodies.push(v);
1633                        }
1634                    }
1635                    other => return Err(error(r.at, format!("module record {other}"))),
1636                },
1637                crate::bitstream::Element::Block(b) => match b.id {
1638                    BLOCKINFO | USELIST => {}
1639                    PARAMATTR_GROUP => m.read_attribute_groups(b)?,
1640                    PARAMATTR => m.read_attribute_lists(b),
1641                    TYPES => m.read_types(b)?,
1642                    CONSTANTS => m.read_constants(b)?,
1643                    METADATA => m.read_metadata(b)?,
1644                    VALUE_SYMTAB => m.read_symbols(b, 0)?,
1645                    FUNCTION => {
1646                        if version != Some(1) {
1647                            return Err(error(b.at, "only relative value ids (module version 1)"));
1648                        }
1649                        // Bodies are stored in the order of their definitions (a hull program has two).
1650                        if bodies.is_empty() {
1651                            return Err(error(b.at, "function body without a definition"));
1652                        }
1653                        let value = bodies.remove(0);
1654                        // A body's values are its own; the next body numbers from the module's values again.
1655                        let f = m.read_function(b, value)?;
1656                        m.functions.push(f);
1657                    }
1658                    other => return Err(error(b.at, format!("module block {other}"))),
1659                },
1660            }
1661        }
1662        if !bodies.is_empty() {
1663            return Err(error(module.at, "a defined function has no body"));
1664        }
1665        Ok(m)
1666    }
1667}