diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 83029df0fe72f..041565c8b5a07 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::Unsafety; use hir::def_id::DefId; -use ty::{self, Ty, TypeFoldable, Substs, TyCtxt}; +use ty::{self, Ty, PolyFnSig, TypeFoldable, Substs, TyCtxt}; use traits; use rustc_target::spec::abi::Abi; use util::ppaux; use std::fmt; +use std::iter; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Instance<'tcx> { @@ -59,6 +61,65 @@ impl<'a, 'tcx> Instance<'tcx> { &ty, ) } + + fn fn_sig_noadjust(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> PolyFnSig<'tcx> { + let ty = self.ty(tcx); + match ty.sty { + ty::FnDef(..) | + // Shims currently have type FnPtr. Not sure this should remain. + ty::FnPtr(_) => ty.fn_sig(tcx), + ty::Closure(def_id, substs) => { + let sig = substs.closure_sig(def_id, tcx); + + let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); + sig.map_bound(|sig| tcx.mk_fn_sig( + iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.variadic, + sig.unsafety, + sig.abi + )) + } + ty::Generator(def_id, substs, _) => { + let sig = substs.poly_sig(def_id, tcx); + + let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); + let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); + + sig.map_bound(|sig| { + let state_did = tcx.lang_items().gen_state().unwrap(); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[ + sig.yield_ty.into(), + sig.return_ty.into(), + ]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + + tcx.mk_fn_sig(iter::once(env_ty), + ret_ty, + false, + Unsafety::Normal, + Abi::Rust + ) + }) + } + _ => bug!("unexpected type {:?} in Instance::fn_sig_noadjust", ty) + } + } + + pub fn fn_sig(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { + let mut fn_sig = self.fn_sig_noadjust(tcx); + if let InstanceDef::VtableShim(..) = self.def { + // Modify fn(self, ...) to fn(self: *mut Self, ...) + fn_sig = fn_sig.map_bound(|mut fn_sig| { + let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); + inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); + fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + fn_sig + }); + } + fn_sig + } } impl<'tcx> InstanceDef<'tcx> { diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 72daa0beb0982..7c7662a88de53 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -11,7 +11,7 @@ use llvm::{self, AttributePlace}; use base; use builder::{Builder, MemFlags}; -use common::{ty_fn_sig, C_usize}; +use common::C_usize; use context::CodegenCx; use mir::place::PlaceRef; use mir::operand::OperandValue; @@ -283,8 +283,7 @@ pub trait FnTypeExt<'tcx> { impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self { - let fn_ty = instance.ty(cx.tcx); - let sig = ty_fn_sig(cx, fn_ty); + let sig = instance.fn_sig(cx.tcx); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); FnType::new(cx, sig, &[]) } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 501a0b8af76bb..0932ceec9060f 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -56,7 +56,7 @@ use callee; use common::{C_bool, C_bytes_in_context, C_i32, C_usize}; use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode}; use rustc_mir::monomorphize::item::DefPathBasedNames; -use common::{self, C_struct_in_context, C_array, val_ty}; +use common::{C_struct_in_context, C_array, val_ty}; use consts; use context::CodegenCx; use debuginfo; @@ -491,8 +491,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<' // release builds. info!("codegen_instance({})", instance); - let fn_ty = instance.ty(cx.tcx); - let sig = common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim()); + let sig = instance.fn_sig(cx.tcx); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(|| diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index fff0177c94842..7300bac96182b 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -47,16 +47,16 @@ pub fn get_fn( assert!(!instance.substs.has_escaping_regions()); assert!(!instance.substs.has_param_types()); - let fn_ty = instance.ty(cx.tcx); + let sig = instance.fn_sig(cx.tcx); if let Some(&llfn) = cx.instances.borrow().get(&instance) { return llfn; } let sym = tcx.symbol_name(instance).as_str(); - debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym); + debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym); // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim())); + let fn_ptr_ty = tcx.mk_fn_ptr(sig); let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx); let llfn = if let Some(llfn) = declare::get_declared_value(cx, &sym) { @@ -91,7 +91,7 @@ pub fn get_fn( llfn } } else { - let llfn = declare::declare_fn(cx, &sym, common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim())); + let llfn = declare::declare_fn(cx, &sym, sig); assert_eq!(common::val_ty(llfn), llptrty); debug!("get_fn: not casting pointer!"); diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index df91f75837422..c9b464fd8f3dd 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -30,9 +30,7 @@ use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::hir; use libc::{c_uint, c_char}; -use std::iter; -use rustc_target::spec::abi::Abi; use syntax::symbol::LocalInternedString; use syntax_pos::{Span, DUMMY_SP}; @@ -404,71 +402,3 @@ pub fn shift_mask_val( _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind), } } - -pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - ty: Ty<'tcx>) - -> ty::PolyFnSig<'tcx> -{ - match ty.sty { - ty::FnDef(..) | - // Shims currently have type FnPtr. Not sure this should remain. - ty::FnPtr(_) => ty.fn_sig(cx.tcx), - ty::Closure(def_id, substs) => { - let tcx = cx.tcx; - let sig = substs.closure_sig(def_id, tcx); - - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.variadic, - sig.unsafety, - sig.abi - )) - } - ty::Generator(def_id, substs, _) => { - let tcx = cx.tcx; - let sig = substs.poly_sig(def_id, cx.tcx); - - let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); - let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); - - sig.map_bound(|sig| { - let state_did = tcx.lang_items().gen_state().unwrap(); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.intern_substs(&[ - sig.yield_ty.into(), - sig.return_ty.into(), - ]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - - tcx.mk_fn_sig(iter::once(env_ty), - ret_ty, - false, - hir::Unsafety::Normal, - Abi::Rust - ) - }) - } - _ => bug!("unexpected type {:?} to ty_fn_sig", ty) - } -} - -pub fn ty_fn_sig_vtable<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, - ty: Ty<'tcx>, - is_vtable_shim: bool - ) -> ty::PolyFnSig<'tcx> -{ - let mut fn_sig = ty_fn_sig(cx, ty); - if is_vtable_shim { - // Modify fn(self, ...) to fn(self: *mut Self, ...) - fn_sig = fn_sig.map_bound(|mut fn_sig| { - let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); - inputs_and_output[0] = cx.tcx.mk_mut_ptr(inputs_and_output[0]); - fn_sig.inputs_and_output = cx.tcx.intern_type_list(&inputs_and_output); - fn_sig - }); - } - fn_sig -} diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 9fab362f7e2ff..d98b7869ae98e 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -298,8 +298,7 @@ impl FunctionCx<'a, 'll, 'tcx> { }; let (drop_fn, fn_ty) = match ty.sty { ty::Dynamic(..) => { - let fn_ty = drop_fn.ty(bx.cx.tcx); - let sig = common::ty_fn_sig(bx.cx, fn_ty); + let sig = drop_fn.fn_sig(bx.cx.tcx); let sig = bx.tcx().normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), &sig, diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index d160f114d4ccd..91c1ccbe00213 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -17,7 +17,6 @@ use asm; use attributes; use base; -use common; use consts; use context::CodegenCx; use declare; @@ -154,8 +153,7 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, assert!(!instance.substs.needs_infer() && !instance.substs.has_param_types()); - let mono_ty = instance.ty(cx.tcx); - let mono_sig = common::ty_fn_sig_vtable(cx, mono_ty, instance.is_vtable_shim()); + let mono_sig = instance.fn_sig(cx.tcx); let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); let lldecl = declare::declare_fn(cx, symbol_name, mono_sig); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; @@ -180,7 +178,7 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } } - debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance); + debug!("predefine_fn: mono_sig = {:?} instance = {:?}", mono_sig, instance); if instance.def.is_inline(cx.tcx) { attributes::inline(cx, lldecl, attributes::InlineAttr::Hint); }