From 7862e2ea1cd1270744d1d22f6fdff35b7c3c8dc5 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 26 Jul 2018 10:48:50 +0200 Subject: [PATCH] Implement some intrinsics --- example.rs | 8 ++++++++ mini_core.rs | 7 +++++++ src/abi.rs | 42 +++++++++++++++++++++++++++++++++++++++++- src/base.rs | 34 ++++++++++++++++++++++++++++++++-- 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/example.rs b/example.rs index 0f37d7f4c363..1c67b6810ce7 100644 --- a/example.rs +++ b/example.rs @@ -115,3 +115,11 @@ fn call_closure() { })(0u8, 42u8, 0u8) } + +fn eq_char(a: char, b: char) -> bool { + a == b +} + +unsafe fn transmute(c: char) -> u32 { + intrinsics::transmute(c) +} diff --git a/mini_core.rs b/mini_core.rs index d4844cc0be2d..2496eb1bf4a3 100644 --- a/mini_core.rs +++ b/mini_core.rs @@ -17,6 +17,7 @@ unsafe impl Copy for i8 {} unsafe impl Copy for i16 {} unsafe impl Copy for i32 {} unsafe impl Copy for isize {} +unsafe impl Copy for char {} unsafe impl<'a, T: ?Sized> Copy for &'a T {} unsafe impl Copy for *const T {} @@ -50,6 +51,11 @@ impl PartialEq for u8 { fn ne(&self, other: &u8) -> bool { (*self) != (*other) } } +impl PartialEq for char { + fn eq(&self, other: &char) -> bool { (*self) == (*other) } + fn ne(&self, other: &char) -> 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 } @@ -86,5 +92,6 @@ pub mod intrinsics { extern "rust-intrinsic" { pub fn size_of() -> usize; pub fn copy(src: *const T, dst: *mut T, count: usize); + pub fn transmute(e: T) -> U; } } diff --git a/src/abi.rs b/src/abi.rs index a36ac1611a19..6e57d7ac5f7e 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -203,6 +203,7 @@ pub fn codegen_call<'a, 'tcx: 'a>( let intrinsic = &intrinsic[..]; let usize_layout = fx.layout_of(fx.tcx.types.usize); + let ret = return_place.unwrap(); match intrinsic { "copy" => { /*let elem_ty = substs.type_at(0); @@ -213,9 +214,48 @@ pub fn codegen_call<'a, 'tcx: 'a>( unimplemented!("copy"); } "size_of" => { + assert_eq!(args.len(), 0); let size_of = fx.layout_of(substs.type_at(0)).size.bytes(); let size_of = CValue::const_val(fx, usize_layout.ty, size_of as i64); - return_place.unwrap().write_cvalue(fx, size_of); + ret.write_cvalue(fx, size_of); + } + _ if intrinsic.starts_with("unchecked_") => { + assert_eq!(args.len(), 2); + let lhs = args[0].load_value(fx); + let rhs = args[1].load_value(fx); + let bin_op = match intrinsic { + "unchecked_div" => BinOp::Div, + "unchecked_rem" => BinOp::Rem, + "unchecked_shl" => BinOp::Shl, + "unchecked_shr" => BinOp::Shr, + _ => unimplemented!("intrinsic {}", intrinsic), + }; + let res = match ret.layout().ty.sty { + TypeVariants::TyUint(_) => { + ::base::trans_int_binop(fx, bin_op, lhs, rhs, args[0].layout().ty, false, false) + } + TypeVariants::TyInt(_) => { + ::base::trans_int_binop(fx, bin_op, lhs, rhs, args[0].layout().ty, true, false) + } + _ => panic!(), + }; + ret.write_cvalue(fx, res); + } + "offset" => { + assert_eq!(args.len(), 2); + let base = args[0].load_value(fx); + let offset = args[1].load_value(fx); + let res = fx.bcx.ins().iadd(base, offset); + ret.write_cvalue(fx, CValue::ByVal(res, args[0].layout())); + } + "transmute" => { + assert_eq!(args.len(), 1); + let src_ty = substs.type_at(0); + let dst_ty = substs.type_at(1); + assert_eq!(args[0].layout().ty, src_ty); + let addr = args[0].force_stack(fx); + let dst_layout = fx.layout_of(dst_ty); + ret.write_cvalue(fx, CValue::ByRef(addr, dst_layout)) } _ => fx.tcx.sess.fatal(&format!("unsupported intrinsic {}", intrinsic)), } diff --git a/src/base.rs b/src/base.rs index 2e6d0bcd1549..d5c67480ef23 100644 --- a/src/base.rs +++ b/src/base.rs @@ -248,6 +248,9 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: & TypeVariants::TyInt(_) => { trans_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, true, false) } + TypeVariants::TyChar => { + trans_char_binop(fx, *bin_op, lhs, rhs, lval.layout().ty) + } TypeVariants::TyRawPtr(..) => { trans_ptr_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, false) } @@ -423,9 +426,9 @@ macro_rules! binop_match { } } -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> { +pub 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"; + fx, bin_op, signed, lhs, rhs, "int/uint"; Add (_) iadd; Sub (_) isub; Mul (_) imul; @@ -458,6 +461,33 @@ fn trans_int_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, l CValue::ByVal(res, fx.layout_of(ty)) } +pub fn trans_char_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: Value, rhs: Value, ty: Ty<'tcx>) -> CValue<'tcx> { + let res = binop_match! { + fx, bin_op, false, lhs, rhs, "char"; + 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 (_) bug; + }; + + 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";