]> git.lizzy.rs Git - rust.git/commitdiff
std: Ensure OOM is classified as `nounwind`
authorAlex Crichton <alex@alexcrichton.com>
Thu, 24 May 2018 19:03:05 +0000 (12:03 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 24 May 2018 19:03:05 +0000 (12:03 -0700)
OOM can't unwind today, and historically it's been optimized as if it can't
unwind. This accidentally regressed with recent changes to the OOM handler, so
this commit adds in a codegen test to assert that everything gets optimized away
after the OOM function is approrpiately classified as nounwind

Closes #50925

src/liballoc/alloc.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_codegen_llvm/callee.rs
src/test/codegen/vec-iter-collect-len.rs [new file with mode: 0644]

index 79607b06f9468465c6a376bc2c9a344be7b98539..4ae8fc649ddbf201b0b63f235adee73a9459300e 100644 (file)
@@ -133,6 +133,7 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
     }
 }
 
+#[rustc_allocator_nounwind]
 pub fn oom() -> ! {
     extern {
         #[lang = "oom"]
index b64e102ba788252a20e0e8f89ba93e5d01d1b33b..d6806e7afd306ef2ede905df3a5d6725f803b71f 100644 (file)
@@ -20,7 +20,9 @@
 use rustc::ty::maps::Providers;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_target::spec::PanicStrategy;
 
+use attributes;
 use llvm::{self, Attribute, ValueRef};
 use llvm::AttributePlace::Function;
 use llvm_util;
@@ -135,11 +137,28 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
         Attribute::NoAlias.apply_llfn(
             llvm::AttributePlace::ReturnValue, llfn);
     }
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
-        unwind(llfn, true);
-    }
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
-        unwind(llfn, false);
+
+    let can_unwind = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
+        Some(true)
+    } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
+        Some(false)
+
+    // Perhaps questionable, but we assume that anything defined
+    // *in Rust code* may unwind. Foreign items like `extern "C" {
+    // fn foo(); }` are assumed not to unwind **unless** they have
+    // a `#[unwind]` attribute.
+    } else if !cx.tcx.is_foreign_item(id) {
+        Some(true)
+    } else {
+        None
+    };
+
+    match can_unwind {
+        Some(false) => attributes::unwind(llfn, false),
+        Some(true) if cx.tcx.sess.panic_strategy() == PanicStrategy::Unwind => {
+            attributes::unwind(llfn, true);
+        }
+        Some(true) | None => {}
     }
 
     let features = llvm_target_features(cx.tcx.sess)
index a3dbc450ce72f4de6e6038bd062844dfb3da370d..2c01bd42cc77a4dee0b5d6dd7cdeb4151b1db5b6 100644 (file)
@@ -26,7 +26,6 @@
 use rustc::ty::{self, TypeFoldable};
 use rustc::ty::layout::LayoutOf;
 use rustc::ty::subst::Substs;
-use rustc_target::spec::PanicStrategy;
 
 /// Codegens a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
@@ -102,16 +101,6 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         let instance_def_id = instance.def_id();
 
-        // Perhaps questionable, but we assume that anything defined
-        // *in Rust code* may unwind. Foreign items like `extern "C" {
-        // fn foo(); }` are assumed not to unwind **unless** they have
-        // a `#[unwind]` attribute.
-        if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
-            if !tcx.is_foreign_item(instance_def_id) {
-                attributes::unwind(llfn, true);
-            }
-        }
-
         // Apply an appropriate linkage/visibility value to our item that we
         // just declared.
         //
diff --git a/src/test/codegen/vec-iter-collect-len.rs b/src/test/codegen/vec-iter-collect-len.rs
new file mode 100644 (file)
index 0000000..efb384d
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-system-llvm
+// compile-flags: -O
+#![crate_type="lib"]
+
+#[no_mangle]
+pub fn get_len() -> usize {
+    // CHECK-LABEL: @get_len
+    // CHECK-NOT: call
+    // CHECK-NOT: invoke
+    [1, 2, 3].iter().collect::<Vec<_>>().len()
+}