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 :-/
This commit is contained in:
commit
2d4ae52cbd
@ -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)]
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
23
src/test/codegen/extern-functions.rs
Normal file
23
src/test/codegen/extern-functions.rs
Normal file
@ -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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user