Skip to content

Commit f669c0a

Browse files
authored
Simplify and optimize the way that enums are passed in fused adapters (#10939)
* Simplify and optimize the way that `enum`s are passed in fused adapters instead of treating them like variants that don't have payloads, just check that the discriminant is in bounds. * cargo +stable fmt
1 parent 5750700 commit f669c0a

2 files changed

Lines changed: 156 additions & 18 deletions

File tree

crates/environ/src/fact/trampoline.rs

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,26 +2679,52 @@ impl<'a, 'b> Compiler<'a, 'b> {
26792679
InterfaceType::Enum(t) => &self.types[*t],
26802680
_ => panic!("expected an option"),
26812681
};
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));
26842682

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,
2699-
}
2700-
}),
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!(
2686+
src_ty
2687+
.names
2688+
.iter()
2689+
.zip(dst_ty.names.iter())
2690+
.all(|(a, b)| a == b)
27012691
);
2692+
2693+
// Get the discriminant.
2694+
match src {
2695+
Source::Stack(s) => self.stack_get(&s.slice(0..1), ValType::I32),
2696+
Source::Memory(mem) => match src_ty.info.size {
2697+
DiscriminantSize::Size1 => self.i32_load8u(mem),
2698+
DiscriminantSize::Size2 => self.i32_load16u(mem),
2699+
DiscriminantSize::Size4 => self.i32_load(mem),
2700+
},
2701+
}
2702+
let tmp = self.local_tee_new_tmp(ValType::I32);
2703+
2704+
// Assert that the discriminant is valid.
2705+
self.instruction(I32Const(i32::try_from(src_ty.names.len()).unwrap()));
2706+
self.instruction(I32GtU);
2707+
self.instruction(If(BlockType::Empty));
2708+
self.trap(Trap::InvalidDiscriminant);
2709+
self.instruction(End);
2710+
2711+
// Save the discriminant to the destination.
2712+
match dst {
2713+
Destination::Stack(stack, _) => {
2714+
self.local_get_tmp(&tmp);
2715+
self.stack_set(&stack[..1], ValType::I32)
2716+
}
2717+
Destination::Memory(mem) => {
2718+
self.push_dst_addr(dst);
2719+
self.local_get_tmp(&tmp);
2720+
match dst_ty.info.size {
2721+
DiscriminantSize::Size1 => self.i32_store8(mem),
2722+
DiscriminantSize::Size2 => self.i32_store16(mem),
2723+
DiscriminantSize::Size4 => self.i32_store(mem),
2724+
}
2725+
}
2726+
}
2727+
self.free_temp_local(tmp);
27022728
}
27032729

27042730
fn translate_option(
@@ -3118,6 +3144,10 @@ impl<'a, 'b> Compiler<'a, 'b> {
31183144
self.gen_temp_local(ty, LocalSet)
31193145
}
31203146

3147+
fn local_get_tmp(&mut self, local: &TempLocal) {
3148+
self.instruction(LocalGet(local.idx));
3149+
}
3150+
31213151
fn gen_temp_local(&mut self, ty: ValType, insn: fn(u32) -> Instruction<'static>) -> TempLocal {
31223152
// First check to see if any locals are available in this function which
31233153
// were previously generated but are no longer in use.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
;;! target = "riscv64"
2+
;;! test = 'optimize'
3+
;;! filter = 'wasm_func_1'
4+
5+
(component
6+
(type $a (enum "a" "b" "c"))
7+
(type $func_ty (func (param "x" $a)))
8+
9+
(component $c1
10+
(import "a" (type $a' (eq $a)))
11+
(core module $m1
12+
(func (export "f") (result i32)
13+
(i32.const 0)))
14+
(core instance $ci1 (instantiate $m1))
15+
(func (export "f") (result $a') (canon lift (core func $ci1 "f"))))
16+
17+
(component $c2
18+
(import "a" (type $a' (eq $a)))
19+
(import "f" (func $f (result $a')))
20+
(core func $g (canon lower (func $f)))
21+
(core module $m2
22+
(import "" "f" (func (result i32)))
23+
(func (export "f") (result i32) (call 0)))
24+
(core instance $ci2
25+
(instantiate $m2 (with "" (instance (export "f" (func $g))))))
26+
(func (export "f") (result $a') (canon lift (core func $ci2 "f"))))
27+
28+
(instance $i1 (instantiate $c1 (with "a" (type $a))))
29+
(instance $i2 (instantiate $c2
30+
(with "a" (type $a))
31+
(with "f" (func $i1 "f"))))
32+
)
33+
34+
;; function u0:1(i64 vmctx, i64) -> i32 tail {
35+
;; gv0 = vmctx
36+
;; gv1 = load.i64 notrap aligned readonly gv0+8
37+
;; gv2 = load.i64 notrap aligned gv1+16
38+
;; gv3 = vmctx
39+
;; gv4 = load.i64 notrap aligned readonly can_move gv3+104
40+
;; gv5 = load.i64 notrap aligned readonly can_move gv3+80
41+
;; sig0 = (i64 vmctx, i64) -> i32 tail
42+
;; fn0 = u0:0 sig0
43+
;; stack_limit = gv2
44+
;;
45+
;; block0(v0: i64, v1: i64):
46+
;; @0063 v4 = load.i64 notrap aligned readonly can_move v0+104
47+
;; @0063 v5 = load.i32 notrap aligned table v4
48+
;; @0065 v6 = iconst.i32 1
49+
;; @0067 v7 = band v5, v6 ; v6 = 1
50+
;; @0061 v3 = iconst.i32 0
51+
;; @0068 v8 = icmp eq v7, v3 ; v3 = 0
52+
;; @0068 v9 = uextend.i32 v8
53+
;; @0069 brif v9, block2, block3
54+
;;
55+
;; block2:
56+
;; @006b trap user11
57+
;;
58+
;; block3:
59+
;; @006d v10 = load.i64 notrap aligned readonly can_move v0+80
60+
;; @006d v11 = load.i32 notrap aligned table v10
61+
;; @006f v12 = iconst.i32 2
62+
;; @0071 v13 = band v11, v12 ; v12 = 2
63+
;; v82 = iconst.i32 0
64+
;; v83 = icmp eq v13, v82 ; v82 = 0
65+
;; @0072 v15 = uextend.i32 v83
66+
;; @0073 brif v15, block4, block5
67+
;;
68+
;; block4:
69+
;; @0075 trap user11
70+
;;
71+
;; block5:
72+
;; @0079 v18 = iconst.i32 -3
73+
;; @007b v19 = band.i32 v11, v18 ; v18 = -3
74+
;; @007c store notrap aligned table v19, v10
75+
;; v70 = iconst.i32 -4
76+
;; v76 = band.i32 v11, v70 ; v70 = -4
77+
;; @0083 store notrap aligned table v76, v10
78+
;; v84 = iconst.i32 1
79+
;; v85 = bor v19, v84 ; v84 = 1
80+
;; @008a store notrap aligned table v85, v10
81+
;; @008c v32 = load.i64 notrap aligned readonly can_move v0+56
82+
;; @008c v33 = load.i64 notrap aligned readonly can_move v0+72
83+
;; @008c v34 = call_indirect sig0, v32(v33, v0)
84+
;; @0090 v36 = load.i32 notrap aligned table v4
85+
;; @0080 v23 = iconst.i32 -2
86+
;; @0094 v38 = band v36, v23 ; v23 = -2
87+
;; @0095 store notrap aligned table v38, v4
88+
;; @009b v40 = iconst.i32 3
89+
;; @009d v41 = icmp ugt v34, v40 ; v40 = 3
90+
;; @009d v42 = uextend.i32 v41
91+
;; @009e brif v42, block6, block7
92+
;;
93+
;; block6:
94+
;; @00a0 trap user11
95+
;;
96+
;; block7:
97+
;; v86 = iconst.i32 1
98+
;; v87 = bor.i32 v36, v86 ; v86 = 1
99+
;; @00a9 store notrap aligned table v87, v4
100+
;; @00ab v49 = load.i32 notrap aligned table v10
101+
;; v88 = iconst.i32 2
102+
;; v89 = bor v49, v88 ; v88 = 2
103+
;; @00b0 store notrap aligned table v89, v10
104+
;; @00b2 jump block1
105+
;;
106+
;; block1:
107+
;; @00b2 return v34
108+
;; }

0 commit comments

Comments
 (0)