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::CalleeData::*;
19 use llvm::{self, ValueRef, get_params};
20 use rustc::hir::def_id::DefId;
21 use rustc::ty::subst::Substs;
23 use abi::{Abi, FnType};
28 self, CrateContext, FunctionContext, SharedCrateContext
30 use adt::MaybeSizedValue;
35 use monomorphize::{self, Instance};
36 use trans_item::TransItem;
39 use rustc::ty::{self, Ty, TypeFoldable};
43 use syntax_pos::DUMMY_SP;
47 /// Constructor for enum variant/tuple-like-struct.
48 NamedTupleConstructor(Disr),
55 /// Trait object found in the vtable at that index.
60 pub struct Callee<'tcx> {
65 impl<'tcx> Callee<'tcx> {
67 pub fn ptr(llfn: ValueRef, ty: Ty<'tcx>) -> Callee<'tcx> {
74 /// Function or method definition.
75 pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>)
79 if let Some(trait_id) = tcx.trait_of_item(def_id) {
80 return Callee::trait_method(ccx, trait_id, def_id, substs);
83 let fn_ty = def_ty(ccx.shared(), def_id, substs);
84 if let ty::TyFnDef(.., f) = fn_ty.sty {
85 if f.abi == Abi::RustIntrinsic || f.abi == Abi::PlatformIntrinsic {
93 // FIXME(eddyb) Detect ADT constructors more efficiently.
94 if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
95 if let Some(v) = adt_def.variants.iter().find(|v| def_id == v.did) {
97 data: NamedTupleConstructor(Disr::from(v.disr_val)),
103 let (llfn, ty) = get_fn(ccx, def_id, substs);
104 Callee::ptr(llfn, ty)
107 /// Trait method, which has to be resolved to an impl method.
108 pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
111 substs: &'tcx Substs<'tcx>)
115 let trait_ref = ty::TraitRef::from_method(tcx, trait_id, substs);
116 let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref));
117 match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
118 traits::VtableImpl(vtable_impl) => {
119 let name = tcx.item_name(def_id);
120 let (def_id, substs) = traits::find_method(tcx, name, substs, &vtable_impl);
122 // Translate the function, bypassing Callee::def.
123 // That is because default methods have the same ID as the
124 // trait method used to look up the impl method that ended
125 // up here, so calling Callee::def would infinitely recurse.
126 let (llfn, ty) = get_fn(ccx, def_id, substs);
127 Callee::ptr(llfn, ty)
129 traits::VtableClosure(vtable_closure) => {
130 // The substitutions should have no type parameters remaining
131 // after passing through fulfill_obligation
132 let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
133 let instance = Instance::new(def_id, substs);
134 let llfn = trans_closure_method(
136 vtable_closure.closure_def_id,
137 vtable_closure.substs,
141 let method_ty = def_ty(ccx.shared(), def_id, substs);
142 Callee::ptr(llfn, method_ty)
144 traits::VtableFnPointer(vtable_fn_pointer) => {
145 let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
146 let instance = Instance::new(def_id, substs);
147 let llfn = trans_fn_pointer_shim(ccx, instance,
149 vtable_fn_pointer.fn_ty);
151 let method_ty = def_ty(ccx.shared(), def_id, substs);
152 Callee::ptr(llfn, method_ty)
154 traits::VtableObject(ref data) => {
156 data: Virtual(tcx.get_vtable_index_of_object_method(data, def_id)),
157 ty: def_ty(ccx.shared(), def_id, substs)
161 bug!("resolved vtable bad vtable {:?} in trans", vtable);
166 /// Get the abi::FnType for a direct call. Mainly deals with the fact
167 /// that a Virtual call doesn't take the vtable, like its shim does.
168 /// The extra argument types are for variadic (extern "C") functions.
169 pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
170 extra_args: &[Ty<'tcx>]) -> FnType {
171 let abi = self.ty.fn_abi();
172 let sig = ccx.tcx().erase_late_bound_regions_and_normalize(self.ty.fn_sig());
173 let mut fn_ty = FnType::unadjusted(ccx, abi, &sig, extra_args);
174 if let Virtual(_) = self.data {
175 // Don't pass the vtable, it's not an argument of the virtual fn.
176 fn_ty.args[1].ignore();
178 fn_ty.adjust_for_abi(ccx, abi, &sig);
182 /// Turn the callee into a function pointer.
183 pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
186 Virtual(_) => meth::trans_object_shim(ccx, self),
187 NamedTupleConstructor(disr) => match self.ty.sty {
188 ty::TyFnDef(def_id, substs, _) => {
189 let instance = Instance::new(def_id, substs);
190 if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
194 let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
195 TransItem::Fn(instance));
196 assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
197 let lldecl = declare::define_internal_fn(ccx, &sym, self.ty);
198 base::trans_ctor_shim(ccx, def_id, substs, disr, lldecl);
199 ccx.instances().borrow_mut().insert(instance, lldecl);
203 _ => bug!("expected fn item type, found {}", self.ty)
205 Intrinsic => bug!("intrinsic {} getting reified", self.ty)
210 /// Given a DefId and some Substs, produces the monomorphic item type.
211 fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
213 substs: &'tcx Substs<'tcx>)
215 let ty = shared.tcx().item_type(def_id);
216 monomorphize::apply_param_substs(shared, substs, &ty)
220 fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
222 substs: ty::ClosureSubsts<'tcx>,
223 method_instance: Instance<'tcx>,
224 trait_closure_kind: ty::ClosureKind)
227 // If this is a closure, redirect to it.
228 let (llfn, _) = get_fn(ccx, def_id, substs.substs);
230 // If the closure is a Fn closure, but a FnOnce is needed (etc),
231 // then adapt the self type
232 let llfn_closure_kind = ccx.tcx().closure_kind(def_id);
234 debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
235 trait_closure_kind={:?}, llfn={:?})",
236 llfn_closure_kind, trait_closure_kind, Value(llfn));
238 match needs_fn_once_adapter_shim(llfn_closure_kind, trait_closure_kind) {
239 Ok(true) => trans_fn_once_adapter_shim(ccx,
246 bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
253 pub fn needs_fn_once_adapter_shim(actual_closure_kind: ty::ClosureKind,
254 trait_closure_kind: ty::ClosureKind)
257 match (actual_closure_kind, trait_closure_kind) {
258 (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
259 (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
260 (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
261 // No adapter needed.
264 (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
265 // The closure fn `llfn` is a `fn(&self, ...)`. We want a
266 // `fn(&mut self, ...)`. In fact, at trans time, these are
267 // basically the same thing, so we can just return llfn.
270 (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
271 (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
272 // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
273 // self, ...)`. We want a `fn(self, ...)`. We can produce
274 // this by doing something like:
276 // fn call_once(self, ...) { call_mut(&self, ...) }
277 // fn call_once(mut self, ...) { call_mut(&mut self, ...) }
279 // These are both the same at trans time.
286 fn trans_fn_once_adapter_shim<'a, 'tcx>(
287 ccx: &'a CrateContext<'a, 'tcx>,
289 substs: ty::ClosureSubsts<'tcx>,
290 method_instance: Instance<'tcx>,
294 if let Some(&llfn) = ccx.instances().borrow().get(&method_instance) {
298 debug!("trans_fn_once_adapter_shim(def_id={:?}, substs={:?}, llreffn={:?})",
299 def_id, substs, Value(llreffn));
303 // Find a version of the closure type. Substitute static for the
304 // region since it doesn't really matter.
305 let closure_ty = tcx.mk_closure_from_closure_substs(def_id, substs);
306 let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty);
308 // Make a version with the type of by-ref closure.
309 let ty::ClosureTy { unsafety, abi, mut sig } = tcx.closure_type(def_id, substs);
310 sig.0 = tcx.mk_fn_sig(
311 iter::once(ref_closure_ty).chain(sig.0.inputs().iter().cloned()),
315 let llref_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
320 debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
324 // Make a version of the closure type with the same arguments, but
325 // with argument #0 being by value.
326 assert_eq!(abi, Abi::RustCall);
327 sig.0 = tcx.mk_fn_sig(
328 iter::once(closure_ty).chain(sig.0.inputs().iter().skip(1).cloned()),
333 let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
334 let fn_ty = FnType::new(ccx, abi, &sig, &[]);
336 let llonce_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
342 // Create the by-value helper.
343 let function_name = method_instance.symbol_name(ccx.shared());
344 let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
345 attributes::set_frame_pointer_elimination(ccx, lloncefn);
347 let orig_fn_ty = fn_ty;
348 let fcx = FunctionContext::new(ccx, lloncefn);
349 let mut bcx = fcx.get_entry_block();
351 let callee = Callee {
356 // the first argument (`self`) will be the (by value) closure env.
358 let mut llargs = get_params(fcx.llfn);
359 let fn_ret = callee.ty.fn_ret();
360 let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
361 let self_idx = fn_ty.ret.is_indirect() as usize;
362 let env_arg = &orig_fn_ty.args[0];
363 let llenv = if env_arg.is_indirect() {
366 let scratch = alloc_ty(&bcx, closure_ty, "self");
367 let mut llarg_idx = self_idx;
368 env_arg.store_fn_arg(&bcx, &mut llarg_idx, scratch);
372 debug!("trans_fn_once_adapter_shim: env={:?}", Value(llenv));
373 // Adjust llargs such that llargs[self_idx..] has the call arguments.
374 // For zero-sized closures that means sneaking in a new argument.
375 if env_arg.is_ignore() {
376 llargs.insert(self_idx, llenv);
378 llargs[self_idx] = llenv;
381 // Call the by-ref closure body with `self` in a cleanup scope,
382 // to drop `self` when the body returns, or in case it unwinds.
383 let self_scope = fcx.schedule_drop_mem(MaybeSizedValue::sized(llenv), closure_ty);
385 let llfn = callee.reify(bcx.ccx);
387 if let Some(landing_pad) = self_scope.landing_pad {
388 let normal_bcx = bcx.fcx().build_new_block("normal-return");
389 llret = bcx.invoke(llfn, &llargs[..], normal_bcx.llbb(), landing_pad, None);
392 llret = bcx.call(llfn, &llargs[..], None);
394 fn_ty.apply_attrs_callsite(llret);
396 if fn_ret.0.is_never() {
399 self_scope.trans(&bcx);
401 if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
408 ccx.instances().borrow_mut().insert(method_instance, lloncefn);
413 /// Translates an adapter that implements the `Fn` trait for a fn
414 /// pointer. This is basically the equivalent of something like:
417 /// impl<'a> Fn(&'a int) -> &'a int for fn(&int) -> &int {
418 /// extern "rust-abi" fn call(&self, args: (&'a int,)) -> &'a int {
424 /// but for the bare function type given.
425 fn trans_fn_pointer_shim<'a, 'tcx>(
426 ccx: &'a CrateContext<'a, 'tcx>,
427 method_instance: Instance<'tcx>,
428 closure_kind: ty::ClosureKind,
429 bare_fn_ty: Ty<'tcx>)
434 // Normalize the type for better caching.
435 let bare_fn_ty = tcx.normalize_associated_type(&bare_fn_ty);
437 // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
438 let is_by_ref = match closure_kind {
439 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => true,
440 ty::ClosureKind::FnOnce => false,
443 let llfnpointer = match bare_fn_ty.sty {
444 ty::TyFnDef(def_id, substs, _) => {
445 // Function definitions have to be turned into a pointer.
446 let llfn = Callee::def(ccx, def_id, substs).reify(ccx);
448 // A by-value fn item is ignored, so the shim has
449 // the same signature as the original function.
457 let bare_fn_ty_maybe_ref = if is_by_ref {
458 tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), bare_fn_ty)
463 // Check if we already trans'd this shim.
464 if let Some(&llval) = ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
468 debug!("trans_fn_pointer_shim(bare_fn_ty={:?})",
471 // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
472 // which is the fn pointer, and `args`, which is the arguments tuple.
473 let sig = match bare_fn_ty.sty {
475 &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
478 ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal,
483 bug!("trans_fn_pointer_shim invoked on invalid type: {}",
487 let sig = tcx.erase_late_bound_regions_and_normalize(sig);
488 let tuple_input_ty = tcx.intern_tup(sig.inputs());
489 let sig = tcx.mk_fn_sig(
490 [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
494 let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]);
495 let tuple_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
496 unsafety: hir::Unsafety::Normal,
500 debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
503 let function_name = method_instance.symbol_name(ccx.shared());
504 let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
505 attributes::set_frame_pointer_elimination(ccx, llfn);
507 let fcx = FunctionContext::new(ccx, llfn);
508 let bcx = fcx.get_entry_block();
510 let mut llargs = get_params(fcx.llfn);
512 let self_arg = llargs.remove(fn_ty.ret.is_indirect() as usize);
513 let llfnpointer = llfnpointer.unwrap_or_else(|| {
514 // the first argument (`self`) will be ptr to the fn pointer
522 let callee = Callee {
523 data: Fn(llfnpointer),
526 let fn_ret = callee.ty.fn_ret();
527 let fn_ty = callee.direct_fn_type(ccx, &[]);
528 let llret = bcx.call(llfnpointer, &llargs, None);
529 fn_ty.apply_attrs_callsite(llret);
531 if fn_ret.0.is_never() {
534 if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
541 ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
546 /// Translates a reference to a fn/method item, monomorphizing and
547 /// inlining as it goes.
551 /// - `ccx`: the crate context
552 /// - `def_id`: def id of the fn or method item being referenced
553 /// - `substs`: values for each of the fn/method's parameters
554 fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
556 substs: &'tcx Substs<'tcx>)
557 -> (ValueRef, Ty<'tcx>) {
560 debug!("get_fn(def_id={:?}, substs={:?})", def_id, substs);
562 assert!(!substs.needs_infer());
563 assert!(!substs.has_escaping_regions());
564 assert!(!substs.has_param_types());
566 let substs = tcx.normalize_associated_type(&substs);
567 let instance = Instance::new(def_id, substs);
568 let item_ty = ccx.tcx().item_type(def_id);
569 let fn_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &item_ty);
571 if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
572 return (llfn, fn_ty);
575 let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
576 TransItem::Fn(instance));
577 debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
579 // This is subtle and surprising, but sometimes we have to bitcast
580 // the resulting fn pointer. The reason has to do with external
581 // functions. If you have two crates that both bind the same C
582 // library, they may not use precisely the same types: for
583 // example, they will probably each declare their own structs,
584 // which are distinct types from LLVM's point of view (nominal
587 // Now, if those two crates are linked into an application, and
588 // they contain inlined code, you can wind up with a situation
589 // where both of those functions wind up being loaded into this
590 // application simultaneously. In that case, the same function
591 // (from LLVM's point of view) requires two types. But of course
592 // LLVM won't allow one function to have two types.
594 // What we currently do, therefore, is declare the function with
595 // one of the two types (whichever happens to come first) and then
596 // bitcast as needed when the function is referenced to make sure
597 // it has the type we expect.
599 // This can occur on either a crate-local or crate-external
600 // reference. It also occurs when testing libcore and in some
601 // other weird situations. Annoying.
603 // Create a fn pointer with the substituted signature.
604 let fn_ptr_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(common::ty_fn_ty(ccx, fn_ty).into_owned()));
605 let llptrty = type_of::type_of(ccx, fn_ptr_ty);
607 let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
608 if common::val_ty(llfn) != llptrty {
609 debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
610 consts::ptrcast(llfn, llptrty)
612 debug!("get_fn: not casting pointer!");
616 let llfn = declare::declare_fn(ccx, &sym, fn_ty);
617 assert_eq!(common::val_ty(llfn), llptrty);
618 debug!("get_fn: not casting pointer!");
620 let attrs = ccx.tcx().get_attrs(def_id);
621 attributes::from_fn_attrs(ccx, &attrs, llfn);
623 let is_local_def = ccx.shared().translation_items().borrow()
624 .contains(&TransItem::Fn(instance));
626 // FIXME(eddyb) Doubt all extern fn should allow unwinding.
627 attributes::unwind(llfn, true);
629 llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
632 if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) {
634 llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
640 ccx.instances().borrow_mut().insert(instance, llfn);