提交 b122d163 编写于 作者: E Eduard Burtescu

trans: simplify the declare interface.

上级 c6d214bd
......@@ -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());
......
......@@ -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();
......
......@@ -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_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::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<String, ValueRef>;
pub fn validate_substs(substs: &Substs) {
assert!(!substs.types.needs_infer());
}
......@@ -539,31 +536,33 @@ pub fn eh_personality(&self) -> ValueRef {
// 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))
}
}
......
......@@ -26,6 +26,7 @@
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<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
}
}
......
......@@ -530,7 +530,7 @@ fn build_rust_fn<'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
......
......@@ -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,
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册