summaryrefslogtreecommitdiff
path: root/src/librustc_trans/trans/declare.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_trans/trans/declare.rs')
-rw-r--r--src/librustc_trans/trans/declare.rs146
1 files changed, 29 insertions, 117 deletions
diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs
index 0c512200ff3..e63f17770bc 100644
--- a/src/librustc_trans/trans/declare.rs
+++ b/src/librustc_trans/trans/declare.rs
@@ -22,13 +22,10 @@
use llvm::{self, ValueRef};
use middle::ty;
use middle::infer;
-use middle::traits::ProjectionMode;
-use syntax::abi::Abi;
+use trans::abi::{Abi, FnType};
use trans::attributes;
-use trans::base;
use trans::context::CrateContext;
use trans::type_::Type;
-use trans::type_of;
use std::ffi::CString;
use libc::c_uint;
@@ -51,13 +48,10 @@ 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.
-pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv,
- ty: Type, output: ty::FnOutput) -> ValueRef {
- debug!("declare_fn(name={:?})", name);
+fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
+ debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
let namebuf = CString::new(name).unwrap_or_else(|_|{
ccx.sess().bug(&format!("name {:?} contains an interior null byte", name))
});
@@ -70,10 +64,6 @@ pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv,
// be merged.
llvm::SetUnnamedAddr(llfn, true);
- if output == ty::FnDiverging {
- llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn);
- }
-
if ccx.tcx().sess.opts.cg.no_redzone
.unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZone)
@@ -86,13 +76,12 @@ pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv,
/// 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.
-pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type,
- output: ty::Ty) -> ValueRef {
- declare_fn(ccx, name, llvm::CCallConv, fn_type, ty::FnConverging(output))
+pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef {
+ declare_raw_fn(ccx, name, llvm::CCallConv, fn_type)
}
@@ -100,53 +89,27 @@ pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type,
///
/// 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 {
- debug!("declare_rust_fn(name={:?}, fn_type={:?})", name,
- fn_type);
-
- let function_type; // placeholder so that the memory ownership works out ok
- let (sig, abi, env) = match fn_type.sty {
- ty::TyFnDef(_, _, f) |
- ty::TyFnPtr(f) => {
- (&f.sig, f.abi, None)
- }
- ty::TyClosure(closure_did, ref substs) => {
- let infcx = infer::normalizing_infer_ctxt(ccx.tcx(),
- &ccx.tcx().tables,
- ProjectionMode::Any);
- function_type = infcx.closure_type(closure_did, substs);
- let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
- let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type);
- debug!("declare_rust_fn function_type={:?} self_type={:?}",
- function_type, self_type);
- (&function_type.sig, Abi::RustCall, Some(llenvironment_type))
- }
- _ => ccx.sess().bug("expected closure or fn")
- };
-
- let sig = ccx.tcx().erase_late_bound_regions(sig);
+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);
+ let abi = fn_type.fn_abi();
+ let sig = ccx.tcx().erase_late_bound_regions(fn_type.fn_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={}", ccx.tn().type_to_string(llfty));
- // 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
-}
+ let fty = FnType::new(ccx, abi, &sig, &[]);
+ let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
+ if sig.output == ty::FnDiverging {
+ llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn);
+ }
+
+ if abi != Abi::Rust && abi != Abi::RustCall {
+ attributes::unwind(llfn, false);
+ }
+
+ fty.apply_attrs_llfn(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
}
@@ -166,78 +129,27 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
}
-/// Declare a function with an intention to define it.
-///
-/// For rust functions use `define_rust_fn` instead.
-///
-/// 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_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv,
- fn_type: Type, output: ty::FnOutput) -> Option<ValueRef> {
- 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<ValueRef> {
- 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<ValueRef> {
- 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
}
}
/// Get defined or externally defined (AvailableExternally linkage) value by
/// name.
-fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
+pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
debug!("get_defined_value(name={:?})", name);
let namebuf = CString::new(name).unwrap_or_else(|_|{
ccx.sess().bug(&format!("name {:?} contains an interior null byte", name))