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