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