1 use cranelift_codegen::ir::{Block, Function, Inst, InstructionData, Signature};
2 use serde_derive::{Deserialize, Serialize};
3
4 /// Serializable version of the original Cranelift IR
5 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
6 pub enum SerInstData {
7 Unary {
8 opcode: String,
9 arg: String,
10 },
11 UnaryImm {
12 opcode: String,
13 imm: String,
14 },
15 UnaryIeee32 {
16 opcode: String,
17 imm: String,
18 },
19 UnaryIeee64 {
20 opcode: String,
21 imm: String,
22 },
23 UnaryBool {
24 opcode: String,
25 imm: bool,
26 },
27 UnaryGlobalValue {
28 opcode: String,
29 global_value: String,
30 },
31 Binary {
32 opcode: String,
33 args: [String; 2],
34 },
35 BinaryImm8 {
36 opcode: String,
37 arg: String,
38 imm: String,
39 },
40 BinaryImm64 {
41 opcode: String,
42 arg: String,
43 imm: String,
44 },
45 Ternary {
46 opcode: String,
47 args: [String; 3],
48 },
49 TernaryImm8 {
50 opcode: String,
51 args: [String; 2],
52 imm: String,
53 },
54 MultiAry {
55 opcode: String,
56 args: Vec<String>,
57 },
58 NullAry {
59 opcode: String,
60 },
61 Shuffle {
62 opcode: String,
63 args: [String; 2],
64 mask: String,
65 },
66 IntCompare {
67 opcode: String,
68 args: [String; 2],
69 cond: String,
70 },
71 IntCompareImm {
72 opcode: String,
73 arg: String,
74 cond: String,
75 imm: String,
76 },
77 IntCond {
78 opcode: String,
79 arg: String,
80 cond: String,
81 },
82 FloatCompare {
83 opcode: String,
84 args: [String; 2],
85 cond: String,
86 },
87 FloatCond {
88 opcode: String,
89 arg: String,
90 cond: String,
91 },
92 IntSelect {
93 opcode: String,
94 args: [String; 3],
95 cond: String,
96 },
97 Jump {
98 opcode: String,
99 args: Vec<String>,
100 destination: String,
101 },
102 Branch {
103 opcode: String,
104 args: Vec<String>,
105 destination: String,
106 },
107 BranchInt {
108 opcode: String,
109 args: Vec<String>,
110 cond: String,
111 destination: String,
112 },
113 BranchFloat {
114 opcode: String,
115 args: Vec<String>,
116 cond: String,
117 destination: String,
118 },
119 BranchIcmp {
120 opcode: String,
121 args: Vec<String>,
122 cond: String,
123 destination: String,
124 },
125 BranchTable {
126 opcode: String,
127 arg: String,
128 destination: String,
129 table: String,
130 },
131 BranchTableEntry {
132 opcode: String,
133 args: [String; 2],
134 imm: String,
135 table: String,
136 },
137 BranchTableBase {
138 opcode: String,
139 table: String,
140 },
141 IndirectJump {
142 opcode: String,
143 arg: String,
144 table: String,
145 },
146 Call {
147 opcode: String,
148 args: Vec<String>,
149 func_ref: String,
150 },
151 CallIndirect {
152 opcode: String,
153 args: Vec<String>,
154 sig_ref: String,
155 },
156 FuncAddr {
157 opcode: String,
158 func_ref: String,
159 },
160 Load {
161 opcode: String,
162 arg: String,
163 flags: String,
164 offset: String,
165 },
166 LoadComplex {
167 opcode: String,
168 args: Vec<String>,
169 flags: String,
170 offset: String,
171 },
172 Store {
173 opcode: String,
174 args: [String; 2],
175 flags: String,
176 offset: String,
177 },
178 StoreComplex {
179 opcode: String,
180 args: Vec<String>,
181 flags: String,
182 offset: String,
183 },
184 StackLoad {
185 opcode: String,
186 stack_slot: String,
187 offset: String,
188 },
189 StackStore {
190 opcode: String,
191 arg: String,
192 stack_slot: String,
193 offset: String,
194 },
195 HeapAddr {
196 opcode: String,
197 arg: String,
198 heap: String,
199 imm: String,
200 },
201 TableAddr {
202 opcode: String,
203 arg: String,
204 table: String,
205 offset: String,
206 },
207 RegMove {
208 opcode: String,
209 arg: String,
210 src: String,
211 dst: String,
212 },
213 CopySpecial {
214 opcode: String,
215 src: String,
216 dst: String,
217 },
218 CopyToSsa {
219 opcode: String,
220 src: String,
221 },
222 RegSpill {
223 opcode: String,
224 arg: String,
225 src: String,
226 dst: String,
227 },
228 RegFill {
229 opcode: String,
230 arg: String,
231 src: String,
232 dst: String,
233 },
234 Trap {
235 opcode: String,
236 code: String,
237 },
238 CondTrap {
239 opcode: String,
240 arg: String,
241 code: String,
242 },
243 IntCondTrap {
244 opcode: String,
245 arg: String,
246 cond: String,
247 code: String,
248 },
249 FloatCondTrap {
250 opcode: String,
251 arg: String,
252 cond: String,
253 code: String,
254 },
255 }
256
257 /// Convert Cranelift IR instructions to JSON format.
get_inst_data(inst_index: Inst, func: &Function) -> SerInstData258 pub fn get_inst_data(inst_index: Inst, func: &Function) -> SerInstData {
259 let inst = &func.dfg[inst_index];
260 match *inst {
261 InstructionData::Unary { opcode, arg } => SerInstData::Unary {
262 opcode: opcode.to_string(),
263 arg: arg.to_string(),
264 },
265 InstructionData::UnaryImm { opcode, imm } => SerInstData::UnaryImm {
266 opcode: opcode.to_string(),
267 imm: imm.to_string(),
268 },
269 InstructionData::UnaryIeee32 { opcode, imm } => SerInstData::UnaryIeee32 {
270 opcode: opcode.to_string(),
271 imm: imm.to_string(),
272 },
273 InstructionData::UnaryIeee64 { opcode, imm } => SerInstData::UnaryIeee64 {
274 opcode: opcode.to_string(),
275 imm: imm.to_string(),
276 },
277 InstructionData::UnaryBool { opcode, imm } => SerInstData::UnaryBool {
278 opcode: opcode.to_string(),
279 imm,
280 },
281 InstructionData::UnaryGlobalValue {
282 opcode,
283 global_value,
284 } => SerInstData::UnaryGlobalValue {
285 opcode: opcode.to_string(),
286 global_value: global_value.to_string(),
287 },
288 InstructionData::Binary { opcode, args } => {
289 let hold_args = [args[0].to_string(), args[1].to_string()];
290 SerInstData::Binary {
291 opcode: opcode.to_string(),
292 args: hold_args,
293 }
294 }
295 InstructionData::BinaryImm8 { opcode, arg, imm } => SerInstData::BinaryImm8 {
296 opcode: opcode.to_string(),
297 arg: arg.to_string(),
298 imm: imm.to_string(),
299 },
300 InstructionData::BinaryImm64 { opcode, arg, imm } => SerInstData::BinaryImm64 {
301 opcode: opcode.to_string(),
302 arg: arg.to_string(),
303 imm: imm.to_string(),
304 },
305 InstructionData::Ternary { opcode, args } => {
306 let hold_args = [
307 args[0].to_string(),
308 args[1].to_string(),
309 args[2].to_string(),
310 ];
311 SerInstData::Ternary {
312 opcode: opcode.to_string(),
313 args: hold_args,
314 }
315 }
316 InstructionData::MultiAry { opcode, ref args } => {
317 let mut hold_args = Vec::new();
318 let args_iter = args.as_slice(&func.dfg.value_lists);
319 for arg in args_iter {
320 hold_args.push(arg.to_string());
321 }
322
323 SerInstData::MultiAry {
324 opcode: opcode.to_string(),
325 args: hold_args,
326 }
327 }
328 InstructionData::NullAry { opcode } => SerInstData::NullAry {
329 opcode: opcode.to_string(),
330 },
331 InstructionData::TernaryImm8 { opcode, args, imm } => {
332 let hold_args = [args[0].to_string(), args[1].to_string()];
333 SerInstData::TernaryImm8 {
334 opcode: opcode.to_string(),
335 args: hold_args,
336 imm: imm.to_string(),
337 }
338 }
339 InstructionData::UnaryConst {
340 opcode,
341 constant_handle,
342 } => {
343 let constant = func.dfg.constants.get(constant_handle);
344 SerInstData::UnaryImm {
345 opcode: opcode.to_string(),
346 imm: format!("{:?}", constant),
347 }
348 }
349 InstructionData::Shuffle { opcode, args, mask } => {
350 let mask = func
351 .dfg
352 .immediates
353 .get(mask)
354 .expect("Expected shuffle mask to already be inserted in immediate mapping");
355 SerInstData::Shuffle {
356 opcode: opcode.to_string(),
357 args: [args[0].to_string(), args[1].to_string()],
358 mask: format!("{:?}", mask),
359 }
360 }
361 InstructionData::IntCompare { opcode, args, cond } => {
362 let hold_args = [args[0].to_string(), args[1].to_string()];
363 SerInstData::IntCompare {
364 opcode: opcode.to_string(),
365 args: hold_args,
366 cond: cond.to_string(),
367 }
368 }
369 InstructionData::IntCompareImm {
370 opcode,
371 arg,
372 cond,
373 imm,
374 } => SerInstData::IntCompareImm {
375 opcode: opcode.to_string(),
376 arg: arg.to_string(),
377 cond: cond.to_string(),
378 imm: imm.to_string(),
379 },
380 InstructionData::IntCond { opcode, arg, cond } => SerInstData::IntCond {
381 opcode: opcode.to_string(),
382 arg: arg.to_string(),
383 cond: cond.to_string(),
384 },
385 InstructionData::FloatCompare { opcode, args, cond } => {
386 let hold_args = [args[0].to_string(), args[1].to_string()];
387 SerInstData::FloatCompare {
388 opcode: opcode.to_string(),
389 args: hold_args,
390 cond: cond.to_string(),
391 }
392 }
393 InstructionData::FloatCond { opcode, arg, cond } => SerInstData::FloatCond {
394 opcode: opcode.to_string(),
395 arg: arg.to_string(),
396 cond: cond.to_string(),
397 },
398 InstructionData::IntSelect { opcode, args, cond } => {
399 let hold_args = [
400 args[0].to_string(),
401 args[1].to_string(),
402 args[2].to_string(),
403 ];
404 SerInstData::IntSelect {
405 opcode: opcode.to_string(),
406 args: hold_args,
407 cond: cond.to_string(),
408 }
409 }
410 InstructionData::Jump {
411 opcode,
412 ref args,
413 destination,
414 } => {
415 let mut hold_args = Vec::new();
416 let args_iter = args.as_slice(&func.dfg.value_lists);
417 for arg in args_iter {
418 hold_args.push(arg.to_string());
419 }
420 SerInstData::Jump {
421 opcode: opcode.to_string(),
422 args: hold_args,
423 destination: destination.to_string(),
424 }
425 }
426 InstructionData::Branch {
427 opcode,
428 ref args,
429 destination,
430 } => {
431 let mut hold_args = Vec::new();
432 let args_iter = args.as_slice(&func.dfg.value_lists);
433 for arg in args_iter {
434 hold_args.push(arg.to_string());
435 }
436 SerInstData::Branch {
437 opcode: opcode.to_string(),
438 args: hold_args,
439 destination: destination.to_string(),
440 }
441 }
442 InstructionData::BranchInt {
443 opcode,
444 ref args,
445 cond,
446 destination,
447 } => {
448 let mut hold_args = Vec::new();
449 let args_iter = args.as_slice(&func.dfg.value_lists);
450 for arg in args_iter {
451 hold_args.push(arg.to_string());
452 }
453 SerInstData::BranchInt {
454 opcode: opcode.to_string(),
455 args: hold_args,
456 cond: cond.to_string(),
457 destination: destination.to_string(),
458 }
459 }
460 InstructionData::BranchFloat {
461 opcode,
462 ref args,
463 cond,
464 destination,
465 } => {
466 let mut hold_args = Vec::new();
467 let args_iter = args.as_slice(&func.dfg.value_lists);
468 for arg in args_iter {
469 hold_args.push(arg.to_string());
470 }
471 SerInstData::BranchFloat {
472 opcode: opcode.to_string(),
473 args: hold_args,
474 cond: cond.to_string(),
475 destination: destination.to_string(),
476 }
477 }
478 InstructionData::BranchIcmp {
479 opcode,
480 ref args,
481 cond,
482 destination,
483 } => {
484 let mut hold_args = Vec::new();
485 let args_iter = args.as_slice(&func.dfg.value_lists);
486 for arg in args_iter {
487 hold_args.push(arg.to_string());
488 }
489 SerInstData::BranchIcmp {
490 opcode: opcode.to_string(),
491 args: hold_args,
492 cond: cond.to_string(),
493 destination: destination.to_string(),
494 }
495 }
496 InstructionData::BranchTable {
497 opcode,
498 arg,
499 destination,
500 table,
501 } => SerInstData::BranchTable {
502 opcode: opcode.to_string(),
503 arg: arg.to_string(),
504 destination: destination.to_string(),
505 table: table.to_string(),
506 },
507 InstructionData::BranchTableBase { opcode, table } => SerInstData::BranchTableBase {
508 opcode: opcode.to_string(),
509 table: table.to_string(),
510 },
511 InstructionData::BranchTableEntry {
512 opcode,
513 args,
514 imm,
515 table,
516 } => {
517 let hold_args = [args[0].to_string(), args[1].to_string()];
518 SerInstData::BranchTableEntry {
519 opcode: opcode.to_string(),
520 args: hold_args,
521 imm: imm.to_string(),
522 table: table.to_string(),
523 }
524 }
525 InstructionData::IndirectJump { opcode, arg, table } => SerInstData::IndirectJump {
526 opcode: opcode.to_string(),
527 arg: arg.to_string(),
528 table: table.to_string(),
529 },
530 InstructionData::Call {
531 opcode,
532 ref args,
533 func_ref,
534 } => {
535 let mut hold_args = Vec::new();
536 let args_iter = args.as_slice(&func.dfg.value_lists);
537 for arg in args_iter {
538 hold_args.push(arg.to_string());
539 }
540 SerInstData::Call {
541 opcode: opcode.to_string(),
542 args: hold_args,
543 func_ref: func_ref.to_string(),
544 }
545 }
546 InstructionData::CallIndirect {
547 opcode,
548 ref args,
549 sig_ref,
550 } => {
551 let mut hold_args = Vec::new();
552 let args_iter = args.as_slice(&func.dfg.value_lists);
553 for arg in args_iter {
554 hold_args.push(arg.to_string());
555 }
556 SerInstData::CallIndirect {
557 opcode: opcode.to_string(),
558 args: hold_args,
559 sig_ref: sig_ref.to_string(),
560 }
561 }
562 InstructionData::FuncAddr { opcode, func_ref } => SerInstData::FuncAddr {
563 opcode: opcode.to_string(),
564 func_ref: func_ref.to_string(),
565 },
566 InstructionData::Load {
567 opcode,
568 arg,
569 flags,
570 offset,
571 } => SerInstData::Load {
572 opcode: opcode.to_string(),
573 arg: arg.to_string(),
574 flags: flags.to_string(),
575 offset: offset.to_string(),
576 },
577 InstructionData::LoadComplex {
578 opcode,
579 ref args,
580 flags,
581 offset,
582 } => {
583 let mut hold_args = Vec::new();
584 let args_iter = args.as_slice(&func.dfg.value_lists);
585 for arg in args_iter {
586 hold_args.push(arg.to_string());
587 }
588 SerInstData::LoadComplex {
589 opcode: opcode.to_string(),
590 args: hold_args,
591 flags: flags.to_string(),
592 offset: offset.to_string(),
593 }
594 }
595 InstructionData::Store {
596 opcode,
597 args,
598 flags,
599 offset,
600 } => {
601 let hold_args = [args[0].to_string(), args[1].to_string()];
602 SerInstData::Store {
603 opcode: opcode.to_string(),
604 args: hold_args,
605 flags: flags.to_string(),
606 offset: offset.to_string(),
607 }
608 }
609 InstructionData::StoreComplex {
610 opcode,
611 ref args,
612 flags,
613 offset,
614 } => {
615 let mut hold_args = Vec::new();
616 let args_iter = args.as_slice(&func.dfg.value_lists);
617 for arg in args_iter {
618 hold_args.push(arg.to_string());
619 }
620 SerInstData::StoreComplex {
621 opcode: opcode.to_string(),
622 args: hold_args,
623 flags: flags.to_string(),
624 offset: offset.to_string(),
625 }
626 }
627 InstructionData::StackLoad {
628 opcode,
629 stack_slot,
630 offset,
631 } => SerInstData::StackLoad {
632 opcode: opcode.to_string(),
633 stack_slot: stack_slot.to_string(),
634 offset: offset.to_string(),
635 },
636 InstructionData::StackStore {
637 opcode,
638 arg,
639 stack_slot,
640 offset,
641 } => SerInstData::StackStore {
642 opcode: opcode.to_string(),
643 arg: arg.to_string(),
644 stack_slot: stack_slot.to_string(),
645 offset: offset.to_string(),
646 },
647 InstructionData::HeapAddr {
648 opcode,
649 arg,
650 heap,
651 imm,
652 } => SerInstData::HeapAddr {
653 opcode: opcode.to_string(),
654 arg: arg.to_string(),
655 heap: heap.to_string(),
656 imm: imm.to_string(),
657 },
658 InstructionData::TableAddr {
659 opcode,
660 arg,
661 table,
662 offset,
663 } => SerInstData::TableAddr {
664 opcode: opcode.to_string(),
665 arg: arg.to_string(),
666 table: table.to_string(),
667 offset: offset.to_string(),
668 },
669 InstructionData::RegMove {
670 opcode,
671 arg,
672 src,
673 dst,
674 } => SerInstData::RegMove {
675 opcode: opcode.to_string(),
676 arg: arg.to_string(),
677 src: src.to_string(),
678 dst: dst.to_string(),
679 },
680 InstructionData::CopySpecial { opcode, src, dst } => SerInstData::CopySpecial {
681 opcode: opcode.to_string(),
682 src: src.to_string(),
683 dst: dst.to_string(),
684 },
685 InstructionData::CopyToSsa { opcode, src } => SerInstData::CopyToSsa {
686 opcode: opcode.to_string(),
687 src: src.to_string(),
688 },
689 InstructionData::RegSpill {
690 opcode,
691 arg,
692 src,
693 dst,
694 } => SerInstData::RegSpill {
695 opcode: opcode.to_string(),
696 arg: arg.to_string(),
697 src: src.to_string(),
698 dst: dst.to_string(),
699 },
700 InstructionData::RegFill {
701 opcode,
702 arg,
703 src,
704 dst,
705 } => SerInstData::RegFill {
706 opcode: opcode.to_string(),
707 arg: arg.to_string(),
708 src: src.to_string(),
709 dst: dst.to_string(),
710 },
711 InstructionData::Trap { opcode, code } => SerInstData::Trap {
712 opcode: opcode.to_string(),
713 code: code.to_string(),
714 },
715 InstructionData::CondTrap { opcode, arg, code } => SerInstData::CondTrap {
716 opcode: opcode.to_string(),
717 arg: arg.to_string(),
718 code: code.to_string(),
719 },
720 InstructionData::IntCondTrap {
721 opcode,
722 arg,
723 cond,
724 code,
725 } => SerInstData::IntCondTrap {
726 opcode: opcode.to_string(),
727 arg: arg.to_string(),
728 cond: cond.to_string(),
729 code: code.to_string(),
730 },
731 InstructionData::FloatCondTrap {
732 opcode,
733 arg,
734 cond,
735 code,
736 } => SerInstData::FloatCondTrap {
737 opcode: opcode.to_string(),
738 arg: arg.to_string(),
739 cond: cond.to_string(),
740 code: code.to_string(),
741 },
742 }
743 }
744
745 /// Serializable version of Cranelift IR instructions.
746 #[derive(Clone, Deserialize, Serialize, Debug)]
747 pub struct SerInst {
748 pub inst_name: String,
749 pub inst_data: SerInstData,
750 }
751
752 impl SerInst {
new(inst: Inst, func: &Function) -> Self753 pub fn new(inst: Inst, func: &Function) -> Self {
754 Self {
755 inst_name: inst.to_string(),
756 inst_data: get_inst_data(inst, func),
757 }
758 }
759 }
760
761 /// Serializable version of Cranelift IR Blocks.
762 #[derive(Clone, Deserialize, Serialize, Debug)]
763 pub struct SerBlock {
764 pub block: String,
765 pub params: Vec<String>,
766 pub insts: Vec<SerInst>,
767 }
768
769 impl SerBlock {
new(name: String) -> Self770 pub fn new(name: String) -> Self {
771 Self {
772 block: name,
773 params: Vec::new(),
774 insts: Vec::new(),
775 }
776 }
777 }
778
populate_inst(func: &Function, block: Block) -> Vec<SerInst>779 pub fn populate_inst(func: &Function, block: Block) -> Vec<SerInst> {
780 let mut ser_vec: Vec<SerInst> = Vec::new();
781 let ret_iter = func.layout.block_insts(block);
782 for inst in ret_iter {
783 let ser_inst: SerInst = SerInst::new(inst, &func);
784 ser_vec.push(ser_inst);
785 }
786 ser_vec
787 }
788
789 /// Translating Block parameters into serializable parameters.
populate_params(func: &Function, block: Block) -> Vec<String>790 pub fn populate_params(func: &Function, block: Block) -> Vec<String> {
791 let mut ser_vec: Vec<String> = Vec::new();
792 let parameters = func.dfg.block_params(block);
793 for param in parameters {
794 ser_vec.push(param.to_string());
795 }
796 ser_vec
797 }
798
799 /// Serializable Data Flow Graph.
800 #[derive(Deserialize, Serialize, Debug)]
801 pub struct SerDataFlowGraph {
802 blocks: Vec<SerBlock>,
803 }
804
805 /// Serialize all parts of the Cranelift Block data structure, this includes name, parameters, and
806 /// instructions.
populate_blocks(func: &Function) -> Vec<SerBlock>807 pub fn populate_blocks(func: &Function) -> Vec<SerBlock> {
808 let mut block_vec: Vec<SerBlock> = Vec::new();
809 for block in func.layout.blocks() {
810 let mut ser_block: SerBlock = SerBlock::new(block.to_string());
811 ser_block.params = populate_params(&func, block);
812 ser_block.insts = populate_inst(&func, block);
813 block_vec.push(ser_block);
814 }
815 block_vec
816 }
817
818 /// Serializable Cranelift IR data flow graph, including all blocks.
819 impl SerDataFlowGraph {
create_new(func: &Function) -> Self820 pub fn create_new(func: &Function) -> Self {
821 Self {
822 blocks: populate_blocks(func),
823 }
824 }
825
new(func: &Function) -> Self826 pub fn new(func: &Function) -> Self {
827 Self::create_new(func)
828 }
829 }
830
831 /// Serializable signature including function parameters and returns.
832 #[derive(Serialize, Deserialize, Debug)]
833 pub struct SerSignature {
834 pub func_params: Vec<String>,
835 pub func_returns: Vec<String>,
836 }
837
838 impl SerSignature {
839 /// Creating serializable signature data structure from all Cranelift IR functions.
create_new(sig: &Signature) -> Self840 fn create_new(sig: &Signature) -> Self {
841 let mut params_vec: Vec<String> = Vec::new();
842 let mut returns_vec: Vec<String> = Vec::new();
843 for param in &sig.params {
844 params_vec.push(param.to_string());
845 }
846 for ret in &sig.returns {
847 returns_vec.push(ret.to_string());
848 }
849 Self {
850 func_params: params_vec,
851 func_returns: returns_vec,
852 }
853 }
854
new(func: &Function) -> Self855 pub fn new(func: &Function) -> Self {
856 Self::create_new(&func.signature)
857 }
858 }
859
860 /// Serializable Function type, including name, signature, global values, and data flow graph.
861 #[derive(Serialize, Deserialize, Debug)]
862 pub struct SerFunction {
863 pub name: String,
864 pub signature: SerSignature,
865 pub globals: Vec<String>,
866 pub dfg: SerDataFlowGraph,
867 }
868
869 impl SerFunction {
870 /// Creates serializable global values, as well as the functions signature, name, and data flow
871 /// graph.
create_new(func: &Function) -> Self872 fn create_new(func: &Function) -> Self {
873 let mut global_vec: Vec<String> = Vec::new();
874 for (glob_name, _) in func.global_values.iter() {
875 global_vec.push(glob_name.to_string());
876 }
877 Self {
878 name: func.name.to_string(),
879 signature: SerSignature::new(&func),
880 globals: global_vec,
881 dfg: SerDataFlowGraph::new(&func),
882 }
883 }
884
new(func: &Function) -> Self885 pub fn new(func: &Function) -> Self {
886 Self::create_new(func)
887 }
888 }
889
890 /// Must have SerObj for deserialization, contains all of the functions from inside the file to be
891 /// serialized. Files have one SerObj each, with all SerFunctions contained inside that SerObj.
892 #[derive(Serialize, Deserialize, Debug)]
893 pub struct SerObj {
894 pub functions: Vec<SerFunction>,
895 }
896
897 impl SerObj {
create_new(funcs: Vec<SerFunction>) -> Self898 fn create_new(funcs: Vec<SerFunction>) -> Self {
899 Self { functions: funcs }
900 }
901
new(funcs: &[Function]) -> Self902 pub fn new(funcs: &[Function]) -> Self {
903 let mut func_vec: Vec<SerFunction> = Vec::new();
904 for func in funcs {
905 let ser_func: SerFunction = SerFunction::new(&func);
906 func_vec.push(ser_func);
907 }
908 Self::create_new(func_vec)
909 }
910 }
911