Implement some intrinsics

This commit is contained in:
bjorn3 2018-07-26 10:48:50 +02:00
parent 874208bcd5
commit 7862e2ea1c
4 changed files with 88 additions and 3 deletions

View file

@ -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)
}

View file

@ -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<T: ?Sized> 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<T: ?Sized> 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<T>() -> usize;
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
pub fn transmute<T, U>(e: T) -> U;
}
}

View file

@ -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)),
}

View file

@ -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";