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 if declare::get_defined_value(ccx, &guard_name[..]).is_some() {
54 &format!("Link guard already defined"));
56 let guard_function = declare::declare_cfn(ccx, &guard_name[..], llfty);
58 attributes::emit_uwtable(guard_function, true);
59 attributes::unwind(guard_function, false);
61 let bld = ccx.raw_builder();
63 let llbb = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(),
65 "link_guard_top\0".as_ptr() as *const _);
66 llvm::LLVMPositionBuilderAtEnd(bld, llbb);
68 for crate_num in ccx.sess().cstore.crates() {
69 if !ccx.sess().cstore.is_explicitly_linked(crate_num) {
73 let crate_name = ccx.sess().cstore.original_crate_name(crate_num);
74 let svh = ccx.sess().cstore.crate_hash(crate_num);
76 let dependency_guard_name = link_guard_name(&crate_name[..], &svh);
78 if declare::get_defined_value(ccx, &dependency_guard_name[..]).is_some() {
80 &format!("Link guard already defined for dependency `{}`",
83 let decl = declare::declare_cfn(ccx, &dependency_guard_name[..], llfty);
84 attributes::unwind(decl, false);
86 llvm::LLVMPositionBuilderAtEnd(bld, llbb);
88 let args: &[llvm::ValueRef] = &[];
89 llvm::LLVMRustBuildCall(bld,
97 llvm::LLVMBuildRetVoid(bld);
103 pub fn insert_reference_to_link_guard<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
104 llbb: llvm::BasicBlockRef) {
105 let guard_function = get_or_insert_link_guard(ccx);
108 llvm::LLVMPositionBuilderAtEnd(ccx.raw_builder(), llbb);
109 let args: &[llvm::ValueRef] = &[];
110 llvm::LLVMRustBuildCall(ccx.raw_builder(),
113 args.len() as c_uint,