Remove TrByImplicitRef and source field on datums

This commit is contained in:
Niko Matsakis 2013-05-29 15:49:23 -04:00
parent 682afcac52
commit dcd84901c6
7 changed files with 86 additions and 115 deletions

View File

@ -314,7 +314,6 @@ pub fn variant_opt(bcx: block, pat_id: ast::node_id)
pub enum TransBindingMode {
TrByValue(/*ismove:*/ bool, /*llbinding:*/ ValueRef),
TrByRef,
TrByImplicitRef
}
/**
@ -881,7 +880,7 @@ fn match_datum(bcx: block, val: ValueRef, pat_id: ast::node_id) -> Datum {
//! we should just pass around a Datum and be done with it.
let ty = node_id_type(bcx, pat_id);
Datum {val: val, ty: ty, mode: datum::ByRef, source: RevokeClean}
Datum {val: val, ty: ty, mode: datum::ByRef(RevokeClean)}
}
@ -988,7 +987,7 @@ pub fn root_pats_as_necessary(mut bcx: block,
let pat_id = br.pats[col].id;
if pat_id != 0 {
let datum = Datum {val: val, ty: node_id_type(bcx, pat_id),
mode: ByRef, source: ZeroMem};
mode: ByRef(ZeroMem)};
bcx = datum.root_and_write_guard(bcx, br.pats[col].span, pat_id, 0);
}
}
@ -1146,7 +1145,7 @@ pub fn store_non_ref_bindings(bcx: block,
TrByValue(is_move, lldest) => {
let llval = Load(bcx, binding_info.llmatch); // get a T*
let datum = Datum {val: llval, ty: binding_info.ty,
mode: ByRef, source: ZeroMem};
mode: ByRef(ZeroMem)};
bcx = {
if is_move {
datum.move_to(bcx, INIT, lldest)
@ -1161,7 +1160,7 @@ pub fn store_non_ref_bindings(bcx: block,
temp_cleanups
}
}
TrByRef | TrByImplicitRef => {}
TrByRef => {}
}
}
return bcx;
@ -1192,13 +1191,6 @@ pub fn insert_lllocals(bcx: block,
TrByRef => {
binding_info.llmatch
}
// Ugly: for implicit ref, we actually want a T*, but
// we have a T**, so we had to load. This will go away
// once implicit refs go away.
TrByImplicitRef => {
Load(bcx, binding_info.llmatch)
}
};
bcx.fcx.lllocals.insert(binding_info.id,
@ -1254,7 +1246,7 @@ pub fn compile_guard(bcx: block,
TrByValue(_, llval) => {
bcx = glue::drop_ty(bcx, llval, binding_info.ty);
}
TrByRef | TrByImplicitRef => {}
TrByRef => {}
}
bcx.fcx.lllocals.remove(&binding_info.id);
}
@ -1757,7 +1749,7 @@ pub fn bind_irrefutable_pat(bcx: block,
if make_copy {
let binding_ty = node_id_type(bcx, pat.id);
let datum = Datum {val: val, ty: binding_ty,
mode: ByRef, source: RevokeClean};
mode: ByRef(RevokeClean)};
let scratch = scratch_datum(bcx, binding_ty, false);
datum.copy_to_datum(bcx, INIT, scratch);
match binding_mode {

View File

@ -711,8 +711,7 @@ pub fn trans_arg_expr(bcx: block,
DatumBlock {bcx: bcx,
datum: Datum {val: scratch,
ty: scratch_ty,
mode: ByRef,
source: RevokeClean}}
mode: ByRef(RevokeClean)}}
}
_ => {
bcx.sess().impossible_case(
@ -775,7 +774,7 @@ pub fn trans_arg_expr(bcx: block,
match arg_datum.appropriate_mode() {
ByValue => val = Load(bcx, scratch.val),
ByRef => val = scratch.val,
ByRef(_) => val = scratch.val,
}
}
}

View File

@ -287,7 +287,7 @@ pub fn build_closure(bcx0: block,
for include_ret_handle.each |flagptr| {
// Flag indicating we have returned (a by-ref bool):
let flag_datum = Datum {val: *flagptr, ty: ty::mk_bool(),
mode: ByRef, source: ZeroMem};
mode: ByRef(ZeroMem)};
env_vals.push(EnvValue {action: EnvRef,
datum: flag_datum});
@ -299,7 +299,7 @@ pub fn build_closure(bcx0: block,
};
let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil()));
let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(),
mode: ByRef, source: ZeroMem};
mode: ByRef(ZeroMem)};
env_vals.push(EnvValue {action: EnvRef,
datum: ret_datum});
}

View File

@ -44,15 +44,17 @@
* # Datum cleanup styles
*
* Each datum carries with it an idea of how its value will be cleaned
* up. This is important after a move, because we need to know how to
* cancel the cleanup (since the value has been moved and therefore does
* not need to be freed). There are two options:
*
* 1. `RevokeClean`: To cancel the cleanup, we invoke `revoke_clean()`.
* This is used for temporary rvalues.
*
* 2. `ZeroMem`: To cancel the cleanup, we zero out the memory where
* the value resides. This is used for lvalues.
* up. This is primarily determined by the mode: a `ByValue` datum
* will always be cleaned up by revoking cleanup using
* `revoke_clean()`, because there is no other option. By ref datums
* can sometimes be cleaned up via `revoke_clean` (in particular,
* by-ref datums that originated from rvalues), but sometimes they
* must be zeroed. This is indicated by the `DatumCleanup`
* parameter. Note that zeroing a by-ref datum *always works* to
* cancel the cleanup, but using `revoke_clean` is preferable since
* there is no runtime cost. Some older parts of the code (notably
* `match_`, at least at the time of this writing) rely on this and
* only use zeroing.
*
* # Copying, moving, and storing
*
@ -125,12 +127,6 @@ pub struct Datum {
/// Indicates whether this is by-ref or by-value.
mode: DatumMode,
/// How did this value originate? This is particularly important
/// if the value is MOVED or prematurely DROPPED, because it
/// describes how to cancel the cleanup that was scheduled before.
/// See the def'n of the `DatumCleanup` type.
source: DatumCleanup
}
pub struct DatumBlock {
@ -138,10 +134,13 @@ pub struct DatumBlock {
datum: Datum,
}
#[deriving(Eq)]
#[deriving(Eq, IterBytes)]
pub enum DatumMode {
/// `val` is a pointer to the actual value (and thus has type *T)
ByRef,
/// `val` is a pointer to the actual value (and thus has type *T).
/// The argument indicates how to cancel cleanup of this datum if
/// the value is moved elsewhere, which can either be by zeroing
/// the memory or by canceling a registered cleanup.
ByRef(DatumCleanup),
/// `val` is the actual value (*only used for immediates* like ints, ptrs)
ByValue,
@ -149,30 +148,23 @@ pub enum DatumMode {
pub impl DatumMode {
fn is_by_ref(&self) -> bool {
match *self { ByRef => true, ByValue => false }
match *self { ByRef(_) => true, ByValue => false }
}
fn is_by_value(&self) -> bool {
match *self { ByRef => false, ByValue => true }
}
}
impl to_bytes::IterBytes for DatumMode {
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
(*self as uint).iter_bytes(lsb0, f)
match *self { ByRef(_) => false, ByValue => true }
}
}
/// See `Datum cleanup styles` section at the head of this module.
#[deriving(Eq)]
#[deriving(Eq, IterBytes)]
pub enum DatumCleanup {
RevokeClean,
ZeroMem
}
pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum {
return Datum {val: val, ty: ty,
mode: ByValue, source: RevokeClean};
return Datum {val: val, ty: ty, mode: ByValue};
}
pub fn immediate_rvalue_bcx(bcx: block,
@ -195,7 +187,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum {
let llty = type_of::type_of(bcx.ccx(), ty);
let scratch = alloca_maybe_zeroed(bcx, llty, zero);
Datum { val: scratch, ty: ty, mode: ByRef, source: RevokeClean }
Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
}
pub fn appropriate_mode(ty: ty::t) -> DatumMode {
@ -210,7 +202,7 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode {
} else if ty::type_is_immediate(ty) {
ByValue
} else {
ByRef
ByRef(RevokeClean)
}
}
@ -289,7 +281,7 @@ pub impl Datum {
ty::type_needs_drop(bcx.tcx(), self.ty)
{
match self.mode {
ByRef => {
ByRef(_) => {
let cast = PointerCast(bcx, dst, val_ty(self.val));
let cmp = ICmp(bcx, lib::llvm::IntNE, cast, self.val);
do with_cond(bcx, cmp) |bcx| {
@ -324,7 +316,7 @@ pub impl Datum {
ByValue => {
Store(bcx, self.val, dst);
}
ByRef => {
ByRef(_) => {
memcpy_ty(bcx, dst, self.val, self.ty);
}
}
@ -352,7 +344,7 @@ pub impl Datum {
}
match self.mode {
ByRef => {
ByRef(_) => {
memcpy_ty(bcx, dst, self.val, self.ty);
}
ByValue => {
@ -367,28 +359,32 @@ pub impl Datum {
fn add_clean(&self, bcx: block) {
/*!
*
* Schedules this datum for cleanup in `bcx`. The datum
* must be an rvalue. */
* must be an rvalue.
*/
assert_eq!(self.source, RevokeClean);
match self.mode {
ByValue => {
add_clean_temp_immediate(bcx, self.val, self.ty);
}
ByRef => {
ByRef(RevokeClean) => {
add_clean_temp_mem(bcx, self.val, self.ty);
}
ByRef(ZeroMem) => {
bcx.tcx().sess.bug(
fmt!("Cannot add clean to a 'zero-mem' datum"));
}
}
}
fn cancel_clean(&self, bcx: block) {
if ty::type_needs_drop(bcx.tcx(), self.ty) {
match self.source {
RevokeClean => {
match self.mode {
ByValue |
ByRef(RevokeClean) => {
revoke_clean(bcx, self.val);
}
ZeroMem => {
ByRef(ZeroMem) => {
// Lvalues which potentially need to be dropped
// must be passed by ref, so that we can zero them
// out.
@ -400,11 +396,10 @@ pub impl Datum {
}
fn to_str(&self, ccx: &CrateContext) -> ~str {
fmt!("Datum { val=%s, ty=%s, mode=%?, source=%? }",
fmt!("Datum { val=%s, ty=%s, mode=%? }",
val_str(ccx.tn, self.val),
ty_to_str(ccx.tcx, self.ty),
self.mode,
self.source)
self.mode)
}
fn to_value_datum(&self, bcx: block) -> Datum {
@ -417,9 +412,9 @@ pub impl Datum {
match self.mode {
ByValue => *self,
ByRef => {
ByRef(_) => {
Datum {val: self.to_value_llval(bcx), mode: ByValue,
ty: self.ty, source: RevokeClean}
ty: self.ty}
}
}
}
@ -434,7 +429,7 @@ pub impl Datum {
} else {
match self.mode {
ByValue => self.val,
ByRef => {
ByRef(_) => {
if ty::type_is_bool(self.ty) {
LoadRangeAssert(bcx, self.val, 0, 2, lib::llvm::True)
} else {
@ -447,24 +442,24 @@ pub impl Datum {
fn to_ref_datum(&self, bcx: block) -> Datum {
/*!
*
* Yields a by-ref form of this datum. This may involve
* creation of a temporary stack slot. The value returned by
* this function is not separately rooted from this datum, so
* it will not live longer than the current datum. */
* it will not live longer than the current datum.
*/
match self.mode {
ByRef => *self,
ByRef(_) => *self,
ByValue => {
Datum {val: self.to_ref_llval(bcx), mode: ByRef,
ty: self.ty, source: RevokeClean}
Datum {val: self.to_ref_llval(bcx), mode: ByRef(RevokeClean),
ty: self.ty}
}
}
}
fn to_ref_llval(&self, bcx: block) -> ValueRef {
match self.mode {
ByRef => self.val,
ByRef(_) => self.val,
ByValue => {
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty)))
@ -490,7 +485,7 @@ pub impl Datum {
match self.appropriate_mode() {
ByValue => self.to_value_llval(bcx),
ByRef => self.to_ref_llval(bcx)
ByRef(_) => self.to_ref_llval(bcx)
}
}
@ -501,7 +496,7 @@ pub impl Datum {
match self.appropriate_mode() {
ByValue => self.to_value_datum(bcx),
ByRef => self.to_ref_datum(bcx)
ByRef(_) => self.to_ref_datum(bcx)
}
}
@ -512,9 +507,8 @@ pub impl Datum {
let base_val = self.to_ref_llval(bcx);
Datum {
val: gep(base_val),
mode: ByRef,
mode: ByRef(source),
ty: ty,
source: source
}
}
@ -524,7 +518,7 @@ pub impl Datum {
}
return match self.mode {
ByRef => glue::drop_ty(bcx, self.val, self.ty),
ByRef(_) => glue::drop_ty(bcx, self.val, self.ty),
ByValue => glue::drop_ty_immediate(bcx, self.val, self.ty)
};
}
@ -546,7 +540,7 @@ pub impl Datum {
let ptr = self.to_value_llval(bcx);
let body = opaque_box_body(bcx, content_ty, ptr);
Datum {val: body, ty: content_ty, mode: ByRef, source: ZeroMem}
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
}
fn to_rptr(&self, bcx: block) -> Datum {
@ -561,8 +555,7 @@ pub impl Datum {
let llval = self.to_ref_llval(bcx);
let rptr_ty = ty::mk_imm_rptr(bcx.tcx(), ty::re_static,
self.ty);
Datum {val: llval, ty: rptr_ty,
mode: ByValue, source: RevokeClean}
Datum {val: llval, ty: rptr_ty, mode: ByValue}
}
fn try_deref(&self,
@ -606,7 +599,7 @@ pub impl Datum {
let repr = adt::represent_type(ccx, self.ty);
let ty = ty::subst(ccx.tcx, substs, variants[0].args[0]);
return match self.mode {
ByRef => {
ByRef(_) => {
// Recast lv.val as a pointer to the newtype
// rather than a ptr to the enum type.
(
@ -614,8 +607,7 @@ pub impl Datum {
val: adt::trans_field_ptr(bcx, repr, self.val,
0, 0),
ty: ty,
mode: ByRef,
source: ZeroMem
mode: ByRef(ZeroMem)
}),
bcx
)
@ -645,7 +637,7 @@ pub impl Datum {
let repr = adt::represent_type(ccx, self.ty);
let ty = fields[0].mt.ty;
return match self.mode {
ByRef => {
ByRef(_) => {
// Recast lv.val as a pointer to the newtype rather
// than a pointer to the struct type.
// FIXME #6572: This isn't correct for structs with
@ -655,8 +647,7 @@ pub impl Datum {
val: adt::trans_field_ptr(bcx, repr, self.val,
0, 0),
ty: ty,
mode: ByRef,
source: ZeroMem
mode: ByRef(ZeroMem)
}),
bcx
)
@ -683,8 +674,7 @@ pub impl Datum {
Datum {
val: lv.to_value_llval(bcx),
ty: ty,
mode: ByRef,
source: ZeroMem // *p is an lvalue
mode: ByRef(ZeroMem)
}
}
}

View File

@ -247,7 +247,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
// must patchup the type.
DatumBlock {bcx: bcx,
datum: Datum {val: datum.val, ty: adjusted_ty,
mode: datum.mode, source: datum.source}}
mode: datum.mode}}
}
fn auto_slice(bcx: block,
@ -793,8 +793,7 @@ fn trans_def_datum_unadjusted(bcx: block,
bcx: bcx,
datum: Datum {val: llval,
ty: rust_ty,
mode: ByValue,
source: RevokeClean}
mode: ByValue}
};
}
}
@ -920,8 +919,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
bcx: bcx,
datum: Datum {val: elt,
ty: vt.unit_ty,
mode: ByRef,
source: ZeroMem}
mode: ByRef(ZeroMem)}
};
}
@ -988,8 +986,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
bcx: bcx,
datum: Datum {val: val,
ty: const_ty,
mode: ByRef,
source: ZeroMem}
mode: ByRef(ZeroMem)}
}
}
_ => {
@ -1014,8 +1011,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
Datum {
val: val,
ty: local_ty,
mode: ByRef,
source: ZeroMem
mode: ByRef(ZeroMem)
}
}
None => {
@ -1052,8 +1048,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
Datum {
val: casted_val,
ty: self_info.t,
mode: ByRef,
source: ZeroMem
mode: ByRef(ZeroMem)
}
}
_ => {
@ -1066,7 +1061,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
table: &HashMap<ast::node_id, local_val>,
nid: ast::node_id) -> Datum {
let (v, mode) = match table.find(&nid) {
Some(&local_mem(v)) => (v, ByRef),
Some(&local_mem(v)) => (v, ByRef(ZeroMem)),
Some(&local_imm(v)) => (v, ByValue),
None => {
bcx.sess().bug(fmt!(
@ -1082,7 +1077,6 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
val: v,
ty: ty,
mode: mode,
source: ZeroMem
}
}
}

View File

@ -692,19 +692,15 @@ pub fn trans_intrinsic(ccx: @CrateContext,
fcx.llretptr.get());
}
~"move_val" => {
// Create a datum reflecting the value being moved:
//
// - the datum will be by ref if the value is non-immediate;
//
// - the datum has a RevokeClean source because, that way,
// the `move_to()` method does not feel compelled to
// zero out the memory where the datum resides. Zeroing
// is not necessary since, for intrinsics, there is no
// cleanup to concern ourselves with.
// Create a datum reflecting the value being moved.
// Use `appropriate_mode` so that the datum is by ref
// if the value is non-immediate. Note that, with
// intrinsics, there are no argument cleanups to
// concern ourselves with.
let tp_ty = substs.tys[0];
let mode = appropriate_mode(tp_ty);
let src = Datum {val: get_param(decl, first_real_arg + 1u),
ty: tp_ty, mode: mode, source: RevokeClean};
ty: tp_ty, mode: mode};
bcx = src.move_to(bcx, DROP_EXISTING,
get_param(decl, first_real_arg));
}
@ -713,7 +709,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
let tp_ty = substs.tys[0];
let mode = appropriate_mode(tp_ty);
let src = Datum {val: get_param(decl, first_real_arg + 1u),
ty: tp_ty, mode: mode, source: RevokeClean};
ty: tp_ty, mode: mode};
bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
}
~"min_align_of" => {
@ -832,7 +828,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
}
});
let datum = Datum {val: get_param(decl, first_real_arg),
mode: ByRef, ty: fty, source: ZeroMem};
mode: ByRef(ZeroMem), ty: fty};
let arg_vals = ~[frameaddress_val];
bcx = trans_call_inner(
bcx, None, fty, ty::mk_nil(),

View File

@ -197,7 +197,7 @@ pub fn trans_method_callee(bcx: block,
// Replace method_self with method_static here.
let mut origin = mentry.origin;
match origin {
typeck::method_self(copy trait_id, copy method_index) => {
typeck::method_self(trait_id, method_index) => {
// Get the ID of the impl we're inside.
let impl_def_id = bcx.fcx.impl_id.get();
@ -445,7 +445,7 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id,
_, _)) => {
m.generics.ty_params.len()
}
copy e => fail!("method_ty_param_count %?", e)
ref e => fail!("method_ty_param_count %?", *e)
}
} else {
csearch::get_type_param_count(ccx.sess.cstore, m_id) -