1use alloc::{borrow::ToOwned, collections::BTreeMap};
2
3use alloc::vec;
4use alloc::vec::Vec;
5use anyhow::Context;
6use waffle::{
7 util::new_sig, Block, BlockTarget, Func, FunctionBody, Memory, MemoryArg, Module, Operator,
8 SignatureData, Type,
9};
10
11use crate::{
12 add_op,
13 fcopy::{DontObf, Obfuscate},
14 Builder, Expr,
15};
16
17
18#[derive(Default, Clone, Copy)]
19pub struct Reload<T> {
20 pub wrapped: T,
21}
22impl<T: Obfuscate> Reload<T> {
23 fn store(
24 &mut self,
25 o: usize,
26 memory: &MemoryArg,
27 f: &mut waffle::FunctionBody,
28 b: waffle::Block,
29 args: &[waffle::Value],
30 types: &[waffle::Type],
31 module: &mut Module,
32 ) -> anyhow::Result<(waffle::Value, waffle::Block)> {
33 let r = f.values[args[0]].ty(&f.type_pool).unwrap();
34 let r2 = f.values[args[1]].ty(&f.type_pool).unwrap();
35 if o == 1 {
36 return self.obf(
37 match r2 {
38 Type::I32 => Operator::I32Store8 {
39 memory: memory.clone(),
40 },
41 Type::I64 => Operator::I64Store8 {
42 memory: memory.clone(),
43 },
44 _ => anyhow::bail!("nop!"),
45 },
46 f,
47 b,
48 args,
49 types,
50 module,
51 );
52 }
53 let (a, b) = self.obf(
54 match r2 {
55 Type::I32 => Operator::I32Const { value: 0xff },
56 Type::I64 => Operator::I64Const { value: 0xff },
57 _ => anyhow::bail!("nop!"),
58 },
59 f,
60 b,
61 &[],
62 &[r2],
63 module,
64 )?;
65 let (a, b) = self.obf(
66 match r2 {
67 Type::I32 => Operator::I32And,
68 Type::I64 => Operator::I64And,
69 _ => anyhow::bail!("nop!"),
70 },
71 f,
72 b,
73 &[args[1], a],
74 &[r2],
75 module,
76 )?;
77 let (_, b) = self.obf(
78 match r2 {
79 Type::I32 => Operator::I32Store8 {
80 memory: memory.clone(),
81 },
82 Type::I64 => Operator::I64Store8 {
83 memory: memory.clone(),
84 },
85 _ => anyhow::bail!("nop!"),
86 },
87 f,
88 b,
89 &[args[0], a],
90 types,
91 module,
92 )?;
93 let (a, b) = self.obf(
94 match r2 {
95 Type::I32 => Operator::I32Const { value: 8 },
96 Type::I64 => Operator::I64Const { value: 8 },
97 _ => anyhow::bail!("nop!"),
98 },
99 f,
100 b,
101 &[],
102 &[r2],
103 module,
104 )?;
105 let (c, b) = self.obf(
106 match r2 {
107 Type::I32 => Operator::I32ShrU,
108 Type::I64 => Operator::I64ShrU,
109 _ => anyhow::bail!("nop!"),
110 },
111 f,
112 b,
113 &[args[1], a],
114 &[r2],
115 module,
116 )?;
117 let (a, b) = self.obf(
118 match r {
119 Type::I32 => Operator::I32Const { value: 1 },
120 Type::I64 => Operator::I64Const { value: 1 },
121 _ => anyhow::bail!("nop!"),
122 },
123 f,
124 b,
125 &[],
126 &[r],
127 module,
128 )?;
129 let (a, b) = self.obf(
130 match r {
131 Type::I32 => Operator::I32Add,
132 Type::I64 => Operator::I64Add,
133 _ => anyhow::bail!("nop!"),
134 },
135 f,
136 b,
137 &[args[0], a],
138 &[r],
139 module,
140 )?;
141 return self.store(o - 1, memory, f, b, &[a, c], types, module);
142 }
143 fn load(
144 &mut self,
145 o: usize,
146 memory: &MemoryArg,
147 f: &mut waffle::FunctionBody,
148 b: waffle::Block,
149 args: &[waffle::Value],
150 types: &[waffle::Type],
151 module: &mut Module,
152 ) -> anyhow::Result<(waffle::Value, waffle::Block)> {
153 let r = f.values[args[0]].ty(&f.type_pool).unwrap();
154 if o == 0 {
155 return self.obf(
156 match types[0] {
157 Type::I32 => Operator::I32Const { value: 0 },
158 Type::I64 => Operator::I64Const { value: 0 },
159 _ => anyhow::bail!("nop!"),
160 },
161 f,
162 b,
163 args,
164 types,
165 module,
166 );
167 }
168 if o == 1 {
169 return self.obf(
170 match types[0] {
171 Type::I32 => Operator::I32Load8U {
172 memory: memory.clone(),
173 },
174 Type::I64 => Operator::I64Load8U {
175 memory: memory.clone(),
176 },
177 _ => anyhow::bail!("nop!"),
178 },
179 f,
180 b,
181 args,
182 types,
183 module,
184 );
185 }
186 let (first, b) = self.obf(
187 match types[0] {
188 Type::I32 => Operator::I32Load8U {
189 memory: memory.clone(),
190 },
191 Type::I64 => Operator::I64Load8U {
192 memory: memory.clone(),
193 },
194 _ => anyhow::bail!("nop!"),
195 },
196 f,
197 b,
198 args,
199 types,
200 module,
201 )?;
202 let (n, b) = self.obf(
203 match r {
204 Type::I32 => Operator::I32Const { value: 1 },
205 Type::I64 => Operator::I64Const { value: 1 },
206 _ => anyhow::bail!("nop!"),
207 },
208 f,
209 b,
210 &[],
211 &[r],
212 module,
213 )?;
214 let (n, b) = self.obf(
215 match types[0] {
216 Type::I32 => Operator::I32Add,
217 Type::I64 => Operator::I64Add,
218 _ => anyhow::bail!("nop!"),
219 },
220 f,
221 b,
222 &[args[0], n],
223 &[r],
224 module,
225 )?;
226 let (second, b) = self.load(o - 1, memory, f, b, &[n], types, module)?;
227 let (n, b) = self.obf(
228 Operator::I32Const { value: 8 },
229 f,
230 b,
231 &[],
232 &[Type::I32],
233 module,
234 )?;
235 let (m, b) = self.obf(
236 match types[0] {
237 Type::I32 => Operator::I32Shl,
238 Type::I64 => Operator::I64Shl,
239 _ => anyhow::bail!("nop!"),
240 },
241 f,
242 b,
243 &[second, n],
244 types,
245 module,
246 )?;
247 return self.obf(
248 match types[0] {
249 Type::I32 => Operator::I32Add,
250 Type::I64 => Operator::I64Add,
251 _ => anyhow::bail!("nop!"),
252 },
253 f,
254 b,
255 &[m, first],
256 types,
257 module,
258 );
259 }
260}
261impl<T: Obfuscate> Obfuscate for Reload<T> {
262 fn boot(
263 &mut self,
264 b: waffle::Block,
265 f: &mut waffle::FunctionBody,
266 ) -> anyhow::Result<waffle::Block> {
267 return self.wrapped.boot(b, f);
268 }
269 fn obf_term(
270 &mut self,
271 t: waffle::Terminator,
272 b: waffle::Block,
273 f: &mut waffle::FunctionBody,
274 ) -> anyhow::Result<()> {
275 return self.wrapped.obf_term(t, b, f);
276 }
277 fn sig(&mut self, a: waffle::SignatureData) -> anyhow::Result<waffle::SignatureData> {
278 return self.wrapped.sig(a);
279 }
280 fn obf(
281 &mut self,
282 o: waffle::Operator,
283 f: &mut waffle::FunctionBody,
284 b: waffle::Block,
285 args: &[waffle::Value],
286 types: &[waffle::Type],
287 module: &mut Module,
288 ) -> anyhow::Result<(waffle::Value, waffle::Block)> {
289 match &o {
290 Operator::I32Load8S { memory } => {
292 let (unsigned, b) = self.obf(
293 Operator::I32Load8U {
294 memory: memory.clone(),
295 },
296 f,
297 b,
298 args,
299 types,
300 module,
301 )?;
302 let (signed, b) =
303 self.obf(Operator::I32Extend8S, f, b, &[unsigned], types, module)?;
304 return Ok((signed, b));
305 }
306 Operator::I64Load8S { memory } => {
307 let (unsigned, b) = self.obf(
308 Operator::I64Load8U {
309 memory: memory.clone(),
310 },
311 f,
312 b,
313 args,
314 types,
315 module,
316 )?;
317 let (signed, b) =
318 self.obf(Operator::I64Extend8S, f, b, &[unsigned], types, module)?;
319 return Ok((signed, b));
320 }
321 Operator::I32Load16S { memory } => {
322 let (unsigned, b) = self.obf(
323 Operator::I32Load16U {
324 memory: memory.clone(),
325 },
326 f,
327 b,
328 args,
329 types,
330 module,
331 )?;
332 let (signed, b) =
333 self.obf(Operator::I32Extend16S, f, b, &[unsigned], types, module)?;
334 return Ok((signed, b));
335 }
336 Operator::I64Load16S { memory } => {
337 let (unsigned, b) = self.obf(
338 Operator::I64Load16U {
339 memory: memory.clone(),
340 },
341 f,
342 b,
343 args,
344 types,
345 module,
346 )?;
347 let (signed, b) =
348 self.obf(Operator::I64Extend16S, f, b, &[unsigned], types, module)?;
349 return Ok((signed, b));
350 }
351 Operator::I64Load32S { memory } => {
352 let (unsigned, b) = self.obf(
353 Operator::I64Load32U {
354 memory: memory.clone(),
355 },
356 f,
357 b,
358 args,
359 types,
360 module,
361 )?;
362 let (signed, b) =
363 self.obf(Operator::I64Extend32S, f, b, &[unsigned], types, module)?;
364 return Ok((signed, b));
365 }
366 Operator::I32Load16U { memory } => {
368 return self.load(2, memory, f, b, args, types, module);
369 }
370 Operator::I64Load16U { memory } => {
371 return self.load(2, memory, f, b, args, types, module);
372 }
373 Operator::I32Load { memory } => {
374 return self.load(4, memory, f, b, args, types, module);
375 }
376 Operator::I64Load32U { memory } => {
377 return self.load(4, memory, f, b, args, types, module);
378 }
379 Operator::I64Load { memory } => {
380 return self.load(8, memory, f, b, args, types, module);
381 }
382 Operator::I32Store16 { memory } => {
384 return self.store(2, memory, f, b, args, types, module);
385 }
386 Operator::I64Store16 { memory } => {
387 return self.store(2, memory, f, b, args, types, module);
388 }
389 Operator::I32Store { memory } => {
390 return self.store(4, memory, f, b, args, types, module);
391 }
392 Operator::I64Store32 { memory } => {
393 return self.store(4, memory, f, b, args, types, module);
394 }
395 Operator::I64Store { memory } => {
396 return self.store(8, memory, f, b, args, types, module);
397 }
398 Operator::F32Load { memory } => {
400 let (a, b) = self.load(4, memory, f, b, args, &[Type::I32], module)?;
401 return self.obf(Operator::F32ReinterpretI32, f, b, &[a], types, module);
402 }
403 Operator::F64Load { memory } => {
404 let (a, b) = self.load(8, memory, f, b, args, &[Type::I64], module)?;
405 return self.obf(Operator::F64ReinterpretI64, f, b, &[a], types, module);
406 }
407 Operator::F32Store { memory } => {
409 let (a, b) = self.obf(
410 Operator::I32ReinterpretF32,
411 f,
412 b,
413 args,
414 &[Type::I32],
415 module,
416 )?;
417 return self.store(4, memory, f, b, &[a], types, module);
418 }
419 Operator::F64Store { memory } => {
420 let (a, b) = self.obf(
421 Operator::I64ReinterpretF64,
422 f,
423 b,
424 args,
425 &[Type::I64],
426 module,
427 )?;
428 return self.store(8, memory, f, b, &[a], types, module);
429 }
430 Operator::I64Load8U { memory } => {
432 let (a, b) = self.obf(
433 Operator::I32Load8U {
434 memory: memory.clone(),
435 },
436 f,
437 b,
438 args,
439 &[Type::I32],
440 module,
441 )?;
442 return self.obf(Operator::I64ExtendI32U, f, b, &[a], types, module);
443 }
444 Operator::I64Store8 { memory } => {
445 let (a, b) =
446 self.obf(Operator::I32WrapI64, f, b, &[args[1]], &[Type::I32], module)?;
447 return self.obf(
448 Operator::I32Store8 {
449 memory: memory.clone(),
450 },
451 f,
452 b,
453 &[args[0], a],
454 types,
455 module,
456 );
457 }
458 _ => {
459 return self.wrapped.obf(o, f, b, args, types, module);
460 }
461 }
462 }
463}
464pub struct LowerBulkMemory {}
465impl Obfuscate for LowerBulkMemory {
466 fn obf(
467 &mut self,
468 o: Operator,
469 f: &mut waffle::FunctionBody,
470 b: waffle::Block,
471 args: &[waffle::Value],
472 types: &[Type],
473 mo: &mut Module,
474 ) -> anyhow::Result<(waffle::Value, waffle::Block)> {
475 match o {
476 Operator::MemoryFill { mem } => {
477 let n = f.add_block();
478 let dstt = f.values[args[0]].ty(&f.type_pool).unwrap();
479 let mut dst = f.add_blockparam(n, dstt);
480 let srct = f.values[args[1]].ty(&f.type_pool).unwrap();
481 let mut src = f.add_blockparam(n, srct);
482 let countt = f.values[args[2]].ty(&f.type_pool).unwrap();
483 let mut count = f.add_blockparam(n, countt);
484 f.set_terminator(
485 b,
486 waffle::Terminator::Br {
487 target: BlockTarget {
488 block: n,
489 args: args.to_owned(),
490 },
491 },
492 );
493 let b = n;
494 let mut e = Expr::Bind(
495 Operator::I32Store8 {
496 memory: MemoryArg {
497 align: 0,
498 offset: 0,
499 memory: mem,
500 },
501 },
502 vec![Expr::Leaf(dst), Expr::Leaf(src)],
503 );
504 let (_, b) = e.build(mo, f, b)?;
505 let oc = count;
506 for (r, sub) in vec![(&mut dst, false), (&mut count, true)] {
507 let t = f.values[*r].ty(&f.type_pool).unwrap();
508 let s = add_op(
509 f,
510 &[],
511 &[t],
512 match t {
513 Type::I32 => Operator::I32Const { value: 1 },
514 Type::I64 => Operator::I64Const { value: 1 },
515 _ => anyhow::bail!("wrong type"),
516 },
517 );
518 f.append_to_block(b, s);
519 let s = add_op(
520 f,
521 &[*r, s],
522 &[t],
523 match t {
524 Type::I32 => {
525 if sub {
526 Operator::I32Sub
527 } else {
528 Operator::I32Add
529 }
530 }
531 Type::I64 => {
532 if sub {
533 Operator::I64Sub
534 } else {
535 Operator::I64Add
536 }
537 }
538 _ => anyhow::bail!("wrong type"),
539 },
540 );
541 f.append_to_block(b, s);
542 *r = s;
543 }
544 let oc = add_op(
545 f,
546 &[oc],
547 &[countt],
548 match countt {
549 Type::I32 => Operator::I32Eqz,
550 Type::I64 => Operator::I64Eqz,
551 _ => anyhow::bail!("wrong type"),
552 },
553 );
554 f.append_to_block(b, oc);
555 let m = f.add_block();
556 f.set_terminator(
557 b,
558 waffle::Terminator::CondBr {
559 cond: oc,
560 if_true: BlockTarget {
561 block: m,
562 args: vec![],
563 },
564 if_false: BlockTarget {
565 block: n,
566 args: vec![src, dst, count],
567 },
568 },
569 );
570 let o = add_op(f, &[], &[], Operator::Nop);
571 f.append_to_block(m, o);
572 return Ok((o, m));
573 }
574 Operator::MemoryCopy { dst_mem, src_mem } => {
575 let n = f.add_block();
576 let dstt = f.values[args[0]].ty(&f.type_pool).unwrap();
577 let mut dst = f.add_blockparam(n, dstt);
578 let srct = f.values[args[1]].ty(&f.type_pool).unwrap();
579 let mut src = f.add_blockparam(n, srct);
580 let countt = f.values[args[2]].ty(&f.type_pool).unwrap();
581 let mut count = f.add_blockparam(n, countt);
582 f.set_terminator(
583 b,
584 waffle::Terminator::Br {
585 target: BlockTarget {
586 block: n,
587 args: args.to_owned(),
588 },
589 },
590 );
591 let b = n;
592 let mut e = Expr::Bind(
593 Operator::I32Store8 {
594 memory: MemoryArg {
595 align: 0,
596 offset: 0,
597 memory: dst_mem,
598 },
599 },
600 vec![
601 Expr::Leaf(dst),
602 Expr::Bind(
603 Operator::I32Load8U {
604 memory: MemoryArg {
605 align: 0,
606 offset: 0,
607 memory: src_mem,
608 },
609 },
610 vec![Expr::Leaf(src)],
611 ),
612 ],
613 );
614 let (_, b) = e.build(mo, f, b)?;
615 let oc = count;
616 for (r, sub) in vec![(&mut dst, false), (&mut src, false), (&mut count, true)] {
617 let t = f.values[*r].ty(&f.type_pool).unwrap();
618 let s = add_op(
619 f,
620 &[],
621 &[t],
622 match t {
623 Type::I32 => Operator::I32Const { value: 1 },
624 Type::I64 => Operator::I64Const { value: 1 },
625 _ => anyhow::bail!("wrong type"),
626 },
627 );
628 f.append_to_block(b, s);
629 let s = add_op(
630 f,
631 &[*r, s],
632 &[t],
633 match t {
634 Type::I32 => {
635 if sub {
636 Operator::I32Sub
637 } else {
638 Operator::I32Add
639 }
640 }
641 Type::I64 => {
642 if sub {
643 Operator::I64Sub
644 } else {
645 Operator::I64Add
646 }
647 }
648 _ => anyhow::bail!("wrong type"),
649 },
650 );
651 f.append_to_block(b, s);
652 *r = s;
653 }
654 let oc = add_op(
655 f,
656 &[oc],
657 &[countt],
658 match countt {
659 Type::I32 => Operator::I32Eqz,
660 Type::I64 => Operator::I64Eqz,
661 _ => anyhow::bail!("wrong type"),
662 },
663 );
664 f.append_to_block(b, oc);
665 let m = f.add_block();
666 f.set_terminator(
667 b,
668 waffle::Terminator::CondBr {
669 cond: oc,
670 if_true: BlockTarget {
671 block: m,
672 args: vec![],
673 },
674 if_false: BlockTarget {
675 block: n,
676 args: vec![src, dst, count],
677 },
678 },
679 );
680 let o = add_op(f, &[], &[], Operator::Nop);
681 f.append_to_block(m, o);
682 return Ok((o, m));
683 }
684 _ => {
685 let v = crate::add_op(f, args, types, o);
686 f.append_to_block(b, v);
687 return Ok((v, b));
688 }
689 }
690 }
691}
692pub struct Warp {
693 pub all: BTreeMap<(Memory, bool), Func>,
694}
695impl Obfuscate for Warp {
696 fn obf(
697 &mut self,
698 o: Operator,
699 f: &mut waffle::FunctionBody,
700 b: waffle::Block,
701 args: &[waffle::Value],
702 types: &[Type],
703 module: &mut Module,
704 ) -> anyhow::Result<(waffle::Value, waffle::Block)> {
705 if let Operator::I32Load8U { memory } = o {
706 let ty = f.values[args[0]]
707 .ty(&f.type_pool)
708 .context("in getting the type")?;
709 let a = f.add_op(
710 b,
711 match &ty {
712 Type::I32 => Operator::I32Const {
713 value: memory.offset as u32,
714 },
715 Type::I64 => Operator::I64Const {
716 value: memory.offset,
717 },
718 _ => todo!(),
719 },
720 &[],
721 &[ty],
722 );
723 let a = f.add_op(
724 b,
725 match &ty {
726 Type::I32 => Operator::I32Add,
727 Type::I64 => Operator::I64Add,
728 _ => todo!(),
729 },
730 &[a, args[0]],
731 &[ty],
732 );
733 let mut entry = self.all.entry((memory.memory, false));
734 let entry = entry.or_insert_with_key(|(memory, isStore)| {
735 assert!(!isStore);
736 let mut total = vec![];
737 for n in &module.memories[*memory].segments {
738 total.resize(n.offset + n.data.len(), 0u8);
739 total[n.offset..][..n.data.len()].copy_from_slice(&n.data);
740 }
741 let sig = new_sig(
742 module,
743 SignatureData::Func {
744 params: vec![ty.clone()],
745 returns: vec![Type::I32],
746 },
747 );
748 let mut b = FunctionBody::new(module, sig);
749 let p = b.blocks[b.entry].params[0].1;
750 let ns: [Block; 256] = core::array::from_fn(|x| {
751 let x = x as u8;
752 let r = b.add_block();
753 let rv = b.add_op(r, Operator::I32Const { value: x as u32 }, &[], &[Type::I32]);
754 b.set_terminator(r, waffle::Terminator::Return { values: vec![rv] });
755 return r;
756 });
757 let bak = b.add_block();
758 let a = b.add_op(
759 bak,
760 match &ty {
761 Type::I32 => Operator::I32Const {
762 value: total.len() as u32,
763 },
764 Type::I64 => Operator::I64Const {
765 value: total.len() as u64,
766 },
767 _ => todo!(),
768 },
769 &[],
770 &[ty],
771 );
772 let a = b.add_op(
773 bak,
774 match &ty {
775 Type::I32 => Operator::I32Sub,
776 Type::I64 => Operator::I64Sub,
777 _ => todo!(),
778 },
779 &[a, p],
780 &[ty],
781 );
782 let a = b.add_op(
783 bak,
784 Operator::I32Load8U {
785 memory: MemoryArg {
786 align: 0,
787 offset: 0,
788 memory: *memory,
789 },
790 },
791 &[a],
792 types,
793 );
794 b.set_terminator(bak, waffle::Terminator::Return { values: vec![a] });
795 b.set_terminator(
796 b.entry,
797 waffle::Terminator::Select {
798 value: p,
799 targets: total
800 .iter()
801 .map(|x| ns[*x as usize])
802 .map(|x| BlockTarget {
803 block: x,
804 args: vec![],
805 })
806 .collect(),
807 default: BlockTarget {
808 block: bak,
809 args: vec![],
810 },
811 },
812 );
813 return module
814 .funcs
815 .push(waffle::FuncDecl::Body(sig, format!(""), b));
816 });
817 return DontObf {}.obf(
818 Operator::Call {
819 function_index: *entry,
820 },
821 f,
822 b,
823 &[a],
824 types,
825 module,
826 );
827 }
828 if let Operator::I32Store8 { memory } = o {
829 let ty = f.values[args[0]]
830 .ty(&f.type_pool)
831 .context("in getting the type")?;
832 let a = f.add_op(
833 b,
834 match &ty {
835 Type::I32 => Operator::I32Const {
836 value: memory.offset as u32,
837 },
838 Type::I64 => Operator::I64Const {
839 value: memory.offset,
840 },
841 _ => todo!(),
842 },
843 &[],
844 &[ty],
845 );
846 let a = f.add_op(
847 b,
848 match &ty {
849 Type::I32 => Operator::I32Add,
850 Type::I64 => Operator::I64Add,
851 _ => todo!(),
852 },
853 &[a, args[0]],
854 &[ty],
855 );
856 let mut entry = self.all.entry((memory.memory, true));
857 let entry = entry.or_insert_with_key(|(memory, isStore)| {
858 assert!(isStore);
859 let mut total = vec![];
860 for n in &module.memories[*memory].segments {
861 total.resize(n.offset + n.data.len(), 0u8);
862 total[n.offset..][..n.data.len()].copy_from_slice(&n.data);
863 }
864 let sig = new_sig(
865 module,
866 SignatureData::Func {
867 params: vec![ty.clone(), Type::I32],
868 returns: vec![],
869 },
870 );
871 let mut b = FunctionBody::new(module, sig);
872 let p = b.blocks[b.entry].params[0].1;
873 let p2 = b.blocks[b.entry].params[1].1;
874 let ns: [Block; 256] = core::array::from_fn(|x| {
875 let x = x as u8;
876 let r = b.add_block();
877 b.set_terminator(r, waffle::Terminator::Return { values: vec![] });
878 return r;
879 });
880 let bak = b.add_block();
881 let a = b.add_op(
882 bak,
883 match &ty {
884 Type::I32 => Operator::I32Const {
885 value: total.len() as u32,
886 },
887 Type::I64 => Operator::I64Const {
888 value: total.len() as u64,
889 },
890 _ => todo!(),
891 },
892 &[],
893 &[ty],
894 );
895 let a = b.add_op(
896 bak,
897 match &ty {
898 Type::I32 => Operator::I32Sub,
899 Type::I64 => Operator::I64Sub,
900 _ => todo!(),
901 },
902 &[a, p],
903 &[ty],
904 );
905 let a = b.add_op(
906 bak,
907 Operator::I32Store8 {
908 memory: MemoryArg {
909 align: 0,
910 offset: 0,
911 memory: *memory,
912 },
913 },
914 &[a, p2],
915 types,
916 );
917 b.set_terminator(bak, waffle::Terminator::Return { values: vec![] });
918 b.set_terminator(
919 b.entry,
920 waffle::Terminator::Select {
921 value: p,
922 targets: total
923 .iter()
924 .map(|x| ns[*x as usize])
925 .map(|x| BlockTarget {
926 block: x,
927 args: vec![],
928 })
929 .collect(),
930 default: BlockTarget {
931 block: bak,
932 args: vec![],
933 },
934 },
935 );
936 return module
937 .funcs
938 .push(waffle::FuncDecl::Body(sig, format!(""), b));
939 });
940 return DontObf {}.obf(
941 Operator::Call {
942 function_index: *entry,
943 },
944 f,
945 b,
946 &[a, args[1]],
947 types,
948 module,
949 );
950 }
951 return DontObf {}.obf(o, f, b, args, types, module);
952 }
953}