]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2014 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 | use back::link::exported_name; | |
1a4d82fc JJ |
12 | use llvm::ValueRef; |
13 | use llvm; | |
e9174d1e SL |
14 | use middle::def_id::DefId; |
15 | use middle::infer::normalize_associated_type; | |
1a4d82fc JJ |
16 | use middle::subst; |
17 | use middle::subst::{Subst, Substs}; | |
e9174d1e | 18 | use middle::ty::fold::{TypeFolder, TypeFoldable}; |
9346a6ac | 19 | use trans::attributes; |
1a4d82fc | 20 | use trans::base::{trans_enum_variant, push_ctxt, get_item_val}; |
9346a6ac | 21 | use trans::base::trans_fn; |
1a4d82fc JJ |
22 | use trans::base; |
23 | use trans::common::*; | |
9346a6ac | 24 | use trans::declare; |
1a4d82fc | 25 | use trans::foreign; |
9cc50fc6 SL |
26 | use middle::ty::{self, Ty}; |
27 | use trans::Disr; | |
e9174d1e SL |
28 | use rustc::front::map as hir_map; |
29 | ||
30 | use rustc_front::hir; | |
1a4d82fc | 31 | |
7453a54e | 32 | use syntax::abi::Abi; |
1a4d82fc | 33 | use syntax::ast; |
b039eaaf | 34 | use syntax::attr; |
9cc50fc6 | 35 | use syntax::errors; |
1a4d82fc JJ |
36 | use std::hash::{Hasher, Hash, SipHasher}; |
37 | ||
38 | pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, | |
e9174d1e | 39 | fn_id: DefId, |
85aaf69f | 40 | psubsts: &'tcx subst::Substs<'tcx>, |
1a4d82fc | 41 | ref_id: Option<ast::NodeId>) |
b039eaaf | 42 | -> (ValueRef, Ty<'tcx>, bool) { |
1a4d82fc | 43 | debug!("monomorphic_fn(\ |
62682a34 SL |
44 | fn_id={:?}, \ |
45 | real_substs={:?}, \ | |
1a4d82fc | 46 | ref_id={:?})", |
62682a34 SL |
47 | fn_id, |
48 | psubsts, | |
1a4d82fc JJ |
49 | ref_id); |
50 | ||
c1a9b12d | 51 | assert!(!psubsts.types.needs_infer() && !psubsts.types.has_param_types()); |
1a4d82fc | 52 | |
b039eaaf SL |
53 | // we can only monomorphize things in this crate (or inlined into it) |
54 | let fn_node_id = ccx.tcx().map.as_local_node_id(fn_id).unwrap(); | |
55 | ||
1a4d82fc JJ |
56 | let _icx = push_ctxt("monomorphic_fn"); |
57 | ||
58 | let hash_id = MonoId { | |
59 | def: fn_id, | |
85aaf69f | 60 | params: &psubsts.types |
1a4d82fc JJ |
61 | }; |
62 | ||
c1a9b12d | 63 | let item_ty = ccx.tcx().lookup_item_type(fn_id).ty; |
62682a34 SL |
64 | |
65 | debug!("monomorphic_fn about to subst into {:?}", item_ty); | |
c1a9b12d SL |
66 | let mono_ty = apply_param_substs(ccx.tcx(), psubsts, &item_ty); |
67 | debug!("mono_ty = {:?} (post-substitution)", mono_ty); | |
1a4d82fc JJ |
68 | |
69 | match ccx.monomorphized().borrow().get(&hash_id) { | |
70 | Some(&val) => { | |
71 | debug!("leaving monomorphic fn {}", | |
c1a9b12d | 72 | ccx.tcx().item_path_str(fn_id)); |
1a4d82fc JJ |
73 | return (val, mono_ty, false); |
74 | } | |
75 | None => () | |
76 | } | |
77 | ||
78 | debug!("monomorphic_fn(\ | |
62682a34 SL |
79 | fn_id={:?}, \ |
80 | psubsts={:?}, \ | |
1a4d82fc | 81 | hash_id={:?})", |
62682a34 SL |
82 | fn_id, |
83 | psubsts, | |
1a4d82fc JJ |
84 | hash_id); |
85 | ||
86 | ||
9cc50fc6 SL |
87 | let map_node = errors::expect( |
88 | ccx.sess().diagnostic(), | |
b039eaaf | 89 | ccx.tcx().map.find(fn_node_id), |
1a4d82fc JJ |
90 | || { |
91 | format!("while monomorphizing {:?}, couldn't find it in \ | |
92 | the item map (may have attempted to monomorphize \ | |
93 | an item defined in a different crate?)", | |
94 | fn_id) | |
95 | }); | |
96 | ||
e9174d1e | 97 | if let hir_map::NodeForeignItem(_) = map_node { |
b039eaaf | 98 | let abi = ccx.tcx().map.get_foreign_abi(fn_node_id); |
7453a54e | 99 | if abi != Abi::RustIntrinsic && abi != Abi::PlatformIntrinsic { |
1a4d82fc | 100 | // Foreign externs don't have to be monomorphized. |
b039eaaf | 101 | return (get_item_val(ccx, fn_node_id), mono_ty, true); |
1a4d82fc JJ |
102 | } |
103 | } | |
104 | ||
1a4d82fc JJ |
105 | ccx.stats().n_monos.set(ccx.stats().n_monos.get() + 1); |
106 | ||
107 | let depth; | |
108 | { | |
109 | let mut monomorphizing = ccx.monomorphizing().borrow_mut(); | |
110 | depth = match monomorphizing.get(&fn_id) { | |
111 | Some(&d) => d, None => 0 | |
112 | }; | |
113 | ||
b039eaaf SL |
114 | debug!("monomorphic_fn: depth for fn_id={:?} is {:?}", fn_id, depth+1); |
115 | ||
1a4d82fc JJ |
116 | // Random cut-off -- code that needs to instantiate the same function |
117 | // recursively more than thirty times can probably safely be assumed | |
118 | // to be causing an infinite expansion. | |
119 | if depth > ccx.sess().recursion_limit.get() { | |
b039eaaf | 120 | ccx.sess().span_fatal(ccx.tcx().map.span(fn_node_id), |
1a4d82fc JJ |
121 | "reached the recursion limit during monomorphization"); |
122 | } | |
123 | ||
124 | monomorphizing.insert(fn_id, depth + 1); | |
125 | } | |
126 | ||
127 | let hash; | |
128 | let s = { | |
129 | let mut state = SipHasher::new(); | |
130 | hash_id.hash(&mut state); | |
131 | mono_ty.hash(&mut state); | |
132 | ||
133 | hash = format!("h{}", state.finish()); | |
b039eaaf SL |
134 | let path = ccx.tcx().map.def_path_from_id(fn_node_id); |
135 | exported_name(path, &hash[..]) | |
1a4d82fc JJ |
136 | }; |
137 | ||
138 | debug!("monomorphize_fn mangled to {}", s); | |
139 | ||
140 | // This shouldn't need to option dance. | |
141 | let mut hash_id = Some(hash_id); | |
7453a54e SL |
142 | let mut mk_lldecl = |abi: Abi| { |
143 | let lldecl = if abi != Abi::Rust { | |
b039eaaf | 144 | foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, &s) |
1a4d82fc | 145 | } else { |
c1a9b12d SL |
146 | // FIXME(nagisa): perhaps needs a more fine grained selection? See |
147 | // setup_lldecl below. | |
148 | declare::define_internal_rust_fn(ccx, &s, mono_ty) | |
1a4d82fc JJ |
149 | }; |
150 | ||
151 | ccx.monomorphized().borrow_mut().insert(hash_id.take().unwrap(), lldecl); | |
152 | lldecl | |
153 | }; | |
b039eaaf | 154 | let setup_lldecl = |lldecl, attrs: &[ast::Attribute]| { |
1a4d82fc | 155 | base::update_linkage(ccx, lldecl, None, base::OriginalTranslation); |
9346a6ac | 156 | attributes::from_fn_attrs(ccx, attrs, lldecl); |
1a4d82fc JJ |
157 | |
158 | let is_first = !ccx.available_monomorphizations().borrow().contains(&s); | |
159 | if is_first { | |
160 | ccx.available_monomorphizations().borrow_mut().insert(s.clone()); | |
161 | } | |
162 | ||
163 | let trans_everywhere = attr::requests_inline(attrs); | |
164 | if trans_everywhere && !is_first { | |
165 | llvm::SetLinkage(lldecl, llvm::AvailableExternallyLinkage); | |
166 | } | |
167 | ||
168 | // If `true`, then `lldecl` should be given a function body. | |
169 | // Otherwise, it should be left as a declaration of an external | |
170 | // function, with no definition in the current compilation unit. | |
171 | trans_everywhere || is_first | |
172 | }; | |
173 | ||
174 | let lldecl = match map_node { | |
e9174d1e | 175 | hir_map::NodeItem(i) => { |
1a4d82fc | 176 | match *i { |
e9174d1e SL |
177 | hir::Item { |
178 | node: hir::ItemFn(ref decl, _, _, abi, _, ref body), | |
1a4d82fc JJ |
179 | .. |
180 | } => { | |
181 | let d = mk_lldecl(abi); | |
c34b1796 | 182 | let needs_body = setup_lldecl(d, &i.attrs); |
1a4d82fc | 183 | if needs_body { |
7453a54e | 184 | if abi != Abi::Rust { |
1a4d82fc | 185 | foreign::trans_rust_fn_with_foreign_abi( |
7453a54e | 186 | ccx, &decl, &body, &[], d, psubsts, fn_node_id, |
85aaf69f | 187 | Some(&hash[..])); |
1a4d82fc | 188 | } else { |
9cc50fc6 | 189 | trans_fn(ccx, |
7453a54e SL |
190 | &decl, |
191 | &body, | |
9cc50fc6 SL |
192 | d, |
193 | psubsts, | |
194 | fn_node_id, | |
195 | &i.attrs); | |
1a4d82fc JJ |
196 | } |
197 | } | |
198 | ||
199 | d | |
200 | } | |
201 | _ => { | |
202 | ccx.sess().bug("Can't monomorphize this kind of item") | |
203 | } | |
204 | } | |
205 | } | |
e9174d1e | 206 | hir_map::NodeVariant(v) => { |
b039eaaf SL |
207 | let variant = inlined_variant_def(ccx, fn_node_id); |
208 | assert_eq!(v.node.name, variant.name); | |
7453a54e | 209 | let d = mk_lldecl(Abi::Rust); |
9346a6ac | 210 | attributes::inline(d, attributes::InlineAttr::Hint); |
9cc50fc6 | 211 | trans_enum_variant(ccx, fn_node_id, Disr::from(variant.disr_val), psubsts, d); |
1a4d82fc JJ |
212 | d |
213 | } | |
e9174d1e | 214 | hir_map::NodeImplItem(impl_item) => { |
c34b1796 | 215 | match impl_item.node { |
92a42be0 | 216 | hir::ImplItemKind::Method(ref sig, ref body) => { |
7453a54e | 217 | let d = mk_lldecl(Abi::Rust); |
c34b1796 | 218 | let needs_body = setup_lldecl(d, &impl_item.attrs); |
1a4d82fc JJ |
219 | if needs_body { |
220 | trans_fn(ccx, | |
c34b1796 AL |
221 | &sig.decl, |
222 | body, | |
1a4d82fc JJ |
223 | d, |
224 | psubsts, | |
c34b1796 | 225 | impl_item.id, |
9cc50fc6 | 226 | &impl_item.attrs); |
1a4d82fc JJ |
227 | } |
228 | d | |
229 | } | |
d9579d0f AL |
230 | _ => { |
231 | ccx.sess().bug(&format!("can't monomorphize a {:?}", | |
232 | map_node)) | |
c34b1796 | 233 | } |
1a4d82fc JJ |
234 | } |
235 | } | |
e9174d1e | 236 | hir_map::NodeTraitItem(trait_item) => { |
c34b1796 | 237 | match trait_item.node { |
e9174d1e | 238 | hir::MethodTraitItem(ref sig, Some(ref body)) => { |
7453a54e | 239 | let d = mk_lldecl(Abi::Rust); |
c34b1796 | 240 | let needs_body = setup_lldecl(d, &trait_item.attrs); |
1a4d82fc | 241 | if needs_body { |
9cc50fc6 SL |
242 | trans_fn(ccx, |
243 | &sig.decl, | |
244 | body, | |
245 | d, | |
246 | psubsts, | |
247 | trait_item.id, | |
248 | &trait_item.attrs); | |
1a4d82fc JJ |
249 | } |
250 | d | |
251 | } | |
252 | _ => { | |
253 | ccx.sess().bug(&format!("can't monomorphize a {:?}", | |
c34b1796 | 254 | map_node)) |
1a4d82fc JJ |
255 | } |
256 | } | |
257 | } | |
e9174d1e | 258 | hir_map::NodeStructCtor(struct_def) => { |
7453a54e | 259 | let d = mk_lldecl(Abi::Rust); |
9346a6ac | 260 | attributes::inline(d, attributes::InlineAttr::Hint); |
b039eaaf SL |
261 | if struct_def.is_struct() { |
262 | panic!("ast-mapped struct didn't have a ctor id") | |
263 | } | |
1a4d82fc | 264 | base::trans_tuple_struct(ccx, |
b039eaaf | 265 | struct_def.id(), |
1a4d82fc JJ |
266 | psubsts, |
267 | d); | |
268 | d | |
269 | } | |
270 | ||
271 | // Ugh -- but this ensures any new variants won't be forgotten | |
e9174d1e SL |
272 | hir_map::NodeForeignItem(..) | |
273 | hir_map::NodeLifetime(..) | | |
274 | hir_map::NodeTyParam(..) | | |
275 | hir_map::NodeExpr(..) | | |
276 | hir_map::NodeStmt(..) | | |
e9174d1e SL |
277 | hir_map::NodeBlock(..) | |
278 | hir_map::NodePat(..) | | |
279 | hir_map::NodeLocal(..) => { | |
1a4d82fc | 280 | ccx.sess().bug(&format!("can't monomorphize a {:?}", |
c34b1796 | 281 | map_node)) |
1a4d82fc JJ |
282 | } |
283 | }; | |
284 | ||
285 | ccx.monomorphizing().borrow_mut().insert(fn_id, depth); | |
286 | ||
c1a9b12d | 287 | debug!("leaving monomorphic fn {}", ccx.tcx().item_path_str(fn_id)); |
1a4d82fc JJ |
288 | (lldecl, mono_ty, true) |
289 | } | |
290 | ||
85aaf69f | 291 | #[derive(PartialEq, Eq, Hash, Debug)] |
1a4d82fc | 292 | pub struct MonoId<'tcx> { |
e9174d1e | 293 | pub def: DefId, |
85aaf69f | 294 | pub params: &'tcx subst::VecPerParamSpace<Ty<'tcx>> |
1a4d82fc JJ |
295 | } |
296 | ||
297 | /// Monomorphizes a type from the AST by first applying the in-scope | |
298 | /// substitutions and then normalizing any associated types. | |
299 | pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>, | |
300 | param_substs: &Substs<'tcx>, | |
301 | value: &T) | |
302 | -> T | |
9cc50fc6 | 303 | where T : TypeFoldable<'tcx> |
1a4d82fc JJ |
304 | { |
305 | let substituted = value.subst(tcx, param_substs); | |
306 | normalize_associated_type(tcx, &substituted) | |
307 | } | |
308 | ||
c1a9b12d | 309 | |
e9174d1e SL |
310 | /// Returns the normalized type of a struct field |
311 | pub fn field_ty<'tcx>(tcx: &ty::ctxt<'tcx>, | |
312 | param_substs: &Substs<'tcx>, | |
313 | f: ty::FieldDef<'tcx>) | |
314 | -> Ty<'tcx> | |
315 | { | |
316 | normalize_associated_type(tcx, &f.ty(tcx, param_substs)) | |
1a4d82fc | 317 | } |