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