1 // Copyright 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.
11 //! Walks the crate looking for items/impl-items/trait-items that have
12 //! either a `rustc_symbol_name` or `rustc_item_path` attribute and
13 //! generates an error giving, respectively, the symbol name or
14 //! item-path. This is used for unit testing the code that generates
15 //! paths etc in all kinds of annoying scenarios.
21 use context
::CodegenCx
;
24 use monomorphize
::Instance
;
25 use type_of
::LayoutLlvmExt
;
27 use rustc
::hir
::def
::Def
;
28 use rustc
::hir
::def_id
::DefId
;
29 use rustc
::mir
::mono
::{Linkage, Visibility}
;
30 use rustc
::ty
::TypeFoldable
;
31 use rustc
::ty
::layout
::LayoutOf
;
35 pub use rustc
::mir
::mono
::MonoItem
;
37 pub use rustc_mir
::monomorphize
::item
::*;
38 pub use rustc_mir
::monomorphize
::item
::MonoItemExt
as BaseMonoItemExt
;
40 pub trait MonoItemExt
<'a
, 'tcx
>: fmt
::Debug
+ BaseMonoItemExt
<'a
, 'tcx
> {
41 fn define(&self, cx
: &CodegenCx
<'a
, 'tcx
>) {
42 debug
!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
43 self.to_string(cx
.tcx
),
45 cx
.codegen_unit
.name());
47 match *self.as_mono_item() {
48 MonoItem
::Static(def_id
) => {
50 let is_mutable
= match tcx
.describe_def(def_id
) {
51 Some(Def
::Static(_
, is_mutable
)) => is_mutable
,
53 bug
!("Expected Def::Static, found {:?}", other
)
56 bug
!("Expected Def::Static for {:?}, found nothing", def_id
)
59 let attrs
= tcx
.get_attrs(def_id
);
61 consts
::trans_static(&cx
, def_id
, is_mutable
, &attrs
);
63 MonoItem
::GlobalAsm(node_id
) => {
64 let item
= cx
.tcx
.hir
.expect_item(node_id
);
65 if let hir
::ItemGlobalAsm(ref ga
) = item
.node
{
66 asm
::trans_global_asm(cx
, ga
);
68 span_bug
!(item
.span
, "Mismatch between hir::Item type and TransItem type")
71 MonoItem
::Fn(instance
) => {
72 base
::trans_instance(&cx
, instance
);
76 debug
!("END IMPLEMENTING '{} ({})' in cgu {}",
77 self.to_string(cx
.tcx
),
79 cx
.codegen_unit
.name());
83 cx
: &CodegenCx
<'a
, 'tcx
>,
85 visibility
: Visibility
) {
86 debug
!("BEGIN PREDEFINING '{} ({})' in cgu {}",
87 self.to_string(cx
.tcx
),
89 cx
.codegen_unit
.name());
91 let symbol_name
= self.symbol_name(cx
.tcx
);
93 debug
!("symbol {}", &symbol_name
);
95 match *self.as_mono_item() {
96 MonoItem
::Static(def_id
) => {
97 predefine_static(cx
, def_id
, linkage
, visibility
, &symbol_name
);
99 MonoItem
::Fn(instance
) => {
100 predefine_fn(cx
, instance
, linkage
, visibility
, &symbol_name
);
102 MonoItem
::GlobalAsm(..) => {}
105 debug
!("END PREDEFINING '{} ({})' in cgu {}",
106 self.to_string(cx
.tcx
),
107 self.to_raw_string(),
108 cx
.codegen_unit
.name());
111 fn to_raw_string(&self) -> String
{
112 match *self.as_mono_item() {
113 MonoItem
::Fn(instance
) => {
114 format
!("Fn({:?}, {})",
116 instance
.substs
.as_ptr() as usize)
118 MonoItem
::Static(id
) => {
119 format
!("Static({:?})", id
)
121 MonoItem
::GlobalAsm(id
) => {
122 format
!("GlobalAsm({:?})", id
)
128 impl<'a
, 'tcx
> MonoItemExt
<'a
, 'tcx
> for MonoItem
<'tcx
> {}
130 fn predefine_static
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>,
133 visibility
: Visibility
,
135 let instance
= Instance
::mono(cx
.tcx
, def_id
);
136 let ty
= instance
.ty(cx
.tcx
);
137 let llty
= cx
.layout_of(ty
).llvm_type(cx
);
139 let g
= declare
::define_global(cx
, symbol_name
, llty
).unwrap_or_else(|| {
140 cx
.sess().span_fatal(cx
.tcx
.def_span(def_id
),
141 &format
!("symbol `{}` is already defined", symbol_name
))
145 llvm
::LLVMRustSetLinkage(g
, base
::linkage_to_llvm(linkage
));
146 llvm
::LLVMRustSetVisibility(g
, base
::visibility_to_llvm(visibility
));
149 cx
.instances
.borrow_mut().insert(instance
, g
);
150 cx
.statics
.borrow_mut().insert(g
, def_id
);
153 fn predefine_fn
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>,
154 instance
: Instance
<'tcx
>,
156 visibility
: Visibility
,
158 assert
!(!instance
.substs
.needs_infer() &&
159 !instance
.substs
.has_param_types());
161 let mono_ty
= instance
.ty(cx
.tcx
);
162 let attrs
= instance
.def
.attrs(cx
.tcx
);
163 let lldecl
= declare
::declare_fn(cx
, symbol_name
, mono_ty
);
164 unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }
;
165 base
::set_link_section(cx
, lldecl
, &attrs
);
166 if linkage
== Linkage
::LinkOnceODR
||
167 linkage
== Linkage
::WeakODR
{
168 llvm
::SetUniqueComdat(cx
.llmod
, lldecl
);
171 // If we're compiling the compiler-builtins crate, e.g. the equivalent of
172 // compiler-rt, then we want to implicitly compile everything with hidden
173 // visibility as we're going to link this object all over the place but
174 // don't want the symbols to get exported.
175 if linkage
!= Linkage
::Internal
&& linkage
!= Linkage
::Private
&&
176 attr
::contains_name(cx
.tcx
.hir
.krate_attrs(), "compiler_builtins") {
178 llvm
::LLVMRustSetVisibility(lldecl
, llvm
::Visibility
::Hidden
);
182 llvm
::LLVMRustSetVisibility(lldecl
, base
::visibility_to_llvm(visibility
));
186 debug
!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty
, instance
);
187 if instance
.def
.is_inline(cx
.tcx
) {
188 attributes
::inline(lldecl
, attributes
::InlineAttr
::Hint
);
190 attributes
::from_fn_attrs(cx
, lldecl
, instance
.def
.def_id());
192 cx
.instances
.borrow_mut().insert(instance
, lldecl
);