]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/callee.rs
Unignore u128 test for stage 0,1
[rust.git] / src / librustc_trans / callee.rs
1 // Copyright 2012 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 //! Handles translation of callees as well as other call-related
12 //! things.  Callees are a superset of normal rust values and sometimes
13 //! have different representations.  In particular, top-level fn items
14 //! and methods are represented as just a fn ptr and not a full
15 //! closure.
16
17 pub use self::CalleeData::*;
18
19 use llvm::{self, ValueRef, get_params};
20 use rustc::hir::def_id::DefId;
21 use rustc::ty::subst::Substs;
22 use rustc::traits;
23 use abi::{Abi, FnType};
24 use attributes;
25 use base;
26 use builder::Builder;
27 use common::{self, CrateContext, SharedCrateContext};
28 use cleanup::CleanupScope;
29 use mir::lvalue::LvalueRef;
30 use consts;
31 use declare;
32 use value::Value;
33 use meth;
34 use monomorphize::{self, Instance};
35 use trans_item::TransItem;
36 use type_of;
37 use Disr;
38 use rustc::ty::{self, Ty, TypeFoldable};
39 use rustc::hir;
40 use std::iter;
41
42 use syntax_pos::DUMMY_SP;
43
44 #[derive(Debug)]
45 pub enum CalleeData {
46     /// Constructor for enum variant/tuple-like-struct.
47     NamedTupleConstructor(Disr),
48
49     /// Function pointer.
50     Fn(ValueRef),
51
52     Intrinsic,
53
54     /// Trait object found in the vtable at that index.
55     Virtual(usize)
56 }
57
58 #[derive(Debug)]
59 pub struct Callee<'tcx> {
60     pub data: CalleeData,
61     pub ty: Ty<'tcx>
62 }
63
64 impl<'tcx> Callee<'tcx> {
65     /// Function pointer.
66     pub fn ptr(llfn: ValueRef, ty: Ty<'tcx>) -> Callee<'tcx> {
67         Callee {
68             data: Fn(llfn),
69             ty: ty
70         }
71     }
72
73     /// Function or method definition.
74     pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>)
75                    -> Callee<'tcx> {
76         let tcx = ccx.tcx();
77
78         if let Some(trait_id) = tcx.trait_of_item(def_id) {
79             return Callee::trait_method(ccx, trait_id, def_id, substs);
80         }
81
82         let fn_ty = def_ty(ccx.shared(), def_id, substs);
83         if let ty::TyFnDef(.., f) = fn_ty.sty {
84             if f.abi == Abi::RustIntrinsic || f.abi == Abi::PlatformIntrinsic {
85                 return Callee {
86                     data: Intrinsic,
87                     ty: fn_ty
88                 };
89             }
90         }
91
92         // FIXME(eddyb) Detect ADT constructors more efficiently.
93         if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
94             if let Some(v) = adt_def.variants.iter().find(|v| def_id == v.did) {
95                 return Callee {
96                     data: NamedTupleConstructor(Disr::from(v.disr_val)),
97                     ty: fn_ty
98                 };
99             }
100         }
101
102         let (llfn, ty) = get_fn(ccx, def_id, substs);
103         Callee::ptr(llfn, ty)
104     }
105
106     /// Trait method, which has to be resolved to an impl method.
107     pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
108                             trait_id: DefId,
109                             def_id: DefId,
110                             substs: &'tcx Substs<'tcx>)
111                             -> Callee<'tcx> {
112         let tcx = ccx.tcx();
113
114         let trait_ref = ty::TraitRef::from_method(tcx, trait_id, substs);
115         let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref));
116         match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
117             traits::VtableImpl(vtable_impl) => {
118                 let name = tcx.item_name(def_id);
119                 let (def_id, substs) = traits::find_method(tcx, name, substs, &vtable_impl);
120
121                 // Translate the function, bypassing Callee::def.
122                 // That is because default methods have the same ID as the
123                 // trait method used to look up the impl method that ended
124                 // up here, so calling Callee::def would infinitely recurse.
125                 let (llfn, ty) = get_fn(ccx, def_id, substs);
126                 Callee::ptr(llfn, ty)
127             }
128             traits::VtableClosure(vtable_closure) => {
129                 // The substitutions should have no type parameters remaining
130                 // after passing through fulfill_obligation
131                 let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
132                 let instance = Instance::new(def_id, substs);
133                 let llfn = trans_closure_method(
134                     ccx,
135                     vtable_closure.closure_def_id,
136                     vtable_closure.substs,
137                     instance,
138                     trait_closure_kind);
139
140                 let method_ty = def_ty(ccx.shared(), def_id, substs);
141                 Callee::ptr(llfn, method_ty)
142             }
143             traits::VtableFnPointer(vtable_fn_pointer) => {
144                 let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
145                 let instance = Instance::new(def_id, substs);
146                 let llfn = trans_fn_pointer_shim(ccx, instance,
147                                                  trait_closure_kind,
148                                                  vtable_fn_pointer.fn_ty);
149
150                 let method_ty = def_ty(ccx.shared(), def_id, substs);
151                 Callee::ptr(llfn, method_ty)
152             }
153             traits::VtableObject(ref data) => {
154                 Callee {
155                     data: Virtual(tcx.get_vtable_index_of_object_method(data, def_id)),
156                     ty: def_ty(ccx.shared(), def_id, substs)
157                 }
158             }
159             vtable => {
160                 bug!("resolved vtable bad vtable {:?} in trans", vtable);
161             }
162         }
163     }
164
165     /// Get the abi::FnType for a direct call. Mainly deals with the fact
166     /// that a Virtual call doesn't take the vtable, like its shim does.
167     /// The extra argument types are for variadic (extern "C") functions.
168     pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
169                               extra_args: &[Ty<'tcx>]) -> FnType {
170         let abi = self.ty.fn_abi();
171         let sig = ccx.tcx().erase_late_bound_regions_and_normalize(self.ty.fn_sig());
172         let mut fn_ty = FnType::unadjusted(ccx, abi, &sig, extra_args);
173         if let Virtual(_) = self.data {
174             // Don't pass the vtable, it's not an argument of the virtual fn.
175             fn_ty.args[1].ignore();
176         }
177         fn_ty.adjust_for_abi(ccx, abi, &sig);
178         fn_ty
179     }
180
181     /// Turn the callee into a function pointer.
182     pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
183         match self.data {
184             Fn(llfn) => llfn,
185             Virtual(_) => meth::trans_object_shim(ccx, self),
186             NamedTupleConstructor(disr) => match self.ty.sty {
187                 ty::TyFnDef(def_id, substs, _) => {
188                     let instance = Instance::new(def_id, substs);
189                     if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
190                         return llfn;
191                     }
192
193                     let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
194                                                               TransItem::Fn(instance));
195                     assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
196                     let lldecl = declare::define_internal_fn(ccx, &sym, self.ty);
197                     base::trans_ctor_shim(ccx, def_id, substs, disr, lldecl);
198                     ccx.instances().borrow_mut().insert(instance, lldecl);
199
200                     lldecl
201                 }
202                 _ => bug!("expected fn item type, found {}", self.ty)
203             },
204             Intrinsic => bug!("intrinsic {} getting reified", self.ty)
205         }
206     }
207 }
208
209 /// Given a DefId and some Substs, produces the monomorphic item type.
210 fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
211                     def_id: DefId,
212                     substs: &'tcx Substs<'tcx>)
213                     -> Ty<'tcx> {
214     let ty = shared.tcx().item_type(def_id);
215     monomorphize::apply_param_substs(shared, substs, &ty)
216 }
217
218
219 fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
220                                   def_id: DefId,
221                                   substs: ty::ClosureSubsts<'tcx>,
222                                   method_instance: Instance<'tcx>,
223                                   trait_closure_kind: ty::ClosureKind)
224                                   -> ValueRef
225 {
226     // If this is a closure, redirect to it.
227     let (llfn, _) = get_fn(ccx, def_id, substs.substs);
228
229     // If the closure is a Fn closure, but a FnOnce is needed (etc),
230     // then adapt the self type
231     let llfn_closure_kind = ccx.tcx().closure_kind(def_id);
232
233     debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
234            trait_closure_kind={:?}, llfn={:?})",
235            llfn_closure_kind, trait_closure_kind, Value(llfn));
236
237     match needs_fn_once_adapter_shim(llfn_closure_kind, trait_closure_kind) {
238         Ok(true) => trans_fn_once_adapter_shim(ccx,
239                                                def_id,
240                                                substs,
241                                                method_instance,
242                                                llfn),
243         Ok(false) => llfn,
244         Err(()) => {
245             bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
246                  llfn_closure_kind,
247                  trait_closure_kind);
248         }
249     }
250 }
251
252 pub fn needs_fn_once_adapter_shim(actual_closure_kind: ty::ClosureKind,
253                                   trait_closure_kind: ty::ClosureKind)
254                                   -> Result<bool, ()>
255 {
256     match (actual_closure_kind, trait_closure_kind) {
257         (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
258         (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
259         (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
260             // No adapter needed.
261            Ok(false)
262         }
263         (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
264             // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
265             // `fn(&mut self, ...)`. In fact, at trans time, these are
266             // basically the same thing, so we can just return llfn.
267             Ok(false)
268         }
269         (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
270         (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
271             // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
272             // self, ...)`.  We want a `fn(self, ...)`. We can produce
273             // this by doing something like:
274             //
275             //     fn call_once(self, ...) { call_mut(&self, ...) }
276             //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
277             //
278             // These are both the same at trans time.
279             Ok(true)
280         }
281         _ => Err(()),
282     }
283 }
284
285 fn trans_fn_once_adapter_shim<'a, 'tcx>(
286     ccx: &'a CrateContext<'a, 'tcx>,
287     def_id: DefId,
288     substs: ty::ClosureSubsts<'tcx>,
289     method_instance: Instance<'tcx>,
290     llreffn: ValueRef)
291     -> ValueRef
292 {
293     if let Some(&llfn) = ccx.instances().borrow().get(&method_instance) {
294         return llfn;
295     }
296
297     debug!("trans_fn_once_adapter_shim(def_id={:?}, substs={:?}, llreffn={:?})",
298            def_id, substs, Value(llreffn));
299
300     let tcx = ccx.tcx();
301
302     // Find a version of the closure type. Substitute static for the
303     // region since it doesn't really matter.
304     let closure_ty = tcx.mk_closure_from_closure_substs(def_id, substs);
305     let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty);
306
307     // Make a version with the type of by-ref closure.
308     let ty::ClosureTy { unsafety, abi, mut sig } = tcx.closure_type(def_id, substs);
309     sig.0 = tcx.mk_fn_sig(
310         iter::once(ref_closure_ty).chain(sig.0.inputs().iter().cloned()),
311         sig.0.output(),
312         sig.0.variadic
313     );
314     let llref_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
315         unsafety: unsafety,
316         abi: abi,
317         sig: sig.clone()
318     }));
319     debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
320            llref_fn_ty);
321
322
323     // Make a version of the closure type with the same arguments, but
324     // with argument #0 being by value.
325     assert_eq!(abi, Abi::RustCall);
326     sig.0 = tcx.mk_fn_sig(
327         iter::once(closure_ty).chain(sig.0.inputs().iter().skip(1).cloned()),
328         sig.0.output(),
329         sig.0.variadic
330     );
331
332     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
333     let fn_ty = FnType::new(ccx, abi, &sig, &[]);
334
335     let llonce_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
336         unsafety: unsafety,
337         abi: abi,
338         sig: ty::Binder(sig)
339     }));
340
341     // Create the by-value helper.
342     let function_name = method_instance.symbol_name(ccx.shared());
343     let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
344     attributes::set_frame_pointer_elimination(ccx, lloncefn);
345
346     let orig_fn_ty = fn_ty;
347     let mut bcx = Builder::new_block(ccx, lloncefn, "entry-block");
348
349     let callee = Callee {
350         data: Fn(llreffn),
351         ty: llref_fn_ty
352     };
353
354     // the first argument (`self`) will be the (by value) closure env.
355
356     let mut llargs = get_params(lloncefn);
357     let fn_ret = callee.ty.fn_ret();
358     let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
359     let self_idx = fn_ty.ret.is_indirect() as usize;
360     let env_arg = &orig_fn_ty.args[0];
361     let llenv = if env_arg.is_indirect() {
362         llargs[self_idx]
363     } else {
364         let scratch = bcx.alloca_ty(closure_ty, "self");
365         let mut llarg_idx = self_idx;
366         env_arg.store_fn_arg(&bcx, &mut llarg_idx, scratch);
367         scratch
368     };
369
370     debug!("trans_fn_once_adapter_shim: env={:?}", Value(llenv));
371     // Adjust llargs such that llargs[self_idx..] has the call arguments.
372     // For zero-sized closures that means sneaking in a new argument.
373     if env_arg.is_ignore() {
374         llargs.insert(self_idx, llenv);
375     } else {
376         llargs[self_idx] = llenv;
377     }
378
379     // Call the by-ref closure body with `self` in a cleanup scope,
380     // to drop `self` when the body returns, or in case it unwinds.
381     let self_scope = CleanupScope::schedule_drop_mem(
382         &bcx, LvalueRef::new_sized_ty(llenv, closure_ty)
383     );
384
385     let llfn = callee.reify(bcx.ccx);
386     let llret;
387     if let Some(landing_pad) = self_scope.landing_pad {
388         let normal_bcx = bcx.build_sibling_block("normal-return");
389         llret = bcx.invoke(llfn, &llargs[..], normal_bcx.llbb(), landing_pad, None);
390         bcx = normal_bcx;
391     } else {
392         llret = bcx.call(llfn, &llargs[..], None);
393     }
394     fn_ty.apply_attrs_callsite(llret);
395
396     if fn_ret.0.is_never() {
397         bcx.unreachable();
398     } else {
399         self_scope.trans(&bcx);
400
401         if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
402             bcx.ret_void();
403         } else {
404             bcx.ret(llret);
405         }
406     }
407
408     ccx.instances().borrow_mut().insert(method_instance, lloncefn);
409
410     lloncefn
411 }
412
413 /// Translates an adapter that implements the `Fn` trait for a fn
414 /// pointer. This is basically the equivalent of something like:
415 ///
416 /// ```
417 /// impl<'a> Fn(&'a int) -> &'a int for fn(&int) -> &int {
418 ///     extern "rust-abi" fn call(&self, args: (&'a int,)) -> &'a int {
419 ///         (*self)(args.0)
420 ///     }
421 /// }
422 /// ```
423 ///
424 /// but for the bare function type given.
425 fn trans_fn_pointer_shim<'a, 'tcx>(
426     ccx: &'a CrateContext<'a, 'tcx>,
427     method_instance: Instance<'tcx>,
428     closure_kind: ty::ClosureKind,
429     bare_fn_ty: Ty<'tcx>)
430     -> ValueRef
431 {
432     let tcx = ccx.tcx();
433
434     // Normalize the type for better caching.
435     let bare_fn_ty = tcx.normalize_associated_type(&bare_fn_ty);
436
437     // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
438     let is_by_ref = match closure_kind {
439         ty::ClosureKind::Fn | ty::ClosureKind::FnMut => true,
440         ty::ClosureKind::FnOnce => false,
441     };
442
443     let llfnpointer = match bare_fn_ty.sty {
444         ty::TyFnDef(def_id, substs, _) => {
445             // Function definitions have to be turned into a pointer.
446             let llfn = Callee::def(ccx, def_id, substs).reify(ccx);
447             if !is_by_ref {
448                 // A by-value fn item is ignored, so the shim has
449                 // the same signature as the original function.
450                 return llfn;
451             }
452             Some(llfn)
453         }
454         _ => None
455     };
456
457     let bare_fn_ty_maybe_ref = if is_by_ref {
458         tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), bare_fn_ty)
459     } else {
460         bare_fn_ty
461     };
462
463     // Check if we already trans'd this shim.
464     if let Some(&llval) = ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
465         return llval;
466     }
467
468     debug!("trans_fn_pointer_shim(bare_fn_ty={:?})",
469            bare_fn_ty);
470
471     // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
472     // which is the fn pointer, and `args`, which is the arguments tuple.
473     let sig = match bare_fn_ty.sty {
474         ty::TyFnDef(..,
475                     &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
476                                     abi: Abi::Rust,
477                                     ref sig }) |
478         ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal,
479                                     abi: Abi::Rust,
480                                     ref sig }) => sig,
481
482         _ => {
483             bug!("trans_fn_pointer_shim invoked on invalid type: {}",
484                  bare_fn_ty);
485         }
486     };
487     let sig = tcx.erase_late_bound_regions_and_normalize(sig);
488     let tuple_input_ty = tcx.intern_tup(sig.inputs(), false);
489     let sig = tcx.mk_fn_sig(
490         [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
491         sig.output(),
492         false
493     );
494     let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]);
495     let tuple_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
496         unsafety: hir::Unsafety::Normal,
497         abi: Abi::RustCall,
498         sig: ty::Binder(sig)
499     }));
500     debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
501
502     //
503     let function_name = method_instance.symbol_name(ccx.shared());
504     let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
505     attributes::set_frame_pointer_elimination(ccx, llfn);
506     //
507     let bcx = Builder::new_block(ccx, llfn, "entry-block");
508
509     let mut llargs = get_params(llfn);
510
511     let self_arg = llargs.remove(fn_ty.ret.is_indirect() as usize);
512     let llfnpointer = llfnpointer.unwrap_or_else(|| {
513         // the first argument (`self`) will be ptr to the fn pointer
514         if is_by_ref {
515             bcx.load(self_arg)
516         } else {
517             self_arg
518         }
519     });
520
521     let callee = Callee {
522         data: Fn(llfnpointer),
523         ty: bare_fn_ty
524     };
525     let fn_ret = callee.ty.fn_ret();
526     let fn_ty = callee.direct_fn_type(ccx, &[]);
527     let llret = bcx.call(llfnpointer, &llargs, None);
528     fn_ty.apply_attrs_callsite(llret);
529
530     if fn_ret.0.is_never() {
531         bcx.unreachable();
532     } else {
533         if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
534             bcx.ret_void();
535         } else {
536             bcx.ret(llret);
537         }
538     }
539
540     ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
541
542     llfn
543 }
544
545 /// Translates a reference to a fn/method item, monomorphizing and
546 /// inlining as it goes.
547 ///
548 /// # Parameters
549 ///
550 /// - `ccx`: the crate context
551 /// - `def_id`: def id of the fn or method item being referenced
552 /// - `substs`: values for each of the fn/method's parameters
553 fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
554                     def_id: DefId,
555                     substs: &'tcx Substs<'tcx>)
556                     -> (ValueRef, Ty<'tcx>) {
557     let tcx = ccx.tcx();
558
559     debug!("get_fn(def_id={:?}, substs={:?})", def_id, substs);
560
561     assert!(!substs.needs_infer());
562     assert!(!substs.has_escaping_regions());
563     assert!(!substs.has_param_types());
564
565     let substs = tcx.normalize_associated_type(&substs);
566     let instance = Instance::new(def_id, substs);
567     let item_ty = ccx.tcx().item_type(def_id);
568     let fn_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &item_ty);
569
570     if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
571         return (llfn, fn_ty);
572     }
573
574     let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
575                                               TransItem::Fn(instance));
576     debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
577
578     // This is subtle and surprising, but sometimes we have to bitcast
579     // the resulting fn pointer.  The reason has to do with external
580     // functions.  If you have two crates that both bind the same C
581     // library, they may not use precisely the same types: for
582     // example, they will probably each declare their own structs,
583     // which are distinct types from LLVM's point of view (nominal
584     // types).
585     //
586     // Now, if those two crates are linked into an application, and
587     // they contain inlined code, you can wind up with a situation
588     // where both of those functions wind up being loaded into this
589     // application simultaneously. In that case, the same function
590     // (from LLVM's point of view) requires two types. But of course
591     // LLVM won't allow one function to have two types.
592     //
593     // What we currently do, therefore, is declare the function with
594     // one of the two types (whichever happens to come first) and then
595     // bitcast as needed when the function is referenced to make sure
596     // it has the type we expect.
597     //
598     // This can occur on either a crate-local or crate-external
599     // reference. It also occurs when testing libcore and in some
600     // other weird situations. Annoying.
601
602     // Create a fn pointer with the substituted signature.
603     let fn_ptr_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(common::ty_fn_ty(ccx, fn_ty).into_owned()));
604     let llptrty = type_of::type_of(ccx, fn_ptr_ty);
605
606     let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
607         if common::val_ty(llfn) != llptrty {
608             debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
609             consts::ptrcast(llfn, llptrty)
610         } else {
611             debug!("get_fn: not casting pointer!");
612             llfn
613         }
614     } else {
615         let llfn = declare::declare_fn(ccx, &sym, fn_ty);
616         assert_eq!(common::val_ty(llfn), llptrty);
617         debug!("get_fn: not casting pointer!");
618
619         let attrs = ccx.tcx().get_attrs(def_id);
620         attributes::from_fn_attrs(ccx, &attrs, llfn);
621
622         let is_local_def = ccx.shared().translation_items().borrow()
623                               .contains(&TransItem::Fn(instance));
624         if is_local_def {
625             // FIXME(eddyb) Doubt all extern fn should allow unwinding.
626             attributes::unwind(llfn, true);
627             unsafe {
628                 llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
629             }
630         }
631         if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) {
632             unsafe {
633                 llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
634             }
635         }
636         llfn
637     };
638
639     ccx.instances().borrow_mut().insert(instance, llfn);
640
641     (llfn, fn_ty)
642 }