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