about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-09-14 11:05:34 +0000
committerbors <bors@rust-lang.org>2015-09-14 11:05:34 +0000
commit2d4ae52cbdca96d4dd6d5a009e4a5ef87a279df0 (patch)
tree782f1b598d547a1d7b62afe14809b84aa82d11f7
parent664a45976fb5dd433766f73a221435883151d0ee (diff)
parent3ef75d5774cb9a7cf839a69341c620b98fa9c7df (diff)
downloadrust-2d4ae52cbdca96d4dd6d5a009e4a5ef87a279df0.tar.gz
rust-2d4ae52cbdca96d4dd6d5a009e4a5ef87a279df0.zip
Auto merge of #28358 - dotdash:nounwind, r=alexcrichton
This allows to skip the codegen for all the unneeded landing pads, reducing code size across the board by about 2-5%, depending on the crate. Compile times seem to be pretty unaffected though :-/
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/panicking.rs1
-rw-r--r--src/librustc_trans/trans/attributes.rs3
-rw-r--r--src/librustc_trans/trans/base.rs9
-rw-r--r--src/librustc_trans/trans/foreign.rs8
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/sys/common/libunwind.rs2
-rw-r--r--src/libstd/sys/common/unwind/mod.rs1
-rw-r--r--src/libstd/sys/common/unwind/seh.rs1
-rw-r--r--src/libstd/sys/common/unwind/seh64_gnu.rs2
-rw-r--r--src/libsyntax/feature_gate.rs4
-rw-r--r--src/test/codegen/extern-functions.rs23
12 files changed, 45 insertions, 11 deletions
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 78a467e3657..94408072932 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -79,6 +79,7 @@
 #![feature(optin_builtin_traits)]
 #![feature(reflect)]
 #![feature(rustc_attrs)]
+#![feature(unwind_attributes)]
 #![cfg_attr(stage0, feature(simd))]
 #![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))]
 #![feature(staged_api)]
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index b443ae0636f..93ddfa72f63 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -62,6 +62,7 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
     #[allow(improper_ctypes)]
     extern {
         #[lang = "panic_fmt"]
+        #[unwind]
         fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32) -> !;
     }
     let (file, line) = *file_line;
diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs
index a1f4ed5c20d..c77cb491448 100644
--- a/src/librustc_trans/trans/attributes.rs
+++ b/src/librustc_trans/trans/attributes.rs
@@ -59,7 +59,6 @@ pub fn emit_uwtable(val: ValueRef, emit: bool) {
 
 /// Tell LLVM whether the function can or cannot unwind.
 #[inline]
-#[allow(dead_code)] // possibly useful function
 pub fn unwind(val: ValueRef, can_unwind: bool) {
     if can_unwind {
         unsafe {
@@ -118,6 +117,8 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[hir::Attribute], llfn: ValueRe
             }
         } else if attr.check_name("allocator") {
             llvm::Attribute::NoAlias.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
+        } else if attr.check_name("unwind") {
+            unwind(llfn, true);
         }
     }
 }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index f8b60ebdea5..1359252e035 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -677,11 +677,8 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     ccx.sess().bug("unexpected intrinsic in trans_external_path")
                 }
                 _ => {
-                    let llfn = foreign::register_foreign_item_fn(ccx, fn_ty.abi,
-                                                                 t, &name);
                     let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
-                    attributes::from_fn_attrs(ccx, &attrs, llfn);
-                    llfn
+                    foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, &name, &attrs)
                 }
             }
         }
@@ -2418,9 +2415,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     let abi = ccx.tcx().map.get_foreign_abi(id);
                     let ty = ccx.tcx().node_id_to_type(ni.id);
                     let name = foreign::link_name(&*ni);
-                    let llfn = foreign::register_foreign_item_fn(ccx, abi, ty, &name);
-                    attributes::from_fn_attrs(ccx, &ni.attrs, llfn);
-                    llfn
+                    foreign::register_foreign_item_fn(ccx, abi, ty, &name, &ni.attrs)
                 }
                 hir::ForeignItemStatic(..) => {
                     foreign::register_static(ccx, &*ni)
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 9781fd037d7..cbb092aa4eb 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -187,7 +187,8 @@ pub fn get_extern_fn(ccx: &CrateContext,
 /// Registers a foreign function found in a library. Just adds a LLVM global.
 pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           abi: Abi, fty: Ty<'tcx>,
-                                          name: &str) -> ValueRef {
+                                          name: &str,
+                                          attrs: &[hir::Attribute])-> ValueRef {
     debug!("register_foreign_item_fn(abi={:?}, \
             ty={:?}, \
             name={})",
@@ -210,7 +211,9 @@ pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
 
     let llfn = get_extern_fn(ccx, &mut *ccx.externs().borrow_mut(), name, cc, llfn_ty, fty);
+    attributes::unwind(llfn, false);
     add_argument_attributes(&tys, llfn);
+    attributes::from_fn_attrs(ccx, attrs, llfn);
     llfn
 }
 
@@ -489,8 +492,7 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &hir::ForeignMod) {
                                                      "foreign fn's sty isn't a bare_fn_ty?")
                     }
 
-                    let llfn = register_foreign_item_fn(ccx, abi, ty, &lname);
-                    attributes::from_fn_attrs(ccx, &foreign_item.attrs, llfn);
+                    register_foreign_item_fn(ccx, abi, ty, &lname, &foreign_item.attrs);
                     // Unlike for other items, we shouldn't call
                     // `base::update_linkage` here.  Foreign items have
                     // special linkage requirements, which are handled
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 868fef06aa4..774d13966bd 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -242,6 +242,7 @@
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(decode_utf16)]
+#![feature(unwind_attributes)]
 #![feature(vec_push_all)]
 #![feature(vec_resize)]
 #![feature(wrapping)]
diff --git a/src/libstd/sys/common/libunwind.rs b/src/libstd/sys/common/libunwind.rs
index fde612014e9..c6bffb0f733 100644
--- a/src/libstd/sys/common/libunwind.rs
+++ b/src/libstd/sys/common/libunwind.rs
@@ -124,10 +124,12 @@ extern "C" {
     // iOS on armv7 uses SjLj exceptions and requires to link
     // against corresponding routine (..._SjLj_...)
     #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
+    #[unwind]
     pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception)
                                   -> _Unwind_Reason_Code;
 
     #[cfg(all(target_os = "ios", target_arch = "arm"))]
+    #[unwind]
     fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception)
                                    -> _Unwind_Reason_Code;
 
diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs
index ff93d0526b7..738681c3cfe 100644
--- a/src/libstd/sys/common/unwind/mod.rs
+++ b/src/libstd/sys/common/unwind/mod.rs
@@ -192,6 +192,7 @@ fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
 #[cfg(not(test))]
 /// Entry point of panic from the libcore crate.
 #[lang = "panic_fmt"]
+#[unwind]
 pub extern fn rust_begin_unwind(msg: fmt::Arguments,
                                 file: &'static str, line: u32) -> ! {
     begin_unwind_fmt(msg, &(file, line))
diff --git a/src/libstd/sys/common/unwind/seh.rs b/src/libstd/sys/common/unwind/seh.rs
index a201e406a23..a89e8b499ac 100644
--- a/src/libstd/sys/common/unwind/seh.rs
+++ b/src/libstd/sys/common/unwind/seh.rs
@@ -62,6 +62,7 @@ static PANIC_DATA: StaticKey = StaticKey::new(None);
 
 // This function is provided by kernel32.dll
 extern "system" {
+    #[unwind]
     fn RaiseException(dwExceptionCode: DWORD,
                       dwExceptionFlags: DWORD,
                       nNumberOfArguments: DWORD,
diff --git a/src/libstd/sys/common/unwind/seh64_gnu.rs b/src/libstd/sys/common/unwind/seh64_gnu.rs
index 4d23794de24..9478678fda9 100644
--- a/src/libstd/sys/common/unwind/seh64_gnu.rs
+++ b/src/libstd/sys/common/unwind/seh64_gnu.rs
@@ -93,6 +93,7 @@ pub enum EXCEPTION_DISPOSITION {
 
 // From kernel32.dll
 extern "system" {
+    #[unwind]
     fn RaiseException(dwExceptionCode: DWORD,
                       dwExceptionFlags: DWORD,
                       nNumberOfArguments: DWORD,
@@ -198,6 +199,7 @@ unsafe extern fn rust_eh_personality(
 
 #[lang = "eh_unwind_resume"]
 #[cfg(not(test))]
+#[unwind]
 unsafe extern fn rust_eh_unwind_resume(panic_ctx: LPVOID) {
     let params = [panic_ctx as ULONG_PTR];
     RaiseException(RUST_PANIC,
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 47f24856303..abc04102950 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -188,6 +188,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
 
     // allow `extern "platform-intrinsic" { ... }`
     ("platform_intrinsics", "1.4.0", Some(27731), Active),
+
+    // allow `#[unwind]`
+    ("unwind_attributes", "1.4.0", None, Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -316,6 +319,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
     ("unsafe_no_drop_flag", Whitelisted, Gated("unsafe_no_drop_flag",
                                                "unsafe_no_drop_flag has unstable semantics \
                                                 and may be removed in the future")),
+    ("unwind", Whitelisted, Gated("unwind_attributes", "#[unwind] is experimental")),
 
     // used in resolve
     ("prelude_import", Whitelisted, Gated("prelude_import",
diff --git a/src/test/codegen/extern-functions.rs b/src/test/codegen/extern-functions.rs
new file mode 100644
index 00000000000..4c30b5ce02f
--- /dev/null
+++ b/src/test/codegen/extern-functions.rs
@@ -0,0 +1,23 @@
+// Copyright 2015 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.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(unwind_attributes)]
+
+extern {
+// CHECK: Function Attrs: nounwind
+// CHECK-NEXT: declare void @extern_fn
+    fn extern_fn();
+// CHECK-NOT: Function Attrs: nounwind
+// CHECK: declare void @unwinding_extern_fn
+    #[unwind]
+    fn unwinding_extern_fn();
+}