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
1140 pub fn add_string_cmp(
1141 &mut self,
1142 dest_bool_reg: &TypedRegister,
1143 a: &TypedRegister,
1144 b: &TypedRegister,
1145 node: &Node,
1146 comment: &str,
1147 ) {
1148 self.state.add_instruction(
1149 OpCode::StringCmp,
1150 &[dest_bool_reg.addressing(), a.addressing(), b.addressing()],
1151 node,
1152 comment,
1153 );
1154 }
1155
1156 pub fn add_fixed_capacity_array_init_fill_capacity_and_len(
1157 &mut self,
1158 target_vec_to_init: &PointerLocation,
1159 capacity: u16,
1160 element_size: &MemorySize,
1161 node: &Node,
1162 comment: &str,
1163 ) {
1164 debug_assert!(capacity > 0);
1166
1167 let capacity_bytes = u16_to_u8_pair(capacity);
1168 let element_bytes = u32_to_bytes(element_size.0);
1169
1170 self.state.add_instruction(
1171 OpCode::ArrayInitWithLenAndCapacity,
1172 &[
1173 target_vec_to_init.ptr_reg.addressing(),
1174 capacity_bytes.0,
1175 capacity_bytes.1,
1176 element_bytes.0,
1177 element_bytes.1,
1178 element_bytes.2,
1179 element_bytes.3,
1180 ],
1181 node,
1182 comment,
1183 );
1184 }
1185
1186 pub fn add_map_init_set_capacity(
1187 &mut self,
1188 target_map_to_init: &PointerLocation,
1189 logical_limit: CountU16,
1190 key_size_reg: &TypedRegister,
1191 key_alignment: MemoryAlignment,
1192 value_size_reg: &TypedRegister,
1193 value_alignment: MemoryAlignment,
1194 node: &Node,
1195 comment: &str,
1196 ) {
1197 debug_assert!(logical_limit.0 > 0);
1198
1199 let logical_limit_bytes = u16_to_u8_pair(logical_limit.0);
1200
1201 let key_alignment_usize: usize = key_alignment.into();
1202 let value_alignment_usize: usize = value_alignment.into();
1203
1204 self.state.add_instruction(
1206 OpCode::MapInitWithCapacityAndKeyAndTupleSizeAddr,
1207 &[
1208 target_map_to_init.ptr_reg.addressing(),
1209 logical_limit_bytes.0,
1210 logical_limit_bytes.1,
1211 key_size_reg.addressing(),
1212 key_alignment_usize as u8,
1213 value_size_reg.addressing(),
1214 value_alignment_usize as u8,
1215 ],
1216 node,
1217 comment,
1218 );
1219 }
1220
1221 pub fn add_map_overwrite(
1222 &mut self,
1223 destination_map: &PointerLocation,
1224 source_map: &PointerLocation,
1225 node: &Node,
1226 comment: &str,
1227 ) {
1228 self.state.add_instruction(
1229 OpCode::MapOverwrite,
1230 &[destination_map.addressing(), source_map.addressing()],
1231 node,
1232 comment,
1233 );
1234 }
1235
1236 pub fn add_range_iter_init(
1237 &mut self,
1238 iterator_target: &TypedRegister,
1239 range_source_header: &TypedRegister,
1240 node: &Node,
1241 comment: &str,
1242 ) {
1243 self.state.add_instruction(
1247 OpCode::RangeIterInit,
1248 &[
1249 iterator_target.addressing(),
1250 range_source_header.addressing(),
1251 ],
1252 node,
1253 comment,
1254 );
1255 }
1256
1257 pub fn add_vec_copy(
1258 &mut self,
1259 target_vec: &PointerLocation,
1260 source_vec: &PointerLocation,
1261 node: &Node,
1262 comment: &str,
1263 ) {
1264 self.state.add_instruction(
1265 OpCode::VecCopy,
1266 &[
1267 target_vec.ptr_reg.addressing(),
1268 source_vec.ptr_reg.addressing(),
1269 ],
1270 node,
1271 comment,
1272 );
1273 }
1274
1275 pub fn add_vec_copy_range(
1276 &mut self,
1277 target_vec: &PointerLocation,
1278 source_vec: &PointerLocation,
1279 range_header: &TypedRegister,
1280 node: &Node,
1281 comment: &str,
1282 ) {
1283 self.state.add_instruction(
1284 OpCode::VecCopyRange,
1285 &[
1286 target_vec.addressing(),
1287 source_vec.addressing(),
1288 range_header.addressing(),
1289 ],
1290 node,
1291 comment,
1292 );
1293 }
1294
1295 pub fn add_vec_init_set_capacity(
1296 &mut self,
1297 target_vec_to_init: &PointerLocation,
1298 capacity: CountU16,
1299 element_size: &MemorySize,
1300 node: &Node,
1301 comment: &str,
1302 ) {
1303 debug_assert!(capacity.0 > 0);
1305
1306 let capacity_bytes = u16_to_u8_pair(capacity.0);
1307 let element_bytes = u32_to_bytes(element_size.0);
1308 self.state.add_instruction(
1309 OpCode::VecInit,
1310 &[
1311 target_vec_to_init.ptr_reg.addressing(),
1312 capacity_bytes.0,
1313 capacity_bytes.1,
1314 element_bytes.0,
1315 element_bytes.1,
1316 element_bytes.2,
1317 element_bytes.3,
1318 ],
1319 node,
1320 comment,
1321 );
1322 }
1323
1324 pub fn add_vec_iter_init(
1325 &mut self,
1326 iterator_target: &TypedRegister,
1327 pointer_to_vec_header: &TypedRegister,
1328 node: &Node,
1329 comment: &str,
1330 ) {
1331 self.state.add_instruction(
1332 OpCode::VecIterInit,
1333 &[
1334 iterator_target.addressing(),
1335 pointer_to_vec_header.addressing(),
1336 ],
1337 node,
1338 comment,
1339 );
1340 }
1341
1342 pub fn add_vec_iter_next(
1343 &mut self,
1344 iterator_target: &TypedRegister,
1345 closure_variable: &TypedRegister,
1346 instruction_position: InstructionPosition,
1347 node: &Node,
1348 comment: &str,
1349 ) {
1350 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1351 self.state.add_instruction(
1352 OpCode::VecIterNext,
1353 &[
1354 iterator_target.addressing(),
1355 closure_variable.addressing(),
1356 bytes[0],
1357 bytes[1],
1358 ],
1359 node,
1360 comment,
1361 );
1362 }
1363
1364 pub fn add_vec_iter_next_pair(
1365 &mut self,
1366 iterator_target: &TypedRegister,
1367 closure_variable_key: &TypedRegister,
1368 closure_variable_value: &TypedRegister,
1369 instruction_position: InstructionPosition,
1370 node: &Node,
1371 comment: &str,
1372 ) {
1373 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1374 self.state.add_instruction(
1375 OpCode::VecIterNextPair,
1376 &[
1377 iterator_target.addressing(),
1378 closure_variable_key.addressing(),
1379 closure_variable_value.addressing(),
1380 bytes[0],
1381 bytes[1],
1382 ],
1383 node,
1384 comment,
1385 );
1386 }
1387
1388 pub fn add_string_iter_init(
1389 &mut self,
1390 iterator_target: &TypedRegister,
1391 pointer_to_vec_header: &TypedRegister,
1392 element_size: MemorySize,
1393 node: &Node,
1394 comment: &str,
1395 ) {
1396 let element_size_bytes = u32_to_bytes(element_size.0);
1397 self.state.add_instruction(
1398 OpCode::StringIterInit,
1399 &[
1400 iterator_target.addressing(),
1401 pointer_to_vec_header.addressing(),
1402 element_size_bytes.0,
1403 element_size_bytes.1,
1404 element_size_bytes.2,
1405 element_size_bytes.3,
1406 ],
1407 node,
1408 comment,
1409 );
1410 }
1411
1412 pub fn add_string_iter_next(
1413 &mut self,
1414 iterator_target: &TypedRegister,
1415 closure_variable: &TypedRegister,
1416 instruction_position: InstructionPosition,
1417 node: &Node,
1418 comment: &str,
1419 ) {
1420 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1421 self.state.add_instruction(
1422 OpCode::StringIterNext,
1423 &[
1424 iterator_target.addressing(),
1425 closure_variable.addressing(),
1426 bytes[0],
1427 bytes[1],
1428 ],
1429 node,
1430 comment,
1431 );
1432 }
1433
1434 pub fn add_string_iter_next_pair(
1435 &mut self,
1436 iterator_target: &TypedRegister,
1437 closure_variable_key: &TypedRegister,
1438 closure_variable_value: &TypedRegister,
1439 instruction_position: InstructionPosition,
1440 node: &Node,
1441 comment: &str,
1442 ) {
1443 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1444 self.state.add_instruction(
1445 OpCode::StringIterNextPair,
1446 &[
1447 iterator_target.addressing(),
1448 closure_variable_key.addressing(),
1449 closure_variable_value.addressing(),
1450 bytes[0],
1451 bytes[1],
1452 ],
1453 node,
1454 comment,
1455 );
1456 }
1457 fn convert_to_lower_and_upper(data: u32) -> (u8, u8, u8, u8) {
1458 data.to_le_bytes().into()
1459 }
1460
1461 fn u16_to_octets(data: u16) -> (u8, u8) {
1462 data.to_le_bytes().into()
1463 }
1464
1465 pub fn add_st32_using_ptr_with_offset(
1466 &mut self,
1467 scalar_lvalue_location: &MemoryLocation,
1468 u32_reg: &TypedRegister,
1469 node: &Node,
1470 comment: &str,
1471 ) {
1472 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1474 self.state.add_instruction(
1475 OpCode::St32UsingPtrWithOffset,
1476 &[
1477 scalar_lvalue_location.base_ptr_reg.addressing(),
1478 offset_bytes.0,
1479 offset_bytes.1,
1480 offset_bytes.2,
1481 offset_bytes.3,
1482 u32_reg.index,
1483 ],
1484 node,
1485 comment,
1486 );
1487 }
1488
1489 pub fn add_st16_using_ptr_with_offset(
1490 &mut self,
1491 scalar_lvalue_location: &MemoryLocation,
1492 u16_reg: &TypedRegister,
1493 node: &Node,
1494 comment: &str,
1495 ) {
1496 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1498 self.state.add_instruction(
1499 OpCode::St16UsingPtrWithOffset,
1500 &[
1501 scalar_lvalue_location.base_ptr_reg.addressing(),
1502 offset_bytes.0,
1503 offset_bytes.1,
1504 offset_bytes.2,
1505 offset_bytes.3,
1506 u16_reg.index,
1507 ],
1508 node,
1509 comment,
1510 );
1511 }
1512
1513 pub fn add_st8_using_ptr_with_offset(
1514 &mut self,
1515 scalar_lvalue_location: &MemoryLocation,
1516 u8_reg: &TypedRegister,
1517 node: &Node,
1518 comment: &str,
1519 ) {
1520 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1522 self.state.add_instruction(
1523 OpCode::St8UsingPtrWithOffset,
1524 &[
1525 scalar_lvalue_location.base_ptr_reg.addressing(),
1526 offset_bytes.0,
1527 offset_bytes.1,
1528 offset_bytes.2,
1529 offset_bytes.3,
1530 u8_reg.addressing(),
1531 ],
1532 node,
1533 comment,
1534 );
1535 }
1536
1537 pub fn add_mov_16_immediate_value(
1538 &mut self,
1539 dst_offset: &TypedRegister,
1540 value: u16,
1541 node: &Node,
1542 comment: &str,
1543 ) {
1544 let bytes = Self::u16_to_octets(value);
1545
1546 self.state.add_instruction(
1547 OpCode::Mov16FromImmediateValue,
1548 &[dst_offset.addressing(), bytes.0, bytes.1],
1549 node,
1550 comment,
1551 );
1552 }
1553
1554 pub fn add_mov_32_immediate_value(
1555 &mut self,
1556 dst_offset: &TypedRegister,
1557 value: u32,
1558 node: &Node,
1559 comment: &str,
1560 ) {
1561 let bytes = Self::convert_to_lower_and_upper(value);
1562
1563 self.state.add_instruction(
1564 OpCode::Mov32FromImmediateValue,
1565 &[dst_offset.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1566 node,
1567 comment,
1568 );
1569 }
1570
1571 pub fn add_ld32_from_absolute_memory_address(
1572 &mut self,
1573 dst_reg: &TypedRegister,
1574 absolute_mem_addr: &HeapMemoryAddress,
1575 node: &Node,
1576 comment: &str,
1577 ) {
1578 let bytes = u32_to_bytes(absolute_mem_addr.0);
1579
1580 self.state.add_instruction(
1581 OpCode::Ld32FromAbsoluteAddress,
1582 &[dst_reg.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1583 node,
1584 comment,
1585 );
1586 }
1587
1588 pub fn add_ld16_from_pointer_from_memory_location(
1589 &mut self,
1590 dst_reg: &TypedRegister,
1591 source_memory_location: &MemoryLocation,
1592 node: &Node,
1593 comment: &str,
1594 ) {
1595 self.add_ld16_from_pointer_with_offset_u16(
1596 dst_reg,
1597 &source_memory_location.base_ptr_reg,
1598 source_memory_location.offset,
1599 node,
1600 comment,
1601 );
1602 }
1603
1604 pub fn add_ld16_from_pointer_with_offset_u16(
1605 &mut self,
1606 dst_reg: &TypedRegister,
1607 base_ptr_reg: &TypedRegister,
1608 offset: MemoryOffset,
1609 node: &Node,
1610 comment: &str,
1611 ) {
1612 let offset_bytes = u32_to_bytes(offset.0);
1613
1614 self.state.add_instruction(
1615 OpCode::Ld16FromPointerWithOffset,
1616 &[
1617 dst_reg.addressing(),
1618 base_ptr_reg.addressing(),
1619 offset_bytes.0,
1620 offset_bytes.1,
1621 offset_bytes.2,
1622 offset_bytes.3,
1623 ],
1624 node,
1625 comment,
1626 );
1627 }
1628
1629 pub fn add_ld32_from_pointer_with_offset_u16(
1630 &mut self,
1631 dst_reg: &TypedRegister,
1632 base_ptr_reg: &TypedRegister,
1633 offset: MemoryOffset,
1634 node: &Node,
1635 comment: &str,
1636 ) {
1637 let offset_bytes = u32_to_bytes(offset.0);
1638
1639 self.state.add_instruction(
1640 OpCode::Ld32FromPointerWithOffset,
1641 &[
1642 dst_reg.addressing(),
1643 base_ptr_reg.addressing(),
1644 offset_bytes.0,
1645 offset_bytes.1,
1646 offset_bytes.2,
1647 offset_bytes.3,
1648 ],
1649 node,
1650 comment,
1651 );
1652 }
1653
1654 pub fn add_ld8_from_absolute_memory_address(
1655 &mut self,
1656 dst_reg: &TypedRegister,
1657 absolute_mem_addr: &HeapMemoryAddress,
1658 node: &Node,
1659 comment: &str,
1660 ) {
1661 let absolute_memory_addr = u32_to_bytes(absolute_mem_addr.0);
1662
1663 self.state.add_instruction(
1664 OpCode::Ld8FromAbsoluteAddress,
1665 &[
1666 dst_reg.addressing(),
1667 absolute_memory_addr.0,
1668 absolute_memory_addr.1,
1669 absolute_memory_addr.2,
1670 absolute_memory_addr.3,
1671 ],
1672 node,
1673 comment,
1674 );
1675 }
1676
1677 pub fn add_ld8_from_pointer_with_offset_u16(
1678 &mut self,
1679 dst_reg: &TypedRegister,
1680 base_ptr_reg: &TypedRegister,
1681 offset: MemoryOffset,
1682 node: &Node,
1683 comment: &str,
1684 ) {
1685 let offset_bytes = u32_to_bytes(offset.0);
1686
1687 self.state.add_instruction(
1688 OpCode::Ld8FromPointerWithOffset,
1689 &[
1690 dst_reg.addressing(),
1691 base_ptr_reg.addressing(),
1692 offset_bytes.0,
1693 offset_bytes.1,
1694 offset_bytes.2,
1695 offset_bytes.3,
1696 ],
1697 node,
1698 comment,
1699 );
1700 }
1701
1702 pub fn add_mov_reg(
1703 &mut self,
1704 dst_offset: &TypedRegister,
1705 src_offset: &TypedRegister,
1706 node: &Node,
1707 comment: &str,
1708 ) {
1709 if dst_offset.index == src_offset.index {
1710 return;
1711 }
1712 self.state.add_instruction(
1713 OpCode::MovReg,
1714 &[dst_offset.addressing(), src_offset.addressing()],
1715 node,
1716 comment,
1717 );
1718 }
1719
1720 pub fn add_mov8_immediate(
1721 &mut self,
1722 dst_offset: &TypedRegister,
1723 value: u8,
1724 node: &Node,
1725 comment: &str,
1726 ) {
1727 self.state.add_instruction(
1728 OpCode::Mov8FromImmediateValue,
1729 &[dst_offset.addressing(), value],
1730 node,
1731 comment,
1732 );
1733 }
1734
1735 pub fn add_add_u32(
1736 &mut self,
1737 dst_offset: &TypedRegister,
1738 lhs_offset: &TypedRegister,
1739 rhs_offset: &TypedRegister,
1740 node: &Node,
1741 comment: &str,
1742 ) {
1743 self.state.add_instruction(
1747 OpCode::AddU32,
1748 &[
1749 dst_offset.addressing(),
1750 lhs_offset.addressing(),
1751 rhs_offset.addressing(),
1752 ],
1753 node,
1754 comment,
1755 );
1756 }
1757
1758 pub fn add_add_u32_imm(
1759 &mut self,
1760 dst_offset: &TypedRegister,
1761 lhs_offset: &TypedRegister,
1762 rhs_immediate: u32,
1763 node: &Node,
1764 comment: &str,
1765 ) {
1766 let immediate_bytes = u32_to_bytes(rhs_immediate);
1770 self.state.add_instruction(
1771 OpCode::AddU32Imm,
1772 &[
1773 dst_offset.addressing(),
1774 lhs_offset.addressing(),
1775 immediate_bytes.0,
1776 immediate_bytes.1,
1777 immediate_bytes.2,
1778 immediate_bytes.3,
1779 ],
1780 node,
1781 comment,
1782 );
1783 }
1784
1785 pub fn add_mod_i32(
1786 &mut self,
1787 dst_offset: &TypedRegister,
1788 lhs_offset: &TypedRegister,
1789 rhs_offset: &TypedRegister,
1790 node: &Node,
1791 comment: &str,
1792 ) {
1793 self.state.add_instruction(
1798 OpCode::ModI32,
1799 &[
1800 dst_offset.addressing(),
1801 lhs_offset.addressing(),
1802 rhs_offset.addressing(),
1803 ],
1804 node,
1805 comment,
1806 );
1807 }
1808
1809 pub fn add_div_i32(
1810 &mut self,
1811 dst_offset: &TypedRegister,
1812 lhs_offset: &TypedRegister,
1813 rhs_offset: &TypedRegister,
1814 node: &Node,
1815 comment: &str,
1816 ) {
1817 self.state.add_instruction(
1821 OpCode::DivI32,
1822 &[
1823 dst_offset.addressing(),
1824 lhs_offset.addressing(),
1825 rhs_offset.addressing(),
1826 ],
1827 node,
1828 comment,
1829 );
1830 }
1831
1832 pub fn add_sub_u32(
1833 &mut self,
1834 dst_offset: &TypedRegister,
1835 lhs_offset: &TypedRegister,
1836 rhs_offset: &TypedRegister,
1837 node: &Node,
1838 comment: &str,
1839 ) {
1840 self.state.add_instruction(
1844 OpCode::SubU32,
1845 &[
1846 dst_offset.addressing(),
1847 lhs_offset.addressing(),
1848 rhs_offset.addressing(),
1849 ],
1850 node,
1851 comment,
1852 );
1853 }
1854
1855 pub fn add_mul_i32(
1856 &mut self,
1857 dst_offset: &TypedRegister,
1858 lhs_offset: &TypedRegister,
1859 rhs_offset: &TypedRegister,
1860 node: &Node,
1861 comment: &str,
1862 ) {
1863 self.state.add_instruction(
1867 OpCode::MulU32,
1868 &[
1869 dst_offset.addressing(),
1870 lhs_offset.addressing(),
1871 rhs_offset.addressing(),
1872 ],
1873 node,
1874 comment,
1875 );
1876 }
1877
1878 pub fn add_neg_i32(
1879 &mut self,
1880 target: &TypedRegister,
1881 source: &TypedRegister,
1882 node: &Node,
1883 comment: &str,
1884 ) {
1885 self.state.add_instruction(
1888 OpCode::NegI32,
1889 &[target.addressing(), source.addressing()],
1890 node,
1891 comment,
1892 );
1893 }
1894
1895 pub fn add_sub_f32(
1896 &mut self,
1897 dst_offset: &TypedRegister,
1898 lhs_offset: &TypedRegister,
1899 rhs_offset: &TypedRegister,
1900 node: &Node,
1901 comment: &str,
1902 ) {
1903 self.state.add_instruction(
1907 OpCode::SubU32,
1908 &[
1909 dst_offset.addressing(),
1910 lhs_offset.addressing(),
1911 rhs_offset.addressing(),
1912 ],
1913 node,
1914 comment,
1915 );
1916 }
1917 pub fn add_mul_f32(
1918 &mut self,
1919 dst_offset: &TypedRegister,
1920 lhs_offset: &TypedRegister,
1921 rhs_offset: &TypedRegister,
1922 node: &Node,
1923 comment: &str,
1924 ) {
1925 self.state.add_instruction(
1929 OpCode::MulF32,
1930 &[
1931 dst_offset.addressing(),
1932 lhs_offset.addressing(),
1933 rhs_offset.addressing(),
1934 ],
1935 node,
1936 comment,
1937 );
1938 }
1939 pub fn add_div_f32(
1940 &mut self,
1941 dst_offset: &TypedRegister,
1942 lhs_offset: &TypedRegister,
1943 rhs_offset: &TypedRegister,
1944 node: &Node,
1945 comment: &str,
1946 ) {
1947 self.state.add_instruction(
1951 OpCode::DivF32,
1952 &[
1953 dst_offset.addressing(),
1954 lhs_offset.addressing(),
1955 rhs_offset.addressing(),
1956 ],
1957 node,
1958 comment,
1959 );
1960 }
1961
1962 pub fn add_add_f32(
1963 &mut self,
1964 dst_offset: &TypedRegister,
1965 lhs_offset: &TypedRegister,
1966 rhs_offset: &TypedRegister,
1967 node: &Node,
1968 comment: &str,
1969 ) {
1970 self.state.add_instruction(
1974 OpCode::AddU32,
1975 &[
1976 dst_offset.addressing(),
1977 lhs_offset.addressing(),
1978 rhs_offset.addressing(),
1979 ],
1980 node,
1981 comment,
1982 );
1983 }
1984
1985 pub fn add_neg_f32(
1986 &mut self,
1987 target: &TypedRegister,
1988 source: &TypedRegister,
1989 node: &Node,
1990 comment: &str,
1991 ) {
1992 self.state.add_instruction(
1995 OpCode::NegI32,
1996 &[target.addressing(), source.addressing()],
1997 node,
1998 comment,
1999 );
2000 }
2001
2002 pub fn add_lt_i32(
2003 &mut self,
2004 dest_bool_reg: &TypedRegister,
2005 lhs_offset: &TypedRegister,
2006 rhs_offset: &TypedRegister,
2007 node: &Node,
2008 comment: &str,
2009 ) {
2010 self.state.add_instruction(
2013 OpCode::LtI32,
2014 &[
2015 dest_bool_reg.addressing(),
2016 lhs_offset.addressing(),
2017 rhs_offset.addressing(),
2018 ],
2019 node,
2020 comment,
2021 );
2022 }
2023
2024 pub fn add_lt_u32(
2025 &mut self,
2026 lhs_offset: &TypedRegister,
2027 rhs_offset: &TypedRegister,
2028 node: &Node,
2029 comment: &str,
2030 ) {
2031 self.state.add_instruction(
2034 OpCode::LtU32,
2035 &[lhs_offset.addressing(), rhs_offset.addressing()],
2036 node,
2037 comment,
2038 );
2039 }
2040
2041 pub fn add_le_i32(
2042 &mut self,
2043 dest_bool_reg: &TypedRegister,
2044 lhs_offset: &TypedRegister,
2045 rhs_offset: &TypedRegister,
2046 node: &Node,
2047 comment: &str,
2048 ) {
2049 self.state.add_instruction(
2052 OpCode::LeI32,
2053 &[
2054 dest_bool_reg.addressing(),
2055 lhs_offset.addressing(),
2056 rhs_offset.addressing(),
2057 ],
2058 node,
2059 comment,
2060 );
2061 }
2062
2063 pub fn add_gt_i32(
2064 &mut self,
2065 dest_bool_reg: &TypedRegister,
2066 lhs_offset: &TypedRegister,
2067 rhs_offset: &TypedRegister,
2068 node: &Node,
2069 comment: &str,
2070 ) {
2071 self.state.add_instruction(
2074 OpCode::GtI32,
2075 &[
2076 dest_bool_reg.addressing(),
2077 lhs_offset.addressing(),
2078 rhs_offset.addressing(),
2079 ],
2080 node,
2081 comment,
2082 );
2083 }
2084
2085 pub fn add_ge_i32(
2086 &mut self,
2087 dest_bool_reg: &TypedRegister,
2088 lhs_offset: &TypedRegister,
2089 rhs_offset: &TypedRegister,
2090 node: &Node,
2091 comment: &str,
2092 ) {
2093 self.state.add_instruction(
2096 OpCode::GeI32,
2097 &[
2098 dest_bool_reg.addressing(),
2099 lhs_offset.addressing(),
2100 rhs_offset.addressing(),
2101 ],
2102 node,
2103 comment,
2104 );
2105 }
2106
2107 pub fn add_ge_u32(
2108 &mut self,
2109 dest_bool_reg: &TypedRegister,
2110 lhs_offset: &TypedRegister,
2111 rhs_offset: &TypedRegister,
2112 node: &Node,
2113 comment: &str,
2114 ) {
2115 self.state.add_instruction(
2118 OpCode::GeU32,
2119 &[
2120 dest_bool_reg.addressing(),
2121 lhs_offset.addressing(),
2122 rhs_offset.addressing(),
2123 ],
2124 node,
2125 comment,
2126 );
2127 }
2128
2129 pub fn add_meqz(
2130 &mut self,
2131 dest_bool_reg: &TypedRegister,
2132 addr: &TypedRegister,
2133 node: &Node,
2134 comment: &str,
2135 ) {
2136 self.state.add_instruction(
2137 OpCode::MovEqualToZero,
2138 &[dest_bool_reg.addressing(), addr.addressing()],
2139 node,
2140 comment,
2141 );
2142 }
2143
2144 pub fn add_trap(&mut self, trap_code: u8, node: &Node, comment: &str) {
2145 self.state
2146 .add_instruction(OpCode::Trap, &[trap_code], node, comment);
2147 }
2148
2149 pub fn add_cmp_reg(
2150 &mut self,
2151 dest_bool_reg: &TypedRegister,
2152 source_a: &TypedRegister,
2153 source_b: &TypedRegister,
2154 node: &Node,
2155 comment: &str,
2156 ) {
2157 self.state.add_instruction(
2158 OpCode::CmpReg,
2159 &[
2160 dest_bool_reg.addressing(),
2161 source_a.addressing(),
2162 source_b.addressing(),
2163 ],
2164 node,
2165 comment,
2166 );
2167 }
2168
2169 pub fn add_block_cmp(
2170 &mut self,
2171 dest_bool_reg: &TypedRegister,
2172 first_ptr: &TypedRegister,
2173 second_ptr: &TypedRegister,
2174 size: MemorySize,
2175 node: &Node,
2176 comment: &str,
2177 ) {
2178 let block_size_bytes = u32_to_bytes(size.0);
2179 self.state.add_instruction(
2180 OpCode::CmpBlock,
2181 &[
2182 dest_bool_reg.addressing(),
2183 first_ptr.addressing(),
2184 second_ptr.addressing(),
2185 block_size_bytes.0,
2186 block_size_bytes.1,
2187 block_size_bytes.2,
2188 block_size_bytes.3,
2189 ],
2190 node,
2191 comment,
2192 );
2193 }
2194
2195 pub fn add_map_has(
2198 &mut self,
2199 dest_reg: &TypedRegister,
2200 self_addr: &PointerLocation,
2201 key_addr: &TypedRegister,
2202 node: &Node,
2203 comment: &str,
2204 ) {
2205 matches!(
2206 self_addr.ptr_reg.ty().kind,
2207 BasicTypeKind::DynamicLengthMapView(_, _)
2208 );
2209 self.state.add_instruction(
2210 OpCode::MapHas,
2211 &[
2212 dest_reg.addressing(),
2213 self_addr.addressing(),
2214 key_addr.addressing(),
2215 ],
2216 node,
2217 comment,
2218 );
2219 }
2220
2221 pub fn add_map_remove(
2222 &mut self,
2223 self_addr: &PointerLocation,
2224 key_addr: &TypedRegister,
2225 node: &Node,
2226 comment: &str,
2227 ) {
2228 matches!(
2229 self_addr.ptr_reg.ty().kind,
2230 BasicTypeKind::DynamicLengthMapView(_, _)
2231 );
2232 self.state.add_instruction(
2233 OpCode::MapRemove,
2234 &[self_addr.addressing(), key_addr.addressing()],
2235 node,
2236 comment,
2237 );
2238 }
2239
2240 pub fn add_map_get_entry_location(
2241 &mut self,
2242 target_entry_addr: &TypedRegister,
2243 map_self_addr: &PointerLocation,
2244 key: &TypedRegister,
2245 node: &Node,
2246 comment: &str,
2247 ) {
2248 self.state.add_instruction(
2250 OpCode::MapGetEntryLocation,
2251 &[
2252 target_entry_addr.addressing(),
2253 map_self_addr.addressing(),
2254 key.addressing(),
2255 ],
2256 node,
2257 comment,
2258 );
2259 }
2260
2261 pub fn add_map_get_or_reserve_entry_location(
2262 &mut self,
2263 target_entry_reg: &TypedRegister,
2264 map_self_addr: &PointerLocation,
2265 key: &TypedRegister,
2266 node: &Node,
2267 comment: &str,
2268 ) {
2269 self.state.add_instruction(
2270 OpCode::MapGetOrReserveEntryLocation,
2271 &[
2272 target_entry_reg.addressing(),
2273 map_self_addr.addressing(),
2274 key.addressing(),
2275 ],
2276 node,
2277 comment,
2278 );
2279 }
2280
2281 pub fn add_int_rnd(
2282 &mut self,
2283 dest: &TypedRegister,
2284 self_int: &TypedRegister,
2285 node: &Node,
2286 comment: &str,
2287 ) {
2288 assert!(dest.ty().is_int());
2289 assert!(self_int.ty().is_int());
2290 self.state.add_instruction(
2291 OpCode::IntToRnd,
2292 &[dest.addressing(), self_int.addressing()],
2293 node,
2294 comment,
2295 );
2296 }
2297
2298 pub fn add_int_min(
2299 &mut self,
2300 dest: &TypedRegister,
2301 self_int: &TypedRegister,
2302 other_int: &TypedRegister,
2303 node: &Node,
2304 comment: &str,
2305 ) {
2306 self.state.add_instruction(
2310 OpCode::IntMin,
2311 &[
2312 dest.addressing(),
2313 self_int.addressing(),
2314 other_int.addressing(),
2315 ],
2316 node,
2317 comment,
2318 );
2319 }
2320
2321 pub fn add_int_max(
2322 &mut self,
2323 dest: &TypedRegister,
2324 self_int: &TypedRegister,
2325 other_int: &TypedRegister,
2326 node: &Node,
2327 comment: &str,
2328 ) {
2329 self.state.add_instruction(
2333 OpCode::IntMax,
2334 &[
2335 dest.addressing(),
2336 self_int.addressing(),
2337 other_int.addressing(),
2338 ],
2339 node,
2340 comment,
2341 );
2342 }
2343
2344 pub fn add_int_clamp(
2345 &mut self,
2346 dest: &TypedRegister,
2347 self_int: &TypedRegister,
2348 min_int: &TypedRegister,
2349 max_int: &TypedRegister,
2350 node: &Node,
2351 comment: &str,
2352 ) {
2353 assert!(dest.ty().is_int());
2354 assert!(self_int.ty().is_int());
2355 assert!(min_int.ty().is_int());
2356 assert!(max_int.ty().is_int());
2357 self.state.add_instruction(
2358 OpCode::IntClamp,
2359 &[
2360 dest.addressing(),
2361 self_int.addressing(),
2362 min_int.addressing(),
2363 max_int.addressing(),
2364 ],
2365 node,
2366 comment,
2367 );
2368 }
2369
2370 pub fn add_int_abs(
2371 &mut self,
2372 dest: &TypedRegister,
2373 self_int: &TypedRegister,
2374 node: &Node,
2375 comment: &str,
2376 ) {
2377 self.state.add_instruction(
2380 OpCode::IntAbs,
2381 &[dest.addressing(), self_int.addressing()],
2382 node,
2383 comment,
2384 );
2385 }
2386
2387 pub fn add_int_to_float(
2388 &mut self,
2389 dest: &TypedRegister,
2390 self_int: &TypedRegister,
2391 node: &Node,
2392 comment: &str,
2393 ) {
2394 self.state.add_instruction(
2397 OpCode::IntToFloat,
2398 &[dest.addressing(), self_int.addressing()],
2399 node,
2400 comment,
2401 );
2402 }
2403
2404 pub fn add_int_to_string(
2405 &mut self,
2406 dest: &TypedRegister,
2407 self_int: &TypedRegister,
2408 node: &Node,
2409 comment: &str,
2410 ) {
2411 assert!(dest.ty().is_str());
2412 assert!(self_int.ty().is_int());
2413 self.state.add_instruction(
2414 OpCode::IntToString,
2415 &[dest.addressing(), self_int.addressing()],
2416 node,
2417 comment,
2418 );
2419 }
2420
2421 pub fn bool_to_string(
2422 &mut self,
2423 dest_str: &TypedRegister,
2424 self_bool: &TypedRegister,
2425 node: &Node,
2426 comment: &str,
2427 ) {
2428 assert!(dest_str.ty().is_str());
2429 assert!(self_bool.ty().is_bool());
2430 self.state.add_instruction(
2431 OpCode::BoolToString,
2432 &[dest_str.addressing(), self_bool.addressing()],
2433 node,
2434 comment,
2435 );
2436 }
2437
2438 pub fn byte_to_string(
2439 &mut self,
2440 dest_str: &TypedRegister,
2441 self_bool: &TypedRegister,
2442 node: &Node,
2443 comment: &str,
2444 ) {
2445 assert!(dest_str.ty().is_str());
2446 assert!(self_bool.ty().is_byte());
2447 self.state.add_instruction(
2448 OpCode::ByteToString,
2449 &[dest_str.addressing(), self_bool.addressing()],
2450 node,
2451 comment,
2452 );
2453 }
2454
2455 pub fn codepoint_to_string(
2456 &mut self,
2457 dest_str: &TypedRegister,
2458 self_char: &TypedRegister,
2459 node: &Node,
2460 comment: &str,
2461 ) {
2462 assert!(dest_str.ty().is_str());
2463 assert!(self_char.ty().is_codepoint());
2464 self.state.add_instruction(
2465 OpCode::CodepointToString,
2466 &[dest_str.addressing(), self_char.addressing()],
2467 node,
2468 comment,
2469 );
2470 }
2471
2472 pub fn string_to_string(
2473 &mut self,
2474 dest_str: &TypedRegister,
2475 self_str: &TypedRegister,
2476 node: &Node,
2477 comment: &str,
2478 ) {
2479 assert!(dest_str.ty().is_str());
2480 assert!(self_str.ty().is_str());
2481 self.state.add_instruction(
2482 OpCode::StringToString,
2483 &[dest_str.addressing(), self_str.addressing()],
2484 node,
2485 comment,
2486 );
2487 }
2488
2489 pub fn float_to_string(
2490 &mut self,
2491 dest_str: &TypedRegister,
2492 self_float: &TypedRegister,
2493 node: &Node,
2494 comment: &str,
2495 ) {
2496 assert!(dest_str.ty().is_str());
2497 assert!(self_float.ty().is_float());
2498 self.state.add_instruction(
2499 OpCode::FloatToString,
2500 &[dest_str.addressing(), self_float.addressing()],
2501 node,
2502 comment,
2503 );
2504 }
2505
2506 pub fn add_float_round(
2507 &mut self,
2508 dest_int: &TypedRegister,
2509 self_float: &TypedRegister,
2510 node: &Node,
2511 comment: &str,
2512 ) {
2513 assert!(self_float.ty().is_float());
2515 self.state.add_instruction(
2516 OpCode::FloatRound,
2517 &[dest_int.addressing(), self_float.addressing()],
2518 node,
2519 comment,
2520 );
2521 }
2522
2523 pub fn add_float_floor(
2524 &mut self,
2525 dest_int: &TypedRegister,
2526 self_float: &TypedRegister,
2527 node: &Node,
2528 comment: &str,
2529 ) {
2530 self.state.add_instruction(
2533 OpCode::FloatFloor,
2534 &[dest_int.addressing(), self_float.addressing()],
2535 node,
2536 comment,
2537 );
2538 }
2539
2540 pub fn add_float_sqrt(
2541 &mut self,
2542 dest_float: &TypedRegister,
2543 self_float: &TypedRegister,
2544 node: &Node,
2545 comment: &str,
2546 ) {
2547 self.state.add_instruction(
2550 OpCode::FloatSqrt,
2551 &[dest_float.addressing(), self_float.addressing()],
2552 node,
2553 comment,
2554 );
2555 }
2556
2557 pub fn add_float_sign(
2558 &mut self,
2559 dest_float: &TypedRegister,
2560 self_float: &TypedRegister,
2561 node: &Node,
2562 comment: &str,
2563 ) {
2564 assert!(dest_float.ty().is_float());
2565 assert!(self_float.ty().is_float());
2566 self.state.add_instruction(
2567 OpCode::FloatSign,
2568 &[dest_float.addressing(), self_float.addressing()],
2569 node,
2570 comment,
2571 );
2572 }
2573
2574 pub fn add_float_abs(
2575 &mut self,
2576 dest_float: &TypedRegister,
2577 self_float: &TypedRegister,
2578 node: &Node,
2579 comment: &str,
2580 ) {
2581 assert!(dest_float.ty().is_float());
2582 assert!(self_float.ty().is_float());
2583 self.state.add_instruction(
2584 OpCode::FloatAbs,
2585 &[dest_float.addressing(), self_float.addressing()],
2586 node,
2587 comment,
2588 );
2589 }
2590
2591 pub fn add_float_prnd(
2592 &mut self,
2593 dest_float: &TypedRegister,
2594 self_float: &TypedRegister,
2595 node: &Node,
2596 comment: &str,
2597 ) {
2598 assert!(dest_float.ty().is_float());
2599 assert!(self_float.ty().is_float());
2600 self.state.add_instruction(
2601 OpCode::FloatPseudoRandom,
2602 &[dest_float.addressing(), self_float.addressing()],
2603 node,
2604 comment,
2605 );
2606 }
2607
2608 pub fn add_float_sin(
2609 &mut self,
2610 dest_float: &TypedRegister,
2611 self_float: &TypedRegister,
2612 node: &Node,
2613 comment: &str,
2614 ) {
2615 assert!(dest_float.ty().is_float());
2616 assert!(self_float.ty().is_float());
2617 self.state.add_instruction(
2618 OpCode::FloatSin,
2619 &[dest_float.addressing(), self_float.addressing()],
2620 node,
2621 comment,
2622 );
2623 }
2624
2625 pub fn add_float_cos(
2626 &mut self,
2627 dest_float: &TypedRegister,
2628 self_float: &TypedRegister,
2629 node: &Node,
2630 comment: &str,
2631 ) {
2632 assert!(dest_float.ty().is_float());
2633 assert!(self_float.ty().is_float());
2634 self.state.add_instruction(
2635 OpCode::FloatCos,
2636 &[dest_float.addressing(), self_float.addressing()],
2637 node,
2638 comment,
2639 );
2640 }
2641
2642 pub fn add_float_acos(
2643 &mut self,
2644 dest_float: &TypedRegister,
2645 self_float: &TypedRegister,
2646 node: &Node,
2647 comment: &str,
2648 ) {
2649 assert!(dest_float.ty().is_float());
2650 assert!(self_float.ty().is_float());
2651 self.state.add_instruction(
2652 OpCode::FloatAcos,
2653 &[dest_float.addressing(), self_float.addressing()],
2654 node,
2655 comment,
2656 );
2657 }
2658
2659 pub fn add_float_asin(
2660 &mut self,
2661 dest_float: &TypedRegister,
2662 self_float: &TypedRegister,
2663 node: &Node,
2664 comment: &str,
2665 ) {
2666 assert!(dest_float.ty().is_float());
2667 assert!(self_float.ty().is_float());
2668 self.state.add_instruction(
2669 OpCode::FloatAsin,
2670 &[dest_float.addressing(), self_float.addressing()],
2671 node,
2672 comment,
2673 );
2674 }
2675
2676 pub fn add_float_atan2(
2677 &mut self,
2678 dest_float: &TypedRegister,
2679 self_float: &TypedRegister,
2680 node: &Node,
2681 comment: &str,
2682 ) {
2683 assert!(dest_float.ty().is_float());
2684 assert!(self_float.ty().is_float());
2685 self.state.add_instruction(
2686 OpCode::FloatAtan2,
2687 &[dest_float.addressing(), self_float.addressing()],
2688 node,
2689 comment,
2690 );
2691 }
2692
2693 pub fn add_float_min(
2694 &mut self,
2695 dest_float: &TypedRegister,
2696 self_float: &TypedRegister,
2697 other: &TypedRegister,
2698 node: &Node,
2699 comment: &str,
2700 ) {
2701 assert!(dest_float.ty().is_float());
2702 assert!(self_float.ty().is_float());
2703 self.state.add_instruction(
2704 OpCode::FloatMin,
2705 &[
2706 dest_float.addressing(),
2707 self_float.addressing(),
2708 other.addressing(),
2709 ],
2710 node,
2711 comment,
2712 );
2713 }
2714
2715 pub fn add_float_max(
2716 &mut self,
2717 dest_float: &TypedRegister,
2718 self_float: &TypedRegister,
2719 max_float: &TypedRegister,
2720 node: &Node,
2721 comment: &str,
2722 ) {
2723 assert!(dest_float.ty().is_float());
2724 assert!(self_float.ty().is_float());
2725 assert!(max_float.ty().is_float());
2726 self.state.add_instruction(
2727 OpCode::FloatMax,
2728 &[
2729 dest_float.addressing(),
2730 self_float.addressing(),
2731 max_float.addressing(),
2732 ],
2733 node,
2734 comment,
2735 );
2736 }
2737
2738 pub fn add_float_clamp(
2739 &mut self,
2740 dest_float: &TypedRegister,
2741 self_float: &TypedRegister,
2742 min_float: &TypedRegister,
2743 max_float: &TypedRegister,
2744 node: &Node,
2745 comment: &str,
2746 ) {
2747 assert!(dest_float.ty().is_float());
2748 assert!(self_float.ty().is_float());
2749 assert!(min_float.ty().is_float());
2750 assert!(max_float.ty().is_float());
2751
2752 self.state.add_instruction(
2753 OpCode::FloatClamp,
2754 &[
2755 dest_float.addressing(),
2756 min_float.addressing(),
2757 self_float.addressing(),
2758 max_float.addressing(),
2759 ],
2760 node,
2761 comment,
2762 );
2763 }
2764
2765 pub fn add_sparse_iter_init(
2766 &mut self,
2767 iterator_target: &TypedRegister,
2768 pointer_to_sparse_header: &TypedRegister,
2769 node: &Node,
2770 comment: &str,
2771 ) {
2772 self.state.add_instruction(
2773 OpCode::SparseIterInit,
2774 &[
2775 iterator_target.addressing(),
2776 pointer_to_sparse_header.addressing(),
2777 ],
2778 node,
2779 comment,
2780 );
2781 }
2782
2783 pub fn add_sparse_iter_next_placeholder(
2784 &mut self,
2785 iterator_target: &TypedRegister,
2786 closure_variable: &TypedRegister,
2787 node: &Node,
2788 comment: &str,
2789 ) -> PatchPosition {
2790 let position = self.position();
2791 self.state.add_instruction(
2792 OpCode::SparseIterNext,
2793 &[
2794 iterator_target.addressing(),
2795 closure_variable.addressing(),
2796 0,
2797 0,
2798 ],
2799 node,
2800 comment,
2801 );
2802 PatchPosition(position)
2803 }
2804
2805 pub fn add_sparse_iter_next_pair_placeholder(
2806 &mut self,
2807 iterator_target: &TypedRegister,
2808 closure_variable: &TypedRegister,
2809 closure_variable_b: &TypedRegister,
2810 node: &Node,
2811 comment: &str,
2812 ) -> PatchPosition {
2813 let position = self.position();
2814 self.state.add_instruction(
2815 OpCode::SparseIterNextPair,
2816 &[
2817 iterator_target.addressing(),
2818 closure_variable.addressing(),
2819 closure_variable_b.addressing(),
2820 0,
2821 0,
2822 ],
2823 node,
2824 comment,
2825 );
2826 PatchPosition(position)
2827 }
2828}