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