diff --git a/example/mini_core.rs b/example/mini_core.rs index ffc2cd8fb65..dd42257b194 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -371,6 +371,7 @@ pub mod intrinsics { pub fn copy(src: *const T, dst: *mut T, count: usize); pub fn transmute(e: T) -> U; pub fn uninit() -> T; + pub fn init() -> T; pub fn ctlz_nonzero(x: T) -> T; pub fn needs_drop() -> bool; pub fn bitreverse(x: T) -> T; diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index e69c509b763..fdd26f8791d 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -165,6 +165,29 @@ fn main() { struct MyDst(T); intrinsics::size_of_val(&MyDst([0u8; 4]) as &MyDst<[u8]>); + + struct Foo { + x: u8, + y: !, + } + + unsafe fn zeroed() -> T { + intrinsics::init::() + } + + unsafe fn uninitialized() -> T { + intrinsics::uninit::() + } + + #[allow(unreachable_code)] + { + if false { + zeroed::(); + zeroed::(); + zeroed::<(u8, u8)>(); + uninitialized::(); + } + } } let _ = box NoisyDrop { diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 821f7858c90..34b58c5b407 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -337,16 +337,36 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( let dst_layout = fx.layout_of(dst_ty); ret.write_cvalue(fx, CValue::ByRef(addr, dst_layout)) }; - init, () { - let layout = fx.layout_of(T); - let inited_place = CPlace::new_stack_slot(fx, T); - let addr = inited_place.to_addr(fx); - let zero_val = fx.bcx.ins().iconst(types::I8, 0); - let len_val = fx.bcx.ins().iconst(pointer_ty(fx.tcx), layout.size.bytes() as i64); - fx.bcx.call_memset(fx.module.target_config(), addr, zero_val, len_val); + init, () { + if ret.layout().abi == Abi::Uninhabited { + crate::trap::trap_panic(&mut fx.bcx); + return; + } - let inited_val = inited_place.to_cvalue(fx); - ret.write_cvalue(fx, inited_val); + match ret { + CPlace::NoPlace(_layout) => {} + CPlace::Var(var, layout) => { + let clif_ty = fx.clif_type(layout.ty).unwrap(); + let val = match clif_ty { + types::I8 | types::I16 | types::I32 | types::I64 => fx.bcx.ins().iconst(clif_ty, 0), + types::F32 => { + let zero = fx.bcx.ins().iconst(types::I32, 0); + fx.bcx.ins().bitcast(types::F32, zero) + } + types::F64 => { + let zero = fx.bcx.ins().iconst(types::I64, 0); + fx.bcx.ins().bitcast(types::F64, zero) + } + _ => panic!("clif_type returned {}", clif_ty), + }; + fx.bcx.def_var(mir_var(var), val); + } + _ => { + let addr = ret.to_addr(fx); + let layout = ret.layout(); + fx.bcx.emit_small_memset(fx.module.target_config(), addr, 0, layout.size.bytes(), 1); + } + } }; write_bytes, (c dst, v val, v count) { let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty; @@ -356,6 +376,11 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( fx.bcx.call_memset(fx.module.target_config(), dst_ptr, val, count); }; uninit, () { + if ret.layout().abi == Abi::Uninhabited { + crate::trap::trap_panic(&mut fx.bcx); + return; + } + let uninit_place = CPlace::new_stack_slot(fx, T); let uninit_val = uninit_place.to_cvalue(fx); ret.write_cvalue(fx, uninit_val);