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