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