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 HEAP_PTR_ON_FRAME_SIZE, HeapMemoryOffset, HeapMemoryRegion, InstructionPosition,
11 InstructionPositionOffset, MemoryOffset, MemorySize, Meta, PatchPosition, RANGE_HEADER_SIZE,
12 RANGE_ITERATOR_SIZE, ZFlagPolarity,
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_pop(
500 &mut self,
501 target_addr: &TypedRegister,
502 self_addr: &TypedRegister,
503 element_size: MemorySize,
504 node: &Node,
505 comment: &str,
506 ) {
507 let element_size_bytes = u32_to_bytes(element_size.0);
516 self.state.add_instruction(
517 OpCode::VecPop,
518 &[
519 target_addr.addressing(),
520 self_addr.addressing(),
521 element_size_bytes.0,
522 element_size_bytes.1,
523 element_size_bytes.2,
524 element_size_bytes.3,
525 ],
526 node,
527 comment,
528 );
529 }
530
531 pub fn add_vec_remove_index(
532 &mut self,
533 self_addr: &TypedRegister,
534 element_item: &TypedRegister,
535 node: &Node,
536 comment: &str,
537 ) {
538 self.state.add_instruction(
546 OpCode::VecRemoveIndex,
547 &[self_addr.addressing(), element_item.addressing()],
548 node,
549 comment,
550 );
551 }
552
553 pub fn add_vec_remove_index_get_value(
554 &mut self,
555 target_addr: &TypedRegister,
556 self_addr: &TypedRegister,
557 element_item: &TypedRegister,
558 node: &Node,
559 comment: &str,
560 ) {
561 assert!(matches!(
562 self_addr.ty().kind,
563 BasicTypeKind::DynamicLengthVecView(_)
564 ));
565 self.state.add_instruction(
566 OpCode::VecRemoveIndexGetValue,
567 &[
568 target_addr.addressing(),
569 self_addr.addressing(),
570 element_item.addressing(),
571 ],
572 node,
573 comment,
574 );
575 }
576
577 pub fn add_vec_iter_next_placeholder(
578 &mut self,
579 iterator_target: &TypedRegister,
580 closure_variable: &TypedRegister,
581 node: &Node,
582 comment: &str,
583 ) -> PatchPosition {
584 assert!(matches!(
585 iterator_target.ty().kind,
586 BasicTypeKind::InternalVecIterator
587 ));
588 let position = self.position();
589 self.state.add_instruction(
590 OpCode::VecIterNext,
591 &[
592 iterator_target.addressing(),
593 closure_variable.addressing(),
594 0,
595 0,
596 ],
597 node,
598 comment,
599 );
600 PatchPosition(position)
601 }
602
603 pub fn add_vec_iter_next_pair_placeholder(
604 &mut self,
605 iterator_target: &TypedRegister,
606 closure_variable_key: &TypedRegister,
607 closure_variable_value: &TypedRegister,
608 node: &Node,
609 comment: &str,
610 ) -> PatchPosition {
611 assert!(matches!(
612 iterator_target.ty().kind,
613 BasicTypeKind::InternalVecIterator
614 ));
615 let position = self.position();
616 self.state.add_instruction(
617 OpCode::VecIterNextPair,
618 &[
619 iterator_target.addressing(),
620 closure_variable_key.addressing(),
621 closure_variable_value.addressing(),
622 0,
623 ],
624 node,
625 comment,
626 );
627 PatchPosition(position)
628 }
629
630 pub fn add_string_iter_next_placeholder(
631 &mut self,
632 iterator_target: &TypedRegister,
633 closure_variable: &TypedRegister,
634 node: &Node,
635 comment: &str,
636 ) -> PatchPosition {
637 assert!(matches!(
638 iterator_target.ty().kind,
639 BasicTypeKind::InternalStringIterator
640 ));
641 let position = self.position();
642 self.state.add_instruction(
643 OpCode::StringIterNext,
644 &[
645 iterator_target.addressing(),
646 closure_variable.addressing(),
647 0,
648 0,
649 ],
650 node,
651 comment,
652 );
653 PatchPosition(position)
654 }
655
656 pub fn add_string_iter_next_pair_placeholder(
657 &mut self,
658 iterator_target: &TypedRegister,
659 closure_variable_key: &TypedRegister,
660 closure_variable_value: &TypedRegister,
661 node: &Node,
662 comment: &str,
663 ) -> PatchPosition {
664 let position = self.position();
672 self.state.add_instruction(
673 OpCode::StringIterNextPair,
674 &[
675 iterator_target.addressing(),
676 closure_variable_key.addressing(),
677 closure_variable_value.addressing(),
678 0,
679 ],
680 node,
681 comment,
682 );
683 PatchPosition(position)
684 }
685
686 pub fn add_eq_u8_immediate(
687 &mut self,
688 dest_bool_reg: &TypedRegister,
689 source_addr: &TypedRegister,
690 immediate: u8,
691 node: &Node,
692 comment: &str,
693 ) {
694 self.state.add_instruction(
696 OpCode::Eq8Imm,
697 &[
698 dest_bool_reg.addressing(),
699 source_addr.addressing(),
700 immediate,
701 ],
702 node,
703 comment,
704 );
705 }
706
707 pub fn add_call_placeholder(&mut self, node: &Node, comment: &str) -> PatchPosition {
708 let position = self.position();
709 self.state
710 .add_instruction(OpCode::Call, &[0], node, comment);
711 PatchPosition(position)
712 }
713
714 pub fn add_jump_placeholder(&mut self, node: &Node, comment: &str) -> PatchPosition {
715 let position = self.position();
716
717 self.state
718 .add_instruction(OpCode::B, &[0, 0], node, comment);
719
720 PatchPosition(position)
721 }
722
723 pub fn add_lea_from_frame_region(
724 &mut self,
725 target_heap: &TypedRegister,
726 frame_address_to_convert: FrameMemoryRegion,
727 node: &Node,
728 comment: &str,
729 ) {
730 let frame_addr_bytes = u32_to_bytes(frame_address_to_convert.addr.0);
731 self.state.add_instruction(
732 OpCode::LdPtrFromEffectiveFrameAddress,
733 &[
734 target_heap.addressing(),
735 frame_addr_bytes.0,
736 frame_addr_bytes.1,
737 frame_addr_bytes.2,
738 frame_addr_bytes.3,
739 ],
740 node,
741 &format!("{comment} region: {frame_address_to_convert}"),
742 );
743 }
744
745 pub fn add_ld_contiguous_regs_from_frame(
746 &mut self,
747 target_reg: u8,
748 stored_in_frame: FrameMemoryRegion,
749 count: u8,
750 node: &Node,
751 comment: &str,
752 ) {
753 let address_bytes = stored_in_frame.addr.0.to_le_bytes();
754 self.state.add_instruction(
755 OpCode::LdRegFromFrameRange,
756 &[
757 target_reg,
758 address_bytes[0],
759 address_bytes[1],
760 address_bytes[2],
761 address_bytes[3],
762 count,
763 ],
764 node,
765 comment,
766 );
767 }
768
769 pub fn add_ld_masked_regs_from_frame(
770 &mut self,
771 register_mask: u8,
772 stored_in_frame: FrameMemoryRegion,
773 node: &Node,
774 comment: &str,
775 ) {
776 let address_bytes = stored_in_frame.addr.0.to_le_bytes();
777 self.state.add_instruction(
778 OpCode::LdRegFromFrameUsingMask,
779 &[
780 register_mask,
781 address_bytes[0],
782 address_bytes[1],
783 address_bytes[2],
784 address_bytes[3],
785 ],
786 node,
787 comment,
788 );
789 }
790
791 pub fn add_st_contiguous_regs_to_frame(
792 &mut self,
793 frame_mem: FrameMemoryRegion,
794 source_reg: u8,
795 count: u8,
796 node: &Node,
797 comment: &str,
798 ) {
799 let address_bytes = frame_mem.addr.0.to_le_bytes();
800 self.state.add_instruction(
801 OpCode::StRegToFrame,
802 &[
803 address_bytes[0],
804 address_bytes[1],
805 address_bytes[2],
806 address_bytes[3],
807 source_reg,
808 count,
809 ],
810 node,
811 comment,
812 );
813 }
814
815 pub fn add_st_masked_regs_to_frame(
816 &mut self,
817 start_frame_mem: FrameMemoryAddress,
818 source_reg_mask: u8,
819 node: &Node,
820 comment: &str,
821 ) {
822 let address_bytes = start_frame_mem.0.to_le_bytes();
823 self.state.add_instruction(
824 OpCode::StRegToFrameUsingMask,
825 &[
826 address_bytes[0],
827 address_bytes[1],
828 address_bytes[2],
829 address_bytes[3],
830 source_reg_mask,
831 ],
832 node,
833 comment,
834 );
835 }
836
837 pub fn add_block_copy_with_immediate_size(
838 &mut self,
839 target_base_ptr_reg: &PointerLocation,
840 source_base_ptr_reg: &PointerLocation,
841 memory_size: MemorySize,
842 node: &Node,
843 comment: &str,
844 ) {
845 let size_bytes = u32_to_bytes(memory_size.0);
846
847 self.state.add_instruction(
848 OpCode::BlockCopy,
849 &[
850 target_base_ptr_reg.addressing(),
851 source_base_ptr_reg.addressing(),
852 size_bytes.0,
853 size_bytes.1,
854 size_bytes.2,
855 size_bytes.3,
856 ],
857 node,
858 comment,
859 );
860 }
861
862 pub fn add_panic(&mut self, str: &TypedRegister, node: &Node, comment: &str) {
863 self.state
864 .add_instruction(OpCode::Panic, &[str.addressing()], node, comment);
865 }
866
867 pub fn add_halt(&mut self, node: &Node, comment: &str) {
868 self.state.add_instruction(OpCode::Hlt, &[], node, comment);
869 }
870
871 pub fn add_step(&mut self, node: &Node, comment: &str) {
872 self.state.add_instruction(OpCode::Step, &[], node, comment);
873 }
874 pub fn add_call(&mut self, function_ip: &InstructionPosition, node: &Node, comment: &str) {
875 let ip_bytes = function_ip.0.to_le_bytes();
876 self.state.add_instruction(
877 OpCode::Call,
878 &[ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3]],
879 node,
880 comment,
881 );
882 }
883
884 pub fn add_host_call(
885 &mut self,
886 host_function_id: u16,
887 arguments_count: u8,
888 node: &Node,
889 comment: &str,
890 ) {
891 let ip_bytes = Self::u16_to_octets(host_function_id);
892 self.state.add_instruction(
893 OpCode::HostCall,
894 &[ip_bytes.0, ip_bytes.1, arguments_count],
895 node,
896 comment,
897 );
898 }
899
900 pub fn patch_jump(
903 &mut self,
904 patch_position: PatchPosition,
905 target_position: &InstructionPosition,
906 ) {
907 const JMP_IF_NOT: u8 = OpCode::BTrue as u8;
908 const JMP_IF: u8 = OpCode::BFalse as u8;
909 const JMP: u8 = OpCode::B as u8;
910
911 const VEC_ITER_NEXT: u8 = OpCode::VecIterNext as u8;
912 const VEC_ITER_NEXT_PAIR: u8 = OpCode::VecIterNextPair as u8;
913 const MAP_ITER_NEXT: u8 = OpCode::MapIterNext as u8;
914 const MAP_ITER_NEXT_PAIR: u8 = OpCode::MapIterNextPair as u8;
915
916 const SPARSE_ITER_NEXT: u8 = OpCode::SparseIterNext as u8;
917 const SPARSE_ITER_NEXT_PAIR: u8 = OpCode::SparseIterNextPair as u8;
918
919 const STRING_ITER_NEXT: u8 = OpCode::StringIterNext as u8;
920 const STRING_ITER_NEXT_PAIR: u8 = OpCode::StringIterNextPair as u8;
921
922 const RANGE_ITER_NEXT: u8 = OpCode::RangeIterNext as u8;
923
924 let instruction = &mut self.state.instructions[patch_position.0.0 as usize];
928 let effective_pc_address = patch_position.0 + ProgramCounterDelta(1); let delta = *target_position - effective_pc_address;
930 let raw = delta.0;
931 let delta_bytes = raw.to_le_bytes();
932
933 match instruction.opcode {
934 JMP_IF_NOT | JMP_IF => {
935 instruction.operands[1] = delta_bytes[0];
936 instruction.operands[2] = delta_bytes[1];
937 }
938
939 JMP => {
940 instruction.operands[0] = delta_bytes[0];
941 instruction.operands[1] = delta_bytes[1];
942 }
943
944 SPARSE_ITER_NEXT | VEC_ITER_NEXT | STRING_ITER_NEXT | MAP_ITER_NEXT
945 | RANGE_ITER_NEXT => {
946 instruction.operands[2] = delta_bytes[0];
947 instruction.operands[3] = delta_bytes[1];
948 }
949
950 SPARSE_ITER_NEXT_PAIR
951 | VEC_ITER_NEXT_PAIR
952 | STRING_ITER_NEXT_PAIR
953 | MAP_ITER_NEXT_PAIR => {
954 instruction.operands[3] = delta_bytes[0];
955 instruction.operands[4] = delta_bytes[1];
956 }
957
958 _ => panic!("Attempted to patch a non-jump instruction at position {patch_position:?}"),
959 }
960 }
961
962 pub fn patch_jump_here(&mut self, jump_position: PatchPosition) {
964 self.patch_jump(jump_position, &self.position());
965 }
966
967 pub fn add_jmp(&mut self, pc: InstructionPosition, node: &Node, comment: &str) {
968 let delta_bytes = self.calculate_pc_delta_bytes(pc);
969 self.state
970 .add_instruction(OpCode::B, &[delta_bytes[0], delta_bytes[1]], node, comment);
971 }
972
973 const fn calculate_pc_delta(
974 &self,
975 target_instruction: InstructionPosition,
976 ) -> ProgramCounterDelta {
977 ProgramCounterDelta(
978 ((target_instruction.0 as i32) - ((self.position().0 + 1) as i32)) as i16,
979 )
980 }
981 const fn calculate_pc_delta_bytes(&self, pc: InstructionPosition) -> [u8; 2] {
982 let delta = self.calculate_pc_delta(pc);
983
984 delta.0.to_le_bytes()
985 }
986
987 pub fn add_frame_memory_clear(
988 &mut self,
989 frame_region: FrameMemoryRegion,
990 node: &Node,
991 comment: &str,
992 ) {
993 let addr_bytes = u32_to_bytes(frame_region.addr.0);
994 let size_bytes = u32_to_bytes(frame_region.size.0);
995 self.state.add_instruction(
996 OpCode::FrameMemClr,
997 &[
998 addr_bytes.0,
999 addr_bytes.1,
1000 addr_bytes.2,
1001 addr_bytes.3,
1002 size_bytes.0,
1003 size_bytes.1,
1004 size_bytes.2,
1005 size_bytes.3,
1006 ],
1007 node,
1008 comment,
1009 );
1010 }
1011
1012 pub fn add_map_iter_init(
1015 &mut self,
1016 iterator_target: &TypedRegister,
1017 pointer_to_map_header: &TypedRegister,
1018 node: &Node,
1019 comment: &str,
1020 ) {
1021 self.state.add_instruction(
1022 OpCode::MapIterInit,
1023 &[
1024 iterator_target.addressing(),
1025 pointer_to_map_header.addressing(),
1026 ],
1027 node,
1028 comment,
1029 );
1030 }
1031
1032 pub fn add_map_iter_next_placeholder(
1033 &mut self,
1034 iterator_target: &TypedRegister,
1035 closure_variable: &TypedRegister,
1036 node: &Node,
1037 comment: &str,
1038 ) -> PatchPosition {
1039 let position = self.position();
1040 self.state.add_instruction(
1041 OpCode::MapIterNext,
1042 &[
1043 iterator_target.addressing(),
1044 closure_variable.addressing(),
1045 0,
1046 ],
1047 node,
1048 comment,
1049 );
1050 PatchPosition(position)
1051 }
1052
1053 pub fn add_map_iter_next_pair_placeholder(
1054 &mut self,
1055 iterator_target: &TypedRegister,
1056 closure_variable: &TypedRegister,
1057 closure_variable_b: &TypedRegister,
1058 node: &Node,
1059 comment: &str,
1060 ) -> PatchPosition {
1061 let position = self.position();
1062 self.state.add_instruction(
1063 OpCode::MapIterNextPair,
1064 &[
1065 iterator_target.addressing(),
1066 closure_variable.addressing(),
1067 closure_variable_b.addressing(),
1068 0,
1069 ],
1070 node,
1071 comment,
1072 );
1073 PatchPosition(position)
1074 }
1075
1076 pub fn add_range_init(
1077 &mut self,
1078 target_range_iterator: &TypedRegister,
1079 min_reg: &TypedRegister,
1080 max_reg: &TypedRegister,
1081 is_inclusive_reg: &TypedRegister,
1082 node: &Node,
1083 comment: &str,
1084 ) {
1085 self.state.add_instruction(
1086 OpCode::RangeInit,
1087 &[
1088 target_range_iterator.addressing(),
1089 min_reg.addressing(),
1090 max_reg.addressing(),
1091 is_inclusive_reg.addressing(),
1092 ],
1093 node,
1094 comment,
1095 );
1096 }
1097
1098 pub fn add_range_iter_next_placeholder(
1099 &mut self,
1100 iterator_target: &TypedRegister,
1101 closure_variable: &TypedRegister,
1102 node: &Node,
1103
1104 comment: &str,
1105 ) -> PatchPosition {
1106 let position = self.position();
1107 self.state.add_instruction(
1108 OpCode::RangeIterNext,
1109 &[
1110 iterator_target.addressing(),
1111 closure_variable.addressing(),
1112 0,
1113 0,
1114 ],
1115 node,
1116 comment,
1117 );
1118 PatchPosition(position)
1119 }
1120
1121 pub fn add_string_duplicate(
1122 &mut self,
1123 dst_offset: &TypedRegister,
1124 lhs_offset: &TypedRegister,
1125 node: &Node,
1126 comment: &str,
1127 ) {
1128 self.state.add_instruction(
1129 OpCode::StringDuplicate,
1130 &[dst_offset.addressing(), lhs_offset.addressing()],
1131 node,
1132 comment,
1133 );
1134 }
1135
1136 pub fn add_string_append(
1137 &mut self,
1138 dst_offset: &TypedRegister,
1139 lhs_offset: &TypedRegister,
1140 rhs_offset: &TypedRegister,
1141 node: &Node,
1142 comment: &str,
1143 ) {
1144 self.state.add_instruction(
1145 OpCode::StringAppend,
1146 &[
1147 dst_offset.addressing(),
1148 lhs_offset.addressing(),
1149 rhs_offset.addressing(),
1150 ],
1151 node,
1152 comment,
1153 );
1154 }
1155 pub fn add_string_multiply(
1156 &mut self,
1157 dst_offset: &TypedRegister,
1158 lhs_offset: &TypedRegister,
1159 rhs_offset: &TypedRegister,
1160 node: &Node,
1161 comment: &str,
1162 ) {
1163 self.state.add_instruction(
1164 OpCode::StringRepeat,
1165 &[
1166 dst_offset.addressing(),
1167 lhs_offset.addressing(),
1168 rhs_offset.addressing(),
1169 ],
1170 node,
1171 comment,
1172 );
1173 }
1174
1175 pub fn add_string_cmp(
1176 &mut self,
1177 dest_bool_reg: &TypedRegister,
1178 a: &TypedRegister,
1179 b: &TypedRegister,
1180 node: &Node,
1181 comment: &str,
1182 ) {
1183 self.state.add_instruction(
1184 OpCode::StringCmp,
1185 &[dest_bool_reg.addressing(), a.addressing(), b.addressing()],
1186 node,
1187 comment,
1188 );
1189 }
1190
1191 pub fn add_fixed_capacity_array_init_fill_capacity_and_len(
1192 &mut self,
1193 target_vec_to_init: &PointerLocation,
1194 capacity: u16,
1195 element_size: &MemorySize,
1196 node: &Node,
1197 comment: &str,
1198 ) {
1199 debug_assert!(capacity > 0);
1201
1202 let capacity_bytes = u16_to_u8_pair(capacity);
1203 let element_bytes = u32_to_bytes(element_size.0);
1204
1205 self.state.add_instruction(
1206 OpCode::ArrayInitWithLenAndCapacity,
1207 &[
1208 target_vec_to_init.ptr_reg.addressing(),
1209 capacity_bytes.0,
1210 capacity_bytes.1,
1211 element_bytes.0,
1212 element_bytes.1,
1213 element_bytes.2,
1214 element_bytes.3,
1215 ],
1216 node,
1217 comment,
1218 );
1219 }
1220
1221 pub fn add_map_init_set_capacity(
1222 &mut self,
1223 target_map_to_init: &PointerLocation,
1224 logical_limit: CountU16,
1225 key_size_reg: &TypedRegister,
1226 key_alignment: MemoryAlignment,
1227 value_size_reg: &TypedRegister,
1228 value_alignment: MemoryAlignment,
1229 node: &Node,
1230 comment: &str,
1231 ) {
1232 debug_assert!(logical_limit.0 > 0);
1233
1234 let logical_limit_bytes = u16_to_u8_pair(logical_limit.0);
1235
1236 let key_alignment_usize: usize = key_alignment.into();
1237 let value_alignment_usize: usize = value_alignment.into();
1238
1239 self.state.add_instruction(
1241 OpCode::MapInitWithCapacityAndKeyAndTupleSizeAddr,
1242 &[
1243 target_map_to_init.ptr_reg.addressing(),
1244 logical_limit_bytes.0,
1245 logical_limit_bytes.1,
1246 key_size_reg.addressing(),
1247 key_alignment_usize as u8,
1248 value_size_reg.addressing(),
1249 value_alignment_usize as u8,
1250 ],
1251 node,
1252 comment,
1253 );
1254 }
1255
1256 pub fn add_map_overwrite(
1257 &mut self,
1258 destination_map: &PointerLocation,
1259 source_map: &PointerLocation,
1260 node: &Node,
1261 comment: &str,
1262 ) {
1263 self.state.add_instruction(
1264 OpCode::MapOverwrite,
1265 &[destination_map.addressing(), source_map.addressing()],
1266 node,
1267 comment,
1268 );
1269 }
1270
1271 pub fn add_range_iter_init(
1272 &mut self,
1273 iterator_target: &TypedRegister,
1274 range_source_header: &TypedRegister,
1275 node: &Node,
1276 comment: &str,
1277 ) {
1278 self.state.add_instruction(
1282 OpCode::RangeIterInit,
1283 &[
1284 iterator_target.addressing(),
1285 range_source_header.addressing(),
1286 ],
1287 node,
1288 comment,
1289 );
1290 }
1291
1292 pub fn add_vec_copy(
1293 &mut self,
1294 target_vec: &PointerLocation,
1295 source_vec: &PointerLocation,
1296 node: &Node,
1297 comment: &str,
1298 ) {
1299 self.state.add_instruction(
1300 OpCode::VecCopy,
1301 &[
1302 target_vec.ptr_reg.addressing(),
1303 source_vec.ptr_reg.addressing(),
1304 ],
1305 node,
1306 comment,
1307 );
1308 }
1309
1310 pub fn add_vec_copy_range(
1311 &mut self,
1312 target_vec: &PointerLocation,
1313 source_vec: &PointerLocation,
1314 range_header: &TypedRegister,
1315 node: &Node,
1316 comment: &str,
1317 ) {
1318 self.state.add_instruction(
1319 OpCode::VecCopyRange,
1320 &[
1321 target_vec.addressing(),
1322 source_vec.addressing(),
1323 range_header.addressing(),
1324 ],
1325 node,
1326 comment,
1327 );
1328 }
1329
1330 pub fn add_vec_init_set_capacity(
1331 &mut self,
1332 target_vec_to_init: &PointerLocation,
1333 capacity: CountU16,
1334 element_size: &MemorySize,
1335 node: &Node,
1336 comment: &str,
1337 ) {
1338 debug_assert!(capacity.0 > 0);
1340
1341 let capacity_bytes = u16_to_u8_pair(capacity.0);
1342 let element_bytes = u32_to_bytes(element_size.0);
1343 self.state.add_instruction(
1344 OpCode::VecInit,
1345 &[
1346 target_vec_to_init.ptr_reg.addressing(),
1347 capacity_bytes.0,
1348 capacity_bytes.1,
1349 element_bytes.0,
1350 element_bytes.1,
1351 element_bytes.2,
1352 element_bytes.3,
1353 ],
1354 node,
1355 comment,
1356 );
1357 }
1358
1359 pub fn add_vec_iter_init(
1360 &mut self,
1361 iterator_target: &TypedRegister,
1362 pointer_to_vec_header: &TypedRegister,
1363 node: &Node,
1364 comment: &str,
1365 ) {
1366 self.state.add_instruction(
1367 OpCode::VecIterInit,
1368 &[
1369 iterator_target.addressing(),
1370 pointer_to_vec_header.addressing(),
1371 ],
1372 node,
1373 comment,
1374 );
1375 }
1376
1377 pub fn add_vec_iter_next(
1378 &mut self,
1379 iterator_target: &TypedRegister,
1380 closure_variable: &TypedRegister,
1381 instruction_position: InstructionPosition,
1382 node: &Node,
1383 comment: &str,
1384 ) {
1385 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1386 self.state.add_instruction(
1387 OpCode::VecIterNext,
1388 &[
1389 iterator_target.addressing(),
1390 closure_variable.addressing(),
1391 bytes[0],
1392 bytes[1],
1393 ],
1394 node,
1395 comment,
1396 );
1397 }
1398
1399 pub fn add_vec_iter_next_pair(
1400 &mut self,
1401 iterator_target: &TypedRegister,
1402 closure_variable_key: &TypedRegister,
1403 closure_variable_value: &TypedRegister,
1404 instruction_position: InstructionPosition,
1405 node: &Node,
1406 comment: &str,
1407 ) {
1408 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1409 self.state.add_instruction(
1410 OpCode::VecIterNextPair,
1411 &[
1412 iterator_target.addressing(),
1413 closure_variable_key.addressing(),
1414 closure_variable_value.addressing(),
1415 bytes[0],
1416 bytes[1],
1417 ],
1418 node,
1419 comment,
1420 );
1421 }
1422
1423 pub fn add_string_iter_init(
1424 &mut self,
1425 iterator_target: &TypedRegister,
1426 pointer_to_vec_header: &TypedRegister,
1427 element_size: MemorySize,
1428 node: &Node,
1429 comment: &str,
1430 ) {
1431 let element_size_bytes = u32_to_bytes(element_size.0);
1432 self.state.add_instruction(
1433 OpCode::StringIterInit,
1434 &[
1435 iterator_target.addressing(),
1436 pointer_to_vec_header.addressing(),
1437 element_size_bytes.0,
1438 element_size_bytes.1,
1439 element_size_bytes.2,
1440 element_size_bytes.3,
1441 ],
1442 node,
1443 comment,
1444 );
1445 }
1446
1447 pub fn add_string_iter_next(
1448 &mut self,
1449 iterator_target: &TypedRegister,
1450 closure_variable: &TypedRegister,
1451 instruction_position: InstructionPosition,
1452 node: &Node,
1453 comment: &str,
1454 ) {
1455 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1456 self.state.add_instruction(
1457 OpCode::StringIterNext,
1458 &[
1459 iterator_target.addressing(),
1460 closure_variable.addressing(),
1461 bytes[0],
1462 bytes[1],
1463 ],
1464 node,
1465 comment,
1466 );
1467 }
1468
1469 pub fn add_string_iter_next_pair(
1470 &mut self,
1471 iterator_target: &TypedRegister,
1472 closure_variable_key: &TypedRegister,
1473 closure_variable_value: &TypedRegister,
1474 instruction_position: InstructionPosition,
1475 node: &Node,
1476 comment: &str,
1477 ) {
1478 let bytes = self.calculate_pc_delta_bytes(instruction_position);
1479 self.state.add_instruction(
1480 OpCode::StringIterNextPair,
1481 &[
1482 iterator_target.addressing(),
1483 closure_variable_key.addressing(),
1484 closure_variable_value.addressing(),
1485 bytes[0],
1486 bytes[1],
1487 ],
1488 node,
1489 comment,
1490 );
1491 }
1492 fn convert_to_lower_and_upper(data: u32) -> (u8, u8, u8, u8) {
1493 data.to_le_bytes().into()
1494 }
1495
1496 fn u16_to_octets(data: u16) -> (u8, u8) {
1497 data.to_le_bytes().into()
1498 }
1499
1500 pub fn add_st32_using_ptr_with_offset(
1501 &mut self,
1502 scalar_lvalue_location: &MemoryLocation,
1503 u32_reg: &TypedRegister,
1504 node: &Node,
1505 comment: &str,
1506 ) {
1507 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1509 self.state.add_instruction(
1510 OpCode::St32UsingPtrWithOffset,
1511 &[
1512 scalar_lvalue_location.base_ptr_reg.addressing(),
1513 offset_bytes.0,
1514 offset_bytes.1,
1515 offset_bytes.2,
1516 offset_bytes.3,
1517 u32_reg.index,
1518 ],
1519 node,
1520 comment,
1521 );
1522 }
1523
1524 pub fn add_st16_using_ptr_with_offset(
1525 &mut self,
1526 scalar_lvalue_location: &MemoryLocation,
1527 u16_reg: &TypedRegister,
1528 node: &Node,
1529 comment: &str,
1530 ) {
1531 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1533 self.state.add_instruction(
1534 OpCode::St16UsingPtrWithOffset,
1535 &[
1536 scalar_lvalue_location.base_ptr_reg.addressing(),
1537 offset_bytes.0,
1538 offset_bytes.1,
1539 offset_bytes.2,
1540 offset_bytes.3,
1541 u16_reg.index,
1542 ],
1543 node,
1544 comment,
1545 );
1546 }
1547
1548 pub fn add_st8_using_ptr_with_offset(
1549 &mut self,
1550 scalar_lvalue_location: &MemoryLocation,
1551 u8_reg: &TypedRegister,
1552 node: &Node,
1553 comment: &str,
1554 ) {
1555 let offset_bytes = u32_to_bytes(scalar_lvalue_location.offset.0);
1557 self.state.add_instruction(
1558 OpCode::St8UsingPtrWithOffset,
1559 &[
1560 scalar_lvalue_location.base_ptr_reg.addressing(),
1561 offset_bytes.0,
1562 offset_bytes.1,
1563 offset_bytes.2,
1564 offset_bytes.3,
1565 u8_reg.addressing(),
1566 ],
1567 node,
1568 comment,
1569 );
1570 }
1571
1572 pub fn add_mov_16_immediate_value(
1573 &mut self,
1574 dst_offset: &TypedRegister,
1575 value: u16,
1576 node: &Node,
1577 comment: &str,
1578 ) {
1579 let bytes = Self::u16_to_octets(value);
1580
1581 self.state.add_instruction(
1582 OpCode::Mov16FromImmediateValue,
1583 &[dst_offset.addressing(), bytes.0, bytes.1],
1584 node,
1585 comment,
1586 );
1587 }
1588
1589 pub fn add_mov_32_immediate_value(
1590 &mut self,
1591 dst_offset: &TypedRegister,
1592 value: u32,
1593 node: &Node,
1594 comment: &str,
1595 ) {
1596 let bytes = Self::convert_to_lower_and_upper(value);
1597
1598 self.state.add_instruction(
1599 OpCode::Mov32FromImmediateValue,
1600 &[dst_offset.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1601 node,
1602 comment,
1603 );
1604 }
1605
1606 pub fn add_ld32_from_absolute_memory_address(
1607 &mut self,
1608 dst_reg: &TypedRegister,
1609 absolute_mem_addr: &HeapMemoryAddress,
1610 node: &Node,
1611 comment: &str,
1612 ) {
1613 let bytes = u32_to_bytes(absolute_mem_addr.0);
1614
1615 self.state.add_instruction(
1616 OpCode::Ld32FromAbsoluteAddress,
1617 &[dst_reg.addressing(), bytes.0, bytes.1, bytes.2, bytes.3],
1618 node,
1619 comment,
1620 );
1621 }
1622
1623 pub fn add_ld16_from_pointer_from_memory_location(
1624 &mut self,
1625 dst_reg: &TypedRegister,
1626 source_memory_location: &MemoryLocation,
1627 node: &Node,
1628 comment: &str,
1629 ) {
1630 self.add_ld16_from_pointer_with_offset_u16(
1631 dst_reg,
1632 &source_memory_location.base_ptr_reg,
1633 source_memory_location.offset,
1634 node,
1635 comment,
1636 );
1637 }
1638
1639 pub fn add_ld16_from_pointer_with_offset_u16(
1640 &mut self,
1641 dst_reg: &TypedRegister,
1642 base_ptr_reg: &TypedRegister,
1643 offset: MemoryOffset,
1644 node: &Node,
1645 comment: &str,
1646 ) {
1647 let offset_bytes = u32_to_bytes(offset.0);
1648
1649 self.state.add_instruction(
1650 OpCode::Ld16FromPointerWithOffset,
1651 &[
1652 dst_reg.addressing(),
1653 base_ptr_reg.addressing(),
1654 offset_bytes.0,
1655 offset_bytes.1,
1656 offset_bytes.2,
1657 offset_bytes.3,
1658 ],
1659 node,
1660 comment,
1661 );
1662 }
1663
1664 pub fn add_ld32_from_pointer_with_offset_u16(
1665 &mut self,
1666 dst_reg: &TypedRegister,
1667 base_ptr_reg: &TypedRegister,
1668 offset: MemoryOffset,
1669 node: &Node,
1670 comment: &str,
1671 ) {
1672 let offset_bytes = u32_to_bytes(offset.0);
1673
1674 self.state.add_instruction(
1675 OpCode::Ld32FromPointerWithOffset,
1676 &[
1677 dst_reg.addressing(),
1678 base_ptr_reg.addressing(),
1679 offset_bytes.0,
1680 offset_bytes.1,
1681 offset_bytes.2,
1682 offset_bytes.3,
1683 ],
1684 node,
1685 comment,
1686 );
1687 }
1688
1689 pub fn add_ld8_from_absolute_memory_address(
1690 &mut self,
1691 dst_reg: &TypedRegister,
1692 absolute_mem_addr: &HeapMemoryAddress,
1693 node: &Node,
1694 comment: &str,
1695 ) {
1696 let absolute_memory_addr = u32_to_bytes(absolute_mem_addr.0);
1697
1698 self.state.add_instruction(
1699 OpCode::Ld8FromAbsoluteAddress,
1700 &[
1701 dst_reg.addressing(),
1702 absolute_memory_addr.0,
1703 absolute_memory_addr.1,
1704 absolute_memory_addr.2,
1705 absolute_memory_addr.3,
1706 ],
1707 node,
1708 comment,
1709 );
1710 }
1711
1712 pub fn add_check_u8(&mut self, dst_reg: &TypedRegister, node: &Node, comment: &str) {
1713 self.state
1714 .add_instruction(OpCode::CheckU8, &[dst_reg.addressing()], node, comment);
1715 }
1716
1717 pub fn add_ld8_from_pointer_with_offset(
1718 &mut self,
1719 dst_reg: &TypedRegister,
1720 base_ptr_reg: &TypedRegister,
1721 offset: MemoryOffset,
1722 node: &Node,
1723 comment: &str,
1724 ) {
1725 let offset_bytes = u32_to_bytes(offset.0);
1726
1727 self.state.add_instruction(
1728 OpCode::Ld8FromPointerWithOffset,
1729 &[
1730 dst_reg.addressing(),
1731 base_ptr_reg.addressing(),
1732 offset_bytes.0,
1733 offset_bytes.1,
1734 offset_bytes.2,
1735 offset_bytes.3,
1736 ],
1737 node,
1738 comment,
1739 );
1740 }
1741
1742 pub fn add_mov_reg(
1743 &mut self,
1744 dst_offset: &TypedRegister,
1745 src_offset: &TypedRegister,
1746 node: &Node,
1747 comment: &str,
1748 ) {
1749 if dst_offset.index == src_offset.index {
1750 return;
1751 }
1752 self.state.add_instruction(
1753 OpCode::MovReg,
1754 &[dst_offset.addressing(), src_offset.addressing()],
1755 node,
1756 comment,
1757 );
1758 }
1759
1760 pub fn add_mov8_immediate(
1761 &mut self,
1762 dst_offset: &TypedRegister,
1763 value: u8,
1764 node: &Node,
1765 comment: &str,
1766 ) {
1767 self.state.add_instruction(
1768 OpCode::Mov8FromImmediateValue,
1769 &[dst_offset.addressing(), value],
1770 node,
1771 comment,
1772 );
1773 }
1774
1775 pub fn add_add_u32(
1776 &mut self,
1777 dst_offset: &TypedRegister,
1778 lhs_offset: &TypedRegister,
1779 rhs_offset: &TypedRegister,
1780 node: &Node,
1781 comment: &str,
1782 ) {
1783 self.state.add_instruction(
1787 OpCode::AddU32,
1788 &[
1789 dst_offset.addressing(),
1790 lhs_offset.addressing(),
1791 rhs_offset.addressing(),
1792 ],
1793 node,
1794 comment,
1795 );
1796 }
1797
1798 pub fn add_add_u32_imm(
1799 &mut self,
1800 dst_offset: &TypedRegister,
1801 lhs_offset: &TypedRegister,
1802 rhs_immediate: u32,
1803 node: &Node,
1804 comment: &str,
1805 ) {
1806 let immediate_bytes = u32_to_bytes(rhs_immediate);
1810 self.state.add_instruction(
1811 OpCode::AddU32Imm,
1812 &[
1813 dst_offset.addressing(),
1814 lhs_offset.addressing(),
1815 immediate_bytes.0,
1816 immediate_bytes.1,
1817 immediate_bytes.2,
1818 immediate_bytes.3,
1819 ],
1820 node,
1821 comment,
1822 );
1823 }
1824
1825 pub fn add_mod_i32(
1826 &mut self,
1827 dst_offset: &TypedRegister,
1828 lhs_offset: &TypedRegister,
1829 rhs_offset: &TypedRegister,
1830 node: &Node,
1831 comment: &str,
1832 ) {
1833 self.state.add_instruction(
1838 OpCode::ModI32,
1839 &[
1840 dst_offset.addressing(),
1841 lhs_offset.addressing(),
1842 rhs_offset.addressing(),
1843 ],
1844 node,
1845 comment,
1846 );
1847 }
1848
1849 pub fn add_div_i32(
1850 &mut self,
1851 dst_offset: &TypedRegister,
1852 lhs_offset: &TypedRegister,
1853 rhs_offset: &TypedRegister,
1854 node: &Node,
1855 comment: &str,
1856 ) {
1857 self.state.add_instruction(
1861 OpCode::DivI32,
1862 &[
1863 dst_offset.addressing(),
1864 lhs_offset.addressing(),
1865 rhs_offset.addressing(),
1866 ],
1867 node,
1868 comment,
1869 );
1870 }
1871
1872 pub fn add_sub_u32(
1873 &mut self,
1874 dst_offset: &TypedRegister,
1875 lhs_offset: &TypedRegister,
1876 rhs_offset: &TypedRegister,
1877 node: &Node,
1878 comment: &str,
1879 ) {
1880 self.state.add_instruction(
1884 OpCode::SubU32,
1885 &[
1886 dst_offset.addressing(),
1887 lhs_offset.addressing(),
1888 rhs_offset.addressing(),
1889 ],
1890 node,
1891 comment,
1892 );
1893 }
1894
1895 pub fn add_mul_i32(
1896 &mut self,
1897 dst_offset: &TypedRegister,
1898 lhs_offset: &TypedRegister,
1899 rhs_offset: &TypedRegister,
1900 node: &Node,
1901 comment: &str,
1902 ) {
1903 self.state.add_instruction(
1907 OpCode::MulU32,
1908 &[
1909 dst_offset.addressing(),
1910 lhs_offset.addressing(),
1911 rhs_offset.addressing(),
1912 ],
1913 node,
1914 comment,
1915 );
1916 }
1917
1918 pub fn add_neg_i32(
1919 &mut self,
1920 target: &TypedRegister,
1921 source: &TypedRegister,
1922 node: &Node,
1923 comment: &str,
1924 ) {
1925 self.state.add_instruction(
1928 OpCode::NegI32,
1929 &[target.addressing(), source.addressing()],
1930 node,
1931 comment,
1932 );
1933 }
1934
1935 pub fn add_sub_f32(
1936 &mut self,
1937 dst_offset: &TypedRegister,
1938 lhs_offset: &TypedRegister,
1939 rhs_offset: &TypedRegister,
1940 node: &Node,
1941 comment: &str,
1942 ) {
1943 self.state.add_instruction(
1947 OpCode::SubU32,
1948 &[
1949 dst_offset.addressing(),
1950 lhs_offset.addressing(),
1951 rhs_offset.addressing(),
1952 ],
1953 node,
1954 comment,
1955 );
1956 }
1957 pub fn add_mul_f32(
1958 &mut self,
1959 dst_offset: &TypedRegister,
1960 lhs_offset: &TypedRegister,
1961 rhs_offset: &TypedRegister,
1962 node: &Node,
1963 comment: &str,
1964 ) {
1965 self.state.add_instruction(
1969 OpCode::MulF32,
1970 &[
1971 dst_offset.addressing(),
1972 lhs_offset.addressing(),
1973 rhs_offset.addressing(),
1974 ],
1975 node,
1976 comment,
1977 );
1978 }
1979 pub fn add_div_f32(
1980 &mut self,
1981 dst_offset: &TypedRegister,
1982 lhs_offset: &TypedRegister,
1983 rhs_offset: &TypedRegister,
1984 node: &Node,
1985 comment: &str,
1986 ) {
1987 self.state.add_instruction(
1991 OpCode::DivF32,
1992 &[
1993 dst_offset.addressing(),
1994 lhs_offset.addressing(),
1995 rhs_offset.addressing(),
1996 ],
1997 node,
1998 comment,
1999 );
2000 }
2001
2002 pub fn add_add_f32(
2003 &mut self,
2004 dst_offset: &TypedRegister,
2005 lhs_offset: &TypedRegister,
2006 rhs_offset: &TypedRegister,
2007 node: &Node,
2008 comment: &str,
2009 ) {
2010 self.state.add_instruction(
2014 OpCode::AddU32,
2015 &[
2016 dst_offset.addressing(),
2017 lhs_offset.addressing(),
2018 rhs_offset.addressing(),
2019 ],
2020 node,
2021 comment,
2022 );
2023 }
2024
2025 pub fn add_neg_f32(
2026 &mut self,
2027 target: &TypedRegister,
2028 source: &TypedRegister,
2029 node: &Node,
2030 comment: &str,
2031 ) {
2032 self.state.add_instruction(
2035 OpCode::NegI32,
2036 &[target.addressing(), source.addressing()],
2037 node,
2038 comment,
2039 );
2040 }
2041
2042 pub fn add_lt_i32(
2043 &mut self,
2044 dest_bool_reg: &TypedRegister,
2045 lhs_offset: &TypedRegister,
2046 rhs_offset: &TypedRegister,
2047 node: &Node,
2048 comment: &str,
2049 ) {
2050 self.state.add_instruction(
2053 OpCode::LtI32,
2054 &[
2055 dest_bool_reg.addressing(),
2056 lhs_offset.addressing(),
2057 rhs_offset.addressing(),
2058 ],
2059 node,
2060 comment,
2061 );
2062 }
2063
2064 pub fn add_lt_u32(
2065 &mut self,
2066 dest_bool_reg: &TypedRegister,
2067 lhs_offset: &TypedRegister,
2068 rhs_offset: &TypedRegister,
2069 node: &Node,
2070 comment: &str,
2071 ) {
2072 self.state.add_instruction(
2075 OpCode::LtU32,
2076 &[
2077 dest_bool_reg.addressing(),
2078 lhs_offset.addressing(),
2079 rhs_offset.addressing(),
2080 ],
2081 node,
2082 comment,
2083 );
2084 }
2085
2086 pub fn add_le_u32(
2087 &mut self,
2088 dest_bool_reg: &TypedRegister,
2089 lhs_offset: &TypedRegister,
2090 rhs_offset: &TypedRegister,
2091 node: &Node,
2092 comment: &str,
2093 ) {
2094 self.state.add_instruction(
2097 OpCode::LeU32,
2098 &[
2099 dest_bool_reg.addressing(),
2100 lhs_offset.addressing(),
2101 rhs_offset.addressing(),
2102 ],
2103 node,
2104 comment,
2105 );
2106 }
2107
2108 pub fn add_le_i32(
2109 &mut self,
2110 dest_bool_reg: &TypedRegister,
2111 lhs_offset: &TypedRegister,
2112 rhs_offset: &TypedRegister,
2113 node: &Node,
2114 comment: &str,
2115 ) {
2116 self.state.add_instruction(
2119 OpCode::LeI32,
2120 &[
2121 dest_bool_reg.addressing(),
2122 lhs_offset.addressing(),
2123 rhs_offset.addressing(),
2124 ],
2125 node,
2126 comment,
2127 );
2128 }
2129
2130 pub fn add_gt_i32(
2131 &mut self,
2132 dest_bool_reg: &TypedRegister,
2133 lhs_offset: &TypedRegister,
2134 rhs_offset: &TypedRegister,
2135 node: &Node,
2136 comment: &str,
2137 ) {
2138 self.state.add_instruction(
2141 OpCode::GtI32,
2142 &[
2143 dest_bool_reg.addressing(),
2144 lhs_offset.addressing(),
2145 rhs_offset.addressing(),
2146 ],
2147 node,
2148 comment,
2149 );
2150 }
2151
2152 pub fn add_ge_i32(
2153 &mut self,
2154 dest_bool_reg: &TypedRegister,
2155 lhs_offset: &TypedRegister,
2156 rhs_offset: &TypedRegister,
2157 node: &Node,
2158 comment: &str,
2159 ) {
2160 self.state.add_instruction(
2163 OpCode::GeI32,
2164 &[
2165 dest_bool_reg.addressing(),
2166 lhs_offset.addressing(),
2167 rhs_offset.addressing(),
2168 ],
2169 node,
2170 comment,
2171 );
2172 }
2173
2174 pub fn add_ge_u32(
2175 &mut self,
2176 dest_bool_reg: &TypedRegister,
2177 lhs_offset: &TypedRegister,
2178 rhs_offset: &TypedRegister,
2179 node: &Node,
2180 comment: &str,
2181 ) {
2182 self.state.add_instruction(
2185 OpCode::GeU32,
2186 &[
2187 dest_bool_reg.addressing(),
2188 lhs_offset.addressing(),
2189 rhs_offset.addressing(),
2190 ],
2191 node,
2192 comment,
2193 );
2194 }
2195
2196 pub fn add_gt_u32(
2197 &mut self,
2198 dest_bool_reg: &TypedRegister,
2199 lhs_offset: &TypedRegister,
2200 rhs_offset: &TypedRegister,
2201 node: &Node,
2202 comment: &str,
2203 ) {
2204 self.state.add_instruction(
2207 OpCode::GtU32,
2208 &[
2209 dest_bool_reg.addressing(),
2210 lhs_offset.addressing(),
2211 rhs_offset.addressing(),
2212 ],
2213 node,
2214 comment,
2215 );
2216 }
2217
2218 pub fn add_meqz(
2219 &mut self,
2220 dest_bool_reg: &TypedRegister,
2221 addr: &TypedRegister,
2222 node: &Node,
2223 comment: &str,
2224 ) {
2225 self.state.add_instruction(
2226 OpCode::MovEqualToZero,
2227 &[dest_bool_reg.addressing(), addr.addressing()],
2228 node,
2229 comment,
2230 );
2231 }
2232
2233 pub fn add_trap(&mut self, trap_code: u8, node: &Node, comment: &str) {
2234 self.state
2235 .add_instruction(OpCode::Trap, &[trap_code], node, comment);
2236 }
2237
2238 pub fn add_cmp_reg(
2239 &mut self,
2240 dest_bool_reg: &TypedRegister,
2241 source_a: &TypedRegister,
2242 source_b: &TypedRegister,
2243 node: &Node,
2244 comment: &str,
2245 ) {
2246 self.state.add_instruction(
2247 OpCode::CmpReg,
2248 &[
2249 dest_bool_reg.addressing(),
2250 source_a.addressing(),
2251 source_b.addressing(),
2252 ],
2253 node,
2254 comment,
2255 );
2256 }
2257
2258 pub fn add_block_cmp(
2259 &mut self,
2260 dest_bool_reg: &TypedRegister,
2261 first_ptr: &TypedRegister,
2262 second_ptr: &TypedRegister,
2263 size: MemorySize,
2264 node: &Node,
2265 comment: &str,
2266 ) {
2267 let block_size_bytes = u32_to_bytes(size.0);
2268 self.state.add_instruction(
2269 OpCode::CmpBlock,
2270 &[
2271 dest_bool_reg.addressing(),
2272 first_ptr.addressing(),
2273 second_ptr.addressing(),
2274 block_size_bytes.0,
2275 block_size_bytes.1,
2276 block_size_bytes.2,
2277 block_size_bytes.3,
2278 ],
2279 node,
2280 comment,
2281 );
2282 }
2283
2284 pub fn add_map_has(
2287 &mut self,
2288 dest_reg: &TypedRegister,
2289 self_addr: &PointerLocation,
2290 key_addr: &TypedRegister,
2291 node: &Node,
2292 comment: &str,
2293 ) {
2294 matches!(
2295 self_addr.ptr_reg.ty().kind,
2296 BasicTypeKind::DynamicLengthMapView(_, _)
2297 );
2298 self.state.add_instruction(
2299 OpCode::MapHas,
2300 &[
2301 dest_reg.addressing(),
2302 self_addr.addressing(),
2303 key_addr.addressing(),
2304 ],
2305 node,
2306 comment,
2307 );
2308 }
2309
2310 pub fn add_map_remove(
2311 &mut self,
2312 self_addr: &PointerLocation,
2313 key_addr: &TypedRegister,
2314 node: &Node,
2315 comment: &str,
2316 ) {
2317 matches!(
2318 self_addr.ptr_reg.ty().kind,
2319 BasicTypeKind::DynamicLengthMapView(_, _)
2320 );
2321 self.state.add_instruction(
2322 OpCode::MapRemove,
2323 &[self_addr.addressing(), key_addr.addressing()],
2324 node,
2325 comment,
2326 );
2327 }
2328
2329 pub fn add_map_get_entry_location(
2330 &mut self,
2331 target_entry_addr: &TypedRegister,
2332 map_self_addr: &PointerLocation,
2333 key: &TypedRegister,
2334 node: &Node,
2335 comment: &str,
2336 ) {
2337 self.state.add_instruction(
2339 OpCode::MapGetEntryLocation,
2340 &[
2341 target_entry_addr.addressing(),
2342 map_self_addr.addressing(),
2343 key.addressing(),
2344 ],
2345 node,
2346 comment,
2347 );
2348 }
2349
2350 pub fn add_map_get_or_reserve_entry_location(
2351 &mut self,
2352 target_entry_reg: &TypedRegister,
2353 map_self_addr: &PointerLocation,
2354 key: &TypedRegister,
2355 node: &Node,
2356 comment: &str,
2357 ) {
2358 self.state.add_instruction(
2359 OpCode::MapGetOrReserveEntryLocation,
2360 &[
2361 target_entry_reg.addressing(),
2362 map_self_addr.addressing(),
2363 key.addressing(),
2364 ],
2365 node,
2366 comment,
2367 );
2368 }
2369
2370 pub fn add_int_rnd(
2371 &mut self,
2372 dest: &TypedRegister,
2373 self_int: &TypedRegister,
2374 node: &Node,
2375 comment: &str,
2376 ) {
2377 assert!(dest.ty().is_int());
2378 assert!(self_int.ty().is_int());
2379 self.state.add_instruction(
2380 OpCode::IntToRnd,
2381 &[dest.addressing(), self_int.addressing()],
2382 node,
2383 comment,
2384 );
2385 }
2386
2387 pub fn add_int_min(
2388 &mut self,
2389 dest: &TypedRegister,
2390 self_int: &TypedRegister,
2391 other_int: &TypedRegister,
2392 node: &Node,
2393 comment: &str,
2394 ) {
2395 self.state.add_instruction(
2399 OpCode::IntMin,
2400 &[
2401 dest.addressing(),
2402 self_int.addressing(),
2403 other_int.addressing(),
2404 ],
2405 node,
2406 comment,
2407 );
2408 }
2409
2410 pub fn add_int_max(
2411 &mut self,
2412 dest: &TypedRegister,
2413 self_int: &TypedRegister,
2414 other_int: &TypedRegister,
2415 node: &Node,
2416 comment: &str,
2417 ) {
2418 self.state.add_instruction(
2422 OpCode::IntMax,
2423 &[
2424 dest.addressing(),
2425 self_int.addressing(),
2426 other_int.addressing(),
2427 ],
2428 node,
2429 comment,
2430 );
2431 }
2432
2433 pub fn add_int_clamp(
2434 &mut self,
2435 dest: &TypedRegister,
2436 self_int: &TypedRegister,
2437 min_int: &TypedRegister,
2438 max_int: &TypedRegister,
2439 node: &Node,
2440 comment: &str,
2441 ) {
2442 assert!(dest.ty().is_int());
2443 assert!(self_int.ty().is_int());
2444 assert!(min_int.ty().is_int());
2445 assert!(max_int.ty().is_int());
2446 self.state.add_instruction(
2447 OpCode::IntClamp,
2448 &[
2449 dest.addressing(),
2450 self_int.addressing(),
2451 min_int.addressing(),
2452 max_int.addressing(),
2453 ],
2454 node,
2455 comment,
2456 );
2457 }
2458
2459 pub fn add_int_abs(
2460 &mut self,
2461 dest: &TypedRegister,
2462 self_int: &TypedRegister,
2463 node: &Node,
2464 comment: &str,
2465 ) {
2466 self.state.add_instruction(
2469 OpCode::IntAbs,
2470 &[dest.addressing(), self_int.addressing()],
2471 node,
2472 comment,
2473 );
2474 }
2475
2476 pub fn add_int_to_float(
2477 &mut self,
2478 dest: &TypedRegister,
2479 self_int: &TypedRegister,
2480 node: &Node,
2481 comment: &str,
2482 ) {
2483 self.state.add_instruction(
2486 OpCode::IntToFloat,
2487 &[dest.addressing(), self_int.addressing()],
2488 node,
2489 comment,
2490 );
2491 }
2492
2493 pub fn add_int_to_string(
2494 &mut self,
2495 dest: &TypedRegister,
2496 self_int: &TypedRegister,
2497 node: &Node,
2498 comment: &str,
2499 ) {
2500 assert!(dest.ty().is_str());
2501 assert!(self_int.ty().is_int());
2502 self.state.add_instruction(
2503 OpCode::IntToString,
2504 &[dest.addressing(), self_int.addressing()],
2505 node,
2506 comment,
2507 );
2508 }
2509
2510 pub fn bool_to_string(
2511 &mut self,
2512 dest_str: &TypedRegister,
2513 self_bool: &TypedRegister,
2514 node: &Node,
2515 comment: &str,
2516 ) {
2517 assert!(dest_str.ty().is_str());
2518 assert!(self_bool.ty().is_bool());
2519 self.state.add_instruction(
2520 OpCode::BoolToString,
2521 &[dest_str.addressing(), self_bool.addressing()],
2522 node,
2523 comment,
2524 );
2525 }
2526
2527 pub fn byte_to_string(
2528 &mut self,
2529 dest_str: &TypedRegister,
2530 self_bool: &TypedRegister,
2531 node: &Node,
2532 comment: &str,
2533 ) {
2534 assert!(dest_str.ty().is_str());
2535 assert!(self_bool.ty().is_byte());
2536 self.state.add_instruction(
2537 OpCode::ByteToString,
2538 &[dest_str.addressing(), self_bool.addressing()],
2539 node,
2540 comment,
2541 );
2542 }
2543
2544 pub fn add_codepoint_to_string(
2545 &mut self,
2546 dest_str: &TypedRegister,
2547 self_char: &TypedRegister,
2548 node: &Node,
2549 comment: &str,
2550 ) {
2551 assert!(dest_str.ty().is_str());
2552 assert!(self_char.ty().is_codepoint());
2553 self.state.add_instruction(
2554 OpCode::CodepointToString,
2555 &[dest_str.addressing(), self_char.addressing()],
2556 node,
2557 comment,
2558 );
2559 }
2560
2561 pub fn add_string_to_string(
2562 &mut self,
2563 dest_str: &TypedRegister,
2564 self_str: &TypedRegister,
2565 node: &Node,
2566 comment: &str,
2567 ) {
2568 assert!(dest_str.ty().is_str());
2569 assert!(self_str.ty().is_str());
2570 self.state.add_instruction(
2571 OpCode::StringToString,
2572 &[dest_str.addressing(), self_str.addressing()],
2573 node,
2574 comment,
2575 );
2576 }
2577
2578 pub fn add_string_starts_with(
2579 &mut self,
2580 dest_bool: &TypedRegister,
2581 source_str: &TypedRegister,
2582 other_str: &TypedRegister,
2583 node: &Node,
2584 comment: &str,
2585 ) {
2586 assert!(dest_bool.ty().is_bool());
2587 assert!(other_str.ty().is_str());
2589 self.state.add_instruction(
2590 OpCode::StringStartsWith,
2591 &[
2592 dest_bool.addressing(),
2593 source_str.addressing(),
2594 other_str.addressing(),
2595 ],
2596 node,
2597 comment,
2598 );
2599 }
2600
2601 pub fn add_string_to_int(
2602 &mut self,
2603 dest_tuple: &TypedRegister,
2604 source_str: &TypedRegister,
2605 node: &Node,
2606 comment: &str,
2607 ) {
2608 self.state.add_instruction(
2609 OpCode::StringToInt,
2610 &[dest_tuple.addressing(), source_str.addressing()],
2611 node,
2612 comment,
2613 );
2614 }
2615
2616 pub fn add_string_to_float(
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::StringToFloat,
2625 &[dest_tuple.addressing(), source_str.addressing()],
2626 node,
2627 comment,
2628 );
2629 }
2630
2631 pub fn add_float_to_string(
2632 &mut self,
2633 dest_str: &TypedRegister,
2634 self_float: &TypedRegister,
2635 node: &Node,
2636 comment: &str,
2637 ) {
2638 assert!(dest_str.ty().is_str());
2639 assert!(self_float.ty().is_float());
2640 self.state.add_instruction(
2641 OpCode::FloatToString,
2642 &[dest_str.addressing(), self_float.addressing()],
2643 node,
2644 comment,
2645 );
2646 }
2647
2648 pub fn add_float_round(
2649 &mut self,
2650 dest_int: &TypedRegister,
2651 self_float: &TypedRegister,
2652 node: &Node,
2653 comment: &str,
2654 ) {
2655 assert!(self_float.ty().is_float());
2657 self.state.add_instruction(
2658 OpCode::FloatRound,
2659 &[dest_int.addressing(), self_float.addressing()],
2660 node,
2661 comment,
2662 );
2663 }
2664
2665 pub fn add_float_floor(
2666 &mut self,
2667 dest_int: &TypedRegister,
2668 self_float: &TypedRegister,
2669 node: &Node,
2670 comment: &str,
2671 ) {
2672 self.state.add_instruction(
2675 OpCode::FloatFloor,
2676 &[dest_int.addressing(), self_float.addressing()],
2677 node,
2678 comment,
2679 );
2680 }
2681
2682 pub fn add_float_sqrt(
2683 &mut self,
2684 dest_float: &TypedRegister,
2685 self_float: &TypedRegister,
2686 node: &Node,
2687 comment: &str,
2688 ) {
2689 self.state.add_instruction(
2692 OpCode::FloatSqrt,
2693 &[dest_float.addressing(), self_float.addressing()],
2694 node,
2695 comment,
2696 );
2697 }
2698
2699 pub fn add_float_sign(
2700 &mut self,
2701 dest_float: &TypedRegister,
2702 self_float: &TypedRegister,
2703 node: &Node,
2704 comment: &str,
2705 ) {
2706 assert!(dest_float.ty().is_float());
2707 assert!(self_float.ty().is_float());
2708 self.state.add_instruction(
2709 OpCode::FloatSign,
2710 &[dest_float.addressing(), self_float.addressing()],
2711 node,
2712 comment,
2713 );
2714 }
2715
2716 pub fn add_float_abs(
2717 &mut self,
2718 dest_float: &TypedRegister,
2719 self_float: &TypedRegister,
2720 node: &Node,
2721 comment: &str,
2722 ) {
2723 assert!(dest_float.ty().is_float());
2724 assert!(self_float.ty().is_float());
2725 self.state.add_instruction(
2726 OpCode::FloatAbs,
2727 &[dest_float.addressing(), self_float.addressing()],
2728 node,
2729 comment,
2730 );
2731 }
2732
2733 pub fn add_float_prnd(
2734 &mut self,
2735 dest_float: &TypedRegister,
2736 self_float: &TypedRegister,
2737 node: &Node,
2738 comment: &str,
2739 ) {
2740 assert!(dest_float.ty().is_float());
2741 assert!(self_float.ty().is_float());
2742 self.state.add_instruction(
2743 OpCode::FloatPseudoRandom,
2744 &[dest_float.addressing(), self_float.addressing()],
2745 node,
2746 comment,
2747 );
2748 }
2749
2750 pub fn add_float_sin(
2751 &mut self,
2752 dest_float: &TypedRegister,
2753 self_float: &TypedRegister,
2754 node: &Node,
2755 comment: &str,
2756 ) {
2757 assert!(dest_float.ty().is_float());
2758 assert!(self_float.ty().is_float());
2759 self.state.add_instruction(
2760 OpCode::FloatSin,
2761 &[dest_float.addressing(), self_float.addressing()],
2762 node,
2763 comment,
2764 );
2765 }
2766
2767 pub fn add_float_cos(
2768 &mut self,
2769 dest_float: &TypedRegister,
2770 self_float: &TypedRegister,
2771 node: &Node,
2772 comment: &str,
2773 ) {
2774 assert!(dest_float.ty().is_float());
2775 assert!(self_float.ty().is_float());
2776 self.state.add_instruction(
2777 OpCode::FloatCos,
2778 &[dest_float.addressing(), self_float.addressing()],
2779 node,
2780 comment,
2781 );
2782 }
2783
2784 pub fn add_float_acos(
2785 &mut self,
2786 dest_float: &TypedRegister,
2787 self_float: &TypedRegister,
2788 node: &Node,
2789 comment: &str,
2790 ) {
2791 assert!(dest_float.ty().is_float());
2792 assert!(self_float.ty().is_float());
2793 self.state.add_instruction(
2794 OpCode::FloatAcos,
2795 &[dest_float.addressing(), self_float.addressing()],
2796 node,
2797 comment,
2798 );
2799 }
2800
2801 pub fn add_float_asin(
2802 &mut self,
2803 dest_float: &TypedRegister,
2804 self_float: &TypedRegister,
2805 node: &Node,
2806 comment: &str,
2807 ) {
2808 assert!(dest_float.ty().is_float());
2809 assert!(self_float.ty().is_float());
2810 self.state.add_instruction(
2811 OpCode::FloatAsin,
2812 &[dest_float.addressing(), self_float.addressing()],
2813 node,
2814 comment,
2815 );
2816 }
2817
2818 pub fn add_float_atan2(
2819 &mut self,
2820 dest_float: &TypedRegister,
2821 self_float: &TypedRegister,
2822 node: &Node,
2823 comment: &str,
2824 ) {
2825 assert!(dest_float.ty().is_float());
2826 assert!(self_float.ty().is_float());
2827 self.state.add_instruction(
2828 OpCode::FloatAtan2,
2829 &[dest_float.addressing(), self_float.addressing()],
2830 node,
2831 comment,
2832 );
2833 }
2834
2835 pub fn add_float_min(
2836 &mut self,
2837 dest_float: &TypedRegister,
2838 self_float: &TypedRegister,
2839 other: &TypedRegister,
2840 node: &Node,
2841 comment: &str,
2842 ) {
2843 assert!(dest_float.ty().is_float());
2844 assert!(self_float.ty().is_float());
2845 self.state.add_instruction(
2846 OpCode::FloatMin,
2847 &[
2848 dest_float.addressing(),
2849 self_float.addressing(),
2850 other.addressing(),
2851 ],
2852 node,
2853 comment,
2854 );
2855 }
2856
2857 pub fn add_float_max(
2858 &mut self,
2859 dest_float: &TypedRegister,
2860 self_float: &TypedRegister,
2861 max_float: &TypedRegister,
2862 node: &Node,
2863 comment: &str,
2864 ) {
2865 assert!(dest_float.ty().is_float());
2866 assert!(self_float.ty().is_float());
2867 assert!(max_float.ty().is_float());
2868 self.state.add_instruction(
2869 OpCode::FloatMax,
2870 &[
2871 dest_float.addressing(),
2872 self_float.addressing(),
2873 max_float.addressing(),
2874 ],
2875 node,
2876 comment,
2877 );
2878 }
2879
2880 pub fn add_float_clamp(
2881 &mut self,
2882 dest_float: &TypedRegister,
2883 self_float: &TypedRegister,
2884 min_float: &TypedRegister,
2885 max_float: &TypedRegister,
2886 node: &Node,
2887 comment: &str,
2888 ) {
2889 assert!(dest_float.ty().is_float());
2890 assert!(self_float.ty().is_float());
2891 assert!(min_float.ty().is_float());
2892 assert!(max_float.ty().is_float());
2893
2894 self.state.add_instruction(
2895 OpCode::FloatClamp,
2896 &[
2897 dest_float.addressing(),
2898 min_float.addressing(),
2899 self_float.addressing(),
2900 max_float.addressing(),
2901 ],
2902 node,
2903 comment,
2904 );
2905 }
2906
2907 pub fn add_sparse_iter_init(
2908 &mut self,
2909 iterator_target: &TypedRegister,
2910 pointer_to_sparse_header: &TypedRegister,
2911 node: &Node,
2912 comment: &str,
2913 ) {
2914 self.state.add_instruction(
2915 OpCode::SparseIterInit,
2916 &[
2917 iterator_target.addressing(),
2918 pointer_to_sparse_header.addressing(),
2919 ],
2920 node,
2921 comment,
2922 );
2923 }
2924
2925 pub fn add_sparse_iter_next_placeholder(
2926 &mut self,
2927 iterator_target: &TypedRegister,
2928 closure_variable: &TypedRegister,
2929 node: &Node,
2930 comment: &str,
2931 ) -> PatchPosition {
2932 let position = self.position();
2933 self.state.add_instruction(
2934 OpCode::SparseIterNext,
2935 &[
2936 iterator_target.addressing(),
2937 closure_variable.addressing(),
2938 0,
2939 0,
2940 ],
2941 node,
2942 comment,
2943 );
2944 PatchPosition(position)
2945 }
2946
2947 pub fn add_sparse_iter_next_pair_placeholder(
2948 &mut self,
2949 iterator_target: &TypedRegister,
2950 closure_variable: &TypedRegister,
2951 closure_variable_b: &TypedRegister,
2952 node: &Node,
2953 comment: &str,
2954 ) -> PatchPosition {
2955 let position = self.position();
2956 self.state.add_instruction(
2957 OpCode::SparseIterNextPair,
2958 &[
2959 iterator_target.addressing(),
2960 closure_variable.addressing(),
2961 closure_variable_b.addressing(),
2962 0,
2963 0,
2964 ],
2965 node,
2966 comment,
2967 );
2968 PatchPosition(position)
2969 }
2970}