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