diff --git a/cranelift/codegen/meta/src/cdsl/ast.rs b/cranelift/codegen/meta/src/cdsl/ast.rs index 6604a5e870..68d99a0218 100644 --- a/cranelift/codegen/meta/src/cdsl/ast.rs +++ b/cranelift/codegen/meta/src/cdsl/ast.rs @@ -376,11 +376,17 @@ pub struct Apply { impl Apply { pub fn new(target: InstSpec, args: Vec) -> Self { - let (inst, value_types) = match target.into() { + let (inst, value_types) = match target { InstSpec::Inst(inst) => (inst, Vec::new()), InstSpec::Bound(bound_inst) => (bound_inst.inst, bound_inst.value_types), }; + // Apply should only operate on concrete value types, not "any". + let value_types = value_types + .into_iter() + .map(|vt| vt.expect("shouldn't be Any")) + .collect(); + // Basic check on number of arguments. assert!( inst.operands_in.len() == args.len(), diff --git a/cranelift/codegen/meta/src/cdsl/instructions.rs b/cranelift/codegen/meta/src/cdsl/instructions.rs index e1ab128d2c..13bac67c8f 100644 --- a/cranelift/codegen/meta/src/cdsl/instructions.rs +++ b/cranelift/codegen/meta/src/cdsl/instructions.rs @@ -183,7 +183,10 @@ impl Instruction { } pub fn bind(&self, lane_type: impl Into) -> BoundInstruction { - bind(self.clone(), lane_type.into(), Vec::new()) + bind(self.clone(), Some(lane_type.into()), Vec::new()) + } + pub fn bind_any(&self) -> BoundInstruction { + bind(self.clone(), None, Vec::new()) } } @@ -380,15 +383,34 @@ impl InstructionBuilder { } } +/// A thin wrapper like Option, but with more precise semantics. +#[derive(Clone)] +pub enum ValueTypeOrAny { + ValueType(ValueType), + Any, +} + +impl ValueTypeOrAny { + pub fn expect(self, msg: &str) -> ValueType { + match self { + ValueTypeOrAny::ValueType(vt) => vt, + ValueTypeOrAny::Any => panic!(format!("Unexpected Any: {}", msg)), + } + } +} + #[derive(Clone)] pub struct BoundInstruction { pub inst: Instruction, - pub value_types: Vec, + pub value_types: Vec, } impl BoundInstruction { pub fn bind(self, lane_type: impl Into) -> BoundInstruction { - bind(self.inst, lane_type.into(), self.value_types) + bind(self.inst, Some(lane_type.into()), self.value_types) + } + pub fn bind_any(self) -> BoundInstruction { + bind(self.inst, None, self.value_types) } } @@ -712,6 +734,12 @@ impl InstSpec { InstSpec::Bound(bound_inst) => &bound_inst.inst, } } + pub fn bind(&self, lane_type: impl Into) -> BoundInstruction { + match self { + InstSpec::Inst(inst) => inst.bind(lane_type), + InstSpec::Bound(inst) => inst.clone().bind(lane_type), + } + } } impl Into for &Instruction { @@ -729,10 +757,18 @@ impl Into for BoundInstruction { /// Helper bind reused by {Bound,}Instruction::bind. fn bind( inst: Instruction, - lane_type: LaneType, - mut value_types: Vec, + lane_type: Option, + mut value_types: Vec, ) -> BoundInstruction { - value_types.push(ValueType::from(lane_type)); + match lane_type { + Some(lane_type) => { + value_types.push(ValueTypeOrAny::ValueType(lane_type.into())); + } + None => { + value_types.push(ValueTypeOrAny::Any); + } + } + match &inst.polymorphic_info { Some(poly) => { assert!( @@ -747,5 +783,6 @@ fn bind( )); } } + BoundInstruction { inst, value_types } }