trans: simplify the declare interface.
This commit is contained in:
parent
c6d214bdeb
commit
b122d1636a
7 changed files with 65 additions and 114 deletions
|
|
@ -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::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<String, ValueRef>;
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<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 @@ 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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue