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