1use llvm_ir::{
25 BasicBlock, ConstantData, Context, FloatKind, Function, InstrKind, Instruction, Module,
26 TypeData, ValueRef,
27};
28
29pub fn write_bitcode(ctx: &Context, module: &Module) -> Vec<u8> {
34 let mut w = Writer::default();
35
36 w.raw(b"LRIR");
38 w.u32(1); let type_count = ctx.num_types() as u32;
42 w.u32(type_count);
43 for (_, td) in ctx.types() {
44 encode_type(&mut w, td);
45 }
46
47 let const_count = ctx.constants.len() as u32;
49 w.u32(const_count);
50 for cd in &ctx.constants {
51 encode_const(&mut w, cd);
52 }
53
54 w.string(&module.name);
56
57 w.u32(module.functions.len() as u32);
59 for func in &module.functions {
60 encode_function(&mut w, func);
61 }
62
63 w.buf
64}
65
66mod type_tag {
70 pub const VOID: u8 = 0;
72 pub const INTEGER: u8 = 1;
74 pub const FLOAT: u8 = 2;
76 pub const POINTER: u8 = 3;
78 pub const ARRAY: u8 = 4;
80 pub const VECTOR: u8 = 5;
82 pub const STRUCT: u8 = 6;
84 pub const FUNCTION: u8 = 7;
86 pub const LABEL: u8 = 8;
88 pub const METADATA: u8 = 9;
90}
91
92mod float_tag {
93 pub const HALF: u8 = 0;
95 pub const BFLOAT: u8 = 1;
97 pub const SINGLE: u8 = 2;
99 pub const DOUBLE: u8 = 3;
101 pub const FP128: u8 = 4;
103 pub const X86FP80: u8 = 5;
105}
106
107fn encode_type(w: &mut Writer, td: &TypeData) {
108 match td {
109 TypeData::Void => {
110 w.u8(type_tag::VOID);
111 }
112 TypeData::Integer(bits) => {
113 w.u8(type_tag::INTEGER);
114 w.u32(*bits);
115 }
116 TypeData::Float(kind) => {
117 w.u8(type_tag::FLOAT);
118 let tag = match kind {
119 FloatKind::Half => float_tag::HALF,
120 FloatKind::BFloat => float_tag::BFLOAT,
121 FloatKind::Single => float_tag::SINGLE,
122 FloatKind::Double => float_tag::DOUBLE,
123 FloatKind::Fp128 => float_tag::FP128,
124 FloatKind::X86Fp80 => float_tag::X86FP80,
125 };
126 w.u8(tag);
127 }
128 TypeData::Pointer => {
129 w.u8(type_tag::POINTER);
130 }
131 TypeData::Array { element, len } => {
132 w.u8(type_tag::ARRAY);
133 w.u32(element.0);
134 w.u64(*len);
135 }
136 TypeData::Vector {
137 element,
138 len,
139 scalable,
140 } => {
141 w.u8(type_tag::VECTOR);
142 w.u32(element.0);
143 w.u32(*len);
144 w.u8(if *scalable { 1 } else { 0 });
145 }
146 TypeData::Struct(st) => {
147 w.u8(type_tag::STRUCT);
148 match &st.name {
150 Some(n) => w.string(n),
151 None => w.u32(0),
152 }
153 w.u8(if st.packed { 1 } else { 0 });
154 w.u32(st.fields.len() as u32);
155 for &f in &st.fields {
156 w.u32(f.0);
157 }
158 }
159 TypeData::Function(ft) => {
160 w.u8(type_tag::FUNCTION);
161 w.u32(ft.ret.0);
162 w.u8(if ft.variadic { 1 } else { 0 });
163 w.u32(ft.params.len() as u32);
164 for &p in &ft.params {
165 w.u32(p.0);
166 }
167 }
168 TypeData::Label => {
169 w.u8(type_tag::LABEL);
170 }
171 TypeData::Metadata => {
172 w.u8(type_tag::METADATA);
173 }
174 }
175}
176
177mod const_tag {
180 pub const INT: u8 = 0;
182 pub const INT_WIDE: u8 = 1;
184 pub const FLOAT: u8 = 2;
186 pub const NULL: u8 = 3;
188 pub const UNDEF: u8 = 4;
190 pub const POISON: u8 = 5;
192 pub const ZERO_INIT: u8 = 6;
194 pub const ARRAY: u8 = 7;
196 pub const STRUCT: u8 = 8;
198 pub const VECTOR: u8 = 9;
200 pub const GLOBAL_REF: u8 = 10;
202}
203
204fn encode_const(w: &mut Writer, cd: &ConstantData) {
205 match cd {
206 ConstantData::Int { ty, val } => {
207 w.u8(const_tag::INT);
208 w.u32(ty.0);
209 w.u64(*val);
210 }
211 ConstantData::IntWide { ty, words } => {
212 w.u8(const_tag::INT_WIDE);
213 w.u32(ty.0);
214 w.u32(words.len() as u32);
215 for &word in words {
216 w.u64(word);
217 }
218 }
219 ConstantData::Float { ty, bits } => {
220 w.u8(const_tag::FLOAT);
221 w.u32(ty.0);
222 w.u64(*bits);
223 }
224 ConstantData::Null(ty) => {
225 w.u8(const_tag::NULL);
226 w.u32(ty.0);
227 }
228 ConstantData::Undef(ty) => {
229 w.u8(const_tag::UNDEF);
230 w.u32(ty.0);
231 }
232 ConstantData::Poison(ty) => {
233 w.u8(const_tag::POISON);
234 w.u32(ty.0);
235 }
236 ConstantData::ZeroInitializer(ty) => {
237 w.u8(const_tag::ZERO_INIT);
238 w.u32(ty.0);
239 }
240 ConstantData::Array { ty, elements } => {
241 w.u8(const_tag::ARRAY);
242 w.u32(ty.0);
243 w.u32(elements.len() as u32);
244 for &e in elements {
245 w.u32(e.0);
246 }
247 }
248 ConstantData::Struct { ty, fields } => {
249 w.u8(const_tag::STRUCT);
250 w.u32(ty.0);
251 w.u32(fields.len() as u32);
252 for &f in fields {
253 w.u32(f.0);
254 }
255 }
256 ConstantData::Vector { ty, elements } => {
257 w.u8(const_tag::VECTOR);
258 w.u32(ty.0);
259 w.u32(elements.len() as u32);
260 for &e in elements {
261 w.u32(e.0);
262 }
263 }
264 ConstantData::GlobalRef { ty, id, name } => {
265 w.u8(const_tag::GLOBAL_REF);
266 w.u32(ty.0);
267 w.u32(id.0);
268 w.string(name);
269 }
270 }
271}
272
273mod linkage_tag {
276 pub const PRIVATE: u8 = 0;
278 pub const INTERNAL: u8 = 1;
280 pub const EXTERNAL: u8 = 2;
282 pub const WEAK: u8 = 3;
284 pub const WEAK_ODR: u8 = 4;
286 pub const LINK_ONCE: u8 = 5;
288 pub const LINK_ONCE_ODR: u8 = 6;
290 pub const COMMON: u8 = 7;
292 pub const AVAILABLE_EXTERNALLY: u8 = 8;
294}
295
296fn encode_function(w: &mut Writer, func: &Function) {
297 w.string(&func.name);
298 w.u32(func.ty.0);
299 use llvm_ir::Linkage;
301 let ltag = match func.linkage {
302 Linkage::Private => linkage_tag::PRIVATE,
303 Linkage::Internal => linkage_tag::INTERNAL,
304 Linkage::External => linkage_tag::EXTERNAL,
305 Linkage::Weak => linkage_tag::WEAK,
306 Linkage::WeakOdr => linkage_tag::WEAK_ODR,
307 Linkage::LinkOnce => linkage_tag::LINK_ONCE,
308 Linkage::LinkOnceOdr => linkage_tag::LINK_ONCE_ODR,
309 Linkage::Common => linkage_tag::COMMON,
310 Linkage::AvailableExternally => linkage_tag::AVAILABLE_EXTERNALLY,
311 };
312 w.u8(ltag);
313 w.u8(if func.is_declaration { 1 } else { 0 });
314
315 w.u32(func.args.len() as u32);
317 for arg in &func.args {
318 w.string(&arg.name);
319 w.u32(arg.ty.0);
320 w.u32(arg.index);
321 }
322
323 w.u32(func.blocks.len() as u32);
325 for bb in &func.blocks {
326 encode_block(w, bb, func);
327 }
328
329 w.u32(func.instructions.len() as u32);
331 for instr in &func.instructions {
332 encode_instr(w, instr);
333 }
334}
335
336fn encode_block(w: &mut Writer, bb: &BasicBlock, func: &Function) {
337 w.string(&bb.name);
338 w.u32(bb.body.len() as u32);
339 for &iid in &bb.body {
340 w.u32(iid.0);
341 }
342 match bb.terminator {
344 Some(tid) => w.u32(tid.0),
345 None => w.u32(0xFFFF_FFFF),
346 }
347 let _ = func;
348}
349
350mod instr_tag {
356 pub const ADD: u32 = 0;
358 pub const SUB: u32 = 1;
360 pub const MUL: u32 = 2;
362 pub const UDIV: u32 = 3;
364 pub const SDIV: u32 = 4;
366 pub const UREM: u32 = 5;
368 pub const SREM: u32 = 6;
370 pub const AND: u32 = 10;
372 pub const OR: u32 = 11;
374 pub const XOR: u32 = 12;
376 pub const SHL: u32 = 13;
378 pub const LSHR: u32 = 14;
380 pub const ASHR: u32 = 15;
382 pub const FADD: u32 = 20;
384 pub const FSUB: u32 = 21;
386 pub const FMUL: u32 = 22;
388 pub const FDIV: u32 = 23;
390 pub const FREM: u32 = 24;
392 pub const FNEG: u32 = 25;
394 pub const ICMP: u32 = 30;
396 pub const FCMP: u32 = 31;
398 pub const ALLOCA: u32 = 40;
400 pub const LOAD: u32 = 41;
402 pub const STORE: u32 = 42;
404 pub const GEP: u32 = 43;
406 pub const TRUNC: u32 = 50;
408 pub const ZEXT: u32 = 51;
410 pub const SEXT: u32 = 52;
412 pub const FPTRUNC: u32 = 53;
414 pub const FPEXT: u32 = 54;
416 pub const FPTOUI: u32 = 55;
418 pub const FPTOSI: u32 = 56;
420 pub const UITOFP: u32 = 57;
422 pub const SITOFP: u32 = 58;
424 pub const PTRTOINT: u32 = 59;
426 pub const INTTOPTR: u32 = 60;
428 pub const BITCAST: u32 = 61;
430 pub const ADDRSPACECAST: u32 = 62;
432 pub const FREEZE: u32 = 63;
434 pub const SELECT: u32 = 70;
436 pub const PHI: u32 = 71;
438 pub const EXTRACTVALUE: u32 = 72;
440 pub const INSERTVALUE: u32 = 73;
442 pub const EXTRACTELEM: u32 = 74;
444 pub const INSERTELEM: u32 = 75;
446 pub const SHUFFLEVEC: u32 = 76;
448 pub const CALL: u32 = 80;
450 pub const RET: u32 = 90;
452 pub const BR: u32 = 91;
454 pub const CONDBR: u32 = 92;
456 pub const SWITCH: u32 = 93;
458 pub const UNREACHABLE: u32 = 94;
460}
461
462fn encode_vref(w: &mut Writer, vr: &ValueRef) {
463 match vr {
464 ValueRef::Instruction(id) => {
465 w.u8(0);
466 w.u32(id.0);
467 }
468 ValueRef::Argument(id) => {
469 w.u8(1);
470 w.u32(id.0);
471 }
472 ValueRef::Constant(id) => {
473 w.u8(2);
474 w.u32(id.0);
475 }
476 ValueRef::Global(id) => {
477 w.u8(3);
478 w.u32(id.0);
479 }
480 }
481}
482
483fn encode_opt_vref(w: &mut Writer, ovr: &Option<ValueRef>) {
484 match ovr {
485 Some(vr) => {
486 w.u8(1);
487 encode_vref(w, vr);
488 }
489 None => {
490 w.u8(0);
491 }
492 }
493}
494
495fn encode_instr(w: &mut Writer, instr: &Instruction) {
496 match &instr.name {
498 Some(n) => w.string(n),
499 None => w.u32(0),
500 }
501 w.u32(instr.ty.0);
503
504 use InstrKind::*;
506 match &instr.kind {
507 Add {
508 flags, lhs, rhs, ..
509 } => {
510 w.u32(instr_tag::ADD);
511 w.u8(if flags.nuw { 1 } else { 0 });
512 w.u8(if flags.nsw { 1 } else { 0 });
513 encode_vref(w, lhs);
514 encode_vref(w, rhs);
515 }
516 Sub {
517 flags, lhs, rhs, ..
518 } => {
519 w.u32(instr_tag::SUB);
520 w.u8(if flags.nuw { 1 } else { 0 });
521 w.u8(if flags.nsw { 1 } else { 0 });
522 encode_vref(w, lhs);
523 encode_vref(w, rhs);
524 }
525 Mul {
526 flags, lhs, rhs, ..
527 } => {
528 w.u32(instr_tag::MUL);
529 w.u8(if flags.nuw { 1 } else { 0 });
530 w.u8(if flags.nsw { 1 } else { 0 });
531 encode_vref(w, lhs);
532 encode_vref(w, rhs);
533 }
534 UDiv { exact, lhs, rhs } => {
535 w.u32(instr_tag::UDIV);
536 w.u8(if *exact { 1 } else { 0 });
537 encode_vref(w, lhs);
538 encode_vref(w, rhs);
539 }
540 SDiv { exact, lhs, rhs } => {
541 w.u32(instr_tag::SDIV);
542 w.u8(if *exact { 1 } else { 0 });
543 encode_vref(w, lhs);
544 encode_vref(w, rhs);
545 }
546 URem { lhs, rhs } => {
547 w.u32(instr_tag::UREM);
548 encode_vref(w, lhs);
549 encode_vref(w, rhs);
550 }
551 SRem { lhs, rhs } => {
552 w.u32(instr_tag::SREM);
553 encode_vref(w, lhs);
554 encode_vref(w, rhs);
555 }
556 And { lhs, rhs } => {
557 w.u32(instr_tag::AND);
558 encode_vref(w, lhs);
559 encode_vref(w, rhs);
560 }
561 Or { lhs, rhs } => {
562 w.u32(instr_tag::OR);
563 encode_vref(w, lhs);
564 encode_vref(w, rhs);
565 }
566 Xor { lhs, rhs } => {
567 w.u32(instr_tag::XOR);
568 encode_vref(w, lhs);
569 encode_vref(w, rhs);
570 }
571 Shl {
572 flags, lhs, rhs, ..
573 } => {
574 w.u32(instr_tag::SHL);
575 w.u8(if flags.nuw { 1 } else { 0 });
576 w.u8(if flags.nsw { 1 } else { 0 });
577 encode_vref(w, lhs);
578 encode_vref(w, rhs);
579 }
580 LShr {
581 exact, lhs, rhs, ..
582 } => {
583 w.u32(instr_tag::LSHR);
584 w.u8(if *exact { 1 } else { 0 });
585 encode_vref(w, lhs);
586 encode_vref(w, rhs);
587 }
588 AShr {
589 exact, lhs, rhs, ..
590 } => {
591 w.u32(instr_tag::ASHR);
592 w.u8(if *exact { 1 } else { 0 });
593 encode_vref(w, lhs);
594 encode_vref(w, rhs);
595 }
596 FAdd { lhs, rhs, .. } => {
597 w.u32(instr_tag::FADD);
598 encode_vref(w, lhs);
599 encode_vref(w, rhs);
600 }
601 FSub { lhs, rhs, .. } => {
602 w.u32(instr_tag::FSUB);
603 encode_vref(w, lhs);
604 encode_vref(w, rhs);
605 }
606 FMul { lhs, rhs, .. } => {
607 w.u32(instr_tag::FMUL);
608 encode_vref(w, lhs);
609 encode_vref(w, rhs);
610 }
611 FDiv { lhs, rhs, .. } => {
612 w.u32(instr_tag::FDIV);
613 encode_vref(w, lhs);
614 encode_vref(w, rhs);
615 }
616 FRem { lhs, rhs, .. } => {
617 w.u32(instr_tag::FREM);
618 encode_vref(w, lhs);
619 encode_vref(w, rhs);
620 }
621 FNeg { operand, .. } => {
622 w.u32(instr_tag::FNEG);
623 encode_vref(w, operand);
624 }
625 ICmp { pred, lhs, rhs } => {
626 w.u32(instr_tag::ICMP);
627 w.u8(encode_int_pred(*pred));
628 encode_vref(w, lhs);
629 encode_vref(w, rhs);
630 }
631 FCmp { pred, lhs, rhs, .. } => {
632 w.u32(instr_tag::FCMP);
633 w.u8(encode_float_pred(*pred));
634 encode_vref(w, lhs);
635 encode_vref(w, rhs);
636 }
637 Alloca {
638 alloc_ty,
639 num_elements,
640 align,
641 } => {
642 w.u32(instr_tag::ALLOCA);
643 w.u32(alloc_ty.0);
644 encode_opt_vref(w, num_elements);
645 encode_opt_u32(w, *align);
646 }
647 Load {
648 ty,
649 ptr,
650 align,
651 volatile,
652 } => {
653 w.u32(instr_tag::LOAD);
654 w.u32(ty.0);
655 encode_vref(w, ptr);
656 encode_opt_u32(w, *align);
657 w.u8(if *volatile { 1 } else { 0 });
658 }
659 Store {
660 val,
661 ptr,
662 align,
663 volatile,
664 } => {
665 w.u32(instr_tag::STORE);
666 encode_vref(w, val);
667 encode_vref(w, ptr);
668 encode_opt_u32(w, *align);
669 w.u8(if *volatile { 1 } else { 0 });
670 }
671 GetElementPtr {
672 inbounds,
673 base_ty,
674 ptr,
675 indices,
676 } => {
677 w.u32(instr_tag::GEP);
678 w.u8(if *inbounds { 1 } else { 0 });
679 w.u32(base_ty.0);
680 encode_vref(w, ptr);
681 w.u32(indices.len() as u32);
682 for idx in indices {
683 encode_vref(w, idx);
684 }
685 }
686 Trunc { val, to } => {
687 w.u32(instr_tag::TRUNC);
688 encode_vref(w, val);
689 w.u32(to.0);
690 }
691 ZExt { val, to } => {
692 w.u32(instr_tag::ZEXT);
693 encode_vref(w, val);
694 w.u32(to.0);
695 }
696 SExt { val, to } => {
697 w.u32(instr_tag::SEXT);
698 encode_vref(w, val);
699 w.u32(to.0);
700 }
701 FPTrunc { val, to } => {
702 w.u32(instr_tag::FPTRUNC);
703 encode_vref(w, val);
704 w.u32(to.0);
705 }
706 FPExt { val, to } => {
707 w.u32(instr_tag::FPEXT);
708 encode_vref(w, val);
709 w.u32(to.0);
710 }
711 FPToUI { val, to } => {
712 w.u32(instr_tag::FPTOUI);
713 encode_vref(w, val);
714 w.u32(to.0);
715 }
716 FPToSI { val, to } => {
717 w.u32(instr_tag::FPTOSI);
718 encode_vref(w, val);
719 w.u32(to.0);
720 }
721 UIToFP { val, to } => {
722 w.u32(instr_tag::UITOFP);
723 encode_vref(w, val);
724 w.u32(to.0);
725 }
726 SIToFP { val, to } => {
727 w.u32(instr_tag::SITOFP);
728 encode_vref(w, val);
729 w.u32(to.0);
730 }
731 PtrToInt { val, to } => {
732 w.u32(instr_tag::PTRTOINT);
733 encode_vref(w, val);
734 w.u32(to.0);
735 }
736 IntToPtr { val, to } => {
737 w.u32(instr_tag::INTTOPTR);
738 encode_vref(w, val);
739 w.u32(to.0);
740 }
741 BitCast { val, to } => {
742 w.u32(instr_tag::BITCAST);
743 encode_vref(w, val);
744 w.u32(to.0);
745 }
746 AddrSpaceCast { val, to } => {
747 w.u32(instr_tag::ADDRSPACECAST);
748 encode_vref(w, val);
749 w.u32(to.0);
750 }
751 Freeze { val } => {
752 w.u32(instr_tag::FREEZE);
753 encode_vref(w, val);
754 }
755 Select {
756 cond,
757 then_val,
758 else_val,
759 } => {
760 w.u32(instr_tag::SELECT);
761 encode_vref(w, cond);
762 encode_vref(w, then_val);
763 encode_vref(w, else_val);
764 }
765 Phi { ty, incoming } => {
766 w.u32(instr_tag::PHI);
767 w.u32(ty.0);
768 w.u32(incoming.len() as u32);
769 for (vr, bid) in incoming {
770 encode_vref(w, vr);
771 w.u32(bid.0);
772 }
773 }
774 ExtractValue { aggregate, indices } => {
775 w.u32(instr_tag::EXTRACTVALUE);
776 encode_vref(w, aggregate);
777 w.u32(indices.len() as u32);
778 for &i in indices {
779 w.u32(i);
780 }
781 }
782 InsertValue {
783 aggregate,
784 val,
785 indices,
786 } => {
787 w.u32(instr_tag::INSERTVALUE);
788 encode_vref(w, aggregate);
789 encode_vref(w, val);
790 w.u32(indices.len() as u32);
791 for &i in indices {
792 w.u32(i);
793 }
794 }
795 ExtractElement { vec, idx } => {
796 w.u32(instr_tag::EXTRACTELEM);
797 encode_vref(w, vec);
798 encode_vref(w, idx);
799 }
800 InsertElement { vec, val, idx } => {
801 w.u32(instr_tag::INSERTELEM);
802 encode_vref(w, vec);
803 encode_vref(w, val);
804 encode_vref(w, idx);
805 }
806 ShuffleVector { v1, v2, mask } => {
807 w.u32(instr_tag::SHUFFLEVEC);
808 encode_vref(w, v1);
809 encode_vref(w, v2);
810 w.u32(mask.len() as u32);
811 for &m in mask {
812 w.i32(m);
813 }
814 }
815 Call {
816 tail,
817 callee_ty,
818 callee,
819 args,
820 } => {
821 w.u32(instr_tag::CALL);
822 use llvm_ir::TailCallKind;
823 let tail_tag = match tail {
824 TailCallKind::None => 0u8,
825 TailCallKind::Tail => 1,
826 TailCallKind::MustTail => 2,
827 TailCallKind::NoTail => 3,
828 };
829 w.u8(tail_tag);
830 w.u32(callee_ty.0);
831 encode_vref(w, callee);
832 w.u32(args.len() as u32);
833 for arg in args {
834 encode_vref(w, arg);
835 }
836 }
837 Ret { val } => {
838 w.u32(instr_tag::RET);
839 encode_opt_vref(w, val);
840 }
841 Br { dest } => {
842 w.u32(instr_tag::BR);
843 w.u32(dest.0);
844 }
845 CondBr {
846 cond,
847 then_dest,
848 else_dest,
849 } => {
850 w.u32(instr_tag::CONDBR);
851 encode_vref(w, cond);
852 w.u32(then_dest.0);
853 w.u32(else_dest.0);
854 }
855 Switch {
856 val,
857 default,
858 cases,
859 } => {
860 w.u32(instr_tag::SWITCH);
861 encode_vref(w, val);
862 w.u32(default.0);
863 w.u32(cases.len() as u32);
864 for (cv, bd) in cases {
865 encode_vref(w, cv);
866 w.u32(bd.0);
867 }
868 }
869 Unreachable => {
870 w.u32(instr_tag::UNREACHABLE);
871 }
872 }
873}
874
875fn encode_opt_u32(w: &mut Writer, v: Option<u32>) {
876 match v {
877 Some(x) => {
878 w.u8(1);
879 w.u32(x);
880 }
881 None => {
882 w.u8(0);
883 }
884 }
885}
886
887fn encode_int_pred(pred: llvm_ir::IntPredicate) -> u8 {
888 use llvm_ir::IntPredicate::*;
889 match pred {
890 Eq => 0,
891 Ne => 1,
892 Ugt => 2,
893 Uge => 3,
894 Ult => 4,
895 Ule => 5,
896 Sgt => 6,
897 Sge => 7,
898 Slt => 8,
899 Sle => 9,
900 }
901}
902
903fn encode_float_pred(pred: llvm_ir::FloatPredicate) -> u8 {
904 use llvm_ir::FloatPredicate::*;
905 match pred {
906 False => 0,
907 Oeq => 1,
908 Ogt => 2,
909 Oge => 3,
910 Olt => 4,
911 Ole => 5,
912 One => 6,
913 Ord => 7,
914 Uno => 8,
915 Ueq => 9,
916 Ugt => 10,
917 Uge => 11,
918 Ult => 12,
919 Ule => 13,
920 Une => 14,
921 True => 15,
922 }
923}
924
925#[derive(Default)]
928struct Writer {
929 buf: Vec<u8>,
930}
931
932impl Writer {
933 fn raw(&mut self, b: &[u8]) {
934 self.buf.extend_from_slice(b);
935 }
936 fn u8(&mut self, v: u8) {
937 self.buf.push(v);
938 }
939 fn u32(&mut self, v: u32) {
940 self.buf.extend_from_slice(&v.to_le_bytes());
941 }
942 fn i32(&mut self, v: i32) {
943 self.buf.extend_from_slice(&v.to_le_bytes());
944 }
945 fn u64(&mut self, v: u64) {
946 self.buf.extend_from_slice(&v.to_le_bytes());
947 }
948 fn string(&mut self, s: &str) {
950 self.u32(s.len() as u32);
951 self.raw(s.as_bytes());
952 }
953}
954
955pub use write_bitcode as write;