diff --git a/src/back/spv/instructions.rs b/src/back/spv/instructions.rs index bc5cc752d8..39a9c4e732 100644 --- a/src/back/spv/instructions.rs +++ b/src/back/spv/instructions.rs @@ -453,7 +453,49 @@ pub(super) fn instruction_function_call( // // Conversion Instructions // +fn instruction_unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Instruction { + let mut instruction = Instruction::new(op); + instruction.set_type(result_type_id); + instruction.set_result(id); + instruction.add_operand(value); + instruction +} +pub(super) fn instruction_convert_f_to_u( + result_type_id: Word, + id: Word, + float_value: Word, +) -> Instruction { + instruction_unary(Op::ConvertFToU, result_type_id, id, float_value) +} + +pub(super) fn instruction_convert_f_to_s( + result_type_id: Word, + id: Word, + float_value: Word, +) -> Instruction { + instruction_unary(Op::ConvertFToS, result_type_id, id, float_value) +} + +pub(super) fn instruction_convert_s_to_f( + result_type_id: Word, + id: Word, + signed_value: Word, +) -> Instruction { + instruction_unary(Op::ConvertSToF, result_type_id, id, signed_value) +} + +pub(super) fn instruction_convert_u_to_f( + result_type_id: Word, + id: Word, + unsigned_value: Word, +) -> Instruction { + instruction_unary(Op::ConvertUToF, result_type_id, id, unsigned_value) +} + +pub(super) fn instruction_bit_cast(result_type_id: Word, id: Word, operand: Word) -> Instruction { + instruction_unary(Op::Bitcast, result_type_id, id, operand) +} // // Composite Instructions // diff --git a/src/back/spv/writer.rs b/src/back/spv/writer.rs index 7821d2b4e1..92b600b68e 100644 --- a/src/back/spv/writer.rs +++ b/src/back/spv/writer.rs @@ -1033,6 +1033,79 @@ impl Writer { } _ => unimplemented!("{:?}", origin), }, + crate::Expression::As { + expr, + kind, + convert, + } => { + if !convert { + return None; + } + + let (expr_id, expr_type) = self + .write_expression( + ir_module, + ir_function, + &ir_function.expressions[*expr], + block, + function, + ) + .unwrap(); + + let id = self.generate_id(); + let instruction = match ir_module.types[expr_type.unwrap()].inner { + crate::TypeInner::Scalar { + kind: expr_kind, + width, + } => { + let kind_type_id = self.get_type_id( + &ir_module.types, + LookupType::Local(LocalType::Scalar { kind: *kind, width }), + ); + + if *convert { + super::instructions::instruction_bit_cast(kind_type_id, id, expr_id) + } else { + match (expr_kind, kind) { + (crate::ScalarKind::Float, crate::ScalarKind::Uint) => { + super::instructions::instruction_convert_f_to_u( + kind_type_id, + id, + expr_id, + ) + } + (crate::ScalarKind::Float, crate::ScalarKind::Sint) => { + super::instructions::instruction_convert_f_to_s( + kind_type_id, + id, + expr_id, + ) + } + (crate::ScalarKind::Sint, crate::ScalarKind::Float) => { + super::instructions::instruction_convert_s_to_f( + kind_type_id, + id, + expr_id, + ) + } + (crate::ScalarKind::Uint, crate::ScalarKind::Float) => { + super::instructions::instruction_convert_u_to_f( + kind_type_id, + id, + expr_id, + ) + } + _ => unreachable!(), + } + } + } + _ => unreachable!(), + }; + + block.body.push(instruction); + + Some((id, None)) + } _ => unimplemented!("{:?}", expression), } }