Implement some intrinsics and fix a codegen error

* intrinsic size_of_val for sized types
* intrinsic needs_drop
* incorrect codegen for UnOp::Not for bools
This commit is contained in:
bjorn3 2018-09-14 19:49:33 +02:00
parent 87c17aba92
commit 0fb7c4d1b9
4 changed files with 66 additions and 9 deletions

View file

@ -50,6 +50,21 @@ unsafe impl Sync for [u8; 16] {}
#[lang = "freeze"]
trait Freeze {}
#[lang = "not"]
pub trait Not {
type Output;
fn not(self) -> Self::Output;
}
impl Not for bool {
type Output = bool;
fn not(self) -> bool {
!self
}
}
#[lang = "mul"]
pub trait Mul<RHS = Self> {
type Output;
@ -211,6 +226,7 @@ pub mod intrinsics {
pub fn transmute<T, U>(e: T) -> U;
pub fn uninit<T>() -> T;
pub fn ctlz_nonzero<T>(x: T) -> T;
pub fn needs_drop<T>() -> bool;
}
}

View file

@ -20,7 +20,9 @@ unsafe extern "C" fn my_puts(s: *const u8) {
// TODO remove when jit supports linking rlibs
#[cfg(jit)]
fn panic<T>(_: T) {
loop {}
unsafe {
intrinsics::abort();
}
}
#[lang = "termination"]
@ -113,6 +115,18 @@ fn main() {
if intrinsics::size_of_val(a) as u8 != 16 {
panic(&("", "", 0, 0));
}
if intrinsics::size_of_val(&0u32) as u8 != 4 {
panic(&("", "", 0, 0));
}
if intrinsics::needs_drop::<u8>() {
panic(&("", "", 0, 0));
}
if !intrinsics::needs_drop::<NoisyDrop>() {
panic(&("", "", 0, 0));
}
}
let _ = NoisyDrop {

View file

@ -660,7 +660,11 @@ fn codegen_intrinsic_call<'a, 'tcx: 'a>(
}
"size_of_val" => {
assert_eq!(args.len(), 1);
let size = match &substs.type_at(0).sty {
let layout = fx.layout_of(substs.type_at(0));
let size = match &layout.ty.sty {
_ if !layout.is_unsized() => {
fx.bcx.ins().iconst(fx.module.pointer_type(), layout.size.bytes() as i64)
}
ty::Slice(elem) => {
let len = args[0].load_value_pair(fx).1;
let elem_size = fx.layout_of(elem).size.bytes();
@ -821,6 +825,17 @@ fn codegen_intrinsic_call<'a, 'tcx: 'a>(
let res = CValue::ByVal(fx.bcx.ins().popcnt(arg), args[0].layout());
ret.write_cvalue(fx, res);
}
"needs_drop" => {
assert_eq!(args.len(), 0);
let ty = substs.type_at(0);
let needs_drop = if ty.needs_drop(fx.tcx, ParamEnv::reveal_all()) {
1
} else {
0
};
let needs_drop = CValue::const_val(fx, fx.tcx.types.bool, needs_drop);
ret.write_cvalue(fx, needs_drop);
}
_ => unimpl!("unsupported intrinsic {}", intrinsic),
}

View file

@ -432,19 +432,31 @@ fn trans_stmt<'a, 'tcx: 'a>(
lval.write_cvalue(fx, res);
}
Rvalue::UnaryOp(un_op, operand) => {
let ty = fx.monomorphize(&operand.ty(&fx.mir.local_decls, fx.tcx));
let layout = fx.layout_of(ty);
let val = trans_operand(fx, operand).load_value(fx);
let operand = trans_operand(fx, operand);
let layout = operand.layout();
let val = operand.load_value(fx);
let res = match un_op {
UnOp::Not => fx.bcx.ins().bnot(val),
UnOp::Neg => match ty.sty {
UnOp::Not => {
match layout.ty.sty {
ty::Bool => {
let val = fx.bcx.ins().uextend(types::I32, val); // WORKAROUND for CraneStation/cranelift#466
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
fx.bcx.ins().bint(types::I8, res)
}
ty::Uint(_) | ty::Int(_) => {
fx.bcx.ins().bnot(val)
}
_ => unimplemented!("un op Not for {:?}", layout.ty),
}
},
UnOp::Neg => match layout.ty.sty {
ty::Int(_) => {
let clif_ty = fx.cton_type(ty).unwrap();
let clif_ty = fx.cton_type(layout.ty).unwrap();
let zero = fx.bcx.ins().iconst(clif_ty, 0);
fx.bcx.ins().isub(zero, val)
}
ty::Float(_) => fx.bcx.ins().fneg(val),
_ => unimplemented!("un op Neg for {:?}", ty),
_ => unimplemented!("un op Neg for {:?}", layout.ty),
},
};
lval.write_cvalue(fx, CValue::ByVal(res, layout));