1#![warn(missing_docs)]
4
5use super::ref_list::{EntryRef, RefList};
6use crate::std::{borrow::ToOwned, collections::BTreeMap, string::String, vec::Vec};
7use parity_wasm::elements;
8
9#[derive(Debug)]
14pub enum ImportedOrDeclared<T = ()> {
15 Imported(String, String),
17 Declared(T),
19}
20
21impl<T> From<&elements::ImportEntry> for ImportedOrDeclared<T> {
22 fn from(v: &elements::ImportEntry) -> Self {
23 ImportedOrDeclared::Imported(v.module().to_owned(), v.field().to_owned())
24 }
25}
26
27#[derive(Debug)]
29pub enum Error {
30 InconsistentSource,
32 Format(elements::Error),
34 DetachedEntry,
36}
37
38pub type FuncOrigin = ImportedOrDeclared<FuncBody>;
40pub type GlobalOrigin = ImportedOrDeclared<Vec<Instruction>>;
42pub type MemoryOrigin = ImportedOrDeclared;
44pub type TableOrigin = ImportedOrDeclared;
46
47#[derive(Debug)]
52pub struct FuncBody {
53 pub locals: Vec<elements::Local>,
54 pub code: Vec<Instruction>,
55}
56
57#[derive(Debug)]
62pub struct Func {
63 pub type_ref: EntryRef<elements::Type>,
65 pub origin: FuncOrigin,
67}
68
69#[derive(Debug)]
74pub struct Global {
75 pub content: elements::ValueType,
76 pub is_mut: bool,
77 pub origin: GlobalOrigin,
78}
79
80#[derive(Debug)]
85pub enum Instruction {
86 Plain(elements::Instruction),
88 Call(EntryRef<Func>),
90 CallIndirect(EntryRef<elements::Type>, u8),
92 GetGlobal(EntryRef<Global>),
94 SetGlobal(EntryRef<Global>),
96}
97
98#[derive(Debug)]
103pub struct Memory {
104 pub limits: elements::ResizableLimits,
106 pub origin: MemoryOrigin,
108}
109
110#[derive(Debug)]
115pub struct Table {
116 pub limits: elements::ResizableLimits,
118 pub origin: TableOrigin,
120}
121
122#[derive(Debug)]
126pub enum SegmentLocation {
127 Passive,
129 Default(Vec<Instruction>),
131 WithIndex(u32, Vec<Instruction>),
133}
134
135#[derive(Debug)]
137pub struct DataSegment {
138 pub location: SegmentLocation,
140 pub value: Vec<u8>,
142}
143
144#[derive(Debug)]
146pub struct ElementSegment {
147 pub location: SegmentLocation,
149 pub value: Vec<EntryRef<Func>>,
151}
152
153#[derive(Debug)]
158pub enum ExportLocal {
159 Func(EntryRef<Func>),
161 Global(EntryRef<Global>),
163 Table(EntryRef<Table>),
165 Memory(EntryRef<Memory>),
167}
168
169#[derive(Debug)]
171pub struct Export {
172 pub name: String,
174 pub local: ExportLocal,
176}
177
178#[derive(Debug, Default)]
180pub struct Module {
181 pub types: RefList<elements::Type>,
183 pub funcs: RefList<Func>,
185 pub memory: RefList<Memory>,
187 pub tables: RefList<Table>,
189 pub globals: RefList<Global>,
191 pub start: Option<EntryRef<Func>>,
193 pub exports: Vec<Export>,
195 pub elements: Vec<ElementSegment>,
197 pub data: Vec<DataSegment>,
199 pub other: BTreeMap<usize, elements::Section>,
201}
202
203impl Module {
204 fn map_instructions(&self, instructions: &[elements::Instruction]) -> Vec<Instruction> {
205 use parity_wasm::elements::Instruction::*;
206 instructions
207 .iter()
208 .map(|instruction| match instruction {
209 Call(func_idx) => Instruction::Call(self.funcs.clone_ref(*func_idx as usize)),
210 CallIndirect(type_idx, arg2) =>
211 Instruction::CallIndirect(self.types.clone_ref(*type_idx as usize), *arg2),
212 SetGlobal(global_idx) =>
213 Instruction::SetGlobal(self.globals.clone_ref(*global_idx as usize)),
214 GetGlobal(global_idx) =>
215 Instruction::GetGlobal(self.globals.clone_ref(*global_idx as usize)),
216 other_instruction => Instruction::Plain(other_instruction.clone()),
217 })
218 .collect()
219 }
220
221 fn generate_instructions(&self, instructions: &[Instruction]) -> Vec<elements::Instruction> {
222 use parity_wasm::elements::Instruction::*;
223 instructions
224 .iter()
225 .map(|instruction| match instruction {
226 Instruction::Call(func_ref) =>
227 Call(func_ref.order().expect("detached instruction!") as u32),
228 Instruction::CallIndirect(type_ref, arg2) =>
229 CallIndirect(type_ref.order().expect("detached instruction!") as u32, *arg2),
230 Instruction::SetGlobal(global_ref) =>
231 SetGlobal(global_ref.order().expect("detached instruction!") as u32),
232 Instruction::GetGlobal(global_ref) =>
233 GetGlobal(global_ref.order().expect("detached instruction!") as u32),
234 Instruction::Plain(plain) => plain.clone(),
235 })
236 .collect()
237 }
238
239 pub fn from_elements(module: &elements::Module) -> Result<Self, Error> {
241 let mut res = Module::default();
242 let mut imported_functions = 0;
243
244 for (idx, section) in module.sections().iter().enumerate() {
245 match section {
246 elements::Section::Type(type_section) => {
247 res.types = RefList::from_slice(type_section.types());
248 },
249 elements::Section::Import(import_section) =>
250 for entry in import_section.entries() {
251 match *entry.external() {
252 elements::External::Function(f) => {
253 res.funcs.push(Func {
254 type_ref: res
255 .types
256 .get(f as usize)
257 .ok_or(Error::InconsistentSource)?
258 .clone(),
259 origin: entry.into(),
260 });
261 imported_functions += 1;
262 },
263 elements::External::Memory(m) => {
264 res.memory
265 .push(Memory { limits: *m.limits(), origin: entry.into() });
266 },
267 elements::External::Global(g) => {
268 res.globals.push(Global {
269 content: g.content_type(),
270 is_mut: g.is_mutable(),
271 origin: entry.into(),
272 });
273 },
274 elements::External::Table(t) => {
275 res.tables
276 .push(Table { limits: *t.limits(), origin: entry.into() });
277 },
278 };
279 },
280 elements::Section::Function(function_section) => {
281 for f in function_section.entries() {
282 res.funcs.push(Func {
283 type_ref: res
284 .types
285 .get(f.type_ref() as usize)
286 .ok_or(Error::InconsistentSource)?
287 .clone(),
288 origin: ImportedOrDeclared::Declared(FuncBody {
289 locals: Vec::new(),
290 code: Vec::new(),
292 }),
293 });
294 }
295 },
296 elements::Section::Table(table_section) =>
297 for t in table_section.entries() {
298 res.tables.push(Table {
299 limits: *t.limits(),
300 origin: ImportedOrDeclared::Declared(()),
301 });
302 },
303 elements::Section::Memory(table_section) =>
304 for t in table_section.entries() {
305 res.memory.push(Memory {
306 limits: *t.limits(),
307 origin: ImportedOrDeclared::Declared(()),
308 });
309 },
310 elements::Section::Global(global_section) =>
311 for g in global_section.entries() {
312 let init_code = res.map_instructions(g.init_expr().code());
313 res.globals.push(Global {
314 content: g.global_type().content_type(),
315 is_mut: g.global_type().is_mutable(),
316 origin: ImportedOrDeclared::Declared(init_code),
317 });
318 },
319 elements::Section::Export(export_section) =>
320 for e in export_section.entries() {
321 let local = match e.internal() {
322 elements::Internal::Function(func_idx) =>
323 ExportLocal::Func(res.funcs.clone_ref(*func_idx as usize)),
324 elements::Internal::Global(global_idx) =>
325 ExportLocal::Global(res.globals.clone_ref(*global_idx as usize)),
326 elements::Internal::Memory(mem_idx) =>
327 ExportLocal::Memory(res.memory.clone_ref(*mem_idx as usize)),
328 elements::Internal::Table(table_idx) =>
329 ExportLocal::Table(res.tables.clone_ref(*table_idx as usize)),
330 };
331
332 res.exports.push(Export { local, name: e.field().to_owned() })
333 },
334 elements::Section::Start(start_func) => {
335 res.start = Some(res.funcs.clone_ref(*start_func as usize));
336 },
337 elements::Section::Element(element_section) => {
338 for element_segment in element_section.entries() {
339 let init_expr = element_segment
349 .offset()
350 .as_ref()
351 .expect("parity-wasm is compiled without bulk-memory operations")
352 .code();
353 let location = SegmentLocation::Default(res.map_instructions(init_expr));
354
355 let funcs_map = element_segment
356 .members()
357 .iter()
358 .map(|idx| res.funcs.clone_ref(*idx as usize))
359 .collect::<Vec<EntryRef<Func>>>();
360
361 res.elements.push(ElementSegment { value: funcs_map, location });
362 }
363 },
364 elements::Section::Code(code_section) => {
365 for (idx, func_body) in code_section.bodies().iter().enumerate() {
366 let code = res.map_instructions(func_body.code().elements());
367 let mut func = res.funcs.get_ref(imported_functions + idx).write();
368 match &mut func.origin {
369 ImportedOrDeclared::Declared(body) => {
370 body.code = code;
371 body.locals = func_body.locals().to_vec();
372 },
373 _ => return Err(Error::InconsistentSource),
374 }
375 }
376 },
377 elements::Section::Data(data_section) => {
378 for data_segment in data_section.entries() {
379 let init_expr = data_segment
382 .offset()
383 .as_ref()
384 .expect("parity-wasm is compiled without bulk-memory operations")
385 .code();
386 let location = SegmentLocation::Default(res.map_instructions(init_expr));
387
388 res.data
389 .push(DataSegment { value: data_segment.value().to_vec(), location });
390 }
391 },
392 _ => {
393 res.other.insert(idx, section.clone());
394 },
395 }
396 }
397
398 Ok(res)
399 }
400
401 pub fn generate(&self) -> Result<elements::Module, Error> {
403 use self::ImportedOrDeclared::*;
404
405 let mut idx = 0;
406 let mut sections = Vec::new();
407
408 custom_round(&self.other, &mut idx, &mut sections);
409
410 if !self.types.is_empty() {
411 let mut type_section = elements::TypeSection::default();
413 {
414 let types = type_section.types_mut();
415
416 for type_entry in self.types.iter() {
417 types.push(type_entry.read().clone())
418 }
419 }
420 sections.push(elements::Section::Type(type_section));
421 idx += 1;
422
423 custom_round(&self.other, &mut idx, &mut sections);
424 }
425
426 let mut import_section = elements::ImportSection::default();
428
429 let add = {
430 let imports = import_section.entries_mut();
431 for func in self.funcs.iter() {
432 match &func.read().origin {
433 Imported(module, field) => imports.push(elements::ImportEntry::new(
434 module.to_owned(),
435 field.to_owned(),
436 elements::External::Function(
437 func.read().type_ref.order().ok_or(Error::DetachedEntry)? as u32,
438 ),
439 )),
440 _ => continue,
441 }
442 }
443
444 for global in self.globals.iter() {
445 match &global.read().origin {
446 Imported(module, field) => imports.push(elements::ImportEntry::new(
447 module.to_owned(),
448 field.to_owned(),
449 elements::External::Global(elements::GlobalType::new(
450 global.read().content,
451 global.read().is_mut,
452 )),
453 )),
454 _ => continue,
455 }
456 }
457
458 for memory in self.memory.iter() {
459 match &memory.read().origin {
460 Imported(module, field) => imports.push(elements::ImportEntry::new(
461 module.to_owned(),
462 field.to_owned(),
463 elements::External::Memory(elements::MemoryType::new(
464 memory.read().limits.initial(),
465 memory.read().limits.maximum(),
466 )),
467 )),
468 _ => continue,
469 }
470 }
471
472 for table in self.tables.iter() {
473 match &table.read().origin {
474 Imported(module, field) => imports.push(elements::ImportEntry::new(
475 module.to_owned(),
476 field.to_owned(),
477 elements::External::Table(elements::TableType::new(
478 table.read().limits.initial(),
479 table.read().limits.maximum(),
480 )),
481 )),
482 _ => continue,
483 }
484 }
485 !imports.is_empty()
486 };
487
488 if add {
489 sections.push(elements::Section::Import(import_section));
490 idx += 1;
491 custom_round(&self.other, &mut idx, &mut sections);
492 }
493
494 if !self.funcs.is_empty() {
495 let mut func_section = elements::FunctionSection::default();
497 {
498 let funcs = func_section.entries_mut();
499
500 for func in self.funcs.iter() {
501 match func.read().origin {
502 Declared(_) => {
503 funcs.push(elements::Func::new(
504 func.read().type_ref.order().ok_or(Error::DetachedEntry)? as u32,
505 ));
506 },
507 _ => continue,
508 }
509 }
510 }
511 sections.push(elements::Section::Function(func_section));
512 idx += 1;
513
514 custom_round(&self.other, &mut idx, &mut sections);
515 }
516
517 if !self.tables.is_empty() {
518 let mut table_section = elements::TableSection::default();
520 {
521 let tables = table_section.entries_mut();
522
523 for table in self.tables.iter() {
524 match table.read().origin {
525 Declared(_) => {
526 tables.push(elements::TableType::new(
527 table.read().limits.initial(),
528 table.read().limits.maximum(),
529 ));
530 },
531 _ => continue,
532 }
533 }
534 }
535 sections.push(elements::Section::Table(table_section));
536 idx += 1;
537
538 custom_round(&self.other, &mut idx, &mut sections);
539 }
540
541 if !self.memory.is_empty() {
542 let mut memory_section = elements::MemorySection::default();
544 {
545 let memories = memory_section.entries_mut();
546
547 for memory in self.memory.iter() {
548 match memory.read().origin {
549 Declared(_) => {
550 memories.push(elements::MemoryType::new(
551 memory.read().limits.initial(),
552 memory.read().limits.maximum(),
553 ));
554 },
555 _ => continue,
556 }
557 }
558 }
559 sections.push(elements::Section::Memory(memory_section));
560 idx += 1;
561
562 custom_round(&self.other, &mut idx, &mut sections);
563 }
564
565 if !self.globals.is_empty() {
566 let mut global_section = elements::GlobalSection::default();
568 {
569 let globals = global_section.entries_mut();
570
571 for global in self.globals.iter() {
572 match &global.read().origin {
573 Declared(init_code) => {
574 globals.push(elements::GlobalEntry::new(
575 elements::GlobalType::new(
576 global.read().content,
577 global.read().is_mut,
578 ),
579 elements::InitExpr::new(self.generate_instructions(&init_code[..])),
580 ));
581 },
582 _ => continue,
583 }
584 }
585 }
586 sections.push(elements::Section::Global(global_section));
587 idx += 1;
588
589 custom_round(&self.other, &mut idx, &mut sections);
590 }
591
592 if !self.exports.is_empty() {
593 let mut export_section = elements::ExportSection::default();
595 {
596 let exports = export_section.entries_mut();
597
598 for export in self.exports.iter() {
599 let internal = match &export.local {
600 ExportLocal::Func(func_ref) => elements::Internal::Function(
601 func_ref.order().ok_or(Error::DetachedEntry)? as u32,
602 ),
603 ExportLocal::Global(global_ref) => elements::Internal::Global(
604 global_ref.order().ok_or(Error::DetachedEntry)? as u32,
605 ),
606 ExportLocal::Table(table_ref) => elements::Internal::Table(
607 table_ref.order().ok_or(Error::DetachedEntry)? as u32,
608 ),
609 ExportLocal::Memory(memory_ref) => elements::Internal::Memory(
610 memory_ref.order().ok_or(Error::DetachedEntry)? as u32,
611 ),
612 };
613
614 exports.push(elements::ExportEntry::new(export.name.to_owned(), internal));
615 }
616 }
617 sections.push(elements::Section::Export(export_section));
618 idx += 1;
619
620 custom_round(&self.other, &mut idx, &mut sections);
621 }
622
623 if let Some(func_ref) = &self.start {
624 sections.push(elements::Section::Start(
626 func_ref.order().ok_or(Error::DetachedEntry)? as u32
627 ));
628 }
629
630 if !self.elements.is_empty() {
631 let mut element_section = elements::ElementSection::default();
633 {
634 let element_segments = element_section.entries_mut();
635
636 for element in self.elements.iter() {
637 match &element.location {
638 SegmentLocation::Default(offset_expr) => {
639 let mut elements_map = Vec::new();
640 for f in element.value.iter() {
641 elements_map.push(f.order().ok_or(Error::DetachedEntry)? as u32);
642 }
643
644 element_segments.push(elements::ElementSegment::new(
645 0,
646 Some(elements::InitExpr::new(
647 self.generate_instructions(&offset_expr[..]),
648 )),
649 elements_map,
650 ));
651 },
652 _ => unreachable!("Other segment location types are never added"),
653 }
654 }
655 }
656
657 sections.push(elements::Section::Element(element_section));
658 idx += 1;
659
660 custom_round(&self.other, &mut idx, &mut sections);
661 }
662
663 if !self.funcs.is_empty() {
664 let mut code_section = elements::CodeSection::default();
666 {
667 let funcs = code_section.bodies_mut();
668
669 for func in self.funcs.iter() {
670 match &func.read().origin {
671 Declared(body) => {
672 funcs.push(elements::FuncBody::new(
673 body.locals.clone(),
674 elements::Instructions::new(
675 self.generate_instructions(&body.code[..]),
676 ),
677 ));
678 },
679 _ => continue,
680 }
681 }
682 }
683 sections.push(elements::Section::Code(code_section));
684 idx += 1;
685
686 custom_round(&self.other, &mut idx, &mut sections);
687 }
688
689 if !self.data.is_empty() {
690 let mut data_section = elements::DataSection::default();
692 {
693 let data_segments = data_section.entries_mut();
694
695 for data_entry in self.data.iter() {
696 match &data_entry.location {
697 SegmentLocation::Default(offset_expr) => {
698 data_segments.push(elements::DataSegment::new(
699 0,
700 Some(elements::InitExpr::new(
701 self.generate_instructions(&offset_expr[..]),
702 )),
703 data_entry.value.clone(),
704 ));
705 },
706 _ => unreachable!("Other segment location types are never added"),
707 }
708 }
709 }
710
711 sections.push(elements::Section::Data(data_section));
712 idx += 1;
713
714 custom_round(&self.other, &mut idx, &mut sections);
715 }
716
717 Ok(elements::Module::new(sections))
718 }
719}
720
721fn custom_round(
722 map: &BTreeMap<usize, elements::Section>,
723 idx: &mut usize,
724 sections: &mut Vec<elements::Section>,
725) {
726 while let Some(other_section) = map.get(idx) {
727 sections.push(other_section.clone());
728 *idx += 1;
729 }
730}
731
732pub fn parse(wasm: &[u8]) -> Result<Module, Error> {
734 Module::from_elements(&::parity_wasm::deserialize_buffer(wasm).map_err(Error::Format)?)
735}
736
737pub fn generate(f: &Module) -> Result<Vec<u8>, Error> {
739 let pm = f.generate()?;
740 ::parity_wasm::serialize(pm).map_err(Error::Format)
741}
742
743#[cfg(test)]
744mod tests {
745 use indoc::indoc;
746 use parity_wasm::elements;
747
748 fn load_sample(wat: &'static str) -> super::Module {
749 super::parse(&wabt::wat2wasm(wat).expect("faled to parse wat!")[..])
750 .expect("error making representation")
751 }
752
753 fn validate_sample(module: &super::Module) {
754 let binary = super::generate(module).expect("Failed to generate binary");
755 wabt::Module::read_binary(&binary, &Default::default())
756 .expect("Wabt failed to read final binary")
757 .validate()
758 .expect("Invalid module");
759 }
760
761 #[test]
762 fn smoky() {
763 let sample = load_sample(indoc!(
764 r#"
765 (module
766 (type (func))
767 (func (type 0))
768 (memory 0 1)
769 (export "simple" (func 0)))"#
770 ));
771
772 assert_eq!(sample.types.len(), 1);
773 assert_eq!(sample.funcs.len(), 1);
774 assert_eq!(sample.tables.len(), 0);
775 assert_eq!(sample.memory.len(), 1);
776 assert_eq!(sample.exports.len(), 1);
777
778 assert_eq!(sample.types.get_ref(0).link_count(), 1);
779 assert_eq!(sample.funcs.get_ref(0).link_count(), 1);
780 }
781
782 #[test]
783 fn table() {
784 let mut sample = load_sample(indoc!(
785 r#"
786 (module
787 (import "env" "foo" (func $foo))
788 (func (param i32)
789 get_local 0
790 i32.const 0
791 call $i32.add
792 drop
793 )
794 (func $i32.add (export "i32.add") (param i32 i32) (result i32)
795 get_local 0
796 get_local 1
797 i32.add
798 )
799 (table 10 anyfunc)
800
801 ;; Refer all types of functions: imported, defined not exported and defined exported.
802 (elem (i32.const 0) 0 1 2)
803 )"#
804 ));
805
806 {
807 let element_func = &sample.elements[0].value[1];
808 let rfunc = element_func.read();
809 let rtype = &**rfunc.type_ref.read();
810 let elements::Type::Function(ftype) = rtype;
811
812 assert_eq!(rfunc.order(), Some(1));
814 assert_eq!(ftype.params().len(), 1);
816 }
817
818 sample.funcs.begin_delete().push(0).done();
819
820 {
821 let element_func = &sample.elements[0].value[1];
822 let rfunc = element_func.read();
823 let rtype = &**rfunc.type_ref.read();
824 let elements::Type::Function(ftype) = rtype;
825
826 assert_eq!(rfunc.order(), Some(0));
828 assert_eq!(ftype.params().len(), 1);
830 }
831 }
832
833 #[test]
834 fn new_import() {
835 let mut sample = load_sample(indoc!(
836 r#"
837 (module
838 (type (;0;) (func))
839 (type (;1;) (func (param i32 i32) (result i32)))
840 (import "env" "foo" (func (type 1)))
841 (func (param i32)
842 get_local 0
843 i32.const 0
844 call 0
845 drop
846 )
847 (func (type 0)
848 i32.const 0
849 call 1
850 )
851 )"#
852 ));
853
854 {
855 let type_ref_0 = sample.types.clone_ref(0);
856 let declared_func_2 = sample.funcs.clone_ref(2);
857
858 let mut tx = sample.funcs.begin_insert_not_until(|f| {
859 matches!(f.origin, super::ImportedOrDeclared::Imported(_, _))
860 });
861
862 let new_import_func = tx.push(super::Func {
863 type_ref: type_ref_0,
864 origin: super::ImportedOrDeclared::Imported("env".to_owned(), "bar".to_owned()),
865 });
866
867 tx.done();
868
869 assert_eq!(new_import_func.order(), Some(1));
870 assert_eq!(declared_func_2.order(), Some(3));
871 assert_eq!(
872 match &declared_func_2.read().origin {
873 super::ImportedOrDeclared::Declared(body) => {
874 match &body.code[1] {
875 super::Instruction::Call(called_func) => called_func.order(),
876 _ => panic!("instruction #2 should be a call!"),
877 }
878 },
879 _ => panic!("func #3 should be declared!"),
880 },
881 Some(2),
882 "Call should be recalculated to 2"
883 );
884 }
885
886 validate_sample(&sample);
887 }
888
889 #[test]
890 fn simple_opt() {
891 let mut sample = load_sample(indoc!(
892 r#"
893 (module
894 (type (;0;) (func))
895 (type (;1;) (func (param i32 i32) (result i32)))
896 (type (;2;) (func (param i32 i32) (result i32)))
897 (type (;3;) (func (param i32 i32) (result i32)))
898 (import "env" "foo" (func (type 1)))
899 (import "env" "foo2" (func (type 2)))
900 (import "env" "foo3" (func (type 3)))
901 (func (type 0)
902 i32.const 1
903 i32.const 1
904 call 0
905 drop
906 )
907 (func (type 0)
908 i32.const 2
909 i32.const 2
910 call 1
911 drop
912 )
913 (func (type 0)
914 i32.const 3
915 i32.const 3
916 call 2
917 drop
918 )
919 (func (type 0)
920 call 3
921 )
922 )"#
923 ));
924
925 validate_sample(&sample);
926
927 sample.funcs.begin_delete().push(4).push(5).done();
930 validate_sample(&sample);
931
932 sample.funcs.begin_delete().push(1).push(2).done();
935 validate_sample(&sample);
936
937 let declared_func_2 = sample.funcs.clone_ref(2);
939 assert_eq!(
940 match &declared_func_2.read().origin {
941 super::ImportedOrDeclared::Declared(body) => {
942 match &body.code[0] {
943 super::Instruction::Call(called_func) => called_func.order(),
944 wrong_instruction => panic!(
945 "instruction #2 should be a call but got {:?}!",
946 wrong_instruction
947 ),
948 }
949 },
950 _ => panic!("func #0 should be declared!"),
951 },
952 Some(1),
953 "Call should be recalculated to 1"
954 );
955 }
956}