]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/callee.rs
auto merge of #15601 : jbclements/rust/disable-default-macro-behavior, r=alexcrichton
[rust.git] / src / librustc / middle / 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 /*!
12  * Handles translation of callees as well as other call-related
13  * things.  Callees are a superset of normal rust values and sometimes
14  * have different representations.  In particular, top-level fn items
15  * and methods are represented as just a fn ptr and not a full
16  * closure.
17  */
18
19 use arena::TypedArena;
20 use back::abi;
21 use back::link;
22 use lib::llvm::ValueRef;
23 use lib::llvm::llvm;
24 use metadata::csearch;
25 use middle::def;
26 use middle::subst;
27 use middle::subst::{Subst, VecPerParamSpace};
28 use middle::trans::base;
29 use middle::trans::base::*;
30 use middle::trans::build::*;
31 use middle::trans::callee;
32 use middle::trans::cleanup;
33 use middle::trans::cleanup::CleanupMethods;
34 use middle::trans::common;
35 use middle::trans::common::*;
36 use middle::trans::datum::*;
37 use middle::trans::datum::{Datum, KindOps};
38 use middle::trans::expr;
39 use middle::trans::glue;
40 use middle::trans::inline;
41 use middle::trans::foreign;
42 use middle::trans::intrinsic;
43 use middle::trans::meth;
44 use middle::trans::monomorphize;
45 use middle::trans::type_::Type;
46 use middle::trans::type_of;
47 use middle::ty;
48 use middle::typeck;
49 use middle::typeck::coherence::make_substs_for_receiver_types;
50 use middle::typeck::MethodCall;
51 use util::ppaux::Repr;
52
53 use std::gc::Gc;
54 use syntax::ast;
55 use synabi = syntax::abi;
56
57 pub struct MethodData {
58     pub llfn: ValueRef,
59     pub llself: ValueRef,
60 }
61
62 pub enum CalleeData {
63     Closure(Datum<Lvalue>),
64
65     // Represents a (possibly monomorphized) top-level fn item or method
66     // item. Note that this is just the fn-ptr and is not a Rust closure
67     // value (which is a pair).
68     Fn(/* llfn */ ValueRef),
69
70     Intrinsic(ast::NodeId, subst::Substs),
71
72     TraitMethod(MethodData)
73 }
74
75 pub struct Callee<'a> {
76     pub bcx: &'a Block<'a>,
77     pub data: CalleeData
78 }
79
80 fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
81     let _icx = push_ctxt("trans_callee");
82     debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
83
84     // pick out special kinds of expressions that can be called:
85     match expr.node {
86         ast::ExprPath(_) => {
87             return trans_def(bcx, bcx.def(expr.id), expr);
88         }
89         _ => {}
90     }
91
92     // any other expressions are closures:
93     return datum_callee(bcx, expr);
94
95     fn datum_callee<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
96         let DatumBlock {bcx: mut bcx, datum} = expr::trans(bcx, expr);
97         match ty::get(datum.ty).sty {
98             ty::ty_bare_fn(..) => {
99                 let llval = datum.to_llscalarish(bcx);
100                 return Callee {bcx: bcx, data: Fn(llval)};
101             }
102             ty::ty_closure(..) => {
103                 let datum = unpack_datum!(
104                     bcx, datum.to_lvalue_datum(bcx, "callee", expr.id));
105                 return Callee {bcx: bcx, data: Closure(datum)};
106             }
107             _ => {
108                 bcx.tcx().sess.span_bug(
109                     expr.span,
110                     format!("type of callee is neither bare-fn nor closure: \
111                              {}",
112                             bcx.ty_to_string(datum.ty)).as_slice());
113             }
114         }
115     }
116
117     fn fn_callee<'a>(bcx: &'a Block<'a>, llfn: ValueRef) -> Callee<'a> {
118         return Callee {bcx: bcx, data: Fn(llfn)};
119     }
120
121     fn trans_def<'a>(bcx: &'a Block<'a>, def: def::Def, ref_expr: &ast::Expr)
122                  -> Callee<'a> {
123         debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx()));
124         let expr_ty = node_id_type(bcx, ref_expr.id);
125         match def {
126             def::DefFn(did, _) if match ty::get(expr_ty).sty {
127                 ty::ty_bare_fn(ref f) => f.abi == synabi::RustIntrinsic,
128                 _ => false
129             } => {
130                 let substs = node_id_substs(bcx, ExprId(ref_expr.id));
131                 let def_id = if did.krate != ast::LOCAL_CRATE {
132                     inline::maybe_instantiate_inline(bcx.ccx(), did)
133                 } else {
134                     did
135                 };
136                 Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
137             }
138             def::DefFn(did, _) |
139             def::DefStaticMethod(did, def::FromImpl(_), _) => {
140                 fn_callee(bcx, trans_fn_ref(bcx, did, ExprId(ref_expr.id)))
141             }
142             def::DefStaticMethod(impl_did,
143                                  def::FromTrait(trait_did),
144                                  _) => {
145                 fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did,
146                                                                 trait_did,
147                                                                 ref_expr.id))
148             }
149             def::DefVariant(tid, vid, _) => {
150                 // nullary variants are not callable
151                 assert!(ty::enum_variant_with_id(bcx.tcx(),
152                                                       tid,
153                                                       vid).args.len() > 0u);
154                 fn_callee(bcx, trans_fn_ref(bcx, vid, ExprId(ref_expr.id)))
155             }
156             def::DefStruct(def_id) => {
157                 fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
158             }
159             def::DefStatic(..) |
160             def::DefArg(..) |
161             def::DefLocal(..) |
162             def::DefBinding(..) |
163             def::DefUpvar(..) => {
164                 datum_callee(bcx, ref_expr)
165             }
166             def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
167             def::DefTy(..) | def::DefPrimTy(..) |
168             def::DefUse(..) | def::DefTyParamBinder(..) |
169             def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) |
170             def::DefSelfTy(..) | def::DefMethod(..) => {
171                 bcx.tcx().sess.span_bug(
172                     ref_expr.span,
173                     format!("cannot translate def {:?} \
174                              to a callable thing!", def).as_slice());
175             }
176         }
177     }
178 }
179
180 pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef {
181     /*!
182      * Translates a reference (with id `ref_id`) to the fn/method
183      * with id `def_id` into a function pointer.  This may require
184      * monomorphization or inlining.
185      */
186
187     let _icx = push_ctxt("trans_fn_ref");
188
189     let substs = node_id_substs(bcx, node);
190     let vtable_key = match node {
191         ExprId(id) => MethodCall::expr(id),
192         MethodCall(method_call) => method_call
193     };
194     let vtables = node_vtables(bcx, vtable_key);
195     debug!("trans_fn_ref(def_id={}, node={:?}, substs={}, vtables={})",
196            def_id.repr(bcx.tcx()),
197            node,
198            substs.repr(bcx.tcx()),
199            vtables.repr(bcx.tcx()));
200     trans_fn_ref_with_vtables(bcx, def_id, node, substs, vtables)
201 }
202
203 fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
204                                            def_id: ast::DefId,
205                                            ref_id: ast::NodeId,
206                                            substs: subst::Substs,
207                                            vtables: typeck::vtable_res)
208                                            -> Callee<'a> {
209     Callee {bcx: bcx,
210             data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ExprId(ref_id),
211                                                substs, vtables))}
212 }
213
214 fn resolve_default_method_vtables(bcx: &Block,
215                                   impl_id: ast::DefId,
216                                   substs: &subst::Substs,
217                                   impl_vtables: typeck::vtable_res)
218                                   -> typeck::vtable_res
219 {
220     // Get the vtables that the impl implements the trait at
221     let impl_res = ty::lookup_impl_vtables(bcx.tcx(), impl_id);
222
223     // Build up a param_substs that we are going to resolve the
224     // trait_vtables under.
225     let param_substs = param_substs {
226         substs: (*substs).clone(),
227         vtables: impl_vtables.clone()
228     };
229
230     let mut param_vtables = resolve_vtables_under_param_substs(
231         bcx.tcx(), &param_substs, &impl_res);
232
233     // Now we pull any vtables for parameters on the actual method.
234     param_vtables.push_all(subst::FnSpace,
235                            impl_vtables.get_slice(subst::FnSpace));
236
237     param_vtables
238 }
239
240 /// Translates the adapter that deconstructs a `Box<Trait>` object into
241 /// `Trait` so that a by-value self method can be called.
242 pub fn trans_unboxing_shim(bcx: &Block,
243                            llshimmedfn: ValueRef,
244                            method: &ty::Method,
245                            method_id: ast::DefId,
246                            substs: subst::Substs)
247                            -> ValueRef {
248     let _icx = push_ctxt("trans_unboxing_shim");
249     let ccx = bcx.ccx();
250     let tcx = bcx.tcx();
251
252     // Transform the self type to `Box<self_type>`.
253     let self_type = *method.fty.sig.inputs.get(0);
254     let boxed_self_type = ty::mk_uniq(tcx, self_type);
255     let boxed_function_type = ty::FnSig {
256         binder_id: method.fty.sig.binder_id,
257         inputs: method.fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
258             if i == 0 {
259                 boxed_self_type
260             } else {
261                 *typ
262             }
263         }).collect(),
264         output: method.fty.sig.output,
265         variadic: false,
266     };
267     let boxed_function_type = ty::BareFnTy {
268         fn_style: method.fty.fn_style,
269         abi: method.fty.abi,
270         sig: boxed_function_type,
271     };
272     let boxed_function_type =
273         ty::mk_bare_fn(tcx, boxed_function_type).subst(tcx, &substs);
274     let function_type =
275         ty::mk_bare_fn(tcx, method.fty.clone()).subst(tcx, &substs);
276
277     let function_name = ty::with_path(tcx, method_id, |path| {
278         link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim")
279     });
280     let llfn = decl_internal_rust_fn(ccx,
281                                      boxed_function_type,
282                                      function_name.as_slice());
283
284     let block_arena = TypedArena::new();
285     let empty_param_substs = param_substs::empty();
286     let return_type = ty::ty_fn_ret(boxed_function_type);
287     let fcx = new_fn_ctxt(ccx,
288                           llfn,
289                           -1,
290                           false,
291                           return_type,
292                           &empty_param_substs,
293                           None,
294                           &block_arena);
295     let mut bcx = init_function(&fcx, false, return_type);
296
297     // Create the substituted versions of the self type.
298     let arg_scope = fcx.push_custom_cleanup_scope();
299     let arg_scope_id = cleanup::CustomScope(arg_scope);
300     let boxed_arg_types = ty::ty_fn_args(boxed_function_type);
301     let boxed_self_type = *boxed_arg_types.get(0);
302     let arg_types = ty::ty_fn_args(function_type);
303     let self_type = *arg_types.get(0);
304     let boxed_self_kind = arg_kind(&fcx, boxed_self_type);
305
306     // Create a datum for self.
307     let llboxedself = unsafe {
308         llvm::LLVMGetParam(fcx.llfn, fcx.arg_pos(0) as u32)
309     };
310     let llboxedself = Datum::new(llboxedself,
311                                  boxed_self_type,
312                                  boxed_self_kind);
313     let boxed_self =
314         unpack_datum!(bcx,
315                       llboxedself.to_lvalue_datum_in_scope(bcx,
316                                                            "boxedself",
317                                                            arg_scope_id));
318
319     // This `Load` is needed because lvalue data are always by-ref.
320     let llboxedself = Load(bcx, boxed_self.val);
321
322     let llself = if type_is_immediate(ccx, self_type) {
323         let llboxedself = Load(bcx, llboxedself);
324         immediate_rvalue(llboxedself, self_type)
325     } else {
326         let llself = rvalue_scratch_datum(bcx, self_type, "self");
327         memcpy_ty(bcx, llself.val, llboxedself, self_type);
328         llself
329     };
330
331     // Make sure we don't free the box twice!
332     boxed_self.kind.post_store(bcx, boxed_self.val, boxed_self_type);
333
334     // Schedule a cleanup to free the box.
335     fcx.schedule_free_value(arg_scope_id,
336                             llboxedself,
337                             cleanup::HeapExchange,
338                             self_type);
339
340     // Now call the function.
341     let mut llshimmedargs = vec!(llself.val);
342     for i in range(1, arg_types.len()) {
343         llshimmedargs.push(unsafe {
344             llvm::LLVMGetParam(fcx.llfn, fcx.arg_pos(i) as u32)
345         });
346     }
347     bcx = trans_call_inner(bcx,
348                            None,
349                            function_type,
350                            |bcx, _| {
351                                Callee {
352                                    bcx: bcx,
353                                    data: Fn(llshimmedfn),
354                                }
355                            },
356                            ArgVals(llshimmedargs.as_slice()),
357                            match fcx.llretptr.get() {
358                                None => None,
359                                Some(llretptr) => Some(expr::SaveIn(llretptr)),
360                            }).bcx;
361
362     bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
363     finish_fn(&fcx, bcx, return_type);
364
365     llfn
366 }
367
368 pub fn trans_fn_ref_with_vtables(
369     bcx: &Block,                 //
370     def_id: ast::DefId,          // def id of fn
371     node: ExprOrMethodCall,      // node id of use of fn; may be zero if N/A
372     substs: subst::Substs,       // values for fn's ty params
373     vtables: typeck::vtable_res) // vtables for the call
374     -> ValueRef
375 {
376     /*!
377      * Translates a reference to a fn/method item, monomorphizing and
378      * inlining as it goes.
379      *
380      * # Parameters
381      *
382      * - `bcx`: the current block where the reference to the fn occurs
383      * - `def_id`: def id of the fn or method item being referenced
384      * - `node`: node id of the reference to the fn/method, if applicable.
385      *   This parameter may be zero; but, if so, the resulting value may not
386      *   have the right type, so it must be cast before being used.
387      * - `substs`: values for each of the fn/method's parameters
388      * - `vtables`: values for each bound on each of the type parameters
389      */
390
391     let _icx = push_ctxt("trans_fn_ref_with_vtables");
392     let ccx = bcx.ccx();
393     let tcx = bcx.tcx();
394
395     debug!("trans_fn_ref_with_vtables(bcx={}, def_id={}, node={:?}, \
396             substs={}, vtables={})",
397            bcx.to_str(),
398            def_id.repr(tcx),
399            node,
400            substs.repr(tcx),
401            vtables.repr(tcx));
402
403     assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
404
405     // Polytype of the function item (may have type params)
406     let fn_tpt = ty::lookup_item_type(tcx, def_id);
407
408     // Load the info for the appropriate trait if necessary.
409     match ty::trait_of_method(tcx, def_id) {
410         None => {}
411         Some(trait_id) => {
412             ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
413         }
414     }
415
416     // We need to do a bunch of special handling for default methods.
417     // We need to modify the def_id and our substs in order to monomorphize
418     // the function.
419     let (is_default, def_id, substs, vtables) =
420         match ty::provided_source(tcx, def_id) {
421         None => (false, def_id, substs, vtables),
422         Some(source_id) => {
423             // There are two relevant substitutions when compiling
424             // default methods. First, there is the substitution for
425             // the type parameters of the impl we are using and the
426             // method we are calling. This substitution is the substs
427             // argument we already have.
428             // In order to compile a default method, though, we need
429             // to consider another substitution: the substitution for
430             // the type parameters on trait; the impl we are using
431             // implements the trait at some particular type
432             // parameters, and we need to substitute for those first.
433             // So, what we need to do is find this substitution and
434             // compose it with the one we already have.
435
436             let impl_id = ty::method(tcx, def_id).container_id();
437             let method = ty::method(tcx, source_id);
438             let trait_ref = ty::impl_trait_ref(tcx, impl_id)
439                 .expect("could not find trait_ref for impl with \
440                          default methods");
441
442             // Compute the first substitution
443             let first_subst = make_substs_for_receiver_types(
444                 tcx, &*trait_ref, &*method);
445
446             // And compose them
447             let new_substs = first_subst.subst(tcx, &substs);
448
449             debug!("trans_fn_with_vtables - default method: \
450                     substs = {}, trait_subst = {}, \
451                     first_subst = {}, new_subst = {}, \
452                     vtables = {}",
453                    substs.repr(tcx), trait_ref.substs.repr(tcx),
454                    first_subst.repr(tcx), new_substs.repr(tcx),
455                    vtables.repr(tcx));
456
457             let param_vtables =
458                 resolve_default_method_vtables(bcx, impl_id, &substs, vtables);
459
460             debug!("trans_fn_with_vtables - default method: \
461                     param_vtables = {}",
462                    param_vtables.repr(tcx));
463
464             (true, source_id, new_substs, param_vtables)
465         }
466     };
467
468     // Check whether this fn has an inlined copy and, if so, redirect
469     // def_id to the local id of the inlined copy.
470     let def_id = {
471         if def_id.krate != ast::LOCAL_CRATE {
472             inline::maybe_instantiate_inline(ccx, def_id)
473         } else {
474             def_id
475         }
476     };
477
478     // We must monomorphise if the fn has type parameters or is a default method.
479     let must_monomorphise = !substs.types.is_empty() || is_default;
480
481     // Create a monomorphic version of generic functions
482     if must_monomorphise {
483         // Should be either intra-crate or inlined.
484         assert_eq!(def_id.krate, ast::LOCAL_CRATE);
485
486         let opt_ref_id = match node {
487             ExprId(id) => if id != 0 { Some(id) } else { None },
488             MethodCall(_) => None,
489         };
490
491         let (val, must_cast) =
492             monomorphize::monomorphic_fn(ccx, def_id, &substs,
493                                          vtables, opt_ref_id);
494         let mut val = val;
495         if must_cast && node != ExprId(0) {
496             // Monotype of the REFERENCE to the function (type params
497             // are subst'd)
498             let ref_ty = match node {
499                 ExprId(id) => node_id_type(bcx, id),
500                 MethodCall(method_call) => {
501                     let t = bcx.tcx().method_map.borrow().get(&method_call).ty;
502                     monomorphize_type(bcx, t)
503                 }
504             };
505
506             val = PointerCast(
507                 bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
508         }
509         return val;
510     }
511
512     // Find the actual function pointer.
513     let mut val = {
514         if def_id.krate == ast::LOCAL_CRATE {
515             // Internal reference.
516             get_item_val(ccx, def_id.node)
517         } else {
518             // External reference.
519             trans_external_path(ccx, def_id, fn_tpt.ty)
520         }
521     };
522
523     // This is subtle and surprising, but sometimes we have to bitcast
524     // the resulting fn pointer.  The reason has to do with external
525     // functions.  If you have two crates that both bind the same C
526     // library, they may not use precisely the same types: for
527     // example, they will probably each declare their own structs,
528     // which are distinct types from LLVM's point of view (nominal
529     // types).
530     //
531     // Now, if those two crates are linked into an application, and
532     // they contain inlined code, you can wind up with a situation
533     // where both of those functions wind up being loaded into this
534     // application simultaneously. In that case, the same function
535     // (from LLVM's point of view) requires two types. But of course
536     // LLVM won't allow one function to have two types.
537     //
538     // What we currently do, therefore, is declare the function with
539     // one of the two types (whichever happens to come first) and then
540     // bitcast as needed when the function is referenced to make sure
541     // it has the type we expect.
542     //
543     // This can occur on either a crate-local or crate-external
544     // reference. It also occurs when testing libcore and in some
545     // other weird situations. Annoying.
546     let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty);
547     let llptrty = llty.ptr_to();
548     if val_ty(val) != llptrty {
549         val = BitCast(bcx, val, llptrty);
550     }
551
552     val
553 }
554
555 // ______________________________________________________________________
556 // Translating calls
557
558 pub fn trans_call<'a>(
559                   in_cx: &'a Block<'a>,
560                   call_ex: &ast::Expr,
561                   f: &ast::Expr,
562                   args: CallArgs,
563                   dest: expr::Dest)
564                   -> &'a Block<'a> {
565     let _icx = push_ctxt("trans_call");
566     trans_call_inner(in_cx,
567                      Some(common::expr_info(call_ex)),
568                      expr_ty(in_cx, f),
569                      |cx, _| trans(cx, f),
570                      args,
571                      Some(dest)).bcx
572 }
573
574 pub fn trans_method_call<'a>(
575                          bcx: &'a Block<'a>,
576                          call_ex: &ast::Expr,
577                          rcvr: &ast::Expr,
578                          args: CallArgs,
579                          dest: expr::Dest)
580                          -> &'a Block<'a> {
581     let _icx = push_ctxt("trans_method_call");
582     debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx()));
583     let method_call = MethodCall::expr(call_ex.id);
584     let method_ty = bcx.tcx().method_map.borrow().get(&method_call).ty;
585     trans_call_inner(
586         bcx,
587         Some(common::expr_info(call_ex)),
588         monomorphize_type(bcx, method_ty),
589         |cx, arg_cleanup_scope| {
590             meth::trans_method_callee(cx, method_call, Some(rcvr), arg_cleanup_scope)
591         },
592         args,
593         Some(dest)).bcx
594 }
595
596 pub fn trans_lang_call<'a>(
597                        bcx: &'a Block<'a>,
598                        did: ast::DefId,
599                        args: &[ValueRef],
600                        dest: Option<expr::Dest>)
601                        -> Result<'a> {
602     let fty = if did.krate == ast::LOCAL_CRATE {
603         ty::node_id_to_type(bcx.tcx(), did.node)
604     } else {
605         csearch::get_type(bcx.tcx(), did).ty
606     };
607     callee::trans_call_inner(bcx,
608                              None,
609                              fty,
610                              |bcx, _| {
611                                 trans_fn_ref_with_vtables_to_callee(bcx,
612                                                                     did,
613                                                                     0,
614                                                                     subst::Substs::empty(),
615                                                                     VecPerParamSpace::empty())
616                              },
617                              ArgVals(args),
618                              dest)
619 }
620
621 pub fn trans_call_inner<'a>(
622                         bcx: &'a Block<'a>,
623                         call_info: Option<NodeInfo>,
624                         callee_ty: ty::t,
625                         get_callee: |bcx: &'a Block<'a>,
626                                      arg_cleanup_scope: cleanup::ScopeId|
627                                      -> Callee<'a>,
628                         args: CallArgs,
629                         dest: Option<expr::Dest>)
630                         -> Result<'a> {
631     /*!
632      * This behemoth of a function translates function calls.
633      * Unfortunately, in order to generate more efficient LLVM
634      * output at -O0, it has quite a complex signature (refactoring
635      * this into two functions seems like a good idea).
636      *
637      * In particular, for lang items, it is invoked with a dest of
638      * None, and in that case the return value contains the result of
639      * the fn. The lang item must not return a structural type or else
640      * all heck breaks loose.
641      *
642      * For non-lang items, `dest` is always Some, and hence the result
643      * is written into memory somewhere. Nonetheless we return the
644      * actual return value of the function.
645      */
646
647     // Introduce a temporary cleanup scope that will contain cleanups
648     // for the arguments while they are being evaluated. The purpose
649     // this cleanup is to ensure that, should a failure occur while
650     // evaluating argument N, the values for arguments 0...N-1 are all
651     // cleaned up. If no failure occurs, the values are handed off to
652     // the callee, and hence none of the cleanups in this temporary
653     // scope will ever execute.
654     let fcx = bcx.fcx;
655     let ccx = fcx.ccx;
656     let arg_cleanup_scope = fcx.push_custom_cleanup_scope();
657
658     let callee = get_callee(bcx, cleanup::CustomScope(arg_cleanup_scope));
659     let mut bcx = callee.bcx;
660
661     let (abi, ret_ty) = match ty::get(callee_ty).sty {
662         ty::ty_bare_fn(ref f) => (f.abi, f.sig.output),
663         ty::ty_closure(ref f) => (synabi::Rust, f.sig.output),
664         _ => fail!("expected bare rust fn or closure in trans_call_inner")
665     };
666
667     let (llfn, llenv, llself) = match callee.data {
668         Fn(llfn) => {
669             (llfn, None, None)
670         }
671         TraitMethod(d) => {
672             (d.llfn, None, Some(d.llself))
673         }
674         Closure(d) => {
675             // Closures are represented as (llfn, llclosure) pair:
676             // load the requisite values out.
677             let pair = d.to_llref();
678             let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
679             let llfn = Load(bcx, llfn);
680             let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
681             let llenv = Load(bcx, llenv);
682             (llfn, Some(llenv), None)
683         }
684         Intrinsic(node, substs) => {
685             assert!(abi == synabi::RustIntrinsic);
686             assert!(dest.is_some());
687
688             return intrinsic::trans_intrinsic_call(bcx, node, callee_ty,
689                                                    arg_cleanup_scope, args,
690                                                    dest.unwrap(), substs);
691         }
692     };
693
694     // Intrinsics should not become actual functions.
695     // We trans them in place in `trans_intrinsic_call`
696     assert!(abi != synabi::RustIntrinsic);
697
698     // Generate a location to store the result. If the user does
699     // not care about the result, just make a stack slot.
700     let opt_llretslot = match dest {
701         None => {
702             assert!(!type_of::return_uses_outptr(ccx, ret_ty));
703             None
704         }
705         Some(expr::SaveIn(dst)) => Some(dst),
706         Some(expr::Ignore) => {
707             if !type_is_zero_size(ccx, ret_ty) {
708                 Some(alloc_ty(bcx, ret_ty, "__llret"))
709             } else {
710                 let llty = type_of::type_of(ccx, ret_ty);
711                 Some(C_undef(llty.ptr_to()))
712             }
713         }
714     };
715
716     let mut llresult = unsafe {
717         llvm::LLVMGetUndef(Type::nil(ccx).ptr_to().to_ref())
718     };
719
720     // The code below invokes the function, using either the Rust
721     // conventions (if it is a rust fn) or the native conventions
722     // (otherwise).  The important part is that, when all is sad
723     // and done, either the return value of the function will have been
724     // written in opt_llretslot (if it is Some) or `llresult` will be
725     // set appropriately (otherwise).
726     if abi == synabi::Rust {
727         let mut llargs = Vec::new();
728
729         // Push the out-pointer if we use an out-pointer for this
730         // return type, otherwise push "undef".
731         if type_of::return_uses_outptr(ccx, ret_ty) {
732             llargs.push(opt_llretslot.unwrap());
733         }
734
735         // Push the environment (or a trait object's self).
736         match (llenv, llself) {
737             (Some(llenv), None) => {
738                 llargs.push(llenv)
739             },
740             (None, Some(llself)) => llargs.push(llself),
741             _ => {}
742         }
743
744         // Push the arguments.
745         bcx = trans_args(bcx, args, callee_ty, &mut llargs,
746                          cleanup::CustomScope(arg_cleanup_scope),
747                          llself.is_some());
748
749         fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
750
751         // Invoke the actual rust fn and update bcx/llresult.
752         let (llret, b) = base::invoke(bcx,
753                                       llfn,
754                                       llargs,
755                                       callee_ty,
756                                       call_info);
757         bcx = b;
758         llresult = llret;
759
760         // If the Rust convention for this type is return via
761         // the return value, copy it into llretslot.
762         match opt_llretslot {
763             Some(llretslot) => {
764                 if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
765                     !type_is_zero_size(bcx.ccx(), ret_ty)
766                 {
767                     store_ty(bcx, llret, llretslot, ret_ty)
768                 }
769             }
770             None => {}
771         }
772     } else {
773         // Lang items are the only case where dest is None, and
774         // they are always Rust fns.
775         assert!(dest.is_some());
776
777         let mut llargs = Vec::new();
778         let arg_tys = match args {
779             ArgExprs(a) => a.iter().map(|x| expr_ty(bcx, &**x)).collect(),
780             _ => fail!("expected arg exprs.")
781         };
782         bcx = trans_args(bcx, args, callee_ty, &mut llargs,
783                          cleanup::CustomScope(arg_cleanup_scope), false);
784         fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
785         bcx = foreign::trans_native_call(bcx, callee_ty,
786                                          llfn, opt_llretslot.unwrap(),
787                                          llargs.as_slice(), arg_tys);
788     }
789
790     // If the caller doesn't care about the result of this fn call,
791     // drop the temporary slot we made.
792     match dest {
793         None => {
794             assert!(!type_of::return_uses_outptr(bcx.ccx(), ret_ty));
795         }
796         Some(expr::Ignore) => {
797             // drop the value if it is not being saved.
798             bcx = glue::drop_ty(bcx, opt_llretslot.unwrap(), ret_ty);
799         }
800         Some(expr::SaveIn(_)) => { }
801     }
802
803     if ty::type_is_bot(ret_ty) {
804         Unreachable(bcx);
805     }
806
807     Result::new(bcx, llresult)
808 }
809
810 pub enum CallArgs<'a> {
811     // Supply value of arguments as a list of expressions that must be
812     // translated. This is used in the common case of `foo(bar, qux)`.
813     ArgExprs(&'a [Gc<ast::Expr>]),
814
815     // Supply value of arguments as a list of LLVM value refs; frequently
816     // used with lang items and so forth, when the argument is an internal
817     // value.
818     ArgVals(&'a [ValueRef]),
819
820     // For overloaded operators: `(lhs, Option(rhs, rhs_id))`. `lhs`
821     // is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of
822     // the right-hand-side (if any).
823     ArgOverloadedOp(Datum<Expr>, Option<(Datum<Expr>, ast::NodeId)>),
824 }
825
826 pub fn trans_args<'a>(cx: &'a Block<'a>,
827                       args: CallArgs,
828                       fn_ty: ty::t,
829                       llargs: &mut Vec<ValueRef> ,
830                       arg_cleanup_scope: cleanup::ScopeId,
831                       ignore_self: bool)
832                       -> &'a Block<'a> {
833     let _icx = push_ctxt("trans_args");
834     let arg_tys = ty::ty_fn_args(fn_ty);
835     let variadic = ty::fn_is_variadic(fn_ty);
836
837     let mut bcx = cx;
838
839     // First we figure out the caller's view of the types of the arguments.
840     // This will be needed if this is a generic call, because the callee has
841     // to cast her view of the arguments to the caller's view.
842     match args {
843         ArgExprs(arg_exprs) => {
844             let num_formal_args = arg_tys.len();
845             for (i, arg_expr) in arg_exprs.iter().enumerate() {
846                 if i == 0 && ignore_self {
847                     continue;
848                 }
849                 let arg_ty = if i >= num_formal_args {
850                     assert!(variadic);
851                     expr_ty_adjusted(cx, &**arg_expr)
852                 } else {
853                     *arg_tys.get(i)
854                 };
855
856                 let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &**arg_expr));
857                 llargs.push(unpack_result!(bcx, {
858                     trans_arg_datum(bcx, arg_ty, arg_datum,
859                                     arg_cleanup_scope,
860                                     DontAutorefArg)
861                 }));
862             }
863         }
864         ArgOverloadedOp(lhs, rhs) => {
865             assert!(!variadic);
866
867             llargs.push(unpack_result!(bcx, {
868                 trans_arg_datum(bcx, *arg_tys.get(0), lhs,
869                                 arg_cleanup_scope,
870                                 DontAutorefArg)
871             }));
872
873             match rhs {
874                 Some((rhs, rhs_id)) => {
875                     assert_eq!(arg_tys.len(), 2);
876
877                     llargs.push(unpack_result!(bcx, {
878                         trans_arg_datum(bcx, *arg_tys.get(1), rhs,
879                                         arg_cleanup_scope,
880                                         DoAutorefArg(rhs_id))
881                     }));
882                 }
883                 None => assert_eq!(arg_tys.len(), 1)
884             }
885         }
886         ArgVals(vs) => {
887             llargs.push_all(vs);
888         }
889     }
890
891     bcx
892 }
893
894 pub enum AutorefArg {
895     DontAutorefArg,
896     DoAutorefArg(ast::NodeId)
897 }
898
899 pub fn trans_arg_datum<'a>(
900                       bcx: &'a Block<'a>,
901                       formal_arg_ty: ty::t,
902                       arg_datum: Datum<Expr>,
903                       arg_cleanup_scope: cleanup::ScopeId,
904                       autoref_arg: AutorefArg)
905                       -> Result<'a> {
906     let _icx = push_ctxt("trans_arg_datum");
907     let mut bcx = bcx;
908     let ccx = bcx.ccx();
909
910     debug!("trans_arg_datum({})",
911            formal_arg_ty.repr(bcx.tcx()));
912
913     let arg_datum_ty = arg_datum.ty;
914
915     debug!("   arg datum: {}", arg_datum.to_string(bcx.ccx()));
916
917     let mut val;
918     if ty::type_is_bot(arg_datum_ty) {
919         // For values of type _|_, we generate an
920         // "undef" value, as such a value should never
921         // be inspected. It's important for the value
922         // to have type lldestty (the callee's expected type).
923         let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
924         unsafe {
925             val = llvm::LLVMGetUndef(llformal_arg_ty.to_ref());
926         }
927     } else {
928         // FIXME(#3548) use the adjustments table
929         match autoref_arg {
930             DoAutorefArg(arg_id) => {
931                 // We will pass argument by reference
932                 // We want an lvalue, so that we can pass by reference and
933                 let arg_datum = unpack_datum!(
934                     bcx, arg_datum.to_lvalue_datum(bcx, "arg", arg_id));
935                 val = arg_datum.val;
936             }
937             DontAutorefArg => {
938                 // Make this an rvalue, since we are going to be
939                 // passing ownership.
940                 let arg_datum = unpack_datum!(
941                     bcx, arg_datum.to_rvalue_datum(bcx, "arg"));
942
943                 // Now that arg_datum is owned, get it into the appropriate
944                 // mode (ref vs value).
945                 let arg_datum = unpack_datum!(
946                     bcx, arg_datum.to_appropriate_datum(bcx));
947
948                 // Technically, ownership of val passes to the callee.
949                 // However, we must cleanup should we fail before the
950                 // callee is actually invoked.
951                 val = arg_datum.add_clean(bcx.fcx, arg_cleanup_scope);
952             }
953         }
954
955         if formal_arg_ty != arg_datum_ty {
956             // this could happen due to e.g. subtyping
957             let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
958             debug!("casting actual type ({}) to match formal ({})",
959                    bcx.val_to_string(val), bcx.llty_str(llformal_arg_ty));
960             val = PointerCast(bcx, val, llformal_arg_ty);
961         }
962     }
963
964     debug!("--- trans_arg_datum passing {}", bcx.val_to_string(val));
965     Result::new(bcx, val)
966 }