implement _nonzero intrinsics
This commit is contained in:
parent
1a1d741df9
commit
269667e152
3 changed files with 55 additions and 6 deletions
|
|
@ -33,6 +33,7 @@ pub enum EvalError<'tcx> {
|
|||
ExecuteMemory,
|
||||
ArrayIndexOutOfBounds(Span, u64, u64),
|
||||
Math(Span, ConstMathErr),
|
||||
Intrinsic(String),
|
||||
OverflowingMath,
|
||||
InvalidChar(u128),
|
||||
OutOfMemory {
|
||||
|
|
@ -104,6 +105,8 @@ impl<'tcx> Error for EvalError<'tcx> {
|
|||
"array index out of bounds",
|
||||
EvalError::Math(..) =>
|
||||
"mathematical operation failed",
|
||||
EvalError::Intrinsic(..) =>
|
||||
"intrinsic failed",
|
||||
EvalError::OverflowingMath =>
|
||||
"attempted to do overflowing math",
|
||||
EvalError::NoMirFor(..) =>
|
||||
|
|
@ -168,6 +171,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
|
|||
write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
|
||||
EvalError::Math(span, ref err) =>
|
||||
write!(f, "{:?} at {:?}", err, span),
|
||||
EvalError::Intrinsic(ref err) =>
|
||||
write!(f, "{}", err),
|
||||
EvalError::InvalidChar(c) =>
|
||||
write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
|
||||
EvalError::OutOfMemory { allocation_size, memory_size, memory_usage } =>
|
||||
|
|
|
|||
|
|
@ -154,12 +154,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
|
||||
"ctpop" |
|
||||
"cttz" |
|
||||
"cttz_nonzero" |
|
||||
"ctlz" |
|
||||
"ctlz_nonzero" |
|
||||
"bswap" => {
|
||||
let ty = substs.type_at(0);
|
||||
let num = self.value_to_primval(arg_vals[0], ty)?;
|
||||
let num = self.value_to_primval(arg_vals[0], ty)?.to_bytes()?;
|
||||
let kind = self.ty_to_primval_kind(ty)?;
|
||||
let num = numeric_intrinsic(intrinsic_name, num, kind)?;
|
||||
let num = if intrinsic_name.ends_with("_nonzero") {
|
||||
if num == 0 {
|
||||
return Err(EvalError::Intrinsic(format!("{} called on 0", intrinsic_name)))
|
||||
}
|
||||
numeric_intrinsic(intrinsic_name.trim_right_matches("_nonzero"), num, kind)?
|
||||
} else {
|
||||
numeric_intrinsic(intrinsic_name, num, kind)?
|
||||
};
|
||||
self.write_primval(dest, num, ty)?;
|
||||
}
|
||||
|
||||
|
|
@ -538,13 +547,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
|
||||
fn numeric_intrinsic<'tcx>(
|
||||
name: &str,
|
||||
val: PrimVal,
|
||||
bytes: u128,
|
||||
kind: PrimValKind
|
||||
) -> EvalResult<'tcx, PrimVal> {
|
||||
macro_rules! integer_intrinsic {
|
||||
($method:ident) => ({
|
||||
let bytes = val.to_bytes()?;
|
||||
|
||||
use value::PrimValKind::*;
|
||||
let result_bytes = match kind {
|
||||
I8 => (bytes as i8).$method() as u128,
|
||||
|
|
@ -557,7 +564,7 @@ fn numeric_intrinsic<'tcx>(
|
|||
U64 => (bytes as u64).$method() as u128,
|
||||
I128 => (bytes as i128).$method() as u128,
|
||||
U128 => bytes.$method() as u128,
|
||||
_ => bug!("invalid `{}` argument: {:?}", name, val),
|
||||
_ => bug!("invalid `{}` argument: {:?}", name, bytes),
|
||||
};
|
||||
|
||||
PrimVal::Bytes(result_bytes)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ mod rusti {
|
|||
extern "rust-intrinsic" {
|
||||
pub fn ctpop<T>(x: T) -> T;
|
||||
pub fn ctlz<T>(x: T) -> T;
|
||||
pub fn ctlz_nonzero<T>(x: T) -> T;
|
||||
pub fn cttz<T>(x: T) -> T;
|
||||
pub fn cttz_nonzero<T>(x: T) -> T;
|
||||
pub fn bswap<T>(x: T) -> T;
|
||||
}
|
||||
}
|
||||
|
|
@ -68,6 +70,21 @@ pub fn main() {
|
|||
assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25);
|
||||
assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57);
|
||||
|
||||
assert_eq!(ctlz_nonzero(1u8), 7); assert_eq!(ctlz_nonzero(1i8), 7);
|
||||
assert_eq!(ctlz_nonzero(1u16), 15); assert_eq!(ctlz_nonzero(1i16), 15);
|
||||
assert_eq!(ctlz_nonzero(1u32), 31); assert_eq!(ctlz_nonzero(1i32), 31);
|
||||
assert_eq!(ctlz_nonzero(1u64), 63); assert_eq!(ctlz_nonzero(1i64), 63);
|
||||
|
||||
assert_eq!(ctlz_nonzero(10u8), 4); assert_eq!(ctlz_nonzero(10i8), 4);
|
||||
assert_eq!(ctlz_nonzero(10u16), 12); assert_eq!(ctlz_nonzero(10i16), 12);
|
||||
assert_eq!(ctlz_nonzero(10u32), 28); assert_eq!(ctlz_nonzero(10i32), 28);
|
||||
assert_eq!(ctlz_nonzero(10u64), 60); assert_eq!(ctlz_nonzero(10i64), 60);
|
||||
|
||||
assert_eq!(ctlz_nonzero(100u8), 1); assert_eq!(ctlz_nonzero(100i8), 1);
|
||||
assert_eq!(ctlz_nonzero(100u16), 9); assert_eq!(ctlz_nonzero(100i16), 9);
|
||||
assert_eq!(ctlz_nonzero(100u32), 25); assert_eq!(ctlz_nonzero(100i32), 25);
|
||||
assert_eq!(ctlz_nonzero(100u64), 57); assert_eq!(ctlz_nonzero(100i64), 57);
|
||||
|
||||
assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0);
|
||||
assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0);
|
||||
assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0);
|
||||
|
|
@ -93,6 +110,26 @@ pub fn main() {
|
|||
assert_eq!(cttz(100u32), 2); assert_eq!(cttz(100i32), 2);
|
||||
assert_eq!(cttz(100u64), 2); assert_eq!(cttz(100i64), 2);
|
||||
|
||||
assert_eq!(cttz_nonzero(-1i8 as u8), 0); assert_eq!(cttz_nonzero(-1i8), 0);
|
||||
assert_eq!(cttz_nonzero(-1i16 as u16), 0); assert_eq!(cttz_nonzero(-1i16), 0);
|
||||
assert_eq!(cttz_nonzero(-1i32 as u32), 0); assert_eq!(cttz_nonzero(-1i32), 0);
|
||||
assert_eq!(cttz_nonzero(-1i64 as u64), 0); assert_eq!(cttz_nonzero(-1i64), 0);
|
||||
|
||||
assert_eq!(cttz_nonzero(1u8), 0); assert_eq!(cttz_nonzero(1i8), 0);
|
||||
assert_eq!(cttz_nonzero(1u16), 0); assert_eq!(cttz_nonzero(1i16), 0);
|
||||
assert_eq!(cttz_nonzero(1u32), 0); assert_eq!(cttz_nonzero(1i32), 0);
|
||||
assert_eq!(cttz_nonzero(1u64), 0); assert_eq!(cttz_nonzero(1i64), 0);
|
||||
|
||||
assert_eq!(cttz_nonzero(10u8), 1); assert_eq!(cttz_nonzero(10i8), 1);
|
||||
assert_eq!(cttz_nonzero(10u16), 1); assert_eq!(cttz_nonzero(10i16), 1);
|
||||
assert_eq!(cttz_nonzero(10u32), 1); assert_eq!(cttz_nonzero(10i32), 1);
|
||||
assert_eq!(cttz_nonzero(10u64), 1); assert_eq!(cttz_nonzero(10i64), 1);
|
||||
|
||||
assert_eq!(cttz_nonzero(100u8), 2); assert_eq!(cttz_nonzero(100i8), 2);
|
||||
assert_eq!(cttz_nonzero(100u16), 2); assert_eq!(cttz_nonzero(100i16), 2);
|
||||
assert_eq!(cttz_nonzero(100u32), 2); assert_eq!(cttz_nonzero(100i32), 2);
|
||||
assert_eq!(cttz_nonzero(100u64), 2); assert_eq!(cttz_nonzero(100i64), 2);
|
||||
|
||||
assert_eq!(bswap(0x0Au8), 0x0A); // no-op
|
||||
assert_eq!(bswap(0x0Ai8), 0x0A); // no-op
|
||||
assert_eq!(bswap(0x0A0Bu16), 0x0B0A);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue