1 // Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use std::ffi::CString;
16 use trans::attributes;
18 use trans::CrateContext;
20 use trans::type_::Type;
22 const GUARD_PREFIX: &'static str = "__rustc_link_guard_";
24 pub fn link_guard_name(crate_name: &str, crate_svh: &Svh) -> String {
26 let mut guard_name = String::new();
28 guard_name.push_str(GUARD_PREFIX);
29 guard_name.push_str(crate_name);
30 guard_name.push_str("_");
31 guard_name.push_str(crate_svh.as_str());
36 pub fn get_or_insert_link_guard<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>)
39 let guard_name = link_guard_name(&ccx.tcx().crate_name[..],
40 &ccx.link_meta().crate_hash);
42 let guard_function = unsafe {
43 let guard_name_c_string = CString::new(&guard_name[..]).unwrap();
44 llvm::LLVMGetNamedValue(ccx.llmod(), guard_name_c_string.as_ptr())
47 if guard_function != ptr::null_mut() {
48 return guard_function;
51 let llfty = Type::func(&[], &Type::void(ccx));
52 let guard_function = declare::define_cfn(ccx,
55 ccx.tcx().mk_nil()).unwrap_or_else(|| {
56 ccx.sess().bug("Link guard already defined.");
59 attributes::emit_uwtable(guard_function, true);
60 attributes::unwind(guard_function, false);
62 let bld = ccx.raw_builder();
64 let llbb = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(),
66 "link_guard_top\0".as_ptr() as *const _);
67 llvm::LLVMPositionBuilderAtEnd(bld, llbb);
69 for crate_num in ccx.sess().cstore.crates() {
70 if !ccx.sess().cstore.is_explicitly_linked(crate_num) {
74 let crate_name = ccx.sess().cstore.original_crate_name(crate_num);
75 let svh = ccx.sess().cstore.crate_hash(crate_num);
77 let dependency_guard_name = link_guard_name(&crate_name[..], &svh);
79 let decl = declare::declare_cfn(ccx,
80 &dependency_guard_name[..],
83 attributes::unwind(decl, false);
85 llvm::LLVMPositionBuilderAtEnd(bld, llbb);
87 let args: &[llvm::ValueRef] = &[];
88 llvm::LLVMRustBuildCall(bld,
96 llvm::LLVMBuildRetVoid(bld);
102 pub fn insert_reference_to_link_guard<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
103 llbb: llvm::BasicBlockRef) {
104 let guard_function = get_or_insert_link_guard(ccx);
107 llvm::LLVMPositionBuilderAtEnd(ccx.raw_builder(), llbb);
108 let args: &[llvm::ValueRef] = &[];
109 llvm::LLVMRustBuildCall(ccx.raw_builder(),
112 args.len() as c_uint,