From 18c8c852e484dc0d16ba999438cd63b4f3a7883f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 29 Sep 2016 16:42:01 +0200 Subject: [PATCH] factor out shared code --- src/interpreter/terminator/intrinsics.rs | 126 +++++++++++------------ 1 file changed, 58 insertions(+), 68 deletions(-) diff --git a/src/interpreter/terminator/intrinsics.rs b/src/interpreter/terminator/intrinsics.rs index f07688202ef7..817ded7273d6 100644 --- a/src/interpreter/terminator/intrinsics.rs +++ b/src/interpreter/terminator/intrinsics.rs @@ -31,7 +31,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let f32 = self.tcx.types.f32; let f64 = self.tcx.types.f64; - match &self.tcx.item_name(def_id).as_str()[..] { + let intrinsic_name = &self.tcx.item_name(def_id).as_str()[..]; + match intrinsic_name { "add_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Add, &args[0], &args[1], dest, dest_layout)?, "sub_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Sub, &args[0], &args[1], dest, dest_layout)?, "mul_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Mul, &args[0], &args[1], dest, dest_layout)?, @@ -64,76 +65,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.memory.copy(src, dest, count as usize * elem_size, elem_align)?; } - "ctpop" => { - let elem_ty = substs.type_at(0); - let elem_size = self.type_size(elem_ty); - let num = self.value_to_primval(args_ptrs[0], elem_ty)?; - let num = match num { - PrimVal::I8(i) => i.count_ones(), - PrimVal::U8(i) => i.count_ones(), - PrimVal::I16(i) => i.count_ones(), - PrimVal::U16(i) => i.count_ones(), - PrimVal::I32(i) => i.count_ones(), - PrimVal::U32(i) => i.count_ones(), - PrimVal::I64(i) => i.count_ones(), - PrimVal::U64(i) => i.count_ones(), - _ => bug!("ctpop called with non-integer type"), - }; - self.memory.write_uint(dest, num.into(), elem_size)?; - } - + "ctpop" | + "cttz" | + "ctlz" | "bswap" => { let elem_ty = substs.type_at(0); - let elem_size = self.type_size(elem_ty); let num = self.value_to_primval(args_ptrs[0], elem_ty)?; - let num = match num { - PrimVal::I8(i) => i.swap_bytes() as u64, - PrimVal::U8(i) => i.swap_bytes() as u64, - PrimVal::I16(i) => i.swap_bytes() as u64, - PrimVal::U16(i) => i.swap_bytes() as u64, - PrimVal::I32(i) => i.swap_bytes() as u64, - PrimVal::U32(i) => i.swap_bytes() as u64, - PrimVal::I64(i) => i.swap_bytes() as u64, - PrimVal::U64(i) => i.swap_bytes(), - _ => bug!("bswap called with non-integer type"), - }; - self.memory.write_uint(dest, num, elem_size)?; - } - - "cttz" => { - let elem_ty = substs.type_at(0); - let elem_size = self.type_size(elem_ty); - let num = self.value_to_primval(args_ptrs[0], elem_ty)?; - let num = match num { - PrimVal::I8(i) => i.trailing_zeros(), - PrimVal::U8(i) => i.trailing_zeros(), - PrimVal::I16(i) => i.trailing_zeros(), - PrimVal::U16(i) => i.trailing_zeros(), - PrimVal::I32(i) => i.trailing_zeros(), - PrimVal::U32(i) => i.trailing_zeros(), - PrimVal::I64(i) => i.trailing_zeros(), - PrimVal::U64(i) => i.trailing_zeros(), - _ => bug!("cttz called with non-integer type"), - }; - self.memory.write_uint(dest, num.into(), elem_size)?; - } - - "ctlz" => { - let elem_ty = substs.type_at(0); - let elem_size = self.type_size(elem_ty); - let num = self.value_to_primval(args_ptrs[0], elem_ty)?; - let num = match num { - PrimVal::I8(i) => i.leading_zeros(), - PrimVal::U8(i) => i.leading_zeros(), - PrimVal::I16(i) => i.leading_zeros(), - PrimVal::U16(i) => i.leading_zeros(), - PrimVal::I32(i) => i.leading_zeros(), - PrimVal::U32(i) => i.leading_zeros(), - PrimVal::I64(i) => i.leading_zeros(), - PrimVal::U64(i) => i.leading_zeros(), - _ => bug!("ctlz called with non-integer type"), - }; - self.memory.write_uint(dest, num.into(), elem_size)?; + let num = numeric_intrinsic(intrinsic_name, num); + self.memory.write_primval(dest, num)?; } "discriminant_value" => { @@ -396,3 +335,54 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.tcx.normalize_associated_type(&f.ty(self.tcx, param_substs)) } } + +fn numeric_intrinsic(name: &str, val: PrimVal) -> PrimVal { + use primval::PrimVal::*; + match name { + "ctpop" => match val { + I8(i) => I8(i.count_ones() as i8), + U8(i) => U8(i.count_ones() as u8), + I16(i) => I16(i.count_ones() as i16), + U16(i) => U16(i.count_ones() as u16), + I32(i) => I32(i.count_ones() as i32), + U32(i) => U32(i.count_ones() as u32), + I64(i) => I64(i.count_ones() as i64), + U64(i) => U64(i.count_ones() as u64), + other => bug!("invalid `ctpop` argument: {:?}", other), + }, + "cttz" => match val { + I8(i) => I8(i.trailing_zeros() as i8), + U8(i) => U8(i.trailing_zeros() as u8), + I16(i) => I16(i.trailing_zeros() as i16), + U16(i) => U16(i.trailing_zeros() as u16), + I32(i) => I32(i.trailing_zeros() as i32), + U32(i) => U32(i.trailing_zeros() as u32), + I64(i) => I64(i.trailing_zeros() as i64), + U64(i) => U64(i.trailing_zeros() as u64), + other => bug!("invalid `cttz` argument: {:?}", other), + }, + "ctlz" => match val { + I8(i) => I8(i.leading_zeros() as i8), + U8(i) => U8(i.leading_zeros() as u8), + I16(i) => I16(i.leading_zeros() as i16), + U16(i) => U16(i.leading_zeros() as u16), + I32(i) => I32(i.leading_zeros() as i32), + U32(i) => U32(i.leading_zeros() as u32), + I64(i) => I64(i.leading_zeros() as i64), + U64(i) => U64(i.leading_zeros() as u64), + other => bug!("invalid `ctlz` argument: {:?}", other), + }, + "bswap" => match val { + I8(i) => I8(i.swap_bytes() as i8), + U8(i) => U8(i.swap_bytes() as u8), + I16(i) => I16(i.swap_bytes() as i16), + U16(i) => U16(i.swap_bytes() as u16), + I32(i) => I32(i.swap_bytes() as i32), + U32(i) => U32(i.swap_bytes() as u32), + I64(i) => I64(i.swap_bytes() as i64), + U64(i) => U64(i.swap_bytes() as u64), + other => bug!("invalid `bswap` argument: {:?}", other), + }, + _ => bug!("not a numeric intrinsic: {}", name), + } +}