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