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.
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
17 pub use self::AutorefArg
::*;
18 pub use self::CalleeData
::*;
19 pub use self::CallArgs
::*;
21 use arena
::TypedArena
;
24 use llvm
::{self, ValueRef, get_params}
;
25 use metadata
::csearch
;
28 use middle
::subst
::{Subst, Substs}
;
35 use trans
::cleanup
::CleanupMethods
;
37 use trans
::common
::{self, Block
, Result
, NodeIdAndSpan
, ExprId
, CrateContext
,
38 ExprOrMethodCall
, FunctionContext
, MethodCallKey
};
41 use trans
::debuginfo
::{DebugLoc, ToDebugLoc}
;
49 use trans
::monomorphize
;
50 use trans
::type_
::Type
;
52 use middle
::ty
::{self, Ty}
;
53 use middle
::ty
::MethodCall
;
56 use syntax
::abi
as synabi
;
60 #[derive(Copy, Clone)]
61 pub struct MethodData
{
66 pub enum CalleeData
<'tcx
> {
67 // Constructor for enum variant/tuple-like-struct
69 NamedTupleConstructor(subst
::Substs
<'tcx
>, ty
::Disr
),
71 // Represents a (possibly monomorphized) top-level fn item or method
72 // item. Note that this is just the fn-ptr and is not a Rust closure
73 // value (which is a pair).
74 Fn(/* llfn */ ValueRef
),
76 Intrinsic(ast
::NodeId
, subst
::Substs
<'tcx
>),
81 pub struct Callee
<'blk
, 'tcx
: 'blk
> {
82 pub bcx
: Block
<'blk
, 'tcx
>,
83 pub data
: CalleeData
<'tcx
>,
86 fn trans
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>, expr
: &ast
::Expr
)
87 -> Callee
<'blk
, 'tcx
> {
88 let _icx
= push_ctxt("trans_callee");
89 debug
!("callee::trans(expr={:?})", expr
);
91 // pick out special kinds of expressions that can be called:
93 ast
::ExprPath(..) => {
94 return trans_def(bcx
, bcx
.def(expr
.id
), expr
);
99 // any other expressions are closures:
100 return datum_callee(bcx
, expr
);
102 fn datum_callee
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>, expr
: &ast
::Expr
)
103 -> Callee
<'blk
, 'tcx
> {
104 let DatumBlock { bcx, datum, .. }
= expr
::trans(bcx
, expr
);
106 ty
::TyBareFn(..) => {
107 let llval
= datum
.to_llscalarish(bcx
);
114 bcx
.tcx().sess
.span_bug(
116 &format
!("type of callee is neither bare-fn nor closure: {}",
122 fn fn_callee
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>, llfn
: ValueRef
)
123 -> Callee
<'blk
, 'tcx
> {
130 fn trans_def
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
132 ref_expr
: &ast
::Expr
)
133 -> Callee
<'blk
, 'tcx
> {
134 debug
!("trans_def(def={:?}, ref_expr={:?})", def
, ref_expr
);
135 let expr_ty
= common
::node_id_type(bcx
, ref_expr
.id
);
137 def
::DefFn(did
, _
) if {
138 let maybe_def_id
= inline
::get_local_instance(bcx
.ccx(), did
);
139 let maybe_ast_node
= maybe_def_id
.and_then(|def_id
| bcx
.tcx().map
141 match maybe_ast_node
{
142 Some(ast_map
::NodeStructCtor(_
)) => true,
146 let substs
= common
::node_id_substs(bcx
.ccx(),
148 bcx
.fcx
.param_substs
);
151 data
: NamedTupleConstructor(substs
, 0)
154 def
::DefFn(did
, _
) if match expr_ty
.sty
{
155 ty
::TyBareFn(_
, ref f
) => f
.abi
== synabi
::RustIntrinsic
,
158 let substs
= common
::node_id_substs(bcx
.ccx(),
160 bcx
.fcx
.param_substs
);
161 let def_id
= inline
::maybe_instantiate_inline(bcx
.ccx(), did
);
162 Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
164 def
::DefFn(did
, _
) | def
::DefMethod(did
, def
::FromImpl(_
)) => {
165 fn_callee(bcx
, trans_fn_ref(bcx
.ccx(), did
, ExprId(ref_expr
.id
),
166 bcx
.fcx
.param_substs
).val
)
168 def
::DefMethod(meth_did
, def
::FromTrait(trait_did
)) => {
169 fn_callee(bcx
, meth
::trans_static_method_callee(bcx
.ccx(),
173 bcx
.fcx
.param_substs
).val
)
175 def
::DefVariant(tid
, vid
, _
) => {
176 let vinfo
= ty
::enum_variant_with_id(bcx
.tcx(), tid
, vid
);
177 let substs
= common
::node_id_substs(bcx
.ccx(),
179 bcx
.fcx
.param_substs
);
181 // Nullary variants are not callable
182 assert
!(!vinfo
.args
.is_empty());
186 data
: NamedTupleConstructor(substs
, vinfo
.disr_val
)
189 def
::DefStruct(_
) => {
190 let substs
= common
::node_id_substs(bcx
.ccx(),
192 bcx
.fcx
.param_substs
);
195 data
: NamedTupleConstructor(substs
, 0)
200 def
::DefAssociatedConst(..) |
202 def
::DefUpvar(..) => {
203 datum_callee(bcx
, ref_expr
)
205 def
::DefMod(..) | def
::DefForeignMod(..) | def
::DefTrait(..) |
206 def
::DefTy(..) | def
::DefPrimTy(..) | def
::DefAssociatedTy(..) |
207 def
::DefUse(..) | def
::DefRegion(..) | def
::DefLabel(..) |
208 def
::DefTyParam(..) | def
::DefSelfTy(..) => {
209 bcx
.tcx().sess
.span_bug(
211 &format
!("cannot translate def {:?} \
212 to a callable thing!", def
));
218 /// Translates a reference (with id `ref_id`) to the fn/method with id `def_id` into a function
219 /// pointer. This may require monomorphization or inlining.
220 pub fn trans_fn_ref
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
222 node
: ExprOrMethodCall
,
223 param_substs
: &'tcx subst
::Substs
<'tcx
>)
224 -> Datum
<'tcx
, Rvalue
> {
225 let _icx
= push_ctxt("trans_fn_ref");
227 let substs
= common
::node_id_substs(ccx
, node
, param_substs
);
228 debug
!("trans_fn_ref(def_id={:?}, node={:?}, substs={:?})",
232 trans_fn_ref_with_substs(ccx
, def_id
, node
, param_substs
, substs
)
235 fn trans_fn_ref_with_substs_to_callee
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
238 substs
: subst
::Substs
<'tcx
>)
239 -> Callee
<'blk
, 'tcx
> {
242 data
: Fn(trans_fn_ref_with_substs(bcx
.ccx(),
245 bcx
.fcx
.param_substs
,
250 /// Translates an adapter that implements the `Fn` trait for a fn
251 /// pointer. This is basically the equivalent of something like:
254 /// impl<'a> Fn(&'a int) -> &'a int for fn(&int) -> &int {
255 /// extern "rust-abi" fn call(&self, args: (&'a int,)) -> &'a int {
261 /// but for the bare function type given.
262 pub fn trans_fn_pointer_shim
<'a
, 'tcx
>(
263 ccx
: &'a CrateContext
<'a
, 'tcx
>,
264 closure_kind
: ty
::ClosureKind
,
265 bare_fn_ty
: Ty
<'tcx
>)
268 let _icx
= push_ctxt("trans_fn_pointer_shim");
271 // Normalize the type for better caching.
272 let bare_fn_ty
= common
::erase_regions(tcx
, &bare_fn_ty
);
274 // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
275 let is_by_ref
= match closure_kind
{
276 ty
::FnClosureKind
| ty
::FnMutClosureKind
=> true,
277 ty
::FnOnceClosureKind
=> false,
279 let bare_fn_ty_maybe_ref
= if is_by_ref
{
280 ty
::mk_imm_rptr(tcx
, tcx
.mk_region(ty
::ReStatic
), bare_fn_ty
)
285 // Check if we already trans'd this shim.
286 match ccx
.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref
) {
287 Some(&llval
) => { return llval; }
291 debug
!("trans_fn_pointer_shim(bare_fn_ty={:?})",
294 // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
295 // which is the fn pointer, and `args`, which is the arguments tuple.
296 let (opt_def_id
, sig
) =
297 match bare_fn_ty
.sty
{
298 ty
::TyBareFn(opt_def_id
,
299 &ty
::BareFnTy
{ unsafety
: ast
::Unsafety
::Normal
,
306 tcx
.sess
.bug(&format
!("trans_fn_pointer_shim invoked on invalid type: {}",
310 let sig
= ty
::erase_late_bound_regions(tcx
, sig
);
311 let tuple_input_ty
= ty
::mk_tup(tcx
, sig
.inputs
.to_vec());
312 let tuple_fn_ty
= ty
::mk_bare_fn(tcx
,
314 tcx
.mk_bare_fn(ty
::BareFnTy
{
315 unsafety
: ast
::Unsafety
::Normal
,
316 abi
: synabi
::RustCall
,
317 sig
: ty
::Binder(ty
::FnSig
{
318 inputs
: vec
![bare_fn_ty_maybe_ref
,
323 debug
!("tuple_fn_ty: {:?}", tuple_fn_ty
);
326 let function_name
= link
::mangle_internal_name_by_type_and_seq(ccx
, bare_fn_ty
,
328 let llfn
= declare
::declare_internal_rust_fn(ccx
, &function_name
[..], tuple_fn_ty
);
331 let empty_substs
= tcx
.mk_substs(Substs
::trans_empty());
332 let (block_arena
, fcx
): (TypedArena
<_
>, FunctionContext
);
333 block_arena
= TypedArena
::new();
334 fcx
= new_fn_ctxt(ccx
,
342 let mut bcx
= init_function(&fcx
, false, sig
.output
);
344 let llargs
= get_params(fcx
.llfn
);
346 let self_idx
= fcx
.arg_offset();
347 // the first argument (`self`) will be ptr to the the fn pointer
348 let llfnpointer
= if is_by_ref
{
349 Load(bcx
, llargs
[self_idx
])
354 assert
!(!fcx
.needs_ret_allocas
);
356 let dest
= fcx
.llretslotptr
.get().map(|_
|
357 expr
::SaveIn(fcx
.get_ret_slot(bcx
, sig
.output
, "ret_slot"))
360 bcx
= trans_call_inner(bcx
,
363 |bcx
, _
| Callee { bcx: bcx, data: Fn(llfnpointer) }
,
364 ArgVals(&llargs
[(self_idx
+ 1)..]),
367 finish_fn(&fcx
, bcx
, sig
.output
, DebugLoc
::None
);
369 ccx
.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref
, llfn
);
374 /// Translates a reference to a fn/method item, monomorphizing and
375 /// inlining as it goes.
379 /// - `ccx`: the crate context
380 /// - `def_id`: def id of the fn or method item being referenced
381 /// - `node`: node id of the reference to the fn/method, if applicable.
382 /// This parameter may be zero; but, if so, the resulting value may not
383 /// have the right type, so it must be cast before being used.
384 /// - `param_substs`: if the `node` is in a polymorphic function, these
385 /// are the substitutions required to monomorphize its type
386 /// - `substs`: values for each of the fn/method's parameters
387 pub fn trans_fn_ref_with_substs
<'a
, 'tcx
>(
388 ccx
: &CrateContext
<'a
, 'tcx
>,
390 node
: ExprOrMethodCall
,
391 param_substs
: &'tcx subst
::Substs
<'tcx
>,
392 substs
: subst
::Substs
<'tcx
>)
393 -> Datum
<'tcx
, Rvalue
>
395 let _icx
= push_ctxt("trans_fn_ref_with_substs");
398 debug
!("trans_fn_ref_with_substs(def_id={:?}, node={:?}, \
399 param_substs={:?}, substs={:?})",
405 assert
!(substs
.types
.all(|t
| !ty
::type_needs_infer(*t
)));
406 assert
!(substs
.types
.all(|t
| !ty
::type_has_escaping_regions(*t
)));
407 let substs
= substs
.erase_regions();
409 // Load the info for the appropriate trait if necessary.
410 match ty
::trait_of_item(tcx
, def_id
) {
413 ty
::populate_implementations_for_trait_if_necessary(tcx
, trait_id
)
417 // We need to do a bunch of special handling for default methods.
418 // We need to modify the def_id and our substs in order to monomorphize
420 let (is_default
, def_id
, substs
) = match ty
::provided_source(tcx
, def_id
) {
422 (false, def_id
, tcx
.mk_substs(substs
))
425 // There are two relevant substitutions when compiling
426 // default methods. First, there is the substitution for
427 // the type parameters of the impl we are using and the
428 // method we are calling. This substitution is the substs
429 // argument we already have.
430 // In order to compile a default method, though, we need
431 // to consider another substitution: the substitution for
432 // the type parameters on trait; the impl we are using
433 // implements the trait at some particular type
434 // parameters, and we need to substitute for those first.
435 // So, what we need to do is find this substitution and
436 // compose it with the one we already have.
438 let impl_id
= ty
::impl_or_trait_item(tcx
, def_id
).container()
440 let impl_or_trait_item
= ty
::impl_or_trait_item(tcx
, source_id
);
441 match impl_or_trait_item
{
442 ty
::MethodTraitItem(method
) => {
443 let trait_ref
= ty
::impl_trait_ref(tcx
, impl_id
).unwrap();
445 // Compute the first substitution
447 ty
::make_substs_for_receiver_types(tcx
, &trait_ref
, &*method
)
451 let new_substs
= tcx
.mk_substs(first_subst
.subst(tcx
, &substs
));
453 debug
!("trans_fn_with_vtables - default method: \
454 substs = {:?}, trait_subst = {:?}, \
455 first_subst = {:?}, new_subst = {:?}",
456 substs
, trait_ref
.substs
,
457 first_subst
, new_substs
);
459 (true, source_id
, new_substs
)
462 tcx
.sess
.bug("trans_fn_ref_with_vtables() tried \
463 to translate a non-method?!")
469 // If this is a closure, redirect to it.
470 match closure
::get_or_create_declaration_if_closure(ccx
, def_id
, substs
) {
472 Some(llfn
) => return llfn
,
475 // Check whether this fn has an inlined copy and, if so, redirect
476 // def_id to the local id of the inlined copy.
477 let def_id
= inline
::maybe_instantiate_inline(ccx
, def_id
);
479 // We must monomorphise if the fn has type parameters, is a default method,
480 // or is a named tuple constructor.
481 let must_monomorphise
= if !substs
.types
.is_empty() || is_default
{
483 } else if def_id
.krate
== ast
::LOCAL_CRATE
{
484 let map_node
= session
::expect(
486 tcx
.map
.find(def_id
.node
),
487 || "local item should be in ast map".to_string());
490 ast_map
::NodeVariant(v
) => match v
.node
.kind
{
491 ast
::TupleVariantKind(ref args
) => !args
.is_empty(),
494 ast_map
::NodeStructCtor(_
) => true,
501 debug
!("trans_fn_ref_with_substs({:?}) must_monomorphise: {}",
502 def_id
, must_monomorphise
);
504 // Create a monomorphic version of generic functions
505 if must_monomorphise
{
506 // Should be either intra-crate or inlined.
507 assert_eq
!(def_id
.krate
, ast
::LOCAL_CRATE
);
509 let opt_ref_id
= match node
{
510 ExprId(id
) => if id
!= 0 { Some(id) }
else { None }
,
511 MethodCallKey(_
) => None
,
514 let (val
, fn_ty
, must_cast
) =
515 monomorphize
::monomorphic_fn(ccx
, def_id
, substs
, opt_ref_id
);
516 if must_cast
&& node
!= ExprId(0) {
517 // Monotype of the REFERENCE to the function (type params
519 let ref_ty
= match node
{
520 ExprId(id
) => ty
::node_id_to_type(tcx
, id
),
521 MethodCallKey(method_call
) => {
522 tcx
.method_map
.borrow().get(&method_call
).unwrap().ty
525 let ref_ty
= monomorphize
::apply_param_substs(tcx
,
528 let llptrty
= type_of
::type_of_fn_from_ty(ccx
, ref_ty
).ptr_to();
529 if llptrty
!= common
::val_ty(val
) {
530 let val
= consts
::ptrcast(val
, llptrty
);
531 return Datum
::new(val
, ref_ty
, Rvalue
::new(ByValue
));
534 return Datum
::new(val
, fn_ty
, Rvalue
::new(ByValue
));
537 // Type scheme of the function item (may have type params)
538 let fn_type_scheme
= ty
::lookup_item_type(tcx
, def_id
);
539 let fn_type
= monomorphize
::normalize_associated_type(tcx
, &fn_type_scheme
.ty
);
541 // Find the actual function pointer.
543 if def_id
.krate
== ast
::LOCAL_CRATE
{
544 // Internal reference.
545 get_item_val(ccx
, def_id
.node
)
547 // External reference.
548 trans_external_path(ccx
, def_id
, fn_type
)
552 // This is subtle and surprising, but sometimes we have to bitcast
553 // the resulting fn pointer. The reason has to do with external
554 // functions. If you have two crates that both bind the same C
555 // library, they may not use precisely the same types: for
556 // example, they will probably each declare their own structs,
557 // which are distinct types from LLVM's point of view (nominal
560 // Now, if those two crates are linked into an application, and
561 // they contain inlined code, you can wind up with a situation
562 // where both of those functions wind up being loaded into this
563 // application simultaneously. In that case, the same function
564 // (from LLVM's point of view) requires two types. But of course
565 // LLVM won't allow one function to have two types.
567 // What we currently do, therefore, is declare the function with
568 // one of the two types (whichever happens to come first) and then
569 // bitcast as needed when the function is referenced to make sure
570 // it has the type we expect.
572 // This can occur on either a crate-local or crate-external
573 // reference. It also occurs when testing libcore and in some
574 // other weird situations. Annoying.
575 let llty
= type_of
::type_of_fn_from_ty(ccx
, fn_type
);
576 let llptrty
= llty
.ptr_to();
577 if common
::val_ty(val
) != llptrty
{
578 debug
!("trans_fn_ref_with_vtables(): casting pointer!");
579 val
= consts
::ptrcast(val
, llptrty
);
581 debug
!("trans_fn_ref_with_vtables(): not casting pointer!");
584 Datum
::new(val
, fn_type
, Rvalue
::new(ByValue
))
587 // ______________________________________________________________________
590 pub fn trans_call
<'a
, 'blk
, 'tcx
>(in_cx
: Block
<'blk
, 'tcx
>,
591 call_expr
: &ast
::Expr
,
593 args
: CallArgs
<'a
, 'tcx
>,
595 -> Block
<'blk
, 'tcx
> {
596 let _icx
= push_ctxt("trans_call");
597 trans_call_inner(in_cx
,
598 call_expr
.debug_loc(),
599 common
::expr_ty_adjusted(in_cx
, f
),
600 |cx
, _
| trans(cx
, f
),
605 pub fn trans_method_call
<'a
, 'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
606 call_expr
: &ast
::Expr
,
608 args
: CallArgs
<'a
, 'tcx
>,
610 -> Block
<'blk
, 'tcx
> {
611 let _icx
= push_ctxt("trans_method_call");
612 debug
!("trans_method_call(call_expr={:?})", call_expr
);
613 let method_call
= MethodCall
::expr(call_expr
.id
);
614 let method_ty
= match bcx
.tcx().method_map
.borrow().get(&method_call
) {
615 Some(method
) => match method
.origin
{
616 ty
::MethodTraitObject(_
) => match method
.ty
.sty
{
617 ty
::TyBareFn(_
, ref fty
) => {
618 ty
::mk_bare_fn(bcx
.tcx(), None
, meth
::opaque_method_ty(bcx
.tcx(), fty
))
624 None
=> panic
!("method not found in trans_method_call")
628 call_expr
.debug_loc(),
629 common
::monomorphize_type(bcx
, method_ty
),
630 |cx
, arg_cleanup_scope
| {
631 meth
::trans_method_callee(cx
, method_call
, Some(rcvr
), arg_cleanup_scope
)
637 pub fn trans_lang_call
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
640 dest
: Option
<expr
::Dest
>,
642 -> Result
<'blk
, 'tcx
> {
643 let fty
= if did
.krate
== ast
::LOCAL_CRATE
{
644 ty
::node_id_to_type(bcx
.tcx(), did
.node
)
646 csearch
::get_type(bcx
.tcx(), did
).ty
648 callee
::trans_call_inner(bcx
,
652 trans_fn_ref_with_substs_to_callee(bcx
,
655 subst
::Substs
::trans_empty())
661 /// This behemoth of a function translates function calls. Unfortunately, in order to generate more
662 /// efficient LLVM output at -O0, it has quite a complex signature (refactoring this into two
663 /// functions seems like a good idea).
665 /// In particular, for lang items, it is invoked with a dest of None, and in that case the return
666 /// value contains the result of the fn. The lang item must not return a structural type or else
667 /// all heck breaks loose.
669 /// For non-lang items, `dest` is always Some, and hence the result is written into memory
670 /// somewhere. Nonetheless we return the actual return value of the function.
671 pub fn trans_call_inner
<'a
, 'blk
, 'tcx
, F
>(bcx
: Block
<'blk
, 'tcx
>,
675 args
: CallArgs
<'a
, 'tcx
>,
676 dest
: Option
<expr
::Dest
>)
677 -> Result
<'blk
, 'tcx
> where
678 F
: FnOnce(Block
<'blk
, 'tcx
>, cleanup
::ScopeId
) -> Callee
<'blk
, 'tcx
>,
680 // Introduce a temporary cleanup scope that will contain cleanups
681 // for the arguments while they are being evaluated. The purpose
682 // this cleanup is to ensure that, should a panic occur while
683 // evaluating argument N, the values for arguments 0...N-1 are all
684 // cleaned up. If no panic occurs, the values are handed off to
685 // the callee, and hence none of the cleanups in this temporary
686 // scope will ever execute.
689 let arg_cleanup_scope
= fcx
.push_custom_cleanup_scope();
691 let callee
= get_callee(bcx
, cleanup
::CustomScope(arg_cleanup_scope
));
692 let mut bcx
= callee
.bcx
;
694 let (abi
, ret_ty
) = match callee_ty
.sty
{
695 ty
::TyBareFn(_
, ref f
) => {
696 let output
= ty
::erase_late_bound_regions(bcx
.tcx(), &f
.sig
.output());
699 _
=> panic
!("expected bare rust fn or closure in trans_call_inner")
702 let (llfn
, llenv
, llself
) = match callee
.data
{
707 (d
.llfn
, None
, Some(d
.llself
))
709 Intrinsic(node
, substs
) => {
710 assert
!(abi
== synabi
::RustIntrinsic
);
711 assert
!(dest
.is_some());
713 let call_info
= match debug_loc
{
714 DebugLoc
::At(id
, span
) => NodeIdAndSpan { id: id, span: span }
,
716 bcx
.sess().bug("No call info for intrinsic call?")
720 return intrinsic
::trans_intrinsic_call(bcx
, node
, callee_ty
,
721 arg_cleanup_scope
, args
,
722 dest
.unwrap(), substs
,
725 NamedTupleConstructor(substs
, disr
) => {
726 assert
!(dest
.is_some());
727 fcx
.pop_custom_cleanup_scope(arg_cleanup_scope
);
729 let ctor_ty
= callee_ty
.subst(bcx
.tcx(), &substs
);
730 return base
::trans_named_tuple_constructor(bcx
,
739 // Intrinsics should not become actual functions.
740 // We trans them in place in `trans_intrinsic_call`
741 assert
!(abi
!= synabi
::RustIntrinsic
);
743 let is_rust_fn
= abi
== synabi
::Rust
|| abi
== synabi
::RustCall
;
745 // Generate a location to store the result. If the user does
746 // not care about the result, just make a stack slot.
747 let opt_llretslot
= dest
.and_then(|dest
| match dest
{
748 expr
::SaveIn(dst
) => Some(dst
),
750 let ret_ty
= match ret_ty
{
751 ty
::FnConverging(ret_ty
) => ret_ty
,
752 ty
::FnDiverging
=> ty
::mk_nil(ccx
.tcx())
755 type_of
::return_uses_outptr(ccx
, ret_ty
) ||
756 bcx
.fcx
.type_needs_drop(ret_ty
) {
757 // Push the out-pointer if we use an out-pointer for this
758 // return type, otherwise push "undef".
759 if common
::type_is_zero_size(ccx
, ret_ty
) {
760 let llty
= type_of
::type_of(ccx
, ret_ty
);
761 Some(common
::C_undef(llty
.ptr_to()))
763 Some(alloc_ty(bcx
, ret_ty
, "__llret"))
771 let mut llresult
= unsafe {
772 llvm
::LLVMGetUndef(Type
::nil(ccx
).ptr_to().to_ref())
775 // The code below invokes the function, using either the Rust
776 // conventions (if it is a rust fn) or the native conventions
777 // (otherwise). The important part is that, when all is said
778 // and done, either the return value of the function will have been
779 // written in opt_llretslot (if it is Some) or `llresult` will be
780 // set appropriately (otherwise).
782 let mut llargs
= Vec
::new();
784 if let (ty
::FnConverging(ret_ty
), Some(mut llretslot
)) = (ret_ty
, opt_llretslot
) {
785 if type_of
::return_uses_outptr(ccx
, ret_ty
) {
786 let llformal_ret_ty
= type_of
::type_of(ccx
, ret_ty
).ptr_to();
787 let llret_ty
= common
::val_ty(llretslot
);
788 if llformal_ret_ty
!= llret_ty
{
789 // this could happen due to e.g. subtyping
790 debug
!("casting actual return type ({}) to match formal ({})",
791 bcx
.llty_str(llret_ty
), bcx
.llty_str(llformal_ret_ty
));
792 llretslot
= PointerCast(bcx
, llretslot
, llformal_ret_ty
);
794 llargs
.push(llretslot
);
798 // Push the environment (or a trait object's self).
799 match (llenv
, llself
) {
800 (Some(llenv
), None
) => llargs
.push(llenv
),
801 (None
, Some(llself
)) => llargs
.push(llself
),
805 // Push the arguments.
806 bcx
= trans_args(bcx
,
810 cleanup
::CustomScope(arg_cleanup_scope
),
814 fcx
.scopes
.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean();
816 // Invoke the actual rust fn and update bcx/llresult.
817 let (llret
, b
) = base
::invoke(bcx
,
825 // If the Rust convention for this type is return via
826 // the return value, copy it into llretslot.
827 match (opt_llretslot
, ret_ty
) {
828 (Some(llretslot
), ty
::FnConverging(ret_ty
)) => {
829 if !type_of
::return_uses_outptr(bcx
.ccx(), ret_ty
) &&
830 !common
::type_is_zero_size(bcx
.ccx(), ret_ty
)
832 store_ty(bcx
, llret
, llretslot
, ret_ty
)
838 // Lang items are the only case where dest is None, and
839 // they are always Rust fns.
840 assert
!(dest
.is_some());
842 let mut llargs
= Vec
::new();
843 let arg_tys
= match args
{
844 ArgExprs(a
) => a
.iter().map(|x
| common
::expr_ty_adjusted(bcx
, &**x
)).collect(),
845 _
=> panic
!("expected arg exprs.")
847 bcx
= trans_args(bcx
,
851 cleanup
::CustomScope(arg_cleanup_scope
),
854 fcx
.scopes
.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean();
856 bcx
= foreign
::trans_native_call(bcx
,
859 opt_llretslot
.unwrap(),
865 fcx
.pop_and_trans_custom_cleanup_scope(bcx
, arg_cleanup_scope
);
867 // If the caller doesn't care about the result of this fn call,
868 // drop the temporary slot we made.
869 match (dest
, opt_llretslot
, ret_ty
) {
870 (Some(expr
::Ignore
), Some(llretslot
), ty
::FnConverging(ret_ty
)) => {
871 // drop the value if it is not being saved.
872 bcx
= glue
::drop_ty(bcx
,
876 call_lifetime_end(bcx
, llretslot
);
881 if ret_ty
== ty
::FnDiverging
{
885 Result
::new(bcx
, llresult
)
888 pub enum CallArgs
<'a
, 'tcx
> {
889 // Supply value of arguments as a list of expressions that must be
890 // translated. This is used in the common case of `foo(bar, qux)`.
891 ArgExprs(&'a
[P
<ast
::Expr
>]),
893 // Supply value of arguments as a list of LLVM value refs; frequently
894 // used with lang items and so forth, when the argument is an internal
896 ArgVals(&'a
[ValueRef
]),
898 // For overloaded operators: `(lhs, Vec(rhs, rhs_id), autoref)`. `lhs`
899 // is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of
900 // the right-hand-side arguments (if any). `autoref` indicates whether the `rhs`
901 // arguments should be auto-referenced
902 ArgOverloadedOp(Datum
<'tcx
, Expr
>, Vec
<(Datum
<'tcx
, Expr
>, ast
::NodeId
)>, bool
),
904 // Supply value of arguments as a list of expressions that must be
905 // translated, for overloaded call operators.
906 ArgOverloadedCall(Vec
<&'a ast
::Expr
>),
909 fn trans_args_under_call_abi
<'blk
, 'tcx
>(
910 mut bcx
: Block
<'blk
, 'tcx
>,
911 arg_exprs
: &[P
<ast
::Expr
>],
913 llargs
: &mut Vec
<ValueRef
>,
914 arg_cleanup_scope
: cleanup
::ScopeId
,
919 ty
::erase_late_bound_regions(
920 bcx
.tcx(), &ty
::ty_fn_args(fn_ty
));
922 // Translate the `self` argument first.
924 let arg_datum
= unpack_datum
!(bcx
, expr
::trans(bcx
, &*arg_exprs
[0]));
925 bcx
= trans_arg_datum(bcx
,
933 // Now untuple the rest of the arguments.
934 let tuple_expr
= &arg_exprs
[1];
935 let tuple_type
= common
::node_id_type(bcx
, tuple_expr
.id
);
937 match tuple_type
.sty
{
938 ty
::TyTuple(ref field_types
) => {
939 let tuple_datum
= unpack_datum
!(bcx
,
940 expr
::trans(bcx
, &**tuple_expr
));
941 let tuple_lvalue_datum
=
943 tuple_datum
.to_lvalue_datum(bcx
,
946 let repr
= adt
::represent_type(bcx
.ccx(), tuple_type
);
947 let repr_ptr
= &*repr
;
948 for (i
, field_type
) in field_types
.iter().enumerate() {
949 let arg_datum
= tuple_lvalue_datum
.get_element(
953 adt
::trans_field_ptr(bcx
, repr_ptr
, srcval
, 0, i
)
955 bcx
= trans_arg_datum(bcx
,
964 bcx
.sess().span_bug(tuple_expr
.span
,
965 "argument to `.call()` wasn't a tuple?!")
972 fn trans_overloaded_call_args
<'blk
, 'tcx
>(
973 mut bcx
: Block
<'blk
, 'tcx
>,
974 arg_exprs
: Vec
<&ast
::Expr
>,
976 llargs
: &mut Vec
<ValueRef
>,
977 arg_cleanup_scope
: cleanup
::ScopeId
,
979 -> Block
<'blk
, 'tcx
> {
980 // Translate the `self` argument first.
981 let arg_tys
= ty
::erase_late_bound_regions(bcx
.tcx(), &ty
::ty_fn_args(fn_ty
));
983 let arg_datum
= unpack_datum
!(bcx
, expr
::trans(bcx
, arg_exprs
[0]));
984 bcx
= trans_arg_datum(bcx
,
992 // Now untuple the rest of the arguments.
993 let tuple_type
= arg_tys
[1];
994 match tuple_type
.sty
{
995 ty
::TyTuple(ref field_types
) => {
996 for (i
, &field_type
) in field_types
.iter().enumerate() {
998 unpack_datum
!(bcx
, expr
::trans(bcx
, arg_exprs
[i
+ 1]));
999 bcx
= trans_arg_datum(bcx
,
1008 bcx
.sess().span_bug(arg_exprs
[0].span
,
1009 "argument to `.call()` wasn't a tuple?!")
1016 pub fn trans_args
<'a
, 'blk
, 'tcx
>(cx
: Block
<'blk
, 'tcx
>,
1017 args
: CallArgs
<'a
, 'tcx
>,
1019 llargs
: &mut Vec
<ValueRef
>,
1020 arg_cleanup_scope
: cleanup
::ScopeId
,
1023 -> Block
<'blk
, 'tcx
> {
1024 debug
!("trans_args(abi={})", abi
);
1026 let _icx
= push_ctxt("trans_args");
1027 let arg_tys
= ty
::erase_late_bound_regions(cx
.tcx(), &ty
::ty_fn_args(fn_ty
));
1028 let variadic
= ty
::fn_is_variadic(fn_ty
);
1032 // First we figure out the caller's view of the types of the arguments.
1033 // This will be needed if this is a generic call, because the callee has
1034 // to cast her view of the arguments to the caller's view.
1036 ArgExprs(arg_exprs
) => {
1037 if abi
== synabi
::RustCall
{
1038 // This is only used for direct calls to the `call`,
1039 // `call_mut` or `call_once` functions.
1040 return trans_args_under_call_abi(cx
,
1048 let num_formal_args
= arg_tys
.len();
1049 for (i
, arg_expr
) in arg_exprs
.iter().enumerate() {
1050 if i
== 0 && ignore_self
{
1053 let arg_ty
= if i
>= num_formal_args
{
1055 common
::expr_ty_adjusted(cx
, &**arg_expr
)
1060 let arg_datum
= unpack_datum
!(bcx
, expr
::trans(bcx
, &**arg_expr
));
1061 bcx
= trans_arg_datum(bcx
, arg_ty
, arg_datum
,
1067 ArgOverloadedCall(arg_exprs
) => {
1068 return trans_overloaded_call_args(cx
,
1075 ArgOverloadedOp(lhs
, rhs
, autoref
) => {
1078 bcx
= trans_arg_datum(bcx
, arg_tys
[0], lhs
,
1083 assert_eq
!(arg_tys
.len(), 1 + rhs
.len());
1084 for (rhs
, rhs_id
) in rhs
{
1085 bcx
= trans_arg_datum(bcx
, arg_tys
[1], rhs
,
1087 if autoref { DoAutorefArg(rhs_id) }
else { DontAutorefArg }
,
1092 llargs
.push_all(vs
);
1099 #[derive(Copy, Clone)]
1100 pub enum AutorefArg
{
1102 DoAutorefArg(ast
::NodeId
)
1105 pub fn trans_arg_datum
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
1106 formal_arg_ty
: Ty
<'tcx
>,
1107 arg_datum
: Datum
<'tcx
, Expr
>,
1108 arg_cleanup_scope
: cleanup
::ScopeId
,
1109 autoref_arg
: AutorefArg
,
1110 llargs
: &mut Vec
<ValueRef
>)
1111 -> Block
<'blk
, 'tcx
> {
1112 let _icx
= push_ctxt("trans_arg_datum");
1114 let ccx
= bcx
.ccx();
1116 debug
!("trans_arg_datum({:?})",
1119 let arg_datum_ty
= arg_datum
.ty
;
1121 debug
!(" arg datum: {}", arg_datum
.to_string(bcx
.ccx()));
1124 // FIXME(#3548) use the adjustments table
1126 DoAutorefArg(arg_id
) => {
1127 // We will pass argument by reference
1128 // We want an lvalue, so that we can pass by reference and
1129 let arg_datum
= unpack_datum
!(
1130 bcx
, arg_datum
.to_lvalue_datum(bcx
, "arg", arg_id
));
1131 val
= arg_datum
.val
;
1133 DontAutorefArg
if common
::type_is_fat_ptr(bcx
.tcx(), arg_datum_ty
) &&
1134 !bcx
.fcx
.type_needs_drop(arg_datum_ty
) => {
1138 // Make this an rvalue, since we are going to be
1139 // passing ownership.
1140 let arg_datum
= unpack_datum
!(
1141 bcx
, arg_datum
.to_rvalue_datum(bcx
, "arg"));
1143 // Now that arg_datum is owned, get it into the appropriate
1144 // mode (ref vs value).
1145 let arg_datum
= unpack_datum
!(
1146 bcx
, arg_datum
.to_appropriate_datum(bcx
));
1148 // Technically, ownership of val passes to the callee.
1149 // However, we must cleanup should we panic before the
1150 // callee is actually invoked.
1151 val
= arg_datum
.add_clean(bcx
.fcx
, arg_cleanup_scope
);
1155 if type_of
::arg_is_indirect(ccx
, formal_arg_ty
) && formal_arg_ty
!= arg_datum_ty
{
1156 // this could happen due to e.g. subtyping
1157 let llformal_arg_ty
= type_of
::type_of_explicit_arg(ccx
, formal_arg_ty
);
1158 debug
!("casting actual type ({}) to match formal ({})",
1159 bcx
.val_to_string(val
), bcx
.llty_str(llformal_arg_ty
));
1160 debug
!("Rust types: {:?}; {:?}", arg_datum_ty
,
1162 val
= PointerCast(bcx
, val
, llformal_arg_ty
);
1165 debug
!("--- trans_arg_datum passing {}", bcx
.val_to_string(val
));
1167 if common
::type_is_fat_ptr(bcx
.tcx(), formal_arg_ty
) {
1168 llargs
.push(Load(bcx
, expr
::get_dataptr(bcx
, val
)));
1169 llargs
.push(Load(bcx
, expr
::get_len(bcx
, val
)));