1use source_map_node::Node;
6use swamp_vm_isa::opcode::OpCode;
7use swamp_vm_isa::{
8 BinaryInstruction, FrameMemorySize, HeapMemoryAddress, InstructionPosition, MemoryAlignment,
9 MemoryOffset, MemorySize, ProgramCounterDelta,
10};
11use swamp_vm_types::types::{BasicTypeKind, TypedRegister};
12use swamp_vm_types::{CountU16, MemoryLocation, PointerLocation};
13pub use swamp_vm_types::{
14 FrameMemoryAddress, FrameMemoryRegion, HeapMemoryOffset, InstructionPositionOffset, Meta,
15 PatchPosition, ZFlagPolarity,
16};
17
18pub struct InstructionBuilderState {
20 pub instructions: Vec<BinaryInstruction>,
21 pub meta: Vec<Meta>,
22}
23
24#[must_use]
25pub const fn u16_to_u8_pair(v: u16) -> (u8, u8) {
26 let bytes = v.to_le_bytes();
27 (bytes[0], bytes[1])
28}
29
30#[must_use]
31pub const fn u32_to_bytes(a: u32) -> (u8, u8, u8, u8) {
32 let bytes = a.to_le_bytes();
33 (bytes[0], bytes[1], bytes[2], bytes[3])
34}
35
36impl Default for InstructionBuilderState {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41impl InstructionBuilderState {
42 #[must_use]
43 pub const fn new() -> Self {
44 Self {
45 instructions: Vec::new(),
46 meta: Vec::new(),
47 }
48 }
49
50 #[must_use]
51 pub const fn position(&self) -> InstructionPosition {
52 InstructionPosition(self.instructions.len() as u32)
53 }
54
55 pub fn patch_enter(
56 &mut self,
57 patch_position: PatchPosition,
58 frame_memory_size: FrameMemorySize,
59 ) {
60 const ENTER: u8 = OpCode::Enter as u8;
61
62 let instruction = &mut self.instructions[patch_position.0.0 as usize];
63
64 match instruction.opcode {
65 ENTER => {
66 let bytes = frame_memory_size.0.to_le_bytes();
67
68 instruction.operands[0] = bytes[0];
69 instruction.operands[1] = bytes[1];
70 instruction.operands[2] = bytes[2];
71 instruction.operands[3] = bytes[3];
72 }
73 _ => {
74 panic!("Attempted to patch a non-enter instruction at position {patch_position:?}")
75 }
76 }
77 }
78
79 pub fn patch_call(&mut self, patch_position: PatchPosition, ip: &InstructionPosition) {
82 const CALL: u8 = OpCode::Call as u8;
83
84 let instruction = &mut self.instructions[patch_position.0.0 as usize];
85
86 match instruction.opcode {
87 CALL => {
88 let bytes = u32_to_bytes(ip.0);
89
90 instruction.operands[0] = bytes.0;
91 instruction.operands[1] = bytes.1;
92 instruction.operands[2] = bytes.2;
93 instruction.operands[3] = bytes.3;
94 }
95 _ => panic!("Attempted to patch a non-call instruction at position {patch_position:?}"),
96 }
97 }
98
99 pub fn add_ret(&mut self, node: &Node, comment: &str) {
100 self.add_instruction(OpCode::Ret, &[], node, comment);
101 }
102
103 pub fn add_hlt(&mut self, node: &Node, comment: &str) {
104 self.add_instruction(OpCode::Hlt, &[], node, comment);
105 }
106
107 fn add_instruction(&mut self, op_code: OpCode, operands: &[u8], node: &Node, comment: &str) {
108 let mut array: [u8; 8] = [0; 8];
109 assert!(operands.len() <= 8);
110 let len = operands.len();
111 array[..len].copy_from_slice(&operands[..len]);
112 self.instructions.push(BinaryInstruction {
113 opcode: op_code as u8,
114 operands: array,
115 });
116 let meta = Meta {
117 comment: comment.to_string(),
118 node: node.clone(),
119 };
120
121 self.meta.push(meta);
122 }
123}
124
125pub struct InstructionBuilder<'a> {
126 pub state: &'a mut InstructionBuilderState,
127}
128
129impl InstructionBuilder<'_> {}
130
131impl InstructionBuilder<'_> {}
132
133impl<'a> InstructionBuilder<'a> {
134 #[must_use]
135 pub const fn new(state: &'a mut InstructionBuilderState) -> Self {
136 Self { state }
137 }
138}
139
140impl InstructionBuilder<'_> {
141 pub fn add_trap_if_lt(
142 &mut self,
143 a: &TypedRegister,
144 b: &TypedRegister,
145 node: &Node,
146 comment: &str,
147 ) {
148 self.state.add_instruction(
149 OpCode::TrapOnLessThan,
150 &[a.addressing(), b.addressing()],
151 node,
152 comment,
153 );
154 }
155
156 #[must_use]
157 pub const fn position(&self) -> InstructionPosition {
158 InstructionPosition(self.state.instructions.len() as u32)
159 }
160
161 pub fn add_enter_placeholder(&mut self, node: &Node, comment: &str) -> PatchPosition {
162 let patch_position = PatchPosition(self.position());
163 self.state
164 .add_instruction(OpCode::Enter, &[0, 0, 0, 0], node, comment);
165
166 patch_position
167 }
168
169 pub fn patch_enter(&mut self, size: FrameMemorySize, patch_position: PatchPosition) {
170 self.state.patch_enter(patch_position, size);
171 }
172
173 pub fn add_jmp_if_equal_placeholder(
174 &mut self,
175 test_reg: &TypedRegister,
176 node: &Node,
177 comment: &str,
178 ) -> PatchPosition {
179 let position = self.position();
180
181 self.state
182 .add_instruction(OpCode::BTrue, &[test_reg.addressing(), 0, 0], node, comment);
183
184 PatchPosition(position)
185 }
186
187 pub fn add_jmp_if_true_placeholder(
188 &mut self,
189 test_reg: &TypedRegister,
190 node: &Node,
191 comment: &str,
192 ) -> PatchPosition {
193 self.add_jmp_if_equal_placeholder(test_reg, node, comment)
194 }
195
196 pub fn add_jmp_if_not_equal_placeholder(
197 &mut self,
198 test_reg: &TypedRegister,
199 node: &Node,
200 comment: &str,
201 ) -> PatchPosition {
202 let position = self.position();
203
204 self.state.add_instruction(
205 OpCode::BFalse,
206 &[test_reg.addressing(), 0, 0],
207 node,
208 comment,
209 );
210
211 PatchPosition(position)
212 }
213
214 pub fn add_jmp_if_not_true_placeholder(
215 &mut self,
216 test_reg: &TypedRegister,
217 node: &Node,
218 comment: &str,
219 ) -> PatchPosition {
220 self.add_jmp_if_not_equal_placeholder(test_reg, node, comment)
221 }
222
223 pub fn add_jmp_if_not_equal_polarity_placeholder(
224 &mut self,
225 test_reg: &TypedRegister,
226 polarity: &ZFlagPolarity,
227 node: &Node,
228 comment: &str,
229 ) -> PatchPosition {
230 match polarity {
231 ZFlagPolarity::TrueWhenSet => {
232 self.add_jmp_if_not_equal_placeholder(test_reg, node, comment)
233 }
234 ZFlagPolarity::TrueWhenClear => {
235 self.add_jmp_if_equal_placeholder(test_reg, node, comment)
236 }
237 }
238 }
239
240 pub fn add_grid_init(
241 &mut self,
242 target: &TypedRegister,
243 element_size_reg: &TypedRegister,
244 width: u16,
245 height: u16,
246 node: &Node,
247 comment: &str,
248 ) {
249 let width_octets = Self::u16_to_octets(width);
250 let height_octets = Self::u16_to_octets(height);
251 self.state.add_instruction(
252 OpCode::GridInit,
253 &[
254 target.addressing(),
255 element_size_reg.addressing(),
256 width_octets.0,
257 width_octets.1,
258 height_octets.0,
259 height_octets.1,
260 ],
261 node,
262 comment,
263 );
264 }
265
266 pub fn add_grid_get_entry_addr(
267 &mut self,
268 target: &TypedRegister,
269 grid_self_addr_reg: &PointerLocation,
270 x_reg: &TypedRegister,
271 y_reg: &TypedRegister,
272 element_size: MemorySize,
273 node: &Node,
274 comment: &str,
275 ) {
276 let element_size_bytes = u32_to_bytes(element_size.0);
277 self.state.add_instruction(
278 OpCode::GridGetEntryAddr,
279 &[
280 target.addressing(),
281 grid_self_addr_reg.addressing(),
282 x_reg.addressing(),
283 y_reg.addressing(),
284 element_size_bytes.0,
285 element_size_bytes.1,
286 element_size_bytes.2,
287 element_size_bytes.3,
288 ],
289 node,
290 comment,
291 );
292 }
293
294 pub fn add_sparse_init(
295 &mut self,
296 target: &PointerLocation,
297 element_size: MemorySize,
298 capacity: u16,
299 node: &Node,
300 comment: &str,
301 ) {
302 let element_size_octets = u32_to_bytes(element_size.0);
303 let capacity_octets = Self::u16_to_octets(capacity);
304 self.state.add_instruction(
305 OpCode::SparseInit,
306 &[
307 target.addressing(),
308 element_size_octets.0,
309 element_size_octets.1,
310 element_size_octets.2,
311 element_size_octets.3,
312 capacity_octets.0,
313 capacity_octets.1,
314 ],
315 node,
316 comment,
317 );
318 }
319
320 pub fn add_sparse_add_give_entry_address(
321 &mut self,
322 target_entry_addr_reg: &TypedRegister,
323 dest_handle_reg: &TypedRegister,
324 sparse_addr_reg: &PointerLocation,
325 element_size: MemorySize,
326 node: &Node,
327 comment: &str,
328 ) {
329 let element_size_octets = u32_to_bytes(element_size.0);
330 self.state.add_instruction(
331 OpCode::SparseAddGiveEntryAddress,
332 &[
333 target_entry_addr_reg.addressing(),
334 dest_handle_reg.addressing(),
335 sparse_addr_reg.addressing(),
336 element_size_octets.0,
337 element_size_octets.1,
338 element_size_octets.2,
339 element_size_octets.3,
340 ],
341 node,
342 comment,
343 );
344 }
345
346 pub fn add_sparse_remove(
347 &mut self,
348 sparse_ptr_reg: &PointerLocation,
349 int_reg: &TypedRegister,
350 node: &Node,
351 comment: &str,
352 ) {
353 self.state.add_instruction(
354 OpCode::SparseRemove,
355 &[sparse_ptr_reg.addressing(), int_reg.addressing()],
356 node,
357 comment,
358 );
359 }
360
361 pub fn add_sparse_is_alive(
362 &mut self,
363 dest_bool_reg: &TypedRegister,
364 sparse_ptr_reg: &PointerLocation,
365 int_reg: &TypedRegister,
366 node: &Node,
367 comment: &str,
368 ) {
369 self.state.add_instruction(
370 OpCode::SparseIsAlive,
371 &[
372 dest_bool_reg.addressing(),
373 sparse_ptr_reg.addressing(),
374 int_reg.addressing(),
375 ],
376 node,
377 comment,
378 );
379 }
380
381 pub fn add_sparse_get_entry_addr(
382 &mut self,
383 dest_entry_address_reg: &TypedRegister,
384 sparse_ptr_reg: &PointerLocation,
385 int_handle_reg: &TypedRegister,
386 element_size: MemorySize,
387 node: &Node,
388 comment: &str,
389 ) {
390 let element_size_bytes = u32_to_bytes(element_size.0);
391 self.state.add_instruction(
392 OpCode::SparseGetEntryAddr,
393 &[
394 dest_entry_address_reg.addressing(),
395 sparse_ptr_reg.addressing(),
396 int_handle_reg.addressing(),
397 element_size_bytes.0,
398 element_size_bytes.1,
399 element_size_bytes.2,
400 element_size_bytes.3,
401 ],
402 node,
403 comment,
404 );
405 }
406
407 pub fn add_vec_cmp(
408 &mut self,
409 dest_bool_reg: &TypedRegister,
410 first_ptr: &TypedRegister,
411 second_ptr: &TypedRegister,
412 node: &Node,
413 comment: &str,
414 ) {
415 self.state.add_instruction(
416 OpCode::VecCmp,
417 &[
418 dest_bool_reg.addressing(),
419 first_ptr.addressing(),
420 second_ptr.addressing(),
421 ],
422 node,
423 comment,
424 );
425 }
426
427 pub fn add_vec_swap(
428 &mut self,
429 vec_self_addr: &TypedRegister,
430 int_index_a: &TypedRegister,
431 int_index_b: &TypedRegister,
432 node: &Node,
433 comment: &str,
434 ) {
435 assert!(matches!(
436 vec_self_addr.ty().kind,
437 BasicTypeKind::DynamicLengthVecView(_)
438 ));
439 assert_eq!(int_index_a.size(), int_index_b.size());
440 self.state.add_instruction(
441 OpCode::VecSwap,
442 &[
443 vec_self_addr.addressing(),
444 int_index_a.addressing(),
445 int_index_b.addressing(),
446 ],
447 node,
448 comment,
449 );
450 }
451
452 pub fn add_vec_subscript(
453 &mut self,
454 target: &TypedRegister,
455 self_addr: &TypedRegister,
456 index: &TypedRegister,
457 node: &Node,
458 comment: &str,
459 ) {
460 self.state.add_instruction(
467 OpCode::VecGet,
468 &[
469 target.addressing(),
470 self_addr.addressing(),
471 index.addressing(),
472 ],
473 node,
474 comment,
475 );
476 }
477
478 pub fn add_vec_push_addr(
479 &mut self,
480 target_reg: &TypedRegister,
481 vec_self_reg: &TypedRegister,
482 node: &Node,
483 comment: &str,
484 ) {
485 self.state.add_instruction(
486 OpCode::VecPushAddr,
487 &[target_reg.addressing(), vec_self_reg.addressing()],
488 node,
489 comment,
490 );
491 }
492
493 pub fn add_vec_extend(
494 &mut self,
495 self_vec_addr: &TypedRegister,
496 other_vec_addr: &TypedRegister,
497 node: &Node,
498 comment: &str,
499 ) {
500 self.state.add_instruction(
501 OpCode::VecExtend,
502 &[self_vec_addr.addressing(), other_vec_addr.addressing()],
503 node,
504 comment,
505 );
506 }
507
508 pub fn add_vec_pop(
509 &mut self,
510 target_addr: &TypedRegister,
511 self_addr: &TypedRegister,
512 element_size: MemorySize,
513 node: &Node,
514 comment: &str,
515 ) {
516 let element_size_bytes = u32_to_bytes(element_size.0);
525 self.state.add_instruction(
526 OpCode::VecPop,
527 &[
528 target_addr.addressing(),
529 self_addr.addressing(),
530 element_size_bytes.0,
531 element_size_bytes.1,
532 element_size_bytes.2,
533 element_size_bytes.3,
534 ],
535 node,
536 comment,
537 );
538 }
539
540 pub fn add_vec_remove_index(
541 &mut self,
542 self_addr: &TypedRegister,
543 element_item: &TypedRegister,
544 node: &Node,
545 comment: &str,
546 ) {
547 self.state.add_instruction(
555 OpCode::VecRemoveIndex,
556 &[self_addr.addressing(), element_item.addressing()],
557 node,
558 comment,
559 );
560 }
561
562 pub fn add_vec_remove_index_get_value(
563 &mut self,
564 target_addr: &TypedRegister,
565 self_addr: &TypedRegister,
566 element_item: &TypedRegister,
567 node: &Node,
568 comment: &str,
569 ) {
570 assert!(matches!(
571 self_addr.ty().kind,
572 BasicTypeKind::DynamicLengthVecView(_)
573 ));
574 self.state.add_instruction(
575 OpCode::VecRemoveIndexGetValue,
576 &[
577 target_addr.addressing(),
578 self_addr.addressing(),
579 element_item.addressing(),
580 ],
581 node,
582 comment,
583 );
584 }
585
586 pub fn add_vec_iter_next_placeholder(
587 &mut self,
588 iterator_target: &TypedRegister,
589 closure_variable: &TypedRegister,
590 node: &Node,
591 comment: &str,
592 ) -> PatchPosition {
593 assert!(matches!(
594 iterator_target.ty().kind,
595 BasicTypeKind::InternalVecIterator
596 ));
597 let position = self.position();
598 self.state.add_instruction(
599 OpCode::VecIterNext,
600 &[
601 iterator_target.addressing(),
602 closure_variable.addressing(),
603 0,
604 0,
605 ],
606 node,
607 comment,
608 );
609 PatchPosition(position)
610 }
611
612 pub fn add_vec_iter_next_pair_placeholder(
613 &mut self,
614 iterator_target: &TypedRegister,
615 closure_variable_key: &TypedRegister,
616 closure_variable_value: &TypedRegister,
617 node: &Node,
618 comment: &str,
619 ) -> PatchPosition {
620 assert!(matches!(
621 iterator_target.ty().kind,
622 BasicTypeKind::InternalVecIterator
623 ));
624 let position = self.position();
625 self.state.add_instruction(
626 OpCode::VecIterNextPair,
627 &[
628 iterator_target.addressing(),
629 closure_variable_key.addressing(),
630 closure_variable_value.addressing(),
631 0,
632 ],
633 node,
634 comment,
635 );
636 PatchPosition(position)
637 }
638
639 pub fn add_string_iter_next_placeholder(
640 &mut self,
641 iterator_target: &TypedRegister,
642 closure_variable: &TypedRegister,
643 node: &Node,
644 comment: &str,
645 ) -> PatchPosition {
646 assert!(matches!(
647 iterator_target.ty().kind,
648 BasicTypeKind::InternalStringIterator
649 ));
650 let position = self.position();
651 self.state.add_instruction(
652 OpCode::StringIterNext,
653 &[
654 iterator_target.addressing(),
655 closure_variable.addressing(),
656 0,
657 0,
658 ],
659 node,
660 comment,
661 );
662 PatchPosition(position)
663 }
664
665 pub fn add_string_iter_next_pair_placeholder(
666 &mut self,
667 iterator_target: &TypedRegister,
668 closure_variable_key: &TypedRegister,
669 closure_variable_value: &TypedRegister,
670 node: &Node,
671 comment: &str,
672 ) -> PatchPosition {
673 let position = self.position();
681 self.state.add_instruction(
682 OpCode::StringIterNextPair,
683 &[
684 iterator_target.addressing(),
685 closure_variable_key.addressing(),
686 closure_variable_value.addressing(),
687 0,
688 ],
689 node,
690 comment,
691 );
692 PatchPosition(position)
693 }
694
695 pub fn add_eq_u8_immediate(
696 &mut self,
697 dest_bool_reg: &TypedRegister,
698 source_addr: &TypedRegister,
699 immediate: u8,
700 node: &Node,
701 comment: &str,
702 ) {
703 self.state.add_instruction(
705 OpCode::Eq8Imm,
706 &[
707 dest_bool_reg.addressing(),
708 source_addr.addressing(),
709 immediate,
710 ],
711 node,
712 comment,
713 );
714 }
715
716 pub fn add_call_placeholder(&mut self, node: &Node, comment: &str) -> PatchPosition {
717 let position = self.position();
718 self.state
719 .add_instruction(OpCode::Call, &[0], node, comment);
720 PatchPosition(position)
721 }
722
723 pub fn add_jump_placeholder(&mut self, node: &Node, comment: &str) -> PatchPosition {
724 let position = self.position();
725
726 self.state
727 .add_instruction(OpCode::B, &[0, 0], node, comment);
728
729 PatchPosition(position)
730 }
731
732 pub fn add_lea_from_frame_region(
733 &mut self,
734 target_heap: &TypedRegister,
735 frame_address_to_convert: FrameMemoryRegion,
736 node: &Node,
737 comment: &str,
738 ) {
739 let frame_addr_bytes = u32_to_bytes(frame_address_to_convert.addr.0);
740 self.state.add_instruction(
741 OpCode::LdPtrFromEffectiveFrameAddress,
742 &[
743 target_heap.addressing(),
744 frame_addr_bytes.0,
745 frame_addr_bytes.1,
746 frame_addr_bytes.2,
747 frame_addr_bytes.3,
748 ],
749 node,
750 &format!("{comment} region: {frame_address_to_convert}"),
751 );
752 }
753
754 pub fn add_ld_contiguous_regs_from_frame(
755 &mut self,
756 target_reg: u8,
757 stored_in_frame: FrameMemoryRegion,
758 count: u8,
759 node: &Node,
760 comment: &str,
761 ) {
762 let address_bytes = stored_in_frame.addr.0.to_le_bytes();
763 self.state.add_instruction(
764 OpCode::LdRegFromFrameRange,
765 &[
766 target_reg,
767 address_bytes[0],
768 address_bytes[1],
769 address_bytes[2],
770 address_bytes[3],
771 count,
772 ],
773 node,
774 comment,
775 );
776 }
777
778 pub fn add_ld_masked_regs_from_frame(
779 &mut self,
780 register_mask: u8,
781 stored_in_frame: FrameMemoryRegion,
782 node: &Node,
783 comment: &str,
784 ) {
785 let address_bytes = stored_in_frame.addr.0.to_le_bytes();
786 self.state.add_instruction(
787 OpCode::LdRegFromFrameUsingMask,
788 &[
789 register_mask,
790 address_bytes[0],
791 address_bytes[1],
792 address_bytes[2],
793 address_bytes[3],
794 ],
795 node,
796 comment,
797 );
798 }
799
800 pub fn add_st_contiguous_regs_to_frame(
801 &mut self,
802 frame_mem: FrameMemoryRegion,
803 source_reg: u8,
804 count: u8,
805 node: &Node,
806 comment: &str,
807 ) {
808 let address_bytes = frame_mem.addr.0.to_le_bytes();
809 self.state.add_instruction(
810 OpCode::StRegToFrame,
811 &[
812 address_bytes[0],
813 address_bytes[1],
814 address_bytes[2],
815 address_bytes[3],
816 source_reg,
817 count,
818 ],
819 node,
820 comment,
821 );
822 }
823
824 pub fn add_st_masked_regs_to_frame(
825 &mut self,
826 start_frame_mem: FrameMemoryAddress,
827 source_reg_mask: u8,
828 node: &Node,
829 comment: &str,
830 ) {
831 let address_bytes = start_frame_mem.0.to_le_bytes();
832 self.state.add_instruction(
833 OpCode::StRegToFrameUsingMask,
834 &[
835 address_bytes[0],
836 address_bytes[1],
837 address_bytes[2],
838 address_bytes[3],
839 source_reg_mask,
840 ],
841 node,
842 comment,
843 );
844 }
845
846 pub fn add_block_copy_with_immediate_size(
847 &mut self,
848 target_base_ptr_reg: &PointerLocation,
849 source_base_ptr_reg: &PointerLocation,
850 memory_size: MemorySize,
851 node: &Node,
852 comment: &str,
853 ) {
854 let size_bytes = u32_to_bytes(memory_size.0);
855
856 self.state.add_instruction(
857 OpCode::BlockCopy,
858 &[
859 target_base_ptr_reg.addressing(),
860 source_base_ptr_reg.addressing(),
861 size_bytes.0,
862 size_bytes.1,
863 size_bytes.2,
864 size_bytes.3,
865 ],
866 node,
867 comment,
868 );
869 }
870
871 pub fn add_panic(&mut self, str: &TypedRegister, node: &Node, comment: &str) {
872 self.state
873 .add_instruction(OpCode::Panic, &[str.addressing()], node, comment);
874 }
875
876 pub fn add_halt(&mut self, node: &Node, comment: &str) {
877 self.state.add_instruction(OpCode::Hlt, &[], node, comment);
878 }
879
880 pub fn add_step(&mut self, node: &Node, comment: &str) {
881 self.state.add_instruction(OpCode::Step, &[], node, comment);
882 }
883 pub fn add_call(&mut self, function_ip: &InstructionPosition, node: &Node, comment: &str) {
884 let ip_bytes = function_ip.0.to_le_bytes();
885 self.state.add_instruction(
886 OpCode::Call,
887 &[ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3]],
888 node,
889 comment,
890 );
891 }
892
893 pub fn add_host_call(
894 &mut self,
895 host_function_id: u16,
896 arguments_count: u8,
897 node: &Node,
898 comment: &str,
899 ) {
900 let ip_bytes = Self::u16_to_octets(host_function_id);
901 self.state.add_instruction(
902 OpCode::HostCall,
903 &[ip_bytes.0, ip_bytes.1, arguments_count],
904 node,
905 comment,
906 );
907 }
908
909 pub fn patch_jump(
912 &mut self,
913 patch_position: PatchPosition,
914 target_position: &InstructionPosition,
915 ) {
916 const JMP_IF_NOT: u8 = OpCode::BTrue as u8;
917 const JMP_IF: u8 = OpCode::BFalse as u8;
918 const JMP: u8 = OpCode::B as u8;
919
920 const VEC_ITER_NEXT: u8 = OpCode::VecIterNext as u8;
921 const VEC_ITER_NEXT_PAIR: u8 = OpCode::VecIterNextPair as u8;
922 const MAP_ITER_NEXT: u8 = OpCode::MapIterNext as u8;
923 const MAP_ITER_NEXT_PAIR: u8 = OpCode::MapIterNextPair as u8;
924
925 const SPARSE_ITER_NEXT: u8 = OpCode::SparseIterNext as u8;
926 const SPARSE_ITER_NEXT_PAIR: u8 = OpCode::SparseIterNextPair as u8;
927
928 const STRING_ITER_NEXT: u8 = OpCode::StringIterNext as u8;
929 const STRING_ITER_NEXT_PAIR: u8 = OpCode::StringIterNextPair as u8;
930
931 const RANGE_ITER_NEXT: u8 = OpCode::RangeIterNext as u8;
932
933 let instruction = &mut self.state.instructions[patch_position.0.0 as usize];
937 let effective_pc_address = patch_position.0 + ProgramCounterDelta(1); let delta = *target_position - effective_pc_address;
939 let raw = delta.0;
940 let delta_bytes = raw.to_le_bytes();
941
942 match instruction.opcode {
943 JMP_IF_NOT | JMP_IF => {
944 instruction.operands[1] = delta_bytes[0];
945 instruction.operands[2] = delta_bytes[1];
946 }
947
948 JMP => {
949 instruction.operands[0] = delta_bytes[0];
950 instruction.operands[1] = delta_bytes[1];
951 }
952
953 SPARSE_ITER_NEXT | VEC_ITER_NEXT | STRING_ITER_NEXT | MAP_ITER_NEXT
954 | RANGE_ITER_NEXT => {
955 instruction.operands[2] = delta_bytes[0];
956 instruction.operands[3] = delta_bytes[1];
957 }
958
959 SPARSE_ITER_NEXT_PAIR
960 | VEC_ITER_NEXT_PAIR
961 | STRING_ITER_NEXT_PAIR
962 | MAP_ITER_NEXT_PAIR => {
963 instruction.operands[3] = delta_bytes[0];
964 instruction.operands[4] = delta_bytes[1];
965 }
966
967 _ => panic!("Attempted to patch a non-jump instruction at position {patch_position:?}"),
968 }
969 }
970
971 pub fn patch_jump_here(&mut self, jump_position: PatchPosition) {
973 self.patch_jump(jump_position, &self.position());
974 }
975
976 pub fn add_jmp(&mut self, pc: InstructionPosition, node: &Node, comment: &str) {
977 let delta_bytes = self.calculate_pc_delta_bytes(pc);
978 self.state
979 .add_instruction(OpCode::B, &[delta_bytes[0], delta_bytes[1]], node, comment);
980 }
981
982 const fn calculate_pc_delta(
983 &self,
984 target_instruction: InstructionPosition,
985 ) -> ProgramCounterDelta {
986 ProgramCounterDelta(
987 ((target_instruction.0 as i32) - ((self.position().0 + 1) as i32)) as i16,
988 )
989 }
990 const fn calculate_pc_delta_bytes(&self, pc: InstructionPosition) -> [u8; 2] {
991 let delta = self.calculate_pc_delta(pc);
992
993 delta.0.to_le_bytes()
994 }
995
996 pub fn add_frame_memory_clear(
997 &mut self,
998 frame_region: FrameMemoryRegion,
999 node: &Node,
1000 comment: &str,
1001 ) {
1002 let addr_bytes = u32_to_bytes(frame_region.addr.0);
1003 let size_bytes = u32_to_bytes(frame_region.size.0);
1004 self.state.add_instruction(
1005 OpCode::FrameMemClr,
1006 &[
1007 addr_bytes.0,
1008 addr_bytes.1,
1009 addr_bytes.2,
1010 addr_bytes.3,
1011 size_bytes.0,
1012 size_bytes.1,
1013 size_bytes.2,
1014 size_bytes.3,
1015 ],
1016 node,
1017 comment,
1018 );
1019 }
1020
1021 pub fn add_map_iter_init(
1024 &mut self,
1025 iterator_target: &TypedRegister,
1026 pointer_to_map_header: &TypedRegister,
1027 node: &Node,
1028 comment: &str,
1029 ) {
1030 self.state.add_instruction(
1031 OpCode::MapIterInit,
1032 &[
1033 iterator_target.addressing(),
1034 pointer_to_map_header.addressing(),
1035 ],
1036 node,
1037 comment,
1038 );
1039 }
1040
1041 pub fn add_map_iter_next_placeholder(
1042 &mut self,
1043 iterator_target: &TypedRegister,
1044 closure_variable: &TypedRegister,
1045 node: &Node,
1046 comment: &str,
1047 ) -> PatchPosition {
1048 let position = self.position();
1049 self.state.add_instruction(
1050 OpCode::MapIterNext,
1051 &[
1052 iterator_target.addressing(),
1053 closure_variable.addressing(),
1054 0,
1055 ],
1056 node,
1057 comment,
1058 );
1059 PatchPosition(position)
1060 }
1061
1062 pub fn add_map_iter_next_pair_placeholder(
1063 &mut self,
1064 iterator_target: &TypedRegister,
1065 closure_variable: &TypedRegister,
1066 closure_variable_b: &TypedRegister,
1067 node: &Node,
1068 comment: &str,
1069 ) -> PatchPosition {
1070 let position = self.position();
1071 self.state.add_instruction(
1072 OpCode::MapIterNextPair,
1073 &[
1074 iterator_target.addressing(),
1075 closure_variable.addressing(),
1076 closure_variable_b.addressing(),
1077 0,
1078 ],
1079 node,
1080 comment,
1081 );
1082 PatchPosition(position)
1083 }
1084
1085 pub fn add_range_init(
1086 &mut self,
1087 target_range_iterator: &TypedRegister,
1088 min_reg: &TypedRegister,
1089 max_reg: &TypedRegister,
1090 is_inclusive_reg: &TypedRegister,
1091 node: &Node,
1092 comment: &str,
1093 ) {
1094 self.state.add_instruction(
1095 OpCode::RangeInit,
1096 &[
1097 target_range_iterator.addressing(),
1098 min_reg.addressing(),
1099 max_reg.addressing(),
1100 is_inclusive_reg.addressing(),
1101 ],
1102 node,
1103 comment,
1104 );
1105 }
1106
1107 pub fn add_range_iter_next_placeholder(
1108 &mut self,
1109 iterator_target: &TypedRegister,
1110 closure_variable: &TypedRegister,
1111 node: &Node,
1112
1113 comment: &str,
1114 ) -> PatchPosition {
1115 let position = self.position();
1116 self.state.add_instruction(
1117 OpCode::RangeIterNext,
1118 &[
1119 iterator_target.addressing(),
1120 closure_variable.addressing(),
1121 0,
1122 0,
1123 ],
1124 node,
1125 comment,
1126 );
1127 PatchPosition(position)
1128 }
1129
1130 pub fn add_string_duplicate(
1131 &mut self,
1132 dst_offset: &TypedRegister,
1133 lhs_offset: &TypedRegister,
1134 node: &Node,
1135 comment: &str,
1136 ) {
1137 self.state.add_instruction(
1138 OpCode::StringDuplicate,
1139 &[dst_offset.addressing(), lhs_offset.addressing()],
1140 node,
1141 comment,
1142 );
1143 }
1144
1145 pub fn add_bytes_to_string(
1146 &mut self,
1147 dest_string_view_reg: &TypedRegister,
1148 source_byte_vec_ref: &TypedRegister,
1149 node: &Node,
1150 comment: &str,
1151 ) {
1152 self.state.add_instruction(
1153 OpCode::BytesToString,
1154 &[
1155 dest_string_view_reg.addressing(),
1156 source_byte_vec_ref.addressing(),
1157 ],
1158 node,
1159 comment,
1160 );
1161 }
1162
1163 pub fn add_bytes_to_string_storage(
1164 &mut self,
1165 dest_string_storage_reg: &TypedRegister,
1166 source_byte_vec_ref: &TypedRegister,
1167 node: &Node,
1168 comment: &str,
1169 ) {
1170 self.state.add_instruction(
1171 OpCode::BytesToStringStorage,
1172 &[
1173 dest_string_storage_reg.addressing(),
1174 source_byte_vec_ref.addressing(),
1175 ],
1176 node,
1177 comment,
1178 );
1179 }
1180
1181 pub fn add_string_append(
1182 &mut self,
1183 dst_offset: &TypedRegister,
1184 lhs_offset: &TypedRegister,
1185 rhs_offset: &TypedRegister,
1186 node: &Node,
1187 comment: &str,
1188 ) {
1189 self.state.add_instruction(
1190 OpCode::StringAppend,
1191 &[
1192 dst_offset.addressing(),
1193 lhs_offset.addressing(),
1194 rhs_offset.addressing(),
1195 ],
1196 node,
1197 comment,
1198 );
1199 }
1200 pub fn add_string_multiply(
1201 &mut self,
1202 dst_offset: &TypedRegister,
1203 lhs_offset: &TypedRegister,
1204 rhs_offset: &TypedRegister,
1205 node: &Node,
1206 comment: &str,
1207 ) {
1208 self.state.add_instruction(
1209 OpCode::StringRepeat,
1210 &[
1211 dst_offset.addressing(),
1212 lhs_offset.addressing(),
1213 rhs_offset.addressing(),
1214 ],
1215 node,
1216 comment,
1217 );
1218 }
1219
1220 pub fn add_string_cmp(
1221 &mut self,
1222 dest_bool_reg: &TypedRegister,
1223 a: &TypedRegister,
1224 b: &TypedRegister,
1225 node: &Node,
1226 comment: &str,
1227 ) {
1228 self.state.add_instruction(
1229 OpCode::StringCmp,
1230 &[dest_bool_reg.addressing(), a.addressing(), b.addressing()],
1231 node,
1232 comment,
1233 );
1234 }
1235
1236 pub fn add_fixed_capacity_array_init_fill_capacity_and_len(
1237 &mut self,
1238 target_vec_to_init: &PointerLocation,
1239 capacity: u16,
1240 element_size: &MemorySize,
1241 node: &Node,
1242 comment: &str,
1243 ) {
1244 let capacity_bytes = u16_to_u8_pair(capacity);
1245 let element_bytes = u32_to_bytes(element_size.0);
1246
1247 self.state.add_instruction(
1248 OpCode::ArrayInitWithLenAndCapacity,
1249 &[
1250 target_vec_to_init.ptr_reg.addressing(),
1251 capacity_bytes.0,
1252 capacity_bytes.1,
1253 element_bytes.0,
1254 element_bytes.1,
1255 element_bytes.2,
1256 element_bytes.3,
1257 ],
1258 node,
1259 comment,
1260 );
1261 }
1262
1263 pub fn add_map_init_set_capacity(
1264 &mut self,
1265 target_map_to_init: &PointerLocation,
1266 logical_limit: CountU16,
1267 key_size_reg: &TypedRegister,
1268 key_alignment: MemoryAlignment,
1269 value_size_reg: &TypedRegister,
1270 value_alignment: MemoryAlignment,
1271 node: &Node,
1272 comment: &str,
1273 ) {
1274 debug_assert!(logical_limit.0 > 0);
1275
1276 let logical_limit_bytes = u16_to_u8_pair(logical_limit.0);
1277
1278 let key_alignment_usize: usize = key_alignment.into();
1279 let value_alignment_usize: usize = value_alignment.into();
1280
1281 self.state.add_instruction(
1283 OpCode::MapInitWithCapacityAndKeyAndTupleSizeAddr,
1284 &[
1285 target_map_to_init.ptr_reg.addressing(),
1286 logical_limit_bytes.0,
1287 logical_limit_bytes.1,
1288 key_size_reg.addressing(),
1289 key_alignment_usize as u8,
1290 value_size_reg.addressing(),
1291 value_alignment_usize as u8,
1292 ],
1293 node,
1294 comment,
1295 );
1296 }
1297
1298 pub fn add_map_overwrite(
1299 &mut self,
1300 destination_map: &PointerLocation,
1301 source_map: &PointerLocation,
1302 node: &Node,
1303 comment: &str,
1304 ) {
1305 self.state.add_instruction(
1306 OpCode::MapOverwrite,
1307 &[destination_map.addressing(), source_map.addressing()],
1308 node,
1309 comment,
1310 );
1311 }
1312
1313 pub fn add_range_iter_init(
1314 &mut self,
1315 iterator_target: &TypedRegister,
1316 range_source_header: &TypedRegister,
1317 node: &Node,
1318 comment: &str,
1319 ) {
1320 self.state.add_instruction(
1324 OpCode::RangeIterInit,
1325 &[
1326 iterator_target.addressing(),
1327 range_source_header.addressing(),
1328 ],
1329 node,
1330 comment,
1331 );
1332 }
1333
1334 pub fn add_vec_copy(
1335 &mut self,
1336 target_vec: &PointerLocation,
1337 source_vec: &PointerLocation,
1338 node: &Node,
1339 comment: &str,
1340 ) {
1341 self.state.add_instruction(
1342 OpCode::VecCopy,
1343 &[
1344 target_vec.ptr_reg.addressing(),
1345 source_vec.ptr_reg.addressing(),
1346 ],
1347 node,
1348 comment,
1349 );
1350 }
1351
1352 pub fn add_vec_copy_range(
1353 &mut self,
1354 target_vec: &PointerLocation,
1355 source_vec: &PointerLocation,
1356 range_header: &TypedRegister,
1357 node: &Node,
1358 comment: &str,
1359 ) {
1360 self.state.add_instruction(
1361 OpCode::VecCopyRange,
1362 &[
1363 target_vec.addressing(),
1364 source_vec.addressing(),
1365 range_header.addressing(),
1366 ],
1367 node,
1368 comment,
1369 );
1370 }
1371
1372 pub fn add_vec_init_set_capacity(
1373 &mut self,
1374 target_vec_to_init: &PointerLocation,
1375 capacity: CountU16,
1376 element_size: &MemorySize,
1377 node: &Node,
1378 comment: &str,
1379 ) {
1380 let capacity_bytes = u16_to_u8_pair(capacity.0);
1384 let element_bytes = u32_to_bytes(element_size.0);
1385 self.state.add_instruction(
1386 OpCode::VecInit,
1387 &[
1388 target_vec_to_init.ptr_reg.addressing(),
1389 capacity_bytes.0,
1390 capacity_bytes.1,
1391 element_bytes.0,
1392 element_bytes.1,
1393 element_bytes.2,
1394 element_bytes.3,
1395 ],
1396 node,
1397 comment,
1398 );
1399 }
1400
1401 pub fn add_vec_iter_init(
1402 &mut self,
1403 iterator_target: &TypedRegister,
1404 pointer_to_vec_header: &TypedRegister,
1405 node: &Node,
1406 comment: &str,
1407 ) {
1408 self.state.add_instruction(
1409 OpCode::VecIterInit,
1410 &[
1411 iterator_target.addressing(),
1412 pointer_to_vec_header.addressing(),
1413 ],
1414 node,
1415 comment,
1416 );
1417 }
1418
1419 pub fn add_vec_iter_next(
1420 &mut self,
1421 iterator_target: &TypedRegister,
1422 closure_variable: &TypedRegister,
1423 instruction_position: InstructionPosition,
1424 node: &Node,
1425 comment: &str,
1426 ) {
1427 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1428 self.state.add_instruction(
1429 OpCode::VecIterNext,
1430 &[
1431 iterator_target.addressing(),
1432 closure_variable.addressing(),
1433 bytes[0],
1434 bytes[1],
1435 ],
1436 node,
1437 comment,
1438 );
1439 }
1440
1441 pub fn add_vec_iter_next_pair(
1442 &mut self,
1443 iterator_target: &TypedRegister,
1444 closure_variable_key: &TypedRegister,
1445 closure_variable_value: &TypedRegister,
1446 instruction_position: InstructionPosition,
1447 node: &Node,
1448 comment: &str,
1449 ) {
1450 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1451 self.state.add_instruction(
1452 OpCode::VecIterNextPair,
1453 &[
1454 iterator_target.addressing(),
1455 closure_variable_key.addressing(),
1456 closure_variable_value.addressing(),
1457 bytes[0],
1458 bytes[1],
1459 ],
1460 node,
1461 comment,
1462 );
1463 }
1464
1465 pub fn add_string_iter_init(
1466 &mut self,
1467 iterator_target: &TypedRegister,
1468 pointer_to_vec_header: &TypedRegister,
1469 element_size: MemorySize,
1470 node: &Node,
1471 comment: &str,
1472 ) {
1473 let element_size_bytes = u32_to_bytes(element_size.0);
1474 self.state.add_instruction(
1475 OpCode::StringIterInit,
1476 &[
1477 iterator_target.addressing(),
1478 pointer_to_vec_header.addressing(),
1479 element_size_bytes.0,
1480 element_size_bytes.1,
1481 element_size_bytes.2,
1482 element_size_bytes.3,
1483 ],
1484 node,
1485 comment,
1486 );
1487 }
1488
1489 pub fn add_string_iter_next(
1490 &mut self,
1491 iterator_target: &TypedRegister,
1492 closure_variable: &TypedRegister,
1493 instruction_position: InstructionPosition,
1494 node: &Node,
1495 comment: &str,
1496 ) {
1497 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1498 self.state.add_instruction(
1499 OpCode::StringIterNext,
1500 &[
1501 iterator_target.addressing(),
1502 closure_variable.addressing(),
1503 bytes[0],
1504 bytes[1],
1505 ],
1506 node,
1507 comment,
1508 );
1509 }
1510
1511 pub fn add_string_iter_next_pair(
1512 &mut self,
1513 iterator_target: &TypedRegister,
1514 closure_variable_key: &TypedRegister,
1515 closure_variable_value: &TypedRegister,
1516 instruction_position: InstructionPosition,
1517 node: &Node,
1518 comment: &str,
1519 ) {
1520 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1521 self.state.add_instruction(
1522 OpCode::StringIterNextPair,
1523 &[
1524 iterator_target.addressing(),
1525 closure_variable_key.addressing(),
1526 closure_variable_value.addressing(),
1527 bytes[0],
1528 bytes[1],
1529 ],
1530 node,
1531 comment,
1532 );
1533 }
1534 fn convert_to_lower_and_upper(data: u32) -> (u8, u8, u8, u8) {
1535 data.to_le_bytes().into()
1536 }
1537
1538 fn u16_to_octets(data: u16) -> (u8, u8) {
1539 data.to_le_bytes().into()
1540 }
1541
1542 pub fn add_st32_using_ptr_with_offset(
1543 &mut self,
1544 scalar_lvalue_location: &MemoryLocation,
1545 u32_reg: &TypedRegister,
1546 node: &Node,
1547 comment: &str,
1548 ) {
1549 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1551 self.state.add_instruction(
1552 OpCode::St32UsingPtrWithOffset,
1553 &[
1554 scalar_lvalue_location.base_ptr_reg.addressing(),
1555 offset_bytes.0,
1556 offset_bytes.1,
1557 offset_bytes.2,
1558 offset_bytes.3,
1559 u32_reg.index,
1560 ],
1561 node,
1562 comment,
1563 );
1564 }
1565
1566 pub fn add_st16_using_ptr_with_offset(
1567 &mut self,
1568 scalar_lvalue_location: &MemoryLocation,
1569 u16_reg: &TypedRegister,
1570 node: &Node,
1571 comment: &str,
1572 ) {
1573 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1575 self.state.add_instruction(
1576 OpCode::St16UsingPtrWithOffset,
1577 &[
1578 scalar_lvalue_location.base_ptr_reg.addressing(),
1579 offset_bytes.0,
1580 offset_bytes.1,
1581 offset_bytes.2,
1582 offset_bytes.3,
1583 u16_reg.index,
1584 ],
1585 node,
1586 comment,
1587 );
1588 }
1589
1590 pub fn add_st8_using_ptr_with_offset(
1591 &mut self,
1592 scalar_lvalue_location: &MemoryLocation,
1593 u8_reg: &TypedRegister,
1594 node: &Node,
1595 comment: &str,
1596 ) {
1597 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1599 self.state.add_instruction(
1600 OpCode::St8UsingPtrWithOffset,
1601 &[
1602 scalar_lvalue_location.base_ptr_reg.addressing(),
1603 offset_bytes.0,
1604 offset_bytes.1,
1605 offset_bytes.2,
1606 offset_bytes.3,
1607 u8_reg.addressing(),
1608 ],
1609 node,
1610 comment,
1611 );
1612 }
1613
1614 pub fn add_mov_16_immediate_value(
1615 &mut self,
1616 dst_offset: &TypedRegister,
1617 value: u16,
1618 node: &Node,
1619 comment: &str,
1620 ) {
1621 let bytes = Self::u16_to_octets(value);
1622
1623 self.state.add_instruction(
1624 OpCode::Mov16FromImmediateValue,
1625 &[dst_offset.addressing(), bytes.0, bytes.1],
1626 node,
1627 comment,
1628 );
1629 }
1630
1631 pub fn add_mov_32_immediate_value(
1632 &mut self,
1633 dst_offset: &TypedRegister,
1634 value: u32,
1635 node: &Node,
1636 comment: &str,
1637 ) {
1638 let bytes = Self::convert_to_lower_and_upper(value);
1639
1640 self.state.add_instruction(
1641 OpCode::Mov32FromImmediateValue,
1642 &[dst_offset.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1643 node,
1644 comment,
1645 );
1646 }
1647
1648 pub fn add_ld32_from_absolute_memory_address(
1649 &mut self,
1650 dst_reg: &TypedRegister,
1651 absolute_mem_addr: &HeapMemoryAddress,
1652 node: &Node,
1653 comment: &str,
1654 ) {
1655 let bytes = u32_to_bytes(absolute_mem_addr.0);
1656
1657 self.state.add_instruction(
1658 OpCode::Ld32FromAbsoluteAddress,
1659 &[dst_reg.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1660 node,
1661 comment,
1662 );
1663 }
1664
1665 pub fn add_ld16_from_pointer_from_memory_location(
1666 &mut self,
1667 dst_reg: &TypedRegister,
1668 source_memory_location: &MemoryLocation,
1669 node: &Node,
1670 comment: &str,
1671 ) {
1672 self.add_ld16_from_pointer_with_offset_u16(
1673 dst_reg,
1674 &source_memory_location.base_ptr_reg,
1675 source_memory_location.offset,
1676 node,
1677 comment,
1678 );
1679 }
1680
1681 pub fn add_ld16_from_pointer_with_offset_u16(
1682 &mut self,
1683 dst_reg: &TypedRegister,
1684 base_ptr_reg: &TypedRegister,
1685 offset: MemoryOffset,
1686 node: &Node,
1687 comment: &str,
1688 ) {
1689 let offset_bytes = u32_to_bytes(offset.0);
1690
1691 self.state.add_instruction(
1692 OpCode::Ld16FromPointerWithOffset,
1693 &[
1694 dst_reg.addressing(),
1695 base_ptr_reg.addressing(),
1696 offset_bytes.0,
1697 offset_bytes.1,
1698 offset_bytes.2,
1699 offset_bytes.3,
1700 ],
1701 node,
1702 comment,
1703 );
1704 }
1705
1706 pub fn add_ld32_from_pointer_with_offset_u16(
1707 &mut self,
1708 dst_reg: &TypedRegister,
1709 base_ptr_reg: &TypedRegister,
1710 offset: MemoryOffset,
1711 node: &Node,
1712 comment: &str,
1713 ) {
1714 let offset_bytes = u32_to_bytes(offset.0);
1715
1716 self.state.add_instruction(
1717 OpCode::Ld32FromPointerWithOffset,
1718 &[
1719 dst_reg.addressing(),
1720 base_ptr_reg.addressing(),
1721 offset_bytes.0,
1722 offset_bytes.1,
1723 offset_bytes.2,
1724 offset_bytes.3,
1725 ],
1726 node,
1727 comment,
1728 );
1729 }
1730
1731 pub fn add_ld8_from_absolute_memory_address(
1732 &mut self,
1733 dst_reg: &TypedRegister,
1734 absolute_mem_addr: &HeapMemoryAddress,
1735 node: &Node,
1736 comment: &str,
1737 ) {
1738 let absolute_memory_addr = u32_to_bytes(absolute_mem_addr.0);
1739
1740 self.state.add_instruction(
1741 OpCode::Ld8FromAbsoluteAddress,
1742 &[
1743 dst_reg.addressing(),
1744 absolute_memory_addr.0,
1745 absolute_memory_addr.1,
1746 absolute_memory_addr.2,
1747 absolute_memory_addr.3,
1748 ],
1749 node,
1750 comment,
1751 );
1752 }
1753
1754 pub fn add_check_u8(&mut self, dst_reg: &TypedRegister, node: &Node, comment: &str) {
1755 self.state
1756 .add_instruction(OpCode::CheckU8, &[dst_reg.addressing()], node, comment);
1757 }
1758
1759 pub fn add_ld8_from_pointer_with_offset(
1760 &mut self,
1761 dst_reg: &TypedRegister,
1762 base_ptr_reg: &TypedRegister,
1763 offset: MemoryOffset,
1764 node: &Node,
1765 comment: &str,
1766 ) {
1767 let offset_bytes = u32_to_bytes(offset.0);
1768
1769 self.state.add_instruction(
1770 OpCode::Ld8FromPointerWithOffset,
1771 &[
1772 dst_reg.addressing(),
1773 base_ptr_reg.addressing(),
1774 offset_bytes.0,
1775 offset_bytes.1,
1776 offset_bytes.2,
1777 offset_bytes.3,
1778 ],
1779 node,
1780 comment,
1781 );
1782 }
1783
1784 pub fn add_mov_reg(
1785 &mut self,
1786 dst_offset: &TypedRegister,
1787 src_offset: &TypedRegister,
1788 node: &Node,
1789 comment: &str,
1790 ) {
1791 if dst_offset.index == src_offset.index {
1792 return;
1793 }
1794 self.state.add_instruction(
1795 OpCode::MovReg,
1796 &[dst_offset.addressing(), src_offset.addressing()],
1797 node,
1798 comment,
1799 );
1800 }
1801
1802 pub fn add_mov8_immediate(
1803 &mut self,
1804 dst_offset: &TypedRegister,
1805 value: u8,
1806 node: &Node,
1807 comment: &str,
1808 ) {
1809 self.state.add_instruction(
1810 OpCode::Mov8FromImmediateValue,
1811 &[dst_offset.addressing(), value],
1812 node,
1813 comment,
1814 );
1815 }
1816
1817 pub fn add_add_u32(
1818 &mut self,
1819 dst_offset: &TypedRegister,
1820 lhs_offset: &TypedRegister,
1821 rhs_offset: &TypedRegister,
1822 node: &Node,
1823 comment: &str,
1824 ) {
1825 self.state.add_instruction(
1829 OpCode::AddU32,
1830 &[
1831 dst_offset.addressing(),
1832 lhs_offset.addressing(),
1833 rhs_offset.addressing(),
1834 ],
1835 node,
1836 comment,
1837 );
1838 }
1839
1840 pub fn add_add_u32_imm(
1841 &mut self,
1842 dst_offset: &TypedRegister,
1843 lhs_offset: &TypedRegister,
1844 rhs_immediate: u32,
1845 node: &Node,
1846 comment: &str,
1847 ) {
1848 let immediate_bytes = u32_to_bytes(rhs_immediate);
1852 self.state.add_instruction(
1853 OpCode::AddU32Imm,
1854 &[
1855 dst_offset.addressing(),
1856 lhs_offset.addressing(),
1857 immediate_bytes.0,
1858 immediate_bytes.1,
1859 immediate_bytes.2,
1860 immediate_bytes.3,
1861 ],
1862 node,
1863 comment,
1864 );
1865 }
1866
1867 pub fn add_mod_i32(
1868 &mut self,
1869 dst_offset: &TypedRegister,
1870 lhs_offset: &TypedRegister,
1871 rhs_offset: &TypedRegister,
1872 node: &Node,
1873 comment: &str,
1874 ) {
1875 self.state.add_instruction(
1880 OpCode::ModI32,
1881 &[
1882 dst_offset.addressing(),
1883 lhs_offset.addressing(),
1884 rhs_offset.addressing(),
1885 ],
1886 node,
1887 comment,
1888 );
1889 }
1890
1891 pub fn add_div_i32(
1892 &mut self,
1893 dst_offset: &TypedRegister,
1894 lhs_offset: &TypedRegister,
1895 rhs_offset: &TypedRegister,
1896 node: &Node,
1897 comment: &str,
1898 ) {
1899 self.state.add_instruction(
1903 OpCode::DivI32,
1904 &[
1905 dst_offset.addressing(),
1906 lhs_offset.addressing(),
1907 rhs_offset.addressing(),
1908 ],
1909 node,
1910 comment,
1911 );
1912 }
1913
1914 pub fn add_sub_u32(
1915 &mut self,
1916 dst_offset: &TypedRegister,
1917 lhs_offset: &TypedRegister,
1918 rhs_offset: &TypedRegister,
1919 node: &Node,
1920 comment: &str,
1921 ) {
1922 self.state.add_instruction(
1926 OpCode::SubU32,
1927 &[
1928 dst_offset.addressing(),
1929 lhs_offset.addressing(),
1930 rhs_offset.addressing(),
1931 ],
1932 node,
1933 comment,
1934 );
1935 }
1936
1937 pub fn add_mul_i32(
1938 &mut self,
1939 dst_offset: &TypedRegister,
1940 lhs_offset: &TypedRegister,
1941 rhs_offset: &TypedRegister,
1942 node: &Node,
1943 comment: &str,
1944 ) {
1945 self.state.add_instruction(
1949 OpCode::MulU32,
1950 &[
1951 dst_offset.addressing(),
1952 lhs_offset.addressing(),
1953 rhs_offset.addressing(),
1954 ],
1955 node,
1956 comment,
1957 );
1958 }
1959
1960 pub fn add_neg_i32(
1961 &mut self,
1962 target: &TypedRegister,
1963 source: &TypedRegister,
1964 node: &Node,
1965 comment: &str,
1966 ) {
1967 self.state.add_instruction(
1970 OpCode::NegI32,
1971 &[target.addressing(), source.addressing()],
1972 node,
1973 comment,
1974 );
1975 }
1976
1977 pub fn add_sub_f32(
1978 &mut self,
1979 dst_offset: &TypedRegister,
1980 lhs_offset: &TypedRegister,
1981 rhs_offset: &TypedRegister,
1982 node: &Node,
1983 comment: &str,
1984 ) {
1985 self.state.add_instruction(
1989 OpCode::SubU32,
1990 &[
1991 dst_offset.addressing(),
1992 lhs_offset.addressing(),
1993 rhs_offset.addressing(),
1994 ],
1995 node,
1996 comment,
1997 );
1998 }
1999 pub fn add_mul_f32(
2000 &mut self,
2001 dst_offset: &TypedRegister,
2002 lhs_offset: &TypedRegister,
2003 rhs_offset: &TypedRegister,
2004 node: &Node,
2005 comment: &str,
2006 ) {
2007 self.state.add_instruction(
2011 OpCode::MulF32,
2012 &[
2013 dst_offset.addressing(),
2014 lhs_offset.addressing(),
2015 rhs_offset.addressing(),
2016 ],
2017 node,
2018 comment,
2019 );
2020 }
2021 pub fn add_div_f32(
2022 &mut self,
2023 dst_offset: &TypedRegister,
2024 lhs_offset: &TypedRegister,
2025 rhs_offset: &TypedRegister,
2026 node: &Node,
2027 comment: &str,
2028 ) {
2029 self.state.add_instruction(
2033 OpCode::DivF32,
2034 &[
2035 dst_offset.addressing(),
2036 lhs_offset.addressing(),
2037 rhs_offset.addressing(),
2038 ],
2039 node,
2040 comment,
2041 );
2042 }
2043
2044 pub fn add_add_f32(
2045 &mut self,
2046 dst_offset: &TypedRegister,
2047 lhs_offset: &TypedRegister,
2048 rhs_offset: &TypedRegister,
2049 node: &Node,
2050 comment: &str,
2051 ) {
2052 self.state.add_instruction(
2056 OpCode::AddU32,
2057 &[
2058 dst_offset.addressing(),
2059 lhs_offset.addressing(),
2060 rhs_offset.addressing(),
2061 ],
2062 node,
2063 comment,
2064 );
2065 }
2066
2067 pub fn add_neg_f32(
2068 &mut self,
2069 target: &TypedRegister,
2070 source: &TypedRegister,
2071 node: &Node,
2072 comment: &str,
2073 ) {
2074 self.state.add_instruction(
2077 OpCode::NegI32,
2078 &[target.addressing(), source.addressing()],
2079 node,
2080 comment,
2081 );
2082 }
2083
2084 pub fn add_lt_i32(
2085 &mut self,
2086 dest_bool_reg: &TypedRegister,
2087 lhs_offset: &TypedRegister,
2088 rhs_offset: &TypedRegister,
2089 node: &Node,
2090 comment: &str,
2091 ) {
2092 self.state.add_instruction(
2095 OpCode::LtI32,
2096 &[
2097 dest_bool_reg.addressing(),
2098 lhs_offset.addressing(),
2099 rhs_offset.addressing(),
2100 ],
2101 node,
2102 comment,
2103 );
2104 }
2105
2106 pub fn add_lt_u32(
2107 &mut self,
2108 dest_bool_reg: &TypedRegister,
2109 lhs_offset: &TypedRegister,
2110 rhs_offset: &TypedRegister,
2111 node: &Node,
2112 comment: &str,
2113 ) {
2114 self.state.add_instruction(
2117 OpCode::LtU32,
2118 &[
2119 dest_bool_reg.addressing(),
2120 lhs_offset.addressing(),
2121 rhs_offset.addressing(),
2122 ],
2123 node,
2124 comment,
2125 );
2126 }
2127
2128 pub fn add_le_u32(
2129 &mut self,
2130 dest_bool_reg: &TypedRegister,
2131 lhs_offset: &TypedRegister,
2132 rhs_offset: &TypedRegister,
2133 node: &Node,
2134 comment: &str,
2135 ) {
2136 self.state.add_instruction(
2139 OpCode::LeU32,
2140 &[
2141 dest_bool_reg.addressing(),
2142 lhs_offset.addressing(),
2143 rhs_offset.addressing(),
2144 ],
2145 node,
2146 comment,
2147 );
2148 }
2149
2150 pub fn add_le_i32(
2151 &mut self,
2152 dest_bool_reg: &TypedRegister,
2153 lhs_offset: &TypedRegister,
2154 rhs_offset: &TypedRegister,
2155 node: &Node,
2156 comment: &str,
2157 ) {
2158 self.state.add_instruction(
2161 OpCode::LeI32,
2162 &[
2163 dest_bool_reg.addressing(),
2164 lhs_offset.addressing(),
2165 rhs_offset.addressing(),
2166 ],
2167 node,
2168 comment,
2169 );
2170 }
2171
2172 pub fn add_gt_i32(
2173 &mut self,
2174 dest_bool_reg: &TypedRegister,
2175 lhs_offset: &TypedRegister,
2176 rhs_offset: &TypedRegister,
2177 node: &Node,
2178 comment: &str,
2179 ) {
2180 self.state.add_instruction(
2183 OpCode::GtI32,
2184 &[
2185 dest_bool_reg.addressing(),
2186 lhs_offset.addressing(),
2187 rhs_offset.addressing(),
2188 ],
2189 node,
2190 comment,
2191 );
2192 }
2193
2194 pub fn add_ge_i32(
2195 &mut self,
2196 dest_bool_reg: &TypedRegister,
2197 lhs_offset: &TypedRegister,
2198 rhs_offset: &TypedRegister,
2199 node: &Node,
2200 comment: &str,
2201 ) {
2202 self.state.add_instruction(
2205 OpCode::GeI32,
2206 &[
2207 dest_bool_reg.addressing(),
2208 lhs_offset.addressing(),
2209 rhs_offset.addressing(),
2210 ],
2211 node,
2212 comment,
2213 );
2214 }
2215
2216 pub fn add_ge_u32(
2217 &mut self,
2218 dest_bool_reg: &TypedRegister,
2219 lhs_offset: &TypedRegister,
2220 rhs_offset: &TypedRegister,
2221 node: &Node,
2222 comment: &str,
2223 ) {
2224 self.state.add_instruction(
2227 OpCode::GeU32,
2228 &[
2229 dest_bool_reg.addressing(),
2230 lhs_offset.addressing(),
2231 rhs_offset.addressing(),
2232 ],
2233 node,
2234 comment,
2235 );
2236 }
2237
2238 pub fn add_gt_u32(
2239 &mut self,
2240 dest_bool_reg: &TypedRegister,
2241 lhs_offset: &TypedRegister,
2242 rhs_offset: &TypedRegister,
2243 node: &Node,
2244 comment: &str,
2245 ) {
2246 self.state.add_instruction(
2249 OpCode::GtU32,
2250 &[
2251 dest_bool_reg.addressing(),
2252 lhs_offset.addressing(),
2253 rhs_offset.addressing(),
2254 ],
2255 node,
2256 comment,
2257 );
2258 }
2259
2260 pub fn add_meqz(
2261 &mut self,
2262 dest_bool_reg: &TypedRegister,
2263 addr: &TypedRegister,
2264 node: &Node,
2265 comment: &str,
2266 ) {
2267 self.state.add_instruction(
2268 OpCode::MovEqualToZero,
2269 &[dest_bool_reg.addressing(), addr.addressing()],
2270 node,
2271 comment,
2272 );
2273 }
2274
2275 pub fn add_trap(&mut self, trap_code: u8, node: &Node, comment: &str) {
2276 self.state
2277 .add_instruction(OpCode::Trap, &[trap_code], node, comment);
2278 }
2279
2280 pub fn add_cmp_reg(
2281 &mut self,
2282 dest_bool_reg: &TypedRegister,
2283 source_a: &TypedRegister,
2284 source_b: &TypedRegister,
2285 node: &Node,
2286 comment: &str,
2287 ) {
2288 self.state.add_instruction(
2289 OpCode::CmpReg,
2290 &[
2291 dest_bool_reg.addressing(),
2292 source_a.addressing(),
2293 source_b.addressing(),
2294 ],
2295 node,
2296 comment,
2297 );
2298 }
2299
2300 pub fn add_block_cmp(
2301 &mut self,
2302 dest_bool_reg: &TypedRegister,
2303 first_ptr: &TypedRegister,
2304 second_ptr: &TypedRegister,
2305 size: MemorySize,
2306 node: &Node,
2307 comment: &str,
2308 ) {
2309 let block_size_bytes = u32_to_bytes(size.0);
2310 self.state.add_instruction(
2311 OpCode::CmpBlock,
2312 &[
2313 dest_bool_reg.addressing(),
2314 first_ptr.addressing(),
2315 second_ptr.addressing(),
2316 block_size_bytes.0,
2317 block_size_bytes.1,
2318 block_size_bytes.2,
2319 block_size_bytes.3,
2320 ],
2321 node,
2322 comment,
2323 );
2324 }
2325
2326 pub fn add_map_has(
2329 &mut self,
2330 dest_reg: &TypedRegister,
2331 self_addr: &PointerLocation,
2332 key_addr: &TypedRegister,
2333 node: &Node,
2334 comment: &str,
2335 ) {
2336 matches!(
2337 self_addr.ptr_reg.ty().kind,
2338 BasicTypeKind::DynamicLengthMapView(_, _)
2339 );
2340 self.state.add_instruction(
2341 OpCode::MapHas,
2342 &[
2343 dest_reg.addressing(),
2344 self_addr.addressing(),
2345 key_addr.addressing(),
2346 ],
2347 node,
2348 comment,
2349 );
2350 }
2351
2352 pub fn add_map_remove(
2353 &mut self,
2354 self_addr: &PointerLocation,
2355 key_addr: &TypedRegister,
2356 node: &Node,
2357 comment: &str,
2358 ) {
2359 matches!(
2360 self_addr.ptr_reg.ty().kind,
2361 BasicTypeKind::DynamicLengthMapView(_, _)
2362 );
2363 self.state.add_instruction(
2364 OpCode::MapRemove,
2365 &[self_addr.addressing(), key_addr.addressing()],
2366 node,
2367 comment,
2368 );
2369 }
2370
2371 pub fn add_map_get_entry_location(
2372 &mut self,
2373 target_entry_addr: &TypedRegister,
2374 map_self_addr: &PointerLocation,
2375 key: &TypedRegister,
2376 node: &Node,
2377 comment: &str,
2378 ) {
2379 self.state.add_instruction(
2381 OpCode::MapGetEntryLocation,
2382 &[
2383 target_entry_addr.addressing(),
2384 map_self_addr.addressing(),
2385 key.addressing(),
2386 ],
2387 node,
2388 comment,
2389 );
2390 }
2391
2392 pub fn add_map_get_or_reserve_entry_location(
2393 &mut self,
2394 target_entry_reg: &TypedRegister,
2395 map_self_addr: &PointerLocation,
2396 key: &TypedRegister,
2397 node: &Node,
2398 comment: &str,
2399 ) {
2400 self.state.add_instruction(
2401 OpCode::MapGetOrReserveEntryLocation,
2402 &[
2403 target_entry_reg.addressing(),
2404 map_self_addr.addressing(),
2405 key.addressing(),
2406 ],
2407 node,
2408 comment,
2409 );
2410 }
2411
2412 pub fn add_int_rnd(
2413 &mut self,
2414 dest: &TypedRegister,
2415 self_int: &TypedRegister,
2416 node: &Node,
2417 comment: &str,
2418 ) {
2419 assert!(dest.ty().is_int());
2420 assert!(self_int.ty().is_int());
2421 self.state.add_instruction(
2422 OpCode::IntToRnd,
2423 &[dest.addressing(), self_int.addressing()],
2424 node,
2425 comment,
2426 );
2427 }
2428
2429 pub fn add_int_min(
2430 &mut self,
2431 dest: &TypedRegister,
2432 self_int: &TypedRegister,
2433 other_int: &TypedRegister,
2434 node: &Node,
2435 comment: &str,
2436 ) {
2437 self.state.add_instruction(
2441 OpCode::IntMin,
2442 &[
2443 dest.addressing(),
2444 self_int.addressing(),
2445 other_int.addressing(),
2446 ],
2447 node,
2448 comment,
2449 );
2450 }
2451
2452 pub fn add_int_max(
2453 &mut self,
2454 dest: &TypedRegister,
2455 self_int: &TypedRegister,
2456 other_int: &TypedRegister,
2457 node: &Node,
2458 comment: &str,
2459 ) {
2460 self.state.add_instruction(
2464 OpCode::IntMax,
2465 &[
2466 dest.addressing(),
2467 self_int.addressing(),
2468 other_int.addressing(),
2469 ],
2470 node,
2471 comment,
2472 );
2473 }
2474
2475 pub fn add_int_clamp(
2476 &mut self,
2477 dest: &TypedRegister,
2478 self_int: &TypedRegister,
2479 min_int: &TypedRegister,
2480 max_int: &TypedRegister,
2481 node: &Node,
2482 comment: &str,
2483 ) {
2484 assert!(dest.ty().is_int());
2485 assert!(self_int.ty().is_int());
2486 assert!(min_int.ty().is_int());
2487 assert!(max_int.ty().is_int());
2488 self.state.add_instruction(
2489 OpCode::IntClamp,
2490 &[
2491 dest.addressing(),
2492 self_int.addressing(),
2493 min_int.addressing(),
2494 max_int.addressing(),
2495 ],
2496 node,
2497 comment,
2498 );
2499 }
2500
2501 pub fn add_int_abs(
2502 &mut self,
2503 dest: &TypedRegister,
2504 self_int: &TypedRegister,
2505 node: &Node,
2506 comment: &str,
2507 ) {
2508 self.state.add_instruction(
2511 OpCode::IntAbs,
2512 &[dest.addressing(), self_int.addressing()],
2513 node,
2514 comment,
2515 );
2516 }
2517
2518 pub fn add_int_to_float(
2519 &mut self,
2520 dest: &TypedRegister,
2521 self_int: &TypedRegister,
2522 node: &Node,
2523 comment: &str,
2524 ) {
2525 self.state.add_instruction(
2528 OpCode::IntToFloat,
2529 &[dest.addressing(), self_int.addressing()],
2530 node,
2531 comment,
2532 );
2533 }
2534
2535 pub fn add_int_to_string(
2536 &mut self,
2537 dest: &TypedRegister,
2538 self_int: &TypedRegister,
2539 node: &Node,
2540 comment: &str,
2541 ) {
2542 assert!(self_int.ty().is_int());
2544 self.state.add_instruction(
2545 OpCode::IntToString,
2546 &[dest.addressing(), self_int.addressing()],
2547 node,
2548 comment,
2549 );
2550 }
2551
2552 pub fn bool_to_string(
2553 &mut self,
2554 dest_str: &TypedRegister,
2555 self_bool: &TypedRegister,
2556 node: &Node,
2557 comment: &str,
2558 ) {
2559 assert!(self_bool.ty().is_bool());
2561 self.state.add_instruction(
2562 OpCode::BoolToString,
2563 &[dest_str.addressing(), self_bool.addressing()],
2564 node,
2565 comment,
2566 );
2567 }
2568
2569 pub fn byte_to_string(
2570 &mut self,
2571 dest_str: &TypedRegister,
2572 self_bool: &TypedRegister,
2573 node: &Node,
2574 comment: &str,
2575 ) {
2576 assert!(self_bool.ty().is_byte());
2578 self.state.add_instruction(
2579 OpCode::ByteToString,
2580 &[dest_str.addressing(), self_bool.addressing()],
2581 node,
2582 comment,
2583 );
2584 }
2585
2586 pub fn add_codepoint_to_string(
2587 &mut self,
2588 dest_str: &TypedRegister,
2589 self_char: &TypedRegister,
2590 node: &Node,
2591 comment: &str,
2592 ) {
2593 assert!(self_char.ty().is_codepoint());
2595 self.state.add_instruction(
2596 OpCode::CodepointToString,
2597 &[dest_str.addressing(), self_char.addressing()],
2598 node,
2599 comment,
2600 );
2601 }
2602
2603 pub fn add_string_to_string(
2604 &mut self,
2605 dest_str: &TypedRegister,
2606 self_str: &TypedRegister,
2607 node: &Node,
2608 comment: &str,
2609 ) {
2610 assert!(self_str.ty().is_str());
2612 self.state.add_instruction(
2613 OpCode::StringToString,
2614 &[dest_str.addressing(), self_str.addressing()],
2615 node,
2616 comment,
2617 );
2618 }
2619
2620 pub fn add_string_starts_with(
2621 &mut self,
2622 dest_bool: &TypedRegister,
2623 source_str: &TypedRegister,
2624 other_str: &TypedRegister,
2625 node: &Node,
2626 comment: &str,
2627 ) {
2628 assert!(dest_bool.ty().is_bool());
2629 assert!(other_str.ty().is_str());
2631 self.state.add_instruction(
2632 OpCode::StringStartsWith,
2633 &[
2634 dest_bool.addressing(),
2635 source_str.addressing(),
2636 other_str.addressing(),
2637 ],
2638 node,
2639 comment,
2640 );
2641 }
2642
2643 pub fn add_string_to_int(
2644 &mut self,
2645 dest_tuple: &TypedRegister,
2646 source_str: &TypedRegister,
2647 node: &Node,
2648 comment: &str,
2649 ) {
2650 self.state.add_instruction(
2651 OpCode::StringToInt,
2652 &[dest_tuple.addressing(), source_str.addressing()],
2653 node,
2654 comment,
2655 );
2656 }
2657
2658 pub fn add_string_to_float(
2659 &mut self,
2660 dest_tuple: &TypedRegister,
2661 source_str: &TypedRegister,
2662 node: &Node,
2663 comment: &str,
2664 ) {
2665 self.state.add_instruction(
2666 OpCode::StringToFloat,
2667 &[dest_tuple.addressing(), source_str.addressing()],
2668 node,
2669 comment,
2670 );
2671 }
2672
2673 pub fn add_float_to_string(
2674 &mut self,
2675 dest_str: &TypedRegister,
2676 self_float: &TypedRegister,
2677 node: &Node,
2678 comment: &str,
2679 ) {
2680 assert!(self_float.ty().is_float());
2682 self.state.add_instruction(
2683 OpCode::FloatToString,
2684 &[dest_str.addressing(), self_float.addressing()],
2685 node,
2686 comment,
2687 );
2688 }
2689
2690 pub fn add_float_round(
2691 &mut self,
2692 dest_int: &TypedRegister,
2693 self_float: &TypedRegister,
2694 node: &Node,
2695 comment: &str,
2696 ) {
2697 assert!(self_float.ty().is_float());
2699 self.state.add_instruction(
2700 OpCode::FloatRound,
2701 &[dest_int.addressing(), self_float.addressing()],
2702 node,
2703 comment,
2704 );
2705 }
2706
2707 pub fn add_float_floor(
2708 &mut self,
2709 dest_int: &TypedRegister,
2710 self_float: &TypedRegister,
2711 node: &Node,
2712 comment: &str,
2713 ) {
2714 self.state.add_instruction(
2717 OpCode::FloatFloor,
2718 &[dest_int.addressing(), self_float.addressing()],
2719 node,
2720 comment,
2721 );
2722 }
2723
2724 pub fn add_float_sqrt(
2725 &mut self,
2726 dest_float: &TypedRegister,
2727 self_float: &TypedRegister,
2728 node: &Node,
2729 comment: &str,
2730 ) {
2731 self.state.add_instruction(
2734 OpCode::FloatSqrt,
2735 &[dest_float.addressing(), self_float.addressing()],
2736 node,
2737 comment,
2738 );
2739 }
2740
2741 pub fn add_float_sign(
2742 &mut self,
2743 dest_float: &TypedRegister,
2744 self_float: &TypedRegister,
2745 node: &Node,
2746 comment: &str,
2747 ) {
2748 assert!(dest_float.ty().is_float());
2749 assert!(self_float.ty().is_float());
2750 self.state.add_instruction(
2751 OpCode::FloatSign,
2752 &[dest_float.addressing(), self_float.addressing()],
2753 node,
2754 comment,
2755 );
2756 }
2757
2758 pub fn add_float_abs(
2759 &mut self,
2760 dest_float: &TypedRegister,
2761 self_float: &TypedRegister,
2762 node: &Node,
2763 comment: &str,
2764 ) {
2765 assert!(dest_float.ty().is_float());
2766 assert!(self_float.ty().is_float());
2767 self.state.add_instruction(
2768 OpCode::FloatAbs,
2769 &[dest_float.addressing(), self_float.addressing()],
2770 node,
2771 comment,
2772 );
2773 }
2774
2775 pub fn add_float_prnd(
2776 &mut self,
2777 dest_float: &TypedRegister,
2778 self_float: &TypedRegister,
2779 node: &Node,
2780 comment: &str,
2781 ) {
2782 assert!(dest_float.ty().is_float());
2783 assert!(self_float.ty().is_float());
2784 self.state.add_instruction(
2785 OpCode::FloatPseudoRandom,
2786 &[dest_float.addressing(), self_float.addressing()],
2787 node,
2788 comment,
2789 );
2790 }
2791
2792 pub fn add_float_sin(
2793 &mut self,
2794 dest_float: &TypedRegister,
2795 self_float: &TypedRegister,
2796 node: &Node,
2797 comment: &str,
2798 ) {
2799 assert!(dest_float.ty().is_float());
2800 assert!(self_float.ty().is_float());
2801 self.state.add_instruction(
2802 OpCode::FloatSin,
2803 &[dest_float.addressing(), self_float.addressing()],
2804 node,
2805 comment,
2806 );
2807 }
2808
2809 pub fn add_float_cos(
2810 &mut self,
2811 dest_float: &TypedRegister,
2812 self_float: &TypedRegister,
2813 node: &Node,
2814 comment: &str,
2815 ) {
2816 assert!(dest_float.ty().is_float());
2817 assert!(self_float.ty().is_float());
2818 self.state.add_instruction(
2819 OpCode::FloatCos,
2820 &[dest_float.addressing(), self_float.addressing()],
2821 node,
2822 comment,
2823 );
2824 }
2825
2826 pub fn add_float_acos(
2827 &mut self,
2828 dest_float: &TypedRegister,
2829 self_float: &TypedRegister,
2830 node: &Node,
2831 comment: &str,
2832 ) {
2833 assert!(dest_float.ty().is_float());
2834 assert!(self_float.ty().is_float());
2835 self.state.add_instruction(
2836 OpCode::FloatAcos,
2837 &[dest_float.addressing(), self_float.addressing()],
2838 node,
2839 comment,
2840 );
2841 }
2842
2843 pub fn add_float_asin(
2844 &mut self,
2845 dest_float: &TypedRegister,
2846 self_float: &TypedRegister,
2847 node: &Node,
2848 comment: &str,
2849 ) {
2850 assert!(dest_float.ty().is_float());
2851 assert!(self_float.ty().is_float());
2852 self.state.add_instruction(
2853 OpCode::FloatAsin,
2854 &[dest_float.addressing(), self_float.addressing()],
2855 node,
2856 comment,
2857 );
2858 }
2859
2860 pub fn add_float_atan2(
2861 &mut self,
2862 dest_float: &TypedRegister,
2863 self_float: &TypedRegister,
2864 node: &Node,
2865 comment: &str,
2866 ) {
2867 assert!(dest_float.ty().is_float());
2868 assert!(self_float.ty().is_float());
2869 self.state.add_instruction(
2870 OpCode::FloatAtan2,
2871 &[dest_float.addressing(), self_float.addressing()],
2872 node,
2873 comment,
2874 );
2875 }
2876
2877 pub fn add_float_min(
2878 &mut self,
2879 dest_float: &TypedRegister,
2880 self_float: &TypedRegister,
2881 other: &TypedRegister,
2882 node: &Node,
2883 comment: &str,
2884 ) {
2885 assert!(dest_float.ty().is_float());
2886 assert!(self_float.ty().is_float());
2887 self.state.add_instruction(
2888 OpCode::FloatMin,
2889 &[
2890 dest_float.addressing(),
2891 self_float.addressing(),
2892 other.addressing(),
2893 ],
2894 node,
2895 comment,
2896 );
2897 }
2898
2899 pub fn add_float_max(
2900 &mut self,
2901 dest_float: &TypedRegister,
2902 self_float: &TypedRegister,
2903 max_float: &TypedRegister,
2904 node: &Node,
2905 comment: &str,
2906 ) {
2907 assert!(dest_float.ty().is_float());
2908 assert!(self_float.ty().is_float());
2909 assert!(max_float.ty().is_float());
2910 self.state.add_instruction(
2911 OpCode::FloatMax,
2912 &[
2913 dest_float.addressing(),
2914 self_float.addressing(),
2915 max_float.addressing(),
2916 ],
2917 node,
2918 comment,
2919 );
2920 }
2921
2922 pub fn add_float_clamp(
2923 &mut self,
2924 dest_float: &TypedRegister,
2925 self_float: &TypedRegister,
2926 min_float: &TypedRegister,
2927 max_float: &TypedRegister,
2928 node: &Node,
2929 comment: &str,
2930 ) {
2931 assert!(dest_float.ty().is_float());
2932 assert!(self_float.ty().is_float());
2933 assert!(min_float.ty().is_float());
2934 assert!(max_float.ty().is_float());
2935
2936 self.state.add_instruction(
2937 OpCode::FloatClamp,
2938 &[
2939 dest_float.addressing(),
2940 min_float.addressing(),
2941 self_float.addressing(),
2942 max_float.addressing(),
2943 ],
2944 node,
2945 comment,
2946 );
2947 }
2948
2949 pub fn add_sparse_iter_init(
2950 &mut self,
2951 iterator_target: &TypedRegister,
2952 pointer_to_sparse_header: &TypedRegister,
2953 node: &Node,
2954 comment: &str,
2955 ) {
2956 self.state.add_instruction(
2957 OpCode::SparseIterInit,
2958 &[
2959 iterator_target.addressing(),
2960 pointer_to_sparse_header.addressing(),
2961 ],
2962 node,
2963 comment,
2964 );
2965 }
2966
2967 pub fn add_sparse_iter_next_placeholder(
2968 &mut self,
2969 iterator_target: &TypedRegister,
2970 closure_variable: &TypedRegister,
2971 node: &Node,
2972 comment: &str,
2973 ) -> PatchPosition {
2974 let position = self.position();
2975 self.state.add_instruction(
2976 OpCode::SparseIterNext,
2977 &[
2978 iterator_target.addressing(),
2979 closure_variable.addressing(),
2980 0,
2981 0,
2982 ],
2983 node,
2984 comment,
2985 );
2986 PatchPosition(position)
2987 }
2988
2989 pub fn add_sparse_iter_next_pair_placeholder(
2990 &mut self,
2991 iterator_target: &TypedRegister,
2992 closure_variable: &TypedRegister,
2993 closure_variable_b: &TypedRegister,
2994 node: &Node,
2995 comment: &str,
2996 ) -> PatchPosition {
2997 let position = self.position();
2998 self.state.add_instruction(
2999 OpCode::SparseIterNextPair,
3000 &[
3001 iterator_target.addressing(),
3002 closure_variable.addressing(),
3003 closure_variable_b.addressing(),
3004 0,
3005 0,
3006 ],
3007 node,
3008 comment,
3009 );
3010 PatchPosition(position)
3011 }
3012}