|
16 | 16 | //! can be somewhat arbitrary, an intentional decision. |
17 | 17 |
|
18 | 18 | use crate::component::{ |
19 | | - CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, FixedEncoding as FE, |
20 | | - FlatType, InterfaceType, MAX_FLAT_PARAMS, StringEncoding, Transcode, |
21 | | - TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFlagsIndex, TypeFutureTableIndex, |
22 | | - TypeListIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, |
23 | | - TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo, |
| 19 | + CanonicalAbiInfo, ComponentTypesBuilder, FixedEncoding as FE, FlatType, InterfaceType, |
| 20 | + StringEncoding, Transcode, TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, |
| 21 | + TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, |
| 22 | + TypeResourceTableIndex, TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex, |
| 23 | + TypeVariantIndex, VariantInfo, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, MAX_FLAT_PARAMS, |
24 | 24 | }; |
25 | 25 | use crate::fact::signature::Signature; |
26 | 26 | use crate::fact::transcode::Transcoder; |
@@ -2679,26 +2679,50 @@ impl<'a, 'b> Compiler<'a, 'b> { |
2679 | 2679 | InterfaceType::Enum(t) => &self.types[*t], |
2680 | 2680 | _ => panic!("expected an option"), |
2681 | 2681 | }; |
2682 | | - let src_info = variant_info(self.types, src_ty.names.iter().map(|_| None)); |
2683 | | - let dst_info = variant_info(self.types, dst_ty.names.iter().map(|_| None)); |
2684 | 2682 |
|
2685 | | - self.convert_variant( |
2686 | | - src, |
2687 | | - &src_info, |
2688 | | - dst, |
2689 | | - &dst_info, |
2690 | | - src_ty.names.iter().enumerate().map(|(src_i, src_name)| { |
2691 | | - let dst_i = dst_ty.names.iter().position(|n| n == src_name).unwrap(); |
2692 | | - let src_i = u32::try_from(src_i).unwrap(); |
2693 | | - let dst_i = u32::try_from(dst_i).unwrap(); |
2694 | | - VariantCase { |
2695 | | - src_i, |
2696 | | - dst_i, |
2697 | | - src_ty: None, |
2698 | | - dst_ty: None, |
| 2683 | + debug_assert_eq!(src_ty.info.size, dst_ty.info.size); |
| 2684 | + debug_assert_eq!(src_ty.names.len(), dst_ty.names.len()); |
| 2685 | + debug_assert!(src_ty |
| 2686 | + .names |
| 2687 | + .iter() |
| 2688 | + .zip(dst_ty.names.iter()) |
| 2689 | + .all(|(a, b)| a == b)); |
| 2690 | + |
| 2691 | + // Get the discriminant. |
| 2692 | + match src { |
| 2693 | + Source::Stack(s) => self.stack_get(&s.slice(0..1), ValType::I32), |
| 2694 | + Source::Memory(mem) => match src_ty.info.size { |
| 2695 | + DiscriminantSize::Size1 => self.i32_load8u(mem), |
| 2696 | + DiscriminantSize::Size2 => self.i32_load16u(mem), |
| 2697 | + DiscriminantSize::Size4 => self.i32_load(mem), |
| 2698 | + }, |
| 2699 | + } |
| 2700 | + let tmp = self.local_tee_new_tmp(ValType::I32); |
| 2701 | + |
| 2702 | + // Assert that the discriminant is valid. |
| 2703 | + self.instruction(I32Const(i32::try_from(src_ty.names.len()).unwrap())); |
| 2704 | + self.instruction(I32GtU); |
| 2705 | + self.instruction(If(BlockType::Empty)); |
| 2706 | + self.trap(Trap::InvalidDiscriminant); |
| 2707 | + self.instruction(End); |
| 2708 | + |
| 2709 | + // Save the discriminant to the destination. |
| 2710 | + match dst { |
| 2711 | + Destination::Stack(stack, _) => { |
| 2712 | + self.local_get_tmp(&tmp); |
| 2713 | + self.stack_set(&stack[..1], ValType::I32) |
| 2714 | + } |
| 2715 | + Destination::Memory(mem) => { |
| 2716 | + self.push_dst_addr(dst); |
| 2717 | + self.local_get_tmp(&tmp); |
| 2718 | + match dst_ty.info.size { |
| 2719 | + DiscriminantSize::Size1 => self.i32_store8(mem), |
| 2720 | + DiscriminantSize::Size2 => self.i32_store16(mem), |
| 2721 | + DiscriminantSize::Size4 => self.i32_store(mem), |
2699 | 2722 | } |
2700 | | - }), |
2701 | | - ); |
| 2723 | + } |
| 2724 | + } |
| 2725 | + self.free_temp_local(tmp); |
2702 | 2726 | } |
2703 | 2727 |
|
2704 | 2728 | fn translate_option( |
@@ -3118,6 +3142,10 @@ impl<'a, 'b> Compiler<'a, 'b> { |
3118 | 3142 | self.gen_temp_local(ty, LocalSet) |
3119 | 3143 | } |
3120 | 3144 |
|
| 3145 | + fn local_get_tmp(&mut self, local: &TempLocal) { |
| 3146 | + self.instruction(LocalGet(local.idx)); |
| 3147 | + } |
| 3148 | + |
3121 | 3149 | fn gen_temp_local(&mut self, ty: ValType, insn: fn(u32) -> Instruction<'static>) -> TempLocal { |
3122 | 3150 | // First check to see if any locals are available in this function which |
3123 | 3151 | // were previously generated but are no longer in use. |
|
0 commit comments