about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-10-01 14:58:24 +0000
committerbors <bors@rust-lang.org>2018-10-01 14:58:24 +0000
commitde3d640f59c4fa4a09faf2a8d6b0a812aaa6d6cb (patch)
treea972fbca76a07b42c194d259fb11105fe8d78726 /src/librustc_codegen_llvm
parent6188c58a55a27efac25f6e50a8e5f18c2650b60f (diff)
parentdd65d732ed702302ac0943179cb2feec835975ee (diff)
downloadrust-de3d640f59c4fa4a09faf2a8d6b0a812aaa6d6cb.tar.gz
rust-de3d640f59c4fa4a09faf2a8d6b0a812aaa6d6cb.zip
Auto merge of #54667 - RalfJung:maybe-uninit, r=pnkfelix
Panic when using mem::uninitialized or mem::zeroed on an uninhabited type

All code by @japaric. This re-submits one half of https://github.com/rust-lang/rust/pull/53508. This is likely not the one that introduced the perf regression, but just to be sure I'll do a perf run anyway.
Diffstat (limited to 'src/librustc_codegen_llvm')
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs2
-rw-r--r--src/librustc_codegen_llvm/declare.rs4
-rw-r--r--src/librustc_codegen_llvm/mir/block.rs48
-rw-r--r--src/librustc_codegen_llvm/mir/place.rs4
-rw-r--r--src/librustc_codegen_llvm/mir/rvalue.rs2
5 files changed, 54 insertions, 6 deletions
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 99919a940b4..7b0c413e857 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -279,7 +279,7 @@ pub fn create_function_debug_context(
         }
         None => {}
     };
-    if cx.layout_of(sig.output()).abi == ty::layout::Abi::Uninhabited {
+    if cx.layout_of(sig.output()).abi.is_uninhabited() {
         flags = flags | DIFlags::FlagNoReturn;
     }
 
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index 5e743ac51bc..7141c9ece89 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -23,7 +23,7 @@
 use llvm;
 use llvm::AttributePlace::Function;
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, LayoutOf};
+use rustc::ty::layout::LayoutOf;
 use rustc::session::config::Sanitizer;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_target::spec::PanicStrategy;
@@ -137,7 +137,7 @@ pub fn declare_fn(
     let fty = FnType::new(cx, sig, &[]);
     let llfn = declare_raw_fn(cx, name, fty.llvm_cconv(), fty.llvm_type(cx));
 
-    if cx.layout_of(sig.output()).abi == layout::Abi::Uninhabited {
+    if cx.layout_of(sig.output()).abi.is_uninhabited() {
         llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
     }
 
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs
index a534b4e478f..709fceb4925 100644
--- a/src/librustc_codegen_llvm/mir/block.rs
+++ b/src/librustc_codegen_llvm/mir/block.rs
@@ -482,6 +482,54 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     _ => FnType::new(bx.cx, sig, &extra_args)
                 };
 
+                // emit a panic instead of instantiating an uninhabited type
+                if (intrinsic == Some("init") || intrinsic == Some("uninit")) &&
+                    fn_ty.ret.layout.abi.is_uninhabited()
+                {
+                    let loc = bx.sess().source_map().lookup_char_pos(span.lo());
+                    let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
+                    let filename = C_str_slice(bx.cx, filename);
+                    let line = C_u32(bx.cx, loc.line as u32);
+                    let col = C_u32(bx.cx, loc.col.to_usize() as u32 + 1);
+                    let align = tcx.data_layout.aggregate_align
+                        .max(tcx.data_layout.i32_align)
+                        .max(tcx.data_layout.pointer_align);
+
+                    let str = format!(
+                        "Attempted to instantiate uninhabited type {} using mem::{}",
+                        sig.output(),
+                        if intrinsic == Some("init") { "zeroed" } else { "uninitialized" }
+                    );
+                    let msg_str = Symbol::intern(&str).as_str();
+                    let msg_str = C_str_slice(bx.cx, msg_str);
+                    let msg_file_line_col = C_struct(bx.cx,
+                                                    &[msg_str, filename, line, col],
+                                                    false);
+                    let msg_file_line_col = consts::addr_of(bx.cx,
+                                                            msg_file_line_col,
+                                                            align,
+                                                            Some("panic_loc"));
+
+                    // Obtain the panic entry point.
+                    let def_id =
+                        common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
+                    let instance = ty::Instance::mono(bx.tcx(), def_id);
+                    let fn_ty = FnType::of_instance(bx.cx, &instance);
+                    let llfn = callee::get_fn(bx.cx, instance);
+
+                    // Codegen the actual panic invoke/call.
+                    do_call(
+                        self,
+                        bx,
+                        fn_ty,
+                        llfn,
+                        &[msg_file_line_col],
+                        destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
+                        cleanup,
+                    );
+                    return;
+                }
+
                 // The arguments we'll be passing. Plus one to account for outptr, if used.
                 let arg_count = fn_ty.args.len() + fn_ty.ret.is_indirect() as usize;
                 let mut llargs = Vec::with_capacity(arg_count);
diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs
index c781b456af6..e7b6f5908a4 100644
--- a/src/librustc_codegen_llvm/mir/place.rs
+++ b/src/librustc_codegen_llvm/mir/place.rs
@@ -275,7 +275,7 @@ impl PlaceRef<'ll, 'tcx> {
     /// Obtain the actual discriminant of a value.
     pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value {
         let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
-        if self.layout.abi == layout::Abi::Uninhabited {
+        if self.layout.abi.is_uninhabited() {
             return C_undef(cast_to);
         }
         match self.layout.variants {
@@ -338,7 +338,7 @@ impl PlaceRef<'ll, 'tcx> {
     /// Set the discriminant for a new value of the given case of the given
     /// representation.
     pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) {
-        if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
+        if self.layout.for_variant(bx.cx, variant_index).abi.is_uninhabited() {
             return;
         }
         match self.layout.variants {
diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs
index c3ec347f608..fa22bdff94d 100644
--- a/src/librustc_codegen_llvm/mir/rvalue.rs
+++ b/src/librustc_codegen_llvm/mir/rvalue.rs
@@ -290,7 +290,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     mir::CastKind::Misc => {
                         assert!(cast.is_llvm_immediate());
                         let ll_t_out = cast.immediate_llvm_type(bx.cx);
-                        if operand.layout.abi == layout::Abi::Uninhabited {
+                        if operand.layout.abi.is_uninhabited() {
                             return (bx, OperandRef {
                                 val: OperandValue::Immediate(C_undef(ll_t_out)),
                                 layout: cast,