Prep for dropflag hints: refactor trans:_match to pass around MatchInput rather than ValueRef.

(already thumbs-upped pre-rebase by nikomatsakis)

The refactoring here is trivial because `trans::datum::Lvalue`
currently carries no payload. However, future commits will start
adding a payload to `Lvalue`, and thus will force us either

 1. to thread the payload through the `_match` code (a long term goal), or

 2. to ensure the payload has some reasonable default value.
This commit is contained in:
Felix S. Klock II 2015-06-05 14:38:49 +02:00
parent 3eb7dd7f74
commit 9ef61f1ee0
2 changed files with 118 additions and 56 deletions

View File

@ -417,16 +417,45 @@ fn has_nested_bindings(m: &[Match], col: usize) -> bool {
return false;
}
// As noted in `fn match_datum`, we should eventually pass around a
// `Datum<Lvalue>` for the `val`; but until we get to that point, this
// `MatchInput` struct will serve -- it has everything `Datum<Lvalue>`
// does except for the type field.
#[derive(Copy, Clone)]
pub struct MatchInput { val: ValueRef, lval: Lvalue }
impl<'tcx> Datum<'tcx, Lvalue> {
pub fn match_input(&self) -> MatchInput {
MatchInput {
val: self.val,
lval: self.kind,
}
}
}
impl MatchInput {
fn from_val(val: ValueRef) -> MatchInput {
MatchInput {
val: val,
lval: Lvalue,
}
}
fn to_datum<'tcx>(self, ty: Ty<'tcx>) -> Datum<'tcx, Lvalue> {
Datum::new(self.val, ty, self.lval)
}
}
fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
m: &[Match<'a, 'p, 'blk, 'tcx>],
col: usize,
val: ValueRef)
val: MatchInput)
-> Vec<Match<'a, 'p, 'blk, 'tcx>> {
debug!("expand_nested_bindings(bcx={}, m={:?}, col={}, val={})",
bcx.to_str(),
m,
col,
bcx.val_to_string(val));
bcx.val_to_string(val.val));
let _indenter = indenter();
m.iter().map(|br| {
@ -435,7 +464,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
loop {
pat = match pat.node {
ast::PatIdent(_, ref path, Some(ref inner)) => {
bound_ptrs.push((path.node, val));
bound_ptrs.push((path.node, val.val));
&**inner
},
_ => break
@ -457,7 +486,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
dm: &DefMap,
m: &[Match<'a, 'p, 'blk, 'tcx>],
col: usize,
val: ValueRef,
val: MatchInput,
mut e: F)
-> Vec<Match<'a, 'p, 'blk, 'tcx>> where
F: FnMut(&[&'p ast::Pat]) -> Option<Vec<&'p ast::Pat>>,
@ -466,7 +495,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
bcx.to_str(),
m,
col,
bcx.val_to_string(val));
bcx.val_to_string(val.val));
let _indenter = indenter();
m.iter().filter_map(|br| {
@ -476,7 +505,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
match this.node {
ast::PatIdent(_, ref path, None) => {
if pat_is_binding(dm, &*this) {
bound_ptrs.push((path.node, val));
bound_ptrs.push((path.node, val.val));
}
}
ast::PatVec(ref before, Some(ref slice), ref after) => {
@ -503,13 +532,13 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
dm: &DefMap,
m: &[Match<'a, 'p, 'blk, 'tcx>],
col: usize,
val: ValueRef)
val: MatchInput)
-> Vec<Match<'a, 'p, 'blk, 'tcx>> {
debug!("enter_default(bcx={}, m={:?}, col={}, val={})",
bcx.to_str(),
m,
col,
bcx.val_to_string(val));
bcx.val_to_string(val.val));
let _indenter = indenter();
// Collect all of the matches that can match against anything.
@ -560,14 +589,14 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
opt: &Opt,
col: usize,
variant_size: usize,
val: ValueRef)
val: MatchInput)
-> Vec<Match<'a, 'p, 'blk, 'tcx>> {
debug!("enter_opt(bcx={}, m={:?}, opt={:?}, col={}, val={})",
bcx.to_str(),
m,
*opt,
col,
bcx.val_to_string(val));
bcx.val_to_string(val.val));
let _indenter = indenter();
let ctor = match opt {
@ -663,11 +692,11 @@ struct ExtractedBlock<'blk, 'tcx: 'blk> {
fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
repr: &adt::Repr<'tcx>,
disr_val: ty::Disr,
val: ValueRef)
val: MatchInput)
-> ExtractedBlock<'blk, 'tcx> {
let _icx = push_ctxt("match::extract_variant_args");
let args = (0..adt::num_args(repr, disr_val)).map(|i| {
adt::trans_field_ptr(bcx, repr, val, disr_val, i)
adt::trans_field_ptr(bcx, repr, val.val, disr_val, i)
}).collect();
ExtractedBlock { vals: args, bcx: bcx }
@ -675,13 +704,13 @@ fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
/// Helper for converting from the ValueRef that we pass around in the match code, which is always
/// an lvalue, into a Datum. Eventually we should just pass around a Datum and be done with it.
fn match_datum<'tcx>(val: ValueRef, left_ty: Ty<'tcx>) -> Datum<'tcx, Lvalue> {
Datum::new(val, left_ty, Lvalue)
fn match_datum<'tcx>(val: MatchInput, left_ty: Ty<'tcx>) -> Datum<'tcx, Lvalue> {
val.to_datum(left_ty)
}
fn bind_subslice_pat(bcx: Block,
pat_id: ast::NodeId,
val: ValueRef,
val: MatchInput,
offset_left: usize,
offset_right: usize) -> ValueRef {
let _icx = push_ctxt("match::bind_subslice_pat");
@ -711,7 +740,7 @@ fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
left_ty: Ty<'tcx>,
before: usize,
after: usize,
val: ValueRef)
val: MatchInput)
-> ExtractedBlock<'blk, 'tcx> {
let _icx = push_ctxt("match::extract_vec_elems");
let vec_datum = match_datum(val, left_ty);
@ -952,7 +981,7 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
guard_expr: &ast::Expr,
data: &ArmData<'p, 'blk, 'tcx>,
m: &[Match<'a, 'p, 'blk, 'tcx>],
vals: &[ValueRef],
vals: &[MatchInput],
chk: &FailureHandler,
has_genuine_default: bool)
-> Block<'blk, 'tcx> {
@ -960,7 +989,7 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
bcx.to_str(),
guard_expr,
m,
vals.iter().map(|v| bcx.val_to_string(*v)).collect::<Vec<_>>().join(", "));
vals.iter().map(|v| bcx.val_to_string(v.val)).collect::<Vec<_>>().join(", "));
let _indenter = indenter();
let mut bcx = insert_lllocals(bcx, &data.bindings_map, None);
@ -999,13 +1028,13 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
m: &[Match<'a, 'p, 'blk, 'tcx>],
vals: &[ValueRef],
vals: &[MatchInput],
chk: &FailureHandler,
has_genuine_default: bool) {
debug!("compile_submatch(bcx={}, m={:?}, vals=[{}])",
bcx.to_str(),
m,
vals.iter().map(|v| bcx.val_to_string(*v)).collect::<Vec<_>>().join(", "));
vals.iter().map(|v| bcx.val_to_string(v.val)).collect::<Vec<_>>().join(", "));
let _indenter = indenter();
let _icx = push_ctxt("match::compile_submatch");
let mut bcx = bcx;
@ -1065,10 +1094,10 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
m: &[Match<'a, 'p, 'blk, 'tcx>],
vals: &[ValueRef],
vals: &[MatchInput],
chk: &FailureHandler,
col: usize,
val: ValueRef,
val: MatchInput,
has_genuine_default: bool) {
let fcx = bcx.fcx;
let tcx = bcx.tcx();
@ -1098,13 +1127,13 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let repr = adt::represent_type(bcx.ccx(), left_ty);
let arg_count = adt::num_args(&*repr, 0);
let (arg_count, struct_val) = if type_is_sized(bcx.tcx(), left_ty) {
(arg_count, val)
(arg_count, val.val)
} else {
// For an unsized ADT (i.e. DST struct), we need to treat
// the last field specially: instead of simply passing a
// ValueRef pointing to that field, as with all the others,
// we skip it and instead construct a 'fat ptr' below.
(arg_count - 1, Load(bcx, expr::get_dataptr(bcx, val)))
(arg_count - 1, Load(bcx, expr::get_dataptr(bcx, val.val)))
};
let mut field_vals: Vec<ValueRef> = (0..arg_count).map(|ix|
adt::trans_field_ptr(bcx, &*repr, struct_val, 0, ix)
@ -1123,7 +1152,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let llty = type_of::type_of(bcx.ccx(), unsized_ty);
let scratch = alloca_no_lifetime(bcx, llty, "__struct_field_fat_ptr");
let data = adt::trans_field_ptr(bcx, &*repr, struct_val, 0, arg_count);
let len = Load(bcx, expr::get_len(bcx, val));
let len = Load(bcx, expr::get_len(bcx, val.val));
Store(bcx, data, expr::get_dataptr(bcx, scratch));
Store(bcx, len, expr::get_len(bcx, scratch));
field_vals.push(scratch);
@ -1132,7 +1161,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
}
Some(field_vals)
} else if any_uniq_pat(m, col) || any_region_pat(m, col) {
Some(vec!(Load(bcx, val)))
Some(vec!(Load(bcx, val.val)))
} else {
match left_ty.sty {
ty::TyArray(_, n) => {
@ -1149,7 +1178,9 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
&check_match::Single, col,
field_vals.len())
);
let mut vals = field_vals;
let mut vals: Vec<_> = field_vals.into_iter()
.map(|v|MatchInput::from_val(v))
.collect();
vals.push_all(&vals_left);
compile_submatch(bcx, &pats, &vals, chk, has_genuine_default);
return;
@ -1161,12 +1192,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let opts = get_branches(bcx, m, col);
debug!("options={:?}", opts);
let mut kind = NoBranch;
let mut test_val = val;
let mut test_val = val.val;
debug!("test_val={}", bcx.val_to_string(test_val));
if !opts.is_empty() {
match opts[0] {
ConstantValue(..) | ConstantRange(..) => {
test_val = load_if_immediate(bcx, val, left_ty);
test_val = load_if_immediate(bcx, val.val, left_ty);
kind = if left_ty.is_integral() {
Switch
} else {
@ -1174,12 +1205,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
};
}
Variant(_, ref repr, _, _) => {
let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val);
let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val.val);
kind = the_kind;
if let Some(tval) = val_opt { test_val = tval; }
}
SliceLengthEqual(..) | SliceLengthGreaterOrEqual(..) => {
let (_, len) = tvec::get_base_and_len(bcx, val, left_ty);
let (_, len) = tvec::get_base_and_len(bcx, val.val, left_ty);
test_val = len;
kind = Switch;
}
@ -1303,7 +1334,9 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
ConstantValue(..) | ConstantRange(..) => ()
}
let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val);
let mut opt_vals = unpacked;
let mut opt_vals: Vec<_> = unpacked.into_iter()
.map(|v|MatchInput::from_val(v))
.collect();
opt_vals.push_all(&vals_left[..]);
compile_submatch(opt_cx,
&opt_ms[..],
@ -1547,7 +1580,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
&& arm.pats.last().unwrap().node == ast::PatWild(ast::PatWildSingle)
});
compile_submatch(bcx, &matches[..], &[discr_datum.val], &chk, has_default);
compile_submatch(bcx, &matches[..], &[discr_datum.match_input()], &chk, has_default);
let mut arm_cxs = Vec::new();
for arm_data in &arm_datas {
@ -1622,7 +1655,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
add_comment(bcx, "creating zeroable ref llval");
}
let var_scope = cleanup::var_scope(tcx, local.id);
bind_irrefutable_pat(bcx, pat, init_datum.val, var_scope)
bind_irrefutable_pat(bcx, pat, init_datum.match_input(), var_scope)
}
None => {
create_dummy_locals(bcx, pat)
@ -1671,7 +1704,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
/// - val: the value being matched -- must be an lvalue (by ref, with cleanup)
pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
pat: &ast::Pat,
val: ValueRef,
val: MatchInput,
cleanup_scope: cleanup::ScopeId)
-> Block<'blk, 'tcx> {
debug!("bind_irrefutable_pat(bcx={}, pat={:?})",
@ -1702,7 +1735,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ast::BindByValue(_) => {
// By value binding: move the value that `val`
// points at into the binding's stack slot.
let d = Datum::new(val, ty, Lvalue);
let d = val.to_datum(ty);
d.store_to(bcx, llval)
}
@ -1710,10 +1743,10 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// By ref binding: the value of the variable
// is the pointer `val` itself or fat pointer referenced by `val`
if type_is_fat_ptr(bcx.tcx(), ty) {
expr::copy_fat_ptr(bcx, val, llval);
expr::copy_fat_ptr(bcx, val.val, llval);
}
else {
Store(bcx, val, llval);
Store(bcx, val.val, llval);
}
bcx
@ -1738,8 +1771,11 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
val);
if let Some(ref sub_pat) = *sub_pats {
for (i, &argval) in args.vals.iter().enumerate() {
bcx = bind_irrefutable_pat(bcx, &*sub_pat[i],
argval, cleanup_scope);
bcx = bind_irrefutable_pat(
bcx,
&*sub_pat[i],
MatchInput::from_val(argval),
cleanup_scope);
}
}
}
@ -1753,9 +1789,12 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let repr = adt::represent_node(bcx, pat.id);
for (i, elem) in elems.iter().enumerate() {
let fldptr = adt::trans_field_ptr(bcx, &*repr,
val, 0, i);
bcx = bind_irrefutable_pat(bcx, &**elem,
fldptr, cleanup_scope);
val.val, 0, i);
bcx = bind_irrefutable_pat(
bcx,
&**elem,
MatchInput::from_val(fldptr),
cleanup_scope);
}
}
}
@ -1772,26 +1811,45 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| {
for f in fields {
let ix = tcx.field_idx_strict(f.node.ident.name, field_tys);
let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val,
discr, ix);
bcx = bind_irrefutable_pat(bcx, &*f.node.pat, fldptr, cleanup_scope);
let fldptr = adt::trans_field_ptr(
bcx,
&*pat_repr,
val.val,
discr,
ix);
bcx = bind_irrefutable_pat(bcx,
&*f.node.pat,
MatchInput::from_val(fldptr),
cleanup_scope);
}
})
}
ast::PatTup(ref elems) => {
let repr = adt::represent_node(bcx, pat.id);
for (i, elem) in elems.iter().enumerate() {
let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i);
bcx = bind_irrefutable_pat(bcx, &**elem, fldptr, cleanup_scope);
let fldptr = adt::trans_field_ptr(bcx, &*repr, val.val, 0, i);
bcx = bind_irrefutable_pat(
bcx,
&**elem,
MatchInput::from_val(fldptr),
cleanup_scope);
}
}
ast::PatBox(ref inner) => {
let llbox = Load(bcx, val);
bcx = bind_irrefutable_pat(bcx, &**inner, llbox, cleanup_scope);
let llbox = Load(bcx, val.val);
bcx = bind_irrefutable_pat(
bcx,
&**inner,
MatchInput::from_val(llbox),
cleanup_scope);
}
ast::PatRegion(ref inner, _) => {
let loaded_val = Load(bcx, val);
bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, cleanup_scope);
let loaded_val = Load(bcx, val.val);
bcx = bind_irrefutable_pat(
bcx,
&**inner,
MatchInput::from_val(loaded_val),
cleanup_scope);
}
ast::PatVec(ref before, ref slice, ref after) => {
let pat_ty = node_id_type(bcx, pat.id);
@ -1811,7 +1869,11 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
.chain(after.iter())
.zip(extracted.vals)
.fold(bcx, |bcx, (inner, elem)|
bind_irrefutable_pat(bcx, &**inner, elem, cleanup_scope)
bind_irrefutable_pat(
bcx,
&**inner,
MatchInput::from_val(elem),
cleanup_scope)
);
}
ast::PatMac(..) => {

View File

@ -1335,9 +1335,9 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
let llarg = get_param(fcx.llfn, idx);
idx += 1;
bcx.fcx.schedule_lifetime_end(arg_scope_id, llarg);
bcx.fcx.schedule_drop_mem(arg_scope_id, llarg, arg_ty);
bcx.fcx.schedule_drop_mem(arg_scope_id, llarg, arg_ty, None);
datum::Datum::new(llarg, arg_ty, datum::Lvalue)
datum::Datum::new(llarg, arg_ty, datum::Lvalue::new("create_datum_for_fn_args"))
} else if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
let data = get_param(fcx.llfn, idx);
let extra = get_param(fcx.llfn, idx + 1);
@ -1408,7 +1408,7 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
} else {
// General path. Copy out the values that are used in the
// pattern.
_match::bind_irrefutable_pat(bcx, pat, arg_datum.val, arg_scope_id)
_match::bind_irrefutable_pat(bcx, pat, arg_datum.match_input(), arg_scope_id)
};
debuginfo::create_argument_metadata(bcx, &args[i]);
}