diff --git a/hercules_cg/src/cpu_beta.rs b/hercules_cg/src/cpu_beta.rs index 9a1c6741009e121a6b9fce71a939e733ec0f4ca0..e3974111b8f57aa75d456eeb367c0daf8aa861cf 100644 --- a/hercules_cg/src/cpu_beta.rs +++ b/hercules_cg/src/cpu_beta.rs @@ -614,6 +614,7 @@ fn emit_llvm_for_node( todo!() } } + UnaryOperator::Cast(_) => todo!(), }, Node::Binary { left, right, op } => { let opcode = match op { diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs index 2657447e2d8f28dd4b66ce17b8273dede6df8205..e2c8c39b0f515ba7b8083a7de279dec5376a0f77 100644 --- a/hercules_ir/src/ir.rs +++ b/hercules_ir/src/ir.rs @@ -225,6 +225,7 @@ pub enum Node { pub enum UnaryOperator { Not, Neg, + Cast(TypeID), } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -1005,6 +1006,7 @@ impl UnaryOperator { match self { UnaryOperator::Not => "Not", UnaryOperator::Neg => "Neg", + UnaryOperator::Cast(_) => "Cast", } } @@ -1012,6 +1014,7 @@ impl UnaryOperator { match self { UnaryOperator::Not => "not", UnaryOperator::Neg => "neg", + UnaryOperator::Cast(_) => "cast", } } } diff --git a/hercules_ir/src/typecheck.rs b/hercules_ir/src/typecheck.rs index ff631bd7d64828cb0519fd709f513736cc41b08b..bcd3a1523748445f673ab69c92de44e04660d4f1 100644 --- a/hercules_ir/src/typecheck.rs +++ b/hercules_ir/src/typecheck.rs @@ -625,6 +625,17 @@ fn typeflow( )); } } + UnaryOperator::Cast(dst_id) => { + let src_ty = &types[id.idx()]; + let dst_ty = &types[dst_id.idx()]; + if cast_compatible(src_ty, dst_ty) { + return Concrete(*dst_id); + } else { + return Error(String::from( + "Cast unary node has incompatible input and output types.", + )); + } + } } } @@ -940,3 +951,12 @@ pub fn fork_join_map( } fork_join_map } + +/* + * Determine if a given cast conversion is valid. + */ +pub fn cast_compatible(src_ty: &Type, dst_ty: &Type) -> bool { + // Can convert between any pair of primitive types, as long as the cast is + // not from a floating point type to a boolean type. + src_ty.is_primitive() && dst_ty.is_primitive() && !(src_ty.is_float() && dst_ty.is_bool()) +} diff --git a/hercules_opt/src/ccp.rs b/hercules_opt/src/ccp.rs index 8999730fcb78065433519e1ed219065ccba53ff9..a7bc60bf5fa94cb98a7b704a7bb4c5560f2c92a3 100644 --- a/hercules_opt/src/ccp.rs +++ b/hercules_opt/src/ccp.rs @@ -444,22 +444,22 @@ fn ccp_flow_function( } = inputs[input.idx()]; let new_constant = if let ConstantLattice::Constant(cons) = constant { - let new_cons = match (op, cons) { - (UnaryOperator::Not, Constant::Boolean(val)) => Constant::Boolean(!val), - (UnaryOperator::Not, Constant::Integer8(val)) => Constant::Integer8(!val), - (UnaryOperator::Not, Constant::Integer16(val)) => Constant::Integer16(!val), - (UnaryOperator::Not, Constant::Integer32(val)) => Constant::Integer32(!val), - (UnaryOperator::Not, Constant::Integer64(val)) => Constant::Integer64(!val), - (UnaryOperator::Neg, Constant::Integer8(val)) => Constant::Integer8(-val), - (UnaryOperator::Neg, Constant::Integer16(val)) => Constant::Integer16(-val), - (UnaryOperator::Neg, Constant::Integer32(val)) => Constant::Integer32(-val), - (UnaryOperator::Neg, Constant::Integer64(val)) => Constant::Integer64(-val), - (UnaryOperator::Neg, Constant::Float32(val)) => Constant::Float32(-val), - (UnaryOperator::Neg, Constant::Float64(val)) => Constant::Float64(-val), - (UnaryOperator::Neg, Constant::Zero(id)) => Constant::Zero(*id), + match (op, cons) { + (UnaryOperator::Not, Constant::Boolean(val)) => ConstantLattice::Constant(Constant::Boolean(!val)), + (UnaryOperator::Not, Constant::Integer8(val)) => ConstantLattice::Constant(Constant::Integer8(!val)), + (UnaryOperator::Not, Constant::Integer16(val)) => ConstantLattice::Constant(Constant::Integer16(!val)), + (UnaryOperator::Not, Constant::Integer32(val)) => ConstantLattice::Constant(Constant::Integer32(!val)), + (UnaryOperator::Not, Constant::Integer64(val)) => ConstantLattice::Constant(Constant::Integer64(!val)), + (UnaryOperator::Neg, Constant::Integer8(val)) => ConstantLattice::Constant(Constant::Integer8(-val)), + (UnaryOperator::Neg, Constant::Integer16(val)) => ConstantLattice::Constant(Constant::Integer16(-val)), + (UnaryOperator::Neg, Constant::Integer32(val)) => ConstantLattice::Constant(Constant::Integer32(-val)), + (UnaryOperator::Neg, Constant::Integer64(val)) => ConstantLattice::Constant(Constant::Integer64(-val)), + (UnaryOperator::Neg, Constant::Float32(val)) => ConstantLattice::Constant(Constant::Float32(-val)), + (UnaryOperator::Neg, Constant::Float64(val)) => ConstantLattice::Constant(Constant::Float64(-val)), + (UnaryOperator::Neg, Constant::Zero(id)) => ConstantLattice::Constant(Constant::Zero(*id)), + (UnaryOperator::Cast(_), _) => ConstantLattice::Bottom, _ => panic!("Unsupported combination of unary operation and constant value. Did typechecking succeed?") - }; - ConstantLattice::Constant(new_cons) + } } else { constant.clone() };