From ffbb263d7deedc236a0685f998639f09e93ebafd Mon Sep 17 00:00:00 2001 From: Russel Arbore <russel.jma@gmail.com> Date: Mon, 19 Feb 2024 19:57:24 -0600 Subject: [PATCH] Cast node --- hercules_cg/src/cpu_beta.rs | 1 + hercules_ir/src/ir.rs | 3 +++ hercules_ir/src/typecheck.rs | 20 ++++++++++++++++++++ hercules_opt/src/ccp.rs | 30 +++++++++++++++--------------- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/hercules_cg/src/cpu_beta.rs b/hercules_cg/src/cpu_beta.rs index 9a1c6741..e3974111 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 2657447e..e2c8c39b 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 ff631bd7..bcd3a152 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 8999730f..a7bc60bf 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() }; -- GitLab