Implement some intrinsics
This commit is contained in:
parent
874208bcd5
commit
7862e2ea1c
4 changed files with 88 additions and 3 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
42
src/abi.rs
42
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)),
|
||||
}
|
||||
|
|
|
|||
34
src/base.rs
34
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";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue