diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index daf8640ce94b..5e412baa9cea 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -337,7 +337,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( // let function_name = link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty, "fn_pointer_shim"); - let llfn = declare::declare_internal_rust_fn(ccx, &function_name[..], tuple_fn_ty); + let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty); // let empty_substs = tcx.mk_substs(Substs::trans_empty()); diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index eb050c43fa53..91bbcef9ce63 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -155,7 +155,7 @@ pub fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let symbol = mangle_internal_name_by_path_and_seq(path, "closure"); let function_type = ccx.tcx().mk_closure_from_closure_substs(closure_id, Box::new(substs)); - let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type); + let llfn = declare::define_internal_fn(ccx, &symbol, function_type); // set an inline hint for all closures attributes::inline(llfn, attributes::InlineAttr::Hint); @@ -357,8 +357,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Create the by-value helper. let function_name = link::mangle_internal_name_by_type_and_seq(ccx, llonce_fn_ty, "once_shim"); - let lloncefn = declare::define_internal_rust_fn(ccx, &function_name, - llonce_fn_ty); + let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty); let (block_arena, fcx): (TypedArena<_>, FunctionContext); block_arena = TypedArena::new(); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index aaaa636ea841..655a57b6f20f 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -12,8 +12,6 @@ //! Code that is useful in various trans modules. -pub use self::ExprOrMethodCall::*; - use session::Session; use llvm; use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef, TypeKind}; @@ -23,11 +21,11 @@ use middle::def::Def; use middle::def_id::DefId; use middle::infer; use middle::lang_items::LangItem; -use middle::subst::{self, Substs}; +use middle::subst::Substs; use trans::base; use trans::build; use trans::builder::Builder; -use trans::callee; +use trans::callee::Callee; use trans::cleanup; use trans::consts; use trans::datum; @@ -43,14 +41,15 @@ use middle::traits::{self, SelectionContext, ProjectionMode}; use middle::ty::fold::{TypeFolder, TypeFoldable}; use rustc_front::hir; use rustc::mir::repr::Mir; -use util::nodemap::{FnvHashMap, NodeMap}; +use util::nodemap::NodeMap; use arena::TypedArena; use libc::{c_uint, c_char}; use std::ops::Deref; use std::ffi::CString; use std::cell::{Cell, RefCell}; -use std::vec::Vec; + +use syntax::abi::Abi; use syntax::ast; use syntax::codemap::{DUMMY_SP, Span}; use syntax::parse::token::InternedString; @@ -253,8 +252,6 @@ pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res { } } -pub type ExternMap = FnvHashMap; - pub fn validate_substs(substs: &Substs) { assert!(!substs.types.needs_infer()); } @@ -539,31 +536,33 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined, // otherwise declares it as an external function. - pub fn eh_unwind_resume(&self) -> ValueRef { + pub fn eh_unwind_resume(&self) -> Callee<'tcx> { use trans::attributes; - assert!(self.ccx.sess().target.target.options.custom_unwind_resume); - match self.ccx.tcx().lang_items.eh_unwind_resume() { - Some(def_id) => { - callee::trans_fn_ref(self.ccx, def_id, ExprId(0), - self.param_substs).val - } - None => { - let mut unwresume = self.ccx.eh_unwind_resume().borrow_mut(); - match *unwresume { - Some(llfn) => llfn, - None => { - let fty = Type::func(&[Type::i8p(self.ccx)], &Type::void(self.ccx)); - let llfn = declare::declare_fn(self.ccx, - "rust_eh_unwind_resume", - llvm::CCallConv, - fty, ty::FnDiverging); - attributes::unwind(llfn, true); - *unwresume = Some(llfn); - llfn - } - } - } + let ccx = self.ccx; + let tcx = ccx.tcx(); + assert!(ccx.sess().target.target.options.custom_unwind_resume); + if let Some(def_id) = tcx.lang_items.eh_unwind_resume() { + return Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty())); } + + let ty = tcx.mk_fn_ptr(ty::BareFnTy { + unsafety: hir::Unsafety::Unsafe, + abi: Abi::C, + sig: ty::Binder(ty::FnSig { + inputs: vec![tcx.mk_mut_ptr(tcx.types.u8)], + output: ty::FnDiverging, + variadic: false + }), + }); + + let unwresume = ccx.eh_unwind_resume(); + if let Some(llfn) = unwresume.get() { + return Callee::ptr(datum::immediate_rvalue(llfn, ty)); + } + let llfn = declare::declare_fn(ccx, "rust_eh_unwind_resume", ty); + attributes::unwind(llfn, true); + unwresume.set(Some(llfn)); + Callee::ptr(datum::immediate_rvalue(llfn, ty)) } } diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs index 3df33d7d076b..d77fd6f10a0b 100644 --- a/src/librustc_trans/trans/declare.rs +++ b/src/librustc_trans/trans/declare.rs @@ -26,6 +26,7 @@ use middle::traits::ProjectionMode; use syntax::abi::Abi; use trans::attributes; use trans::base; +use trans::cabi::FnType; use trans::context::CrateContext; use trans::type_::Type; use trans::type_of; @@ -51,8 +52,6 @@ pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRe /// Declare a function. /// -/// For rust functions use `declare_rust_fn` instead. -/// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing ValueRef instead. fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef { @@ -81,7 +80,7 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: /// Declare a C ABI function. /// /// Only use this for foreign function ABIs and glue. For Rust functions use -/// `declare_rust_fn` instead. +/// `declare_fn` instead. /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing ValueRef instead. @@ -94,8 +93,8 @@ pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing ValueRef instead. -pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, - fn_type: ty::Ty<'tcx>) -> ValueRef { +pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, + fn_type: ty::Ty<'tcx>) -> ValueRef { debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); @@ -118,28 +117,33 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, _ => ccx.sess().bug("expected closure or fn") }; + let sig = ccx.tcx().erase_late_bound_regions(sig); let sig = infer::normalize_associated_type(ccx.tcx(), &sig); debug!("declare_rust_fn (after region erasure) sig={:?}", sig); - let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi); - debug!("declare_rust_fn llfty={:?}", llfty); + + let (cconv, llfty) = if abi == Abi::Rust || abi == Abi::RustCall { + (llvm::CCallConv, type_of::type_of_rust_fn(ccx, env, &sig, abi)) + } else { + let fty = FnType::new(ccx, abi, &sig, &[]); + (fty.cconv, fty.to_llvm(ccx)) + }; // it is ok to directly access sig.0.output because we erased all // late-bound-regions above - let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.output); - attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn); - llfn -} + debug!("declare_rust_fn llfty={:?}", llfty); + let llfn = declare_raw_fn(ccx, name, cconv, llfty); + if sig.output == ty::FnDiverging { + llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn); + } + + if abi == Abi::Rust || abi == Abi::RustCall { + attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn); + } else { + FnType::new(ccx, abi, &sig, &[]).add_attributes(llfn); + } -/// Declare a Rust function with internal linkage. -/// -/// If there’s a value with the same name already declared, the function will -/// update the declaration and return existing ValueRef instead. -pub fn declare_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, - fn_type: ty::Ty<'tcx>) -> ValueRef { - let llfn = declare_rust_fn(ccx, name, fn_type); - llvm::SetLinkage(llfn, llvm::InternalLinkage); llfn } @@ -159,71 +163,20 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option Option { - if get_defined_value(ccx, name).is_some() { - None - } else { - Some(declare_fn(ccx, name, callconv, fn_type, output)) - } -} - - -/// Declare a C ABI function with an intention to define it. -/// -/// Use this function when you intend to define a function. This function will -/// return None if the name already has a definition associated with it. In that -/// case an error should be reported to the user, because it usually happens due -/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). -/// -/// Only use this for foreign function ABIs and glue. For Rust functions use -/// `declare_rust_fn` instead. -pub fn define_cfn(ccx: &CrateContext, name: &str, fn_type: Type, - output: ty::Ty) -> Option { - if get_defined_value(ccx, name).is_some() { - None - } else { - Some(declare_cfn(ccx, name, fn_type, output)) - } -} - - -/// Declare a Rust function with an intention to define it. -/// -/// Use this function when you intend to define a function. This function will -/// return None if the name already has a definition associated with it. In that -/// case an error should be reported to the user, because it usually happens due -/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). -pub fn define_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, - fn_type: ty::Ty<'tcx>) -> Option { - if get_defined_value(ccx, name).is_some() { - None - } else { - Some(declare_rust_fn(ccx, name, fn_type)) - } -} - - /// Declare a Rust function with an intention to define it. /// /// Use this function when you intend to define a function. This function will /// return panic if the name already has a definition associated with it. This /// can happen with #[no_mangle] or #[export_name], for example. -pub fn define_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - name: &str, - fn_type: ty::Ty<'tcx>) -> ValueRef { +pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + name: &str, + fn_type: ty::Ty<'tcx>) -> ValueRef { if get_defined_value(ccx, name).is_some() { ccx.sess().fatal(&format!("symbol `{}` already defined", name)) } else { - declare_internal_rust_fn(ccx, name, fn_type) + let llfn = declare_fn(ccx, name, fn_type); + llvm::SetLinkage(llfn, llvm::InternalLinkage); + llfn } } diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 99df9c181856..27d2c07893b6 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -530,7 +530,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.tcx().map.path_to_string(id), id, rust_fn_ty); - let llfn = declare::define_internal_rust_fn(ccx, &ps, t); + let llfn = declare::define_internal_fn(ccx, &ps, rust_fn_ty); attributes::from_fn_attrs(ccx, attrs, llfn); base::trans_fn(ccx, decl, body, llfn, param_substs, id, attrs); llfn diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 24e13d750a95..46afeaa4d9e7 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -1275,7 +1275,7 @@ fn gen_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, trans: &mut for<'b> FnMut(Block<'b, 'tcx>)) -> ValueRef { let ccx = fcx.ccx; - let llfn = declare::define_internal_rust_fn(ccx, name, ty); + let llfn = declare::define_internal_fn(ccx, name, ty); let (fcx, block_arena); block_arena = TypedArena::new(); fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index dad26900fdff..2a51c3937176 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -108,7 +108,7 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, // let function_name = link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim"); - let llfn = declare::define_internal_rust_fn(ccx, &function_name, shim_fn_ty); + let llfn = declare::define_internal_fn(ccx, &function_name, shim_fn_ty); let empty_substs = tcx.mk_substs(Substs::trans_empty()); let (block_arena, fcx): (TypedArena<_>, FunctionContext);