refactor away callee::Callee and translate virtual calls through a MIR shim
These changes are in the same commit to avoid needing to adapt meth::trans_object_shim to the new scheme. One codegen-units test is broken because we instantiate the shims even when they are not needed. This will be fixed in the next PR.
This commit is contained in:
parent
aac5ba5dab
commit
65a4266f1f
|
@ -23,6 +23,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
|
|||
#![feature(associated_consts)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![cfg_attr(stage0, feature(field_init_shorthand))]
|
||||
#![feature(i128_type)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -252,12 +252,9 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
-> Ty<'tcx> {
|
||||
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
|
||||
|
||||
// We're just hard-coding the idea that the signature will be
|
||||
// &self or &mut self and hence will have a bound region with
|
||||
// number 0, hokey.
|
||||
let region = ty::Region::ReFree(ty::FreeRegion {
|
||||
scope: tcx.region_maps.item_extent(body_id.node_id),
|
||||
bound_region: ty::BoundRegion::BrAnon(0),
|
||||
bound_region: ty::BoundRegion::BrEnv,
|
||||
});
|
||||
let region = tcx.mk_region(region);
|
||||
|
||||
|
|
|
@ -9,17 +9,19 @@
|
|||
// except according to those terms.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer;
|
||||
use rustc::middle::region::ROOT_CODE_EXTENT;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::maps::Providers;
|
||||
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
@ -35,11 +37,51 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
-> &'tcx RefCell<Mir<'tcx>>
|
||||
{
|
||||
debug!("make_shim({:?})", instance);
|
||||
let did = instance.def_id();
|
||||
let span = tcx.def_span(did);
|
||||
let param_env =
|
||||
tcx.construct_parameter_environment(span, did, ROOT_CODE_EXTENT);
|
||||
|
||||
let result = match instance {
|
||||
ty::InstanceDef::Item(..) =>
|
||||
bug!("item {:?} passed to make_shim", instance),
|
||||
ty::InstanceDef::FnPtrShim(_, ty) => {
|
||||
build_fn_ptr_shim(tcx, ty, instance.def_ty(tcx))
|
||||
ty::InstanceDef::FnPtrShim(def_id, ty) => {
|
||||
let trait_ = tcx.trait_of_item(def_id).unwrap();
|
||||
let adjustment = match tcx.lang_items.fn_trait_kind(trait_) {
|
||||
Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
|
||||
Some(ty::ClosureKind::FnMut) |
|
||||
Some(ty::ClosureKind::Fn) => Adjustment::Deref,
|
||||
None => bug!("fn pointer {:?} is not an fn", ty)
|
||||
};
|
||||
// HACK: we need the "real" argument types for the MIR,
|
||||
// but because our substs are (Self, Args), where Args
|
||||
// is a tuple, we must include the *concrete* argument
|
||||
// types in the MIR. They will be substituted again with
|
||||
// the param-substs, but because they are concrete, this
|
||||
// will not do any harm.
|
||||
let sig = tcx.erase_late_bound_regions(&ty.fn_sig());
|
||||
let arg_tys = sig.inputs();
|
||||
|
||||
build_call_shim(
|
||||
tcx,
|
||||
¶m_env,
|
||||
def_id,
|
||||
adjustment,
|
||||
CallKind::Indirect,
|
||||
Some(arg_tys)
|
||||
)
|
||||
}
|
||||
ty::InstanceDef::Virtual(def_id, _) => {
|
||||
// We are translating a call back to our def-id, which
|
||||
// trans::mir knows to turn to an actual virtual call.
|
||||
build_call_shim(
|
||||
tcx,
|
||||
¶m_env,
|
||||
def_id,
|
||||
Adjustment::Identity,
|
||||
CallKind::Direct(def_id),
|
||||
None
|
||||
)
|
||||
}
|
||||
_ => bug!("unknown shim kind")
|
||||
};
|
||||
|
@ -51,124 +93,135 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||
result
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum Adjustment {
|
||||
Identity,
|
||||
Deref,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum CallKind {
|
||||
Indirect,
|
||||
Direct(DefId),
|
||||
}
|
||||
|
||||
fn temp_decl(mutability: Mutability, ty: Ty) -> LocalDecl {
|
||||
LocalDecl { mutability, ty, name: None, source_info: None }
|
||||
}
|
||||
|
||||
fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
|
||||
-> IndexVec<Local, LocalDecl<'tcx>>
|
||||
{
|
||||
iter::once(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: sig.output(),
|
||||
name: None,
|
||||
source_info: None
|
||||
}).chain(sig.inputs().iter().map(|ity| LocalDecl {
|
||||
mutability: Mutability::Not,
|
||||
ty: *ity,
|
||||
name: None,
|
||||
source_info: None,
|
||||
})).collect()
|
||||
iter::once(temp_decl(Mutability::Mut, sig.output()))
|
||||
.chain(sig.inputs().iter().map(
|
||||
|ity| temp_decl(Mutability::Not, ity)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
fn build_fn_ptr_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn_ty: Ty<'tcx>,
|
||||
sig_ty: Ty<'tcx>)
|
||||
-> Mir<'tcx>
|
||||
/// Build a "call" shim for `def_id`. The shim calls the
|
||||
/// function specified by `call_kind`, first adjusting its first
|
||||
/// argument according to `rcvr_adjustment`.
|
||||
///
|
||||
/// If `untuple_args` is a vec of types, the second argument of the
|
||||
/// function will be untupled as these types.
|
||||
fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: &ty::ParameterEnvironment<'tcx>,
|
||||
def_id: DefId,
|
||||
rcvr_adjustment: Adjustment,
|
||||
call_kind: CallKind,
|
||||
untuple_args: Option<&[Ty<'tcx>]>)
|
||||
-> Mir<'tcx>
|
||||
{
|
||||
debug!("build_fn_ptr_shim(fn_ty={:?}, sig_ty={:?})", fn_ty, sig_ty);
|
||||
let trait_sig = match sig_ty.sty {
|
||||
ty::TyFnDef(_, _, fty) => tcx.erase_late_bound_regions(&fty),
|
||||
_ => bug!("unexpected type for shim {:?}", sig_ty)
|
||||
};
|
||||
debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \
|
||||
call_kind={:?}, untuple_args={:?})",
|
||||
def_id, rcvr_adjustment, call_kind, untuple_args);
|
||||
|
||||
let self_ty = match trait_sig.inputs()[0].sty {
|
||||
ty::TyParam(..) => fn_ty,
|
||||
ty::TyRef(r, mt) => tcx.mk_ref(r, ty::TypeAndMut {
|
||||
ty: fn_ty,
|
||||
mutbl: mt.mutbl
|
||||
}),
|
||||
_ => bug!("unexpected self_ty {:?}", trait_sig),
|
||||
};
|
||||
let fn_ty = tcx.item_type(def_id).subst(tcx, param_env.free_substs);
|
||||
// Not normalizing here without a param env.
|
||||
let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
|
||||
let span = tcx.def_span(def_id);
|
||||
|
||||
let fn_ptr_sig = match fn_ty.sty {
|
||||
ty::TyFnPtr(fty) |
|
||||
ty::TyFnDef(_, _, fty) =>
|
||||
tcx.erase_late_bound_regions_and_normalize(&fty),
|
||||
_ => bug!("non-fn-ptr {:?} in build_fn_ptr_shim", fn_ty)
|
||||
};
|
||||
|
||||
let sig = tcx.mk_fn_sig(
|
||||
[
|
||||
self_ty,
|
||||
tcx.intern_tup(fn_ptr_sig.inputs(), false)
|
||||
].iter().cloned(),
|
||||
fn_ptr_sig.output(),
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
Abi::RustCall,
|
||||
);
|
||||
debug!("build_call_shim: sig={:?}", sig);
|
||||
|
||||
let local_decls = local_decls_for_sig(&sig);
|
||||
let source_info = SourceInfo {
|
||||
span: DUMMY_SP,
|
||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||
};
|
||||
let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
|
||||
|
||||
let fn_ptr = Lvalue::Local(Local::new(1+0));
|
||||
let fn_ptr = match trait_sig.inputs()[0].sty {
|
||||
ty::TyParam(..) => fn_ptr,
|
||||
ty::TyRef(..) => Lvalue::Projection(box Projection {
|
||||
base: fn_ptr, elem: ProjectionElem::Deref
|
||||
}),
|
||||
_ => bug!("unexpected self_ty {:?}", trait_sig),
|
||||
};
|
||||
let fn_args = Local::new(1+1);
|
||||
let rcvr_l = Lvalue::Local(Local::new(1+0));
|
||||
|
||||
let return_block_id = BasicBlock::new(1);
|
||||
|
||||
// return = ADT(arg0, arg1, ...); return
|
||||
let start_block = BasicBlockData {
|
||||
let rcvr = match rcvr_adjustment {
|
||||
Adjustment::Identity => Operand::Consume(rcvr_l),
|
||||
Adjustment::Deref => Operand::Consume(Lvalue::Projection(
|
||||
box Projection { base: rcvr_l, elem: ProjectionElem::Deref }
|
||||
))
|
||||
};
|
||||
|
||||
let (callee, mut args) = match call_kind {
|
||||
CallKind::Indirect => (rcvr, vec![]),
|
||||
CallKind::Direct(def_id) => (
|
||||
Operand::Constant(Constant {
|
||||
span: span,
|
||||
ty: tcx.item_type(def_id).subst(tcx, param_env.free_substs),
|
||||
literal: Literal::Item { def_id, substs: param_env.free_substs },
|
||||
}),
|
||||
vec![rcvr]
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(untuple_args) = untuple_args {
|
||||
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
|
||||
let arg_lv = Lvalue::Local(Local::new(1+1));
|
||||
Operand::Consume(Lvalue::Projection(box Projection {
|
||||
base: arg_lv,
|
||||
elem: ProjectionElem::Field(Field::new(i), *ity)
|
||||
}))
|
||||
}));
|
||||
} else {
|
||||
args.extend((1..sig.inputs().len()).map(|i| {
|
||||
Operand::Consume(Lvalue::Local(Local::new(1+i)))
|
||||
}));
|
||||
}
|
||||
|
||||
let mut blocks = IndexVec::new();
|
||||
blocks.push(BasicBlockData {
|
||||
statements: vec![],
|
||||
terminator: Some(Terminator {
|
||||
source_info: source_info,
|
||||
kind: TerminatorKind::Call {
|
||||
func: Operand::Consume(fn_ptr),
|
||||
args: fn_ptr_sig.inputs().iter().enumerate().map(|(i, ity)| {
|
||||
Operand::Consume(Lvalue::Projection(box Projection {
|
||||
base: Lvalue::Local(fn_args),
|
||||
elem: ProjectionElem::Field(
|
||||
Field::new(i), *ity
|
||||
)
|
||||
}))
|
||||
}).collect(),
|
||||
// FIXME: can we pass a Some destination for an uninhabited ty?
|
||||
func: callee,
|
||||
args: args,
|
||||
destination: Some((Lvalue::Local(RETURN_POINTER),
|
||||
return_block_id)),
|
||||
cleanup: None
|
||||
}
|
||||
}),
|
||||
is_cleanup: false
|
||||
};
|
||||
let return_block = BasicBlockData {
|
||||
});
|
||||
blocks.push(BasicBlockData {
|
||||
statements: vec![],
|
||||
terminator: Some(Terminator {
|
||||
source_info: source_info,
|
||||
kind: TerminatorKind::Return
|
||||
}),
|
||||
is_cleanup: false
|
||||
};
|
||||
});
|
||||
|
||||
let mut mir = Mir::new(
|
||||
vec![start_block, return_block].into_iter().collect(),
|
||||
blocks,
|
||||
IndexVec::from_elem_n(
|
||||
VisibilityScopeData { span: DUMMY_SP, parent_scope: None }, 1
|
||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||
),
|
||||
IndexVec::new(),
|
||||
sig.output(),
|
||||
local_decls,
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
DUMMY_SP
|
||||
span
|
||||
);
|
||||
mir.spread_arg = Some(fn_args);
|
||||
if let Abi::RustCall = sig.abi {
|
||||
mir.spread_arg = Some(Local::new(sig.inputs().len()));
|
||||
}
|
||||
mir
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use llvm::{self, ValueRef, Integer, Pointer, Float, Double, Struct, Array, Vector, AttributePlace};
|
||||
use base;
|
||||
use builder::Builder;
|
||||
use common::{type_is_fat_ptr, C_uint};
|
||||
use common::{self, type_is_fat_ptr, C_uint};
|
||||
use context::CrateContext;
|
||||
use cabi_x86;
|
||||
use cabi_x86_64;
|
||||
|
@ -334,9 +334,30 @@ impl FnType {
|
|||
fn_ty
|
||||
}
|
||||
|
||||
pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
pub fn new_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
sig: ty::FnSig<'tcx>,
|
||||
extra_args: &[Ty<'tcx>]) -> FnType {
|
||||
let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
|
||||
// Don't pass the vtable, it's not an argument of the virtual fn.
|
||||
fn_ty.args[1].ignore();
|
||||
fn_ty.adjust_for_abi(ccx, sig);
|
||||
fn_ty
|
||||
}
|
||||
|
||||
pub fn from_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
instance: &ty::Instance<'tcx>,
|
||||
extra_args: &[Ty<'tcx>]) -> FnType
|
||||
{
|
||||
let ity = common::instance_ty(ccx.shared(), instance);
|
||||
let sig = common::ty_fn_sig(ccx, ity);
|
||||
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
|
||||
|
||||
Self::new(ccx, sig, extra_args)
|
||||
}
|
||||
|
||||
fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
sig: ty::FnSig<'tcx>,
|
||||
extra_args: &[Ty<'tcx>]) -> FnType {
|
||||
use self::Abi::*;
|
||||
let cconv = match ccx.sess().target.target.adjust_abi(sig.abi) {
|
||||
RustIntrinsic | PlatformIntrinsic |
|
||||
|
@ -532,9 +553,9 @@ impl FnType {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn adjust_for_abi<'a, 'tcx>(&mut self,
|
||||
ccx: &CrateContext<'a, 'tcx>,
|
||||
sig: ty::FnSig<'tcx>) {
|
||||
fn adjust_for_abi<'a, 'tcx>(&mut self,
|
||||
ccx: &CrateContext<'a, 'tcx>,
|
||||
sig: ty::FnSig<'tcx>) {
|
||||
let abi = sig.abi;
|
||||
if abi == Abi::Unadjusted { return }
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ use abi;
|
|||
use mir::lvalue::LvalueRef;
|
||||
use attributes;
|
||||
use builder::Builder;
|
||||
use callee::{Callee};
|
||||
use callee;
|
||||
use common::{C_bool, C_bytes_in_context, C_i32, C_uint};
|
||||
use collector::{self, TransItemCollectionMode};
|
||||
use common::{C_struct_in_context, C_u64, C_undef};
|
||||
|
@ -654,7 +654,7 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
|
|||
return;
|
||||
}
|
||||
|
||||
let main_llfn = Callee::def(ccx, main_def_id, instance.substs).reify(ccx);
|
||||
let main_llfn = callee::get_fn(ccx, instance);
|
||||
|
||||
let et = ccx.sess().entry_type.get().unwrap();
|
||||
match et {
|
||||
|
@ -688,8 +688,8 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
|
|||
|
||||
let (start_fn, args) = if use_start_lang_item {
|
||||
let start_def_id = ccx.tcx().require_lang_item(StartFnLangItem);
|
||||
let empty_substs = ccx.tcx().intern_substs(&[]);
|
||||
let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx);
|
||||
let start_instance = Instance::mono(ccx.tcx(), start_def_id);
|
||||
let start_fn = callee::get_fn(ccx, start_instance);
|
||||
(start_fn, vec![bld.pointercast(rust_main, Type::i8p(ccx).ptr_to()), get_param(llfn, 0),
|
||||
get_param(llfn, 1)])
|
||||
} else {
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
//! and methods are represented as just a fn ptr and not a full
|
||||
//! closure.
|
||||
|
||||
pub use self::CalleeData::*;
|
||||
|
||||
use llvm::{self, ValueRef, get_params};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::subst::{Substs, Subst};
|
||||
|
@ -27,98 +25,17 @@ use cleanup::CleanupScope;
|
|||
use mir::lvalue::LvalueRef;
|
||||
use monomorphize;
|
||||
use consts;
|
||||
use common::instance_ty;
|
||||
use declare;
|
||||
use value::Value;
|
||||
use meth;
|
||||
use monomorphize::Instance;
|
||||
use back::symbol_names::symbol_name;
|
||||
use trans_item::TransItem;
|
||||
use type_of;
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use rustc::ty::{self, TypeFoldable};
|
||||
use std::iter;
|
||||
|
||||
use mir::lvalue::Alignment;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CalleeData {
|
||||
/// Function pointer.
|
||||
Fn(ValueRef),
|
||||
|
||||
Intrinsic,
|
||||
|
||||
/// Trait object found in the vtable at that index.
|
||||
Virtual(usize)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Callee<'tcx> {
|
||||
pub data: CalleeData,
|
||||
pub ty: Ty<'tcx>
|
||||
}
|
||||
|
||||
impl<'tcx> Callee<'tcx> {
|
||||
/// Function or method definition.
|
||||
pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>)
|
||||
-> Callee<'tcx> {
|
||||
let instance = monomorphize::resolve(ccx.shared(), def_id, substs);
|
||||
let ty = instance_ty(ccx.shared(), &instance);
|
||||
let data = match instance.def {
|
||||
ty::InstanceDef::Intrinsic(_) => Intrinsic,
|
||||
ty::InstanceDef::ClosureOnceShim { .. } => {
|
||||
let closure_ty = instance.substs.type_at(0);
|
||||
let (closure_def_id, closure_substs) = match closure_ty.sty {
|
||||
ty::TyClosure(def_id, substs) => (def_id, substs),
|
||||
_ => bug!("bad closure instance {:?}", instance)
|
||||
};
|
||||
|
||||
Fn(trans_fn_once_adapter_shim(
|
||||
ccx,
|
||||
closure_def_id,
|
||||
closure_substs,
|
||||
instance,
|
||||
get_fn(
|
||||
ccx,
|
||||
Instance::new(closure_def_id, closure_substs.substs)
|
||||
)
|
||||
))
|
||||
}
|
||||
ty::InstanceDef::Virtual(_, n) => Virtual(n),
|
||||
ty::InstanceDef::FnPtrShim(..) |
|
||||
ty::InstanceDef::Item(..) => {
|
||||
Fn(get_fn(ccx, instance))
|
||||
}
|
||||
};
|
||||
|
||||
Callee { data, ty }
|
||||
}
|
||||
|
||||
/// Get the abi::FnType for a direct call. Mainly deals with the fact
|
||||
/// that a Virtual call doesn't take the vtable, like its shim does.
|
||||
/// The extra argument types are for variadic (extern "C") functions.
|
||||
pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
|
||||
extra_args: &[Ty<'tcx>]) -> FnType {
|
||||
let sig = common::ty_fn_sig(ccx, self.ty);
|
||||
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
|
||||
let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
|
||||
if let Virtual(_) = self.data {
|
||||
// Don't pass the vtable, it's not an argument of the virtual fn.
|
||||
fn_ty.args[1].ignore();
|
||||
}
|
||||
fn_ty.adjust_for_abi(ccx, sig);
|
||||
fn_ty
|
||||
}
|
||||
|
||||
/// Turn the callee into a function pointer.
|
||||
pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
|
||||
match self.data {
|
||||
Fn(llfn) => llfn,
|
||||
Virtual(_) => meth::trans_object_shim(ccx, self),
|
||||
Intrinsic => bug!("intrinsic {} getting reified", self.ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
||||
ccx: &'a CrateContext<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
|
@ -145,13 +62,14 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
let sig = tcx.closure_type(def_id).subst(tcx, substs.substs);
|
||||
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
|
||||
assert_eq!(sig.abi, Abi::RustCall);
|
||||
let llref_fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
|
||||
let llref_fn_sig = tcx.mk_fn_sig(
|
||||
iter::once(ref_closure_ty).chain(sig.inputs().iter().cloned()),
|
||||
sig.output(),
|
||||
sig.variadic,
|
||||
sig.unsafety,
|
||||
Abi::RustCall
|
||||
)));
|
||||
);
|
||||
let llref_fn_ty = tcx.mk_fn_ptr(ty::Binder(llref_fn_sig));
|
||||
debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
|
||||
llref_fn_ty);
|
||||
|
||||
|
@ -177,15 +95,10 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
let orig_fn_ty = fn_ty;
|
||||
let mut bcx = Builder::new_block(ccx, lloncefn, "entry-block");
|
||||
|
||||
let callee = Callee {
|
||||
data: Fn(llreffn),
|
||||
ty: llref_fn_ty
|
||||
};
|
||||
|
||||
// the first argument (`self`) will be the (by value) closure env.
|
||||
|
||||
let mut llargs = get_params(lloncefn);
|
||||
let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
|
||||
let fn_ty = FnType::new(ccx, llref_fn_sig, &[]);
|
||||
let self_idx = fn_ty.ret.is_indirect() as usize;
|
||||
let env_arg = &orig_fn_ty.args[0];
|
||||
let env = if env_arg.is_indirect() {
|
||||
|
@ -210,14 +123,13 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
// to drop `self` when the body returns, or in case it unwinds.
|
||||
let self_scope = CleanupScope::schedule_drop_mem(&bcx, env);
|
||||
|
||||
let llfn = callee.reify(bcx.ccx);
|
||||
let llret;
|
||||
if let Some(landing_pad) = self_scope.landing_pad {
|
||||
let normal_bcx = bcx.build_sibling_block("normal-return");
|
||||
llret = bcx.invoke(llfn, &llargs[..], normal_bcx.llbb(), landing_pad, None);
|
||||
llret = bcx.invoke(llreffn, &llargs[..], normal_bcx.llbb(), landing_pad, None);
|
||||
bcx = normal_bcx;
|
||||
} else {
|
||||
llret = bcx.call(llfn, &llargs[..], None);
|
||||
llret = bcx.call(llreffn, &llargs[..], None);
|
||||
}
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
|
||||
|
@ -247,9 +159,9 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
/// - `ccx`: the crate context
|
||||
/// - `def_id`: def id of the fn or method item being referenced
|
||||
/// - `substs`: values for each of the fn/method's parameters
|
||||
fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
instance: Instance<'tcx>)
|
||||
-> ValueRef
|
||||
fn do_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
instance: Instance<'tcx>)
|
||||
-> ValueRef
|
||||
{
|
||||
let tcx = ccx.tcx();
|
||||
|
||||
|
@ -335,3 +247,45 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
instance: Instance<'tcx>)
|
||||
-> ValueRef
|
||||
{
|
||||
match instance.def {
|
||||
ty::InstanceDef::Intrinsic(_) => {
|
||||
bug!("intrinsic {} getting reified", instance)
|
||||
}
|
||||
ty::InstanceDef::ClosureOnceShim { .. } => {
|
||||
let closure_ty = instance.substs.type_at(0);
|
||||
let (closure_def_id, closure_substs) = match closure_ty.sty {
|
||||
ty::TyClosure(def_id, substs) => (def_id, substs),
|
||||
_ => bug!("bad closure instance {:?}", instance)
|
||||
};
|
||||
|
||||
trans_fn_once_adapter_shim(
|
||||
ccx,
|
||||
closure_def_id,
|
||||
closure_substs,
|
||||
instance,
|
||||
do_get_fn(
|
||||
ccx,
|
||||
Instance::new(closure_def_id, closure_substs.substs)
|
||||
)
|
||||
)
|
||||
}
|
||||
ty::InstanceDef::FnPtrShim(..) |
|
||||
ty::InstanceDef::Item(..) |
|
||||
ty::InstanceDef::Virtual(..) => {
|
||||
do_get_fn(ccx, instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
-> ValueRef
|
||||
{
|
||||
get_fn(ccx, monomorphize::resolve(ccx.shared(), def_id, substs))
|
||||
}
|
||||
|
|
|
@ -656,8 +656,8 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan
|
|||
ty::InstanceDef::ClosureOnceShim {
|
||||
call_once: _, closure_did: def_id
|
||||
} => def_id,
|
||||
ty::InstanceDef::FnPtrShim(..) => return true,
|
||||
ty::InstanceDef::Virtual(..) |
|
||||
ty::InstanceDef::FnPtrShim(..) => return true,
|
||||
ty::InstanceDef::Intrinsic(_) => return false
|
||||
};
|
||||
match tcx.hir.get_if_local(def_id) {
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc::hir::def::ExportMap;
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::traits;
|
||||
use debuginfo;
|
||||
use callee::Callee;
|
||||
use callee;
|
||||
use base;
|
||||
use declare;
|
||||
use glue::DropGlueKind;
|
||||
|
@ -920,7 +920,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
let llfn = match tcx.lang_items.eh_personality() {
|
||||
Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
|
||||
Callee::def(self, def_id, tcx.intern_substs(&[])).reify(self)
|
||||
callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
|
||||
}
|
||||
_ => {
|
||||
let name = if base::wants_msvc_seh(self.sess()) {
|
||||
|
@ -948,7 +948,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
assert!(self.sess().target.target.options.custom_unwind_resume);
|
||||
if let Some(def_id) = tcx.lang_items.eh_unwind_resume() {
|
||||
let llfn = Callee::def(self, def_id, tcx.intern_substs(&[])).reify(self);
|
||||
let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
|
||||
unwresume.set(Some(llfn));
|
||||
return llfn;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,10 @@ use rustc::ty::{self, layout, AdtDef, AdtKind, Ty, TypeFoldable};
|
|||
use rustc::ty::subst::Kind;
|
||||
use rustc::mir::tcx::LvalueTy;
|
||||
use mir::lvalue::LvalueRef;
|
||||
use abi::FnType;
|
||||
use adt;
|
||||
use base::*;
|
||||
use callee::Callee;
|
||||
use callee::get_fn;
|
||||
use cleanup::CleanupScope;
|
||||
use common::*;
|
||||
use machine::*;
|
||||
|
@ -45,11 +46,10 @@ pub fn trans_exchange_free_ty<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, ptr: LvalueRef<
|
|||
let content_ty = ptr.ty.to_ty(bcx.tcx());
|
||||
let def_id = langcall(bcx.tcx(), None, "", BoxFreeFnLangItem);
|
||||
let substs = bcx.tcx().mk_substs(iter::once(Kind::from(content_ty)));
|
||||
let callee = Callee::def(bcx.ccx, def_id, substs);
|
||||
let instance = monomorphize::resolve(bcx.ccx.shared(), def_id, substs);
|
||||
|
||||
let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
|
||||
|
||||
let llret = bcx.call(callee.reify(bcx.ccx),
|
||||
let fn_ty = FnType::from_instance(bcx.ccx, &instance, &[]);
|
||||
let llret = bcx.call(get_fn(bcx.ccx, instance),
|
||||
&[ptr.llval, ptr.llextra][..1 + ptr.has_extra() as usize], None);
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
}
|
||||
|
@ -258,16 +258,18 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
|
|||
.find(|it| it.kind == ty::AssociatedKind::Method)
|
||||
.unwrap().def_id;
|
||||
let self_type_substs = tcx.mk_substs_trait(t, &[]);
|
||||
let callee = Callee::def(bcx.ccx, drop_method, self_type_substs);
|
||||
let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
|
||||
let drop_instance = monomorphize::resolve(
|
||||
bcx.ccx.shared(), drop_method, self_type_substs);
|
||||
let fn_ty = FnType::from_instance(bcx.ccx, &drop_instance, &[]);
|
||||
let llfn = get_fn(bcx.ccx, drop_instance);
|
||||
let llret;
|
||||
let args = &[ptr.llval, ptr.llextra][..1 + ptr.has_extra() as usize];
|
||||
if let Some(landing_pad) = contents_scope.landing_pad {
|
||||
let normal_bcx = bcx.build_sibling_block("normal-return");
|
||||
llret = bcx.invoke(callee.reify(ccx), args, normal_bcx.llbb(), landing_pad, None);
|
||||
llret = bcx.invoke(llfn, args, normal_bcx.llbb(), landing_pad, None);
|
||||
bcx = normal_bcx;
|
||||
} else {
|
||||
llret = bcx.call(callee.reify(bcx.ccx), args, None);
|
||||
llret = bcx.call(llfn, args, None);
|
||||
}
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
contents_scope.trans(&bcx);
|
||||
|
|
|
@ -8,20 +8,16 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use attributes;
|
||||
use llvm::{ValueRef, get_params};
|
||||
use llvm::ValueRef;
|
||||
use rustc::traits;
|
||||
use callee::{Callee, CalleeData};
|
||||
use callee;
|
||||
use common::*;
|
||||
use builder::Builder;
|
||||
use consts;
|
||||
use declare;
|
||||
use glue;
|
||||
use machine;
|
||||
use monomorphize::Instance;
|
||||
use type_::Type;
|
||||
use type_of::*;
|
||||
use back::symbol_names;
|
||||
use value::Value;
|
||||
use rustc::ty;
|
||||
|
||||
|
@ -42,74 +38,6 @@ pub fn get_virtual_method<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
|||
ptr
|
||||
}
|
||||
|
||||
/// Generate a shim function that allows an object type like `SomeTrait` to
|
||||
/// implement the type `SomeTrait`. Imagine a trait definition:
|
||||
///
|
||||
/// trait SomeTrait { fn get(&self) -> i32; ... }
|
||||
///
|
||||
/// And a generic bit of code:
|
||||
///
|
||||
/// fn foo<T:SomeTrait>(t: &T) {
|
||||
/// let x = SomeTrait::get;
|
||||
/// x(t)
|
||||
/// }
|
||||
///
|
||||
/// What is the value of `x` when `foo` is invoked with `T=SomeTrait`?
|
||||
/// The answer is that it is a shim function generated by this routine:
|
||||
///
|
||||
/// fn shim(t: &SomeTrait) -> i32 {
|
||||
/// // ... call t.get() virtually ...
|
||||
/// }
|
||||
///
|
||||
/// In fact, all virtual calls can be thought of as normal trait calls
|
||||
/// that go through this shim function.
|
||||
pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
|
||||
callee: Callee<'tcx>)
|
||||
-> ValueRef {
|
||||
debug!("trans_object_shim({:?})", callee);
|
||||
|
||||
let function_name = match callee.ty.sty {
|
||||
ty::TyFnDef(def_id, substs, _) => {
|
||||
let instance = Instance::new(def_id, substs);
|
||||
symbol_names::symbol_name(instance, ccx.shared())
|
||||
}
|
||||
_ => bug!()
|
||||
};
|
||||
|
||||
let llfn = declare::define_internal_fn(ccx, &function_name, callee.ty);
|
||||
attributes::set_frame_pointer_elimination(ccx, llfn);
|
||||
|
||||
let bcx = Builder::new_block(ccx, llfn, "entry-block");
|
||||
|
||||
let mut llargs = get_params(llfn);
|
||||
let fn_ret = callee.ty.fn_ret();
|
||||
let fn_ty = callee.direct_fn_type(ccx, &[]);
|
||||
|
||||
let fn_ptr = match callee.data {
|
||||
CalleeData::Virtual(idx) => {
|
||||
let fn_ptr = get_virtual_method(&bcx,
|
||||
llargs.remove(fn_ty.ret.is_indirect() as usize + 1), idx);
|
||||
let llty = fn_ty.llvm_type(bcx.ccx).ptr_to();
|
||||
bcx.pointercast(fn_ptr, llty)
|
||||
},
|
||||
_ => bug!("trans_object_shim called with non-virtual callee"),
|
||||
};
|
||||
let llret = bcx.call(fn_ptr, &llargs, None);
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
|
||||
if fn_ret.0.is_never() {
|
||||
bcx.unreachable();
|
||||
} else {
|
||||
if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
|
||||
bcx.ret_void();
|
||||
} else {
|
||||
bcx.ret(llret);
|
||||
}
|
||||
}
|
||||
|
||||
llfn
|
||||
}
|
||||
|
||||
/// Creates a dynamic vtable for the given type and vtable origin.
|
||||
/// This is used only for objects.
|
||||
///
|
||||
|
@ -150,7 +78,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
let trait_ref = trait_ref.with_self_ty(tcx, ty);
|
||||
let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| {
|
||||
opt_mth.map_or(nullptr, |(def_id, substs)| {
|
||||
Callee::def(ccx, def_id, substs).reify(ccx)
|
||||
callee::resolve_and_get_fn(ccx, def_id, substs)
|
||||
})
|
||||
});
|
||||
components.extend(methods);
|
||||
|
|
|
@ -16,13 +16,14 @@ use rustc::ty::{self, layout, TypeFoldable};
|
|||
use rustc::mir;
|
||||
use abi::{Abi, FnType, ArgType};
|
||||
use base::{self, Lifetime};
|
||||
use callee::{Callee, CalleeData, Fn, Intrinsic, Virtual};
|
||||
use callee;
|
||||
use builder::Builder;
|
||||
use common::{self, Funclet};
|
||||
use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef};
|
||||
use consts;
|
||||
use machine::llalign_of_min;
|
||||
use meth;
|
||||
use monomorphize;
|
||||
use type_of::{self, align_of};
|
||||
use glue;
|
||||
use type_::Type;
|
||||
|
@ -340,9 +341,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
|
||||
// Obtain the panic entry point.
|
||||
let def_id = common::langcall(bcx.tcx(), Some(span), "", lang_item);
|
||||
let callee = Callee::def(bcx.ccx, def_id,
|
||||
bcx.ccx.empty_substs_for_def_id(def_id));
|
||||
let llfn = callee.reify(bcx.ccx);
|
||||
let instance = ty::Instance::mono(bcx.tcx(), def_id);
|
||||
let llfn = callee::get_fn(bcx.ccx, instance);
|
||||
|
||||
// Translate the actual panic invoke/call.
|
||||
if let Some(unwind) = cleanup {
|
||||
|
@ -365,30 +365,30 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
|
||||
let callee = self.trans_operand(&bcx, func);
|
||||
|
||||
let (mut callee, sig) = match callee.ty.sty {
|
||||
let (instance, mut llfn, sig) = match callee.ty.sty {
|
||||
ty::TyFnDef(def_id, substs, sig) => {
|
||||
(Callee::def(bcx.ccx, def_id, substs), sig)
|
||||
(Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)),
|
||||
None,
|
||||
sig)
|
||||
}
|
||||
ty::TyFnPtr(sig) => {
|
||||
(Callee {
|
||||
data: Fn(callee.immediate()),
|
||||
ty: callee.ty
|
||||
}, sig)
|
||||
(None,
|
||||
Some(callee.immediate()),
|
||||
sig)
|
||||
}
|
||||
_ => bug!("{} is not callable", callee.ty)
|
||||
};
|
||||
|
||||
let def = instance.map(|i| i.def);
|
||||
let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
|
||||
let abi = sig.abi;
|
||||
|
||||
// Handle intrinsics old trans wants Expr's for, ourselves.
|
||||
let intrinsic = match (&callee.ty.sty, &callee.data) {
|
||||
(&ty::TyFnDef(def_id, ..), &Intrinsic) => {
|
||||
Some(bcx.tcx().item_name(def_id).as_str())
|
||||
}
|
||||
let intrinsic = match def {
|
||||
Some(ty::InstanceDef::Intrinsic(def_id))
|
||||
=> Some(bcx.tcx().item_name(def_id).as_str()),
|
||||
_ => None
|
||||
};
|
||||
let mut intrinsic = intrinsic.as_ref().map(|s| &s[..]);
|
||||
let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
|
||||
|
||||
if intrinsic == Some("move_val_init") {
|
||||
let &(_, target) = destination.as_ref().unwrap();
|
||||
|
@ -412,15 +412,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
let op_ty = op_arg.ty(&self.mir, bcx.tcx());
|
||||
self.monomorphize(&op_ty)
|
||||
}).collect::<Vec<_>>();
|
||||
let fn_ty = callee.direct_fn_type(bcx.ccx, &extra_args);
|
||||
|
||||
let fn_ty = match def {
|
||||
Some(ty::InstanceDef::Virtual(..)) => {
|
||||
FnType::new_vtable(bcx.ccx, sig, &extra_args)
|
||||
}
|
||||
_ => FnType::new(bcx.ccx, sig, &extra_args)
|
||||
};
|
||||
|
||||
if intrinsic == Some("drop_in_place") {
|
||||
let &(_, target) = destination.as_ref().unwrap();
|
||||
let ty = if let ty::TyFnDef(_, substs, _) = callee.ty.sty {
|
||||
substs.type_at(0)
|
||||
} else {
|
||||
bug!("Unexpected ty: {}", callee.ty);
|
||||
};
|
||||
let ty = instance.unwrap().substs.type_at(0);
|
||||
|
||||
// Double check for necessity to drop
|
||||
if !bcx.ccx.shared().type_needs_drop(ty) {
|
||||
|
@ -430,8 +432,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
|
||||
let drop_fn = glue::get_drop_glue(bcx.ccx, ty);
|
||||
let llty = fn_ty.llvm_type(bcx.ccx).ptr_to();
|
||||
callee.data = Fn(bcx.pointercast(drop_fn, llty));
|
||||
intrinsic = None;
|
||||
llfn = Some(bcx.pointercast(drop_fn, llty));
|
||||
}
|
||||
|
||||
// The arguments we'll be passing. Plus one to account for outptr, if used.
|
||||
|
@ -440,12 +441,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
|
||||
// Prepare the return value destination
|
||||
let ret_dest = if let Some((ref dest, _)) = *destination {
|
||||
let is_intrinsic = if let Intrinsic = callee.data {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs, is_intrinsic)
|
||||
let is_intrinsic = intrinsic.is_some();
|
||||
self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs,
|
||||
is_intrinsic)
|
||||
} else {
|
||||
ReturnDest::Nothing
|
||||
};
|
||||
|
@ -483,52 +481,56 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
|
||||
let op = self.trans_operand(&bcx, arg);
|
||||
self.trans_argument(&bcx, op, &mut llargs, &fn_ty,
|
||||
&mut idx, &mut callee.data);
|
||||
&mut idx, &mut llfn, &def);
|
||||
}
|
||||
if let Some(tup) = untuple {
|
||||
self.trans_arguments_untupled(&bcx, tup, &mut llargs, &fn_ty,
|
||||
&mut idx, &mut callee.data)
|
||||
&mut idx, &mut llfn, &def)
|
||||
}
|
||||
|
||||
let fn_ptr = match callee.data {
|
||||
Intrinsic => {
|
||||
use intrinsic::trans_intrinsic_call;
|
||||
if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
|
||||
use intrinsic::trans_intrinsic_call;
|
||||
|
||||
let (dest, llargs) = match ret_dest {
|
||||
_ if fn_ty.ret.is_indirect() => {
|
||||
(llargs[0], &llargs[1..])
|
||||
}
|
||||
ReturnDest::Nothing => {
|
||||
(C_undef(fn_ty.ret.original_ty.ptr_to()), &llargs[..])
|
||||
}
|
||||
ReturnDest::IndirectOperand(dst, _) |
|
||||
ReturnDest::Store(dst) => (dst, &llargs[..]),
|
||||
ReturnDest::DirectOperand(_) =>
|
||||
bug!("Cannot use direct operand with an intrinsic call")
|
||||
let (dest, llargs) = match ret_dest {
|
||||
_ if fn_ty.ret.is_indirect() => {
|
||||
(llargs[0], &llargs[1..])
|
||||
}
|
||||
ReturnDest::Nothing => {
|
||||
(C_undef(fn_ty.ret.original_ty.ptr_to()), &llargs[..])
|
||||
}
|
||||
ReturnDest::IndirectOperand(dst, _) |
|
||||
ReturnDest::Store(dst) => (dst, &llargs[..]),
|
||||
ReturnDest::DirectOperand(_) =>
|
||||
bug!("Cannot use direct operand with an intrinsic call")
|
||||
};
|
||||
|
||||
let callee_ty = common::instance_ty(
|
||||
bcx.ccx.shared(), instance.as_ref().unwrap());
|
||||
trans_intrinsic_call(&bcx, callee_ty, &fn_ty, &llargs, dest,
|
||||
terminator.source_info.span);
|
||||
|
||||
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
||||
// Make a fake operand for store_return
|
||||
let op = OperandRef {
|
||||
val: Ref(dst, Alignment::AbiAligned),
|
||||
ty: sig.output(),
|
||||
};
|
||||
|
||||
trans_intrinsic_call(&bcx, callee.ty, &fn_ty, &llargs, dest,
|
||||
terminator.source_info.span);
|
||||
|
||||
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
||||
// Make a fake operand for store_return
|
||||
let op = OperandRef {
|
||||
val: Ref(dst, Alignment::AbiAligned),
|
||||
ty: sig.output(),
|
||||
};
|
||||
self.store_return(&bcx, ret_dest, fn_ty.ret, op);
|
||||
}
|
||||
|
||||
if let Some((_, target)) = *destination {
|
||||
funclet_br(self, bcx, target);
|
||||
} else {
|
||||
bcx.unreachable();
|
||||
}
|
||||
|
||||
return;
|
||||
self.store_return(&bcx, ret_dest, fn_ty.ret, op);
|
||||
}
|
||||
Fn(f) => f,
|
||||
Virtual(_) => bug!("Virtual fn ptr not extracted")
|
||||
|
||||
if let Some((_, target)) = *destination {
|
||||
funclet_br(self, bcx, target);
|
||||
} else {
|
||||
bcx.unreachable();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let fn_ptr = match (llfn, instance) {
|
||||
(Some(llfn), _) => llfn,
|
||||
(None, Some(instance)) => callee::get_fn(bcx.ccx, instance),
|
||||
_ => span_bug!(span, "no llfn for call"),
|
||||
};
|
||||
|
||||
// Many different ways to call a function handled here
|
||||
|
@ -578,16 +580,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
llargs: &mut Vec<ValueRef>,
|
||||
fn_ty: &FnType,
|
||||
next_idx: &mut usize,
|
||||
callee: &mut CalleeData) {
|
||||
llfn: &mut Option<ValueRef>,
|
||||
def: &Option<ty::InstanceDef<'tcx>>) {
|
||||
if let Pair(a, b) = op.val {
|
||||
// Treat the values in a fat pointer separately.
|
||||
if common::type_is_fat_ptr(bcx.ccx, op.ty) {
|
||||
let (ptr, meta) = (a, b);
|
||||
if *next_idx == 0 {
|
||||
if let Virtual(idx) = *callee {
|
||||
let llfn = meth::get_virtual_method(bcx, meta, idx);
|
||||
if let Some(ty::InstanceDef::Virtual(_, idx)) = *def {
|
||||
let llmeth = meth::get_virtual_method(bcx, meta, idx);
|
||||
let llty = fn_ty.llvm_type(bcx.ccx).ptr_to();
|
||||
*callee = Fn(bcx.pointercast(llfn, llty));
|
||||
*llfn = Some(bcx.pointercast(llmeth, llty));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,8 +599,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
// We won't be checking the type again.
|
||||
ty: bcx.tcx().types.err
|
||||
};
|
||||
self.trans_argument(bcx, imm_op(ptr), llargs, fn_ty, next_idx, callee);
|
||||
self.trans_argument(bcx, imm_op(meta), llargs, fn_ty, next_idx, callee);
|
||||
self.trans_argument(bcx, imm_op(ptr), llargs, fn_ty, next_idx, llfn, def);
|
||||
self.trans_argument(bcx, imm_op(meta), llargs, fn_ty, next_idx, llfn, def);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -660,7 +663,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
llargs: &mut Vec<ValueRef>,
|
||||
fn_ty: &FnType,
|
||||
next_idx: &mut usize,
|
||||
callee: &mut CalleeData) {
|
||||
llfn: &mut Option<ValueRef>,
|
||||
def: &Option<ty::InstanceDef<'tcx>>) {
|
||||
let tuple = self.trans_operand(bcx, operand);
|
||||
|
||||
let arg_types = match tuple.ty.sty {
|
||||
|
@ -686,7 +690,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
val: val,
|
||||
ty: ty
|
||||
};
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -708,7 +712,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
val: Immediate(elem),
|
||||
ty: ty
|
||||
};
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
|
||||
}
|
||||
}
|
||||
Pair(a, b) => {
|
||||
|
@ -724,7 +728,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
val: Immediate(elem),
|
||||
ty: ty
|
||||
};
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use rustc::ty::cast::{CastTy, IntTy};
|
|||
use rustc::ty::subst::{Kind, Substs, Subst};
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use {abi, adt, base, Disr, machine};
|
||||
use callee::Callee;
|
||||
use callee;
|
||||
use builder::Builder;
|
||||
use common::{self, CrateContext, const_get_elt, val_ty};
|
||||
use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral, C_big_integral};
|
||||
|
@ -565,8 +565,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
|||
mir::CastKind::ReifyFnPointer => {
|
||||
match operand.ty.sty {
|
||||
ty::TyFnDef(def_id, substs, _) => {
|
||||
Callee::def(self.ccx, def_id, substs)
|
||||
.reify(self.ccx)
|
||||
callee::resolve_and_get_fn(self.ccx, def_id, substs)
|
||||
}
|
||||
_ => {
|
||||
span_bug!(span, "{} cannot be reified to a fn ptr",
|
||||
|
@ -589,8 +588,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
|||
let input = tcx.erase_late_bound_regions_and_normalize(&input);
|
||||
let substs = tcx.mk_substs([operand.ty, input]
|
||||
.iter().cloned().map(Kind::from));
|
||||
Callee::def(self.ccx, call_once, substs)
|
||||
.reify(self.ccx)
|
||||
callee::resolve_and_get_fn(self.ccx, call_once, substs)
|
||||
}
|
||||
_ => {
|
||||
bug!("{} cannot be cast to a fn ptr", operand.ty)
|
||||
|
|
|
@ -19,7 +19,7 @@ use middle::lang_items::ExchangeMallocFnLangItem;
|
|||
|
||||
use base;
|
||||
use builder::Builder;
|
||||
use callee::Callee;
|
||||
use callee;
|
||||
use common::{self, val_ty, C_bool, C_null, C_uint};
|
||||
use common::{C_integral};
|
||||
use adt;
|
||||
|
@ -183,8 +183,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
match operand.ty.sty {
|
||||
ty::TyFnDef(def_id, substs, _) => {
|
||||
OperandValue::Immediate(
|
||||
Callee::def(bcx.ccx, def_id, substs)
|
||||
.reify(bcx.ccx))
|
||||
callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
|
||||
}
|
||||
_ => {
|
||||
bug!("{} cannot be reified to a fn ptr", operand.ty)
|
||||
|
@ -208,8 +207,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
let substs = bcx.tcx().mk_substs([operand.ty, input]
|
||||
.iter().cloned().map(Kind::from));
|
||||
OperandValue::Immediate(
|
||||
Callee::def(bcx.ccx, call_once, substs)
|
||||
.reify(bcx.ccx))
|
||||
callee::resolve_and_get_fn(bcx.ccx, call_once, substs)
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
bug!("{} cannot be cast to a fn ptr", operand.ty)
|
||||
|
@ -463,8 +462,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
bcx.sess().fatal(&format!("allocation of `{}` {}", box_ty, s));
|
||||
}
|
||||
};
|
||||
let r = Callee::def(bcx.ccx, def_id, bcx.tcx().intern_substs(&[]))
|
||||
.reify(bcx.ccx);
|
||||
let instance = ty::Instance::mono(bcx.tcx(), def_id);
|
||||
let r = callee::get_fn(bcx.ccx, instance);
|
||||
let val = bcx.pointercast(bcx.call(r, &[llsize, llalign], None), llty_ptr);
|
||||
|
||||
let operand = OperandRef {
|
||||
|
|
Loading…
Reference in New Issue