1use crate::bitstream::{Block, Record};
7use crate::{Result, error};
8
9const MODULE: u64 = 8;
10const PARAMATTR: u64 = 9;
11const PARAMATTR_GROUP: u64 = 10;
12const CONSTANTS: u64 = 11;
13const FUNCTION: u64 = 12;
14const VALUE_SYMTAB: u64 = 14;
15const METADATA: u64 = 15;
16const METADATA_ATTACHMENT: u64 = 16;
17const TYPES: u64 = 17;
18const USELIST: u64 = 18;
19const BLOCKINFO: u64 = 0;
20
21const MAX_VALUES: usize = 1 << 22;
23const MAX_TYPES: usize = 1 << 16;
24
25pub type TypeId = usize;
27pub type ValueId = usize;
29pub type MetadataId = usize;
31
32#[derive(Clone, Debug, PartialEq, Eq)]
34pub enum Type {
35 Void,
37 Label,
39 Metadata,
41 Half,
43 Float,
45 Double,
47 Integer(u32),
49 Pointer(TypeId, u32),
52 Array(u64, TypeId),
54 Vector(u64, TypeId),
56 Struct {
58 name: Option<String>,
60 elements: Vec<TypeId>,
62 },
63 Opaque(Option<String>),
65 Function {
67 vararg: bool,
69 ret: TypeId,
71 params: Vec<TypeId>,
73 },
74}
75
76#[derive(Clone, Debug, PartialEq)]
78pub enum Constant {
79 Null,
81 Undef,
83 Integer(i64),
85 Float(u64),
87 Aggregate(Vec<ValueId>),
89 Data(Vec<u64>),
91 String(Vec<u8>),
93 Gep {
95 base: ValueId,
97 indices: Vec<ValueId>,
99 },
100 Cast {
102 op: CastOp,
104 value: ValueId,
106 },
107 Binary {
109 op: BinaryOp,
111 lhs: ValueId,
113 rhs: ValueId,
115 },
116}
117
118#[derive(Clone, Debug, PartialEq)]
120pub enum Value {
121 Function {
123 ty: TypeId,
125 declaration: bool,
127 },
128 Global {
130 ty: TypeId,
132 value_ty: TypeId,
134 init: Option<ValueId>,
136 constant: bool,
138 address_space: u32,
140 },
141 Constant(Constant),
143 Local,
145}
146
147#[derive(Clone, Debug, PartialEq)]
149pub enum Metadata {
150 String(Vec<u8>),
152 Value {
154 ty: TypeId,
156 value: ValueId,
158 },
159 Node(Vec<Option<MetadataId>>),
161}
162
163#[derive(Clone, Copy, Debug, PartialEq, Eq)]
165pub enum BinaryOp {
166 Add,
168 Sub,
170 Mul,
172 UDiv,
174 SDiv,
176 URem,
178 SRem,
180 Shl,
182 LShr,
184 AShr,
186 And,
188 Or,
190 Xor,
192}
193#[derive(Clone, Copy, Debug, PartialEq, Eq)]
195pub enum CastOp {
196 Trunc,
198 ZExt,
200 SExt,
202 FpToUi,
204 FpToSi,
206 UiToFp,
208 SiToFp,
210 FpTrunc,
212 FpExt,
214 PtrToInt,
216 IntToPtr,
218 BitCast,
220}
221
222#[derive(Clone, Debug, PartialEq)]
224pub enum Op {
225 Binary {
227 op: BinaryOp,
229 lhs: ValueId,
231 rhs: ValueId,
233 },
234 Cast {
236 op: CastOp,
238 value: ValueId,
240 },
241 Compare {
243 predicate: u64,
245 lhs: ValueId,
247 rhs: ValueId,
249 },
250 Select {
252 condition: ValueId,
254 then: ValueId,
256 otherwise: ValueId,
258 },
259 ExtractValue {
261 aggregate: ValueId,
263 indices: Vec<u64>,
265 },
266 InsertValue {
268 aggregate: ValueId,
270 value: ValueId,
272 indices: Vec<u64>,
274 },
275 ExtractElement {
277 vector: ValueId,
279 index: ValueId,
281 },
282 InsertElement {
284 vector: ValueId,
286 value: ValueId,
288 index: ValueId,
290 },
291 ShuffleVector {
293 first: ValueId,
295 second: ValueId,
297 mask: ValueId,
299 },
300 Call {
302 function: ValueId,
304 args: Vec<ValueId>,
306 },
307 Phi {
309 incoming: Vec<(ValueId, usize)>,
311 },
312 Return(Option<ValueId>),
314 Branch {
316 target: usize,
318 },
319 CondBranch {
321 condition: ValueId,
323 then: usize,
325 otherwise: usize,
327 },
328 Switch {
330 value: ValueId,
332 default: usize,
334 cases: Vec<(ValueId, usize)>,
336 },
337 Unreachable,
339 Alloca {
341 ty: TypeId,
343 },
344 Load {
346 pointer: ValueId,
348 },
349 Store {
351 pointer: ValueId,
353 value: ValueId,
355 },
356 Gep {
358 base: ValueId,
360 indices: Vec<ValueId>,
362 },
363 AtomicRmw {
366 pointer: ValueId,
368 value: ValueId,
370 op: u64,
372 },
373 CmpXchg {
375 pointer: ValueId,
377 compare: ValueId,
379 value: ValueId,
381 },
382 Fence,
384}
385
386impl Op {
387 pub fn operands(&self) -> Vec<ValueId> {
389 match self {
390 Op::Binary { lhs, rhs, .. } | Op::Compare { lhs, rhs, .. } => vec![*lhs, *rhs],
391 Op::Cast { value, .. } => vec![*value],
392 Op::Select {
393 condition,
394 then,
395 otherwise,
396 } => vec![*condition, *then, *otherwise],
397 Op::ExtractValue { aggregate, .. } => vec![*aggregate],
398 Op::InsertValue { aggregate, value, .. } => vec![*aggregate, *value],
399 Op::ExtractElement { vector, index } => vec![*vector, *index],
400 Op::InsertElement { vector, value, index } => vec![*vector, *value, *index],
401 Op::ShuffleVector { first, second, mask } => vec![*first, *second, *mask],
402 Op::Call { args, .. } => args.clone(),
403 Op::Phi { incoming } => incoming.iter().map(|(v, _)| *v).collect(),
404 Op::Return(value) => value.iter().copied().collect(),
405 Op::CondBranch { condition, .. } => vec![*condition],
406 Op::Switch { value, cases, .. } => std::iter::once(*value)
407 .chain(cases.iter().map(|(c, _)| *c))
408 .collect(),
409 Op::Load { pointer } => vec![*pointer],
410 Op::Store { pointer, value } | Op::AtomicRmw { pointer, value, .. } => vec![*pointer, *value],
411 Op::Gep { base, indices } => std::iter::once(*base).chain(indices.iter().copied()).collect(),
412 Op::CmpXchg {
413 pointer,
414 compare,
415 value,
416 } => vec![*pointer, *compare, *value],
417 Op::Branch { .. } | Op::Unreachable | Op::Alloca { .. } | Op::Fence => Vec::new(),
418 }
419 }
420
421 pub fn blocks(&self) -> Vec<usize> {
423 match self {
424 Op::Branch { target } => vec![*target],
425 Op::CondBranch { then, otherwise, .. } => vec![*then, *otherwise],
426 Op::Switch { default, cases, .. } => std::iter::once(*default)
427 .chain(cases.iter().map(|(_, b)| *b))
428 .collect(),
429 Op::Phi { incoming } => incoming.iter().map(|(_, b)| *b).collect(),
430 _ => Vec::new(),
431 }
432 }
433}
434
435#[derive(Clone, Debug, PartialEq)]
437pub struct Instruction {
438 pub op: Op,
440 pub result: Option<(ValueId, TypeId)>,
442 pub block: usize,
444 pub at: usize,
446 pub precise: bool,
452}
453
454#[derive(Clone, Debug, PartialEq)]
456pub struct Function {
457 pub value: ValueId,
459 pub blocks: usize,
461 pub instructions: Vec<Instruction>,
463 pub first: ValueId,
466 pub locals: Vec<Value>,
468 pub local_types: Vec<TypeId>,
470}
471
472#[derive(Clone, Debug, Default, PartialEq)]
474pub struct Module {
475 pub types: Vec<Type>,
477 pub values: Vec<Value>,
480 pub value_types: Vec<TypeId>,
482 pub names: Vec<(ValueId, String)>,
484 pub metadata: Vec<Metadata>,
486 pub metadata_at: Vec<usize>,
488 pub named_metadata: Vec<(String, Vec<MetadataId>)>,
490 pub named_metadata_at: Vec<usize>,
492 pub at: usize,
494 pub functions: Vec<Function>,
496 pub precise_kind: Option<u64>,
498}
499
500fn op(r: &Record, i: usize) -> Result<u64> {
501 r.operands
502 .get(i)
503 .copied()
504 .ok_or_else(|| error(r.at, format!("record {} lacks operand {i}", r.code)))
505}
506fn text(ops: &[u64], at: usize) -> Result<Vec<u8>> {
507 ops.iter()
508 .map(|&c| u8::try_from(c).map_err(|_| error(at, "character above 255")))
509 .collect()
510}
511fn utf8(bytes: Vec<u8>, at: usize) -> Result<String> {
512 String::from_utf8(bytes).map_err(|_| error(at, "name is not UTF-8"))
513}
514fn signed_vbr(v: u64) -> i64 {
515 if v & 1 == 0 {
516 i64::try_from(v >> 1).unwrap_or(i64::MAX)
517 } else if v == 1 {
518 i64::MIN
519 } else {
520 i64::try_from(v >> 1).map_or(i64::MIN, i64::wrapping_neg)
521 }
522}
523
524impl Module {
525 fn ty(&self, id: u64, at: usize) -> Result<TypeId> {
526 let id = usize::try_from(id).map_err(|_| error(at, "type id"))?;
527 if id < self.types.len() {
528 Ok(id)
529 } else {
530 Err(error(at, format!("type {id} undefined")))
531 }
532 }
533 fn type_at(&self, id: TypeId, at: usize) -> Result<&Type> {
535 self.types
536 .get(id)
537 .ok_or_else(|| error(at, format!("type {id} of {} types", self.types.len())))
538 }
539 fn intern(&mut self, ty: Type) -> TypeId {
541 match self.types.iter().position(|x| *x == ty) {
542 Some(p) => p,
543 None => {
544 self.types.push(ty);
545 self.types.len().saturating_sub(1)
546 }
547 }
548 }
549 pub fn name(&self, value: ValueId) -> Option<&str> {
551 self.names
552 .iter()
553 .find(|(v, _)| *v == value)
554 .map(|(_, n)| n.as_str())
555 }
556 fn push(&mut self, value: Value, ty: TypeId, at: usize) -> Result<ValueId> {
557 if self.values.len() >= MAX_VALUES {
558 return Err(error(at, "too many values"));
559 }
560 self.values.push(value);
561 self.value_types.push(ty);
562 Ok(self.values.len().saturating_sub(1))
563 }
564
565 fn read_types(&mut self, block: &Block) -> Result<()> {
566 let mut struct_name: Option<String> = None;
567 for r in block.records() {
568 if self.types.len() >= MAX_TYPES {
569 return Err(error(r.at, "too many types"));
570 }
571 let t = match r.code {
572 1 => continue, 2 => Type::Void,
574 3 => Type::Float,
575 4 => Type::Double,
576 5 => Type::Label,
577 6 => Type::Opaque(struct_name.take()),
578 7 => Type::Integer(
579 u32::try_from(op(r, 0)?)
580 .ok()
581 .filter(|w| (1..=64).contains(w))
582 .ok_or_else(|| error(r.at, "integer width"))?,
583 ),
584 8 => Type::Pointer(
585 self.ty(op(r, 0)?, r.at)?,
586 u32::try_from(op(r, 1)?).map_err(|_| error(r.at, "pointer address space"))?,
587 ),
588 10 => Type::Half,
589 11 => Type::Array(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
590 12 => Type::Vector(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
591 16 => Type::Metadata,
592 18 | 20 => Type::Struct {
593 name: if r.code == 20 { struct_name.take() } else { None },
594 elements: r
595 .operands
596 .get(1..)
597 .unwrap_or_default()
598 .iter()
599 .map(|&t| self.ty(t, r.at))
600 .collect::<Result<_>>()?,
601 },
602 19 => {
603 struct_name = Some(utf8(text(&r.operands, r.at)?, r.at)?);
604 continue;
605 }
606 21 => Type::Function {
607 vararg: op(r, 0)? != 0,
608 ret: self.ty(op(r, 1)?, r.at)?,
609 params: r
610 .operands
611 .get(2..)
612 .unwrap_or_default()
613 .iter()
614 .map(|&t| self.ty(t, r.at))
615 .collect::<Result<_>>()?,
616 },
617 other => return Err(error(r.at, format!("type record {other}"))),
618 };
619 self.types.push(t);
620 }
621 Ok(())
622 }
623
624 fn read_constants(&mut self, block: &Block) -> Result<()> {
626 let mut ty: Option<TypeId> = None;
627 for r in block.records() {
628 let id = |v: u64| usize::try_from(v).map_err(|_| error(r.at, "value id"));
629 if r.code == 1 {
630 ty = Some(self.ty(op(r, 0)?, r.at)?);
631 continue;
632 }
633 let t = ty.ok_or_else(|| error(r.at, "constant before SETTYPE"))?;
634 let c = match r.code {
635 2 => Constant::Null,
636 3 => Constant::Undef,
637 4 => Constant::Integer(signed_vbr(op(r, 0)?)),
638 6 => Constant::Float(op(r, 0)?),
639 7 => Constant::Aggregate(
640 r.operands
641 .iter()
642 .map(|&v| usize::try_from(v).map_err(|_| error(r.at, "value id")))
643 .collect::<Result<_>>()?,
644 ),
645 8 | 9 => Constant::String(text(&r.operands, r.at)?),
646 22 => Constant::Data(r.operands.clone()),
647 12 | 20 => {
649 let ops = r
650 .operands
651 .get(usize::from(r.operands.len() % 2 == 1)..)
652 .unwrap_or_default();
653 let (pairs, rest) = ops.as_chunks::<2>();
654 let ([_, base], true) = (
655 pairs.first().unwrap_or(&[0, 0]),
656 rest.is_empty() && !pairs.is_empty(),
657 ) else {
658 return Err(error(r.at, "constant getelementptr operands"));
659 };
660 Constant::Gep {
661 base: id(*base)?,
662 indices: pairs
663 .iter()
664 .skip(1)
665 .map(|[_, index]| id(*index))
666 .collect::<Result<_>>()?,
667 }
668 }
669 10 => Constant::Binary {
671 op: binary(op(r, 0)?, r.at)?,
672 lhs: id(op(r, 1)?)?,
673 rhs: id(op(r, 2)?)?,
674 },
675 11 => Constant::Cast {
677 op: cast(op(r, 0)?, r.at)?,
678 value: id(op(r, 2)?)?,
679 },
680 other => {
681 return Err(error(
682 r.at,
683 format!("constant record {other} (constant expressions are not supported)"),
684 ));
685 }
686 };
687 self.push(Value::Constant(c), t, r.at)?;
688 }
689 Ok(())
690 }
691
692 fn read_metadata(&mut self, block: &Block) -> Result<()> {
693 let mut name: Option<String> = None;
694 let md = |v: u64, at: usize| usize::try_from(v).map_err(|_| error(at, "metadata id"));
695 for r in block.records() {
696 match r.code {
697 1 => {
698 self.metadata.push(Metadata::String(text(&r.operands, r.at)?));
699 self.metadata_at.push(r.at);
700 }
701 2 => {
702 self.metadata.push(Metadata::Value {
703 ty: self.ty(op(r, 0)?, r.at)?,
704 value: md(op(r, 1)?, r.at)?,
705 });
706 self.metadata_at.push(r.at);
707 }
708 3 | 5 => {
709 self.metadata.push(Metadata::Node(
710 r.operands
711 .iter()
712 .map(|&v| {
713 if v == 0 {
714 Ok(None)
715 } else {
716 md(v.saturating_sub(1), r.at).map(Some)
717 }
718 })
719 .collect::<Result<_>>()?,
720 ));
721 self.metadata_at.push(r.at);
722 }
723 4 => name = Some(utf8(text(&r.operands, r.at)?, r.at)?),
724 10 => {
725 let n = name
726 .take()
727 .ok_or_else(|| error(r.at, "named node without a name"))?;
728 let nodes = r.operands.iter().map(|&v| md(v, r.at)).collect::<Result<_>>()?;
729 self.named_metadata.push((n, nodes));
730 self.named_metadata_at.push(r.at);
731 }
732 6 => {
733 if text(r.operands.get(1..).unwrap_or_default(), r.at)? == b"dx.precise" {
735 self.precise_kind = Some(op(r, 0)?);
736 }
737 }
738 other => return Err(error(r.at, format!("metadata record {other}"))),
739 }
740 }
741 Ok(())
742 }
743
744 fn read_symbols(&mut self, block: &Block, base: usize) -> Result<()> {
745 for r in block.records() {
746 match r.code {
747 1 | 3 => {
748 let value = usize::try_from(op(r, 0)?).map_err(|_| error(r.at, "value id"))?;
749 let skip = if r.code == 3 { 2 } else { 1 };
750 let n = utf8(text(r.operands.get(skip..).unwrap_or_default(), r.at)?, r.at)?;
751 let id = base.checked_add(value).ok_or_else(|| error(r.at, "value id"))?;
752 self.names.push((id, n));
753 }
754 2 => {} other => return Err(error(r.at, format!("symbol record {other}"))),
756 }
757 }
758 Ok(())
759 }
760}
761
762struct Body<'m> {
764 m: &'m mut Module,
765 block: usize,
766 blocks: usize,
767}
768impl Body<'_> {
769 fn next(&self) -> usize {
770 self.m.values.len()
771 }
772 fn value_type(&self, r: &Record, i: &mut usize) -> Result<(ValueId, TypeId)> {
775 let id = self.absolute(op(r, *i)?, r.at)?;
776 *i = i.saturating_add(1);
777 if id < self.next() {
778 let t = self
779 .m
780 .value_types
781 .get(id)
782 .copied()
783 .ok_or_else(|| error(r.at, format!("value {id} has no type")))?;
784 Ok((id, t))
785 } else {
786 let t = self.m.ty(op(r, *i)?, r.at)?;
787 *i = i.saturating_add(1);
788 Ok((id, t))
789 }
790 }
791 fn value(&self, r: &Record, i: &mut usize) -> Result<ValueId> {
793 let id = self.absolute(op(r, *i)?, r.at)?;
794 *i = i.saturating_add(1);
795 Ok(id)
796 }
797 fn absolute(&self, relative: u64, at: usize) -> Result<ValueId> {
800 let relative = u32::try_from(relative)
801 .map_err(|_| error(at, format!("relative value id {relative} wider than 32 bits")))?;
802 let next = u32::try_from(self.next()).map_err(|_| error(at, "too many values"))?;
803 Ok(next.wrapping_sub(relative) as usize)
804 }
805 fn pointer_to(&mut self, t: TypeId) -> TypeId {
807 self.m.intern(Type::Pointer(t, 0))
808 }
809 fn constant_index(&self, v: ValueId) -> Option<usize> {
811 match self.m.values.get(v) {
812 Some(Value::Constant(Constant::Integer(i))) => usize::try_from(*i).ok(),
813 Some(Value::Constant(Constant::Null)) => Some(0),
814 _ => None,
815 }
816 }
817 fn result(&mut self, ty: TypeId, at: usize) -> Result<Option<(ValueId, TypeId)>> {
818 if *self.m.type_at(ty, at)? == Type::Void {
819 return Ok(None);
820 }
821 Ok(Some((self.m.push(Value::Local, ty, at)?, ty)))
822 }
823}
824
825fn binary(code: u64, at: usize) -> Result<BinaryOp> {
826 Ok(match code {
827 0 => BinaryOp::Add,
828 1 => BinaryOp::Sub,
829 2 => BinaryOp::Mul,
830 3 => BinaryOp::UDiv,
831 4 => BinaryOp::SDiv,
832 5 => BinaryOp::URem,
833 6 => BinaryOp::SRem,
834 7 => BinaryOp::Shl,
835 8 => BinaryOp::LShr,
836 9 => BinaryOp::AShr,
837 10 => BinaryOp::And,
838 11 => BinaryOp::Or,
839 12 => BinaryOp::Xor,
840 other => return Err(error(at, format!("binary opcode {other}"))),
841 })
842}
843fn cast(code: u64, at: usize) -> Result<CastOp> {
844 Ok(match code {
845 0 => CastOp::Trunc,
846 1 => CastOp::ZExt,
847 2 => CastOp::SExt,
848 3 => CastOp::FpToUi,
849 4 => CastOp::FpToSi,
850 5 => CastOp::UiToFp,
851 6 => CastOp::SiToFp,
852 7 => CastOp::FpTrunc,
853 8 => CastOp::FpExt,
854 9 => CastOp::PtrToInt,
855 10 => CastOp::IntToPtr,
856 11 => CastOp::BitCast,
857 other => return Err(error(at, format!("cast opcode {other}"))),
858 })
859}
860fn refused(code: u64) -> &'static str {
862 match code {
863 4 | 30 => "getelementptr (old form)",
864 13 => "invoke",
865 41 => "load (atomic)",
866 23 => "va_arg",
867 24 | 42 | 45 => "store (atomic)",
868 31 => "indirectbr",
869 37 => "cmpxchg (old form)",
870 59 => "atomicrmw (new form)",
871 39 => "resume",
872 40 | 47 => "landingpad",
873 _ => "unknown instruction record",
874 }
875}
876
877fn mark_precise(kind: Option<u64>, block: &Block, instructions: &mut [Instruction]) -> Result<()> {
880 let Some(kind) = kind else {
881 return Ok(());
882 };
883 for r in block
884 .records()
885 .filter(|r| r.code == 11 && r.operands.len() % 2 == 1)
886 {
887 let at = usize::try_from(op(r, 0)?).map_err(|_| error(r.at, "attachment instruction"))?;
888 if r.operands
889 .get(1..)
890 .unwrap_or_default()
891 .chunks(2)
892 .any(|pair| pair.first() == Some(&kind))
893 {
894 instructions
895 .get_mut(at)
896 .ok_or_else(|| {
897 error(
898 r.at,
899 format!("an attachment names instruction {at} of a shorter body"),
900 )
901 })?
902 .precise = true;
903 }
904 }
905 Ok(())
906}
907
908impl Module {
909 fn read_function(&mut self, block: &Block, value: ValueId) -> Result<Function> {
910 let fty = match self.value_types.get(value).and_then(|&t| self.types.get(t)) {
911 Some(Type::Pointer(t, _)) => *t,
912 _ => return Err(error(block.at, "function value is not a function pointer")),
913 };
914 let params = match self.type_at(fty, block.at)? {
915 Type::Function { params, .. } => params.clone(),
916 _ => return Err(error(block.at, "function type")),
917 };
918 let base = self.values.len();
919 for p in params {
920 self.push(Value::Local, p, block.at)?;
921 }
922 let mut body = Body {
923 m: self,
924 block: 0,
925 blocks: 0,
926 };
927 let mut instructions = Vec::new();
928 for e in &block.elements {
929 let r = match e {
930 crate::bitstream::Element::Block(b) => {
931 match b.id {
932 CONSTANTS => body.m.read_constants(b)?,
933 VALUE_SYMTAB => body.m.read_symbols(b, 0)?,
934 METADATA_ATTACHMENT => mark_precise(body.m.precise_kind, b, &mut instructions)?,
935 METADATA | USELIST => {}
936 other => return Err(error(b.at, format!("block {other} in a function"))),
937 }
938 continue;
939 }
940 crate::bitstream::Element::Record(r) => r,
941 };
942 let mut i = 0;
943 let (op, ty): (Op, Option<TypeId>) = match r.code {
944 1 => {
945 body.blocks = usize::try_from(op(r, 0)?)
946 .ok()
947 .filter(|&n| n > 0 && n <= 1 << 16)
948 .ok_or_else(|| error(r.at, "basic block count"))?;
949 continue;
950 }
951 33 | 35 => continue, 2 => {
953 let (lhs, t) = body.value_type(r, &mut i)?;
954 let rhs = body.value(r, &mut i)?;
955 let o = binary(op(r, i)?, r.at)?;
956 (Op::Binary { op: o, lhs, rhs }, Some(t))
957 }
958 3 => {
959 let value = body.value(r, &mut i)?;
960 let to = body.m.ty(op(r, i)?, r.at)?;
961 let o = cast(op(r, i.saturating_add(1))?, r.at)?;
962 (Op::Cast { op: o, value }, Some(to))
963 }
964 9 | 28 => {
965 let (lhs, t) = body.value_type(r, &mut i)?;
966 let rhs = body.value(r, &mut i)?;
967 let predicate = op(r, i)?;
968 let bool_ty = match body.m.type_at(t, r.at)? {
969 Type::Vector(..) => {
970 return Err(error(r.at, "vector comparison"));
971 }
972 _ => body
973 .m
974 .types
975 .iter()
976 .position(|x| *x == Type::Integer(1))
977 .ok_or_else(|| error(r.at, "no i1 type for a comparison"))?,
978 };
979 (Op::Compare { predicate, lhs, rhs }, Some(bool_ty))
980 }
981 29 => {
982 let (then, t) = body.value_type(r, &mut i)?;
983 let otherwise = body.value(r, &mut i)?;
984 let condition = body.value(r, &mut i)?;
985 (
986 Op::Select {
987 condition,
988 then,
989 otherwise,
990 },
991 Some(t),
992 )
993 }
994 26 => {
995 let (aggregate, mut t) = body.value_type(r, &mut i)?;
996 let indices = r.operands.get(i..).unwrap_or_default().to_vec();
997 for &k in &indices {
998 t = match body.m.type_at(t, r.at)? {
999 Type::Struct { elements, .. } => *usize::try_from(k)
1000 .ok()
1001 .and_then(|k| elements.get(k))
1002 .ok_or_else(|| error(r.at, "extractvalue index"))?,
1003 Type::Array(n, e) if k < *n => *e,
1004 _ => return Err(error(r.at, "extractvalue index")),
1005 };
1006 }
1007 (Op::ExtractValue { aggregate, indices }, Some(t))
1008 }
1009 6 => {
1010 let (vector, t) = body.value_type(r, &mut i)?;
1011 let (index, _) = body.value_type(r, &mut i)?;
1012 let Type::Vector(_, element) = *body.m.type_at(t, r.at)? else {
1013 return Err(error(r.at, "extractelement of something that is not a vector"));
1014 };
1015 (Op::ExtractElement { vector, index }, Some(element))
1016 }
1017 7 => {
1018 let (vector, t) = body.value_type(r, &mut i)?;
1019 let value = body.value(r, &mut i)?;
1020 let (index, _) = body.value_type(r, &mut i)?;
1021 (Op::InsertElement { vector, value, index }, Some(t))
1022 }
1023 8 => {
1024 let (first, t) = body.value_type(r, &mut i)?;
1025 let second = body.value(r, &mut i)?;
1026 let (mask, mask_ty) = body.value_type(r, &mut i)?;
1027 let (Type::Vector(_, element), Type::Vector(lanes, _)) = (
1028 body.m.type_at(t, r.at)?.clone(),
1029 body.m.type_at(mask_ty, r.at)?.clone(),
1030 ) else {
1031 return Err(error(r.at, "shufflevector of something that is not a vector"));
1032 };
1033 let result = body
1034 .m
1035 .types
1036 .iter()
1037 .position(|x| *x == Type::Vector(lanes, element))
1038 .ok_or_else(|| error(r.at, "no type for the shuffled vector"))?;
1039 (Op::ShuffleVector { first, second, mask }, Some(result))
1040 }
1041 27 => {
1042 let (aggregate, t) = body.value_type(r, &mut i)?;
1043 let value = body.value(r, &mut i)?;
1044 let indices = r.operands.get(i..).unwrap_or_default().to_vec();
1045 (
1046 Op::InsertValue {
1047 aggregate,
1048 value,
1049 indices,
1050 },
1051 Some(t),
1052 )
1053 }
1054 34 => {
1055 i = 1; let cc = op(r, i)?;
1057 i = i.saturating_add(1);
1058 if cc & (1 << 17) != 0 {
1059 i = i.saturating_add(1); }
1061 let explicit = if cc & (1 << 15) != 0 {
1062 let t = body.m.ty(op(r, i)?, r.at)?;
1063 i = i.saturating_add(1);
1064 Some(t)
1065 } else {
1066 None
1067 };
1068 let (function, callee_ty) = body.value_type(r, &mut i)?;
1069 let fty = match (explicit, body.m.type_at(callee_ty, r.at)?) {
1070 (Some(t), _) => t,
1071 (None, Type::Pointer(t, _)) => *t,
1072 _ => return Err(error(r.at, "callee is not a function pointer")),
1073 };
1074 let (ret, params, vararg) = match body.m.type_at(fty, r.at)? {
1075 Type::Function { ret, params, vararg } => (*ret, params.clone(), *vararg),
1076 _ => return Err(error(r.at, "call through a non-function type")),
1077 };
1078 if vararg {
1079 return Err(error(r.at, "vararg call"));
1080 }
1081 let mut args = Vec::with_capacity(params.len());
1082 for p in ¶ms {
1083 let a = body.value(r, &mut i)?;
1085 if a < body.next() && body.m.value_types.get(a) != Some(p) {
1086 return Err(error(r.at, "call argument type"));
1087 }
1088 args.push(a);
1089 }
1090 if i != r.operands.len() {
1091 return Err(error(r.at, "call operands left over"));
1092 }
1093 (Op::Call { function, args }, Some(ret))
1094 }
1095 16 => {
1096 let t = body.m.ty(op(r, 0)?, r.at)?;
1097 let pairs = r.operands.get(1..).unwrap_or_default();
1098 if pairs.is_empty() || pairs.len() % 2 != 0 {
1099 return Err(error(r.at, "phi operands"));
1100 }
1101 let next = i64::try_from(body.next()).map_err(|_| error(r.at, "too many values"))?;
1102 let mut incoming = Vec::with_capacity(pairs.len() / 2);
1103 for pair in pairs.as_chunks::<2>().0 {
1104 let id = next
1106 .checked_sub(signed_vbr(pair[0]))
1107 .and_then(|v| usize::try_from(v).ok())
1108 .ok_or_else(|| error(r.at, "phi value"))?;
1109 let block = usize::try_from(pair[1])
1110 .ok()
1111 .filter(|&b| b < body.blocks)
1112 .ok_or_else(|| error(r.at, "phi block"))?;
1113 incoming.push((id, block));
1114 }
1115 (Op::Phi { incoming }, Some(t))
1116 }
1117 10 => {
1118 if r.operands.is_empty() {
1119 (Op::Return(None), None)
1120 } else {
1121 (Op::Return(Some(body.value(r, &mut i)?)), None)
1122 }
1123 }
1124 11 => {
1125 let target = |v: u64| -> Result<usize> {
1126 usize::try_from(v)
1127 .ok()
1128 .filter(|&b| b < body.blocks)
1129 .ok_or_else(|| error(r.at, "branch target"))
1130 };
1131 if r.operands.len() == 1 {
1132 (
1133 Op::Branch {
1134 target: target(op(r, 0)?)?,
1135 },
1136 None,
1137 )
1138 } else {
1139 let then = target(op(r, 0)?)?;
1140 let otherwise = target(op(r, 1)?)?;
1141 i = 2;
1142 let condition = body.value(r, &mut i)?;
1143 (
1144 Op::CondBranch {
1145 condition,
1146 then,
1147 otherwise,
1148 },
1149 None,
1150 )
1151 }
1152 }
1153 12 => {
1154 let block = |v: u64| -> Result<usize> {
1156 usize::try_from(v)
1157 .ok()
1158 .filter(|&b| b < body.blocks)
1159 .ok_or_else(|| error(r.at, "switch target"))
1160 };
1161 i = 1;
1162 let value = body.value(r, &mut i)?;
1163 let default = block(op(r, i)?)?;
1164 let pairs = r.operands.get(i.saturating_add(1)..).unwrap_or_default();
1165 if pairs.len() % 2 != 0 {
1166 return Err(error(r.at, "switch cases"));
1167 }
1168 let cases = pairs
1169 .as_chunks::<2>()
1170 .0
1171 .iter()
1172 .map(|p| {
1173 Ok((
1174 usize::try_from(p[0]).map_err(|_| error(r.at, "case value"))?,
1175 block(p[1])?,
1176 ))
1177 })
1178 .collect::<Result<Vec<_>>>()?;
1179 (
1180 Op::Switch {
1181 value,
1182 default,
1183 cases,
1184 },
1185 None,
1186 )
1187 }
1188 15 => (Op::Unreachable, None),
1189 19 => {
1190 let ty = body.m.ty(op(r, 0)?, r.at)?;
1192 (Op::Alloca { ty }, Some(body.pointer_to(ty)))
1193 }
1194 20 => {
1195 let (pointer, pt) = body.value_type(r, &mut i)?;
1196 let _ = pt;
1197 let ty = body.m.ty(op(r, i)?, r.at)?;
1198 (Op::Load { pointer }, Some(ty))
1199 }
1200 44 => {
1201 let (pointer, _) = body.value_type(r, &mut i)?;
1202 let (value, _) = body.value_type(r, &mut i)?;
1203 (Op::Store { pointer, value }, None)
1204 }
1205 38 => {
1207 let (pointer, _) = body.value_type(r, &mut i)?;
1208 let value = body.value(r, &mut i)?;
1209 let op = op(r, i)?;
1210 let ty = body.m.value_types.get(value).copied();
1211 let ty = match ty {
1212 Some(t) if value < body.next() => t,
1213 _ => return Err(error(r.at, "an atomicrmw of a value defined later")),
1214 };
1215 (Op::AtomicRmw { pointer, value, op }, Some(ty))
1216 }
1217 46 => {
1220 let (pointer, _) = body.value_type(r, &mut i)?;
1221 let (compare, ty) = body.value_type(r, &mut i)?;
1222 let value = body.value(r, &mut i)?;
1223 let flag = body
1224 .m
1225 .types
1226 .iter()
1227 .position(|t| *t == Type::Integer(1))
1228 .ok_or_else(|| error(r.at, "a cmpxchg without a boolean type"))?;
1229 let pair = Type::Struct {
1230 name: None,
1231 elements: vec![ty, flag],
1232 };
1233 let result = body.m.intern(pair);
1234 (
1235 Op::CmpXchg {
1236 pointer,
1237 compare,
1238 value,
1239 },
1240 Some(result),
1241 )
1242 }
1243 36 => (Op::Fence, None),
1244 43 => {
1245 i = 2;
1247 let source = body.m.ty(op(r, 1)?, r.at)?;
1248 let (base, _) = body.value_type(r, &mut i)?;
1249 let mut indices = Vec::new();
1250 while i < r.operands.len() {
1251 indices.push(body.value_type(r, &mut i)?.0);
1252 }
1253 let mut t = source;
1256 for &index in indices.iter().skip(1) {
1257 t = match body.m.type_at(t, r.at)?.clone() {
1258 Type::Array(_, e) | Type::Vector(_, e) => e,
1259 Type::Struct { elements, .. } => {
1260 let k = match body.constant_index(index) {
1261 Some(k) => k,
1262 None => {
1263 return Err(error(r.at, "a structure index that is not constant"));
1264 }
1265 };
1266 *elements
1267 .get(k)
1268 .ok_or_else(|| error(r.at, "getelementptr structure index"))?
1269 }
1270 _ => return Err(error(r.at, "getelementptr into a scalar")),
1271 };
1272 }
1273 (Op::Gep { base, indices }, Some(body.pointer_to(t)))
1274 }
1275 other => {
1276 return Err(error(
1277 r.at,
1278 format!("instruction {} (record {other}) is not supported", refused(other)),
1279 ));
1280 }
1281 };
1282 let result = match ty {
1283 Some(t) => body.result(t, r.at)?,
1284 None => None,
1285 };
1286 let terminator = matches!(
1287 op,
1288 Op::Return(_)
1289 | Op::Branch { .. }
1290 | Op::CondBranch { .. }
1291 | Op::Switch { .. }
1292 | Op::Unreachable
1293 );
1294 instructions.push(Instruction {
1295 op,
1296 result,
1297 block: body.block,
1298 at: r.at,
1299 precise: false,
1300 });
1301 if terminator {
1302 body.block = body.block.saturating_add(1);
1303 }
1304 }
1305 if body.block != body.blocks {
1306 return Err(error(block.at, "basic blocks without terminators"));
1307 }
1308 let end = body.next();
1309 let blocks = body.blocks;
1310 for inst in &instructions {
1313 if inst.block >= blocks {
1314 return Err(error(inst.at, "an instruction after the last terminator"));
1315 }
1316 if let Some(v) = inst.op.operands().into_iter().find(|v| *v >= end) {
1317 return Err(error(inst.at, format!("value {v} of {end} values")));
1318 }
1319 if let Some(b) = inst.op.blocks().into_iter().find(|b| *b >= blocks) {
1320 return Err(error(inst.at, format!("basic block {b} of {blocks}")));
1321 }
1322 if let Op::Call { function, args } = &inst.op {
1323 if *function >= end {
1324 return Err(error(inst.at, format!("callee {function} of {end} values")));
1325 }
1326 if let Some(Value::Function { ty, .. }) = self.values.get(*function)
1327 && let Some(Type::Function {
1328 vararg: false,
1329 params,
1330 ..
1331 }) = self.types.get(*ty)
1332 && params.len() != args.len()
1333 {
1334 return Err(error(
1335 inst.at,
1336 format!(
1337 "a call of {} arguments to a function of {} parameters",
1338 args.len(),
1339 params.len()
1340 ),
1341 ));
1342 }
1343 }
1344 }
1345 let locals = self.values.split_off(base);
1346 let local_types = self.value_types.split_off(base);
1347 Ok(Function {
1348 value,
1349 blocks,
1350 instructions,
1351 first: base,
1352 locals,
1353 local_types,
1354 })
1355 }
1356
1357 pub fn read(top: &[Block]) -> Result<Self> {
1359 let module = match top {
1360 [m] if m.id == MODULE => m,
1361 _ => return Err(error(0, "bitcode is not one module block")),
1362 };
1363 let mut m = Module {
1364 at: module.at,
1365 ..Module::default()
1366 };
1367 let mut bodies: Vec<ValueId> = Vec::new();
1368 let mut version = None;
1369 for e in &module.elements {
1370 match e {
1371 crate::bitstream::Element::Record(r) => match r.code {
1372 1 => version = Some(op(r, 0)?),
1373 2..=6 | 11 | 13 | 16 => {} 7 => {
1375 let t = m.ty(op(r, 0)?, r.at)?;
1378 let flags = op(r, 1)?;
1379 let address_space =
1380 u32::try_from(flags >> 2).map_err(|_| error(r.at, "address space"))?;
1381 let (ty, value_ty) = if flags & 2 != 0 {
1382 let pointer = m.intern(Type::Pointer(t, address_space));
1383 (pointer, t)
1384 } else {
1385 match m.type_at(t, r.at)? {
1386 Type::Pointer(inner, _) => (t, *inner),
1387 _ => return Err(error(r.at, "a global whose type is not a pointer")),
1388 }
1389 };
1390 let init = match op(r, 2)? {
1391 0 => None,
1392 n => Some(
1393 usize::try_from(n.saturating_sub(1))
1394 .map_err(|_| error(r.at, "initial value id"))?,
1395 ),
1396 };
1397 m.push(
1398 Value::Global {
1399 ty,
1400 value_ty,
1401 init,
1402 constant: flags & 1 != 0,
1403 address_space,
1404 },
1405 ty,
1406 r.at,
1407 )?;
1408 }
1409 8 => {
1410 let t = m.ty(op(r, 0)?, r.at)?;
1412 let pointer = m.intern(Type::Pointer(t, 0));
1413 let declaration = op(r, 2)? != 0;
1414 let v = m.push(Value::Function { ty: t, declaration }, pointer, r.at)?;
1415 if !declaration {
1416 bodies.push(v);
1417 }
1418 }
1419 other => return Err(error(r.at, format!("module record {other}"))),
1420 },
1421 crate::bitstream::Element::Block(b) => match b.id {
1422 BLOCKINFO | PARAMATTR | PARAMATTR_GROUP | USELIST => {}
1423 TYPES => m.read_types(b)?,
1424 CONSTANTS => m.read_constants(b)?,
1425 METADATA => m.read_metadata(b)?,
1426 VALUE_SYMTAB => m.read_symbols(b, 0)?,
1427 FUNCTION => {
1428 if version != Some(1) {
1429 return Err(error(b.at, "only relative value ids (module version 1)"));
1430 }
1431 if bodies.is_empty() {
1433 return Err(error(b.at, "function body without a definition"));
1434 }
1435 let value = bodies.remove(0);
1436 let f = m.read_function(b, value)?;
1438 m.functions.push(f);
1439 }
1440 other => return Err(error(b.at, format!("module block {other}"))),
1441 },
1442 }
1443 }
1444 if !bodies.is_empty() {
1445 return Err(error(module.at, "a defined function has no body"));
1446 }
1447 Ok(m)
1448 }
1449}