From f52727b8e65ab15a8e12a3927ff3855e2922eda7 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 18 Jul 2018 15:17:22 +0200 Subject: [PATCH] Implement some binops for TyRawPtr --- example.rs | 26 +++++++++++- src/base.rs | 115 +++++++++++++++++++++++++++++++++++++++------------- src/lib.rs | 2 +- 3 files changed, 112 insertions(+), 31 deletions(-) diff --git a/example.rs b/example.rs index d7ef0224450..9f9d518f390 100644 --- a/example.rs +++ b/example.rs @@ -6,7 +6,11 @@ trait Sized {} #[lang="copy"] -trait Copy {} +unsafe trait Copy {} + +unsafe impl Copy for u8 {} +unsafe impl<'a, T: ?Sized> Copy for &'a T {} +unsafe impl Copy for *const T {} #[lang="freeze"] trait Freeze {} @@ -27,6 +31,22 @@ impl Mul for u8 { } } +#[lang = "eq"] +pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + fn ne(&self, other: &Rhs) -> bool; +} + +impl PartialEq for u8 { + fn eq(&self, other: &u8) -> bool { (*self) == (*other) } + fn ne(&self, other: &u8) -> bool { (*self) != (*other) } +} + +impl PartialEq for *const T { + fn eq(&self, other: &*const T) -> bool { *self == *other } + fn ne(&self, other: &*const T) -> bool { *self != *other } +} + #[lang="panic"] fn panic(_expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { loop {} @@ -89,3 +109,7 @@ fn promoted_val() -> &'static u8 { fn cast_ref_to_raw_ptr(abc: &u8) -> *const u8 { abc as *const u8 } + +fn cmp_raw_ptr(a: *const u8, b: *const u8) -> bool { + a == b +} diff --git a/src/base.rs b/src/base.rs index c17e9d02409..37f350b6500 100644 --- a/src/base.rs +++ b/src/base.rs @@ -327,6 +327,9 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, stmt: &Statement<'tcx TypeVariants::TyInt(_) => { trans_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, true, false) } + TypeVariants::TyRawPtr(..) => { + trans_ptr_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, false) + } _ => unimplemented!("bin op {:?} for {:?}", bin_op, ty), }; lval.write_cvalue(fx, res); @@ -467,36 +470,90 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, stmt: &Statement<'tcx Ok(()) } -fn trans_int_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: Value, rhs: Value, ty: Ty<'tcx>, signed: bool, _checked: bool) -> CValue<'tcx> { - let res = match (bin_op, signed) { - (BinOp::Add, _) => fx.bcx.ins().iadd(lhs, rhs), - (BinOp::Sub, _) => fx.bcx.ins().isub(lhs, rhs), - (BinOp::Mul, _) => fx.bcx.ins().imul(lhs, rhs), - (BinOp::Div, false) => fx.bcx.ins().udiv(lhs, rhs), - (BinOp::Div, true) => fx.bcx.ins().sdiv(lhs, rhs), - (BinOp::Rem, false) => fx.bcx.ins().urem(lhs, rhs), - (BinOp::Rem, true) => fx.bcx.ins().srem(lhs, rhs), - (BinOp::BitXor, _) => fx.bcx.ins().bxor(lhs, rhs), - (BinOp::BitAnd, _) => fx.bcx.ins().band(lhs, rhs), - (BinOp::BitOr, _) => fx.bcx.ins().bor(lhs, rhs), - (BinOp::Shl, _) => fx.bcx.ins().ishl(lhs, rhs), - (BinOp::Shr, false) => fx.bcx.ins().ushr(lhs, rhs), - (BinOp::Shr, true) => fx.bcx.ins().sshr(lhs, rhs), - - // TODO: cast b1 to u8 - (BinOp::Eq, _) => fx.bcx.ins().icmp(IntCC::Equal , lhs, rhs), - (BinOp::Lt, false) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan , lhs, rhs), - (BinOp::Lt, true) => fx.bcx.ins().icmp(IntCC::SignedLessThan , lhs, rhs), - (BinOp::Le, false) => fx.bcx.ins().icmp(IntCC::UnsignedLessThanOrEqual , lhs, rhs), - (BinOp::Le, true) => fx.bcx.ins().icmp(IntCC::SignedLessThanOrEqual , lhs, rhs), - (BinOp::Ne, _) => fx.bcx.ins().icmp(IntCC::NotEqual , lhs, rhs), - (BinOp::Ge, false) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThanOrEqual , lhs, rhs), - (BinOp::Ge, true) => fx.bcx.ins().icmp(IntCC::SignedGreaterThanOrEqual , lhs, rhs), - (BinOp::Gt, false) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan , lhs, rhs), - (BinOp::Gt, true) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan , lhs, rhs), - - (BinOp::Offset, _) => bug!("bin op Offset on non ptr lhs: {:?} rhs: {:?}", lhs, rhs), +macro_rules! binop_match { + (@single $fx:expr, $bug_fmt:expr, $var:expr, $lhs:expr, $rhs:expr, bug) => { + bug!("bin op {} on {} lhs: {:?} rhs: {:?}", stringify!($var), $bug_fmt, $lhs, $rhs) }; + (@single $fx:expr, $bug_fmt:expr, $var:expr, $lhs:expr, $rhs:expr, icmp($cc:ident)) => {{ + let b = $fx.bcx.ins().icmp(IntCC::$cc, $lhs, $rhs); + $fx.bcx.ins().bint(types::I8, b) + }}; + (@single $fx:expr, $bug_fmt:expr, $var:expr, $lhs:expr, $rhs:expr, $name:ident) => { + $fx.bcx.ins().$name($lhs, $rhs) + }; + ( + $fx:expr, $bin_op:expr, $signed:expr, $lhs:expr, $rhs:expr, $bug_fmt:expr; + $( + $var:ident ($sign:pat) $name:tt $( ( $next:tt ) )? ; + )* + ) => { + match ($bin_op, $signed) { + $( + (BinOp::$var, $sign) => binop_match!(@single $fx, $bug_fmt, $var, $lhs, $rhs, $name $( ( $next ) )?), + )* + } + } +} + +fn trans_int_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: Value, rhs: Value, ty: Ty<'tcx>, signed: bool, _checked: bool) -> CValue<'tcx> { + let res = binop_match! { + fx, bin_op, signed, lhs, rhs, "non ptr"; + Add (_) iadd; + Sub (_) isub; + Mul (_) imul; + Div (false) udiv; + Div (true) sdiv; + Rem (false) urem; + Rem (true) srem; + BitXor (_) bxor; + BitAnd (_) band; + BitOr (_) bor; + Shl (_) ishl; + Shr (false) ushr; + Shr (true) sshr; + + Eq (_) icmp(Equal); + Lt (false) icmp(UnsignedLessThan); + Lt (true) icmp(SignedLessThan); + Le (false) icmp(UnsignedLessThanOrEqual); + Le (true) icmp(SignedLessThanOrEqual); + Ne (_) icmp(NotEqual); + Ge (false) icmp(UnsignedGreaterThanOrEqual); + Ge (true) icmp(SignedGreaterThanOrEqual); + Gt (false) icmp(UnsignedGreaterThan); + Gt (true) icmp(SignedGreaterThan); + + Offset (_) bug; + }; + + // TODO: return correct value for checked binops + CValue::ByVal(res, fx.layout_of(ty)) +} + +fn trans_ptr_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: Value, rhs: Value, ty: Ty<'tcx>, _checked: bool) -> CValue<'tcx> { + let res = binop_match! { + fx, bin_op, false, lhs, rhs, "ptr"; + Add (_) bug; + Sub (_) bug; + Mul (_) bug; + Div (_) bug; + Rem (_) bug; + BitXor (_) bug; + BitAnd (_) bug; + BitOr (_) bug; + Shl (_) bug; + Shr (_) bug; + + Eq (_) icmp(Equal); + Lt (_) icmp(UnsignedLessThan); + Le (_) icmp(UnsignedLessThanOrEqual); + Ne (_) icmp(NotEqual); + Ge (_) icmp(UnsignedGreaterThanOrEqual); + Gt (_) icmp(UnsignedGreaterThan); + + Offset (_) iadd; + }; + // TODO: return correct value for checked binops CValue::ByVal(res, fx.layout_of(ty)) } diff --git a/src/lib.rs b/src/lib.rs index e02c431b21b..68d807d2b98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(rustc_private)] +#![feature(rustc_private, macro_at_most_once_rep)] #![allow(intra_doc_link_resolution_failure)] extern crate syntax;