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