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