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