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