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.
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.
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
23 use lib::llvm::ValueRef;
25 use metadata::csearch;
26 use middle::trans::base;
27 use middle::trans::base::*;
28 use middle::trans::build::*;
29 use middle::trans::callee;
30 use middle::trans::common;
31 use middle::trans::common::*;
32 use middle::trans::datum::*;
33 use middle::trans::datum::Datum;
34 use middle::trans::expr;
35 use middle::trans::glue;
36 use middle::trans::inline;
37 use middle::trans::meth;
38 use middle::trans::monomorphize;
39 use middle::trans::type_of;
41 use middle::subst::Subst;
43 use middle::typeck::coherence::make_substs_for_receiver_types;
44 use util::ppaux::Repr;
46 use middle::trans::type_::Type;
51 use syntax::visit::Visitor;
53 // Represents a (possibly monomorphized) top-level fn item or method
54 // item. Note that this is just the fn-ptr and is not a Rust closure
55 // value (which is a pair).
60 pub struct MethodData {
63 temp_cleanup: Option<ValueRef>,
64 self_mode: ty::SelfMode,
78 pub fn trans(bcx: @mut Block, expr: @ast::expr) -> Callee {
79 let _icx = push_ctxt("trans_callee");
80 debug!("callee::trans(expr=%s)", expr.repr(bcx.tcx()));
82 // pick out special kinds of expressions that can be called:
84 ast::expr_path(_) => {
85 return trans_def(bcx, bcx.def(expr.id), expr);
90 // any other expressions are closures:
91 return datum_callee(bcx, expr);
93 fn datum_callee(bcx: @mut Block, expr: @ast::expr) -> Callee {
94 let DatumBlock {bcx, datum} = expr::trans_to_datum(bcx, expr);
95 match ty::get(datum.ty).sty {
96 ty::ty_bare_fn(*) => {
97 let llval = datum.to_appropriate_llval(bcx);
98 return Callee {bcx: bcx, data: Fn(FnData {llfn: llval})};
100 ty::ty_closure(*) => {
101 return Callee {bcx: bcx, data: Closure(datum)};
104 bcx.tcx().sess.span_bug(
106 fmt!("Type of callee is neither bare-fn nor closure: %s",
107 bcx.ty_to_str(datum.ty)));
112 fn fn_callee(bcx: @mut Block, fd: FnData) -> Callee {
113 return Callee {bcx: bcx, data: Fn(fd)};
116 fn trans_def(bcx: @mut Block, def: ast::def, ref_expr: @ast::expr) -> Callee {
118 ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
119 fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id))
121 ast::def_static_method(impl_did, Some(trait_did), _) => {
122 fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did,
126 ast::def_variant(tid, vid) => {
127 // nullary variants are not callable
128 assert!(ty::enum_variant_with_id(bcx.tcx(),
130 vid).args.len() > 0u);
131 fn_callee(bcx, trans_fn_ref(bcx, vid, ref_expr.id))
133 ast::def_struct(def_id) => {
134 fn_callee(bcx, trans_fn_ref(bcx, def_id, ref_expr.id))
138 ast::def_binding(*) |
140 ast::def_self(*) => {
141 datum_callee(bcx, ref_expr)
143 ast::def_mod(*) | ast::def_foreign_mod(*) | ast::def_trait(*) |
144 ast::def_static(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
145 ast::def_use(*) | ast::def_typaram_binder(*) |
146 ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) |
147 ast::def_self_ty(*) | ast::def_method(*) => {
148 bcx.tcx().sess.span_bug(
150 fmt!("Cannot translate def %? \
151 to a callable thing!", def));
157 pub fn trans_fn_ref_to_callee(bcx: @mut Block,
159 ref_id: ast::NodeId) -> Callee {
161 data: Fn(trans_fn_ref(bcx, def_id, ref_id))}
164 pub fn trans_fn_ref(bcx: @mut Block,
166 ref_id: ast::NodeId) -> FnData {
169 * Translates a reference (with id `ref_id`) to the fn/method
170 * with id `def_id` into a function pointer. This may require
171 * monomorphization or inlining. */
173 let _icx = push_ctxt("trans_fn_ref");
175 let type_params = node_id_type_params(bcx, ref_id);
176 let vtables = node_vtables(bcx, ref_id);
177 debug!("trans_fn_ref(def_id=%s, ref_id=%?, type_params=%s, vtables=%s)",
178 def_id.repr(bcx.tcx()), ref_id, type_params.repr(bcx.tcx()),
179 vtables.repr(bcx.tcx()));
180 trans_fn_ref_with_vtables(bcx, def_id, ref_id, type_params, vtables)
183 pub fn trans_fn_ref_with_vtables_to_callee(
187 type_params: &[ty::t],
188 vtables: Option<typeck::vtable_res>)
191 data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ref_id,
192 type_params, vtables))}
195 fn resolve_default_method_vtables(bcx: @mut Block,
196 impl_id: ast::def_id,
199 impl_vtables: Option<typeck::vtable_res>)
200 -> (typeck::vtable_res, typeck::vtable_param_res) {
202 // Get the vtables that the impl implements the trait at
203 let impl_res = ty::lookup_impl_vtables(bcx.tcx(), impl_id);
205 // Build up a param_substs that we are going to resolve the
206 // trait_vtables under.
207 let param_substs = Some(@param_substs {
208 tys: substs.tps.clone(),
209 self_ty: substs.self_ty,
210 vtables: impl_vtables,
214 let trait_vtables_fixed = resolve_vtables_under_param_substs(
215 bcx.tcx(), param_substs, impl_res.trait_vtables);
217 // Now we pull any vtables for parameters on the actual method.
218 let num_method_vtables = method.generics.type_param_defs.len();
219 let method_vtables = match impl_vtables {
221 let num_impl_type_parameters =
222 vtables.len() - num_method_vtables;
223 vtables.tailn(num_impl_type_parameters).to_owned()
225 None => vec::from_elem(num_method_vtables, @~[])
228 let param_vtables = @(*trait_vtables_fixed + method_vtables);
230 let self_vtables = resolve_param_vtables_under_param_substs(
231 bcx.tcx(), param_substs, impl_res.self_vtables);
233 (param_vtables, self_vtables)
237 pub fn trans_fn_ref_with_vtables(
239 def_id: ast::def_id, // def id of fn
240 ref_id: ast::NodeId, // node id of use of fn; may be zero if N/A
241 type_params: &[ty::t], // values for fn's ty params
242 vtables: Option<typeck::vtable_res>) // vtables for the call
246 // Translates a reference to a fn/method item, monomorphizing and
247 // inlining as it goes.
251 // - `bcx`: the current block where the reference to the fn occurs
252 // - `def_id`: def id of the fn or method item being referenced
253 // - `ref_id`: node id of the reference to the fn/method, if applicable.
254 // This parameter may be zero; but, if so, the resulting value may not
255 // have the right type, so it must be cast before being used.
256 // - `type_params`: values for each of the fn/method's type parameters
257 // - `vtables`: values for each bound on each of the type parameters
259 let _icx = push_ctxt("trans_fn_ref_with_vtables");
263 debug!("trans_fn_ref_with_vtables(bcx=%s, def_id=%s, ref_id=%?, \
264 type_params=%s, vtables=%s)",
266 def_id.repr(bcx.tcx()),
268 type_params.repr(bcx.tcx()),
269 vtables.repr(bcx.tcx()));
271 assert!(type_params.iter().all(|t| !ty::type_needs_infer(*t)));
273 // Polytype of the function item (may have type params)
274 let fn_tpt = ty::lookup_item_type(tcx, def_id);
276 let substs = ty::substs { regions: ty::ErasedRegions,
278 tps: /*bad*/ type_params.to_owned() };
280 // We need to do a bunch of special handling for default methods.
281 // We need to modify the def_id and our substs in order to monomorphize
283 let (is_default, def_id, substs, self_vtables, vtables) =
284 match ty::provided_source(tcx, def_id) {
285 None => (false, def_id, substs, None, vtables),
287 // There are two relevant substitutions when compiling
288 // default methods. First, there is the substitution for
289 // the type parameters of the impl we are using and the
290 // method we are calling. This substitution is the substs
291 // argument we already have.
292 // In order to compile a default method, though, we need
293 // to consider another substitution: the substitution for
294 // the type parameters on trait; the impl we are using
295 // implements the trait at some particular type
296 // parameters, and we need to substitute for those first.
297 // So, what we need to do is find this substitution and
298 // compose it with the one we already have.
300 let impl_id = ty::method(tcx, def_id).container_id;
301 let method = ty::method(tcx, source_id);
302 let trait_ref = ty::impl_trait_ref(tcx, impl_id)
303 .expect("could not find trait_ref for impl with \
306 // Compute the first substitution
307 let first_subst = make_substs_for_receiver_types(
308 tcx, impl_id, trait_ref, method);
311 let new_substs = first_subst.subst(tcx, &substs);
314 let (param_vtables, self_vtables) =
315 resolve_default_method_vtables(bcx, impl_id,
316 method, &substs, vtables);
318 debug!("trans_fn_with_vtables - default method: \
319 substs = %s, trait_subst = %s, \
320 first_subst = %s, new_subst = %s, \
322 self_vtable = %s, param_vtables = %s",
323 substs.repr(tcx), trait_ref.substs.repr(tcx),
324 first_subst.repr(tcx), new_substs.repr(tcx),
326 self_vtables.repr(tcx), param_vtables.repr(tcx));
329 new_substs, Some(self_vtables), Some(param_vtables))
333 // Check whether this fn has an inlined copy and, if so, redirect
334 // def_id to the local id of the inlined copy.
336 if def_id.crate != ast::LOCAL_CRATE {
337 inline::maybe_instantiate_inline(ccx, def_id)
343 // We must monomorphise if the fn has type parameters, is a rust
344 // intrinsic, or is a default method. In particular, if we see an
345 // intrinsic that is inlined from a different crate, we want to reemit the
346 // intrinsic instead of trying to call it in the other crate.
347 let must_monomorphise;
348 if type_params.len() > 0 || is_default {
349 must_monomorphise = true;
350 } else if def_id.crate == ast::LOCAL_CRATE {
351 let map_node = session::expect(
353 ccx.tcx.items.find(&def_id.node),
354 || fmt!("local item should be in ast map"));
357 ast_map::node_foreign_item(_, abis, _, _) => {
358 must_monomorphise = abis.is_intrinsic()
361 must_monomorphise = false;
365 must_monomorphise = false;
368 // Create a monomorphic verison of generic functions
369 if must_monomorphise {
370 // Should be either intra-crate or inlined.
371 assert_eq!(def_id.crate, ast::LOCAL_CRATE);
373 let (val, must_cast) =
374 monomorphize::monomorphic_fn(ccx, def_id, &substs,
375 vtables, self_vtables,
378 if must_cast && ref_id != 0 {
379 // Monotype of the REFERENCE to the function (type params
381 let ref_ty = common::node_id_type(bcx, ref_id);
384 bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
386 return FnData {llfn: val};
389 // Find the actual function pointer.
391 if def_id.crate == ast::LOCAL_CRATE {
392 // Internal reference.
393 get_item_val(ccx, def_id.node)
395 // External reference.
396 trans_external_path(ccx, def_id, fn_tpt.ty)
400 return FnData {llfn: val};
403 // ______________________________________________________________________
406 pub fn trans_call(in_cx: @mut Block,
413 let _icx = push_ctxt("trans_call");
414 trans_call_inner(in_cx,
417 node_id_type(in_cx, id),
424 pub fn trans_method_call(in_cx: @mut Block,
426 callee_id: ast::NodeId,
431 let _icx = push_ctxt("trans_method_call");
432 debug!("trans_method_call(call_ex=%s, rcvr=%s)",
433 call_ex.repr(in_cx.tcx()),
434 rcvr.repr(in_cx.tcx()));
438 node_id_type(in_cx, callee_id),
439 expr_ty(in_cx, call_ex),
441 match cx.ccx().maps.method_map.find_copy(&call_ex.id) {
443 debug!("origin for %s: %s",
444 call_ex.repr(in_cx.tcx()),
445 origin.repr(in_cx.tcx()));
447 meth::trans_method_callee(cx,
453 cx.tcx().sess.span_bug(call_ex.span, "method call expr wasn't in method map")
462 pub fn trans_lang_call(bcx: @mut Block,
465 dest: Option<expr::Dest>)
467 let fty = if did.crate == ast::LOCAL_CRATE {
468 ty::node_id_to_type(bcx.ccx().tcx, did.node)
470 csearch::get_type(bcx.ccx().tcx, did).ty
472 let rty = ty::ty_fn_ret(fty);
473 callee::trans_call_inner(bcx,
478 trans_fn_ref_with_vtables_to_callee(bcx,
489 pub fn trans_lang_call_with_type_params(bcx: @mut Block,
492 type_params: &[ty::t],
496 if did.crate == ast::LOCAL_CRATE {
497 fty = ty::node_id_to_type(bcx.tcx(), did.node);
499 fty = csearch::get_type(bcx.tcx(), did).ty;
502 let rty = ty::ty_fn_ret(fty);
503 return callee::trans_call_inner(
507 trans_fn_ref_with_vtables_to_callee(bcx, did, 0,
514 let substituted = ty::subst_tps(callee.bcx.tcx(),
518 let llfnty = type_of::type_of(callee.bcx.ccx(),
520 new_llval = PointerCast(callee.bcx, fn_data.llfn, llfnty);
524 Callee { bcx: callee.bcx, data: Fn(FnData { llfn: new_llval }) }
526 ArgVals(args), Some(dest), DontAutorefArg).bcx;
530 struct CalleeTranslationVisitor;
532 impl Visitor<@mut bool> for CalleeTranslationVisitor {
534 fn visit_item(&mut self, _:@ast::item, _:@mut bool) { }
536 fn visit_expr(&mut self, e:@ast::expr, cx:@mut bool) {
540 ast::expr_ret(_) => *cx = true,
541 _ => visit::walk_expr(self, e, cx),
548 pub fn body_contains_ret(body: &ast::Block) -> bool {
550 let mut v = CalleeTranslationVisitor;
551 visit::walk_block(&mut v, body, cx);
555 // See [Note-arg-mode]
556 pub fn trans_call_inner(in_cx: @mut Block,
557 call_info: Option<NodeInfo>,
560 get_callee: &fn(@mut Block) -> Callee,
562 dest: Option<expr::Dest>,
563 autoref_arg: AutorefArg)
565 do base::with_scope_result(in_cx, call_info, "call") |cx| {
566 let callee = get_callee(cx);
567 let mut bcx = callee.bcx;
570 let (llfn, llenv) = unsafe {
573 (d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to().to_ref()))
576 // Weird but true: we pass self in the *environment* slot!
580 // Closures are represented as (llfn, llclosure) pair:
581 // load the requisite values out.
582 let pair = d.to_ref_llval(bcx);
583 let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
584 let llfn = Load(bcx, llfn);
585 let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
586 let llenv = Load(bcx, llenv);
592 let llretslot = trans_ret_slot(bcx, fn_expr_ty, dest);
594 let mut llargs = ~[];
596 if !ty::type_is_immediate(bcx.tcx(), ret_ty) {
597 llargs.push(llretslot);
601 bcx = trans_args(bcx, args, fn_expr_ty, autoref_arg, &mut llargs);
603 // Now that the arguments have finished evaluating, we need to revoke
604 // the cleanup for the self argument
607 for &v in d.temp_cleanup.iter() {
608 revoke_clean(bcx, v);
614 // Uncomment this to debug calls.
616 printfln!("calling: %s", bcx.val_to_str(llfn));
617 for llarg in llargs.iter() {
618 printfln!("arg: %s", bcx.val_to_str(*llarg));
623 // If the block is terminated, then one or more of the args
624 // has type _|_. Since that means it diverges, the code for
625 // the call itself is unreachable.
626 let (llresult, new_bcx) = base::invoke(bcx, llfn, llargs);
630 None => { assert!(ty::type_is_immediate(bcx.tcx(), ret_ty)) }
631 Some(expr::Ignore) => {
632 // drop the value if it is not being saved.
633 if ty::type_needs_drop(bcx.tcx(), ret_ty) {
634 if ty::type_is_immediate(bcx.tcx(), ret_ty) {
635 let llscratchptr = alloc_ty(bcx, ret_ty, "__ret");
636 Store(bcx, llresult, llscratchptr);
637 bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
639 bcx = glue::drop_ty(bcx, llretslot, ret_ty);
643 Some(expr::SaveIn(lldest)) => {
644 // If this is an immediate, store into the result location.
645 // (If this was not an immediate, the result will already be
646 // directly written into the output slot.)
647 if ty::type_is_immediate(bcx.tcx(), ret_ty) {
648 Store(bcx, llresult, lldest);
653 if ty::type_is_bot(ret_ty) {
661 pub enum CallArgs<'self> {
662 ArgExprs(&'self [@ast::expr]),
663 ArgVals(&'self [ValueRef])
666 pub fn trans_ret_slot(bcx: @mut Block, fn_ty: ty::t, dest: Option<expr::Dest>)
668 let retty = ty::ty_fn_ret(fn_ty);
671 Some(expr::SaveIn(dst)) => dst,
673 if ty::type_is_immediate(bcx.tcx(), retty) {
675 llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
678 alloc_ty(bcx, retty, "__trans_ret_slot")
684 pub fn trans_args(cx: @mut Block,
687 autoref_arg: AutorefArg,
688 llargs: &mut ~[ValueRef]) -> @mut Block
690 let _icx = push_ctxt("trans_args");
691 let mut temp_cleanups = ~[];
692 let arg_tys = ty::ty_fn_args(fn_ty);
696 // First we figure out the caller's view of the types of the arguments.
697 // This will be needed if this is a generic call, because the callee has
698 // to cast her view of the arguments to the caller's view.
700 ArgExprs(arg_exprs) => {
701 for (i, arg_expr) in arg_exprs.iter().enumerate() {
702 let arg_val = unpack_result!(bcx, {
710 llargs.push(arg_val);
718 // now that all arguments have been successfully built, we can revoke any
719 // temporary cleanups, as they are only needed if argument construction
720 // should fail (for example, cleanup of copy mode args).
721 for c in temp_cleanups.iter() {
722 revoke_clean(bcx, *c)
728 pub enum AutorefArg {
733 // temp_cleanups: cleanups that should run only if failure occurs before the
735 pub fn trans_arg_expr(bcx: @mut Block,
736 formal_arg_ty: ty::t,
737 self_mode: ty::SelfMode,
738 arg_expr: @ast::expr,
739 temp_cleanups: &mut ~[ValueRef],
740 autoref_arg: AutorefArg) -> Result {
741 let _icx = push_ctxt("trans_arg_expr");
744 debug!("trans_arg_expr(formal_arg_ty=(%s), self_mode=%?, arg_expr=%s)",
745 formal_arg_ty.repr(bcx.tcx()),
747 arg_expr.repr(bcx.tcx()));
749 // translate the arg expr to a datum
750 let arg_datumblock = expr::trans_to_datum(bcx, arg_expr);
751 let arg_datum = arg_datumblock.datum;
752 let bcx = arg_datumblock.bcx;
754 debug!(" arg datum: %s", arg_datum.to_str(bcx.ccx()));
757 if ty::type_is_bot(arg_datum.ty) {
758 // For values of type _|_, we generate an
759 // "undef" value, as such a value should never
760 // be inspected. It's important for the value
761 // to have type lldestty (the callee's expected type).
762 let llformal_arg_ty = type_of::type_of(ccx, formal_arg_ty);
764 val = llvm::LLVMGetUndef(llformal_arg_ty.to_ref());
767 // FIXME(#3548) use the adjustments table
770 val = arg_datum.to_ref_llval(bcx);
773 let need_scratch = ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
774 (bcx.expr_is_lval(arg_expr) &&
775 arg_datum.appropriate_mode(bcx.tcx()).is_by_ref());
777 let arg_datum = if need_scratch {
778 let scratch = scratch_datum(bcx, arg_datum.ty, "__self", false);
779 arg_datum.store_to_datum(bcx, INIT, scratch);
781 // Technically, ownership of val passes to the callee.
782 // However, we must cleanup should we fail before the
783 // callee is actually invoked.
784 scratch.add_clean(bcx);
785 temp_cleanups.push(scratch.val);
792 val = match self_mode {
794 debug!("by ref arg with type %s", bcx.ty_to_str(arg_datum.ty));
795 arg_datum.to_ref_llval(bcx)
798 debug!("by copy arg with type %s", bcx.ty_to_str(arg_datum.ty));
799 arg_datum.to_appropriate_llval(bcx)
805 if formal_arg_ty != arg_datum.ty {
806 // this could happen due to e.g. subtyping
807 let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, &formal_arg_ty);
808 debug!("casting actual type (%s) to match formal (%s)",
809 bcx.val_to_str(val), bcx.llty_str(llformal_arg_ty));
810 val = PointerCast(bcx, val, llformal_arg_ty);
814 debug!("--- trans_arg_expr passing %s", bcx.val_to_str(val));
815 return rslt(bcx, val);