]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans_item.rs
Fixes doc important trait display on mobile
[rust.git] / src / librustc_trans / trans_item.rs
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.
4 //
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.
10
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.
16
17 use asm;
18 use attributes;
19 use base;
20 use consts;
21 use context::CrateContext;
22 use common;
23 use declare;
24 use llvm;
25 use monomorphize::Instance;
26 use type_of::LayoutLlvmExt;
27 use rustc::hir;
28 use rustc::middle::trans::{Linkage, Visibility};
29 use rustc::ty::{self, TyCtxt, TypeFoldable};
30 use rustc::ty::layout::LayoutOf;
31 use syntax::ast;
32 use syntax::attr;
33 use syntax_pos::Span;
34 use syntax_pos::symbol::Symbol;
35 use std::fmt;
36
37 pub use rustc::middle::trans::TransItem;
38
39 pub use rustc_trans_utils::trans_item::*;
40 pub use rustc_trans_utils::trans_item::TransItemExt as BaseTransItemExt;
41
42 pub trait TransItemExt<'a, 'tcx>: fmt::Debug + BaseTransItemExt<'a, 'tcx> {
43     fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
44         debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
45                self.to_string(ccx.tcx()),
46                self.to_raw_string(),
47                ccx.codegen_unit().name());
48
49         match *self.as_trans_item() {
50             TransItem::Static(node_id) => {
51                 let tcx = ccx.tcx();
52                 let item = tcx.hir.expect_item(node_id);
53                 if let hir::ItemStatic(_, m, _) = item.node {
54                     match consts::trans_static(&ccx, m, item.id, &item.attrs) {
55                         Ok(_) => { /* Cool, everything's alright. */ },
56                         Err(err) => {
57                             err.report(tcx, item.span, "static");
58                         }
59                     };
60                 } else {
61                     span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
62                 }
63             }
64             TransItem::GlobalAsm(node_id) => {
65                 let item = ccx.tcx().hir.expect_item(node_id);
66                 if let hir::ItemGlobalAsm(ref ga) = item.node {
67                     asm::trans_global_asm(ccx, ga);
68                 } else {
69                     span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
70                 }
71             }
72             TransItem::Fn(instance) => {
73                 base::trans_instance(&ccx, instance);
74             }
75         }
76
77         debug!("END IMPLEMENTING '{} ({})' in cgu {}",
78                self.to_string(ccx.tcx()),
79                self.to_raw_string(),
80                ccx.codegen_unit().name());
81     }
82
83     fn predefine(&self,
84                  ccx: &CrateContext<'a, 'tcx>,
85                  linkage: Linkage,
86                  visibility: Visibility) {
87         debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
88                self.to_string(ccx.tcx()),
89                self.to_raw_string(),
90                ccx.codegen_unit().name());
91
92         let symbol_name = self.symbol_name(ccx.tcx());
93
94         debug!("symbol {}", &symbol_name);
95
96         match *self.as_trans_item() {
97             TransItem::Static(node_id) => {
98                 predefine_static(ccx, node_id, linkage, visibility, &symbol_name);
99             }
100             TransItem::Fn(instance) => {
101                 predefine_fn(ccx, instance, linkage, visibility, &symbol_name);
102             }
103             TransItem::GlobalAsm(..) => {}
104         }
105
106         debug!("END PREDEFINING '{} ({})' in cgu {}",
107                self.to_string(ccx.tcx()),
108                self.to_raw_string(),
109                ccx.codegen_unit().name());
110     }
111
112     fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
113         match *self.as_trans_item() {
114             TransItem::Fn(instance) => tcx.symbol_name(instance),
115             TransItem::Static(node_id) => {
116                 let def_id = tcx.hir.local_def_id(node_id);
117                 tcx.symbol_name(Instance::mono(tcx, def_id))
118             }
119             TransItem::GlobalAsm(node_id) => {
120                 let def_id = tcx.hir.local_def_id(node_id);
121                 ty::SymbolName {
122                     name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_str()
123                 }
124             }
125         }
126     }
127
128     fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
129         match *self.as_trans_item() {
130             TransItem::Fn(Instance { def, .. }) => {
131                 tcx.hir.as_local_node_id(def.def_id())
132             }
133             TransItem::Static(node_id) |
134             TransItem::GlobalAsm(node_id) => {
135                 Some(node_id)
136             }
137         }.map(|node_id| tcx.hir.span(node_id))
138     }
139
140     fn is_generic_fn(&self) -> bool {
141         match *self.as_trans_item() {
142             TransItem::Fn(ref instance) => {
143                 instance.substs.types().next().is_some()
144             }
145             TransItem::Static(..) |
146             TransItem::GlobalAsm(..) => false,
147         }
148     }
149
150     fn to_raw_string(&self) -> String {
151         match *self.as_trans_item() {
152             TransItem::Fn(instance) => {
153                 format!("Fn({:?}, {})",
154                          instance.def,
155                          instance.substs.as_ptr() as usize)
156             }
157             TransItem::Static(id) => {
158                 format!("Static({:?})", id)
159             }
160             TransItem::GlobalAsm(id) => {
161                 format!("GlobalAsm({:?})", id)
162             }
163         }
164     }
165 }
166
167 impl<'a, 'tcx> TransItemExt<'a, 'tcx> for TransItem<'tcx> {}
168
169 fn predefine_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
170                               node_id: ast::NodeId,
171                               linkage: Linkage,
172                               visibility: Visibility,
173                               symbol_name: &str) {
174     let def_id = ccx.tcx().hir.local_def_id(node_id);
175     let instance = Instance::mono(ccx.tcx(), def_id);
176     let ty = common::instance_ty(ccx.tcx(), &instance);
177     let llty = ccx.layout_of(ty).llvm_type(ccx);
178
179     let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
180         ccx.sess().span_fatal(ccx.tcx().hir.span(node_id),
181             &format!("symbol `{}` is already defined", symbol_name))
182     });
183
184     unsafe {
185         llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
186         llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
187     }
188
189     ccx.instances().borrow_mut().insert(instance, g);
190     ccx.statics().borrow_mut().insert(g, def_id);
191 }
192
193 fn predefine_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
194                           instance: Instance<'tcx>,
195                           linkage: Linkage,
196                           visibility: Visibility,
197                           symbol_name: &str) {
198     assert!(!instance.substs.needs_infer() &&
199             !instance.substs.has_param_types());
200
201     let mono_ty = common::instance_ty(ccx.tcx(), &instance);
202     let attrs = instance.def.attrs(ccx.tcx());
203     let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
204     unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
205     base::set_link_section(ccx, lldecl, &attrs);
206     if linkage == Linkage::LinkOnceODR ||
207         linkage == Linkage::WeakODR {
208         llvm::SetUniqueComdat(ccx.llmod(), lldecl);
209     }
210
211     // If we're compiling the compiler-builtins crate, e.g. the equivalent of
212     // compiler-rt, then we want to implicitly compile everything with hidden
213     // visibility as we're going to link this object all over the place but
214     // don't want the symbols to get exported.
215     if linkage != Linkage::Internal && linkage != Linkage::Private &&
216        attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") {
217         unsafe {
218             llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
219         }
220     } else {
221         unsafe {
222             llvm::LLVMRustSetVisibility(lldecl, base::visibility_to_llvm(visibility));
223         }
224     }
225
226     debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
227     if common::is_inline_instance(ccx.tcx(), &instance) {
228         attributes::inline(lldecl, attributes::InlineAttr::Hint);
229     }
230     attributes::from_fn_attrs(ccx, &attrs, lldecl);
231
232     ccx.instances().borrow_mut().insert(instance, lldecl);
233 }