From 9ef61f1ee0690b4fb04192a283113901d5764b32 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 5 Jun 2015 14:38:49 +0200 Subject: [PATCH] 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. --- src/librustc_trans/trans/_match.rs | 168 ++++++++++++++++++++--------- src/librustc_trans/trans/base.rs | 6 +- 2 files changed, 118 insertions(+), 56 deletions(-) diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index f4024df5713..c1fb6f2437f 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -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` for the `val`; but until we get to that point, this +// `MatchInput` struct will serve -- it has everything `Datum` +// 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> { 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> where F: FnMut(&[&'p ast::Pat]) -> Option>, @@ -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> { 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> { 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::>().join(", ")); + vals.iter().map(|v| bcx.val_to_string(v.val)).collect::>().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::>().join(", ")); + vals.iter().map(|v| bcx.val_to_string(v.val)).collect::>().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 = (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(..) => { diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 3d9989e093c..1e016ea1fdc 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -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]); }