Extend trans::datum::Lvalue
so that it carrys an optional dropflag hint.
Instrumented calls sites that construct Lvalues to ease tracking down cases that we might need to change whether or not they carry a hint. Note that this commit does not do anything to actually *construct* the `lldropflag_hints` map, nor does it change anything about codegen itself. Those parts are in follow-on commits.
This commit is contained in:
parent
20aa27b7bc
commit
a0f3f2ac53
@ -437,7 +437,7 @@ impl MatchInput {
|
||||
fn from_val(val: ValueRef) -> MatchInput {
|
||||
MatchInput {
|
||||
val: val,
|
||||
lval: Lvalue,
|
||||
lval: Lvalue::new("MatchInput::from_val"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -941,30 +941,41 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
cs: Option<cleanup::ScopeId>)
|
||||
-> Block<'blk, 'tcx> {
|
||||
for (&ident, &binding_info) in bindings_map {
|
||||
let llval = match binding_info.trmode {
|
||||
let (llval, aliases_other_state) = match binding_info.trmode {
|
||||
// By value mut binding for a copy type: load from the ptr
|
||||
// into the matched value and copy to our alloca
|
||||
TrByCopy(llbinding) |
|
||||
TrByMoveIntoCopy(llbinding) => {
|
||||
let llval = Load(bcx, binding_info.llmatch);
|
||||
let datum = Datum::new(llval, binding_info.ty, Lvalue);
|
||||
let lval = match binding_info.trmode {
|
||||
TrByCopy(..) =>
|
||||
Lvalue::new("_match::insert_lllocals"),
|
||||
TrByMoveIntoCopy(..) =>
|
||||
Lvalue::match_input("_match::insert_lllocals", bcx, binding_info.id),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let datum = Datum::new(llval, binding_info.ty, lval);
|
||||
call_lifetime_start(bcx, llbinding);
|
||||
bcx = datum.store_to(bcx, llbinding);
|
||||
if let Some(cs) = cs {
|
||||
bcx.fcx.schedule_lifetime_end(cs, llbinding);
|
||||
}
|
||||
|
||||
llbinding
|
||||
(llbinding, false)
|
||||
},
|
||||
|
||||
// By value move bindings: load from the ptr into the matched value
|
||||
TrByMoveRef => Load(bcx, binding_info.llmatch),
|
||||
TrByMoveRef => (Load(bcx, binding_info.llmatch), true),
|
||||
|
||||
// By ref binding: use the ptr into the matched value
|
||||
TrByRef => binding_info.llmatch
|
||||
TrByRef => (binding_info.llmatch, true),
|
||||
};
|
||||
|
||||
let datum = Datum::new(llval, binding_info.ty, Lvalue);
|
||||
let lval = Lvalue::local("_match::insert_lllocals",
|
||||
bcx,
|
||||
binding_info.id,
|
||||
aliases_other_state);
|
||||
let datum = Datum::new(llval, binding_info.ty, lval);
|
||||
if let Some(cs) = cs {
|
||||
bcx.fcx.schedule_lifetime_end(cs, binding_info.llmatch);
|
||||
bcx.fcx.schedule_drop_and_fill_mem(cs, llval, binding_info.ty);
|
||||
@ -1619,6 +1630,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let scope = cleanup::var_scope(tcx, p_id);
|
||||
bcx = mk_binding_alloca(
|
||||
bcx, p_id, path1.node.name, scope, (),
|
||||
"_match::store_local::create_dummy_locals",
|
||||
|(), bcx, llval, ty| { drop_done_fill_mem(bcx, llval, ty); bcx });
|
||||
});
|
||||
bcx
|
||||
@ -1641,6 +1653,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let var_scope = cleanup::var_scope(tcx, local.id);
|
||||
return mk_binding_alloca(
|
||||
bcx, pat.id, ident.name, var_scope, (),
|
||||
"_match::store_local",
|
||||
|(), bcx, v, _| expr::trans_into(bcx, &**init_expr,
|
||||
expr::SaveIn(v)));
|
||||
}
|
||||
@ -1668,6 +1681,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
|
||||
name: ast::Name,
|
||||
cleanup_scope: cleanup::ScopeId,
|
||||
arg: A,
|
||||
caller_name: &'static str,
|
||||
populate: F)
|
||||
-> Block<'blk, 'tcx> where
|
||||
F: FnOnce(A, Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
|
||||
@ -1685,7 +1699,8 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
|
||||
|
||||
// Now that memory is initialized and has cleanup scheduled,
|
||||
// create the datum and insert into the local variable map.
|
||||
let datum = Datum::new(llval, var_ty, Lvalue);
|
||||
let lval = Lvalue::binding(caller_name, bcx, p_id, name);
|
||||
let datum = Datum::new(llval, var_ty, lval);
|
||||
bcx.fcx.lllocals.borrow_mut().insert(p_id, datum);
|
||||
bcx
|
||||
}
|
||||
@ -1730,6 +1745,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
// map.
|
||||
bcx = mk_binding_alloca(
|
||||
bcx, pat.id, path1.node.name, cleanup_scope, (),
|
||||
"_match::bind_irrefutable_pat",
|
||||
|(), bcx, llval, ty| {
|
||||
match pat_binding_mode {
|
||||
ast::BindByValue(_) => {
|
||||
|
@ -1083,7 +1083,7 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
));
|
||||
bcx = fold_variants(bcx, r, val, |variant_cx, st, value| {
|
||||
let ptr = struct_field_ptr(variant_cx, st, value, (st.fields.len() - 1), false);
|
||||
datum::Datum::new(ptr, ptr_ty, datum::Lvalue)
|
||||
datum::Datum::new(ptr, ptr_ty, datum::Lvalue::new("adt::trans_drop_flag_ptr"))
|
||||
.store_to(variant_cx, scratch.val)
|
||||
});
|
||||
let expr_datum = scratch.to_expr_datum();
|
||||
|
@ -56,7 +56,7 @@ use trans::cleanup;
|
||||
use trans::closure;
|
||||
use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_integral};
|
||||
use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
|
||||
use trans::common::{CrateContext, FunctionContext};
|
||||
use trans::common::{CrateContext, DropFlagHintsMap, FunctionContext};
|
||||
use trans::common::{Result, NodeIdAndSpan};
|
||||
use trans::common::{node_id_type, return_type_is_void};
|
||||
use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
|
||||
@ -1235,6 +1235,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
|
||||
caller_expects_out_pointer: uses_outptr,
|
||||
lllocals: RefCell::new(NodeMap()),
|
||||
llupvars: RefCell::new(NodeMap()),
|
||||
lldropflag_hints: RefCell::new(DropFlagHintsMap::new()),
|
||||
id: id,
|
||||
param_substs: param_substs,
|
||||
span: sp,
|
||||
|
@ -124,6 +124,7 @@ use trans::base;
|
||||
use trans::build;
|
||||
use trans::common;
|
||||
use trans::common::{Block, FunctionContext, NodeIdAndSpan};
|
||||
use trans::datum::{Datum, Lvalue};
|
||||
use trans::debuginfo::{DebugLoc, ToDebugLoc};
|
||||
use trans::glue;
|
||||
use middle::region;
|
||||
@ -212,6 +213,12 @@ pub enum ScopeId {
|
||||
CustomScope(CustomScopeIndex)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct DropHint<K>(pub ast::NodeId, pub K);
|
||||
|
||||
pub type DropHintDatum<'tcx> = DropHint<Datum<'tcx, Lvalue>>;
|
||||
pub type DropHintValue = DropHint<ValueRef>;
|
||||
|
||||
impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
|
||||
/// Invoked when we start to trans the code contained within a new cleanup scope.
|
||||
fn push_ast_cleanup_scope(&self, debug_loc: NodeIdAndSpan) {
|
||||
|
@ -299,6 +299,27 @@ pub fn validate_substs(substs: &Substs) {
|
||||
type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
|
||||
pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct HintEntry<'tcx> {
|
||||
// The datum for the dropflag-hint itself; note that many
|
||||
// source-level Lvalues will be associated with the same
|
||||
// dropflag-hint datum.
|
||||
datum: cleanup::DropHintDatum<'tcx>,
|
||||
}
|
||||
|
||||
pub struct DropFlagHintsMap<'tcx> {
|
||||
// Maps NodeId for expressions that read/write unfragmented state
|
||||
// to that state's drop-flag "hint." (A stack-local hint
|
||||
// indicates either that (1.) it is certain that no-drop is
|
||||
// needed, or (2.) inline drop-flag must be consulted.)
|
||||
node_map: NodeMap<HintEntry<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> DropFlagHintsMap<'tcx> {
|
||||
pub fn new() -> DropFlagHintsMap<'tcx> { DropFlagHintsMap { node_map: NodeMap() } }
|
||||
pub fn has_hint(&self, id: ast::NodeId) -> bool { self.node_map.contains_key(&id) }
|
||||
}
|
||||
|
||||
// Function context. Every LLVM function we create will have one of
|
||||
// these.
|
||||
pub struct FunctionContext<'a, 'tcx: 'a> {
|
||||
@ -349,6 +370,10 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
|
||||
// Same as above, but for closure upvars
|
||||
pub llupvars: RefCell<NodeMap<ValueRef>>,
|
||||
|
||||
// Carries info about drop-flags for local bindings (longer term,
|
||||
// paths) for the code being compiled.
|
||||
pub lldropflag_hints: RefCell<DropFlagHintsMap<'tcx>>,
|
||||
|
||||
// The NodeId of the function, or -1 if it doesn't correspond to
|
||||
// a user-defined function.
|
||||
pub id: ast::NodeId,
|
||||
|
@ -138,17 +138,141 @@ pub enum Expr {
|
||||
/// `val` is a pointer into memory for which a cleanup is scheduled
|
||||
/// (and thus has type *T). If you move out of an Lvalue, you must
|
||||
/// zero out the memory (FIXME #5016).
|
||||
LvalueExpr,
|
||||
LvalueExpr(Lvalue),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Lvalue;
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum DropFlagInfo {
|
||||
DontZeroJustUse(ast::NodeId),
|
||||
ZeroAndMaintain(ast::NodeId),
|
||||
None,
|
||||
}
|
||||
|
||||
impl DropFlagInfo {
|
||||
pub fn must_zero(&self) -> bool {
|
||||
match *self {
|
||||
DropFlagInfo::DontZeroJustUse(..) => false,
|
||||
DropFlagInfo::ZeroAndMaintain(..) => true,
|
||||
DropFlagInfo::None => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hint_to_maintain(&self) -> Option<ast::NodeId> {
|
||||
match *self {
|
||||
DropFlagInfo::DontZeroJustUse(id) => Some(id),
|
||||
DropFlagInfo::ZeroAndMaintain(id) => Some(id),
|
||||
DropFlagInfo::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: having Lvalue be `Copy` is a bit of a footgun, since clients
|
||||
// may not realize that subparts of an Lvalue can have a subset of
|
||||
// drop-flags associated with them, while this as written will just
|
||||
// memcpy the drop_flag_info. But, it is an easier way to get `_match`
|
||||
// off the ground to just let this be `Copy` for now.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Lvalue {
|
||||
pub source: &'static str,
|
||||
pub drop_flag_info: DropFlagInfo
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Rvalue {
|
||||
pub mode: RvalueMode
|
||||
}
|
||||
|
||||
impl Lvalue {
|
||||
pub fn new(source: &'static str) -> Lvalue {
|
||||
Lvalue { source: source, drop_flag_info: DropFlagInfo::None }
|
||||
}
|
||||
|
||||
pub fn upvar<'blk, 'tcx>(source: &'static str,
|
||||
bcx: Block<'blk, 'tcx>,
|
||||
id: ast::NodeId) -> Lvalue {
|
||||
let info = if Lvalue::has_dropflag_hint(bcx, id) {
|
||||
DropFlagInfo::ZeroAndMaintain(id)
|
||||
} else {
|
||||
DropFlagInfo::None
|
||||
};
|
||||
let info = if bcx.tcx().sess.nonzeroing_move_hints() { info } else { DropFlagInfo::None };
|
||||
debug!("upvar Lvalue at {}, id: {} info: {:?}", source, id, info);
|
||||
Lvalue { source: source, drop_flag_info: info }
|
||||
}
|
||||
|
||||
pub fn match_input<'blk, 'tcx>(source: &'static str,
|
||||
bcx: Block<'blk, 'tcx>,
|
||||
id: ast::NodeId) -> Lvalue
|
||||
{
|
||||
let info = if Lvalue::has_dropflag_hint(bcx, id) {
|
||||
// match_input is used to move from the input into a
|
||||
// separate stack slot; it must zero (at least until we
|
||||
// improve things to track drop flags for the fragmented
|
||||
// parent match input expression).
|
||||
DropFlagInfo::ZeroAndMaintain(id)
|
||||
} else {
|
||||
DropFlagInfo::None
|
||||
};
|
||||
let info = if bcx.tcx().sess.nonzeroing_move_hints() { info } else { DropFlagInfo::None };
|
||||
debug!("match_input Lvalue at {}, id: {} info: {:?}", source, id, info);
|
||||
Lvalue { source: source, drop_flag_info: info }
|
||||
}
|
||||
|
||||
pub fn local<'blk, 'tcx>(source: &'static str,
|
||||
bcx: Block<'blk, 'tcx>,
|
||||
id: ast::NodeId,
|
||||
aliases_other_state: bool)
|
||||
-> Lvalue
|
||||
{
|
||||
let info = if Lvalue::has_dropflag_hint(bcx, id) {
|
||||
if aliases_other_state {
|
||||
DropFlagInfo::ZeroAndMaintain(id)
|
||||
} else {
|
||||
DropFlagInfo::DontZeroJustUse(id)
|
||||
}
|
||||
} else {
|
||||
DropFlagInfo::None
|
||||
};
|
||||
let info = if bcx.tcx().sess.nonzeroing_move_hints() { info } else { DropFlagInfo::None };
|
||||
debug!("local Lvalue at {}, id: {} info: {:?}", source, id, info);
|
||||
Lvalue { source: source, drop_flag_info: info }
|
||||
}
|
||||
|
||||
pub fn store_arg<'blk, 'tcx>(source: &'static str,
|
||||
bcx: Block<'blk, 'tcx>,
|
||||
id: ast::NodeId) -> Lvalue
|
||||
{
|
||||
let info = if Lvalue::has_dropflag_hint(bcx, id) {
|
||||
DropFlagInfo::ZeroAndMaintain(id)
|
||||
} else {
|
||||
DropFlagInfo::None
|
||||
};
|
||||
let info = if bcx.tcx().sess.nonzeroing_move_hints() { info } else { DropFlagInfo::None };
|
||||
debug!("store_arg Lvalue at {}, id: {} info: {:?}", source, id, info);
|
||||
Lvalue { source: source, drop_flag_info: info }
|
||||
}
|
||||
|
||||
pub fn binding<'blk, 'tcx>(source: &'static str,
|
||||
bcx: Block<'blk, 'tcx>,
|
||||
id: ast::NodeId,
|
||||
name: ast::Name) -> Lvalue {
|
||||
let info = if Lvalue::has_dropflag_hint(bcx, id) {
|
||||
DropFlagInfo::DontZeroJustUse(id)
|
||||
} else {
|
||||
DropFlagInfo::None
|
||||
};
|
||||
let info = if bcx.tcx().sess.nonzeroing_move_hints() { info } else { DropFlagInfo::None };
|
||||
debug!("binding Lvalue at {}, id: {} name: {} info: {:?}",
|
||||
source, id, name, info);
|
||||
Lvalue { source: source, drop_flag_info: info }
|
||||
}
|
||||
|
||||
fn has_dropflag_hint<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
id: ast::NodeId) -> bool {
|
||||
bcx.fcx.lldropflag_hints.borrow().has_hint(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl Rvalue {
|
||||
pub fn new(m: RvalueMode) -> Rvalue {
|
||||
Rvalue { mode: m }
|
||||
@ -201,7 +325,7 @@ pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
|
||||
bcx.fcx.schedule_lifetime_end(scope, scratch);
|
||||
bcx.fcx.schedule_drop_mem(scope, scratch, ty);
|
||||
|
||||
DatumBlock::new(bcx, Datum::new(scratch, ty, Lvalue))
|
||||
DatumBlock::new(bcx, Datum::new(scratch, ty, Lvalue::new("datum::lvalue_scratch_datum")))
|
||||
}
|
||||
|
||||
/// Allocates temporary space on the stack using alloca() and returns a by-ref Datum pointing to
|
||||
@ -308,7 +432,7 @@ impl KindOps for Lvalue {
|
||||
}
|
||||
|
||||
fn to_expr_kind(self) -> Expr {
|
||||
LvalueExpr
|
||||
LvalueExpr(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,14 +443,14 @@ impl KindOps for Expr {
|
||||
ty: Ty<'tcx>)
|
||||
-> Block<'blk, 'tcx> {
|
||||
match *self {
|
||||
LvalueExpr => Lvalue.post_store(bcx, val, ty),
|
||||
LvalueExpr(ref l) => l.post_store(bcx, val, ty),
|
||||
RvalueExpr(ref r) => r.post_store(bcx, val, ty),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_by_ref(&self) -> bool {
|
||||
match *self {
|
||||
LvalueExpr => Lvalue.is_by_ref(),
|
||||
LvalueExpr(ref l) => l.is_by_ref(),
|
||||
RvalueExpr(ref r) => r.is_by_ref()
|
||||
}
|
||||
}
|
||||
@ -360,7 +484,10 @@ impl<'tcx> Datum<'tcx, Rvalue> {
|
||||
match self.kind.mode {
|
||||
ByRef => {
|
||||
add_rvalue_clean(ByRef, fcx, scope, self.val, self.ty);
|
||||
DatumBlock::new(bcx, Datum::new(self.val, self.ty, Lvalue))
|
||||
DatumBlock::new(bcx, Datum::new(
|
||||
self.val,
|
||||
self.ty,
|
||||
Lvalue::new("datum::to_lvalue_datum_in_scope")))
|
||||
}
|
||||
|
||||
ByValue => {
|
||||
@ -417,7 +544,7 @@ impl<'tcx> Datum<'tcx, Expr> {
|
||||
{
|
||||
let Datum { val, ty, kind } = self;
|
||||
match kind {
|
||||
LvalueExpr => if_lvalue(Datum::new(val, ty, Lvalue)),
|
||||
LvalueExpr(l) => if_lvalue(Datum::new(val, ty, l)),
|
||||
RvalueExpr(r) => if_rvalue(Datum::new(val, ty, r)),
|
||||
}
|
||||
}
|
||||
@ -528,7 +655,7 @@ impl<'tcx> Datum<'tcx, Lvalue> {
|
||||
};
|
||||
Datum {
|
||||
val: val,
|
||||
kind: Lvalue,
|
||||
kind: Lvalue::new("Datum::get_element"),
|
||||
ty: ty,
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let const_ty = expr_ty_adjusted(bcx, expr);
|
||||
let llty = type_of::type_of(bcx.ccx(), const_ty);
|
||||
let global = PointerCast(bcx, global, llty.ptr_to());
|
||||
let datum = Datum::new(global, const_ty, Lvalue);
|
||||
let datum = Datum::new(global, const_ty, Lvalue::new("expr::trans"));
|
||||
return DatumBlock::new(bcx, datum.to_expr_datum());
|
||||
}
|
||||
|
||||
@ -733,7 +733,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
|
||||
// Always generate an lvalue datum, because this pointer doesn't own
|
||||
// the data and cleanup is scheduled elsewhere.
|
||||
DatumBlock::new(bcx, Datum::new(scratch.val, scratch.ty, LvalueExpr))
|
||||
DatumBlock::new(bcx, Datum::new(scratch.val, scratch.ty, LvalueExpr(d.kind)))
|
||||
}
|
||||
})
|
||||
|
||||
@ -810,10 +810,11 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
Some(SaveIn(scratch.val)),
|
||||
false));
|
||||
let datum = scratch.to_expr_datum();
|
||||
let lval = Lvalue::new("expr::trans_index overload");
|
||||
if type_is_sized(bcx.tcx(), elt_ty) {
|
||||
Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
|
||||
Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr(lval))
|
||||
} else {
|
||||
Datum::new(datum.val, elt_ty, LvalueExpr)
|
||||
Datum::new(datum.val, elt_ty, LvalueExpr(lval))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
@ -867,7 +868,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
});
|
||||
let elt = InBoundsGEP(bcx, base, &[ix_val]);
|
||||
let elt = PointerCast(bcx, elt, type_of::type_of(ccx, unit_ty).ptr_to());
|
||||
Datum::new(elt, unit_ty, LvalueExpr)
|
||||
let lval = Lvalue::new("expr::trans_index fallback");
|
||||
Datum::new(elt, unit_ty, LvalueExpr(lval))
|
||||
}
|
||||
};
|
||||
|
||||
@ -912,7 +914,8 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
// Case 2.
|
||||
base::get_extern_const(bcx.ccx(), did, const_ty)
|
||||
};
|
||||
DatumBlock::new(bcx, Datum::new(val, const_ty, LvalueExpr))
|
||||
let lval = Lvalue::new("expr::trans_def");
|
||||
DatumBlock::new(bcx, Datum::new(val, const_ty, LvalueExpr(lval)))
|
||||
}
|
||||
def::DefConst(_) => {
|
||||
bcx.sess().span_bug(ref_expr.span,
|
||||
@ -1302,8 +1305,9 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
def::DefUpvar(nid, _) => {
|
||||
// Can't move upvars, so this is never a ZeroMemLastUse.
|
||||
let local_ty = node_id_type(bcx, nid);
|
||||
let lval = Lvalue::upvar("expr::trans_local_var", bcx, nid);
|
||||
match bcx.fcx.llupvars.borrow().get(&nid) {
|
||||
Some(&val) => Datum::new(val, local_ty, Lvalue),
|
||||
Some(&val) => Datum::new(val, local_ty, lval),
|
||||
None => {
|
||||
bcx.sess().bug(&format!(
|
||||
"trans_local_var: no llval for upvar {} found",
|
||||
@ -2267,7 +2271,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
|
||||
if type_is_sized(bcx.tcx(), content_ty) {
|
||||
let ptr = load_ty(bcx, datum.val, datum.ty);
|
||||
DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
|
||||
DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr(datum.kind)))
|
||||
} else {
|
||||
// A fat pointer and a DST lvalue have the same representation
|
||||
// just different types. Since there is no temporary for `*e`
|
||||
@ -2275,13 +2279,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
// object code path for running drop glue and free. Instead,
|
||||
// we schedule cleanup for `e`, turning it into an lvalue.
|
||||
|
||||
let datum = Datum::new(datum.val, content_ty, LvalueExpr);
|
||||
let lval = Lvalue::new("expr::deref_once ty_uniq");
|
||||
let datum = Datum::new(datum.val, content_ty, LvalueExpr(lval));
|
||||
DatumBlock::new(bcx, datum)
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: content_ty, .. }) |
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: content_ty, .. }) => {
|
||||
let lval = Lvalue::new("expr::deref_once ptr");
|
||||
if type_is_sized(bcx.tcx(), content_ty) {
|
||||
let ptr = datum.to_llscalarish(bcx);
|
||||
|
||||
@ -2290,11 +2296,11 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
// rvalue for non-owning pointers like &T or *T, in which
|
||||
// case cleanup *is* scheduled elsewhere, by the true
|
||||
// owner (or, in the case of *T, by the user).
|
||||
DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
|
||||
DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr(lval)))
|
||||
} else {
|
||||
// A fat pointer and a DST lvalue have the same representation
|
||||
// just different types.
|
||||
DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr))
|
||||
DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr(lval)))
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user