3 use crate::context
::CodegenCx
;
5 use crate::type_of
::LayoutLlvmExt
;
6 use rustc_codegen_ssa
::traits
::*;
7 use rustc_hir
::def_id
::{DefId, LOCAL_CRATE}
;
8 pub use rustc_middle
::mir
::mono
::MonoItem
;
9 use rustc_middle
::mir
::mono
::{Linkage, Visibility}
;
10 use rustc_middle
::ty
::layout
::{FnAbiOf, LayoutOf}
;
11 use rustc_middle
::ty
::{self, Instance, TypeVisitable}
;
12 use rustc_session
::config
::CrateType
;
13 use rustc_target
::spec
::RelocModel
;
15 impl<'tcx
> PreDefineMethods
<'tcx
> for CodegenCx
<'_
, 'tcx
> {
20 visibility
: Visibility
,
23 let instance
= Instance
::mono(self.tcx
, def_id
);
24 let ty
= instance
.ty(self.tcx
, ty
::ParamEnv
::reveal_all());
25 let llty
= self.layout_of(ty
).llvm_type(self);
27 let g
= self.define_global(symbol_name
, llty
).unwrap_or_else(|| {
28 self.sess().span_fatal(
29 self.tcx
.def_span(def_id
),
30 &format
!("symbol `{}` is already defined", symbol_name
),
35 llvm
::LLVMRustSetLinkage(g
, base
::linkage_to_llvm(linkage
));
36 llvm
::LLVMRustSetVisibility(g
, base
::visibility_to_llvm(visibility
));
37 if self.should_assume_dso_local(g
, false) {
38 llvm
::LLVMRustSetDSOLocal(g
, true);
42 self.instances
.borrow_mut().insert(instance
, g
);
47 instance
: Instance
<'tcx
>,
49 visibility
: Visibility
,
52 assert
!(!instance
.substs
.needs_infer());
54 let fn_abi
= self.fn_abi_of_instance(instance
, ty
::List
::empty());
55 let lldecl
= self.declare_fn(symbol_name
, fn_abi
);
56 unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }
;
57 let attrs
= self.tcx
.codegen_fn_attrs(instance
.def_id());
58 base
::set_link_section(lldecl
, attrs
);
59 if linkage
== Linkage
::LinkOnceODR
|| linkage
== Linkage
::WeakODR
{
60 llvm
::SetUniqueComdat(self.llmod
, lldecl
);
63 // If we're compiling the compiler-builtins crate, e.g., the equivalent of
64 // compiler-rt, then we want to implicitly compile everything with hidden
65 // visibility as we're going to link this object all over the place but
66 // don't want the symbols to get exported.
67 if linkage
!= Linkage
::Internal
68 && linkage
!= Linkage
::Private
69 && self.tcx
.is_compiler_builtins(LOCAL_CRATE
)
72 llvm
::LLVMRustSetVisibility(lldecl
, llvm
::Visibility
::Hidden
);
76 llvm
::LLVMRustSetVisibility(lldecl
, base
::visibility_to_llvm(visibility
));
80 debug
!("predefine_fn: instance = {:?}", instance
);
82 attributes
::from_fn_attrs(self, lldecl
, instance
);
85 if self.should_assume_dso_local(lldecl
, false) {
86 llvm
::LLVMRustSetDSOLocal(lldecl
, true);
90 self.instances
.borrow_mut().insert(instance
, lldecl
);
94 impl CodegenCx
<'_
, '_
> {
95 /// Whether a definition or declaration can be assumed to be local to a group of
96 /// libraries that form a single DSO or executable.
97 pub(crate) unsafe fn should_assume_dso_local(
100 is_declaration
: bool
,
102 let linkage
= llvm
::LLVMRustGetLinkage(llval
);
103 let visibility
= llvm
::LLVMRustGetVisibility(llval
);
105 if matches
!(linkage
, llvm
::Linkage
::InternalLinkage
| llvm
::Linkage
::PrivateLinkage
) {
109 if visibility
!= llvm
::Visibility
::Default
&& linkage
!= llvm
::Linkage
::ExternalWeakLinkage
114 // Symbols from executables can't really be imported any further.
115 let all_exe
= self.tcx
.sess
.crate_types().iter().all(|ty
| *ty
== CrateType
::Executable
);
116 let is_declaration_for_linker
=
117 is_declaration
|| linkage
== llvm
::Linkage
::AvailableExternallyLinkage
;
118 if all_exe
&& !is_declaration_for_linker
{
122 // PowerPC64 prefers TOC indirection to avoid copy relocations.
123 if matches
!(&*self.tcx
.sess
.target
.arch
, "powerpc64" | "powerpc64le") {
127 // Thread-local variables generally don't support copy relocations.
128 let is_thread_local_var
= llvm
::LLVMIsAGlobalVariable(llval
)
129 .map(|v
| llvm
::LLVMIsThreadLocal(v
) == llvm
::True
)
131 if is_thread_local_var
{
135 // Match clang by only supporting COFF and ELF for now.
136 if self.tcx
.sess
.target
.is_like_osx
{
140 // Static relocation model should force copy relocations everywhere.
141 if self.tcx
.sess
.relocation_model() == RelocModel
::Static
{
145 // With pie relocation model calls of functions defined in the translation
146 // unit can use copy relocations.
147 self.tcx
.sess
.relocation_model() == RelocModel
::Pie
&& !is_declaration