From 0fb7c4d1b9a0b432db0292b2c42e88c2fa21cb02 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 14 Sep 2018 19:49:33 +0200 Subject: [PATCH] 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 --- examples/mini_core.rs | 16 ++++++++++++++++ examples/mini_core_hello_world.rs | 16 +++++++++++++++- src/abi.rs | 17 ++++++++++++++++- src/base.rs | 26 +++++++++++++++++++------- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/examples/mini_core.rs b/examples/mini_core.rs index ea0a8c08ef53..6e2e9dd37f63 100644 --- a/examples/mini_core.rs +++ b/examples/mini_core.rs @@ -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 { type Output; @@ -211,6 +226,7 @@ pub mod intrinsics { pub fn transmute(e: T) -> U; pub fn uninit() -> T; pub fn ctlz_nonzero(x: T) -> T; + pub fn needs_drop() -> bool; } } diff --git a/examples/mini_core_hello_world.rs b/examples/mini_core_hello_world.rs index 661fa3cd7f15..5948415c9291 100644 --- a/examples/mini_core_hello_world.rs +++ b/examples/mini_core_hello_world.rs @@ -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) { - 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::() { + panic(&("", "", 0, 0)); + } + + if !intrinsics::needs_drop::() { + panic(&("", "", 0, 0)); + } } let _ = NoisyDrop { diff --git a/src/abi.rs b/src/abi.rs index c1eefa430e01..8ae0136d00c5 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -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), } diff --git a/src/base.rs b/src/base.rs index e2422fe11578..8f2ab83ceedd 100644 --- a/src/base.rs +++ b/src/base.rs @@ -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));