about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2019-02-24 16:46:11 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2019-04-10 17:25:57 +0200
commit970d164089f0cc2dc90dafeb3eedb681d505dc81 (patch)
treea340199be12c8e664db05b76df4952529289176b
parent16f41266567b16924cd0dff66122db041cc613a5 (diff)
downloadrust-970d164089f0cc2dc90dafeb3eedb681d505dc81.tar.gz
rust-970d164089f0cc2dc90dafeb3eedb681d505dc81.zip
Fix and optimize init intrinsic
-rw-r--r--example/mini_core.rs1
-rw-r--r--example/mini_core_hello_world.rs23
-rw-r--r--src/intrinsics.rs43
3 files changed, 58 insertions, 9 deletions
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<T>(src: *const T, dst: *mut T, count: usize);
         pub fn transmute<T, U>(e: T) -> U;
         pub fn uninit<T>() -> T;
+        pub fn init<T>() -> T;
         pub fn ctlz_nonzero<T>(x: T) -> T;
         pub fn needs_drop<T>() -> bool;
         pub fn bitreverse<T>(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: ?Sized>(T);
 
         intrinsics::size_of_val(&MyDst([0u8; 4]) as &MyDst<[u8]>);
+
+        struct Foo {
+            x: u8,
+            y: !,
+        }
+
+        unsafe fn zeroed<T>() -> T {
+            intrinsics::init::<T>()
+        }
+
+        unsafe fn uninitialized<T>() -> T {
+            intrinsics::uninit::<T>()
+        }
+
+        #[allow(unreachable_code)]
+        {
+            if false {
+                zeroed::<!>();
+                zeroed::<Foo>();
+                zeroed::<(u8, u8)>();
+                uninitialized::<Foo>();
+            }
+        }
     }
 
     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, <T> () {
-            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, <T> () {
+            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);