summaryrefslogtreecommitdiff
path: root/src/librustc_trans/trans/meth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_trans/trans/meth.rs')
-rw-r--r--src/librustc_trans/trans/meth.rs235
1 files changed, 29 insertions, 206 deletions
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 7397ccc2505..30560ec05c4 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -18,14 +18,13 @@ use middle::infer;
use middle::subst::{Subst, Substs};
use middle::subst;
use middle::traits::{self, ProjectionMode};
+use trans::abi::FnType;
use trans::base::*;
use trans::build::*;
-use trans::callee::{Callee, Virtual, ArgVals,
- trans_fn_pointer_shim, trans_fn_ref_with_substs};
+use trans::callee::{Callee, Virtual, ArgVals, trans_fn_pointer_shim};
use trans::closure;
use trans::common::*;
use trans::consts;
-use trans::datum::*;
use trans::debuginfo::DebugLoc;
use trans::declare;
use trans::expr;
@@ -33,158 +32,25 @@ use trans::glue;
use trans::machine;
use trans::type_::Type;
use trans::type_of::*;
+use trans::value::Value;
use middle::ty::{self, Ty, TyCtxt, TypeFoldable};
-use syntax::ast::{self, Name};
-use syntax::attr;
+use syntax::ast::Name;
use syntax::codemap::DUMMY_SP;
-use rustc_front::hir;
-
// drop_glue pointer, size, align.
const VTABLE_OFFSET: usize = 3;
-/// The main "translation" pass for methods. Generates code
-/// for non-monomorphized methods only. Other methods will
-/// be generated once they are invoked with specific type parameters,
-/// see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
-pub fn trans_impl(ccx: &CrateContext,
- name: ast::Name,
- impl_items: &[hir::ImplItem],
- generics: &hir::Generics,
- id: ast::NodeId) {
- let _icx = push_ctxt("meth::trans_impl");
- let tcx = ccx.tcx();
-
- debug!("trans_impl(name={}, id={})", name, id);
-
- // Both here and below with generic methods, be sure to recurse and look for
- // items that we need to translate.
- if !generics.ty_params.is_empty() {
- return;
- }
-
- for impl_item in impl_items {
- match impl_item.node {
- hir::ImplItemKind::Method(ref sig, ref body) => {
- if sig.generics.ty_params.is_empty() {
- let trans_everywhere = attr::requests_inline(&impl_item.attrs);
- for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
- let llfn = get_item_val(ccx, impl_item.id);
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
- trans_fn(ccx,
- &sig.decl,
- body,
- llfn,
- empty_substs,
- impl_item.id,
- &impl_item.attrs);
- update_linkage(ccx,
- llfn,
- Some(impl_item.id),
- if is_origin { OriginalTranslation } else { InlinedCopy });
- }
- }
- }
- _ => {}
- }
- }
-}
-
-/// Compute the appropriate callee, give na method's ID, trait ID,
-/// substitutions and a Vtable for that trait.
-pub fn callee_for_trait_impl<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- method_id: DefId,
- substs: &'tcx subst::Substs<'tcx>,
- trait_id: DefId,
- method_ty: Ty<'tcx>,
- vtable: traits::Vtable<'tcx, ()>)
- -> Callee<'tcx> {
- let _icx = push_ctxt("meth::callee_for_trait_impl");
- match vtable {
- traits::VtableImpl(vtable_impl) => {
- let impl_did = vtable_impl.impl_def_id;
- let mname = ccx.tcx().item_name(method_id);
- // create a concatenated set of substitutions which includes
- // those from the impl and those from the method:
- let impl_substs = vtable_impl.substs.with_method_from(&substs);
- let substs = ccx.tcx().mk_substs(impl_substs);
- let mth = get_impl_method(ccx.tcx(), impl_did, substs, mname);
-
- // Translate the function, bypassing Callee::def.
- // That is because default methods have the same ID as the
- // trait method used to look up the impl method that ended
- // up here, so calling Callee::def would infinitely recurse.
- Callee::ptr(trans_fn_ref_with_substs(ccx, mth.method.def_id,
- Some(method_ty), mth.substs))
- }
- traits::VtableClosure(vtable_closure) => {
- // The substitutions should have no type parameters remaining
- // after passing through fulfill_obligation
- let trait_closure_kind = ccx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
- let llfn = closure::trans_closure_method(ccx,
- vtable_closure.closure_def_id,
- vtable_closure.substs,
- trait_closure_kind);
- let fn_ptr_ty = match method_ty.sty {
- ty::TyFnDef(_, _, fty) => ccx.tcx().mk_ty(ty::TyFnPtr(fty)),
- _ => unreachable!("expected fn item type, found {}",
- method_ty)
- };
- Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
- }
- traits::VtableFnPointer(fn_ty) => {
- let trait_closure_kind = ccx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
- let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, fn_ty);
- let fn_ptr_ty = match method_ty.sty {
- ty::TyFnDef(_, _, fty) => ccx.tcx().mk_ty(ty::TyFnPtr(fty)),
- _ => unreachable!("expected fn item type, found {}",
- method_ty)
- };
- Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
- }
- traits::VtableObject(ref data) => {
- Callee {
- data: Virtual(traits::get_vtable_index_of_object_method(
- ccx.tcx(), data, method_id)),
- ty: method_ty
- }
- }
- traits::VtableBuiltin(..) |
- traits::VtableDefaultImpl(..) |
- traits::VtableParam(..) => {
- ccx.sess().bug(
- &format!("resolved vtable bad vtable {:?} in trans",
- vtable));
- }
- }
-}
-
-/// Extracts a method from a trait object's vtable, at the
-/// specified index, and casts it to the given type.
+/// Extracts a method from a trait object's vtable, at the specified index.
pub fn get_virtual_method<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llvtable: ValueRef,
- vtable_index: usize,
- method_ty: Ty<'tcx>)
- -> Datum<'tcx, Rvalue> {
- let _icx = push_ctxt("meth::get_virtual_method");
- let ccx = bcx.ccx();
-
+ vtable_index: usize)
+ -> ValueRef {
// Load the data pointer from the object.
- debug!("get_virtual_method(callee_ty={}, vtable_index={}, llvtable={})",
- method_ty,
- vtable_index,
- bcx.val_to_string(llvtable));
+ debug!("get_virtual_method(vtable_index={}, llvtable={:?})",
+ vtable_index, Value(llvtable));
- let mptr = Load(bcx, GEPi(bcx, llvtable, &[vtable_index + VTABLE_OFFSET]));
-
- // Replace the self type (&Self or Box<Self>) with an opaque pointer.
- if let ty::TyFnDef(_, _, fty) = method_ty.sty {
- let opaque_ty = opaque_method_ty(ccx.tcx(), fty);
- immediate_rvalue(PointerCast(bcx, mptr, type_of(ccx, opaque_ty)), opaque_ty)
- } else {
- immediate_rvalue(mptr, method_ty)
- }
+ Load(bcx, GEPi(bcx, llvtable, &[vtable_index + VTABLE_OFFSET]))
}
/// Generate a shim function that allows an object type like `SomeTrait` to
@@ -211,7 +77,7 @@ pub fn get_virtual_method<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
method_ty: Ty<'tcx>,
vtable_index: usize)
- -> Datum<'tcx, Rvalue> {
+ -> ValueRef {
let _icx = push_ctxt("trans_object_shim");
let tcx = ccx.tcx();
@@ -219,58 +85,40 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
vtable_index,
method_ty);
- let ret_ty = tcx.erase_late_bound_regions(&method_ty.fn_ret());
- let ret_ty = infer::normalize_associated_type(tcx, &ret_ty);
+ let sig = tcx.erase_late_bound_regions(&method_ty.fn_sig());
+ let sig = infer::normalize_associated_type(tcx, &sig);
+ let fn_ty = FnType::new(ccx, method_ty.fn_abi(), &sig, &[]);
- let shim_fn_ty = match method_ty.sty {
- ty::TyFnDef(_, _, fty) => tcx.mk_ty(ty::TyFnPtr(fty)),
- _ => unreachable!("expected fn item type, found {}", method_ty)
- };
-
- //
- let function_name = link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim");
- let llfn = declare::define_internal_rust_fn(ccx, &function_name, shim_fn_ty);
+ let function_name = link::mangle_internal_name_by_type_and_seq(ccx, method_ty, "object_shim");
+ let llfn = declare::define_internal_fn(ccx, &function_name, method_ty);
let empty_substs = tcx.mk_substs(Substs::trans_empty());
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
- fcx = new_fn_ctxt(ccx,
- llfn,
- ast::DUMMY_NODE_ID,
- false,
- ret_ty,
- empty_substs,
- None,
- &block_arena);
- let mut bcx = init_function(&fcx, false, ret_ty);
-
- let llargs = get_params(fcx.llfn);
-
- let self_idx = fcx.arg_offset();
- let llself = llargs[self_idx];
- let llvtable = llargs[self_idx + 1];
-
- debug!("trans_object_shim: llself={}, llvtable={}",
- bcx.val_to_string(llself), bcx.val_to_string(llvtable));
-
+ fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
+ let mut bcx = fcx.init(false, None);
assert!(!fcx.needs_ret_allocas);
+
let dest =
fcx.llretslotptr.get().map(
- |_| expr::SaveIn(fcx.get_ret_slot(bcx, ret_ty, "ret_slot")));
+ |_| expr::SaveIn(fcx.get_ret_slot(bcx, "ret_slot")));
debug!("trans_object_shim: method_offset_in_vtable={}",
vtable_index);
+ let llargs = get_params(fcx.llfn);
+ let args = ArgVals(&llargs[fcx.fn_ty.ret.is_indirect() as usize..]);
+
let callee = Callee {
data: Virtual(vtable_index),
ty: method_ty
};
- bcx = callee.call(bcx, DebugLoc::None, ArgVals(&llargs[self_idx..]), dest).bcx;
+ bcx = callee.call(bcx, DebugLoc::None, args, dest).bcx;
- finish_fn(&fcx, bcx, ret_ty, DebugLoc::None);
+ fcx.finish(bcx, DebugLoc::None);
- immediate_rvalue(llfn, shim_fn_ty)
+ llfn
}
/// Creates a returns a dynamic vtable for the given type and vtable origin.
@@ -311,17 +159,9 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let nullptr = C_null(Type::nil(ccx).ptr_to());
get_vtable_methods(ccx, id, substs)
.into_iter()
- .map(|opt_mth| {
- match opt_mth {
- Some(mth) => {
- trans_fn_ref_with_substs(ccx,
- mth.method.def_id,
- None,
- &mth.substs).val
- }
- None => nullptr
- }
- })
+ .map(|opt_mth| opt_mth.map_or(nullptr, |mth| {
+ Callee::def(ccx, mth.method.def_id, &mth.substs).reify(ccx).val
+ }))
.collect::<Vec<_>>()
.into_iter()
}
@@ -452,23 +292,6 @@ pub fn get_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
.collect()
}
-/// Replace the self type (&Self or Box<Self>) with an opaque pointer.
-fn opaque_method_ty<'tcx>(tcx: &TyCtxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
- -> Ty<'tcx> {
- let mut inputs = method_ty.sig.0.inputs.clone();
- inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(ast::IntTy::I8));
-
- tcx.mk_fn_ptr(ty::BareFnTy {
- unsafety: method_ty.unsafety,
- abi: method_ty.abi,
- sig: ty::Binder(ty::FnSig {
- inputs: inputs,
- output: method_ty.sig.0.output,
- variadic: method_ty.sig.0.variadic,
- }),
- })
-}
-
#[derive(Debug)]
pub struct ImplMethod<'tcx> {
pub method: Rc<ty::Method<'tcx>>,