diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 50096c012be3d..85217a7d55ece 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -108,14 +108,3 @@ pub fn pat_contains_bindings(dm: resolve::DefMap, pat: &Pat) -> bool { }); contains_bindings } - -pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> { - match pat.node { - PatIdent(BindByValue(_), ref path, None) => { - Some(path) - } - _ => { - None - } - } -} diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 8828fd5e01914..bf62c349e05a5 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1363,13 +1363,9 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>, let datum = Datum(llval, binding_info.ty, Lvalue); fcx.schedule_drop_mem(cleanup_scope, llval, binding_info.ty); - { - debug!("binding {:?} to {}", - binding_info.id, - bcx.val_to_str(llval)); - let mut llmap = bcx.fcx.lllocals.borrow_mut(); - llmap.get().insert(binding_info.id, datum); - } + debug!("binding {:?} to {}", binding_info.id, bcx.val_to_str(llval)); + let local = datum.to_expr_datum(); + bcx.fcx.locals.borrow_mut().get().insert(binding_info.id, local); if bcx.sess().opts.debuginfo { debuginfo::create_match_binding_metadata(bcx, @@ -1434,8 +1430,7 @@ fn compile_guard<'r, } TrByRef => {} } - let mut lllocals = bcx.fcx.lllocals.borrow_mut(); - lllocals.get().remove(&binding_info.id); + bcx.fcx.locals.borrow_mut().get().remove(&binding_info.id); } return bcx; } @@ -1913,7 +1908,7 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>, bcx = store_non_ref_bindings(bcx, arm_data.bindings_map, None); } - // insert bindings into the lllocals map and add cleanups + // insert bindings into the locals map and add cleanups let cleanup_scope = fcx.push_custom_cleanup_scope(); bcx = insert_lllocals(bcx, arm_data.bindings_map, cleanup::CustomScope(cleanup_scope)); @@ -1926,11 +1921,16 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>, return bcx; } -enum IrrefutablePatternBindingMode { - // Stores the association between node ID and LLVM value in `lllocals`. - BindLocal, - // Stores the association between node ID and LLVM value in `llargs`. - BindArgument +fn simple_identifier<'a>(pat: &'a ast::Pat) + -> Option<(&'a ast::Path, ast::Mutability)> { + match pat.node { + ast::PatIdent(ast::BindByValue(mutbl), ref path, None) => { + Some((path, mutbl)) + } + _ => { + None + } + } } pub fn store_local<'a>(bcx: &'a Block<'a>, @@ -1959,12 +1959,12 @@ pub fn store_local<'a>(bcx: &'a Block<'a>, // In such cases, the more general path is unsafe, because // it assumes it is matching against a valid value. match simple_identifier(pat) { - Some(path) => { + Some((path, mutbl)) => { + let var_ty = node_id_type(bcx, pat.id); let var_scope = cleanup::var_scope(tcx, local.id); - return mk_binding_alloca( - bcx, pat.id, path, BindLocal, var_scope, (), - |(), bcx, v, _| expr::trans_into(bcx, init_expr, - expr::SaveIn(v))); + return bind_lvalue(bcx, var_ty, pat.id, path, + mutbl == ast::MutMutable, var_scope, + Some(BindFromExpr(init_expr))); } None => {} @@ -1980,7 +1980,7 @@ pub fn store_local<'a>(bcx: &'a Block<'a>, add_comment(bcx, "creating zeroable ref llval"); } let var_scope = cleanup::var_scope(tcx, local.id); - bind_irrefutable_pat(bcx, pat, init_datum.val, BindLocal, var_scope) + bind_irrefutable_pat(bcx, pat, init_datum.val, var_scope) } } None => { @@ -1995,11 +1995,10 @@ pub fn store_local<'a>(bcx: &'a Block<'a>, // value to store into them immediately let tcx = bcx.tcx(); pat_bindings(tcx.def_map, pat, |_, p_id, _, path| { - let scope = cleanup::var_scope(tcx, p_id); - bcx = mk_binding_alloca( - bcx, p_id, path, BindLocal, scope, (), - |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx }); - }); + let var_ty = node_id_type(bcx, p_id); + let scope = cleanup::var_scope(tcx, p_id); + bcx = bind_lvalue(bcx, var_ty, p_id, path, false, scope, None); + }); bcx } } @@ -2025,7 +2024,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, let _icx = push_ctxt("match::store_arg"); match simple_identifier(pat) { - Some(path) => { + Some((path, mutbl)) => { // Generate nicer LLVM for the common case of fn a pattern // like `x: T` let arg_ty = node_id_type(bcx, pat.id); @@ -2035,13 +2034,12 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, // already put it in a temporary alloca and gave it up, unless // we emit extra-debug-info, which requires local allocas :(. let arg_val = arg.add_clean(bcx.fcx, arg_scope); - let mut llmap = bcx.fcx.llargs.borrow_mut(); - llmap.get().insert(pat.id, Datum(arg_val, arg_ty, Lvalue)); + let datum = Datum(arg_val, arg_ty, LvalueExpr); + bcx.fcx.locals.borrow_mut().get().insert(pat.id, datum); bcx } else { - mk_binding_alloca( - bcx, pat.id, path, BindArgument, arg_scope, arg, - |arg, bcx, llval, _| arg.store_to(bcx, llval)) + bind_lvalue(bcx, arg_ty, pat.id, path, mutbl == ast::MutMutable, + arg_scope, Some(BindFromDatum(arg.to_expr_datum()))) } } @@ -2050,47 +2048,75 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, // pattern. let arg = unpack_datum!( bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope)); - bind_irrefutable_pat(bcx, pat, arg.val, - BindArgument, arg_scope) + bind_irrefutable_pat(bcx, pat, arg.val, arg_scope) } } } -fn mk_binding_alloca<'a,A>(bcx: &'a Block<'a>, - p_id: ast::NodeId, - path: &ast::Path, - binding_mode: IrrefutablePatternBindingMode, - cleanup_scope: cleanup::ScopeId, - arg: A, - populate: |A, &'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>) - -> &'a Block<'a> { - let var_ty = node_id_type(bcx, p_id); - let ident = ast_util::path_to_ident(path); - - // Allocate memory on stack for the binding. - let llval = alloc_ty(bcx, var_ty, bcx.ident(ident)); - - // Subtle: be sure that we *populate* the memory *before* - // we schedule the cleanup. - let bcx = populate(arg, bcx, llval, var_ty); - bcx.fcx.schedule_drop_mem(cleanup_scope, llval, var_ty); +enum BindSource<'a> { + BindFromExpr(&'a ast::Expr), + BindFromDatum(Datum) +} + +fn bind_lvalue<'a>(mut bcx: &'a Block<'a>, + var_ty: ty::t, + p_id: ast::NodeId, + path: &ast::Path, + is_mut: bool, + cleanup_scope: cleanup::ScopeId, + source: Option) + -> &'a Block<'a> { + let needs_drop = ty::type_needs_drop(bcx.tcx(), var_ty); + + // Do not use allocas for immutable immediate PODs, unless debuginfo + // needs them or there is no initializer available. + let datum = if !bcx.ccx().sess.opts.debuginfo && source.is_some() && !is_mut + && !needs_drop && is_by_value_type(bcx.ccx(), var_ty) { + let rvalue = match source.unwrap() { + BindFromExpr(expr) => { + let datum = unpack_datum!(bcx, expr::trans(bcx, expr)); + datum.to_rvalue_datum(bcx, "") + } + BindFromDatum(datum) => { + datum.to_rvalue_datum(bcx, "") + } + }; + unpack_datum!(bcx, rvalue.to_expr_datumblock()) + } else { + // Allocate memory on stack for the binding. + let ident = ast_util::path_to_ident(path); + let llval = alloc_ty(bcx, var_ty, bcx.ident(ident)); + + // Subtle: be sure that we *populate* the memory *before* + // we schedule the cleanup. + match source { + Some(BindFromExpr(expr)) => { + bcx = expr::trans_into(bcx, expr, expr::SaveIn(llval)); + } + Some(BindFromDatum(datum)) => { + bcx = datum.store_to(bcx, llval); + } + None => { + // Cleanup can happen without a valid value being assigned. + if needs_drop { + zero_mem(bcx, llval, var_ty); + } + } + } + bcx.fcx.schedule_drop_mem(cleanup_scope, llval, var_ty); + Datum(llval, var_ty, LvalueExpr) + }; // Now that memory is initialized and has cleanup scheduled, // create the datum and insert into the local variable map. - let datum = Datum(llval, var_ty, Lvalue); - let mut llmap = match binding_mode { - BindLocal => bcx.fcx.lllocals.borrow_mut(), - BindArgument => bcx.fcx.llargs.borrow_mut() - }; - llmap.get().insert(p_id, datum); + bcx.fcx.locals.borrow_mut().get().insert(p_id, datum); bcx } fn bind_irrefutable_pat<'a>( bcx: &'a Block<'a>, - pat: @ast::Pat, + pat: &ast::Pat, val: ValueRef, - binding_mode: IrrefutablePatternBindingMode, cleanup_scope: cleanup::ScopeId) -> &'a Block<'a> { /*! @@ -2106,13 +2132,11 @@ fn bind_irrefutable_pat<'a>( * - bcx: starting basic block context * - pat: the irrefutable pattern being matched. * - val: the value being matched -- must be an lvalue (by ref, with cleanup) - * - binding_mode: is this for an argument or a local variable? */ - debug!("bind_irrefutable_pat(bcx={}, pat={}, binding_mode={:?})", + debug!("bind_irrefutable_pat(bcx={}, pat={})", bcx.to_str(), - pat.repr(bcx.tcx()), - binding_mode); + pat.repr(bcx.tcx())); if bcx.sess().asm_comments() { add_comment(bcx, format!("bind_irrefutable_pat(pat={})", @@ -2131,30 +2155,21 @@ fn bind_irrefutable_pat<'a>( // Allocate the stack slot where the value of this // binding will live and place it into the appropriate // map. - bcx = mk_binding_alloca( - bcx, pat.id, path, binding_mode, cleanup_scope, (), - |(), bcx, llval, ty| { - match pat_binding_mode { - ast::BindByValue(_) => { - // By value binding: move the value that `val` - // points at into the binding's stack slot. - let d = Datum(val, ty, Lvalue); - d.store_to(bcx, llval) - } - - ast::BindByRef(_) => { - // By ref binding: the value of the variable - // is the pointer `val` itself. - Store(bcx, val, llval); - bcx - } - } - }); + let var_ty = node_id_type(bcx, pat.id); + let (kind, is_mut) = match pat_binding_mode { + ast::BindByValue(mutbl) => { + (LvalueExpr, mutbl == ast::MutMutable) + } + ast::BindByRef(_) => (RvalueExpr(Rvalue(ByValue)), false) + }; + let datum = Datum(val, var_ty, kind); + bcx = bind_lvalue(bcx, var_ty, pat.id, path, + is_mut, cleanup_scope, + Some(BindFromDatum(datum))); } for &inner_pat in inner.iter() { - bcx = bind_irrefutable_pat(bcx, inner_pat, val, - binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, inner_pat, val, cleanup_scope); } } ast::PatEnum(_, ref sub_pats) => { @@ -2172,8 +2187,7 @@ fn bind_irrefutable_pat<'a>( for sub_pat in sub_pats.iter() { for (i, argval) in args.vals.iter().enumerate() { bcx = bind_irrefutable_pat(bcx, sub_pat[i], - *argval, binding_mode, - cleanup_scope); + *argval, cleanup_scope); } } } @@ -2190,8 +2204,7 @@ fn bind_irrefutable_pat<'a>( let fldptr = adt::trans_field_ptr(bcx, repr, val, 0, i); bcx = bind_irrefutable_pat(bcx, *elem, - fldptr, binding_mode, - cleanup_scope); + fldptr, cleanup_scope); } } } @@ -2212,8 +2225,7 @@ fn bind_irrefutable_pat<'a>( let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys); let fldptr = adt::trans_field_ptr(bcx, pat_repr, val, discr, ix); - bcx = bind_irrefutable_pat(bcx, f.pat, fldptr, - binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, f.pat, fldptr, cleanup_scope); } }) } @@ -2221,17 +2233,16 @@ fn bind_irrefutable_pat<'a>( 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, - binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, *elem, fldptr, cleanup_scope); } } ast::PatUniq(inner) => { let llbox = Load(bcx, val); - bcx = bind_irrefutable_pat(bcx, inner, llbox, binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, inner, llbox, cleanup_scope); } ast::PatRegion(inner) => { let loaded_val = Load(bcx, val); - bcx = bind_irrefutable_pat(bcx, inner, loaded_val, binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, inner, loaded_val, cleanup_scope); } ast::PatVec(..) => { bcx.tcx().sess.span_bug( diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e76b2a81490e0..035546612281b 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1246,8 +1246,7 @@ pub fn new_fn_ctxt<'a>(ccx: @CrateContext, llreturn: Cell::new(None), personality: Cell::new(None), caller_expects_out_pointer: uses_outptr, - llargs: RefCell::new(HashMap::new()), - lllocals: RefCell::new(HashMap::new()), + locals: RefCell::new(HashMap::new()), llupvars: RefCell::new(HashMap::new()), id: id, param_substs: param_substs, diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 2be53b92db160..e897872ef230d 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -98,7 +98,7 @@ use syntax::ast_util; // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -pub enum EnvAction { +enum EnvAction { /// Copy the value from this llvm ValueRef into the environment. EnvCopy, @@ -109,7 +109,7 @@ pub enum EnvAction { EnvRef } -pub struct EnvValue { +struct EnvValue { action: EnvAction, datum: Datum } @@ -178,7 +178,7 @@ fn allocate_cbox<'a>(bcx: &'a Block<'a>, } } -pub struct ClosureResult<'a> { +struct ClosureResult<'a> { llbox: ValueRef, // llvalue of ptr to closure cdata_ty: ty::t, // type of the closure data bcx: &'a Block<'a> // final bcx @@ -188,8 +188,7 @@ pub struct ClosureResult<'a> { // construct a closure out of them. If copying is true, it is a // heap allocated closure that copies the upvars into environment. // Otherwise, it is stack allocated and copies pointers to the upvars. -pub fn store_environment<'a>( - bcx: &'a Block<'a>, +fn store_environment<'a>(bcx: &'a Block<'a>, bound_values: ~[EnvValue], sigil: ast::Sigil) -> ClosureResult<'a> { @@ -247,38 +246,31 @@ pub fn store_environment<'a>( // Given a context and a list of upvars, build a closure. This just // collects the upvars and packages them up for store_environment. -fn build_closure<'a>(bcx0: &'a Block<'a>, +fn build_closure<'a>(mut bcx: &'a Block<'a>, + id: ast::NodeId, cap_vars: &[moves::CaptureVar], sigil: ast::Sigil) -> ClosureResult<'a> { let _icx = push_ctxt("closure::build_closure"); - // If we need to, package up the iterator body to call - let bcx = bcx0; - // Package up the captured upvars - let mut env_vals = ~[]; - for cap_var in cap_vars.iter() { + let env_vals = cap_vars.map(|cap_var| { debug!("Building closure: captured variable {:?}", *cap_var); + let action = match cap_var.mode { + moves::CapRef => EnvRef, + moves::CapCopy => EnvCopy, + moves::CapMove => EnvMove + }; let datum = expr::trans_local_var(bcx, cap_var.def); - match cap_var.mode { - moves::CapRef => { - assert_eq!(sigil, ast::BorrowedSigil); - env_vals.push(EnvValue {action: EnvRef, - datum: datum}); - } - moves::CapCopy => { - env_vals.push(EnvValue {action: EnvCopy, - datum: datum}); - } - moves::CapMove => { - env_vals.push(EnvValue {action: EnvMove, - datum: datum}); - } + let r = datum.to_lvalue_datum(bcx, "", id); + bcx = r.bcx; + EnvValue { + action: action, + datum: r.datum } - } + }); - return store_environment(bcx, env_vals, sigil); + store_environment(bcx, env_vals, sigil) } // Given an enclosing block context, a new function context, a closure type, @@ -395,7 +387,7 @@ pub fn trans_expr_fn<'a>( let capture_map = ccx.maps.capture_map.borrow(); capture_map.get().get_copy(&id) }; - let ClosureResult {llbox, cdata_ty, bcx} = build_closure(bcx, *cap_vars.borrow(), sigil); + let ClosureResult {llbox, cdata_ty, bcx} = build_closure(bcx, id, *cap_vars.borrow(), sigil); trans_closure(ccx, decl, body, llfn, bcx.fcx.param_substs, id, [], ty::ty_fn_ret(fty), diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 27ad5998d8cf7..0a2c283a4d25b 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -20,7 +20,7 @@ use middle::trans::base; use middle::trans::build; use middle::trans::cleanup; use middle::trans::datum; -use middle::trans::datum::{Datum, Lvalue}; +use middle::trans::datum::Datum; use middle::trans::debuginfo; use middle::trans::type_::Type; use middle::ty::substs; @@ -210,8 +210,7 @@ impl Repr for param_substs { } // work around bizarre resolve errors -type RvalueDatum = datum::Datum; -type LvalueDatum = datum::Datum; +type ExprDatum = datum::Datum; // Function context. Every LLVM function we create will have one of // these. @@ -250,12 +249,9 @@ pub struct FunctionContext<'a> { // this value is false, llretptr will be a local alloca. caller_expects_out_pointer: bool, - // Maps arguments to allocas created for them in llallocas. - llargs: RefCell>, - - // Maps the def_ids for local variables to the allocas created for - // them in llallocas. - lllocals: RefCell>, + // Maps the NodeIds for arguments and local variables to + // the Datums that they were placed in. + locals: RefCell>, // Same as above, but for closure upvars llupvars: RefCell>, diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 329301efa5ebb..73588f12cc900 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -499,6 +499,21 @@ impl Datum { |r| DatumBlock(bcx, r)) } + pub fn to_lvalue_or_pod_rvalue_datum(&self, bcx: &Block) -> Datum { + /*! + * Asserts that this datum *is* copiable and returns it. + */ + + let kind = match self.kind { + LvalueExpr => LvalueExpr, + RvalueExpr(ref r) => { + assert!(!ty::type_needs_drop(bcx.tcx(), self.ty)); + RvalueExpr(Rvalue(r.mode)) + } + }; + Datum(self.val, self.ty, kind) + } + } /** diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 6a9ee514f8fe7..89cb7878cb6f2 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -292,15 +292,11 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) { pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| { let var_ident = ast_util::path_to_ident(path_ref); - let datum = { - let lllocals = bcx.fcx.lllocals.borrow(); - match lllocals.get().find_copy(&node_id) { - Some(datum) => datum, - None => { - bcx.tcx().sess.span_bug(span, - format!("no entry in lllocals table for {:?}", - node_id)); - } + let datum = match bcx.fcx.locals.borrow().get().find(&node_id) { + Some(datum) => datum.to_lvalue_or_pod_rvalue_datum(bcx), + None => { + bcx.tcx().sess.span_bug(span, + format!("no entry in locals table for {:?}", node_id)); } }; @@ -434,19 +430,15 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) { let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata; pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| { - let llarg = { - let llargs = bcx.fcx.llargs.borrow(); - match llargs.get().find_copy(&node_id) { - Some(v) => v, - None => { - bcx.tcx().sess.span_bug(span, - format!("no entry in llargs table for {:?}", - node_id)); - } + let datum = match bcx.fcx.locals.borrow().get().find(&node_id) { + Some(datum) => datum.to_lvalue_or_pod_rvalue_datum(bcx), + None => { + bcx.tcx().sess.span_bug(span, + format!("no entry in llargs table for {:?}", node_id)); } }; - if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() { + if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null() { cx.sess.span_bug(span, "debuginfo::create_argument_metadata() - \ Referenced variable location is not an alloca!"); } @@ -462,9 +454,9 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) { declare_local(bcx, argument_ident, - llarg.ty, + datum.ty, scope_metadata, - DirectVariable { alloca: llarg.val }, + DirectVariable { alloca: datum.val }, ArgumentVariable(argument_index), span); }) diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 794964e105404..5b2d418c89782 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -68,7 +68,6 @@ use middle::trans::machine::llsize_of; use middle::trans::type_::Type; -use std::hashmap::HashMap; use std::vec; use syntax::ast; use syntax::ast_map; @@ -633,7 +632,7 @@ fn trans_def<'a>(bcx: &'a Block<'a>, DatumBlock(bcx, Datum(val, const_ty, LvalueExpr)) } _ => { - DatumBlock(bcx, trans_local_var(bcx, def).to_expr_datum()) + DatumBlock(bcx, trans_local_var(bcx, def)) } } } @@ -908,57 +907,36 @@ fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>, DatumBlock(bcx, Datum(llfn, fn_ty, RvalueExpr(Rvalue(ByValue)))) } -pub fn trans_local_var<'a>(bcx: &'a Block<'a>, - def: ast::Def) - -> Datum { - /*! - * Translates a reference to a local variable or argument. - * This always results in an lvalue datum. - */ - +/// Translates a reference to a local variable or argument. +pub fn trans_local_var<'a>(bcx: &'a Block<'a>, def: ast::Def) -> Datum { let _icx = push_ctxt("trans_local_var"); - return match def { - ast::DefUpvar(nid, _, _, _) => { + match def { + ast::DefUpvar(id, _, _, _) => { // Can't move upvars, so this is never a ZeroMemLastUse. - let local_ty = node_id_type(bcx, nid); + let local_ty = node_id_type(bcx, id); let llupvars = bcx.fcx.llupvars.borrow(); - match llupvars.get().find(&nid) { - Some(&val) => Datum(val, local_ty, Lvalue), + match llupvars.get().find(&id) { + Some(&val) => Datum(val, local_ty, LvalueExpr), None => { bcx.sess().bug(format!( - "trans_local_var: no llval for upvar {:?} found", nid)); + "trans_local_var: no llval for upvar {} found", id)); } } } - ast::DefArg(nid, _) => { - let llargs = bcx.fcx.llargs.borrow(); - take_local(bcx, llargs.get(), nid) - } - ast::DefLocal(nid, _) | ast::DefBinding(nid, _) => { - let lllocals = bcx.fcx.lllocals.borrow(); - take_local(bcx, lllocals.get(), nid) + ast::DefArg(id, _) | ast::DefLocal(id, _) | ast::DefBinding(id, _) => { + match bcx.fcx.locals.borrow().get().find(&id) { + Some(datum) => datum.to_lvalue_or_pod_rvalue_datum(bcx), + None => { + bcx.sess().bug(format!( + "trans_local_var: no datum for local/arg {} found", id)); + } + } } _ => { bcx.sess().unimpl(format!( "unsupported def type in trans_local_var: {:?}", def)); } - }; - - fn take_local<'a>(bcx: &'a Block<'a>, - table: &HashMap>, - nid: ast::NodeId) - -> Datum { - let datum = match table.find(&nid) { - Some(&v) => v, - None => { - bcx.sess().bug(format!( - "trans_local_var: no datum for local/arg {:?} found", nid)); - } - }; - debug!("take_local(nid={:?}, v={}, ty={})", - nid, bcx.val_to_str(datum.val), bcx.ty_to_str(datum.ty)); - datum } }