1use crate::error::BitcodeError;
4use llvm_ir::value::Argument;
5use llvm_ir::{
6 ArgId, BasicBlock, BlockId, ConstId, ConstantData, Context, FastMathFlags, FloatKind,
7 FloatPredicate, Function, GlobalId, InstrId, InstrKind, Instruction, IntArithFlags,
8 IntPredicate, Linkage, Module, TailCallKind, TypeData, TypeId, ValueRef,
9};
10
11const MAGIC: &[u8; 4] = b"LRIR";
13
14pub fn read_bitcode(bytes: &[u8]) -> Result<(Context, Module), BitcodeError> {
16 let mut r = Reader::new(bytes);
17
18 let magic = r.read_bytes(4)?;
20 if magic != MAGIC {
21 return Err(BitcodeError::InvalidMagic);
22 }
23 let version = r.u32()?;
24 if version != 1 {
25 return Err(BitcodeError::ParseError(format!(
26 "unsupported version {}",
27 version
28 )));
29 }
30
31 let mut ctx = Context::new();
33 let type_count = r.u32()? as usize;
34 let mut type_id_map: Vec<TypeId> = Vec::with_capacity(type_count);
37
38 for _ in 0..type_count {
39 let td = decode_type(&mut r, &type_id_map)?;
40 let interned = intern_type(&mut ctx, td);
42 type_id_map.push(interned);
43 }
44
45 let const_count = r.u32()? as usize;
47 let mut const_id_map: Vec<ConstId> = Vec::with_capacity(const_count);
48
49 for _ in 0..const_count {
50 let cd = decode_const(&mut r, &type_id_map, &const_id_map)?;
51 let cid = ctx.push_const(cd);
52 const_id_map.push(cid);
53 }
54
55 let module_name = r.string()?;
57 let mut module = Module::new(module_name);
58
59 let func_count = r.u32()? as usize;
61 for _ in 0..func_count {
62 let func = decode_function(&mut r, &type_id_map, &const_id_map)?;
63 module.add_function(func);
64 }
65
66 Ok((ctx, module))
67}
68
69mod type_tag {
72 pub const VOID: u8 = 0;
74 pub const INTEGER: u8 = 1;
76 pub const FLOAT: u8 = 2;
78 pub const POINTER: u8 = 3;
80 pub const ARRAY: u8 = 4;
82 pub const VECTOR: u8 = 5;
84 pub const STRUCT: u8 = 6;
86 pub const FUNCTION: u8 = 7;
88 pub const LABEL: u8 = 8;
90 pub const METADATA: u8 = 9;
92}
93
94mod float_tag {
95 pub const HALF: u8 = 0;
97 pub const BFLOAT: u8 = 1;
99 pub const SINGLE: u8 = 2;
101 pub const DOUBLE: u8 = 3;
103 pub const FP128: u8 = 4;
105 pub const X86FP80: u8 = 5;
107}
108
109fn decode_type(r: &mut Reader, type_id_map: &[TypeId]) -> Result<TypeData, BitcodeError> {
111 let tag = r.u8()?;
112 match tag {
113 type_tag::VOID => Ok(TypeData::Void),
114 type_tag::INTEGER => {
115 let bits = r.u32()?;
116 Ok(TypeData::Integer(bits))
117 }
118 type_tag::FLOAT => {
119 let ftag = r.u8()?;
120 let kind = match ftag {
121 float_tag::HALF => FloatKind::Half,
122 float_tag::BFLOAT => FloatKind::BFloat,
123 float_tag::SINGLE => FloatKind::Single,
124 float_tag::DOUBLE => FloatKind::Double,
125 float_tag::FP128 => FloatKind::Fp128,
126 float_tag::X86FP80 => FloatKind::X86Fp80,
127 _ => return Err(BitcodeError::InvalidType),
128 };
129 Ok(TypeData::Float(kind))
130 }
131 type_tag::POINTER => Ok(TypeData::Pointer),
132 type_tag::ARRAY => {
133 let elem_raw = r.u32()? as usize;
134 let len = r.u64()?;
135 let element = map_type_id(type_id_map, elem_raw)?;
136 Ok(TypeData::Array { element, len })
137 }
138 type_tag::VECTOR => {
139 let elem_raw = r.u32()? as usize;
140 let len = r.u32()?;
141 let scalable = r.u8()? != 0;
142 let element = map_type_id(type_id_map, elem_raw)?;
143 Ok(TypeData::Vector {
144 element,
145 len,
146 scalable,
147 })
148 }
149 type_tag::STRUCT => {
150 let name = r.opt_string()?;
151 let packed = r.u8()? != 0;
152 let field_count = r.u32()? as usize;
153 let mut fields = Vec::with_capacity(field_count);
154 for _ in 0..field_count {
155 let fid_raw = r.u32()? as usize;
156 fields.push(map_type_id(type_id_map, fid_raw)?);
157 }
158 Ok(TypeData::Struct(llvm_ir::StructType {
159 name,
160 fields,
161 packed,
162 }))
163 }
164 type_tag::FUNCTION => {
165 let ret_raw = r.u32()? as usize;
166 let variadic = r.u8()? != 0;
167 let param_count = r.u32()? as usize;
168 let mut params = Vec::with_capacity(param_count);
169 for _ in 0..param_count {
170 let pid_raw = r.u32()? as usize;
171 params.push(map_type_id(type_id_map, pid_raw)?);
172 }
173 let ret = map_type_id(type_id_map, ret_raw)?;
174 Ok(TypeData::Function(llvm_ir::FunctionType {
175 ret,
176 params,
177 variadic,
178 }))
179 }
180 type_tag::LABEL => Ok(TypeData::Label),
181 type_tag::METADATA => Ok(TypeData::Metadata),
182 _ => Err(BitcodeError::InvalidType),
183 }
184}
185
186fn map_type_id(type_id_map: &[TypeId], raw: usize) -> Result<TypeId, BitcodeError> {
187 type_id_map.get(raw).copied().ok_or_else(|| {
188 BitcodeError::ParseError(format!(
189 "type id {} out of range (table size {})",
190 raw,
191 type_id_map.len()
192 ))
193 })
194}
195
196fn map_const_id(const_id_map: &[ConstId], raw: usize) -> Result<ConstId, BitcodeError> {
197 const_id_map
198 .get(raw)
199 .copied()
200 .ok_or_else(|| BitcodeError::ParseError(format!("const id {} out of range", raw)))
201}
202
203fn intern_type(ctx: &mut Context, td: TypeData) -> TypeId {
205 match td {
206 TypeData::Void => ctx.void_ty,
207 TypeData::Integer(b) => ctx.mk_int(b),
208 TypeData::Float(k) => ctx.mk_float(k),
209 TypeData::Pointer => ctx.mk_ptr(),
210 TypeData::Label => ctx.mk_label(),
211 TypeData::Metadata => ctx.mk_metadata(),
212 TypeData::Array { element, len } => ctx.mk_array(element, len),
213 TypeData::Vector {
214 element,
215 len,
216 scalable,
217 } => ctx.mk_vector(element, len, scalable),
218 TypeData::Struct(st) => {
219 if let Some(ref name) = st.name {
220 let id = ctx.mk_struct_named(name.clone());
221 ctx.define_struct_body(id, st.fields, st.packed);
222 id
223 } else {
224 ctx.mk_struct_anon(st.fields, st.packed)
225 }
226 }
227 TypeData::Function(ft) => ctx.mk_fn_type(ft.ret, ft.params, ft.variadic),
228 }
229}
230
231mod const_tag {
234 pub const INT: u8 = 0;
236 pub const INT_WIDE: u8 = 1;
238 pub const FLOAT: u8 = 2;
240 pub const NULL: u8 = 3;
242 pub const UNDEF: u8 = 4;
244 pub const POISON: u8 = 5;
246 pub const ZERO_INIT: u8 = 6;
248 pub const ARRAY: u8 = 7;
250 pub const STRUCT: u8 = 8;
252 pub const VECTOR: u8 = 9;
254 pub const GLOBAL_REF: u8 = 10;
256}
257
258fn decode_const(
259 r: &mut Reader,
260 type_id_map: &[TypeId],
261 const_id_map: &[ConstId],
262) -> Result<ConstantData, BitcodeError> {
263 let tag = r.u8()?;
264 match tag {
265 const_tag::INT => {
266 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
267 let val = r.u64()?;
268 Ok(ConstantData::Int { ty, val })
269 }
270 const_tag::INT_WIDE => {
271 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
272 let word_count = r.u32()? as usize;
273 let mut words = Vec::with_capacity(word_count);
274 for _ in 0..word_count {
275 words.push(r.u64()?);
276 }
277 Ok(ConstantData::IntWide { ty, words })
278 }
279 const_tag::FLOAT => {
280 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
281 let bits = r.u64()?;
282 Ok(ConstantData::Float { ty, bits })
283 }
284 const_tag::NULL => {
285 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
286 Ok(ConstantData::Null(ty))
287 }
288 const_tag::UNDEF => {
289 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
290 Ok(ConstantData::Undef(ty))
291 }
292 const_tag::POISON => {
293 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
294 Ok(ConstantData::Poison(ty))
295 }
296 const_tag::ZERO_INIT => {
297 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
298 Ok(ConstantData::ZeroInitializer(ty))
299 }
300 const_tag::ARRAY => {
301 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
302 let n = r.u32()? as usize;
303 let mut elems = Vec::with_capacity(n);
304 for _ in 0..n {
305 elems.push(map_const_id(const_id_map, r.u32()? as usize)?);
306 }
307 Ok(ConstantData::Array {
308 ty,
309 elements: elems,
310 })
311 }
312 const_tag::STRUCT => {
313 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
314 let n = r.u32()? as usize;
315 let mut fields = Vec::with_capacity(n);
316 for _ in 0..n {
317 fields.push(map_const_id(const_id_map, r.u32()? as usize)?);
318 }
319 Ok(ConstantData::Struct { ty, fields })
320 }
321 const_tag::VECTOR => {
322 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
323 let n = r.u32()? as usize;
324 let mut elems = Vec::with_capacity(n);
325 for _ in 0..n {
326 elems.push(map_const_id(const_id_map, r.u32()? as usize)?);
327 }
328 Ok(ConstantData::Vector {
329 ty,
330 elements: elems,
331 })
332 }
333 const_tag::GLOBAL_REF => {
334 let ty = map_type_id(type_id_map, r.u32()? as usize)?;
335 let id_raw = r.u32()?;
336 let name = r.string()?;
337 Ok(ConstantData::GlobalRef {
338 ty,
339 id: GlobalId(id_raw),
340 name,
341 })
342 }
343 other => Err(BitcodeError::UnsupportedRecord(other as u32)),
344 }
345}
346
347mod linkage_tag {
350 pub const PRIVATE: u8 = 0;
352 pub const INTERNAL: u8 = 1;
354 pub const EXTERNAL: u8 = 2;
356 pub const WEAK: u8 = 3;
358 pub const WEAK_ODR: u8 = 4;
360 pub const LINK_ONCE: u8 = 5;
362 pub const LINK_ONCE_ODR: u8 = 6;
364 pub const COMMON: u8 = 7;
366 pub const AVAILABLE_EXTERNALLY: u8 = 8;
368}
369
370fn decode_linkage(tag: u8) -> Result<Linkage, BitcodeError> {
371 match tag {
372 linkage_tag::PRIVATE => Ok(Linkage::Private),
373 linkage_tag::INTERNAL => Ok(Linkage::Internal),
374 linkage_tag::EXTERNAL => Ok(Linkage::External),
375 linkage_tag::WEAK => Ok(Linkage::Weak),
376 linkage_tag::WEAK_ODR => Ok(Linkage::WeakOdr),
377 linkage_tag::LINK_ONCE => Ok(Linkage::LinkOnce),
378 linkage_tag::LINK_ONCE_ODR => Ok(Linkage::LinkOnceOdr),
379 linkage_tag::COMMON => Ok(Linkage::Common),
380 linkage_tag::AVAILABLE_EXTERNALLY => Ok(Linkage::AvailableExternally),
381 other => Err(BitcodeError::UnsupportedRecord(other as u32)),
382 }
383}
384
385fn decode_function(
386 r: &mut Reader,
387 type_id_map: &[TypeId],
388 const_id_map: &[ConstId],
389) -> Result<Function, BitcodeError> {
390 let name = r.string()?;
391 let ty_raw = r.u32()? as usize;
392 let ty = map_type_id(type_id_map, ty_raw)?;
393 let linkage = decode_linkage(r.u8()?)?;
394 let is_declaration = r.u8()? != 0;
395
396 let arg_count = r.u32()? as usize;
398 let mut args = Vec::with_capacity(arg_count);
399 for _ in 0..arg_count {
400 let aname = r.string()?;
401 let aty_raw = r.u32()? as usize;
402 let aty = map_type_id(type_id_map, aty_raw)?;
403 let index = r.u32()?;
404 args.push(Argument {
405 name: aname,
406 ty: aty,
407 index,
408 });
409 }
410
411 let mut func = if is_declaration {
412 Function::new_declaration(name, ty, args, linkage)
413 } else {
414 Function::new(name, ty, args, linkage)
415 };
416 func.is_declaration = is_declaration;
417
418 let block_count = r.u32()? as usize;
420 let mut block_records: Vec<(String, Vec<u32>, u32)> = Vec::with_capacity(block_count);
422 for _ in 0..block_count {
423 let bname = r.string()?;
424 let body_count = r.u32()? as usize;
425 let mut body = Vec::with_capacity(body_count);
426 for _ in 0..body_count {
427 body.push(r.u32()?);
428 }
429 let term = r.u32()?;
430 block_records.push((bname, body, term));
431 }
432
433 let instr_count = r.u32()? as usize;
435 for _ in 0..instr_count {
436 let instr = decode_instr(r, type_id_map, const_id_map)?;
437 func.alloc_instr(instr);
438 }
439
440 for (bname, body_ids, term_raw) in block_records {
442 let mut bb = BasicBlock::new(bname);
443 for id in body_ids {
444 bb.body.push(InstrId(id));
445 }
446 bb.terminator = if term_raw == 0xFFFF_FFFF {
447 None
448 } else {
449 Some(InstrId(term_raw))
450 };
451 func.blocks.push(bb);
452 }
453
454 Ok(func)
455}
456
457mod instr_tag {
460 pub const ADD: u32 = 0;
462 pub const SUB: u32 = 1;
464 pub const MUL: u32 = 2;
466 pub const UDIV: u32 = 3;
468 pub const SDIV: u32 = 4;
470 pub const UREM: u32 = 5;
472 pub const SREM: u32 = 6;
474 pub const AND: u32 = 10;
476 pub const OR: u32 = 11;
478 pub const XOR: u32 = 12;
480 pub const SHL: u32 = 13;
482 pub const LSHR: u32 = 14;
484 pub const ASHR: u32 = 15;
486 pub const FADD: u32 = 20;
488 pub const FSUB: u32 = 21;
490 pub const FMUL: u32 = 22;
492 pub const FDIV: u32 = 23;
494 pub const FREM: u32 = 24;
496 pub const FNEG: u32 = 25;
498 pub const ICMP: u32 = 30;
500 pub const FCMP: u32 = 31;
502 pub const ALLOCA: u32 = 40;
504 pub const LOAD: u32 = 41;
506 pub const STORE: u32 = 42;
508 pub const GEP: u32 = 43;
510 pub const TRUNC: u32 = 50;
512 pub const ZEXT: u32 = 51;
514 pub const SEXT: u32 = 52;
516 pub const FPTRUNC: u32 = 53;
518 pub const FPEXT: u32 = 54;
520 pub const FPTOUI: u32 = 55;
522 pub const FPTOSI: u32 = 56;
524 pub const UITOFP: u32 = 57;
526 pub const SITOFP: u32 = 58;
528 pub const PTRTOINT: u32 = 59;
530 pub const INTTOPTR: u32 = 60;
532 pub const BITCAST: u32 = 61;
534 pub const ADDRSPACECAST: u32 = 62;
536 pub const FREEZE: u32 = 63;
538 pub const SELECT: u32 = 70;
540 pub const PHI: u32 = 71;
542 pub const EXTRACTVALUE: u32 = 72;
544 pub const INSERTVALUE: u32 = 73;
546 pub const EXTRACTELEM: u32 = 74;
548 pub const INSERTELEM: u32 = 75;
550 pub const SHUFFLEVEC: u32 = 76;
552 pub const CALL: u32 = 80;
554 pub const RET: u32 = 90;
556 pub const BR: u32 = 91;
558 pub const CONDBR: u32 = 92;
560 pub const SWITCH: u32 = 93;
562 pub const UNREACHABLE: u32 = 94;
564}
565
566fn decode_vref(r: &mut Reader) -> Result<ValueRef, BitcodeError> {
567 let tag = r.u8()?;
568 let id = r.u32()?;
569 match tag {
570 0 => Ok(ValueRef::Instruction(InstrId(id))),
571 1 => Ok(ValueRef::Argument(ArgId(id))),
572 2 => Ok(ValueRef::Constant(ConstId(id))),
573 3 => Ok(ValueRef::Global(GlobalId(id))),
574 other => Err(BitcodeError::UnsupportedRecord(other as u32)),
575 }
576}
577
578fn decode_opt_vref(r: &mut Reader) -> Result<Option<ValueRef>, BitcodeError> {
579 let present = r.u8()?;
580 if present != 0 {
581 Ok(Some(decode_vref(r)?))
582 } else {
583 Ok(None)
584 }
585}
586
587fn decode_opt_u32(r: &mut Reader) -> Result<Option<u32>, BitcodeError> {
588 let present = r.u8()?;
589 if present != 0 {
590 Ok(Some(r.u32()?))
591 } else {
592 Ok(None)
593 }
594}
595
596fn decode_int_pred(tag: u8) -> Result<IntPredicate, BitcodeError> {
597 match tag {
598 0 => Ok(IntPredicate::Eq),
599 1 => Ok(IntPredicate::Ne),
600 2 => Ok(IntPredicate::Ugt),
601 3 => Ok(IntPredicate::Uge),
602 4 => Ok(IntPredicate::Ult),
603 5 => Ok(IntPredicate::Ule),
604 6 => Ok(IntPredicate::Sgt),
605 7 => Ok(IntPredicate::Sge),
606 8 => Ok(IntPredicate::Slt),
607 9 => Ok(IntPredicate::Sle),
608 other => Err(BitcodeError::UnsupportedRecord(other as u32)),
609 }
610}
611
612fn decode_float_pred(tag: u8) -> Result<FloatPredicate, BitcodeError> {
613 match tag {
614 0 => Ok(FloatPredicate::False),
615 1 => Ok(FloatPredicate::Oeq),
616 2 => Ok(FloatPredicate::Ogt),
617 3 => Ok(FloatPredicate::Oge),
618 4 => Ok(FloatPredicate::Olt),
619 5 => Ok(FloatPredicate::Ole),
620 6 => Ok(FloatPredicate::One),
621 7 => Ok(FloatPredicate::Ord),
622 8 => Ok(FloatPredicate::Uno),
623 9 => Ok(FloatPredicate::Ueq),
624 10 => Ok(FloatPredicate::Ugt),
625 11 => Ok(FloatPredicate::Uge),
626 12 => Ok(FloatPredicate::Ult),
627 13 => Ok(FloatPredicate::Ule),
628 14 => Ok(FloatPredicate::Une),
629 15 => Ok(FloatPredicate::True),
630 other => Err(BitcodeError::UnsupportedRecord(other as u32)),
631 }
632}
633
634fn decode_instr(
635 r: &mut Reader,
636 type_id_map: &[TypeId],
637 _const_id_map: &[ConstId],
638) -> Result<Instruction, BitcodeError> {
639 let name = r.opt_string()?;
641 let ty_raw = r.u32()? as usize;
642 let ty = map_type_id(type_id_map, ty_raw)?;
643 let tag = r.u32()?;
644
645 let kind = match tag {
646 instr_tag::ADD => {
647 let nuw = r.u8()? != 0;
648 let nsw = r.u8()? != 0;
649 let flags = IntArithFlags { nuw, nsw };
650 InstrKind::Add {
651 flags,
652 lhs: decode_vref(r)?,
653 rhs: decode_vref(r)?,
654 }
655 }
656 instr_tag::SUB => {
657 let nuw = r.u8()? != 0;
658 let nsw = r.u8()? != 0;
659 let flags = IntArithFlags { nuw, nsw };
660 InstrKind::Sub {
661 flags,
662 lhs: decode_vref(r)?,
663 rhs: decode_vref(r)?,
664 }
665 }
666 instr_tag::MUL => {
667 let nuw = r.u8()? != 0;
668 let nsw = r.u8()? != 0;
669 let flags = IntArithFlags { nuw, nsw };
670 InstrKind::Mul {
671 flags,
672 lhs: decode_vref(r)?,
673 rhs: decode_vref(r)?,
674 }
675 }
676 instr_tag::UDIV => {
677 let exact = r.u8()? != 0;
678 InstrKind::UDiv {
679 exact,
680 lhs: decode_vref(r)?,
681 rhs: decode_vref(r)?,
682 }
683 }
684 instr_tag::SDIV => {
685 let exact = r.u8()? != 0;
686 InstrKind::SDiv {
687 exact,
688 lhs: decode_vref(r)?,
689 rhs: decode_vref(r)?,
690 }
691 }
692 instr_tag::UREM => InstrKind::URem {
693 lhs: decode_vref(r)?,
694 rhs: decode_vref(r)?,
695 },
696 instr_tag::SREM => InstrKind::SRem {
697 lhs: decode_vref(r)?,
698 rhs: decode_vref(r)?,
699 },
700 instr_tag::AND => InstrKind::And {
701 lhs: decode_vref(r)?,
702 rhs: decode_vref(r)?,
703 },
704 instr_tag::OR => InstrKind::Or {
705 lhs: decode_vref(r)?,
706 rhs: decode_vref(r)?,
707 },
708 instr_tag::XOR => InstrKind::Xor {
709 lhs: decode_vref(r)?,
710 rhs: decode_vref(r)?,
711 },
712 instr_tag::SHL => {
713 let nuw = r.u8()? != 0;
714 let nsw = r.u8()? != 0;
715 let flags = IntArithFlags { nuw, nsw };
716 InstrKind::Shl {
717 flags,
718 lhs: decode_vref(r)?,
719 rhs: decode_vref(r)?,
720 }
721 }
722 instr_tag::LSHR => {
723 let exact = r.u8()? != 0;
724 InstrKind::LShr {
725 exact,
726 lhs: decode_vref(r)?,
727 rhs: decode_vref(r)?,
728 }
729 }
730 instr_tag::ASHR => {
731 let exact = r.u8()? != 0;
732 InstrKind::AShr {
733 exact,
734 lhs: decode_vref(r)?,
735 rhs: decode_vref(r)?,
736 }
737 }
738 instr_tag::FADD => InstrKind::FAdd {
739 flags: FastMathFlags::default(),
740 lhs: decode_vref(r)?,
741 rhs: decode_vref(r)?,
742 },
743 instr_tag::FSUB => InstrKind::FSub {
744 flags: FastMathFlags::default(),
745 lhs: decode_vref(r)?,
746 rhs: decode_vref(r)?,
747 },
748 instr_tag::FMUL => InstrKind::FMul {
749 flags: FastMathFlags::default(),
750 lhs: decode_vref(r)?,
751 rhs: decode_vref(r)?,
752 },
753 instr_tag::FDIV => InstrKind::FDiv {
754 flags: FastMathFlags::default(),
755 lhs: decode_vref(r)?,
756 rhs: decode_vref(r)?,
757 },
758 instr_tag::FREM => InstrKind::FRem {
759 flags: FastMathFlags::default(),
760 lhs: decode_vref(r)?,
761 rhs: decode_vref(r)?,
762 },
763 instr_tag::FNEG => InstrKind::FNeg {
764 flags: FastMathFlags::default(),
765 operand: decode_vref(r)?,
766 },
767 instr_tag::ICMP => {
768 let pred = decode_int_pred(r.u8()?)?;
769 InstrKind::ICmp {
770 pred,
771 lhs: decode_vref(r)?,
772 rhs: decode_vref(r)?,
773 }
774 }
775 instr_tag::FCMP => {
776 let pred = decode_float_pred(r.u8()?)?;
777 InstrKind::FCmp {
778 flags: FastMathFlags::default(),
779 pred,
780 lhs: decode_vref(r)?,
781 rhs: decode_vref(r)?,
782 }
783 }
784 instr_tag::ALLOCA => {
785 let alloc_ty = map_type_id(type_id_map, r.u32()? as usize)?;
786 let num_elements = decode_opt_vref(r)?;
787 let align = decode_opt_u32(r)?;
788 InstrKind::Alloca {
789 alloc_ty,
790 num_elements,
791 align,
792 }
793 }
794 instr_tag::LOAD => {
795 let lty = map_type_id(type_id_map, r.u32()? as usize)?;
796 let ptr = decode_vref(r)?;
797 let align = decode_opt_u32(r)?;
798 let volatile = r.u8()? != 0;
799 InstrKind::Load {
800 ty: lty,
801 ptr,
802 align,
803 volatile,
804 }
805 }
806 instr_tag::STORE => {
807 let val = decode_vref(r)?;
808 let ptr = decode_vref(r)?;
809 let align = decode_opt_u32(r)?;
810 let volatile = r.u8()? != 0;
811 InstrKind::Store {
812 val,
813 ptr,
814 align,
815 volatile,
816 }
817 }
818 instr_tag::GEP => {
819 let inbounds = r.u8()? != 0;
820 let base_ty = map_type_id(type_id_map, r.u32()? as usize)?;
821 let ptr = decode_vref(r)?;
822 let idx_count = r.u32()? as usize;
823 let mut indices = Vec::with_capacity(idx_count);
824 for _ in 0..idx_count {
825 indices.push(decode_vref(r)?);
826 }
827 InstrKind::GetElementPtr {
828 inbounds,
829 base_ty,
830 ptr,
831 indices,
832 }
833 }
834 instr_tag::TRUNC => {
835 let val = decode_vref(r)?;
836 let to = map_type_id(type_id_map, r.u32()? as usize)?;
837 InstrKind::Trunc { val, to }
838 }
839 instr_tag::ZEXT => {
840 let val = decode_vref(r)?;
841 let to = map_type_id(type_id_map, r.u32()? as usize)?;
842 InstrKind::ZExt { val, to }
843 }
844 instr_tag::SEXT => {
845 let val = decode_vref(r)?;
846 let to = map_type_id(type_id_map, r.u32()? as usize)?;
847 InstrKind::SExt { val, to }
848 }
849 instr_tag::FPTRUNC => {
850 let val = decode_vref(r)?;
851 let to = map_type_id(type_id_map, r.u32()? as usize)?;
852 InstrKind::FPTrunc { val, to }
853 }
854 instr_tag::FPEXT => {
855 let val = decode_vref(r)?;
856 let to = map_type_id(type_id_map, r.u32()? as usize)?;
857 InstrKind::FPExt { val, to }
858 }
859 instr_tag::FPTOUI => {
860 let val = decode_vref(r)?;
861 let to = map_type_id(type_id_map, r.u32()? as usize)?;
862 InstrKind::FPToUI { val, to }
863 }
864 instr_tag::FPTOSI => {
865 let val = decode_vref(r)?;
866 let to = map_type_id(type_id_map, r.u32()? as usize)?;
867 InstrKind::FPToSI { val, to }
868 }
869 instr_tag::UITOFP => {
870 let val = decode_vref(r)?;
871 let to = map_type_id(type_id_map, r.u32()? as usize)?;
872 InstrKind::UIToFP { val, to }
873 }
874 instr_tag::SITOFP => {
875 let val = decode_vref(r)?;
876 let to = map_type_id(type_id_map, r.u32()? as usize)?;
877 InstrKind::SIToFP { val, to }
878 }
879 instr_tag::PTRTOINT => {
880 let val = decode_vref(r)?;
881 let to = map_type_id(type_id_map, r.u32()? as usize)?;
882 InstrKind::PtrToInt { val, to }
883 }
884 instr_tag::INTTOPTR => {
885 let val = decode_vref(r)?;
886 let to = map_type_id(type_id_map, r.u32()? as usize)?;
887 InstrKind::IntToPtr { val, to }
888 }
889 instr_tag::BITCAST => {
890 let val = decode_vref(r)?;
891 let to = map_type_id(type_id_map, r.u32()? as usize)?;
892 InstrKind::BitCast { val, to }
893 }
894 instr_tag::ADDRSPACECAST => {
895 let val = decode_vref(r)?;
896 let to = map_type_id(type_id_map, r.u32()? as usize)?;
897 InstrKind::AddrSpaceCast { val, to }
898 }
899 instr_tag::FREEZE => InstrKind::Freeze {
900 val: decode_vref(r)?,
901 },
902 instr_tag::SELECT => InstrKind::Select {
903 cond: decode_vref(r)?,
904 then_val: decode_vref(r)?,
905 else_val: decode_vref(r)?,
906 },
907 instr_tag::PHI => {
908 let phi_ty = map_type_id(type_id_map, r.u32()? as usize)?;
909 let in_count = r.u32()? as usize;
910 let mut incoming = Vec::with_capacity(in_count);
911 for _ in 0..in_count {
912 let vr = decode_vref(r)?;
913 let bid = BlockId(r.u32()?);
914 incoming.push((vr, bid));
915 }
916 InstrKind::Phi {
917 ty: phi_ty,
918 incoming,
919 }
920 }
921 instr_tag::EXTRACTVALUE => {
922 let agg = decode_vref(r)?;
923 let idx_count = r.u32()? as usize;
924 let mut indices = Vec::with_capacity(idx_count);
925 for _ in 0..idx_count {
926 indices.push(r.u32()?);
927 }
928 InstrKind::ExtractValue {
929 aggregate: agg,
930 indices,
931 }
932 }
933 instr_tag::INSERTVALUE => {
934 let agg = decode_vref(r)?;
935 let val = decode_vref(r)?;
936 let idx_count = r.u32()? as usize;
937 let mut indices = Vec::with_capacity(idx_count);
938 for _ in 0..idx_count {
939 indices.push(r.u32()?);
940 }
941 InstrKind::InsertValue {
942 aggregate: agg,
943 val,
944 indices,
945 }
946 }
947 instr_tag::EXTRACTELEM => InstrKind::ExtractElement {
948 vec: decode_vref(r)?,
949 idx: decode_vref(r)?,
950 },
951 instr_tag::INSERTELEM => InstrKind::InsertElement {
952 vec: decode_vref(r)?,
953 val: decode_vref(r)?,
954 idx: decode_vref(r)?,
955 },
956 instr_tag::SHUFFLEVEC => {
957 let v1 = decode_vref(r)?;
958 let v2 = decode_vref(r)?;
959 let n = r.u32()? as usize;
960 let mut mask = Vec::with_capacity(n);
961 for _ in 0..n {
962 mask.push(r.i32()?);
963 }
964 InstrKind::ShuffleVector { v1, v2, mask }
965 }
966 instr_tag::CALL => {
967 let tail_tag = r.u8()?;
968 let tail = match tail_tag {
969 0 => TailCallKind::None,
970 1 => TailCallKind::Tail,
971 2 => TailCallKind::MustTail,
972 _ => TailCallKind::NoTail,
973 };
974 let callee_ty = map_type_id(type_id_map, r.u32()? as usize)?;
975 let callee = decode_vref(r)?;
976 let arg_count = r.u32()? as usize;
977 let mut args = Vec::with_capacity(arg_count);
978 for _ in 0..arg_count {
979 args.push(decode_vref(r)?);
980 }
981 InstrKind::Call {
982 tail,
983 callee_ty,
984 callee,
985 args,
986 }
987 }
988 instr_tag::RET => InstrKind::Ret {
989 val: decode_opt_vref(r)?,
990 },
991 instr_tag::BR => InstrKind::Br {
992 dest: BlockId(r.u32()?),
993 },
994 instr_tag::CONDBR => {
995 let cond = decode_vref(r)?;
996 let then_dest = BlockId(r.u32()?);
997 let else_dest = BlockId(r.u32()?);
998 InstrKind::CondBr {
999 cond,
1000 then_dest,
1001 else_dest,
1002 }
1003 }
1004 instr_tag::SWITCH => {
1005 let val = decode_vref(r)?;
1006 let default = BlockId(r.u32()?);
1007 let case_count = r.u32()? as usize;
1008 let mut cases = Vec::with_capacity(case_count);
1009 for _ in 0..case_count {
1010 let cv = decode_vref(r)?;
1011 let bd = BlockId(r.u32()?);
1012 cases.push((cv, bd));
1013 }
1014 InstrKind::Switch {
1015 val,
1016 default,
1017 cases,
1018 }
1019 }
1020 instr_tag::UNREACHABLE => InstrKind::Unreachable,
1021 other => return Err(BitcodeError::UnsupportedRecord(other)),
1022 };
1023
1024 Ok(Instruction::new(name, ty, kind))
1025}
1026
1027struct Reader<'a> {
1030 data: &'a [u8],
1031 pos: usize,
1032}
1033
1034impl<'a> Reader<'a> {
1035 fn new(data: &'a [u8]) -> Self {
1036 Reader { data, pos: 0 }
1037 }
1038
1039 fn read_bytes(&mut self, n: usize) -> Result<&[u8], BitcodeError> {
1040 if self.pos + n > self.data.len() {
1041 return Err(BitcodeError::TruncatedInput);
1042 }
1043 let slice = &self.data[self.pos..self.pos + n];
1044 self.pos += n;
1045 Ok(slice)
1046 }
1047
1048 fn u8(&mut self) -> Result<u8, BitcodeError> {
1049 let b = self.read_bytes(1)?;
1050 Ok(b[0])
1051 }
1052
1053 fn u32(&mut self) -> Result<u32, BitcodeError> {
1054 let b = self.read_bytes(4)?;
1055 Ok(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
1056 }
1057
1058 fn i32(&mut self) -> Result<i32, BitcodeError> {
1059 let b = self.read_bytes(4)?;
1060 Ok(i32::from_le_bytes([b[0], b[1], b[2], b[3]]))
1061 }
1062
1063 fn u64(&mut self) -> Result<u64, BitcodeError> {
1064 let b = self.read_bytes(8)?;
1065 Ok(u64::from_le_bytes([
1066 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
1067 ]))
1068 }
1069
1070 fn opt_string(&mut self) -> Result<Option<String>, BitcodeError> {
1073 let len = self.u32()? as usize;
1074 if len == 0 {
1075 return Ok(None);
1076 }
1077 let bytes = self.read_bytes(len)?;
1078 String::from_utf8(bytes.to_vec())
1079 .map(Some)
1080 .map_err(|e| BitcodeError::ParseError(format!("invalid UTF-8: {}", e)))
1081 }
1082
1083 fn string(&mut self) -> Result<String, BitcodeError> {
1085 let len = self.u32()? as usize;
1086 if len == 0 {
1087 return Ok(String::new());
1088 }
1089 let bytes = self.read_bytes(len)?;
1090 String::from_utf8(bytes.to_vec())
1091 .map_err(|e| BitcodeError::ParseError(format!("invalid UTF-8: {}", e)))
1092 }
1093}