1*a631d20aSPaul Osborne use cranelift_codegen::ir;
2*a631d20aSPaul Osborne use cranelift_codegen::ir::InstBuilder;
3*a631d20aSPaul Osborne use cranelift_codegen::ir::types::{I32, I64};
4*a631d20aSPaul Osborne use cranelift_frontend::FunctionBuilder;
5*a631d20aSPaul Osborne 
6*a631d20aSPaul Osborne /// Universal control effect. This structure encodes return signal,
7*a631d20aSPaul Osborne /// resume signal, suspension signal, and handler index into a
8*a631d20aSPaul Osborne /// u64 value. This instance is used at compile time. There is a runtime
9*a631d20aSPaul Osborne /// counterpart in `continuations/src/lib.rs`.
10*a631d20aSPaul Osborne /// We convert to and from u64 as follows: The low 32 bits of the u64 are the
11*a631d20aSPaul Osborne /// discriminant, the high 32 bits are the handler_index (if `Suspend`)
12*a631d20aSPaul Osborne #[derive(Clone, Copy)]
13*a631d20aSPaul Osborne pub struct ControlEffect(ir::Value);
14*a631d20aSPaul Osborne 
15*a631d20aSPaul Osborne impl ControlEffect {
16*a631d20aSPaul Osborne     // Returns the discriminant
signal(&self, builder: &mut FunctionBuilder) -> ir::Value17*a631d20aSPaul Osborne     pub fn signal(&self, builder: &mut FunctionBuilder) -> ir::Value {
18*a631d20aSPaul Osborne         builder.ins().ushr_imm(self.0, 32)
19*a631d20aSPaul Osborne     }
20*a631d20aSPaul Osborne 
from_u64(val: ir::Value) -> Self21*a631d20aSPaul Osborne     pub fn from_u64(val: ir::Value) -> Self {
22*a631d20aSPaul Osborne         Self(val)
23*a631d20aSPaul Osborne     }
24*a631d20aSPaul Osborne 
to_u64(&self) -> ir::Value25*a631d20aSPaul Osborne     pub fn to_u64(&self) -> ir::Value {
26*a631d20aSPaul Osborne         self.0
27*a631d20aSPaul Osborne     }
28*a631d20aSPaul Osborne 
encode_resume(builder: &mut FunctionBuilder) -> Self29*a631d20aSPaul Osborne     pub fn encode_resume(builder: &mut FunctionBuilder) -> Self {
30*a631d20aSPaul Osborne         let discriminant = builder.ins().iconst(
31*a631d20aSPaul Osborne             I64,
32*a631d20aSPaul Osborne             i64::from(wasmtime_environ::CONTROL_EFFECT_RESUME_DISCRIMINANT),
33*a631d20aSPaul Osborne         );
34*a631d20aSPaul Osborne         let val = builder.ins().ishl_imm(discriminant, 32);
35*a631d20aSPaul Osborne 
36*a631d20aSPaul Osborne         Self(val)
37*a631d20aSPaul Osborne     }
38*a631d20aSPaul Osborne 
encode_switch(builder: &mut FunctionBuilder) -> Self39*a631d20aSPaul Osborne     pub fn encode_switch(builder: &mut FunctionBuilder) -> Self {
40*a631d20aSPaul Osborne         let discriminant = builder.ins().iconst(
41*a631d20aSPaul Osborne             I64,
42*a631d20aSPaul Osborne             i64::from(wasmtime_environ::CONTROL_EFFECT_SWITCH_DISCRIMINANT),
43*a631d20aSPaul Osborne         );
44*a631d20aSPaul Osborne         let val = builder.ins().ishl_imm(discriminant, 32);
45*a631d20aSPaul Osborne 
46*a631d20aSPaul Osborne         Self(val)
47*a631d20aSPaul Osborne     }
48*a631d20aSPaul Osborne 
encode_suspend(builder: &mut FunctionBuilder, handler_index: ir::Value) -> Self49*a631d20aSPaul Osborne     pub fn encode_suspend(builder: &mut FunctionBuilder, handler_index: ir::Value) -> Self {
50*a631d20aSPaul Osborne         let discriminant = builder.ins().iconst(
51*a631d20aSPaul Osborne             I64,
52*a631d20aSPaul Osborne             i64::from(wasmtime_environ::CONTROL_EFFECT_SUSPEND_DISCRIMINANT),
53*a631d20aSPaul Osborne         );
54*a631d20aSPaul Osborne         let val = builder.ins().ishl_imm(discriminant, 32);
55*a631d20aSPaul Osborne         let handler_index = builder.ins().uextend(I64, handler_index);
56*a631d20aSPaul Osborne         let val = builder.ins().bor(val, handler_index);
57*a631d20aSPaul Osborne 
58*a631d20aSPaul Osborne         Self(val)
59*a631d20aSPaul Osborne     }
60*a631d20aSPaul Osborne 
61*a631d20aSPaul Osborne     /// Returns the payload of the `Suspend` variant
handler_index(self, builder: &mut FunctionBuilder) -> ir::Value62*a631d20aSPaul Osborne     pub fn handler_index(self, builder: &mut FunctionBuilder) -> ir::Value {
63*a631d20aSPaul Osborne         builder.ins().ireduce(I32, self.0)
64*a631d20aSPaul Osborne     }
65*a631d20aSPaul Osborne }
66