diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index a1fa4e77a131bb02935ac8231849e39c56e026a1..c7200fc8bb256157c4d0c5f01bcbc995fc175916 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -64,6 +64,7 @@ use trans::controlflow; use trans::datum; use trans::debuginfo::{self, DebugLoc, ToDebugLoc}; +use trans::declare; use trans::expr; use trans::foreign; use trans::glue; @@ -179,44 +180,6 @@ fn drop(&mut self) { } } -// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions -pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv, - ty: Type, output: ty::FnOutput) -> ValueRef { - - let buf = CString::new(name).unwrap(); - let llfn: ValueRef = unsafe { - llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref()) - }; - - // diverging functions may unwind, but can never return normally - if output == ty::FnDiverging { - llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute); - } - - if ccx.tcx().sess.opts.cg.no_redzone - .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) { - llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute) - } - - llvm::SetFunctionCallConv(llfn, cc); - // Function addresses in Rust are never significant, allowing functions to be merged. - llvm::SetUnnamedAddr(llfn, true); - - if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check { - attributes::split_stack(llfn, true); - } - - llfn -} - -// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions -pub fn decl_cdecl_fn(ccx: &CrateContext, - name: &str, - ty: Type, - output: Ty) -> ValueRef { - decl_fn(ccx, name, llvm::CCallConv, ty, ty::FnConverging(output)) -} - fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>, name: &str, did: ast::DefId) -> ValueRef { match ccx.externs().borrow().get(name) { @@ -224,7 +187,7 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>, None => () } - let f = decl_rust_fn(ccx, fn_ty, name); + let f = declare::declare_rust_fn(ccx, name, fn_ty); let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did); attributes::from_fn_attrs(ccx, &attrs[..], f); @@ -254,63 +217,6 @@ pub fn kind_for_closure(ccx: &CrateContext, closure_id: ast::DefId) -> ty::Closu *ccx.tcx().closure_kinds.borrow().get(&closure_id).unwrap() } -pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - fn_ty: Ty<'tcx>, name: &str) -> ValueRef { - debug!("decl_rust_fn(fn_ty={}, name={:?})", - fn_ty.repr(ccx.tcx()), - name); - - let fn_ty = monomorphize::normalize_associated_type(ccx.tcx(), &fn_ty); - - debug!("decl_rust_fn: fn_ty={} (after normalized associated types)", - fn_ty.repr(ccx.tcx())); - - let function_type; // placeholder so that the memory ownership works out ok - - let (sig, abi, env) = match fn_ty.sty { - ty::ty_bare_fn(_, ref f) => { - (&f.sig, f.abi, None) - } - ty::ty_closure(closure_did, substs) => { - let typer = common::NormalizingClosureTyper::new(ccx.tcx()); - function_type = typer.closure_type(closure_did, substs); - let self_type = self_type_for_closure(ccx, closure_did, fn_ty); - let llenvironment_type = type_of_explicit_arg(ccx, self_type); - debug!("decl_rust_fn: function_type={} self_type={}", - function_type.repr(ccx.tcx()), - self_type.repr(ccx.tcx())); - (&function_type.sig, RustCall, Some(llenvironment_type)) - } - _ => ccx.sess().bug("expected closure or fn") - }; - - let sig = ty::erase_late_bound_regions(ccx.tcx(), sig); - let sig = ty::Binder(sig); - - debug!("decl_rust_fn: sig={} (after erasing regions)", - sig.repr(ccx.tcx())); - - let llfty = type_of_rust_fn(ccx, env, &sig, abi); - - debug!("decl_rust_fn: llfty={}", - ccx.tn().type_to_string(llfty)); - - let llfn = decl_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output /* (1) */); - let attrs = get_fn_llvm_attributes(ccx, fn_ty); - attrs.apply_llfn(llfn); - - // (1) it's ok to directly access sig.0.output because we erased all late-bound-regions above - - llfn -} - -pub fn decl_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - fn_ty: Ty<'tcx>, name: &str) -> ValueRef { - let llfn = decl_rust_fn(ccx, fn_ty, name); - llvm::SetLinkage(llfn, llvm::InternalLinkage); - llfn -} - pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, t: Ty<'tcx>) -> ValueRef { let name = csearch::get_symbol(&ccx.sess().cstore, did); @@ -319,23 +225,22 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, Some(n) => return *n, None => () } - unsafe { - let buf = CString::new(name.clone()).unwrap(); - let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr()); - // Thread-local statics in some other crate need to *always* be linked - // against in a thread-local fashion, so we need to be sure to apply the - // thread-local attribute locally if it was present remotely. If we - // don't do this then linker errors can be generated where the linker - // complains that one object files has a thread local version of the - // symbol and another one doesn't. - for attr in &*ty::get_attrs(ccx.tcx(), did) { - if attr.check_name("thread_local") { - llvm::set_thread_local(c, true); - } + // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? + // FIXME(nagisa): investigate whether it can be changed into define_global + let c = declare::declare_global(ccx, &name[..], ty); + // Thread-local statics in some other crate need to *always* be linked + // against in a thread-local fashion, so we need to be sure to apply the + // thread-local attribute locally if it was present remotely. If we + // don't do this then linker errors can be generated where the linker + // complains that one object files has a thread local version of the + // symbol and another one doesn't. + for attr in &*ty::get_attrs(ccx.tcx(), did) { + if attr.check_name("thread_local") { + llvm::set_thread_local(c, true); } - ccx.externs().borrow_mut().insert(name.to_string(), c); - return c; } + ccx.externs().borrow_mut().insert(name.to_string(), c); + return c; } fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, @@ -373,15 +278,6 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } -// Double-check that we never ask LLVM to declare the same symbol twice. It -// silently mangles such symbols, breaking our linkage model. -pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: String) { - if ccx.all_llvm_symbols().borrow().contains(&sym) { - ccx.sess().bug(&format!("duplicate LLVM symbol: {}", sym)); - } - ccx.all_llvm_symbols().borrow_mut().insert(sym); -} - pub fn bin_op_to_icmp_predicate(ccx: &CrateContext, op: ast::BinOp_, signed: bool) -> llvm::IntPredicate { match op { @@ -1713,15 +1609,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let fn_ty = ty::node_id_to_type(ccx.tcx(), id); let output_type = ty::erase_late_bound_regions(ccx.tcx(), &ty::ty_fn_ret(fn_ty)); let abi = ty::ty_fn_abi(fn_ty); - trans_closure(ccx, - decl, - body, - llfndecl, - param_substs, - id, - attrs, - output_type, - abi, + trans_closure(ccx, decl, body, llfndecl, param_substs, id, attrs, output_type, abi, closure::ClosureEnv::NotClosure); } @@ -2066,27 +1954,24 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { let llfn = get_item_val(ccx, item.id); let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty()); if abi != Rust { - foreign::trans_rust_fn_with_foreign_abi(ccx, - &**decl, - &**body, - &item.attrs, - llfn, - empty_substs, - item.id, - None); + foreign::trans_rust_fn_with_foreign_abi(ccx, &**decl, &**body, &item.attrs, + llfn, empty_substs, item.id, None); } else { - trans_fn(ccx, - &**decl, - &**body, - llfn, - empty_substs, - item.id, - &item.attrs); + trans_fn(ccx, &**decl, &**body, llfn, empty_substs, item.id, &item.attrs); } - update_linkage(ccx, - llfn, - Some(item.id), + update_linkage(ccx, llfn, Some(item.id), if is_origin { OriginalTranslation } else { InlinedCopy }); + + if is_entry_fn(ccx.sess(), item.id) { + create_entry_wrapper(ccx, item.span, llfn); + // check for the #[rustc_error] annotation, which forces an + // error in trans. This is used to write compile-fail tests + // that actually test that compilation succeeds without + // reporting an error. + if ty::has_attr(ccx.tcx(), local_def(item.id), "rustc_error") { + ccx.tcx().sess.span_fatal(item.span, "compilation successful"); + } + } } } @@ -2122,8 +2007,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { let mut v = TransItemVisitor{ ccx: ccx }; v.visit_expr(&**expr); - consts::trans_static(ccx, m, item.id); - let g = get_item_val(ccx, item.id); + let g = consts::trans_static(ccx, m, item.id); update_linkage(ccx, g, Some(item.id), OriginalTranslation); // Do static_assert checking. It can't really be done much earlier @@ -2175,7 +2059,25 @@ pub fn trans_mod(ccx: &CrateContext, m: &ast::Mod) { } } -fn finish_register_fn(ccx: &CrateContext, sp: Span, sym: String, node_id: ast::NodeId, + +// only use this for foreign function ABIs and glue, use `register_fn` for Rust functions +pub fn register_fn_llvmty(ccx: &CrateContext, + sp: Span, + sym: String, + node_id: ast::NodeId, + cc: llvm::CallConv, + llfty: Type) -> ValueRef { + debug!("register_fn_llvmty id={} sym={}", node_id, sym); + + let llfn = declare::define_fn(ccx, &sym[..], cc, llfty, + ty::FnConverging(ty::mk_nil(ccx.tcx()))).unwrap_or_else(||{ + ccx.sess().span_fatal(sp, &format!("symbol `{}` is already defined", sym)); + }); + finish_register_fn(ccx, sym, node_id, llfn); + llfn +} + +fn finish_register_fn(ccx: &CrateContext, sym: String, node_id: ast::NodeId, llfn: ValueRef) { ccx.item_symbols().borrow_mut().insert(node_id, sym); @@ -2190,19 +2092,6 @@ fn finish_register_fn(ccx: &CrateContext, sp: Span, sym: String, node_id: ast::N if ccx.tcx().lang_items.eh_personality() == Some(def) { llvm::SetLinkage(llfn, llvm::ExternalLinkage); } - - - if is_entry_fn(ccx.sess(), node_id) { - // check for the #[rustc_error] annotation, which forces an - // error in trans. This is used to write compile-fail tests - // that actually test that compilation succeeds without - // reporting an error. - if ty::has_attr(ccx.tcx(), local_def(node_id), "rustc_error") { - ccx.tcx().sess.span_fatal(sp, "compilation successful"); - } - - create_entry_wrapper(ccx, sp, llfn); - } } fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, @@ -2221,26 +2110,10 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.sess().span_bug(sp, "expected bare rust function") } - let llfn = decl_rust_fn(ccx, node_type, &sym[..]); - finish_register_fn(ccx, sp, sym, node_id, llfn); - llfn -} - -// only use this for foreign function ABIs and glue, use `register_fn` for Rust functions -pub fn register_fn_llvmty(ccx: &CrateContext, - sp: Span, - sym: String, - node_id: ast::NodeId, - cc: llvm::CallConv, - llfty: Type) -> ValueRef { - debug!("register_fn_llvmty id={} sym={}", node_id, sym); - - let llfn = decl_fn(ccx, - &sym[..], - cc, - llfty, - ty::FnConverging(ty::mk_nil(ccx.tcx()))); - finish_register_fn(ccx, sp, sym, node_id, llfn); + let llfn = declare::define_rust_fn(ccx, &sym[..], node_type).unwrap_or_else(||{ + ccx.sess().span_fatal(sp, &format!("symbol `{}` is already defined", sym)); + }); + finish_register_fn(ccx, sym, node_id, llfn); llfn } @@ -2251,27 +2124,36 @@ pub fn is_entry_fn(sess: &Session, node_id: ast::NodeId) -> bool { } } -// Create a _rust_main(args: ~[str]) function which will be called from the -// runtime rust_start function +/// Create the `main` function which will initialise the rust runtime and call users’ main +/// function. pub fn create_entry_wrapper(ccx: &CrateContext, _sp: Span, main_llfn: ValueRef) { let et = ccx.sess().entry_type.get().unwrap(); match et { config::EntryMain => { - create_entry_fn(ccx, main_llfn, true); + create_entry_fn(ccx, _sp, main_llfn, true); } - config::EntryStart => create_entry_fn(ccx, main_llfn, false), + config::EntryStart => create_entry_fn(ccx, _sp, main_llfn, false), config::EntryNone => {} // Do nothing. } + #[inline(never)] fn create_entry_fn(ccx: &CrateContext, + _sp: Span, rust_main: ValueRef, use_start_lang_item: bool) { let llfty = Type::func(&[ccx.int_type(), Type::i8p(ccx).ptr_to()], &ccx.int_type()); - let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil(ccx.tcx())); + let llfn = declare::define_cfn(ccx, "main", llfty, + ty::mk_nil(ccx.tcx())).unwrap_or_else(||{ + ccx.sess().span_err(_sp, "entry symbol `main` defined multiple times"); + // FIXME: We should be smart and show a better diagnostic here. + ccx.sess().help("did you use #[no_mangle] on `fn main`? Use #[start] instead"); + ccx.sess().abort_if_errors(); + panic!(); + }); // FIXME: #16581: Marking a symbol in the executable with `dllexport` // linkage forces MinGW's linker to output a `.reloc` section for ASLR @@ -2407,14 +2289,15 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { } else { llvm::LLVMTypeOf(v) }; - if contains_null(&sym[..]) { - ccx.sess().fatal( - &format!("Illegal null byte in export_name \ - value: `{}`", sym)); - } - let buf = CString::new(sym.clone()).unwrap(); - let g = llvm::LLVMAddGlobal(ccx.llmod(), llty, - buf.as_ptr()); + + // FIXME(nagisa): probably should be declare_global, because no definition + // is happening here, but we depend on it being defined here from + // const::trans_static. This all logic should be replaced. + let g = declare::define_global(ccx, &sym[..], + Type::from_ref(llty)).unwrap_or_else(||{ + ccx.sess().span_fatal(i.span, &format!("symbol `{}` is already defined", + sym)) + }); if attr::contains_name(&i.attrs, "thread_local") { @@ -2430,10 +2313,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let llfn = if abi == Rust { register_fn(ccx, i.span, sym, i.id, ty) } else { - foreign::register_rust_fn_with_foreign_abi(ccx, - i.span, - sym, - i.id) + foreign::register_rust_fn_with_foreign_abi(ccx, i.span, sym, i.id) }; attributes::from_fn_attrs(ccx, &i.attrs, llfn); llfn diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 9eb46d3ff549a80bd33a7ef06295fc67f8a676a8..604f185f396b81994230f77d4738dd73d1334a0f 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -41,6 +41,7 @@ use trans::consts; use trans::datum::*; use trans::debuginfo::{DebugLoc, ToDebugLoc}; +use trans::declare; use trans::expr; use trans::glue; use trans::inline; @@ -326,13 +327,9 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( debug!("tuple_fn_ty: {}", tuple_fn_ty.repr(tcx)); // - let function_name = - link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty, - "fn_pointer_shim"); - let llfn = - decl_internal_rust_fn(ccx, - tuple_fn_ty, - &function_name[..]); + 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 empty_substs = tcx.mk_substs(Substs::trans_empty()); diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 19891e9307229fa52ee380c21b743b0f67fe9d5b..61af5bfaef8dee5db3da83e9ff959fad99ab1963 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -126,6 +126,7 @@ use trans::common; use trans::common::{Block, FunctionContext, ExprId, NodeIdAndSpan}; use trans::debuginfo::{DebugLoc, ToDebugLoc}; +use trans::declare; use trans::glue; use middle::region; use trans::type_::Type; @@ -844,10 +845,8 @@ fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef { Some(llpersonality) => llpersonality, None => { let fty = Type::variadic_func(&[], &Type::i32(self.ccx)); - let f = base::decl_cdecl_fn(self.ccx, - "rust_eh_personality", - fty, - self.ccx.tcx().types.i32); + let f = declare::declare_cfn(self.ccx, "rust_eh_personality", fty, + self.ccx.tcx().types.i32); *personality = Some(f); f } diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index c343d705e866f029b3e3868cf9981dcfcdd1f120..60d54cdebeb83ff670462d84edea05702ec05453 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -21,6 +21,7 @@ use trans::common::*; use trans::datum::{self, Datum, rvalue_scratch_datum, Rvalue, ByValue}; use trans::debuginfo::{self, DebugLoc}; +use trans::declare; use trans::expr; use trans::monomorphize::{self, MonoId}; use trans::type_of::*; @@ -162,7 +163,11 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc mangle_internal_name_by_path_and_seq(path, "closure") }); - let llfn = decl_internal_rust_fn(ccx, function_type, &symbol[..]); + // Currently there’s only a single user of get_or_create_declaration_if_closure and it + // unconditionally defines the function, therefore we use define_* here. + let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type).unwrap_or_else(||{ + ccx.sess().bug(&format!("symbol `{}` already defined", symbol)); + }); // set an inline hint for all closures attributes::inline(llfn, attributes::InlineAttr::Hint); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index c5985e930e97b98b72fc9e3ffdb72a3c6e1af935..153242353d49f5e5c9ac2cfefb482df90fc77861 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -31,6 +31,7 @@ use trans::consts; use trans::datum; use trans::debuginfo::{self, DebugLoc}; +use trans::declare; use trans::machine; use trans::monomorphize; use trans::type_::Type; @@ -872,9 +873,10 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va !null_terminated as Bool); let gsym = token::gensym("str"); - let buf = CString::new(format!("str{}", gsym.usize())); - let buf = buf.unwrap(); - let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr()); + let sym = format!("str{}", gsym.usize()); + let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{ + cx.sess().bug(&format!("symbol `{}` is already defined", sym)); + }); llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); llvm::SetLinkage(g, llvm::InternalLinkage); diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index c32cb28ec78dbb9bbdbf83fced5510b615f2780e..336e68f1e8b496288cb20729e57a9ae93a596b03 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -25,6 +25,7 @@ use trans::{adt, closure, debuginfo, expr, inline, machine}; use trans::base::{self, push_ctxt}; use trans::common::*; +use trans::declare; use trans::monomorphize; use trans::type_::Type; use trans::type_of; @@ -35,6 +36,7 @@ use std::iter::repeat; use libc::c_uint; use syntax::{ast, ast_util}; +use syntax::parse::token; use syntax::ptr::P; pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit) @@ -96,13 +98,16 @@ pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef { fn addr_of_mut(ccx: &CrateContext, cv: ValueRef, - kind: &str, - id: ast::NodeId) + kind: &str) -> ValueRef { unsafe { - let name = format!("{}{}\0", kind, id); - let gv = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(cv).to_ref(), - name.as_ptr() as *const _); + // FIXME: this totally needs a better name generation scheme, perhaps a simple global + // counter? Also most other uses of gensym in trans. + let gsym = token::gensym("_"); + let name = format!("{}{}", kind, gsym.usize()); + let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{ + ccx.sess().bug(&format!("symbol `{}` is already defined", name)); + }); llvm::LLVMSetInitializer(gv, cv); SetLinkage(gv, InternalLinkage); SetUnnamedAddr(gv, true); @@ -112,14 +117,13 @@ fn addr_of_mut(ccx: &CrateContext, pub fn addr_of(ccx: &CrateContext, cv: ValueRef, - kind: &str, - id: ast::NodeId) + kind: &str) -> ValueRef { match ccx.const_globals().borrow().get(&cv) { Some(&gv) => return gv, None => {} } - let gv = addr_of_mut(ccx, cv, kind, id); + let gv = addr_of_mut(ccx, cv, kind); unsafe { llvm::LLVMSetGlobalConstant(gv, True); } @@ -233,7 +237,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } }; - let lvalue = addr_of(ccx, val, "const", expr.id); + let lvalue = addr_of(ccx, val, "const"); ccx.const_values().borrow_mut().insert(key, lvalue); lvalue } @@ -284,7 +288,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, if adj.autoderefs == 0 { // Don't copy data to do a deref+ref // (i.e., skip the last auto-deref). - llconst = addr_of(cx, llconst, "autoref", e.id); + llconst = addr_of(cx, llconst, "autoref"); } else { // Seeing as we are deref'ing here and take a reference // again to make the pointer part of the far pointer below, @@ -312,7 +316,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, None => {} Some(box ty::AutoUnsafe(_, None)) | Some(box ty::AutoPtr(_, _, None)) => { - llconst = addr_of(cx, llconst, "autoref", e.id); + llconst = addr_of(cx, llconst, "autoref"); } Some(box ty::AutoUnsize(ref k)) => { let info = @@ -711,12 +715,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // If this isn't the address of a static, then keep going through // normal constant evaluation. let (v, _) = const_expr(cx, &**sub, param_substs); - addr_of(cx, v, "ref", e.id) + addr_of(cx, v, "ref") } } ast::ExprAddrOf(ast::MutMutable, ref sub) => { let (v, _) = const_expr(cx, &**sub, param_substs); - addr_of_mut(cx, v, "ref_mut_slice", e.id) + addr_of_mut(cx, v, "ref_mut_slice") } ast::ExprTup(ref es) => { let repr = adt::represent_type(cx, ety); @@ -862,7 +866,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } -pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) { +pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) -> ValueRef { unsafe { let _icx = push_ctxt("trans_static"); let g = base::get_item_val(ccx, id); @@ -888,6 +892,7 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) { } } debuginfo::create_global_var_metadata(ccx, id, g); + g } } diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 8919a386a45fb0ac1182174d8dbc65301f9f0318..e54962dc085524e1b41fc337fc453503379c231d 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -20,6 +20,7 @@ use trans::builder::Builder; use trans::common::{ExternMap,BuilderRef_res}; use trans::debuginfo; +use trans::declare; use trans::monomorphize::MonoId; use trans::type_::{Type, TypeNames}; use middle::subst::Substs; @@ -133,7 +134,6 @@ pub struct LocalCrateContext<'tcx> { llsizingtypes: RefCell, Type>>, adt_reprs: RefCell, Rc>>>, type_hashcodes: RefCell, String>>, - all_llvm_symbols: RefCell>, int_type: Type, opaque_vec_type: Type, builder: BuilderRef_res, @@ -413,7 +413,6 @@ fn new(shared: &SharedCrateContext<'tcx>, llsizingtypes: RefCell::new(FnvHashMap()), adt_reprs: RefCell::new(FnvHashMap()), type_hashcodes: RefCell::new(FnvHashMap()), - all_llvm_symbols: RefCell::new(FnvHashSet()), int_type: Type::from_ref(ptr::null_mut()), opaque_vec_type: Type::from_ref(ptr::null_mut()), builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)), @@ -653,10 +652,6 @@ pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell, String>> &self.local.type_hashcodes } - pub fn all_llvm_symbols<'a>(&'a self) -> &'a RefCell> { - &self.local.all_llvm_symbols - } - pub fn stats<'a>(&'a self) -> &'a Stats { &self.shared.stats } @@ -743,17 +738,16 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option $ret:expr) => ( if *key == $name { - let f = base::decl_cdecl_fn( - ccx, $name, Type::func(&[], &$ret), - ty::mk_nil(ccx.tcx())); + let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret), + ty::mk_nil(ccx.tcx())); ccx.intrinsics().borrow_mut().insert($name, f.clone()); return Some(f); } ); ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( if *key == $name { - let f = base::decl_cdecl_fn(ccx, $name, - Type::func(&[$($arg),*], &$ret), ty::mk_nil(ccx.tcx())); + let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret), + ty::mk_nil(ccx.tcx())); ccx.intrinsics().borrow_mut().insert($name, f.clone()); return Some(f); } @@ -888,9 +882,9 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option $ret); } else if *key == $name { - let f = base::decl_cdecl_fn(ccx, stringify!($cname), - Type::func(&[$($arg),*], &$ret), - ty::mk_nil(ccx.tcx())); + let f = declare::declare_cfn(ccx, stringify!($cname), + Type::func(&[$($arg),*], &$ret), + ty::mk_nil(ccx.tcx())); ccx.intrinsics().borrow_mut().insert($name, f.clone()); return Some(f); } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 5b1ac88c2089b951113911b16527cba09b547af8..3ce883af07f6a56e94296a3d238bd2a286e5c024 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -417,8 +417,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let filename = C_str_slice(ccx, filename); let line = C_u32(ccx, loc.line as u32); let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); - let expr_file_line = consts::addr_of(ccx, expr_file_line_const, - "panic_loc", call_info.id); + let expr_file_line = consts::addr_of(ccx, expr_file_line_const, "panic_loc"); let args = vec!(expr_file_line); let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem); let bcx = callee::trans_lang_call(bcx, @@ -450,8 +449,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let filename = C_str_slice(ccx, filename); let line = C_u32(ccx, loc.line as u32); let file_line_const = C_struct(ccx, &[filename, line], false); - let file_line = consts::addr_of(ccx, file_line_const, - "panic_bounds_check_loc", call_info.id); + let file_line = consts::addr_of(ccx, file_line_const, "panic_bounds_check_loc"); let args = vec!(file_line, index, len); let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem); let bcx = callee::trans_lang_call(bcx, diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 2747288b60755c9245156bb496e4278d859e1aef..a32b40dc2b640b673e70a371c580d856831b24e1 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -196,8 +196,9 @@ use metadata::csearch; use middle::subst::{self, Substs}; use trans::{self, adt, machine, type_of}; -use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, - C_bytes, NormalizingClosureTyper}; +use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, C_bytes, + NormalizingClosureTyper}; +use trans::declare; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; use trans::monomorphize; use trans::type_::Type; @@ -4071,7 +4072,7 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) /// section. fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext) -> llvm::ValueRef { - let section_var_name = b"__rustc_debug_gdb_scripts_section__\0"; + let section_var_name = "__rustc_debug_gdb_scripts_section__"; let section_var = unsafe { llvm::LLVMGetNamedGlobal(ccx.llmod(), @@ -4085,10 +4086,11 @@ fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext) unsafe { let llvm_type = Type::array(&Type::i8(ccx), section_contents.len() as u64); - let section_var = llvm::LLVMAddGlobal(ccx.llmod(), - llvm_type.to_ref(), - section_var_name.as_ptr() - as *const _); + + let section_var = declare::define_global(ccx, section_var_name, + llvm_type).unwrap_or_else(||{ + ccx.sess().bug(&format!("symbol `{}` is already defined", section_var_name)) + }); llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _); llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs new file mode 100644 index 0000000000000000000000000000000000000000..147b5161a4ac2fdca1d9feec8b638b7590a4eb50 --- /dev/null +++ b/src/librustc_trans/trans/declare.rs @@ -0,0 +1,263 @@ +// Copyright 2012-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +//! Declare various LLVM values. +//! +//! Prefer using functions and methods from this module rather than calling LLVM functions +//! directly. These functions do some additional work to ensure we do the right thing given +//! the preconceptions of trans. +//! +//! Some useful guidelines: +//! +//! * Use declare_* family of methods if you are declaring, but are not interested in defining the +//! ValueRef they return. +//! * Use define_* family of methods when you might be defining the ValueRef. +//! * When in doubt, define. +#![allow(dead_code)] + +use llvm::{self, ValueRef}; +use middle::ty::{self, ClosureTyper}; +use syntax::abi; +use trans::attributes; +use trans::base; +use trans::common; +use trans::context::CrateContext; +use trans::monomorphize; +use trans::type_::Type; +use trans::type_of; +use util::ppaux::Repr; + +use std::ffi::CString; +use libc::c_uint; + + +/// Declare a global value. +/// +/// If there’s a value with the same name already declared, the function will return its ValueRef +/// instead. +pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef { + debug!("declare_global(name={:?})", name); + let namebuf = CString::new(name).unwrap_or_else(|_|{ + ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) + }); + unsafe { + llvm::LLVMGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref()) + } +} + + +/// 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); + let namebuf = CString::new(name).unwrap_or_else(|_|{ + ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) + }); + let llfn = unsafe { + llvm::LLVMGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref()) + }; + + llvm::SetFunctionCallConv(llfn, callconv); + // Function addresses in Rust are never significant, allowing functions to be merged. + llvm::SetUnnamedAddr(llfn, true); + + if output == ty::FnDiverging { + llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute); + } + + if ccx.tcx().sess.opts.cg.no_redzone + .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) { + llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute) + } + + if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check { + attributes::split_stack(llfn, true); + } + llfn +} + + +/// Declare a C ABI function. +/// +/// Only use this for foreign function ABIs and glue. 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_cfn(ccx: &CrateContext, name: &str, fn_type: Type, output: ty::Ty) -> ValueRef { + declare_fn(ccx, name, llvm::CCallConv, fn_type, ty::FnConverging(output)) +} + + +/// Declare a Rust function. +/// +/// 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.repr(ccx.tcx())); + let fn_type = monomorphize::normalize_associated_type(ccx.tcx(), &fn_type); + debug!("declare_rust_fn (after normalised associated types) fn_type={}", + fn_type.repr(ccx.tcx())); + + let function_type; // placeholder so that the memory ownership works out ok + let (sig, abi, env) = match fn_type.sty { + ty::ty_bare_fn(_, ref f) => { + (&f.sig, f.abi, None) + } + ty::ty_closure(closure_did, substs) => { + let typer = common::NormalizingClosureTyper::new(ccx.tcx()); + function_type = typer.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.repr(ccx.tcx()), self_type.repr(ccx.tcx())); + (&function_type.sig, abi::RustCall, Some(llenvironment_type)) + } + _ => ccx.sess().bug("expected closure or fn") + }; + + let sig = ty::Binder(ty::erase_late_bound_regions(ccx.tcx(), sig)); + debug!("declare_rust_fn (after region erasure) sig={}", sig.repr(ccx.tcx())); + 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.0.output); + attributes::from_fn_type(ccx, fn_type).apply_llfn(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 +} + + +/// Declare a global with an intention to define it. +/// +/// Use this function when you intend to define a global. 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_global(ccx: &CrateContext, name: &str, ty: Type) -> Option { + if get_defined_value(ccx, name).is_some() { + None + } else { + Some(declare_global(ccx, name, ty)) + } +} + + +/// 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 { + 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 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_internal_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_internal_rust_fn(ccx, name, fn_type)) + } +} + + +/// Get defined or externally defined (AvailableExternally linkage) value by name. +fn get_defined_value(ccx: &CrateContext, name: &str) -> Option { + 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)) + }); + let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) }; + if val.is_null() { + debug!("get_defined_value: {:?} value is null", name); + None + } else { + let (declaration, aext_link) = unsafe { + let linkage = llvm::LLVMGetLinkage(val); + (llvm::LLVMIsDeclaration(val) != 0, + linkage == llvm::AvailableExternallyLinkage as c_uint) + }; + debug!("get_defined_value: found {:?} value (declaration: {}, aext_link: {})", name, + declaration, aext_link); + if !declaration || aext_link { + Some(val) + } else { + None + } + } +} diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 20da3c1c9f89518ebfb31bdbccc4ef70486fbe88..8f3a51a5007096984835901d54f13b8f07b21150 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -20,6 +20,7 @@ use trans::cabi; use trans::common::*; use trans::debuginfo::DebugLoc; +use trans::declare; use trans::machine; use trans::monomorphize; use trans::type_::Type; @@ -28,7 +29,6 @@ use middle::ty::{self, Ty}; use middle::subst::Substs; -use std::ffi::CString; use std::cmp; use libc::c_uint; use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi}; @@ -136,9 +136,7 @@ pub fn register_static(ccx: &CrateContext, }; unsafe { // Declare a symbol `foo` with the desired linkage. - let buf = CString::new(ident.as_bytes()).unwrap(); - let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), - buf.as_ptr()); + let g1 = declare::declare_global(ccx, &ident[..], llty2); llvm::SetLinkage(g1, linkage); // Declare an internal global `extern_with_linkage_foo` which @@ -149,19 +147,17 @@ pub fn register_static(ccx: &CrateContext, // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); real_name.push_str(&ident); - let real_name = CString::new(real_name).unwrap(); - let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), - real_name.as_ptr()); + let g2 = declare::define_global(ccx, &real_name[..], llty).unwrap_or_else(||{ + ccx.sess().span_fatal(foreign_item.span, + &format!("symbol `{}` is already defined", ident)) + }); llvm::SetLinkage(g2, llvm::InternalLinkage); llvm::LLVMSetInitializer(g2, g1); g2 } } - None => unsafe { - // Generate an external declaration. - let buf = CString::new(ident.as_bytes()).unwrap(); - llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr()) - } + None => // Generate an external declaration. + declare::declare_global(ccx, &ident[..], llty), } } @@ -177,7 +173,7 @@ pub fn get_extern_fn(ccx: &CrateContext, Some(n) => return *n, None => {} } - let f = base::decl_fn(ccx, name, cc, ty, ty::FnConverging(output)); + let f = declare::declare_fn(ccx, name, cc, ty, ty::FnConverging(output)); externs.insert(name.to_string(), f); f } @@ -534,7 +530,8 @@ pub fn decl_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi") }; - let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::FnConverging(ty::mk_nil(ccx.tcx()))); + let llfn = declare::declare_fn(ccx, name, cconv, llfn_ty, + ty::FnConverging(ty::mk_nil(ccx.tcx()))); add_argument_attributes(&tys, llfn); debug!("decl_rust_fn_with_foreign_abi(llfn_ty={}, llfn={})", ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn)); @@ -623,7 +620,9 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.tcx().map.path_to_string(id), id, t.repr(tcx)); - let llfn = base::decl_internal_rust_fn(ccx, t, &ps[..]); + let llfn = declare::define_internal_rust_fn(ccx, &ps[..], t).unwrap_or_else(||{ + ccx.sess().bug(&format!("symbol `{}` already defined", ps)); + }); attributes::from_fn_attrs(ccx, attrs, llfn); base::trans_fn(ccx, decl, body, llfn, param_substs, id, &[]); llfn diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 898d4216e5a6b6addef3209163d538c38880a5e9..abcd2882b173e90e41e4e69dd5409c6c9986d6cc 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -33,6 +33,7 @@ use trans::consts; use trans::datum; use trans::debuginfo::DebugLoc; +use trans::declare; use trans::expr; use trans::foreign; use trans::inline; @@ -184,7 +185,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val // To avoid infinite recursion, don't `make_drop_glue` until after we've // added the entry to the `drop_glues` cache. if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&t) { - let llfn = decl_cdecl_fn(ccx, &old_sym, llfnty, ty::mk_nil(ccx.tcx())); + let llfn = declare::declare_cfn(ccx, &old_sym, llfnty, ty::mk_nil(ccx.tcx())); ccx.drop_glues().borrow_mut().insert(t, llfn); return llfn; }; @@ -294,12 +295,8 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did, &[get_drop_glue_type(ccx, t)], ty::mk_nil(ccx.tcx())); - foreign::get_extern_fn(ccx, - &mut *ccx.externs().borrow_mut(), - &name[..], - llvm::CCallConv, - llty, - dtor_ty) + foreign::get_extern_fn(ccx, &mut *ccx.externs().borrow_mut(), &name[..], llvm::CCallConv, + llty, dtor_ty) } } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 190e44c9674cb5a13d10826aa60156fb15b40adc..e2f965a95fff78f130638f508f322287d2845e2c 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -28,6 +28,7 @@ use trans::consts; use trans::datum::*; use trans::debuginfo::DebugLoc; +use trans::declare; use trans::expr::SaveIn; use trans::expr; use trans::glue; @@ -590,10 +591,10 @@ pub fn trans_object_shim<'a, 'tcx>( // let shim_fn_ty = ty::mk_bare_fn(tcx, None, fty); let method_bare_fn_ty = ty::mk_bare_fn(tcx, None, method_ty); - let function_name = - link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim"); - let llfn = - decl_internal_rust_fn(ccx, shim_fn_ty, &function_name); + 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).unwrap_or_else(||{ + ccx.sess().bug(&format!("symbol `{}` already defined", function_name)); + }); let sig = ty::erase_late_bound_regions(ccx.tcx(), &fty.sig); @@ -756,8 +757,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, C_uint(ccx, align) ].into_iter().chain(methods).collect(); - let vtable = consts::addr_of(ccx, C_struct(ccx, &components, false), - "vtable", trait_ref.def_id().node); + let vtable = consts::addr_of(ccx, C_struct(ccx, &components, false), "vtable"); ccx.vtables().borrow_mut().insert(trait_ref, vtable); vtable diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 0face6860dce533e9250e558c397f6de6b6f7812..7d568ff90ea43cbc0dbfe078f258000fa807b88b 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -43,6 +43,7 @@ mod controlflow; mod datum; mod debuginfo; +mod declare; mod expr; mod foreign; mod glue; diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 862eb31303e4fa9eda58493877e94dc44763a9c3..1c8d020494fabfa0788d0c053d3ea0a37d38c3bb 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -19,9 +19,10 @@ use middle::ty_fold::{TypeFolder, TypeFoldable}; use trans::attributes; use trans::base::{trans_enum_variant, push_ctxt, get_item_val}; -use trans::base::{trans_fn, decl_internal_rust_fn}; +use trans::base::trans_fn; use trans::base; use trans::common::*; +use trans::declare; use trans::foreign; use middle::ty::{self, HasProjectionTypes, Ty}; use util::ppaux::Repr; @@ -143,7 +144,10 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let lldecl = if abi != abi::Rust { foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, &s[..]) } else { - decl_internal_rust_fn(ccx, mono_ty, &s[..]) + // FIXME(nagisa): perhaps needs a more fine grained selection? See setup_lldecl below. + declare::define_internal_rust_fn(ccx, &s[..], mono_ty).unwrap_or_else(||{ + ccx.sess().bug(&format!("symbol `{}` already defined", s)); + }) }; ccx.monomorphized().borrow_mut().insert(hash_id.take().unwrap(), lldecl);