From c08d004545edf1bf16ee670fd27b8d3a477341a5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 16 Dec 2014 15:00:05 -0500 Subject: [PATCH] Refactor various queries out of `ty` and into `trans/common` --- src/librustc/middle/ty.rs | 44 ---------------------- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/cleanup.rs | 12 +++--- src/librustc_trans/trans/common.rs | 49 +++++++++++++++++++++++++ src/librustc_trans/trans/context.rs | 6 +++ src/librustc_trans/trans/controlflow.rs | 2 +- src/librustc_trans/trans/datum.rs | 4 +- src/librustc_trans/trans/expr.rs | 6 +-- src/librustc_trans/trans/glue.rs | 8 ++-- src/librustc_trans/trans/intrinsic.rs | 2 +- src/librustc_trans/trans/meth.rs | 2 +- src/librustc_trans/trans/tvec.rs | 2 +- 12 files changed, 75 insertions(+), 64 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 617be82701a0..d09efb006f26 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -682,7 +682,6 @@ pub struct ctxt<'tcx> { pub tcache: RefCell>>, pub rcache: RefCell>>, pub short_names_cache: RefCell, String>>, - pub needs_unwind_cleanup_cache: RefCell, bool>>, pub tc_cache: RefCell, TypeContents>>, pub ast_ty_to_ty_cache: RefCell>>, pub enum_var_cache: RefCell>>>>>, @@ -2108,7 +2107,6 @@ pub fn mk_ctxt<'tcx>(s: Session, tcache: RefCell::new(DefIdMap::new()), rcache: RefCell::new(FnvHashMap::new()), short_names_cache: RefCell::new(FnvHashMap::new()), - needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()), tc_cache: RefCell::new(FnvHashMap::new()), ast_ty_to_ty_cache: RefCell::new(NodeMap::new()), enum_var_cache: RefCell::new(DefIdMap::new()), @@ -2824,48 +2822,6 @@ pub fn type_is_floating_point(ty: Ty) -> bool { } } -pub fn type_needs_drop<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - type_contents(cx, ty).needs_drop(cx) -} - -// Some things don't need cleanups during unwinding because the -// task can free them all at once later. Currently only things -// that only contain scalars and shared boxes can avoid unwind -// cleanups. -pub fn type_needs_unwind_cleanup<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - return memoized(&cx.needs_unwind_cleanup_cache, ty, |ty| { - type_needs_unwind_cleanup_(cx, ty, &mut FnvHashSet::new()) - }); - - fn type_needs_unwind_cleanup_<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, - tycache: &mut FnvHashSet>) -> bool { - // Prevent infinite recursion - if !tycache.insert(ty) { - return false; - } - - let mut needs_unwind_cleanup = false; - maybe_walk_ty(ty, |ty| { - needs_unwind_cleanup |= match ty.sty { - ty_bool | ty_int(_) | ty_uint(_) | - ty_float(_) | ty_tup(_) | ty_ptr(_) => false, - - ty_enum(did, substs) => - enum_variants(cx, did).iter().any(|v| - v.args.iter().any(|aty| { - let t = aty.subst(cx, substs); - type_needs_unwind_cleanup_(cx, t, tycache) - }) - ), - - _ => true - }; - !needs_unwind_cleanup - }); - needs_unwind_cleanup - } -} - /// Type contents is how the type checker reasons about kinds. /// They track what kinds of things are found within a type. You can /// think of them as kind of an "anti-kind". They track the kinds of values diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index a159cda9fbae..dab4c0273d07 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -722,7 +722,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }; if !is_rust_fn || type_of::return_uses_outptr(ccx, ret_ty) || - ty::type_needs_drop(bcx.tcx(), ret_ty) { + type_needs_drop(bcx.tcx(), ret_ty) { // Push the out-pointer if we use an out-pointer for this // return type, otherwise push "undef". if type_is_zero_size(ccx, ret_ty) { diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index f96aa484ffc9..d02d6c1e8724 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -279,10 +279,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: false, - must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty), + must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), val: val, ty: ty, zero: false @@ -301,10 +301,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: false, - must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty), + must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), val: val, ty: ty, zero: true @@ -325,10 +325,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { val: ValueRef, ty: Ty<'tcx>) { - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: true, - must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty), + must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), val: val, ty: ty, zero: false diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index b15b75c6715b..7ee4be0ae56f 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -53,9 +53,58 @@ use syntax::ast_map::{PathElem, PathName}; use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::parse::token; +use util::common::memoized; +use util::nodemap::FnvHashSet; pub use trans::context::CrateContext; +// Some things don't need cleanups during unwinding because the +// task can free them all at once later. Currently only things +// that only contain scalars and shared boxes can avoid unwind +// cleanups. +pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { + return memoized(ccx.needs_unwind_cleanup_cache(), ty, |ty| { + type_needs_unwind_cleanup_(ccx.tcx(), ty, &mut FnvHashSet::new()) + }); + + fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>, + tycache: &mut FnvHashSet>) + -> bool + { + // Prevent infinite recursion + if !tycache.insert(ty) { + return false; + } + + let mut needs_unwind_cleanup = false; + ty::maybe_walk_ty(ty, |ty| { + needs_unwind_cleanup |= match ty.sty { + ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) | + ty::ty_float(_) | ty::ty_tup(_) | ty::ty_ptr(_) => false, + + ty::ty_enum(did, substs) => + ty::enum_variants(tcx, did).iter().any(|v| + v.args.iter().any(|aty| { + let t = aty.subst(tcx, substs); + type_needs_unwind_cleanup_(tcx, t, tycache) + }) + ), + + _ => true + }; + !needs_unwind_cleanup + }); + needs_unwind_cleanup + } +} + +pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>) + -> bool { + ty::type_contents(cx, ty).needs_drop(cx) +} + fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.sty { diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 2c71dd831fbc..02eaef885483 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -84,6 +84,7 @@ pub struct LocalCrateContext<'tcx> { tn: TypeNames, externs: RefCell, item_vals: RefCell>, + needs_unwind_cleanup_cache: RefCell, bool>>, fn_pointer_shims: RefCell, ValueRef>>, drop_glues: RefCell, ValueRef>>, tydescs: RefCell, Rc>>>, @@ -389,6 +390,7 @@ impl<'tcx> LocalCrateContext<'tcx> { tn: TypeNames::new(), externs: RefCell::new(FnvHashMap::new()), item_vals: RefCell::new(NodeMap::new()), + needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()), fn_pointer_shims: RefCell::new(FnvHashMap::new()), drop_glues: RefCell::new(FnvHashMap::new()), tydescs: RefCell::new(FnvHashMap::new()), @@ -569,6 +571,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.shared.link_meta } + pub fn needs_unwind_cleanup_cache(&self) -> &RefCell, bool>> { + &self.local.needs_unwind_cleanup_cache + } + pub fn fn_pointer_shims(&self) -> &RefCell, ValueRef>> { &self.local.fn_pointer_shims } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 3b24ded6717c..768de89d5935 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -87,7 +87,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_stmt_semi"); let ty = expr_ty(cx, e); - if ty::type_needs_drop(cx.tcx(), ty) { + if type_needs_drop(cx.tcx(), ty) { expr::trans_to_lvalue(cx, e, "stmt").bcx } else { expr::trans_into(cx, e, expr::Ignore) diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 9ab4e92b5113..ca274ab605e7 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -218,7 +218,7 @@ impl KindOps for Lvalue { val: ValueRef, ty: Ty<'tcx>) -> Block<'blk, 'tcx> { - if ty::type_needs_drop(bcx.tcx(), ty) { + if type_needs_drop(bcx.tcx(), ty) { // cancel cleanup of affine values by zeroing out let () = zero_mem(bcx, val, ty); bcx @@ -567,7 +567,7 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is /// naturally passed around by value, and not by reference. pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { - assert!(!ty::type_needs_drop(bcx.tcx(), self.ty)); + assert!(!type_needs_drop(bcx.tcx(), self.ty)); assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue); if self.kind.is_by_ref() { load_ty(bcx, self.val, self.ty) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index f49769ba0d9c..ae07e094a5c6 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -976,7 +976,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let src_datum = unpack_datum!(bcx, trans(bcx, &**src)); let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign")); - if ty::type_needs_drop(bcx.tcx(), dst_datum.ty) { + if type_needs_drop(bcx.tcx(), dst_datum.ty) { // If there are destructors involved, make sure we // are copying from an rvalue, since that cannot possible // alias an lvalue. We are concerned about code like: @@ -1513,7 +1513,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, assert_eq!(discr, 0); match ty::expr_kind(bcx.tcx(), &*base.expr) { - ty::RvalueDpsExpr | ty::RvalueDatumExpr if !ty::type_needs_drop(bcx.tcx(), ty) => { + ty::RvalueDpsExpr | ty::RvalueDatumExpr if !type_needs_drop(bcx.tcx(), ty) => { bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); }, ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"), @@ -2117,7 +2117,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Evaluate LHS (destination), which should be an lvalue let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op")); - assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty)); + assert!(!type_needs_drop(bcx.tcx(), dst_datum.ty)); let dst_ty = dst_datum.ty; let dst = load_ty(bcx, dst_datum.val, dst_datum.ty); diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index e0a878c8261e..4217dd4c6718 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -84,11 +84,11 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if !ty::type_is_sized(tcx, t) { return t } - if !ty::type_needs_drop(tcx, t) { + if !type_needs_drop(tcx, t) { return ty::mk_i8(); } match t.sty { - ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) + ty::ty_uniq(typ) if !type_needs_drop(tcx, typ) && ty::type_is_sized(tcx, typ) => { let llty = sizing_type_of(ccx, typ); // `Box` does not allocate. @@ -110,7 +110,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // NB: v is an *alias* of type t here, not a direct value. debug!("drop_ty(t={})", t.repr(bcx.tcx())); let _icx = push_ctxt("drop_ty"); - if ty::type_needs_drop(bcx.tcx(), t) { + if type_needs_drop(bcx.tcx(), t) { let ccx = bcx.ccx(); let glue = get_drop_glue(ccx, t); let glue_type = get_drop_glue_type(ccx, t); @@ -469,7 +469,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false), _ => { assert!(ty::type_is_sized(bcx.tcx(), t)); - if ty::type_needs_drop(bcx.tcx(), t) && + if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None)) } else { diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index fff89999d99b..f471a92f6c32 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -365,7 +365,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } (_, "needs_drop") => { let tp_ty = *substs.types.get(FnSpace, 0); - C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty)) + C_bool(ccx, type_needs_drop(ccx.tcx(), tp_ty)) } (_, "owns_managed") => { let tp_ty = *substs.types.get(FnSpace, 0); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 553613a8eac0..a937f989b3ac 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -436,7 +436,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let self_datum = unpack_datum!( bcx, expr::trans(bcx, self_expr)); - let llval = if ty::type_needs_drop(bcx.tcx(), self_datum.ty) { + let llval = if type_needs_drop(bcx.tcx(), self_datum.ty) { let self_datum = unpack_datum!( bcx, self_datum.to_rvalue_datum(bcx, "trait_callee")); diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index e09032ac2d04..688a0d072505 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -62,7 +62,7 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("tvec::make_drop_glue_unboxed"); let dataptr = get_dataptr(bcx, vptr); - let bcx = if ty::type_needs_drop(tcx, unit_ty) { + let bcx = if type_needs_drop(tcx, unit_ty) { let len = get_len(bcx, vptr); iter_vec_raw(bcx, dataptr, unit_ty, len, |bb, vv, tt| glue::drop_ty(bb, vv, tt, None)) } else {