]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/callee.rs
Changed issue number to 36105
[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 pub use self::CallArgs::*;
19
20 use arena::TypedArena;
21 use back::symbol_names;
22 use llvm::{self, ValueRef, get_params};
23 use middle::cstore::LOCAL_CRATE;
24 use rustc::hir::def_id::DefId;
25 use rustc::ty::subst::Substs;
26 use rustc::traits;
27 use rustc::hir::map as hir_map;
28 use abi::{Abi, FnType};
29 use adt;
30 use attributes;
31 use base;
32 use base::*;
33 use build::*;
34 use cleanup;
35 use cleanup::CleanupMethods;
36 use closure;
37 use common::{self, Block, Result, CrateContext, FunctionContext, C_undef};
38 use consts;
39 use datum::*;
40 use debuginfo::DebugLoc;
41 use declare;
42 use expr;
43 use glue;
44 use inline;
45 use intrinsic;
46 use machine::llalign_of_min;
47 use meth;
48 use monomorphize::{self, Instance};
49 use trans_item::TransItem;
50 use type_::Type;
51 use type_of;
52 use value::Value;
53 use Disr;
54 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
55 use rustc::hir;
56
57 use syntax_pos::DUMMY_SP;
58 use errors;
59 use syntax::ptr::P;
60
61 #[derive(Debug)]
62 pub enum CalleeData {
63     /// Constructor for enum variant/tuple-like-struct.
64     NamedTupleConstructor(Disr),
65
66     /// Function pointer.
67     Fn(ValueRef),
68
69     Intrinsic,
70
71     /// Trait object found in the vtable at that index.
72     Virtual(usize)
73 }
74
75 #[derive(Debug)]
76 pub struct Callee<'tcx> {
77     pub data: CalleeData,
78     pub ty: Ty<'tcx>
79 }
80
81 impl<'tcx> Callee<'tcx> {
82     /// Function pointer.
83     pub fn ptr(datum: Datum<'tcx, Rvalue>) -> Callee<'tcx> {
84         Callee {
85             data: Fn(datum.val),
86             ty: datum.ty
87         }
88     }
89
90     /// Trait or impl method call.
91     pub fn method_call<'blk>(bcx: Block<'blk, 'tcx>,
92                              method_call: ty::MethodCall)
93                              -> Callee<'tcx> {
94         let method = bcx.tcx().tables.borrow().method_map[&method_call];
95         Callee::method(bcx, method)
96     }
97
98     /// Trait or impl method.
99     pub fn method<'blk>(bcx: Block<'blk, 'tcx>,
100                         method: ty::MethodCallee<'tcx>) -> Callee<'tcx> {
101         let substs = bcx.fcx.monomorphize(&method.substs);
102         Callee::def(bcx.ccx(), method.def_id, substs)
103     }
104
105     /// Function or method definition.
106     pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>,
107                    def_id: DefId,
108                    substs: &'tcx Substs<'tcx>)
109                    -> Callee<'tcx> {
110         let tcx = ccx.tcx();
111
112         if let Some(trait_id) = tcx.trait_of_item(def_id) {
113             return Callee::trait_method(ccx, trait_id, def_id, substs);
114         }
115
116         let maybe_node_id = inline::get_local_instance(ccx, def_id)
117             .and_then(|def_id| tcx.map.as_local_node_id(def_id));
118         let maybe_ast_node = maybe_node_id.and_then(|node_id| {
119             tcx.map.find(node_id)
120         });
121
122         let data = match maybe_ast_node {
123             Some(hir_map::NodeStructCtor(_)) => {
124                 NamedTupleConstructor(Disr(0))
125             }
126             Some(hir_map::NodeVariant(_)) => {
127                 let vinfo = common::inlined_variant_def(ccx, maybe_node_id.unwrap());
128                 NamedTupleConstructor(Disr::from(vinfo.disr_val))
129             }
130             Some(hir_map::NodeForeignItem(fi)) if {
131                 let abi = tcx.map.get_foreign_abi(fi.id);
132                 abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic
133             } => Intrinsic,
134
135             _ => return Callee::ptr(get_fn(ccx, def_id, substs))
136         };
137
138         Callee {
139             data: data,
140             ty: def_ty(tcx, def_id, substs)
141         }
142     }
143
144     /// Trait method, which has to be resolved to an impl method.
145     pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
146                             trait_id: DefId,
147                             def_id: DefId,
148                             substs: &'tcx Substs<'tcx>)
149                             -> Callee<'tcx> {
150         let tcx = ccx.tcx();
151
152         let trait_ref = ty::TraitRef::from_method(tcx, trait_id, substs);
153         let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref));
154         match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
155             traits::VtableImpl(vtable_impl) => {
156                 let impl_did = vtable_impl.impl_def_id;
157                 let mname = tcx.item_name(def_id);
158                 // create a concatenated set of substitutions which includes
159                 // those from the impl and those from the method:
160                 let mth = meth::get_impl_method(tcx, substs, impl_did, vtable_impl.substs, mname);
161
162                 // Translate the function, bypassing Callee::def.
163                 // That is because default methods have the same ID as the
164                 // trait method used to look up the impl method that ended
165                 // up here, so calling Callee::def would infinitely recurse.
166                 Callee::ptr(get_fn(ccx, mth.method.def_id, mth.substs))
167             }
168             traits::VtableClosure(vtable_closure) => {
169                 // The substitutions should have no type parameters remaining
170                 // after passing through fulfill_obligation
171                 let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
172                 let llfn = closure::trans_closure_method(ccx,
173                                                          vtable_closure.closure_def_id,
174                                                          vtable_closure.substs,
175                                                          trait_closure_kind);
176
177                 let method_ty = def_ty(tcx, def_id, substs);
178                 let fn_ptr_ty = match method_ty.sty {
179                     ty::TyFnDef(_, _, fty) => tcx.mk_fn_ptr(fty),
180                     _ => bug!("expected fn item type, found {}",
181                               method_ty)
182                 };
183                 Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
184             }
185             traits::VtableFnPointer(vtable_fn_pointer) => {
186                 let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
187                 let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, vtable_fn_pointer.fn_ty);
188
189                 let method_ty = def_ty(tcx, def_id, substs);
190                 let fn_ptr_ty = match method_ty.sty {
191                     ty::TyFnDef(_, _, fty) => tcx.mk_fn_ptr(fty),
192                     _ => bug!("expected fn item type, found {}",
193                               method_ty)
194                 };
195                 Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
196             }
197             traits::VtableObject(ref data) => {
198                 Callee {
199                     data: Virtual(tcx.get_vtable_index_of_object_method(data, def_id)),
200                     ty: def_ty(tcx, def_id, substs)
201                 }
202             }
203             vtable => {
204                 bug!("resolved vtable bad vtable {:?} in trans", vtable);
205             }
206         }
207     }
208
209     /// Get the abi::FnType for a direct call. Mainly deals with the fact
210     /// that a Virtual call doesn't take the vtable, like its shim does.
211     /// The extra argument types are for variadic (extern "C") functions.
212     pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
213                               extra_args: &[Ty<'tcx>]) -> FnType {
214         let abi = self.ty.fn_abi();
215         let sig = ccx.tcx().erase_late_bound_regions(self.ty.fn_sig());
216         let sig = ccx.tcx().normalize_associated_type(&sig);
217         let mut fn_ty = FnType::unadjusted(ccx, abi, &sig, extra_args);
218         if let Virtual(_) = self.data {
219             // Don't pass the vtable, it's not an argument of the virtual fn.
220             fn_ty.args[1].ignore();
221         }
222         fn_ty.adjust_for_abi(ccx, abi, &sig);
223         fn_ty
224     }
225
226     /// This behemoth of a function translates function calls. Unfortunately, in
227     /// order to generate more efficient LLVM output at -O0, it has quite a complex
228     /// signature (refactoring this into two functions seems like a good idea).
229     ///
230     /// In particular, for lang items, it is invoked with a dest of None, and in
231     /// that case the return value contains the result of the fn. The lang item must
232     /// not return a structural type or else all heck breaks loose.
233     ///
234     /// For non-lang items, `dest` is always Some, and hence the result is written
235     /// into memory somewhere. Nonetheless we return the actual return value of the
236     /// function.
237     pub fn call<'a, 'blk>(self, bcx: Block<'blk, 'tcx>,
238                           debug_loc: DebugLoc,
239                           args: CallArgs<'a, 'tcx>,
240                           dest: Option<expr::Dest>)
241                           -> Result<'blk, 'tcx> {
242         trans_call_inner(bcx, debug_loc, self, args, dest)
243     }
244
245     /// Turn the callee into a function pointer.
246     pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>)
247                      -> Datum<'tcx, Rvalue> {
248         let fn_ptr_ty = match self.ty.sty {
249             ty::TyFnDef(_, _, f) => ccx.tcx().mk_fn_ptr(f),
250             _ => self.ty
251         };
252         match self.data {
253             Fn(llfn) => {
254                 immediate_rvalue(llfn, fn_ptr_ty)
255             }
256             Virtual(idx) => {
257                 let llfn = meth::trans_object_shim(ccx, self.ty, idx);
258                 immediate_rvalue(llfn, fn_ptr_ty)
259             }
260             NamedTupleConstructor(_) => match self.ty.sty {
261                 ty::TyFnDef(def_id, substs, _) => {
262                     return get_fn(ccx, def_id, substs);
263                 }
264                 _ => bug!("expected fn item type, found {}", self.ty)
265             },
266             Intrinsic => bug!("intrinsic {} getting reified", self.ty)
267         }
268     }
269 }
270
271 /// Given a DefId and some Substs, produces the monomorphic item type.
272 fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
273                     def_id: DefId,
274                     substs: &'tcx Substs<'tcx>)
275                     -> Ty<'tcx> {
276     let ty = tcx.lookup_item_type(def_id).ty;
277     monomorphize::apply_param_substs(tcx, substs, &ty)
278 }
279
280 /// Translates an adapter that implements the `Fn` trait for a fn
281 /// pointer. This is basically the equivalent of something like:
282 ///
283 /// ```
284 /// impl<'a> Fn(&'a int) -> &'a int for fn(&int) -> &int {
285 ///     extern "rust-abi" fn call(&self, args: (&'a int,)) -> &'a int {
286 ///         (*self)(args.0)
287 ///     }
288 /// }
289 /// ```
290 ///
291 /// but for the bare function type given.
292 pub fn trans_fn_pointer_shim<'a, 'tcx>(
293     ccx: &'a CrateContext<'a, 'tcx>,
294     closure_kind: ty::ClosureKind,
295     bare_fn_ty: Ty<'tcx>)
296     -> ValueRef
297 {
298     let _icx = push_ctxt("trans_fn_pointer_shim");
299     let tcx = ccx.tcx();
300
301     // Normalize the type for better caching.
302     let bare_fn_ty = tcx.normalize_associated_type(&bare_fn_ty);
303
304     // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
305     let is_by_ref = match closure_kind {
306         ty::ClosureKind::Fn | ty::ClosureKind::FnMut => true,
307         ty::ClosureKind::FnOnce => false,
308     };
309
310     let llfnpointer = match bare_fn_ty.sty {
311         ty::TyFnDef(def_id, substs, _) => {
312             // Function definitions have to be turned into a pointer.
313             let llfn = Callee::def(ccx, def_id, substs).reify(ccx).val;
314             if !is_by_ref {
315                 // A by-value fn item is ignored, so the shim has
316                 // the same signature as the original function.
317                 return llfn;
318             }
319             Some(llfn)
320         }
321         _ => None
322     };
323
324     let bare_fn_ty_maybe_ref = if is_by_ref {
325         tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), bare_fn_ty)
326     } else {
327         bare_fn_ty
328     };
329
330     // Check if we already trans'd this shim.
331     match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
332         Some(&llval) => { return llval; }
333         None => { }
334     }
335
336     debug!("trans_fn_pointer_shim(bare_fn_ty={:?})",
337            bare_fn_ty);
338
339     // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
340     // which is the fn pointer, and `args`, which is the arguments tuple.
341     let sig = match bare_fn_ty.sty {
342         ty::TyFnDef(_, _,
343                     &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
344                                     abi: Abi::Rust,
345                                     ref sig }) |
346         ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal,
347                                     abi: Abi::Rust,
348                                     ref sig }) => sig,
349
350         _ => {
351             bug!("trans_fn_pointer_shim invoked on invalid type: {}",
352                  bare_fn_ty);
353         }
354     };
355     let sig = tcx.erase_late_bound_regions(sig);
356     let sig = ccx.tcx().normalize_associated_type(&sig);
357     let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec());
358     let sig = ty::FnSig {
359         inputs: vec![bare_fn_ty_maybe_ref,
360                      tuple_input_ty],
361         output: sig.output,
362         variadic: false
363     };
364     let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]);
365     let tuple_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
366         unsafety: hir::Unsafety::Normal,
367         abi: Abi::RustCall,
368         sig: ty::Binder(sig)
369     }));
370     debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
371
372     //
373     let function_name =
374         symbol_names::internal_name_from_type_and_suffix(ccx,
375                                                          bare_fn_ty,
376                                                          "fn_pointer_shim");
377     let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
378     attributes::set_frame_pointer_elimination(ccx, llfn);
379     //
380     let (block_arena, fcx): (TypedArena<_>, FunctionContext);
381     block_arena = TypedArena::new();
382     fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &block_arena);
383     let mut bcx = fcx.init(false, None);
384
385     let llargs = get_params(fcx.llfn);
386
387     let self_idx = fcx.fn_ty.ret.is_indirect() as usize;
388     let llfnpointer = llfnpointer.unwrap_or_else(|| {
389         // the first argument (`self`) will be ptr to the fn pointer
390         if is_by_ref {
391             Load(bcx, llargs[self_idx])
392         } else {
393             llargs[self_idx]
394         }
395     });
396
397     assert!(!fcx.needs_ret_allocas);
398
399     let dest = fcx.llretslotptr.get().map(|_|
400         expr::SaveIn(fcx.get_ret_slot(bcx, "ret_slot"))
401     );
402
403     let callee = Callee {
404         data: Fn(llfnpointer),
405         ty: bare_fn_ty
406     };
407     bcx = callee.call(bcx, DebugLoc::None, ArgVals(&llargs[(self_idx + 1)..]), dest).bcx;
408
409     fcx.finish(bcx, DebugLoc::None);
410
411     ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
412
413     llfn
414 }
415
416 /// Translates a reference to a fn/method item, monomorphizing and
417 /// inlining as it goes.
418 ///
419 /// # Parameters
420 ///
421 /// - `ccx`: the crate context
422 /// - `def_id`: def id of the fn or method item being referenced
423 /// - `substs`: values for each of the fn/method's parameters
424 fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
425                     def_id: DefId,
426                     substs: &'tcx Substs<'tcx>)
427                     -> Datum<'tcx, Rvalue> {
428     let tcx = ccx.tcx();
429
430     debug!("get_fn(def_id={:?}, substs={:?})", def_id, substs);
431
432     assert!(!substs.types.needs_infer());
433     assert!(!substs.types.has_escaping_regions());
434
435     // Check whether this fn has an inlined copy and, if so, redirect
436     // def_id to the local id of the inlined copy.
437     let def_id = inline::maybe_instantiate_inline(ccx, def_id);
438
439     fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
440         let node_id = match tcx.map.as_local_node_id(def_id) {
441             Some(n) => n,
442             None => { return false; }
443         };
444         let map_node = errors::expect(
445             &tcx.sess.diagnostic(),
446             tcx.map.find(node_id),
447             || "local item should be in ast map".to_string());
448
449         match map_node {
450             hir_map::NodeVariant(v) => {
451                 v.node.data.is_tuple()
452             }
453             hir_map::NodeStructCtor(_) => true,
454             _ => false
455         }
456     }
457     let must_monomorphise =
458         !substs.types.is_empty() || is_named_tuple_constructor(tcx, def_id);
459
460     debug!("get_fn({:?}) must_monomorphise: {}",
461            def_id, must_monomorphise);
462
463     // Create a monomorphic version of generic functions
464     if must_monomorphise {
465         // Should be either intra-crate or inlined.
466         assert_eq!(def_id.krate, LOCAL_CRATE);
467
468         let substs = tcx.normalize_associated_type(&substs);
469         let (val, fn_ty) = monomorphize::monomorphic_fn(ccx, def_id, substs);
470         let fn_ptr_ty = match fn_ty.sty {
471             ty::TyFnDef(_, _, fty) => {
472                 // Create a fn pointer with the substituted signature.
473                 tcx.mk_fn_ptr(fty)
474             }
475             _ => bug!("expected fn item type, found {}", fn_ty)
476         };
477         assert_eq!(type_of::type_of(ccx, fn_ptr_ty), common::val_ty(val));
478         return immediate_rvalue(val, fn_ptr_ty);
479     }
480
481     // Find the actual function pointer.
482     let ty = ccx.tcx().lookup_item_type(def_id).ty;
483     let fn_ptr_ty = match ty.sty {
484         ty::TyFnDef(_, _, ref fty) => {
485             // Create a fn pointer with the normalized signature.
486             tcx.mk_fn_ptr(tcx.normalize_associated_type(fty))
487         }
488         _ => bug!("expected fn item type, found {}", ty)
489     };
490
491     let instance = Instance::mono(ccx.shared(), def_id);
492     if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
493         return immediate_rvalue(llfn, fn_ptr_ty);
494     }
495
496     let local_id = ccx.tcx().map.as_local_node_id(def_id);
497     let local_item = match local_id.and_then(|id| tcx.map.find(id)) {
498         Some(hir_map::NodeItem(&hir::Item {
499             span, node: hir::ItemFn(..), ..
500         })) |
501         Some(hir_map::NodeTraitItem(&hir::TraitItem {
502             span, node: hir::MethodTraitItem(_, Some(_)), ..
503         })) |
504         Some(hir_map::NodeImplItem(&hir::ImplItem {
505             span, node: hir::ImplItemKind::Method(..), ..
506         })) => {
507             Some(span)
508         }
509         _ => None
510     };
511
512     // This is subtle and surprising, but sometimes we have to bitcast
513     // the resulting fn pointer.  The reason has to do with external
514     // functions.  If you have two crates that both bind the same C
515     // library, they may not use precisely the same types: for
516     // example, they will probably each declare their own structs,
517     // which are distinct types from LLVM's point of view (nominal
518     // types).
519     //
520     // Now, if those two crates are linked into an application, and
521     // they contain inlined code, you can wind up with a situation
522     // where both of those functions wind up being loaded into this
523     // application simultaneously. In that case, the same function
524     // (from LLVM's point of view) requires two types. But of course
525     // LLVM won't allow one function to have two types.
526     //
527     // What we currently do, therefore, is declare the function with
528     // one of the two types (whichever happens to come first) and then
529     // bitcast as needed when the function is referenced to make sure
530     // it has the type we expect.
531     //
532     // This can occur on either a crate-local or crate-external
533     // reference. It also occurs when testing libcore and in some
534     // other weird situations. Annoying.
535
536     let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
537                                               TransItem::Fn(instance));
538
539     let llptrty = type_of::type_of(ccx, fn_ptr_ty);
540     let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
541         if let Some(span) = local_item {
542             if declare::get_defined_value(ccx, &sym).is_some() {
543                 ccx.sess().span_fatal(span,
544                     &format!("symbol `{}` is already defined", &sym));
545             }
546         }
547
548         if common::val_ty(llfn) != llptrty {
549             if local_item.is_some() {
550                 bug!("symbol `{}` previously declared as {:?}, now wanted as {:?}",
551                      sym, Value(llfn), llptrty);
552             }
553             debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
554             consts::ptrcast(llfn, llptrty)
555         } else {
556             debug!("get_fn: not casting pointer!");
557             llfn
558         }
559     } else {
560         let llfn = declare::declare_fn(ccx, &sym, ty);
561         assert_eq!(common::val_ty(llfn), llptrty);
562         debug!("get_fn: not casting pointer!");
563
564         let attrs = ccx.tcx().get_attrs(def_id);
565         attributes::from_fn_attrs(ccx, &attrs, llfn);
566         if local_item.is_some() {
567             // FIXME(eddyb) Doubt all extern fn should allow unwinding.
568             attributes::unwind(llfn, true);
569         }
570
571         llfn
572     };
573
574     ccx.instances().borrow_mut().insert(instance, llfn);
575
576     immediate_rvalue(llfn, fn_ptr_ty)
577 }
578
579 // ______________________________________________________________________
580 // Translating calls
581
582 fn trans_call_inner<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
583                                     debug_loc: DebugLoc,
584                                     callee: Callee<'tcx>,
585                                     args: CallArgs<'a, 'tcx>,
586                                     dest: Option<expr::Dest>)
587                                     -> Result<'blk, 'tcx> {
588     // Introduce a temporary cleanup scope that will contain cleanups
589     // for the arguments while they are being evaluated. The purpose
590     // this cleanup is to ensure that, should a panic occur while
591     // evaluating argument N, the values for arguments 0...N-1 are all
592     // cleaned up. If no panic occurs, the values are handed off to
593     // the callee, and hence none of the cleanups in this temporary
594     // scope will ever execute.
595     let fcx = bcx.fcx;
596     let ccx = fcx.ccx;
597
598     let abi = callee.ty.fn_abi();
599     let sig = callee.ty.fn_sig();
600     let output = bcx.tcx().erase_late_bound_regions(&sig.output());
601     let output = bcx.tcx().normalize_associated_type(&output);
602
603     let extra_args = match args {
604         ArgExprs(args) if abi != Abi::RustCall => {
605             args[sig.0.inputs.len()..].iter().map(|expr| {
606                 common::expr_ty_adjusted(bcx, expr)
607             }).collect()
608         }
609         _ => vec![]
610     };
611     let fn_ty = callee.direct_fn_type(ccx, &extra_args);
612
613     let mut callee = match callee.data {
614         Intrinsic => {
615             assert!(abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic);
616             assert!(dest.is_some());
617
618             return intrinsic::trans_intrinsic_call(bcx, callee.ty, &fn_ty,
619                                                    args, dest.unwrap(),
620                                                    debug_loc);
621         }
622         NamedTupleConstructor(disr) => {
623             assert!(dest.is_some());
624
625             return base::trans_named_tuple_constructor(bcx,
626                                                        callee.ty,
627                                                        disr,
628                                                        args,
629                                                        dest.unwrap(),
630                                                        debug_loc);
631         }
632         f => f
633     };
634
635     // Generate a location to store the result. If the user does
636     // not care about the result, just make a stack slot.
637     let opt_llretslot = dest.and_then(|dest| match dest {
638         expr::SaveIn(dst) => Some(dst),
639         expr::Ignore => {
640             let needs_drop = || bcx.fcx.type_needs_drop(output);
641             if fn_ty.ret.is_indirect() || fn_ty.ret.cast.is_some() || needs_drop() {
642                 // Push the out-pointer if we use an out-pointer for this
643                 // return type, otherwise push "undef".
644                 if fn_ty.ret.is_ignore() {
645                     Some(C_undef(fn_ty.ret.original_ty.ptr_to()))
646                 } else {
647                     let llresult = alloca(bcx, fn_ty.ret.original_ty, "__llret");
648                     call_lifetime_start(bcx, llresult);
649                     Some(llresult)
650                 }
651             } else {
652                 None
653             }
654         }
655     });
656
657     // If there no destination, return must be direct, with no cast.
658     if opt_llretslot.is_none() {
659         assert!(!fn_ty.ret.is_indirect() && fn_ty.ret.cast.is_none());
660     }
661
662     let mut llargs = Vec::new();
663
664     if fn_ty.ret.is_indirect() {
665         let mut llretslot = opt_llretslot.unwrap();
666         if let Some(ty) = fn_ty.ret.cast {
667             llretslot = PointerCast(bcx, llretslot, ty.ptr_to());
668         }
669         llargs.push(llretslot);
670     }
671
672     let arg_cleanup_scope = fcx.push_custom_cleanup_scope();
673     bcx = trans_args(bcx, abi, &fn_ty, &mut callee, args, &mut llargs,
674                      cleanup::CustomScope(arg_cleanup_scope));
675     fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean();
676
677     let llfn = match callee {
678         Fn(f) => f,
679         _ => bug!("expected fn pointer callee, found {:?}", callee)
680     };
681
682     let (llret, mut bcx) = base::invoke(bcx, llfn, &llargs, debug_loc);
683     if !bcx.unreachable.get() {
684         fn_ty.apply_attrs_callsite(llret);
685
686         // If the function we just called does not use an outpointer,
687         // store the result into the rust outpointer. Cast the outpointer
688         // type to match because some ABIs will use a different type than
689         // the Rust type. e.g., a {u32,u32} struct could be returned as
690         // u64.
691         if !fn_ty.ret.is_indirect() {
692             if let Some(llretslot) = opt_llretslot {
693                 fn_ty.ret.store(&bcx.build(), llret, llretslot);
694             }
695         }
696     }
697
698     fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_cleanup_scope);
699
700     // If the caller doesn't care about the result of this fn call,
701     // drop the temporary slot we made.
702     match (dest, opt_llretslot) {
703         (Some(expr::Ignore), Some(llretslot)) => {
704             // drop the value if it is not being saved.
705             bcx = glue::drop_ty(bcx, llretslot, output, debug_loc);
706             call_lifetime_end(bcx, llretslot);
707         }
708         _ => {}
709     }
710
711     // FIXME(canndrew): This is_never should really be an is_uninhabited
712     if output.is_never() {
713         Unreachable(bcx);
714     }
715
716     Result::new(bcx, llret)
717 }
718
719 pub enum CallArgs<'a, 'tcx> {
720     /// Supply value of arguments as a list of expressions that must be
721     /// translated. This is used in the common case of `foo(bar, qux)`.
722     ArgExprs(&'a [P<hir::Expr>]),
723
724     /// Supply value of arguments as a list of LLVM value refs; frequently
725     /// used with lang items and so forth, when the argument is an internal
726     /// value.
727     ArgVals(&'a [ValueRef]),
728
729     /// For overloaded operators: `(lhs, Option(rhs))`.
730     /// `lhs` is the left-hand-side and `rhs` is the datum
731     /// of the right-hand-side argument (if any).
732     ArgOverloadedOp(Datum<'tcx, Expr>, Option<Datum<'tcx, Expr>>),
733
734     /// Supply value of arguments as a list of expressions that must be
735     /// translated, for overloaded call operators.
736     ArgOverloadedCall(Vec<&'a hir::Expr>),
737 }
738
739 fn trans_args_under_call_abi<'blk, 'tcx>(
740                              mut bcx: Block<'blk, 'tcx>,
741                              arg_exprs: &[P<hir::Expr>],
742                              callee: &mut CalleeData,
743                              fn_ty: &FnType,
744                              llargs: &mut Vec<ValueRef>,
745                              arg_cleanup_scope: cleanup::ScopeId)
746                              -> Block<'blk, 'tcx>
747 {
748     let mut arg_idx = 0;
749
750     // Translate the `self` argument first.
751     let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &arg_exprs[0]));
752     bcx = trans_arg_datum(bcx,
753                           arg_datum,
754                           callee, fn_ty, &mut arg_idx,
755                           arg_cleanup_scope,
756                           llargs);
757
758     // Now untuple the rest of the arguments.
759     let tuple_expr = &arg_exprs[1];
760     let tuple_type = common::node_id_type(bcx, tuple_expr.id);
761
762     match tuple_type.sty {
763         ty::TyTuple(ref field_types) => {
764             let tuple_datum = unpack_datum!(bcx,
765                                             expr::trans(bcx, &tuple_expr));
766             let tuple_lvalue_datum =
767                 unpack_datum!(bcx,
768                               tuple_datum.to_lvalue_datum(bcx,
769                                                           "args",
770                                                           tuple_expr.id));
771             let repr = adt::represent_type(bcx.ccx(), tuple_type);
772             let repr_ptr = &repr;
773             for (i, field_type) in field_types.iter().enumerate() {
774                 let arg_datum = tuple_lvalue_datum.get_element(
775                     bcx,
776                     field_type,
777                     |srcval| {
778                         adt::trans_field_ptr(bcx, repr_ptr, srcval, Disr(0), i)
779                     }).to_expr_datum();
780                 bcx = trans_arg_datum(bcx,
781                                       arg_datum,
782                                       callee, fn_ty, &mut arg_idx,
783                                       arg_cleanup_scope,
784                                       llargs);
785             }
786         }
787         _ => {
788             span_bug!(tuple_expr.span,
789                       "argument to `.call()` wasn't a tuple?!")
790         }
791     };
792
793     bcx
794 }
795
796 pub fn trans_args<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
797                                   abi: Abi,
798                                   fn_ty: &FnType,
799                                   callee: &mut CalleeData,
800                                   args: CallArgs<'a, 'tcx>,
801                                   llargs: &mut Vec<ValueRef>,
802                                   arg_cleanup_scope: cleanup::ScopeId)
803                                   -> Block<'blk, 'tcx> {
804     debug!("trans_args(abi={})", abi);
805
806     let _icx = push_ctxt("trans_args");
807
808     let mut bcx = bcx;
809     let mut arg_idx = 0;
810
811     // First we figure out the caller's view of the types of the arguments.
812     // This will be needed if this is a generic call, because the callee has
813     // to cast her view of the arguments to the caller's view.
814     match args {
815         ArgExprs(arg_exprs) => {
816             if abi == Abi::RustCall {
817                 // This is only used for direct calls to the `call`,
818                 // `call_mut` or `call_once` functions.
819                 return trans_args_under_call_abi(bcx,
820                                                  arg_exprs, callee, fn_ty,
821                                                  llargs,
822                                                  arg_cleanup_scope)
823             }
824
825             for arg_expr in arg_exprs {
826                 let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &arg_expr));
827                 bcx = trans_arg_datum(bcx,
828                                       arg_datum,
829                                       callee, fn_ty, &mut arg_idx,
830                                       arg_cleanup_scope,
831                                       llargs);
832             }
833         }
834         ArgOverloadedCall(arg_exprs) => {
835             for expr in arg_exprs {
836                 let arg_datum =
837                     unpack_datum!(bcx, expr::trans(bcx, expr));
838                 bcx = trans_arg_datum(bcx,
839                                       arg_datum,
840                                       callee, fn_ty, &mut arg_idx,
841                                       arg_cleanup_scope,
842                                       llargs);
843             }
844         }
845         ArgOverloadedOp(lhs, rhs) => {
846             bcx = trans_arg_datum(bcx, lhs,
847                                   callee, fn_ty, &mut arg_idx,
848                                   arg_cleanup_scope,
849                                   llargs);
850
851             if let Some(rhs) = rhs {
852                 bcx = trans_arg_datum(bcx, rhs,
853                                       callee, fn_ty, &mut arg_idx,
854                                       arg_cleanup_scope,
855                                       llargs);
856             }
857         }
858         ArgVals(vs) => {
859             match *callee {
860                 Virtual(idx) => {
861                     llargs.push(vs[0]);
862
863                     let fn_ptr = meth::get_virtual_method(bcx, vs[1], idx);
864                     let llty = fn_ty.llvm_type(bcx.ccx()).ptr_to();
865                     *callee = Fn(PointerCast(bcx, fn_ptr, llty));
866                     llargs.extend_from_slice(&vs[2..]);
867                 }
868                 _ => llargs.extend_from_slice(vs)
869             }
870         }
871     }
872
873     bcx
874 }
875
876 fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
877                                arg_datum: Datum<'tcx, Expr>,
878                                callee: &mut CalleeData,
879                                fn_ty: &FnType,
880                                next_idx: &mut usize,
881                                arg_cleanup_scope: cleanup::ScopeId,
882                                llargs: &mut Vec<ValueRef>)
883                                -> Block<'blk, 'tcx> {
884     let _icx = push_ctxt("trans_arg_datum");
885     let mut bcx = bcx;
886
887     debug!("trans_arg_datum({:?})", arg_datum);
888
889     let arg = &fn_ty.args[*next_idx];
890     *next_idx += 1;
891
892     // Fill padding with undef value, where applicable.
893     if let Some(ty) = arg.pad {
894         llargs.push(C_undef(ty));
895     }
896
897     // Determine whether we want a by-ref datum even if not appropriate.
898     let want_by_ref = arg.is_indirect() || arg.cast.is_some();
899
900     let fat_ptr = common::type_is_fat_ptr(bcx.tcx(), arg_datum.ty);
901     let (by_ref, val) = if fat_ptr && !bcx.fcx.type_needs_drop(arg_datum.ty) {
902         (true, arg_datum.val)
903     } else {
904         // Make this an rvalue, since we are going to be
905         // passing ownership.
906         let arg_datum = unpack_datum!(
907             bcx, arg_datum.to_rvalue_datum(bcx, "arg"));
908
909         // Now that arg_datum is owned, get it into the appropriate
910         // mode (ref vs value).
911         let arg_datum = unpack_datum!(bcx, if want_by_ref {
912             arg_datum.to_ref_datum(bcx)
913         } else {
914             arg_datum.to_appropriate_datum(bcx)
915         });
916
917         // Technically, ownership of val passes to the callee.
918         // However, we must cleanup should we panic before the
919         // callee is actually invoked.
920         (arg_datum.kind.is_by_ref(),
921          arg_datum.add_clean(bcx.fcx, arg_cleanup_scope))
922     };
923
924     if arg.is_ignore() {
925         return bcx;
926     }
927
928     debug!("--- trans_arg_datum passing {:?}", Value(val));
929
930     if fat_ptr {
931         // Fat pointers should be passed without any transformations.
932         assert!(!arg.is_indirect() && arg.cast.is_none());
933         llargs.push(Load(bcx, expr::get_dataptr(bcx, val)));
934
935         let info_arg = &fn_ty.args[*next_idx];
936         *next_idx += 1;
937         assert!(!info_arg.is_indirect() && info_arg.cast.is_none());
938         let info = Load(bcx, expr::get_meta(bcx, val));
939
940         if let Virtual(idx) = *callee {
941             // We have to grab the fn pointer from the vtable when
942             // handling the first argument, ensure that here.
943             assert_eq!(*next_idx, 2);
944             assert!(info_arg.is_ignore());
945             let fn_ptr = meth::get_virtual_method(bcx, info, idx);
946             let llty = fn_ty.llvm_type(bcx.ccx()).ptr_to();
947             *callee = Fn(PointerCast(bcx, fn_ptr, llty));
948         } else {
949             assert!(!info_arg.is_ignore());
950             llargs.push(info);
951         }
952         return bcx;
953     }
954
955     let mut val = val;
956     if by_ref && !arg.is_indirect() {
957         // Have to load the argument, maybe while casting it.
958         if arg.original_ty == Type::i1(bcx.ccx()) {
959             // We store bools as i8 so we need to truncate to i1.
960             val = LoadRangeAssert(bcx, val, 0, 2, llvm::False);
961             val = Trunc(bcx, val, arg.original_ty);
962         } else if let Some(ty) = arg.cast {
963             val = Load(bcx, PointerCast(bcx, val, ty.ptr_to()));
964             if !bcx.unreachable.get() {
965                 let llalign = llalign_of_min(bcx.ccx(), arg.ty);
966                 unsafe {
967                     llvm::LLVMSetAlignment(val, llalign);
968                 }
969             }
970         } else {
971             val = Load(bcx, val);
972         }
973     }
974
975     llargs.push(val);
976     bcx
977 }