]>
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; | |
2c00a5a8 | 21 | use context::CodegenCx; |
5bcae85e | 22 | use declare; |
a7813a04 | 23 | use llvm; |
8bb4bdeb | 24 | use monomorphize::Instance; |
ff7c6d11 | 25 | use type_of::LayoutLlvmExt; |
a7813a04 | 26 | use rustc::hir; |
0531ce1d XL |
27 | use rustc::hir::def::Def; |
28 | use rustc::hir::def_id::DefId; | |
ff7c6d11 | 29 | use rustc::mir::mono::{Linkage, Visibility}; |
2c00a5a8 | 30 | use rustc::ty::TypeFoldable; |
ff7c6d11 | 31 | use rustc::ty::layout::LayoutOf; |
9e0c209e | 32 | use syntax::attr; |
abe05a73 | 33 | use std::fmt; |
a7813a04 | 34 | |
ff7c6d11 | 35 | pub use rustc::mir::mono::MonoItem; |
a7813a04 | 36 | |
ff7c6d11 XL |
37 | pub use rustc_mir::monomorphize::item::*; |
38 | pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt; | |
5bcae85e | 39 | |
ff7c6d11 | 40 | pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { |
2c00a5a8 | 41 | fn define(&self, cx: &CodegenCx<'a, 'tcx>) { |
5bcae85e | 42 | debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}", |
2c00a5a8 | 43 | self.to_string(cx.tcx), |
ea8adc8c | 44 | self.to_raw_string(), |
2c00a5a8 | 45 | cx.codegen_unit.name()); |
5bcae85e | 46 | |
ff7c6d11 | 47 | match *self.as_mono_item() { |
0531ce1d | 48 | MonoItem::Static(def_id) => { |
2c00a5a8 | 49 | let tcx = cx.tcx; |
0531ce1d XL |
50 | let is_mutable = match tcx.describe_def(def_id) { |
51 | Some(Def::Static(_, is_mutable)) => is_mutable, | |
52 | Some(other) => { | |
53 | bug!("Expected Def::Static, found {:?}", other) | |
54 | } | |
55 | None => { | |
56 | bug!("Expected Def::Static for {:?}, found nothing", def_id) | |
57 | } | |
58 | }; | |
59 | let attrs = tcx.get_attrs(def_id); | |
60 | ||
61 | consts::trans_static(&cx, def_id, is_mutable, &attrs); | |
5bcae85e | 62 | } |
ff7c6d11 | 63 | MonoItem::GlobalAsm(node_id) => { |
2c00a5a8 | 64 | let item = cx.tcx.hir.expect_item(node_id); |
cc61c64b | 65 | if let hir::ItemGlobalAsm(ref ga) = item.node { |
2c00a5a8 | 66 | asm::trans_global_asm(cx, ga); |
cc61c64b XL |
67 | } else { |
68 | span_bug!(item.span, "Mismatch between hir::Item type and TransItem type") | |
69 | } | |
70 | } | |
ff7c6d11 | 71 | MonoItem::Fn(instance) => { |
2c00a5a8 | 72 | base::trans_instance(&cx, instance); |
5bcae85e | 73 | } |
5bcae85e SL |
74 | } |
75 | ||
76 | debug!("END IMPLEMENTING '{} ({})' in cgu {}", | |
2c00a5a8 | 77 | self.to_string(cx.tcx), |
5bcae85e | 78 | self.to_raw_string(), |
2c00a5a8 | 79 | cx.codegen_unit.name()); |
5bcae85e SL |
80 | } |
81 | ||
ea8adc8c | 82 | fn predefine(&self, |
2c00a5a8 | 83 | cx: &CodegenCx<'a, 'tcx>, |
ea8adc8c XL |
84 | linkage: Linkage, |
85 | visibility: Visibility) { | |
5bcae85e | 86 | debug!("BEGIN PREDEFINING '{} ({})' in cgu {}", |
2c00a5a8 | 87 | self.to_string(cx.tcx), |
5bcae85e | 88 | self.to_raw_string(), |
2c00a5a8 | 89 | cx.codegen_unit.name()); |
5bcae85e | 90 | |
83c7162d | 91 | let symbol_name = self.symbol_name(cx.tcx).as_str(); |
5bcae85e SL |
92 | |
93 | debug!("symbol {}", &symbol_name); | |
94 | ||
ff7c6d11 | 95 | match *self.as_mono_item() { |
0531ce1d XL |
96 | MonoItem::Static(def_id) => { |
97 | predefine_static(cx, def_id, linkage, visibility, &symbol_name); | |
5bcae85e | 98 | } |
ff7c6d11 | 99 | MonoItem::Fn(instance) => { |
2c00a5a8 | 100 | predefine_fn(cx, instance, linkage, visibility, &symbol_name); |
5bcae85e | 101 | } |
ff7c6d11 | 102 | MonoItem::GlobalAsm(..) => {} |
5bcae85e SL |
103 | } |
104 | ||
105 | debug!("END PREDEFINING '{} ({})' in cgu {}", | |
2c00a5a8 | 106 | self.to_string(cx.tcx), |
5bcae85e | 107 | self.to_raw_string(), |
2c00a5a8 | 108 | cx.codegen_unit.name()); |
7cac9316 XL |
109 | } |
110 | ||
ea8adc8c | 111 | fn to_raw_string(&self) -> String { |
ff7c6d11 XL |
112 | match *self.as_mono_item() { |
113 | MonoItem::Fn(instance) => { | |
5bcae85e SL |
114 | format!("Fn({:?}, {})", |
115 | instance.def, | |
c30ab7b3 | 116 | instance.substs.as_ptr() as usize) |
5bcae85e | 117 | } |
ff7c6d11 | 118 | MonoItem::Static(id) => { |
5bcae85e SL |
119 | format!("Static({:?})", id) |
120 | } | |
ff7c6d11 | 121 | MonoItem::GlobalAsm(id) => { |
cc61c64b XL |
122 | format!("GlobalAsm({:?})", id) |
123 | } | |
5bcae85e SL |
124 | } |
125 | } | |
126 | } | |
127 | ||
ff7c6d11 | 128 | impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {} |
ea8adc8c | 129 | |
2c00a5a8 | 130 | fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, |
0531ce1d | 131 | def_id: DefId, |
ea8adc8c XL |
132 | linkage: Linkage, |
133 | visibility: Visibility, | |
134 | symbol_name: &str) { | |
2c00a5a8 XL |
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); | |
ea8adc8c | 138 | |
2c00a5a8 | 139 | let g = declare::define_global(cx, symbol_name, llty).unwrap_or_else(|| { |
0531ce1d | 140 | cx.sess().span_fatal(cx.tcx.def_span(def_id), |
ea8adc8c XL |
141 | &format!("symbol `{}` is already defined", symbol_name)) |
142 | }); | |
143 | ||
144 | unsafe { | |
145 | llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage)); | |
146 | llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility)); | |
147 | } | |
148 | ||
2c00a5a8 XL |
149 | cx.instances.borrow_mut().insert(instance, g); |
150 | cx.statics.borrow_mut().insert(g, def_id); | |
ea8adc8c XL |
151 | } |
152 | ||
2c00a5a8 | 153 | fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, |
ea8adc8c XL |
154 | instance: Instance<'tcx>, |
155 | linkage: Linkage, | |
156 | visibility: Visibility, | |
157 | symbol_name: &str) { | |
158 | assert!(!instance.substs.needs_infer() && | |
159 | !instance.substs.has_param_types()); | |
160 | ||
2c00a5a8 XL |
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); | |
ea8adc8c | 164 | unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; |
2c00a5a8 | 165 | base::set_link_section(cx, lldecl, &attrs); |
ea8adc8c XL |
166 | if linkage == Linkage::LinkOnceODR || |
167 | linkage == Linkage::WeakODR { | |
2c00a5a8 | 168 | llvm::SetUniqueComdat(cx.llmod, lldecl); |
ea8adc8c XL |
169 | } |
170 | ||
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 && | |
2c00a5a8 | 176 | attr::contains_name(cx.tcx.hir.krate_attrs(), "compiler_builtins") { |
ea8adc8c XL |
177 | unsafe { |
178 | llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden); | |
179 | } | |
180 | } else { | |
181 | unsafe { | |
182 | llvm::LLVMRustSetVisibility(lldecl, base::visibility_to_llvm(visibility)); | |
183 | } | |
184 | } | |
185 | ||
186 | debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance); | |
2c00a5a8 | 187 | if instance.def.is_inline(cx.tcx) { |
ea8adc8c XL |
188 | attributes::inline(lldecl, attributes::InlineAttr::Hint); |
189 | } | |
2c00a5a8 | 190 | attributes::from_fn_attrs(cx, lldecl, instance.def.def_id()); |
ea8adc8c | 191 | |
2c00a5a8 | 192 | cx.instances.borrow_mut().insert(instance, lldecl); |
ea8adc8c | 193 | } |