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