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_swap(
411 &mut self,
412 vec_self_addr: &TypedRegister,
413 int_index_a: &TypedRegister,
414 int_index_b: &TypedRegister,
415 node: &Node,
416 comment: &str,
417 ) {
418 assert!(matches!(
419 vec_self_addr.ty().kind,
420 BasicTypeKind::DynamicLengthVecView(_)
421 ));
422 assert_eq!(int_index_a.size(), int_index_b.size());
423 self.state.add_instruction(
424 OpCode::VecSwap,
425 &[
426 vec_self_addr.addressing(),
427 int_index_a.addressing(),
428 int_index_b.addressing(),
429 ],
430 node,
431 comment,
432 );
433 }
434
435 pub fn add_vec_subscript(
436 &mut self,
437 target: &TypedRegister,
438 self_addr: &TypedRegister,
439 index: &TypedRegister,
440 element_size: MemorySize,
441 node: &Node,
442 comment: &str,
443 ) {
444 let element_size_bytes = u32_to_bytes(element_size.0);
452 self.state.add_instruction(
453 OpCode::VecGet,
454 &[
455 target.addressing(),
456 self_addr.addressing(),
457 index.addressing(),
458 element_size_bytes.0,
459 element_size_bytes.1,
460 element_size_bytes.2,
461 element_size_bytes.3,
462 ],
463 node,
464 comment,
465 );
466 }
467
468 pub fn add_vec_get_range(
469 &mut self,
470 target: &TypedRegister,
471 vec_self_addr: &TypedRegister,
472 range_header: &TypedRegister,
473 node: &Node,
474 comment: &str,
475 ) {
476 assert!(matches!(
477 vec_self_addr.ty().kind,
478 BasicTypeKind::DynamicLengthVecView(_)
479 ));
480
481 self.state.add_instruction(
482 OpCode::VecGetRange,
483 &[
484 target.addressing(),
485 vec_self_addr.addressing(),
486 range_header.addressing(),
487 ],
488 node,
489 comment,
490 );
491 }
492
493 pub fn add_vec_push_addr(
494 &mut self,
495 target_reg: &TypedRegister,
496 vec_self_reg: &TypedRegister,
497 node: &Node,
498 comment: &str,
499 ) {
500 self.state.add_instruction(
501 OpCode::VecPushAddr,
502 &[target_reg.addressing(), vec_self_reg.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::VecIterNext,
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::VecIterNextPair,
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_offset_with_variable_size(
847 &mut self,
848 target_output_destination: &PointerLocation,
849 source_memory_location: &PointerLocation,
850 memory_size_reg: &TypedRegister,
851 node: &Node,
852 comment: &str,
853 ) {
854 self.state.add_instruction(
855 OpCode::BlockCopyWithOffsetsVariableSize,
856 &[
857 target_output_destination.ptr_reg.addressing(),
858 source_memory_location.ptr_reg.addressing(),
859 memory_size_reg.addressing(),
860 ],
861 node,
862 comment,
863 );
864 }
865
866 pub fn add_block_copy_with_immediate_size(
867 &mut self,
868 target_base_ptr_reg: &PointerLocation,
869 source_base_ptr_reg: &PointerLocation,
870 memory_size: MemorySize,
871 node: &Node,
872 comment: &str,
873 ) {
874 let size_bytes = u32_to_bytes(memory_size.0);
875
876 self.state.add_instruction(
877 OpCode::BlockCopy,
878 &[
879 target_base_ptr_reg.addressing(),
880 source_base_ptr_reg.addressing(),
881 size_bytes.0,
882 size_bytes.1,
883 size_bytes.2,
884 size_bytes.3,
885 ],
886 node,
887 comment,
888 );
889 }
890
891 pub fn add_panic(&mut self, str: &TypedRegister, node: &Node, comment: &str) {
892 self.state
893 .add_instruction(OpCode::Panic, &[str.addressing()], node, comment);
894 }
895
896 pub fn add_halt(&mut self, node: &Node, comment: &str) {
897 self.state.add_instruction(OpCode::Hlt, &[], node, comment);
898 }
899
900 pub fn add_step(&mut self, node: &Node, comment: &str) {
901 self.state.add_instruction(OpCode::Step, &[], node, comment);
902 }
903 pub fn add_call(&mut self, function_ip: &InstructionPosition, node: &Node, comment: &str) {
904 let ip_bytes = function_ip.0.to_le_bytes();
905 self.state.add_instruction(
906 OpCode::Call,
907 &[ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3]],
908 node,
909 comment,
910 );
911 }
912
913 pub fn add_host_call(
914 &mut self,
915 host_function_id: u16,
916 arguments_count: u8,
917 node: &Node,
918 comment: &str,
919 ) {
920 let ip_bytes = Self::u16_to_octets(host_function_id);
921 self.state.add_instruction(
922 OpCode::HostCall,
923 &[ip_bytes.0, ip_bytes.1, arguments_count],
924 node,
925 comment,
926 );
927 }
928
929 pub fn patch_jump(
932 &mut self,
933 patch_position: PatchPosition,
934 target_position: &InstructionPosition,
935 ) {
936 const JMP_IF_NOT: u8 = OpCode::BTrue as u8;
937 const JMP_IF: u8 = OpCode::BFalse as u8;
938 const JMP: u8 = OpCode::B as u8;
939
940 const VEC_ITER_NEXT: u8 = OpCode::VecIterNext as u8;
941 const VEC_ITER_NEXT_PAIR: u8 = OpCode::VecIterNextPair as u8;
942 const MAP_ITER_NEXT: u8 = OpCode::MapIterNext as u8;
943 const MAP_ITER_NEXT_PAIR: u8 = OpCode::MapIterNextPair as u8;
944
945 const SPARSE_ITER_NEXT: u8 = OpCode::SparseIterNext as u8;
946 const SPARSE_ITER_NEXT_PAIR: u8 = OpCode::SparseIterNextPair as u8;
947
948 const RANGE_ITER_NEXT: u8 = OpCode::RangeIterNext as u8;
949
950 let instruction = &mut self.state.instructions[patch_position.0.0 as usize];
954 let effective_pc_address = patch_position.0 + ProgramCounterDelta(1); let delta = *target_position - effective_pc_address;
956 let raw = delta.0;
957 let delta_bytes = raw.to_le_bytes();
958
959 match instruction.opcode {
960 JMP_IF_NOT | JMP_IF => {
961 instruction.operands[1] = delta_bytes[0];
962 instruction.operands[2] = delta_bytes[1];
963 }
964
965 JMP => {
966 instruction.operands[0] = delta_bytes[0];
967 instruction.operands[1] = delta_bytes[1];
968 }
969
970 SPARSE_ITER_NEXT | VEC_ITER_NEXT | MAP_ITER_NEXT | RANGE_ITER_NEXT => {
971 instruction.operands[2] = delta_bytes[0];
972 instruction.operands[3] = delta_bytes[1];
973 }
974
975 SPARSE_ITER_NEXT_PAIR | VEC_ITER_NEXT_PAIR | MAP_ITER_NEXT_PAIR => {
976 instruction.operands[3] = delta_bytes[0];
977 instruction.operands[4] = delta_bytes[1];
978 }
979
980 _ => panic!("Attempted to patch a non-jump instruction at position {patch_position:?}"),
981 }
982 }
983
984 pub fn patch_jump_here(&mut self, jump_position: PatchPosition) {
986 self.patch_jump(jump_position, &self.position());
987 }
988
989 pub fn add_jmp(&mut self, pc: InstructionPosition, node: &Node, comment: &str) {
990 let delta_bytes = self.calculate_pc_delta_bytes(pc);
991 self.state
992 .add_instruction(OpCode::B, &[delta_bytes[0], delta_bytes[1]], node, comment);
993 }
994
995 const fn calculate_pc_delta(
996 &self,
997 target_instruction: InstructionPosition,
998 ) -> ProgramCounterDelta {
999 ProgramCounterDelta(
1000 ((target_instruction.0 as i32) - ((self.position().0 + 1) as i32)) as i16,
1001 )
1002 }
1003 const fn calculate_pc_delta_bytes(&self, pc: InstructionPosition) -> [u8; 2] {
1004 let delta = self.calculate_pc_delta(pc);
1005
1006 delta.0.to_le_bytes()
1007 }
1008
1009 pub fn add_frame_memory_clear(
1010 &mut self,
1011 frame_region: FrameMemoryRegion,
1012 node: &Node,
1013 comment: &str,
1014 ) {
1015 let addr_bytes = u32_to_bytes(frame_region.addr.0);
1016 let size_bytes = u32_to_bytes(frame_region.size.0);
1017 self.state.add_instruction(
1018 OpCode::FrameMemClr,
1019 &[
1020 addr_bytes.0,
1021 addr_bytes.1,
1022 addr_bytes.2,
1023 addr_bytes.3,
1024 size_bytes.0,
1025 size_bytes.1,
1026 size_bytes.2,
1027 size_bytes.3,
1028 ],
1029 node,
1030 comment,
1031 );
1032 }
1033
1034 pub fn add_map_iter_init(
1037 &mut self,
1038 iterator_target: &TypedRegister,
1039 pointer_to_map_header: &TypedRegister,
1040 node: &Node,
1041 comment: &str,
1042 ) {
1043 self.state.add_instruction(
1044 OpCode::MapIterInit,
1045 &[
1046 iterator_target.addressing(),
1047 pointer_to_map_header.addressing(),
1048 ],
1049 node,
1050 comment,
1051 );
1052 }
1053
1054 pub fn add_map_iter_next_placeholder(
1055 &mut self,
1056 iterator_target: &TypedRegister,
1057 closure_variable: &TypedRegister,
1058 node: &Node,
1059 comment: &str,
1060 ) -> PatchPosition {
1061 let position = self.position();
1062 self.state.add_instruction(
1063 OpCode::MapIterNext,
1064 &[
1065 iterator_target.addressing(),
1066 closure_variable.addressing(),
1067 0,
1068 ],
1069 node,
1070 comment,
1071 );
1072 PatchPosition(position)
1073 }
1074
1075 pub fn add_map_iter_next_pair_placeholder(
1076 &mut self,
1077 iterator_target: &TypedRegister,
1078 closure_variable: &TypedRegister,
1079 closure_variable_b: &TypedRegister,
1080 node: &Node,
1081 comment: &str,
1082 ) -> PatchPosition {
1083 let position = self.position();
1084 self.state.add_instruction(
1085 OpCode::MapIterNextPair,
1086 &[
1087 iterator_target.addressing(),
1088 closure_variable.addressing(),
1089 closure_variable_b.addressing(),
1090 0,
1091 ],
1092 node,
1093 comment,
1094 );
1095 PatchPosition(position)
1096 }
1097
1098 pub fn add_range_init(
1099 &mut self,
1100 target_range_iterator: &TypedRegister,
1101 min_reg: &TypedRegister,
1102 max_reg: &TypedRegister,
1103 is_inclusive_reg: &TypedRegister,
1104 node: &Node,
1105 comment: &str,
1106 ) {
1107 self.state.add_instruction(
1108 OpCode::RangeInit,
1109 &[
1110 target_range_iterator.addressing(),
1111 min_reg.addressing(),
1112 max_reg.addressing(),
1113 is_inclusive_reg.addressing(),
1114 ],
1115 node,
1116 comment,
1117 );
1118 }
1119
1120 pub fn add_range_iter_next_placeholder(
1121 &mut self,
1122 iterator_target: &TypedRegister,
1123 closure_variable: &TypedRegister,
1124 node: &Node,
1125
1126 comment: &str,
1127 ) -> PatchPosition {
1128 let position = self.position();
1129 self.state.add_instruction(
1130 OpCode::RangeIterNext,
1131 &[
1132 iterator_target.addressing(),
1133 closure_variable.addressing(),
1134 0,
1135 0,
1136 ],
1137 node,
1138 comment,
1139 );
1140 PatchPosition(position)
1141 }
1142
1143 pub fn add_string_append(
1144 &mut self,
1145 dst_offset: &TypedRegister,
1146 lhs_offset: &TypedRegister,
1147 rhs_offset: &TypedRegister,
1148 node: &Node,
1149 comment: &str,
1150 ) {
1151 self.state.add_instruction(
1152 OpCode::StringAppend,
1153 &[
1154 dst_offset.addressing(),
1155 lhs_offset.addressing(),
1156 rhs_offset.addressing(),
1157 ],
1158 node,
1159 comment,
1160 );
1161 }
1162
1163 pub fn add_string_cmp(
1164 &mut self,
1165 dest_bool_reg: &TypedRegister,
1166 a: &TypedRegister,
1167 b: &TypedRegister,
1168 node: &Node,
1169 comment: &str,
1170 ) {
1171 self.state.add_instruction(
1172 OpCode::StringCmp,
1173 &[dest_bool_reg.addressing(), a.addressing(), b.addressing()],
1174 node,
1175 comment,
1176 );
1177 }
1178
1179 pub fn add_fixed_capacity_array_init_fill_capacity_and_len(
1180 &mut self,
1181 target_vec_to_init: &PointerLocation,
1182 capacity: u16,
1183 element_size: &MemorySize,
1184 node: &Node,
1185 comment: &str,
1186 ) {
1187 debug_assert!(capacity > 0);
1189
1190 let capacity_bytes = u16_to_u8_pair(capacity);
1191 let element_bytes = u32_to_bytes(element_size.0);
1192
1193 self.state.add_instruction(
1194 OpCode::ArrayInitWithLenAndCapacity,
1195 &[
1196 target_vec_to_init.ptr_reg.addressing(),
1197 capacity_bytes.0,
1198 capacity_bytes.1,
1199 element_bytes.0,
1200 element_bytes.1,
1201 element_bytes.2,
1202 element_bytes.3,
1203 ],
1204 node,
1205 comment,
1206 );
1207 }
1208
1209 pub fn add_map_init_set_capacity(
1210 &mut self,
1211 target_map_to_init: &PointerLocation,
1212 logical_limit: CountU16,
1213 key_size_reg: &TypedRegister,
1214 key_alignment: MemoryAlignment,
1215 value_size_reg: &TypedRegister,
1216 value_alignment: MemoryAlignment,
1217 node: &Node,
1218 comment: &str,
1219 ) {
1220 debug_assert!(logical_limit.0 > 0);
1221
1222 let logical_limit_bytes = u16_to_u8_pair(logical_limit.0);
1223
1224 let key_alignment_usize: usize = key_alignment.into();
1225 let value_alignment_usize: usize = value_alignment.into();
1226
1227 self.state.add_instruction(
1229 OpCode::MapInitWithCapacityAndKeyAndTupleSizeAddr,
1230 &[
1231 target_map_to_init.ptr_reg.addressing(),
1232 logical_limit_bytes.0,
1233 logical_limit_bytes.1,
1234 key_size_reg.addressing(),
1235 key_alignment_usize as u8,
1236 value_size_reg.addressing(),
1237 value_alignment_usize as u8,
1238 ],
1239 node,
1240 comment,
1241 );
1242 }
1243
1244 pub fn add_map_overwrite(
1245 &mut self,
1246 destination_map: &PointerLocation,
1247 source_map: &PointerLocation,
1248 node: &Node,
1249 comment: &str,
1250 ) {
1251 self.state.add_instruction(
1252 OpCode::MapOverwrite,
1253 &[destination_map.addressing(), source_map.addressing()],
1254 node,
1255 comment,
1256 );
1257 }
1258
1259 pub fn add_range_iter_init(
1260 &mut self,
1261 iterator_target: &TypedRegister,
1262 range_source_header: &TypedRegister,
1263 node: &Node,
1264 comment: &str,
1265 ) {
1266 self.state.add_instruction(
1270 OpCode::RangeIterInit,
1271 &[
1272 iterator_target.addressing(),
1273 range_source_header.addressing(),
1274 ],
1275 node,
1276 comment,
1277 );
1278 }
1279
1280 pub fn add_vec_copy(
1281 &mut self,
1282 target_vec: &PointerLocation,
1283 source_vec: &PointerLocation,
1284 node: &Node,
1285 comment: &str,
1286 ) {
1287 self.state.add_instruction(
1288 OpCode::VecCopy,
1289 &[
1290 target_vec.ptr_reg.addressing(),
1291 source_vec.ptr_reg.addressing(),
1292 ],
1293 node,
1294 comment,
1295 );
1296 }
1297
1298 pub fn add_vec_init_set_capacity(
1299 &mut self,
1300 target_vec_to_init: &PointerLocation,
1301 capacity: CountU16,
1302 element_size: &MemorySize,
1303 node: &Node,
1304 comment: &str,
1305 ) {
1306 debug_assert!(capacity.0 > 0);
1308
1309 let capacity_bytes = u16_to_u8_pair(capacity.0);
1310 let element_bytes = u32_to_bytes(element_size.0);
1311 self.state.add_instruction(
1312 OpCode::VecInit,
1313 &[
1314 target_vec_to_init.ptr_reg.addressing(),
1315 capacity_bytes.0,
1316 capacity_bytes.1,
1317 element_bytes.0,
1318 element_bytes.1,
1319 element_bytes.2,
1320 element_bytes.3,
1321 ],
1322 node,
1323 comment,
1324 );
1325 }
1326
1327 pub fn add_vec_iter_init(
1328 &mut self,
1329 iterator_target: &TypedRegister,
1330 pointer_to_vec_header: &TypedRegister,
1331 element_size: MemorySize,
1332 node: &Node,
1333 comment: &str,
1334 ) {
1335 let element_size_bytes = u32_to_bytes(element_size.0);
1336 self.state.add_instruction(
1337 OpCode::VecIterInit,
1338 &[
1339 iterator_target.addressing(),
1340 pointer_to_vec_header.addressing(),
1341 element_size_bytes.0,
1342 element_size_bytes.1,
1343 element_size_bytes.2,
1344 element_size_bytes.3,
1345 ],
1346 node,
1347 comment,
1348 );
1349 }
1350
1351 pub fn add_vec_iter_next(
1352 &mut self,
1353 iterator_target: &TypedRegister,
1354 closure_variable: &TypedRegister,
1355 instruction_position: InstructionPosition,
1356 node: &Node,
1357 comment: &str,
1358 ) {
1359 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1360 self.state.add_instruction(
1361 OpCode::VecIterNext,
1362 &[
1363 iterator_target.addressing(),
1364 closure_variable.addressing(),
1365 bytes[0],
1366 bytes[1],
1367 ],
1368 node,
1369 comment,
1370 );
1371 }
1372
1373 pub fn add_vec_iter_next_pair(
1374 &mut self,
1375 iterator_target: &TypedRegister,
1376 closure_variable_key: &TypedRegister,
1377 closure_variable_value: &TypedRegister,
1378 instruction_position: InstructionPosition,
1379 node: &Node,
1380 comment: &str,
1381 ) {
1382 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1383 self.state.add_instruction(
1384 OpCode::VecIterNextPair,
1385 &[
1386 iterator_target.addressing(),
1387 closure_variable_key.addressing(),
1388 closure_variable_value.addressing(),
1389 bytes[0],
1390 bytes[1],
1391 ],
1392 node,
1393 comment,
1394 );
1395 }
1396
1397 pub fn add_string_iter_init(
1398 &mut self,
1399 iterator_target: &TypedRegister,
1400 pointer_to_vec_header: &TypedRegister,
1401 element_size: MemorySize,
1402 node: &Node,
1403 comment: &str,
1404 ) {
1405 let element_size_bytes = u32_to_bytes(element_size.0);
1406 self.state.add_instruction(
1407 OpCode::StringIterInit,
1408 &[
1409 iterator_target.addressing(),
1410 pointer_to_vec_header.addressing(),
1411 element_size_bytes.0,
1412 element_size_bytes.1,
1413 element_size_bytes.2,
1414 element_size_bytes.3,
1415 ],
1416 node,
1417 comment,
1418 );
1419 }
1420
1421 pub fn add_string_iter_next(
1422 &mut self,
1423 iterator_target: &TypedRegister,
1424 closure_variable: &TypedRegister,
1425 instruction_position: InstructionPosition,
1426 node: &Node,
1427 comment: &str,
1428 ) {
1429 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1430 self.state.add_instruction(
1431 OpCode::StringIterNext,
1432 &[
1433 iterator_target.addressing(),
1434 closure_variable.addressing(),
1435 bytes[0],
1436 bytes[1],
1437 ],
1438 node,
1439 comment,
1440 );
1441 }
1442
1443 pub fn add_string_iter_next_pair(
1444 &mut self,
1445 iterator_target: &TypedRegister,
1446 closure_variable_key: &TypedRegister,
1447 closure_variable_value: &TypedRegister,
1448 instruction_position: InstructionPosition,
1449 node: &Node,
1450 comment: &str,
1451 ) {
1452 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1453 self.state.add_instruction(
1454 OpCode::StringIterNextPair,
1455 &[
1456 iterator_target.addressing(),
1457 closure_variable_key.addressing(),
1458 closure_variable_value.addressing(),
1459 bytes[0],
1460 bytes[1],
1461 ],
1462 node,
1463 comment,
1464 );
1465 }
1466 fn convert_to_lower_and_upper(data: u32) -> (u8, u8, u8, u8) {
1467 data.to_le_bytes().into()
1468 }
1469
1470 fn u16_to_octets(data: u16) -> (u8, u8) {
1471 data.to_le_bytes().into()
1472 }
1473
1474 pub fn add_st32_using_ptr_with_offset(
1475 &mut self,
1476 scalar_lvalue_location: &MemoryLocation,
1477 u32_reg: &TypedRegister,
1478 node: &Node,
1479 comment: &str,
1480 ) {
1481 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1483 self.state.add_instruction(
1484 OpCode::St32UsingPtrWithOffset,
1485 &[
1486 scalar_lvalue_location.base_ptr_reg.addressing(),
1487 offset_bytes.0,
1488 offset_bytes.1,
1489 offset_bytes.2,
1490 offset_bytes.3,
1491 u32_reg.index,
1492 ],
1493 node,
1494 comment,
1495 );
1496 }
1497
1498 pub fn add_st16_using_ptr_with_offset(
1499 &mut self,
1500 scalar_lvalue_location: &MemoryLocation,
1501 u16_reg: &TypedRegister,
1502 node: &Node,
1503 comment: &str,
1504 ) {
1505 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1507 self.state.add_instruction(
1508 OpCode::St16UsingPtrWithOffset,
1509 &[
1510 scalar_lvalue_location.base_ptr_reg.addressing(),
1511 offset_bytes.0,
1512 offset_bytes.1,
1513 offset_bytes.2,
1514 offset_bytes.3,
1515 u16_reg.index,
1516 ],
1517 node,
1518 comment,
1519 );
1520 }
1521
1522 pub fn add_st8_using_ptr_with_offset(
1523 &mut self,
1524 scalar_lvalue_location: &MemoryLocation,
1525 u8_reg: &TypedRegister,
1526 node: &Node,
1527 comment: &str,
1528 ) {
1529 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1531 self.state.add_instruction(
1532 OpCode::St8UsingPtrWithOffset,
1533 &[
1534 scalar_lvalue_location.base_ptr_reg.addressing(),
1535 offset_bytes.0,
1536 offset_bytes.1,
1537 offset_bytes.2,
1538 offset_bytes.3,
1539 u8_reg.addressing(),
1540 ],
1541 node,
1542 comment,
1543 );
1544 }
1545
1546 pub fn add_mov_16_immediate_value(
1547 &mut self,
1548 dst_offset: &TypedRegister,
1549 value: u16,
1550 node: &Node,
1551 comment: &str,
1552 ) {
1553 let bytes = Self::u16_to_octets(value);
1554
1555 self.state.add_instruction(
1556 OpCode::Mov16FromImmediateValue,
1557 &[dst_offset.addressing(), bytes.0, bytes.1],
1558 node,
1559 comment,
1560 );
1561 }
1562
1563 pub fn add_mov_32_immediate_value(
1564 &mut self,
1565 dst_offset: &TypedRegister,
1566 value: u32,
1567 node: &Node,
1568 comment: &str,
1569 ) {
1570 let bytes = Self::convert_to_lower_and_upper(value);
1571
1572 self.state.add_instruction(
1573 OpCode::Mov32FromImmediateValue,
1574 &[dst_offset.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1575 node,
1576 comment,
1577 );
1578 }
1579
1580 pub fn add_ld32_from_absolute_memory_address(
1581 &mut self,
1582 dst_reg: &TypedRegister,
1583 absolute_mem_addr: &HeapMemoryAddress,
1584 node: &Node,
1585 comment: &str,
1586 ) {
1587 let bytes = u32_to_bytes(absolute_mem_addr.0);
1588
1589 self.state.add_instruction(
1590 OpCode::Ld32FromAbsoluteAddress,
1591 &[dst_reg.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1592 node,
1593 comment,
1594 );
1595 }
1596
1597 pub fn add_ld16_from_pointer_from_memory_location(
1598 &mut self,
1599 dst_reg: &TypedRegister,
1600 source_memory_location: &MemoryLocation,
1601 node: &Node,
1602 comment: &str,
1603 ) {
1604 self.add_ld16_from_pointer_with_offset_u16(
1605 dst_reg,
1606 &source_memory_location.base_ptr_reg,
1607 source_memory_location.offset,
1608 node,
1609 comment,
1610 );
1611 }
1612
1613 pub fn add_ld16_from_pointer_with_offset_u16(
1614 &mut self,
1615 dst_reg: &TypedRegister,
1616 base_ptr_reg: &TypedRegister,
1617 offset: MemoryOffset,
1618 node: &Node,
1619 comment: &str,
1620 ) {
1621 let offset_bytes = u32_to_bytes(offset.0);
1622
1623 self.state.add_instruction(
1624 OpCode::Ld16FromPointerWithOffset,
1625 &[
1626 dst_reg.addressing(),
1627 base_ptr_reg.addressing(),
1628 offset_bytes.0,
1629 offset_bytes.1,
1630 offset_bytes.2,
1631 offset_bytes.3,
1632 ],
1633 node,
1634 comment,
1635 );
1636 }
1637
1638 pub fn add_ld32_from_pointer_with_offset_u16(
1639 &mut self,
1640 dst_reg: &TypedRegister,
1641 base_ptr_reg: &TypedRegister,
1642 offset: MemoryOffset,
1643 node: &Node,
1644 comment: &str,
1645 ) {
1646 let offset_bytes = u32_to_bytes(offset.0);
1647
1648 self.state.add_instruction(
1649 OpCode::Ld32FromPointerWithOffset,
1650 &[
1651 dst_reg.addressing(),
1652 base_ptr_reg.addressing(),
1653 offset_bytes.0,
1654 offset_bytes.1,
1655 offset_bytes.2,
1656 offset_bytes.3,
1657 ],
1658 node,
1659 comment,
1660 );
1661 }
1662
1663 pub fn add_ld8_from_absolute_memory_address(
1664 &mut self,
1665 dst_reg: &TypedRegister,
1666 absolute_mem_addr: &HeapMemoryAddress,
1667 node: &Node,
1668 comment: &str,
1669 ) {
1670 let absolute_memory_addr = u32_to_bytes(absolute_mem_addr.0);
1671
1672 self.state.add_instruction(
1673 OpCode::Ld8FromAbsoluteAddress,
1674 &[
1675 dst_reg.addressing(),
1676 absolute_memory_addr.0,
1677 absolute_memory_addr.1,
1678 absolute_memory_addr.2,
1679 absolute_memory_addr.3,
1680 ],
1681 node,
1682 comment,
1683 );
1684 }
1685
1686 pub fn add_ld8_from_pointer_with_offset_u16(
1687 &mut self,
1688 dst_reg: &TypedRegister,
1689 base_ptr_reg: &TypedRegister,
1690 offset: MemoryOffset,
1691 node: &Node,
1692 comment: &str,
1693 ) {
1694 let offset_bytes = u32_to_bytes(offset.0);
1695
1696 self.state.add_instruction(
1697 OpCode::Ld8FromPointerWithOffset,
1698 &[
1699 dst_reg.addressing(),
1700 base_ptr_reg.addressing(),
1701 offset_bytes.0,
1702 offset_bytes.1,
1703 offset_bytes.2,
1704 offset_bytes.3,
1705 ],
1706 node,
1707 comment,
1708 );
1709 }
1710
1711 pub fn add_mov_reg(
1712 &mut self,
1713 dst_offset: &TypedRegister,
1714 src_offset: &TypedRegister,
1715 node: &Node,
1716 comment: &str,
1717 ) {
1718 if dst_offset.index == src_offset.index {
1719 return;
1720 }
1721 self.state.add_instruction(
1722 OpCode::MovReg,
1723 &[dst_offset.addressing(), src_offset.addressing()],
1724 node,
1725 comment,
1726 );
1727 }
1728
1729 pub fn add_mov8_immediate(
1730 &mut self,
1731 dst_offset: &TypedRegister,
1732 value: u8,
1733 node: &Node,
1734 comment: &str,
1735 ) {
1736 self.state.add_instruction(
1737 OpCode::Mov8FromImmediateValue,
1738 &[dst_offset.addressing(), value],
1739 node,
1740 comment,
1741 );
1742 }
1743
1744 pub fn add_add_u32(
1745 &mut self,
1746 dst_offset: &TypedRegister,
1747 lhs_offset: &TypedRegister,
1748 rhs_offset: &TypedRegister,
1749 node: &Node,
1750 comment: &str,
1751 ) {
1752 self.state.add_instruction(
1756 OpCode::AddU32,
1757 &[
1758 dst_offset.addressing(),
1759 lhs_offset.addressing(),
1760 rhs_offset.addressing(),
1761 ],
1762 node,
1763 comment,
1764 );
1765 }
1766
1767 pub fn add_add_u32_imm(
1768 &mut self,
1769 dst_offset: &TypedRegister,
1770 lhs_offset: &TypedRegister,
1771 rhs_immediate: u32,
1772 node: &Node,
1773 comment: &str,
1774 ) {
1775 let immediate_bytes = u32_to_bytes(rhs_immediate);
1779 self.state.add_instruction(
1780 OpCode::AddU32Imm,
1781 &[
1782 dst_offset.addressing(),
1783 lhs_offset.addressing(),
1784 immediate_bytes.0,
1785 immediate_bytes.1,
1786 immediate_bytes.2,
1787 immediate_bytes.3,
1788 ],
1789 node,
1790 comment,
1791 );
1792 }
1793
1794 pub fn add_mod_i32(
1795 &mut self,
1796 dst_offset: &TypedRegister,
1797 lhs_offset: &TypedRegister,
1798 rhs_offset: &TypedRegister,
1799 node: &Node,
1800 comment: &str,
1801 ) {
1802 self.state.add_instruction(
1807 OpCode::ModI32,
1808 &[
1809 dst_offset.addressing(),
1810 lhs_offset.addressing(),
1811 rhs_offset.addressing(),
1812 ],
1813 node,
1814 comment,
1815 );
1816 }
1817
1818 pub fn add_div_i32(
1819 &mut self,
1820 dst_offset: &TypedRegister,
1821 lhs_offset: &TypedRegister,
1822 rhs_offset: &TypedRegister,
1823 node: &Node,
1824 comment: &str,
1825 ) {
1826 self.state.add_instruction(
1830 OpCode::DivI32,
1831 &[
1832 dst_offset.addressing(),
1833 lhs_offset.addressing(),
1834 rhs_offset.addressing(),
1835 ],
1836 node,
1837 comment,
1838 );
1839 }
1840
1841 pub fn add_sub_u32(
1842 &mut self,
1843 dst_offset: &TypedRegister,
1844 lhs_offset: &TypedRegister,
1845 rhs_offset: &TypedRegister,
1846 node: &Node,
1847 comment: &str,
1848 ) {
1849 self.state.add_instruction(
1853 OpCode::SubU32,
1854 &[
1855 dst_offset.addressing(),
1856 lhs_offset.addressing(),
1857 rhs_offset.addressing(),
1858 ],
1859 node,
1860 comment,
1861 );
1862 }
1863
1864 pub fn add_mul_i32(
1865 &mut self,
1866 dst_offset: &TypedRegister,
1867 lhs_offset: &TypedRegister,
1868 rhs_offset: &TypedRegister,
1869 node: &Node,
1870 comment: &str,
1871 ) {
1872 self.state.add_instruction(
1876 OpCode::MulU32,
1877 &[
1878 dst_offset.addressing(),
1879 lhs_offset.addressing(),
1880 rhs_offset.addressing(),
1881 ],
1882 node,
1883 comment,
1884 );
1885 }
1886
1887 pub fn add_neg_i32(
1888 &mut self,
1889 target: &TypedRegister,
1890 source: &TypedRegister,
1891 node: &Node,
1892 comment: &str,
1893 ) {
1894 self.state.add_instruction(
1897 OpCode::NegI32,
1898 &[target.addressing(), source.addressing()],
1899 node,
1900 comment,
1901 );
1902 }
1903
1904 pub fn add_sub_f32(
1905 &mut self,
1906 dst_offset: &TypedRegister,
1907 lhs_offset: &TypedRegister,
1908 rhs_offset: &TypedRegister,
1909 node: &Node,
1910 comment: &str,
1911 ) {
1912 self.state.add_instruction(
1916 OpCode::SubU32,
1917 &[
1918 dst_offset.addressing(),
1919 lhs_offset.addressing(),
1920 rhs_offset.addressing(),
1921 ],
1922 node,
1923 comment,
1924 );
1925 }
1926 pub fn add_mul_f32(
1927 &mut self,
1928 dst_offset: &TypedRegister,
1929 lhs_offset: &TypedRegister,
1930 rhs_offset: &TypedRegister,
1931 node: &Node,
1932 comment: &str,
1933 ) {
1934 self.state.add_instruction(
1938 OpCode::MulF32,
1939 &[
1940 dst_offset.addressing(),
1941 lhs_offset.addressing(),
1942 rhs_offset.addressing(),
1943 ],
1944 node,
1945 comment,
1946 );
1947 }
1948 pub fn add_div_f32(
1949 &mut self,
1950 dst_offset: &TypedRegister,
1951 lhs_offset: &TypedRegister,
1952 rhs_offset: &TypedRegister,
1953 node: &Node,
1954 comment: &str,
1955 ) {
1956 self.state.add_instruction(
1960 OpCode::DivF32,
1961 &[
1962 dst_offset.addressing(),
1963 lhs_offset.addressing(),
1964 rhs_offset.addressing(),
1965 ],
1966 node,
1967 comment,
1968 );
1969 }
1970
1971 pub fn add_add_f32(
1972 &mut self,
1973 dst_offset: &TypedRegister,
1974 lhs_offset: &TypedRegister,
1975 rhs_offset: &TypedRegister,
1976 node: &Node,
1977 comment: &str,
1978 ) {
1979 self.state.add_instruction(
1983 OpCode::AddU32,
1984 &[
1985 dst_offset.addressing(),
1986 lhs_offset.addressing(),
1987 rhs_offset.addressing(),
1988 ],
1989 node,
1990 comment,
1991 );
1992 }
1993
1994 pub fn add_neg_f32(
1995 &mut self,
1996 target: &TypedRegister,
1997 source: &TypedRegister,
1998 node: &Node,
1999 comment: &str,
2000 ) {
2001 self.state.add_instruction(
2004 OpCode::NegI32,
2005 &[target.addressing(), source.addressing()],
2006 node,
2007 comment,
2008 );
2009 }
2010
2011 pub fn add_lt_i32(
2012 &mut self,
2013 dest_bool_reg: &TypedRegister,
2014 lhs_offset: &TypedRegister,
2015 rhs_offset: &TypedRegister,
2016 node: &Node,
2017 comment: &str,
2018 ) {
2019 self.state.add_instruction(
2022 OpCode::LtI32,
2023 &[
2024 dest_bool_reg.addressing(),
2025 lhs_offset.addressing(),
2026 rhs_offset.addressing(),
2027 ],
2028 node,
2029 comment,
2030 );
2031 }
2032
2033 pub fn add_lt_u32(
2034 &mut self,
2035 lhs_offset: &TypedRegister,
2036 rhs_offset: &TypedRegister,
2037 node: &Node,
2038 comment: &str,
2039 ) {
2040 self.state.add_instruction(
2043 OpCode::LtU32,
2044 &[lhs_offset.addressing(), rhs_offset.addressing()],
2045 node,
2046 comment,
2047 );
2048 }
2049
2050 pub fn add_le_i32(
2051 &mut self,
2052 dest_bool_reg: &TypedRegister,
2053 lhs_offset: &TypedRegister,
2054 rhs_offset: &TypedRegister,
2055 node: &Node,
2056 comment: &str,
2057 ) {
2058 self.state.add_instruction(
2061 OpCode::LeI32,
2062 &[
2063 dest_bool_reg.addressing(),
2064 lhs_offset.addressing(),
2065 rhs_offset.addressing(),
2066 ],
2067 node,
2068 comment,
2069 );
2070 }
2071
2072 pub fn add_gt_i32(
2073 &mut self,
2074 dest_bool_reg: &TypedRegister,
2075 lhs_offset: &TypedRegister,
2076 rhs_offset: &TypedRegister,
2077 node: &Node,
2078 comment: &str,
2079 ) {
2080 self.state.add_instruction(
2083 OpCode::GtI32,
2084 &[
2085 dest_bool_reg.addressing(),
2086 lhs_offset.addressing(),
2087 rhs_offset.addressing(),
2088 ],
2089 node,
2090 comment,
2091 );
2092 }
2093
2094 pub fn add_ge_i32(
2095 &mut self,
2096 dest_bool_reg: &TypedRegister,
2097 lhs_offset: &TypedRegister,
2098 rhs_offset: &TypedRegister,
2099 node: &Node,
2100 comment: &str,
2101 ) {
2102 self.state.add_instruction(
2105 OpCode::GeI32,
2106 &[
2107 dest_bool_reg.addressing(),
2108 lhs_offset.addressing(),
2109 rhs_offset.addressing(),
2110 ],
2111 node,
2112 comment,
2113 );
2114 }
2115
2116 pub fn add_ge_u32(
2117 &mut self,
2118 dest_bool_reg: &TypedRegister,
2119 lhs_offset: &TypedRegister,
2120 rhs_offset: &TypedRegister,
2121 node: &Node,
2122 comment: &str,
2123 ) {
2124 self.state.add_instruction(
2127 OpCode::GeU32,
2128 &[
2129 dest_bool_reg.addressing(),
2130 lhs_offset.addressing(),
2131 rhs_offset.addressing(),
2132 ],
2133 node,
2134 comment,
2135 );
2136 }
2137
2138 pub fn add_seqz(
2139 &mut self,
2140 dest_bool_reg: &TypedRegister,
2141 addr: &TypedRegister,
2142 node: &Node,
2143 comment: &str,
2144 ) {
2145 self.state.add_instruction(
2146 OpCode::MovEqualToZero,
2147 &[dest_bool_reg.addressing(), addr.addressing()],
2148 node,
2149 comment,
2150 );
2151 }
2152
2153 pub fn add_trap(&mut self, trap_code: u8, node: &Node, comment: &str) {
2154 self.state
2155 .add_instruction(OpCode::Trap, &[trap_code], node, comment);
2156 }
2157
2158 pub fn add_cmp_reg(
2159 &mut self,
2160 dest_bool_reg: &TypedRegister,
2161 source_a: &TypedRegister,
2162 source_b: &TypedRegister,
2163 node: &Node,
2164 comment: &str,
2165 ) {
2166 self.state.add_instruction(
2167 OpCode::CmpReg,
2168 &[
2169 dest_bool_reg.addressing(),
2170 source_a.addressing(),
2171 source_b.addressing(),
2172 ],
2173 node,
2174 comment,
2175 );
2176 }
2177
2178 pub fn add_block_cmp(
2179 &mut self,
2180 dest_bool_reg: &TypedRegister,
2181 first_ptr: &TypedRegister,
2182 second_ptr: &TypedRegister,
2183 size: MemorySize,
2184 node: &Node,
2185 comment: &str,
2186 ) {
2187 let block_size_bytes = u32_to_bytes(size.0);
2188 self.state.add_instruction(
2189 OpCode::CmpBlock,
2190 &[
2191 dest_bool_reg.addressing(),
2192 first_ptr.addressing(),
2193 second_ptr.addressing(),
2194 block_size_bytes.0,
2195 block_size_bytes.1,
2196 block_size_bytes.2,
2197 block_size_bytes.3,
2198 ],
2199 node,
2200 comment,
2201 );
2202 }
2203
2204 pub fn add_map_has(
2207 &mut self,
2208 dest_reg: &TypedRegister,
2209 self_addr: &PointerLocation,
2210 key_addr: &TypedRegister,
2211 node: &Node,
2212 comment: &str,
2213 ) {
2214 matches!(
2215 self_addr.ptr_reg.ty().kind,
2216 BasicTypeKind::DynamicLengthMapView(_, _)
2217 );
2218 self.state.add_instruction(
2219 OpCode::MapHas,
2220 &[
2221 dest_reg.addressing(),
2222 self_addr.addressing(),
2223 key_addr.addressing(),
2224 ],
2225 node,
2226 comment,
2227 );
2228 }
2229
2230 pub fn add_map_remove(
2231 &mut self,
2232 self_addr: &PointerLocation,
2233 key_addr: &TypedRegister,
2234 node: &Node,
2235 comment: &str,
2236 ) {
2237 matches!(
2238 self_addr.ptr_reg.ty().kind,
2239 BasicTypeKind::DynamicLengthMapView(_, _)
2240 );
2241 self.state.add_instruction(
2242 OpCode::MapRemove,
2243 &[self_addr.addressing(), key_addr.addressing()],
2244 node,
2245 comment,
2246 );
2247 }
2248
2249 pub fn add_map_get_entry_location(
2250 &mut self,
2251 target_entry_addr: &TypedRegister,
2252 map_self_addr: &PointerLocation,
2253 key: &TypedRegister,
2254 node: &Node,
2255 comment: &str,
2256 ) {
2257 self.state.add_instruction(
2259 OpCode::MapGetEntryLocation,
2260 &[
2261 target_entry_addr.addressing(),
2262 map_self_addr.addressing(),
2263 key.addressing(),
2264 ],
2265 node,
2266 comment,
2267 );
2268 }
2269
2270 pub fn add_map_get_or_reserve_entry_location(
2271 &mut self,
2272 target_entry_reg: &TypedRegister,
2273 map_self_addr: &PointerLocation,
2274 key: &TypedRegister,
2275 node: &Node,
2276 comment: &str,
2277 ) {
2278 self.state.add_instruction(
2279 OpCode::MapGetOrReserveEntryLocation,
2280 &[
2281 target_entry_reg.addressing(),
2282 map_self_addr.addressing(),
2283 key.addressing(),
2284 ],
2285 node,
2286 comment,
2287 );
2288 }
2289
2290 pub fn add_int_rnd(
2291 &mut self,
2292 dest: &TypedRegister,
2293 self_int: &TypedRegister,
2294 node: &Node,
2295 comment: &str,
2296 ) {
2297 assert!(dest.ty().is_int());
2298 assert!(self_int.ty().is_int());
2299 self.state.add_instruction(
2300 OpCode::IntToRnd,
2301 &[dest.addressing(), self_int.addressing()],
2302 node,
2303 comment,
2304 );
2305 }
2306
2307 pub fn add_int_min(
2308 &mut self,
2309 dest: &TypedRegister,
2310 self_int: &TypedRegister,
2311 other_int: &TypedRegister,
2312 node: &Node,
2313 comment: &str,
2314 ) {
2315 self.state.add_instruction(
2319 OpCode::IntMin,
2320 &[
2321 dest.addressing(),
2322 self_int.addressing(),
2323 other_int.addressing(),
2324 ],
2325 node,
2326 comment,
2327 );
2328 }
2329
2330 pub fn add_int_max(
2331 &mut self,
2332 dest: &TypedRegister,
2333 self_int: &TypedRegister,
2334 other_int: &TypedRegister,
2335 node: &Node,
2336 comment: &str,
2337 ) {
2338 self.state.add_instruction(
2342 OpCode::IntMax,
2343 &[
2344 dest.addressing(),
2345 self_int.addressing(),
2346 other_int.addressing(),
2347 ],
2348 node,
2349 comment,
2350 );
2351 }
2352
2353 pub fn add_int_clamp(
2354 &mut self,
2355 dest: &TypedRegister,
2356 self_int: &TypedRegister,
2357 min_int: &TypedRegister,
2358 max_int: &TypedRegister,
2359 node: &Node,
2360 comment: &str,
2361 ) {
2362 assert!(dest.ty().is_int());
2363 assert!(self_int.ty().is_int());
2364 assert!(min_int.ty().is_int());
2365 assert!(max_int.ty().is_int());
2366 self.state.add_instruction(
2367 OpCode::IntClamp,
2368 &[
2369 dest.addressing(),
2370 self_int.addressing(),
2371 min_int.addressing(),
2372 max_int.addressing(),
2373 ],
2374 node,
2375 comment,
2376 );
2377 }
2378
2379 pub fn add_int_abs(
2380 &mut self,
2381 dest: &TypedRegister,
2382 self_int: &TypedRegister,
2383 node: &Node,
2384 comment: &str,
2385 ) {
2386 self.state.add_instruction(
2389 OpCode::IntAbs,
2390 &[dest.addressing(), self_int.addressing()],
2391 node,
2392 comment,
2393 );
2394 }
2395
2396 pub fn add_int_to_float(
2397 &mut self,
2398 dest: &TypedRegister,
2399 self_int: &TypedRegister,
2400 node: &Node,
2401 comment: &str,
2402 ) {
2403 self.state.add_instruction(
2406 OpCode::IntToFloat,
2407 &[dest.addressing(), self_int.addressing()],
2408 node,
2409 comment,
2410 );
2411 }
2412
2413 pub fn add_int_to_string(
2414 &mut self,
2415 dest: &TypedRegister,
2416 self_int: &TypedRegister,
2417 node: &Node,
2418 comment: &str,
2419 ) {
2420 assert!(dest.ty().is_str());
2421 assert!(self_int.ty().is_int());
2422 self.state.add_instruction(
2423 OpCode::IntToString,
2424 &[dest.addressing(), self_int.addressing()],
2425 node,
2426 comment,
2427 );
2428 }
2429
2430 pub fn bool_to_string(
2431 &mut self,
2432 dest_str: &TypedRegister,
2433 self_bool: &TypedRegister,
2434 node: &Node,
2435 comment: &str,
2436 ) {
2437 assert!(dest_str.ty().is_str());
2438 assert!(self_bool.ty().is_bool());
2439 self.state.add_instruction(
2440 OpCode::BoolToString,
2441 &[dest_str.addressing(), self_bool.addressing()],
2442 node,
2443 comment,
2444 );
2445 }
2446
2447 pub fn byte_to_string(
2448 &mut self,
2449 dest_str: &TypedRegister,
2450 self_bool: &TypedRegister,
2451 node: &Node,
2452 comment: &str,
2453 ) {
2454 assert!(dest_str.ty().is_str());
2455 assert!(self_bool.ty().is_byte());
2456 self.state.add_instruction(
2457 OpCode::ByteToString,
2458 &[dest_str.addressing(), self_bool.addressing()],
2459 node,
2460 comment,
2461 );
2462 }
2463
2464 pub fn string_to_string(
2465 &mut self,
2466 dest_str: &TypedRegister,
2467 self_str: &TypedRegister,
2468 node: &Node,
2469 comment: &str,
2470 ) {
2471 assert!(dest_str.ty().is_str());
2472 assert!(self_str.ty().is_str());
2473 self.state.add_instruction(
2474 OpCode::StringToString,
2475 &[dest_str.addressing(), self_str.addressing()],
2476 node,
2477 comment,
2478 );
2479 }
2480
2481 pub fn float_to_string(
2482 &mut self,
2483 dest_str: &TypedRegister,
2484 self_float: &TypedRegister,
2485 node: &Node,
2486 comment: &str,
2487 ) {
2488 assert!(dest_str.ty().is_str());
2489 assert!(self_float.ty().is_float());
2490 self.state.add_instruction(
2491 OpCode::FloatToString,
2492 &[dest_str.addressing(), self_float.addressing()],
2493 node,
2494 comment,
2495 );
2496 }
2497
2498 pub fn add_float_round(
2499 &mut self,
2500 dest_int: &TypedRegister,
2501 self_float: &TypedRegister,
2502 node: &Node,
2503 comment: &str,
2504 ) {
2505 assert!(self_float.ty().is_float());
2507 self.state.add_instruction(
2508 OpCode::FloatRound,
2509 &[dest_int.addressing(), self_float.addressing()],
2510 node,
2511 comment,
2512 );
2513 }
2514
2515 pub fn add_float_floor(
2516 &mut self,
2517 dest_int: &TypedRegister,
2518 self_float: &TypedRegister,
2519 node: &Node,
2520 comment: &str,
2521 ) {
2522 self.state.add_instruction(
2525 OpCode::FloatFloor,
2526 &[dest_int.addressing(), self_float.addressing()],
2527 node,
2528 comment,
2529 );
2530 }
2531
2532 pub fn add_float_sqrt(
2533 &mut self,
2534 dest_float: &TypedRegister,
2535 self_float: &TypedRegister,
2536 node: &Node,
2537 comment: &str,
2538 ) {
2539 self.state.add_instruction(
2542 OpCode::FloatSqrt,
2543 &[dest_float.addressing(), self_float.addressing()],
2544 node,
2545 comment,
2546 );
2547 }
2548
2549 pub fn add_float_sign(
2550 &mut self,
2551 dest_float: &TypedRegister,
2552 self_float: &TypedRegister,
2553 node: &Node,
2554 comment: &str,
2555 ) {
2556 assert!(dest_float.ty().is_float());
2557 assert!(self_float.ty().is_float());
2558 self.state.add_instruction(
2559 OpCode::FloatSign,
2560 &[dest_float.addressing(), self_float.addressing()],
2561 node,
2562 comment,
2563 );
2564 }
2565
2566 pub fn add_float_abs(
2567 &mut self,
2568 dest_float: &TypedRegister,
2569 self_float: &TypedRegister,
2570 node: &Node,
2571 comment: &str,
2572 ) {
2573 assert!(dest_float.ty().is_float());
2574 assert!(self_float.ty().is_float());
2575 self.state.add_instruction(
2576 OpCode::FloatAbs,
2577 &[dest_float.addressing(), self_float.addressing()],
2578 node,
2579 comment,
2580 );
2581 }
2582
2583 pub fn add_float_prnd(
2584 &mut self,
2585 dest_float: &TypedRegister,
2586 self_float: &TypedRegister,
2587 node: &Node,
2588 comment: &str,
2589 ) {
2590 assert!(dest_float.ty().is_float());
2591 assert!(self_float.ty().is_float());
2592 self.state.add_instruction(
2593 OpCode::FloatPseudoRandom,
2594 &[dest_float.addressing(), self_float.addressing()],
2595 node,
2596 comment,
2597 );
2598 }
2599
2600 pub fn add_float_sin(
2601 &mut self,
2602 dest_float: &TypedRegister,
2603 self_float: &TypedRegister,
2604 node: &Node,
2605 comment: &str,
2606 ) {
2607 assert!(dest_float.ty().is_float());
2608 assert!(self_float.ty().is_float());
2609 self.state.add_instruction(
2610 OpCode::FloatSin,
2611 &[dest_float.addressing(), self_float.addressing()],
2612 node,
2613 comment,
2614 );
2615 }
2616
2617 pub fn add_float_cos(
2618 &mut self,
2619 dest_float: &TypedRegister,
2620 self_float: &TypedRegister,
2621 node: &Node,
2622 comment: &str,
2623 ) {
2624 assert!(dest_float.ty().is_float());
2625 assert!(self_float.ty().is_float());
2626 self.state.add_instruction(
2627 OpCode::FloatCos,
2628 &[dest_float.addressing(), self_float.addressing()],
2629 node,
2630 comment,
2631 );
2632 }
2633
2634 pub fn add_float_acos(
2635 &mut self,
2636 dest_float: &TypedRegister,
2637 self_float: &TypedRegister,
2638 node: &Node,
2639 comment: &str,
2640 ) {
2641 assert!(dest_float.ty().is_float());
2642 assert!(self_float.ty().is_float());
2643 self.state.add_instruction(
2644 OpCode::FloatAcos,
2645 &[dest_float.addressing(), self_float.addressing()],
2646 node,
2647 comment,
2648 );
2649 }
2650
2651 pub fn add_float_asin(
2652 &mut self,
2653 dest_float: &TypedRegister,
2654 self_float: &TypedRegister,
2655 node: &Node,
2656 comment: &str,
2657 ) {
2658 assert!(dest_float.ty().is_float());
2659 assert!(self_float.ty().is_float());
2660 self.state.add_instruction(
2661 OpCode::FloatAsin,
2662 &[dest_float.addressing(), self_float.addressing()],
2663 node,
2664 comment,
2665 );
2666 }
2667
2668 pub fn add_float_atan2(
2669 &mut self,
2670 dest_float: &TypedRegister,
2671 self_float: &TypedRegister,
2672 node: &Node,
2673 comment: &str,
2674 ) {
2675 assert!(dest_float.ty().is_float());
2676 assert!(self_float.ty().is_float());
2677 self.state.add_instruction(
2678 OpCode::FloatAtan2,
2679 &[dest_float.addressing(), self_float.addressing()],
2680 node,
2681 comment,
2682 );
2683 }
2684
2685 pub fn add_float_min(
2686 &mut self,
2687 dest_float: &TypedRegister,
2688 self_float: &TypedRegister,
2689 other: &TypedRegister,
2690 node: &Node,
2691 comment: &str,
2692 ) {
2693 assert!(dest_float.ty().is_float());
2694 assert!(self_float.ty().is_float());
2695 self.state.add_instruction(
2696 OpCode::FloatMin,
2697 &[
2698 dest_float.addressing(),
2699 self_float.addressing(),
2700 other.addressing(),
2701 ],
2702 node,
2703 comment,
2704 );
2705 }
2706
2707 pub fn add_float_max(
2708 &mut self,
2709 dest_float: &TypedRegister,
2710 self_float: &TypedRegister,
2711 max_float: &TypedRegister,
2712 node: &Node,
2713 comment: &str,
2714 ) {
2715 assert!(dest_float.ty().is_float());
2716 assert!(self_float.ty().is_float());
2717 assert!(max_float.ty().is_float());
2718 self.state.add_instruction(
2719 OpCode::FloatMax,
2720 &[
2721 dest_float.addressing(),
2722 self_float.addressing(),
2723 max_float.addressing(),
2724 ],
2725 node,
2726 comment,
2727 );
2728 }
2729
2730 pub fn add_float_clamp(
2731 &mut self,
2732 dest_float: &TypedRegister,
2733 self_float: &TypedRegister,
2734 min_float: &TypedRegister,
2735 max_float: &TypedRegister,
2736 node: &Node,
2737 comment: &str,
2738 ) {
2739 assert!(dest_float.ty().is_float());
2740 assert!(self_float.ty().is_float());
2741 assert!(min_float.ty().is_float());
2742 assert!(max_float.ty().is_float());
2743
2744 self.state.add_instruction(
2745 OpCode::FloatClamp,
2746 &[
2747 dest_float.addressing(),
2748 min_float.addressing(),
2749 self_float.addressing(),
2750 max_float.addressing(),
2751 ],
2752 node,
2753 comment,
2754 );
2755 }
2756
2757 pub fn add_sparse_iter_init(
2758 &mut self,
2759 iterator_target: &TypedRegister,
2760 pointer_to_sparse_header: &TypedRegister,
2761 node: &Node,
2762 comment: &str,
2763 ) {
2764 self.state.add_instruction(
2765 OpCode::SparseIterInit,
2766 &[
2767 iterator_target.addressing(),
2768 pointer_to_sparse_header.addressing(),
2769 ],
2770 node,
2771 comment,
2772 );
2773 }
2774
2775 pub fn add_sparse_iter_next_placeholder(
2776 &mut self,
2777 iterator_target: &TypedRegister,
2778 closure_variable: &TypedRegister,
2779 node: &Node,
2780 comment: &str,
2781 ) -> PatchPosition {
2782 let position = self.position();
2783 self.state.add_instruction(
2784 OpCode::SparseIterNext,
2785 &[
2786 iterator_target.addressing(),
2787 closure_variable.addressing(),
2788 0,
2789 0,
2790 ],
2791 node,
2792 comment,
2793 );
2794 PatchPosition(position)
2795 }
2796
2797 pub fn add_sparse_iter_next_pair_placeholder(
2798 &mut self,
2799 iterator_target: &TypedRegister,
2800 closure_variable: &TypedRegister,
2801 closure_variable_b: &TypedRegister,
2802 node: &Node,
2803 comment: &str,
2804 ) -> PatchPosition {
2805 let position = self.position();
2806 self.state.add_instruction(
2807 OpCode::SparseIterNextPair,
2808 &[
2809 iterator_target.addressing(),
2810 closure_variable.addressing(),
2811 closure_variable_b.addressing(),
2812 0,
2813 0,
2814 ],
2815 node,
2816 comment,
2817 );
2818 PatchPosition(position)
2819 }
2820}