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