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