]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/trans_item.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / librustc_trans / trans_item.rs
CommitLineData
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 17use asm;
5bcae85e
SL
18use attributes;
19use base;
20use consts;
cc61c64b 21use context::CrateContext;
476ff2be 22use common;
5bcae85e 23use declare;
a7813a04 24use llvm;
8bb4bdeb 25use monomorphize::Instance;
a7813a04 26use rustc::hir;
ea8adc8c 27use rustc::middle::trans::{Linkage, Visibility};
abe05a73 28use rustc::ty::{self, TyCtxt, TypeFoldable};
ea8adc8c 29use syntax::ast;
9e0c209e 30use syntax::attr;
7cac9316
XL
31use syntax_pos::Span;
32use syntax_pos::symbol::Symbol;
5bcae85e 33use type_of;
abe05a73 34use std::fmt;
a7813a04 35
ea8adc8c 36pub use rustc::middle::trans::TransItem;
a7813a04 37
abe05a73
XL
38pub use rustc_trans_utils::trans_item::*;
39pub use rustc_trans_utils::trans_item::TransItemExt as BaseTransItemExt;
5bcae85e 40
abe05a73 41pub 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 166impl<'a, 'tcx> TransItemExt<'a, 'tcx> for TransItem<'tcx> {}
ea8adc8c
XL
167
168fn 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
192fn 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}