1use crate::bitstream::{Block, Record};
6use crate::{Result, error};
7
8const MODULE: u64 = 8;
9const PARAMATTR: u64 = 9;
10const PARAMATTR_GROUP: u64 = 10;
11const CONSTANTS: u64 = 11;
12const FUNCTION: u64 = 12;
13const VALUE_SYMTAB: u64 = 14;
14const METADATA: u64 = 15;
15const METADATA_ATTACHMENT: u64 = 16;
16const TYPES: u64 = 17;
17const USELIST: u64 = 18;
18const BLOCKINFO: u64 = 0;
19
20const MAX_VALUES: usize = 1 << 22;
22const MAX_TYPES: usize = 1 << 16;
23
24pub type TypeId = usize;
26pub type ValueId = usize;
28pub type MetadataId = usize;
30
31#[derive(Clone, Debug, PartialEq, Eq)]
33pub enum Type {
34 Void,
36 Label,
38 Metadata,
40 Half,
42 Float,
44 Double,
46 Integer(u32),
48 Pointer(TypeId, u32),
51 Array(u64, TypeId),
53 Vector(u64, TypeId),
55 Struct {
57 name: Option<String>,
59 elements: Vec<TypeId>,
61 },
62 Opaque(Option<String>),
64 Function {
66 vararg: bool,
68 ret: TypeId,
70 params: Vec<TypeId>,
72 },
73}
74
75#[derive(Clone, Debug, PartialEq)]
77pub enum Constant {
78 Null,
80 Undef,
82 Integer(i64),
84 Float(u64),
86 Aggregate(Vec<ValueId>),
88 Data(Vec<u64>),
90 String(Vec<u8>),
92 Gep {
94 base: ValueId,
96 indices: Vec<ValueId>,
98 },
99 Cast {
101 op: CastOp,
103 value: ValueId,
105 },
106 Binary {
108 op: BinaryOp,
110 lhs: ValueId,
112 rhs: ValueId,
114 },
115}
116
117#[derive(Clone, Debug, PartialEq)]
119pub enum Value {
120 Function {
122 ty: TypeId,
124 declaration: bool,
126 },
127 Global {
129 ty: TypeId,
131 value_ty: TypeId,
133 init: Option<ValueId>,
135 constant: bool,
137 address_space: u32,
139 },
140 Constant(Constant),
142 Local,
144}
145
146#[derive(Clone, Debug, PartialEq)]
148pub enum Metadata {
149 String(Vec<u8>),
151 Value {
153 ty: TypeId,
155 value: ValueId,
157 },
158 Node(Vec<Option<MetadataId>>),
160}
161
162#[derive(Clone, Copy, Debug, PartialEq, Eq)]
164pub enum BinaryOp {
165 Add,
167 Sub,
169 Mul,
171 UDiv,
173 SDiv,
175 URem,
177 SRem,
179 Shl,
181 LShr,
183 AShr,
185 And,
187 Or,
189 Xor,
191}
192#[derive(Clone, Copy, Debug, PartialEq, Eq)]
194pub enum CastOp {
195 Trunc,
197 ZExt,
199 SExt,
201 FpToUi,
203 FpToSi,
205 UiToFp,
207 SiToFp,
209 FpTrunc,
211 FpExt,
213 PtrToInt,
215 IntToPtr,
217 BitCast,
219}
220
221#[derive(Clone, Debug, PartialEq)]
223pub enum Op {
224 Binary {
226 op: BinaryOp,
228 lhs: ValueId,
230 rhs: ValueId,
232 },
233 Cast {
235 op: CastOp,
237 value: ValueId,
239 },
240 Compare {
242 predicate: u64,
244 lhs: ValueId,
246 rhs: ValueId,
248 },
249 Select {
251 condition: ValueId,
253 then: ValueId,
255 otherwise: ValueId,
257 },
258 ExtractValue {
260 aggregate: ValueId,
262 indices: Vec<u64>,
264 },
265 InsertValue {
267 aggregate: ValueId,
269 value: ValueId,
271 indices: Vec<u64>,
273 },
274 ExtractElement {
276 vector: ValueId,
278 index: ValueId,
280 },
281 InsertElement {
283 vector: ValueId,
285 value: ValueId,
287 index: ValueId,
289 },
290 ShuffleVector {
292 first: ValueId,
294 second: ValueId,
296 mask: ValueId,
298 },
299 Call {
301 function: ValueId,
303 args: Vec<ValueId>,
305 },
306 Phi {
308 incoming: Vec<(ValueId, usize)>,
310 },
311 Return(Option<ValueId>),
313 Branch {
315 target: usize,
317 },
318 CondBranch {
320 condition: ValueId,
322 then: usize,
324 otherwise: usize,
326 },
327 Switch {
329 value: ValueId,
331 default: usize,
333 cases: Vec<(ValueId, usize)>,
335 },
336 Unreachable,
338 Alloca {
340 ty: TypeId,
342 },
343 Load {
345 pointer: ValueId,
347 },
348 Store {
350 pointer: ValueId,
352 value: ValueId,
354 },
355 Gep {
357 base: ValueId,
359 indices: Vec<ValueId>,
361 },
362 AtomicRmw {
365 pointer: ValueId,
367 value: ValueId,
369 op: u64,
371 },
372 CmpXchg {
374 pointer: ValueId,
376 compare: ValueId,
378 value: ValueId,
380 },
381 Fence,
383}
384
385impl Op {
386 pub fn operands(&self) -> Vec<ValueId> {
388 match self {
389 Op::Binary { lhs, rhs, .. } | Op::Compare { lhs, rhs, .. } => vec![*lhs, *rhs],
390 Op::Cast { value, .. } => vec![*value],
391 Op::Select {
392 condition,
393 then,
394 otherwise,
395 } => vec![*condition, *then, *otherwise],
396 Op::ExtractValue { aggregate, .. } => vec![*aggregate],
397 Op::InsertValue { aggregate, value, .. } => vec![*aggregate, *value],
398 Op::ExtractElement { vector, index } => vec![*vector, *index],
399 Op::InsertElement { vector, value, index } => vec![*vector, *value, *index],
400 Op::ShuffleVector { first, second, mask } => vec![*first, *second, *mask],
401 Op::Call { args, .. } => args.clone(),
402 Op::Phi { incoming } => incoming.iter().map(|(v, _)| *v).collect(),
403 Op::Return(value) => value.iter().copied().collect(),
404 Op::CondBranch { condition, .. } => vec![*condition],
405 Op::Switch { value, cases, .. } => std::iter::once(*value)
406 .chain(cases.iter().map(|(c, _)| *c))
407 .collect(),
408 Op::Load { pointer } => vec![*pointer],
409 Op::Store { pointer, value } | Op::AtomicRmw { pointer, value, .. } => vec![*pointer, *value],
410 Op::Gep { base, indices } => std::iter::once(*base).chain(indices.iter().copied()).collect(),
411 Op::CmpXchg {
412 pointer,
413 compare,
414 value,
415 } => vec![*pointer, *compare, *value],
416 Op::Branch { .. } | Op::Unreachable | Op::Alloca { .. } | Op::Fence => Vec::new(),
417 }
418 }
419
420 pub fn blocks(&self) -> Vec<usize> {
422 match self {
423 Op::Branch { target } => vec![*target],
424 Op::CondBranch { then, otherwise, .. } => vec![*then, *otherwise],
425 Op::Switch { default, cases, .. } => std::iter::once(*default)
426 .chain(cases.iter().map(|(_, b)| *b))
427 .collect(),
428 Op::Phi { incoming } => incoming.iter().map(|(_, b)| *b).collect(),
429 _ => Vec::new(),
430 }
431 }
432}
433
434#[derive(Clone, Debug, PartialEq)]
436pub struct Instruction {
437 pub op: Op,
439 pub result: Option<(ValueId, TypeId)>,
441 pub block: usize,
443 pub at: usize,
445}
446
447#[derive(Clone, Debug, PartialEq)]
449pub struct Function {
450 pub value: ValueId,
452 pub blocks: usize,
454 pub instructions: Vec<Instruction>,
456 pub first: ValueId,
459 pub locals: Vec<Value>,
461 pub local_types: Vec<TypeId>,
463}
464
465#[derive(Clone, Debug, Default, PartialEq)]
467pub struct Module {
468 pub types: Vec<Type>,
470 pub values: Vec<Value>,
473 pub value_types: Vec<TypeId>,
475 pub names: Vec<(ValueId, String)>,
477 pub metadata: Vec<Metadata>,
479 pub metadata_at: Vec<usize>,
481 pub named_metadata: Vec<(String, Vec<MetadataId>)>,
483 pub named_metadata_at: Vec<usize>,
485 pub at: usize,
487 pub functions: Vec<Function>,
489}
490
491fn op(r: &Record, i: usize) -> Result<u64> {
492 r.operands
493 .get(i)
494 .copied()
495 .ok_or_else(|| error(r.at, format!("record {} lacks operand {i}", r.code)))
496}
497fn text(ops: &[u64], at: usize) -> Result<Vec<u8>> {
498 ops.iter()
499 .map(|&c| u8::try_from(c).map_err(|_| error(at, "character above 255")))
500 .collect()
501}
502fn utf8(bytes: Vec<u8>, at: usize) -> Result<String> {
503 String::from_utf8(bytes).map_err(|_| error(at, "name is not UTF-8"))
504}
505fn signed_vbr(v: u64) -> i64 {
506 if v & 1 == 0 {
507 i64::try_from(v >> 1).unwrap_or(i64::MAX)
508 } else if v == 1 {
509 i64::MIN
510 } else {
511 i64::try_from(v >> 1).map_or(i64::MIN, i64::wrapping_neg)
512 }
513}
514
515impl Module {
516 fn ty(&self, id: u64, at: usize) -> Result<TypeId> {
517 let id = usize::try_from(id).map_err(|_| error(at, "type id"))?;
518 if id < self.types.len() {
519 Ok(id)
520 } else {
521 Err(error(at, format!("type {id} undefined")))
522 }
523 }
524 fn type_at(&self, id: TypeId, at: usize) -> Result<&Type> {
526 self.types
527 .get(id)
528 .ok_or_else(|| error(at, format!("type {id} of {} types", self.types.len())))
529 }
530 fn intern(&mut self, ty: Type) -> TypeId {
532 match self.types.iter().position(|x| *x == ty) {
533 Some(p) => p,
534 None => {
535 self.types.push(ty);
536 self.types.len().saturating_sub(1)
537 }
538 }
539 }
540 pub fn name(&self, value: ValueId) -> Option<&str> {
542 self.names
543 .iter()
544 .find(|(v, _)| *v == value)
545 .map(|(_, n)| n.as_str())
546 }
547 fn push(&mut self, value: Value, ty: TypeId, at: usize) -> Result<ValueId> {
548 if self.values.len() >= MAX_VALUES {
549 return Err(error(at, "too many values"));
550 }
551 self.values.push(value);
552 self.value_types.push(ty);
553 Ok(self.values.len().saturating_sub(1))
554 }
555
556 fn read_types(&mut self, block: &Block) -> Result<()> {
557 let mut struct_name: Option<String> = None;
558 for r in block.records() {
559 if self.types.len() >= MAX_TYPES {
560 return Err(error(r.at, "too many types"));
561 }
562 let t = match r.code {
563 1 => continue, 2 => Type::Void,
565 3 => Type::Float,
566 4 => Type::Double,
567 5 => Type::Label,
568 6 => Type::Opaque(struct_name.take()),
569 7 => Type::Integer(
570 u32::try_from(op(r, 0)?)
571 .ok()
572 .filter(|w| (1..=64).contains(w))
573 .ok_or_else(|| error(r.at, "integer width"))?,
574 ),
575 8 => Type::Pointer(
576 self.ty(op(r, 0)?, r.at)?,
577 u32::try_from(op(r, 1)?).map_err(|_| error(r.at, "pointer address space"))?,
578 ),
579 10 => Type::Half,
580 11 => Type::Array(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
581 12 => Type::Vector(op(r, 0)?, self.ty(op(r, 1)?, r.at)?),
582 16 => Type::Metadata,
583 18 | 20 => Type::Struct {
584 name: if r.code == 20 { struct_name.take() } else { None },
585 elements: r
586 .operands
587 .get(1..)
588 .unwrap_or_default()
589 .iter()
590 .map(|&t| self.ty(t, r.at))
591 .collect::<Result<_>>()?,
592 },
593 19 => {
594 struct_name = Some(utf8(text(&r.operands, r.at)?, r.at)?);
595 continue;
596 }
597 21 => Type::Function {
598 vararg: op(r, 0)? != 0,
599 ret: self.ty(op(r, 1)?, r.at)?,
600 params: r
601 .operands
602 .get(2..)
603 .unwrap_or_default()
604 .iter()
605 .map(|&t| self.ty(t, r.at))
606 .collect::<Result<_>>()?,
607 },
608 other => return Err(error(r.at, format!("type record {other}"))),
609 };
610 self.types.push(t);
611 }
612 Ok(())
613 }
614
615 fn read_constants(&mut self, block: &Block) -> Result<()> {
617 let mut ty: Option<TypeId> = None;
618 for r in block.records() {
619 let id = |v: u64| usize::try_from(v).map_err(|_| error(r.at, "value id"));
620 if r.code == 1 {
621 ty = Some(self.ty(op(r, 0)?, r.at)?);
622 continue;
623 }
624 let t = ty.ok_or_else(|| error(r.at, "constant before SETTYPE"))?;
625 let c = match r.code {
626 2 => Constant::Null,
627 3 => Constant::Undef,
628 4 => Constant::Integer(signed_vbr(op(r, 0)?)),
629 6 => Constant::Float(op(r, 0)?),
630 7 => Constant::Aggregate(
631 r.operands
632 .iter()
633 .map(|&v| usize::try_from(v).map_err(|_| error(r.at, "value id")))
634 .collect::<Result<_>>()?,
635 ),
636 8 | 9 => Constant::String(text(&r.operands, r.at)?),
637 22 => Constant::Data(r.operands.clone()),
638 12 | 20 => {
640 let ops = r
641 .operands
642 .get(usize::from(r.operands.len() % 2 == 1)..)
643 .unwrap_or_default();
644 let (pairs, rest) = ops.as_chunks::<2>();
645 let ([_, base], true) = (
646 pairs.first().unwrap_or(&[0, 0]),
647 rest.is_empty() && !pairs.is_empty(),
648 ) else {
649 return Err(error(r.at, "constant getelementptr operands"));
650 };
651 Constant::Gep {
652 base: id(*base)?,
653 indices: pairs
654 .iter()
655 .skip(1)
656 .map(|[_, index]| id(*index))
657 .collect::<Result<_>>()?,
658 }
659 }
660 10 => Constant::Binary {
662 op: binary(op(r, 0)?, r.at)?,
663 lhs: id(op(r, 1)?)?,
664 rhs: id(op(r, 2)?)?,
665 },
666 11 => Constant::Cast {
668 op: cast(op(r, 0)?, r.at)?,
669 value: id(op(r, 2)?)?,
670 },
671 other => {
672 return Err(error(
673 r.at,
674 format!("constant record {other} (constant expressions are not supported)"),
675 ));
676 }
677 };
678 self.push(Value::Constant(c), t, r.at)?;
679 }
680 Ok(())
681 }
682
683 fn read_metadata(&mut self, block: &Block) -> Result<()> {
684 let mut name: Option<String> = None;
685 let md = |v: u64, at: usize| usize::try_from(v).map_err(|_| error(at, "metadata id"));
686 for r in block.records() {
687 match r.code {
688 1 => {
689 self.metadata.push(Metadata::String(text(&r.operands, r.at)?));
690 self.metadata_at.push(r.at);
691 }
692 2 => {
693 self.metadata.push(Metadata::Value {
694 ty: self.ty(op(r, 0)?, r.at)?,
695 value: md(op(r, 1)?, r.at)?,
696 });
697 self.metadata_at.push(r.at);
698 }
699 3 | 5 => {
700 self.metadata.push(Metadata::Node(
701 r.operands
702 .iter()
703 .map(|&v| {
704 if v == 0 {
705 Ok(None)
706 } else {
707 md(v.saturating_sub(1), r.at).map(Some)
708 }
709 })
710 .collect::<Result<_>>()?,
711 ));
712 self.metadata_at.push(r.at);
713 }
714 4 => name = Some(utf8(text(&r.operands, r.at)?, r.at)?),
715 10 => {
716 let n = name
717 .take()
718 .ok_or_else(|| error(r.at, "named node without a name"))?;
719 let nodes = r.operands.iter().map(|&v| md(v, r.at)).collect::<Result<_>>()?;
720 self.named_metadata.push((n, nodes));
721 self.named_metadata_at.push(r.at);
722 }
723 6 => {} other => return Err(error(r.at, format!("metadata record {other}"))),
725 }
726 }
727 Ok(())
728 }
729
730 fn read_symbols(&mut self, block: &Block, base: usize) -> Result<()> {
731 for r in block.records() {
732 match r.code {
733 1 | 3 => {
734 let value = usize::try_from(op(r, 0)?).map_err(|_| error(r.at, "value id"))?;
735 let skip = if r.code == 3 { 2 } else { 1 };
736 let n = utf8(text(r.operands.get(skip..).unwrap_or_default(), r.at)?, r.at)?;
737 let id = base.checked_add(value).ok_or_else(|| error(r.at, "value id"))?;
738 self.names.push((id, n));
739 }
740 2 => {} other => return Err(error(r.at, format!("symbol record {other}"))),
742 }
743 }
744 Ok(())
745 }
746}
747
748struct Body<'m> {
750 m: &'m mut Module,
751 block: usize,
752 blocks: usize,
753}
754impl Body<'_> {
755 fn next(&self) -> usize {
756 self.m.values.len()
757 }
758 fn value_type(&self, r: &Record, i: &mut usize) -> Result<(ValueId, TypeId)> {
761 let id = self.absolute(op(r, *i)?, r.at)?;
762 *i = i.saturating_add(1);
763 if id < self.next() {
764 let t = self
765 .m
766 .value_types
767 .get(id)
768 .copied()
769 .ok_or_else(|| error(r.at, format!("value {id} has no type")))?;
770 Ok((id, t))
771 } else {
772 let t = self.m.ty(op(r, *i)?, r.at)?;
773 *i = i.saturating_add(1);
774 Ok((id, t))
775 }
776 }
777 fn value(&self, r: &Record, i: &mut usize) -> Result<ValueId> {
779 let id = self.absolute(op(r, *i)?, r.at)?;
780 *i = i.saturating_add(1);
781 Ok(id)
782 }
783 fn absolute(&self, relative: u64, at: usize) -> Result<ValueId> {
786 let relative = u32::try_from(relative)
787 .map_err(|_| error(at, format!("relative value id {relative} wider than 32 bits")))?;
788 let next = u32::try_from(self.next()).map_err(|_| error(at, "too many values"))?;
789 Ok(next.wrapping_sub(relative) as usize)
790 }
791 fn pointer_to(&mut self, t: TypeId) -> TypeId {
793 self.m.intern(Type::Pointer(t, 0))
794 }
795 fn constant_index(&self, v: ValueId) -> Option<usize> {
797 match self.m.values.get(v) {
798 Some(Value::Constant(Constant::Integer(i))) => usize::try_from(*i).ok(),
799 Some(Value::Constant(Constant::Null)) => Some(0),
800 _ => None,
801 }
802 }
803 fn result(&mut self, ty: TypeId, at: usize) -> Result<Option<(ValueId, TypeId)>> {
804 if *self.m.type_at(ty, at)? == Type::Void {
805 return Ok(None);
806 }
807 Ok(Some((self.m.push(Value::Local, ty, at)?, ty)))
808 }
809}
810
811fn binary(code: u64, at: usize) -> Result<BinaryOp> {
812 Ok(match code {
813 0 => BinaryOp::Add,
814 1 => BinaryOp::Sub,
815 2 => BinaryOp::Mul,
816 3 => BinaryOp::UDiv,
817 4 => BinaryOp::SDiv,
818 5 => BinaryOp::URem,
819 6 => BinaryOp::SRem,
820 7 => BinaryOp::Shl,
821 8 => BinaryOp::LShr,
822 9 => BinaryOp::AShr,
823 10 => BinaryOp::And,
824 11 => BinaryOp::Or,
825 12 => BinaryOp::Xor,
826 other => return Err(error(at, format!("binary opcode {other}"))),
827 })
828}
829fn cast(code: u64, at: usize) -> Result<CastOp> {
830 Ok(match code {
831 0 => CastOp::Trunc,
832 1 => CastOp::ZExt,
833 2 => CastOp::SExt,
834 3 => CastOp::FpToUi,
835 4 => CastOp::FpToSi,
836 5 => CastOp::UiToFp,
837 6 => CastOp::SiToFp,
838 7 => CastOp::FpTrunc,
839 8 => CastOp::FpExt,
840 9 => CastOp::PtrToInt,
841 10 => CastOp::IntToPtr,
842 11 => CastOp::BitCast,
843 other => return Err(error(at, format!("cast opcode {other}"))),
844 })
845}
846fn refused(code: u64) -> &'static str {
848 match code {
849 4 | 30 => "getelementptr (old form)",
850 13 => "invoke",
851 41 => "load (atomic)",
852 23 => "va_arg",
853 24 | 42 | 45 => "store (atomic)",
854 31 => "indirectbr",
855 37 => "cmpxchg (old form)",
856 59 => "atomicrmw (new form)",
857 39 => "resume",
858 40 | 47 => "landingpad",
859 _ => "unknown instruction record",
860 }
861}
862
863impl Module {
864 fn read_function(&mut self, block: &Block, value: ValueId) -> Result<Function> {
865 let fty = match self.value_types.get(value).and_then(|&t| self.types.get(t)) {
866 Some(Type::Pointer(t, _)) => *t,
867 _ => return Err(error(block.at, "function value is not a function pointer")),
868 };
869 let params = match self.type_at(fty, block.at)? {
870 Type::Function { params, .. } => params.clone(),
871 _ => return Err(error(block.at, "function type")),
872 };
873 let base = self.values.len();
874 for p in params {
875 self.push(Value::Local, p, block.at)?;
876 }
877 let mut body = Body {
878 m: self,
879 block: 0,
880 blocks: 0,
881 };
882 let mut instructions = Vec::new();
883 for e in &block.elements {
884 let r = match e {
885 crate::bitstream::Element::Block(b) => {
886 match b.id {
887 CONSTANTS => body.m.read_constants(b)?,
888 VALUE_SYMTAB => body.m.read_symbols(b, 0)?,
889 METADATA | METADATA_ATTACHMENT | USELIST => {}
890 other => return Err(error(b.at, format!("block {other} in a function"))),
891 }
892 continue;
893 }
894 crate::bitstream::Element::Record(r) => r,
895 };
896 let mut i = 0;
897 let (op, ty): (Op, Option<TypeId>) = match r.code {
898 1 => {
899 body.blocks = usize::try_from(op(r, 0)?)
900 .ok()
901 .filter(|&n| n > 0 && n <= 1 << 16)
902 .ok_or_else(|| error(r.at, "basic block count"))?;
903 continue;
904 }
905 33 | 35 => continue, 2 => {
907 let (lhs, t) = body.value_type(r, &mut i)?;
908 let rhs = body.value(r, &mut i)?;
909 let o = binary(op(r, i)?, r.at)?;
910 (Op::Binary { op: o, lhs, rhs }, Some(t))
911 }
912 3 => {
913 let value = body.value(r, &mut i)?;
914 let to = body.m.ty(op(r, i)?, r.at)?;
915 let o = cast(op(r, i.saturating_add(1))?, r.at)?;
916 (Op::Cast { op: o, value }, Some(to))
917 }
918 9 | 28 => {
919 let (lhs, t) = body.value_type(r, &mut i)?;
920 let rhs = body.value(r, &mut i)?;
921 let predicate = op(r, i)?;
922 let bool_ty = match body.m.type_at(t, r.at)? {
923 Type::Vector(..) => {
924 return Err(error(r.at, "vector comparison"));
925 }
926 _ => body
927 .m
928 .types
929 .iter()
930 .position(|x| *x == Type::Integer(1))
931 .ok_or_else(|| error(r.at, "no i1 type for a comparison"))?,
932 };
933 (Op::Compare { predicate, lhs, rhs }, Some(bool_ty))
934 }
935 29 => {
936 let (then, t) = body.value_type(r, &mut i)?;
937 let otherwise = body.value(r, &mut i)?;
938 let condition = body.value(r, &mut i)?;
939 (
940 Op::Select {
941 condition,
942 then,
943 otherwise,
944 },
945 Some(t),
946 )
947 }
948 26 => {
949 let (aggregate, mut t) = body.value_type(r, &mut i)?;
950 let indices = r.operands.get(i..).unwrap_or_default().to_vec();
951 for &k in &indices {
952 t = match body.m.type_at(t, r.at)? {
953 Type::Struct { elements, .. } => *usize::try_from(k)
954 .ok()
955 .and_then(|k| elements.get(k))
956 .ok_or_else(|| error(r.at, "extractvalue index"))?,
957 Type::Array(n, e) if k < *n => *e,
958 _ => return Err(error(r.at, "extractvalue index")),
959 };
960 }
961 (Op::ExtractValue { aggregate, indices }, Some(t))
962 }
963 6 => {
964 let (vector, t) = body.value_type(r, &mut i)?;
965 let (index, _) = body.value_type(r, &mut i)?;
966 let Type::Vector(_, element) = *body.m.type_at(t, r.at)? else {
967 return Err(error(r.at, "extractelement of something that is not a vector"));
968 };
969 (Op::ExtractElement { vector, index }, Some(element))
970 }
971 7 => {
972 let (vector, t) = body.value_type(r, &mut i)?;
973 let value = body.value(r, &mut i)?;
974 let (index, _) = body.value_type(r, &mut i)?;
975 (Op::InsertElement { vector, value, index }, Some(t))
976 }
977 8 => {
978 let (first, t) = body.value_type(r, &mut i)?;
979 let second = body.value(r, &mut i)?;
980 let (mask, mask_ty) = body.value_type(r, &mut i)?;
981 let (Type::Vector(_, element), Type::Vector(lanes, _)) = (
982 body.m.type_at(t, r.at)?.clone(),
983 body.m.type_at(mask_ty, r.at)?.clone(),
984 ) else {
985 return Err(error(r.at, "shufflevector of something that is not a vector"));
986 };
987 let result = body
988 .m
989 .types
990 .iter()
991 .position(|x| *x == Type::Vector(lanes, element))
992 .ok_or_else(|| error(r.at, "no type for the shuffled vector"))?;
993 (Op::ShuffleVector { first, second, mask }, Some(result))
994 }
995 27 => {
996 let (aggregate, t) = body.value_type(r, &mut i)?;
997 let value = body.value(r, &mut i)?;
998 let indices = r.operands.get(i..).unwrap_or_default().to_vec();
999 (
1000 Op::InsertValue {
1001 aggregate,
1002 value,
1003 indices,
1004 },
1005 Some(t),
1006 )
1007 }
1008 34 => {
1009 i = 1; let cc = op(r, i)?;
1011 i = i.saturating_add(1);
1012 if cc & (1 << 17) != 0 {
1013 i = i.saturating_add(1); }
1015 let explicit = if cc & (1 << 15) != 0 {
1016 let t = body.m.ty(op(r, i)?, r.at)?;
1017 i = i.saturating_add(1);
1018 Some(t)
1019 } else {
1020 None
1021 };
1022 let (function, callee_ty) = body.value_type(r, &mut i)?;
1023 let fty = match (explicit, body.m.type_at(callee_ty, r.at)?) {
1024 (Some(t), _) => t,
1025 (None, Type::Pointer(t, _)) => *t,
1026 _ => return Err(error(r.at, "callee is not a function pointer")),
1027 };
1028 let (ret, params, vararg) = match body.m.type_at(fty, r.at)? {
1029 Type::Function { ret, params, vararg } => (*ret, params.clone(), *vararg),
1030 _ => return Err(error(r.at, "call through a non-function type")),
1031 };
1032 if vararg {
1033 return Err(error(r.at, "vararg call"));
1034 }
1035 let mut args = Vec::with_capacity(params.len());
1036 for p in ¶ms {
1037 let a = body.value(r, &mut i)?;
1039 if a < body.next() && body.m.value_types.get(a) != Some(p) {
1040 return Err(error(r.at, "call argument type"));
1041 }
1042 args.push(a);
1043 }
1044 if i != r.operands.len() {
1045 return Err(error(r.at, "call operands left over"));
1046 }
1047 (Op::Call { function, args }, Some(ret))
1048 }
1049 16 => {
1050 let t = body.m.ty(op(r, 0)?, r.at)?;
1051 let pairs = r.operands.get(1..).unwrap_or_default();
1052 if pairs.is_empty() || pairs.len() % 2 != 0 {
1053 return Err(error(r.at, "phi operands"));
1054 }
1055 let next = i64::try_from(body.next()).map_err(|_| error(r.at, "too many values"))?;
1056 let mut incoming = Vec::with_capacity(pairs.len() / 2);
1057 for pair in pairs.as_chunks::<2>().0 {
1058 let id = next
1060 .checked_sub(signed_vbr(pair[0]))
1061 .and_then(|v| usize::try_from(v).ok())
1062 .ok_or_else(|| error(r.at, "phi value"))?;
1063 let block = usize::try_from(pair[1])
1064 .ok()
1065 .filter(|&b| b < body.blocks)
1066 .ok_or_else(|| error(r.at, "phi block"))?;
1067 incoming.push((id, block));
1068 }
1069 (Op::Phi { incoming }, Some(t))
1070 }
1071 10 => {
1072 if r.operands.is_empty() {
1073 (Op::Return(None), None)
1074 } else {
1075 (Op::Return(Some(body.value(r, &mut i)?)), None)
1076 }
1077 }
1078 11 => {
1079 let target = |v: u64| -> Result<usize> {
1080 usize::try_from(v)
1081 .ok()
1082 .filter(|&b| b < body.blocks)
1083 .ok_or_else(|| error(r.at, "branch target"))
1084 };
1085 if r.operands.len() == 1 {
1086 (
1087 Op::Branch {
1088 target: target(op(r, 0)?)?,
1089 },
1090 None,
1091 )
1092 } else {
1093 let then = target(op(r, 0)?)?;
1094 let otherwise = target(op(r, 1)?)?;
1095 i = 2;
1096 let condition = body.value(r, &mut i)?;
1097 (
1098 Op::CondBranch {
1099 condition,
1100 then,
1101 otherwise,
1102 },
1103 None,
1104 )
1105 }
1106 }
1107 12 => {
1108 let block = |v: u64| -> Result<usize> {
1110 usize::try_from(v)
1111 .ok()
1112 .filter(|&b| b < body.blocks)
1113 .ok_or_else(|| error(r.at, "switch target"))
1114 };
1115 i = 1;
1116 let value = body.value(r, &mut i)?;
1117 let default = block(op(r, i)?)?;
1118 let pairs = r.operands.get(i.saturating_add(1)..).unwrap_or_default();
1119 if pairs.len() % 2 != 0 {
1120 return Err(error(r.at, "switch cases"));
1121 }
1122 let cases = pairs
1123 .as_chunks::<2>()
1124 .0
1125 .iter()
1126 .map(|p| {
1127 Ok((
1128 usize::try_from(p[0]).map_err(|_| error(r.at, "case value"))?,
1129 block(p[1])?,
1130 ))
1131 })
1132 .collect::<Result<Vec<_>>>()?;
1133 (
1134 Op::Switch {
1135 value,
1136 default,
1137 cases,
1138 },
1139 None,
1140 )
1141 }
1142 15 => (Op::Unreachable, None),
1143 19 => {
1144 let ty = body.m.ty(op(r, 0)?, r.at)?;
1146 (Op::Alloca { ty }, Some(body.pointer_to(ty)))
1147 }
1148 20 => {
1149 let (pointer, pt) = body.value_type(r, &mut i)?;
1150 let _ = pt;
1151 let ty = body.m.ty(op(r, i)?, r.at)?;
1152 (Op::Load { pointer }, Some(ty))
1153 }
1154 44 => {
1155 let (pointer, _) = body.value_type(r, &mut i)?;
1156 let (value, _) = body.value_type(r, &mut i)?;
1157 (Op::Store { pointer, value }, None)
1158 }
1159 38 => {
1161 let (pointer, _) = body.value_type(r, &mut i)?;
1162 let value = body.value(r, &mut i)?;
1163 let op = op(r, i)?;
1164 let ty = body.m.value_types.get(value).copied();
1165 let ty = match ty {
1166 Some(t) if value < body.next() => t,
1167 _ => return Err(error(r.at, "an atomicrmw of a value defined later")),
1168 };
1169 (Op::AtomicRmw { pointer, value, op }, Some(ty))
1170 }
1171 46 => {
1174 let (pointer, _) = body.value_type(r, &mut i)?;
1175 let (compare, ty) = body.value_type(r, &mut i)?;
1176 let value = body.value(r, &mut i)?;
1177 let flag = body
1178 .m
1179 .types
1180 .iter()
1181 .position(|t| *t == Type::Integer(1))
1182 .ok_or_else(|| error(r.at, "a cmpxchg without a boolean type"))?;
1183 let pair = Type::Struct {
1184 name: None,
1185 elements: vec![ty, flag],
1186 };
1187 let result = body.m.intern(pair);
1188 (
1189 Op::CmpXchg {
1190 pointer,
1191 compare,
1192 value,
1193 },
1194 Some(result),
1195 )
1196 }
1197 36 => (Op::Fence, None),
1198 43 => {
1199 i = 2;
1201 let source = body.m.ty(op(r, 1)?, r.at)?;
1202 let (base, _) = body.value_type(r, &mut i)?;
1203 let mut indices = Vec::new();
1204 while i < r.operands.len() {
1205 indices.push(body.value_type(r, &mut i)?.0);
1206 }
1207 let mut t = source;
1210 for &index in indices.iter().skip(1) {
1211 t = match body.m.type_at(t, r.at)?.clone() {
1212 Type::Array(_, e) | Type::Vector(_, e) => e,
1213 Type::Struct { elements, .. } => {
1214 let k = match body.constant_index(index) {
1215 Some(k) => k,
1216 None => {
1217 return Err(error(r.at, "a structure index that is not constant"));
1218 }
1219 };
1220 *elements
1221 .get(k)
1222 .ok_or_else(|| error(r.at, "getelementptr structure index"))?
1223 }
1224 _ => return Err(error(r.at, "getelementptr into a scalar")),
1225 };
1226 }
1227 (Op::Gep { base, indices }, Some(body.pointer_to(t)))
1228 }
1229 other => {
1230 return Err(error(
1231 r.at,
1232 format!("instruction {} (record {other}) is not supported", refused(other)),
1233 ));
1234 }
1235 };
1236 let result = match ty {
1237 Some(t) => body.result(t, r.at)?,
1238 None => None,
1239 };
1240 let terminator = matches!(
1241 op,
1242 Op::Return(_)
1243 | Op::Branch { .. }
1244 | Op::CondBranch { .. }
1245 | Op::Switch { .. }
1246 | Op::Unreachable
1247 );
1248 instructions.push(Instruction {
1249 op,
1250 result,
1251 block: body.block,
1252 at: r.at,
1253 });
1254 if terminator {
1255 body.block = body.block.saturating_add(1);
1256 }
1257 }
1258 if body.block != body.blocks {
1259 return Err(error(block.at, "basic blocks without terminators"));
1260 }
1261 let end = body.next();
1262 let blocks = body.blocks;
1263 for inst in &instructions {
1266 if inst.block >= blocks {
1267 return Err(error(inst.at, "an instruction after the last terminator"));
1268 }
1269 if let Some(v) = inst.op.operands().into_iter().find(|v| *v >= end) {
1270 return Err(error(inst.at, format!("value {v} of {end} values")));
1271 }
1272 if let Some(b) = inst.op.blocks().into_iter().find(|b| *b >= blocks) {
1273 return Err(error(inst.at, format!("basic block {b} of {blocks}")));
1274 }
1275 if let Op::Call { function, args } = &inst.op {
1276 if *function >= end {
1277 return Err(error(inst.at, format!("callee {function} of {end} values")));
1278 }
1279 if let Some(Value::Function { ty, .. }) = self.values.get(*function)
1280 && let Some(Type::Function {
1281 vararg: false,
1282 params,
1283 ..
1284 }) = self.types.get(*ty)
1285 && params.len() != args.len()
1286 {
1287 return Err(error(
1288 inst.at,
1289 format!(
1290 "a call of {} arguments to a function of {} parameters",
1291 args.len(),
1292 params.len()
1293 ),
1294 ));
1295 }
1296 }
1297 }
1298 let locals = self.values.split_off(base);
1299 let local_types = self.value_types.split_off(base);
1300 Ok(Function {
1301 value,
1302 blocks,
1303 instructions,
1304 first: base,
1305 locals,
1306 local_types,
1307 })
1308 }
1309
1310 pub fn read(top: &[Block]) -> Result<Self> {
1312 let module = match top {
1313 [m] if m.id == MODULE => m,
1314 _ => return Err(error(0, "bitcode is not one module block")),
1315 };
1316 let mut m = Module {
1317 at: module.at,
1318 ..Module::default()
1319 };
1320 let mut bodies: Vec<ValueId> = Vec::new();
1321 let mut version = None;
1322 for e in &module.elements {
1323 match e {
1324 crate::bitstream::Element::Record(r) => match r.code {
1325 1 => version = Some(op(r, 0)?),
1326 2..=6 | 11 | 13 | 16 => {} 7 => {
1328 let t = m.ty(op(r, 0)?, r.at)?;
1331 let flags = op(r, 1)?;
1332 let address_space =
1333 u32::try_from(flags >> 2).map_err(|_| error(r.at, "address space"))?;
1334 let (ty, value_ty) = if flags & 2 != 0 {
1335 let pointer = m.intern(Type::Pointer(t, address_space));
1336 (pointer, t)
1337 } else {
1338 match m.type_at(t, r.at)? {
1339 Type::Pointer(inner, _) => (t, *inner),
1340 _ => return Err(error(r.at, "a global whose type is not a pointer")),
1341 }
1342 };
1343 let init = match op(r, 2)? {
1344 0 => None,
1345 n => Some(
1346 usize::try_from(n.saturating_sub(1))
1347 .map_err(|_| error(r.at, "initial value id"))?,
1348 ),
1349 };
1350 m.push(
1351 Value::Global {
1352 ty,
1353 value_ty,
1354 init,
1355 constant: flags & 1 != 0,
1356 address_space,
1357 },
1358 ty,
1359 r.at,
1360 )?;
1361 }
1362 8 => {
1363 let t = m.ty(op(r, 0)?, r.at)?;
1365 let pointer = m.intern(Type::Pointer(t, 0));
1366 let declaration = op(r, 2)? != 0;
1367 let v = m.push(Value::Function { ty: t, declaration }, pointer, r.at)?;
1368 if !declaration {
1369 bodies.push(v);
1370 }
1371 }
1372 other => return Err(error(r.at, format!("module record {other}"))),
1373 },
1374 crate::bitstream::Element::Block(b) => match b.id {
1375 BLOCKINFO | PARAMATTR | PARAMATTR_GROUP | USELIST => {}
1376 TYPES => m.read_types(b)?,
1377 CONSTANTS => m.read_constants(b)?,
1378 METADATA => m.read_metadata(b)?,
1379 VALUE_SYMTAB => m.read_symbols(b, 0)?,
1380 FUNCTION => {
1381 if version != Some(1) {
1382 return Err(error(b.at, "only relative value ids (module version 1)"));
1383 }
1384 if bodies.is_empty() {
1386 return Err(error(b.at, "function body without a definition"));
1387 }
1388 let value = bodies.remove(0);
1389 let f = m.read_function(b, value)?;
1391 m.functions.push(f);
1392 }
1393 other => return Err(error(b.at, format!("module block {other}"))),
1394 },
1395 }
1396 }
1397 if !bodies.is_empty() {
1398 return Err(error(module.at, "a defined function has no body"));
1399 }
1400 Ok(m)
1401 }
1402}