From d98d50832c8520e7e0284c4d199b305ec0066de2 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 4 Feb 2015 17:16:59 +0100 Subject: [PATCH 1/3] debuginfo: Assign debuginfo source locations to lang-item calls. --- src/librustc_trans/trans/_match.rs | 113 +++++++++++++++--------- src/librustc_trans/trans/base.rs | 15 ++-- src/librustc_trans/trans/callee.rs | 87 ++++++++++-------- src/librustc_trans/trans/cleanup.rs | 15 ++-- src/librustc_trans/trans/controlflow.rs | 19 ++-- src/librustc_trans/trans/debuginfo.rs | 2 +- src/librustc_trans/trans/expr.rs | 29 ++++-- src/librustc_trans/trans/glue.rs | 38 +++++--- src/librustc_trans/trans/meth.rs | 2 +- src/librustc_trans/trans/tvec.rs | 6 +- 10 files changed, 199 insertions(+), 127 deletions(-) diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 1fea8f6aa3b..b171f00d74f 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -244,25 +244,29 @@ impl<'a> ConstantExpr<'a> { // An option identifying a branch (either a literal, an enum variant or a range) #[derive(Debug)] enum Opt<'a, 'tcx> { - ConstantValue(ConstantExpr<'a>), - ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>), - Variant(ty::Disr, Rc>, ast::DefId), - SliceLengthEqual(uint), - SliceLengthGreaterOrEqual(/* prefix length */ uint, /* suffix length */ uint), + ConstantValue(ConstantExpr<'a>, DebugLoc), + ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>, DebugLoc), + Variant(ty::Disr, Rc>, ast::DefId, DebugLoc), + SliceLengthEqual(uint, DebugLoc), + SliceLengthGreaterOrEqual(/* prefix length */ uint, + /* suffix length */ uint, + DebugLoc), } impl<'a, 'tcx> Opt<'a, 'tcx> { fn eq(&self, other: &Opt<'a, 'tcx>, tcx: &ty::ctxt<'tcx>) -> bool { match (self, other) { - (&ConstantValue(a), &ConstantValue(b)) => a.eq(b, tcx), - (&ConstantRange(a1, a2), &ConstantRange(b1, b2)) => { + (&ConstantValue(a, _), &ConstantValue(b, _)) => a.eq(b, tcx), + (&ConstantRange(a1, a2, _), &ConstantRange(b1, b2, _)) => { a1.eq(b1, tcx) && a2.eq(b2, tcx) } - (&Variant(a_disr, ref a_repr, a_def), &Variant(b_disr, ref b_repr, b_def)) => { + (&Variant(a_disr, ref a_repr, a_def, _), + &Variant(b_disr, ref b_repr, b_def, _)) => { a_disr == b_disr && *a_repr == *b_repr && a_def == b_def } - (&SliceLengthEqual(a), &SliceLengthEqual(b)) => a == b, - (&SliceLengthGreaterOrEqual(a1, a2), &SliceLengthGreaterOrEqual(b1, b2)) => { + (&SliceLengthEqual(a, _), &SliceLengthEqual(b, _)) => a == b, + (&SliceLengthGreaterOrEqual(a1, a2, _), + &SliceLengthGreaterOrEqual(b1, b2, _)) => { a1 == b1 && a2 == b2 } _ => false @@ -273,29 +277,39 @@ impl<'a, 'tcx> Opt<'a, 'tcx> { let _icx = push_ctxt("match::trans_opt"); let ccx = bcx.ccx(); match *self { - ConstantValue(ConstantExpr(lit_expr)) => { + ConstantValue(ConstantExpr(lit_expr), _) => { let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id); let (llval, _) = consts::const_expr(ccx, &*lit_expr); let lit_datum = immediate_rvalue(llval, lit_ty); let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx)); SingleResult(Result::new(bcx, lit_datum.val)) } - ConstantRange(ConstantExpr(ref l1), ConstantExpr(ref l2)) => { + ConstantRange(ConstantExpr(ref l1), ConstantExpr(ref l2), _) => { let (l1, _) = consts::const_expr(ccx, &**l1); let (l2, _) = consts::const_expr(ccx, &**l2); RangeResult(Result::new(bcx, l1), Result::new(bcx, l2)) } - Variant(disr_val, ref repr, _) => { + Variant(disr_val, ref repr, _, _) => { adt::trans_case(bcx, &**repr, disr_val) } - SliceLengthEqual(length) => { + SliceLengthEqual(length, _) => { SingleResult(Result::new(bcx, C_uint(ccx, length))) } - SliceLengthGreaterOrEqual(prefix, suffix) => { + SliceLengthGreaterOrEqual(prefix, suffix, _) => { LowerBound(Result::new(bcx, C_uint(ccx, prefix + suffix))) } } } + + fn debug_loc(&self) -> DebugLoc { + match *self { + ConstantValue(_,debug_loc) | + ConstantRange(_, _, debug_loc) | + Variant(_, _, _, debug_loc) | + SliceLengthEqual(_, debug_loc) | + SliceLengthGreaterOrEqual(_, _, debug_loc) => debug_loc + } + } } #[derive(Copy, PartialEq)] @@ -527,18 +541,18 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( let _indenter = indenter(); let ctor = match opt { - &ConstantValue(ConstantExpr(expr)) => check_match::ConstantValue( + &ConstantValue(ConstantExpr(expr), _) => check_match::ConstantValue( const_eval::eval_const_expr(bcx.tcx(), &*expr) ), - &ConstantRange(ConstantExpr(lo), ConstantExpr(hi)) => check_match::ConstantRange( + &ConstantRange(ConstantExpr(lo), ConstantExpr(hi), _) => check_match::ConstantRange( const_eval::eval_const_expr(bcx.tcx(), &*lo), const_eval::eval_const_expr(bcx.tcx(), &*hi) ), - &SliceLengthEqual(n) => + &SliceLengthEqual(n, _) => check_match::Slice(n), - &SliceLengthGreaterOrEqual(before, after) => + &SliceLengthGreaterOrEqual(before, after, _) => check_match::SliceWithSubslice(before, after), - &Variant(_, _, def_id) => + &Variant(_, _, def_id, _) => check_match::Constructor::Variant(def_id) }; @@ -563,27 +577,34 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let mut found: Vec = vec![]; for br in m { let cur = br.pats[col]; + let debug_loc = DebugLoc::At(cur.id, cur.span); + let opt = match cur.node { - ast::PatLit(ref l) => ConstantValue(ConstantExpr(&**l)), + ast::PatLit(ref l) => { + ConstantValue(ConstantExpr(&**l), debug_loc) + } ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => { // This is either an enum variant or a variable binding. let opt_def = tcx.def_map.borrow().get(&cur.id).cloned(); match opt_def { Some(def::DefVariant(enum_id, var_id, _)) => { let variant = ty::enum_variant_with_id(tcx, enum_id, var_id); - Variant(variant.disr_val, adt::represent_node(bcx, cur.id), var_id) + Variant(variant.disr_val, + adt::represent_node(bcx, cur.id), + var_id, + debug_loc) } _ => continue } } ast::PatRange(ref l1, ref l2) => { - ConstantRange(ConstantExpr(&**l1), ConstantExpr(&**l2)) + ConstantRange(ConstantExpr(&**l1), ConstantExpr(&**l2), debug_loc) } ast::PatVec(ref before, None, ref after) => { - SliceLengthEqual(before.len() + after.len()) + SliceLengthEqual(before.len() + after.len(), debug_loc) } ast::PatVec(ref before, Some(_), ref after) => { - SliceLengthGreaterOrEqual(before.len(), after.len()) + SliceLengthGreaterOrEqual(before.len(), after.len(), debug_loc) } _ => continue }; @@ -779,19 +800,21 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, - rhs_t: Ty<'tcx>) + rhs_t: Ty<'tcx>, + debug_loc: DebugLoc) -> Result<'blk, 'tcx> { fn compare_str<'blk, 'tcx>(cx: Block<'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, - rhs_t: Ty<'tcx>) + rhs_t: Ty<'tcx>, + debug_loc: DebugLoc) -> Result<'blk, 'tcx> { let did = langcall(cx, None, &format!("comparison of `{}`", cx.ty_to_string(rhs_t))[], StrEqFnLangItem); - callee::trans_lang_call(cx, did, &[lhs, rhs], None) + callee::trans_lang_call(cx, did, &[lhs, rhs], None, debug_loc) } let _icx = push_ctxt("compare_values"); @@ -802,7 +825,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, match rhs_t.sty { ty::ty_rptr(_, mt) => match mt.ty.sty { - ty::ty_str => compare_str(cx, lhs, rhs, rhs_t), + ty::ty_str => compare_str(cx, lhs, rhs, rhs_t, debug_loc), ty::ty_vec(ty, _) => match ty.sty { ty::ty_uint(ast::TyU8) => { // NOTE: cast &[u8] to &str and abuse the str_eq lang item, @@ -812,7 +835,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ast::MutImmutable); let lhs = BitCast(cx, lhs, type_of::type_of(cx.ccx(), t).ptr_to()); let rhs = BitCast(cx, rhs, type_of::type_of(cx.ccx(), t).ptr_to()); - compare_str(cx, lhs, rhs, rhs_t) + compare_str(cx, lhs, rhs, rhs_t, debug_loc) }, _ => cx.sess().bug("only byte strings supported in compare_values"), }, @@ -1044,7 +1067,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, debug!("test_val={}", bcx.val_to_string(test_val)); if opts.len() > 0 { match opts[0] { - ConstantValue(_) | ConstantRange(_, _) => { + ConstantValue(..) | ConstantRange(..) => { test_val = load_if_immediate(bcx, val, left_ty); kind = if ty::type_is_integral(left_ty) { Switch @@ -1052,12 +1075,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Compare }; } - Variant(_, ref repr, _) => { + Variant(_, ref repr, _, _) => { let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val); kind = the_kind; if let Some(tval) = val_opt { test_val = tval; } } - SliceLengthEqual(_) | SliceLengthGreaterOrEqual(_, _) => { + SliceLengthEqual(..) | SliceLengthGreaterOrEqual(..) => { let (_, len) = tvec::get_base_and_len(bcx, val, left_ty); test_val = len; kind = Switch; @@ -1066,8 +1089,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } for o in &opts { match *o { - ConstantRange(_, _) => { kind = Compare; break }, - SliceLengthGreaterOrEqual(_, _) => { kind = CompareSliceLength; break }, + ConstantRange(..) => { kind = Compare; break }, + SliceLengthGreaterOrEqual(..) => { kind = CompareSliceLength; break }, _ => () } } @@ -1093,10 +1116,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, // for the current conditional branch. let mut branch_chk = None; let mut opt_cx = else_cx; + let debug_loc = opt.debug_loc(); + if !exhaustive || i + 1 < len { opt_cx = bcx.fcx.new_temp_block("match_case"); match kind { - Single => Br(bcx, opt_cx.llbb, DebugLoc::None), + Single => Br(bcx, opt_cx.llbb, debug_loc), Switch => { match opt.trans(bcx) { SingleResult(r) => { @@ -1119,7 +1144,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let Result { bcx: after_cx, val: matches } = { match opt.trans(bcx) { SingleResult(Result { bcx, val }) => { - compare_values(bcx, test_val, val, t) + compare_values(bcx, test_val, val, t, debug_loc) } RangeResult(Result { val: vbegin, .. }, Result { bcx, val: vend }) => { @@ -1131,7 +1156,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, compare_scalar_types( bcx, test_val, vend, t, ast::BiLe); - Result::new(bcx, And(bcx, llge, llle, DebugLoc::None)) + Result::new(bcx, And(bcx, llge, llle, debug_loc)) } LowerBound(Result { bcx, val }) => { compare_scalar_types(bcx, test_val, val, t, ast::BiGe) @@ -1149,37 +1174,37 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, if i + 1 < len && (guarded || multi_pats || kind == CompareSliceLength) { branch_chk = Some(JumpToBasicBlock(bcx.llbb)); } - CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb, DebugLoc::None); + CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb, debug_loc); } _ => () } } else if kind == Compare || kind == CompareSliceLength { - Br(bcx, else_cx.llbb, DebugLoc::None); + Br(bcx, else_cx.llbb, debug_loc); } let mut size = 0; let mut unpacked = Vec::new(); match *opt { - Variant(disr_val, ref repr, _) => { + Variant(disr_val, ref repr, _, _) => { let ExtractedBlock {vals: argvals, bcx: new_bcx} = extract_variant_args(opt_cx, &**repr, disr_val, val); size = argvals.len(); unpacked = argvals; opt_cx = new_bcx; } - SliceLengthEqual(len) => { + SliceLengthEqual(len, _) => { let args = extract_vec_elems(opt_cx, left_ty, len, 0, val); size = args.vals.len(); unpacked = args.vals.clone(); opt_cx = args.bcx; } - SliceLengthGreaterOrEqual(before, after) => { + SliceLengthGreaterOrEqual(before, after, _) => { let args = extract_vec_elems(opt_cx, left_ty, before, after, val); size = args.vals.len(); unpacked = args.vals.clone(); opt_cx = args.bcx; } - ConstantValue(_) | ConstantRange(_, _) => () + ConstantValue(..) | ConstantRange(..) => () } let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val); let mut opt_vals = unpacked; diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 38051a647ca..6f9dc12a26d 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -57,7 +57,7 @@ use trans::closure; use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral}; use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef}; use trans::common::{CrateContext, ExternMap, FunctionContext}; -use trans::common::{Result}; +use trans::common::{Result, NodeIdAndSpan}; use trans::common::{node_id_type, return_type_is_void}; use trans::common::{tydesc_info, type_is_immediate}; use trans::common::{type_is_zero_size, val_ty}; @@ -379,7 +379,8 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llty_ptr: Type, info_ty: Ty<'tcx>, size: ValueRef, - align: ValueRef) + align: ValueRef, + debug_loc: DebugLoc) -> Result<'blk, 'tcx> { let _icx = push_ctxt("malloc_raw_exchange"); @@ -387,7 +388,8 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let r = callee::trans_lang_call(bcx, require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem), &[size, align], - None); + None, + debug_loc); Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr)) } @@ -851,7 +853,7 @@ pub fn cast_shift_rhs(op: ast::BinOp, pub fn fail_if_zero_or_overflows<'blk, 'tcx>( cx: Block<'blk, 'tcx>, - span: Span, + call_info: NodeIdAndSpan, divrem: ast::BinOp, lhs: ValueRef, rhs: ValueRef, @@ -879,7 +881,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( } }; let bcx = with_cond(cx, is_zero, |bcx| { - controlflow::trans_fail(bcx, span, InternedString::new(zero_text)) + controlflow::trans_fail(bcx, call_info, InternedString::new(zero_text)) }); // To quote LLVM's documentation for the sdiv instruction: @@ -913,7 +915,8 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( let is_min = ICmp(bcx, llvm::IntEQ, lhs, C_integral(llty, min, true)); with_cond(bcx, is_min, |bcx| { - controlflow::trans_fail(bcx, span, + controlflow::trans_fail(bcx, + call_info, InternedString::new(overflow_text)) }) }) diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 5f383d54a68..4a0c2147ddb 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -36,8 +36,8 @@ use trans::callee; use trans::cleanup; use trans::cleanup::CleanupMethods; use trans::closure; -use trans::common; -use trans::common::*; +use trans::common::{self, Block, Result, NodeIdAndSpan, ExprId, CrateContext, + ExprOrMethodCall, FunctionContext, MethodCallKey}; use trans::consts; use trans::datum::*; use trans::debuginfo::{DebugLoc, ToDebugLoc}; @@ -136,7 +136,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) ref_expr: &ast::Expr) -> Callee<'blk, 'tcx> { debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx())); - let expr_ty = node_id_type(bcx, ref_expr.id); + let expr_ty = common::node_id_type(bcx, ref_expr.id); match def { def::DefFn(did, _) if { let maybe_def_id = inline::get_local_instance(bcx.ccx(), did); @@ -147,8 +147,9 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) _ => false } } => { - let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), - bcx.fcx.param_substs); + let substs = common::node_id_substs(bcx.ccx(), + ExprId(ref_expr.id), + bcx.fcx.param_substs); Callee { bcx: bcx, data: NamedTupleConstructor(substs, 0) @@ -158,8 +159,9 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic, _ => false } => { - let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), - bcx.fcx.param_substs); + let substs = common::node_id_substs(bcx.ccx(), + ExprId(ref_expr.id), + bcx.fcx.param_substs); let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did); Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) } } @@ -178,8 +180,9 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } def::DefVariant(tid, vid, _) => { let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid); - let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), - bcx.fcx.param_substs); + let substs = common::node_id_substs(bcx.ccx(), + ExprId(ref_expr.id), + bcx.fcx.param_substs); // Nullary variants are not callable assert!(vinfo.args.len() > 0); @@ -190,8 +193,9 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } } def::DefStruct(_) => { - let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), - bcx.fcx.param_substs); + let substs = common::node_id_substs(bcx.ccx(), + ExprId(ref_expr.id), + bcx.fcx.param_substs); Callee { bcx: bcx, data: NamedTupleConstructor(substs, 0) @@ -226,7 +230,7 @@ pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> Datum<'tcx, Rvalue> { let _icx = push_ctxt("trans_fn_ref"); - let substs = node_id_substs(ccx, node, param_substs); + let substs = common::node_id_substs(ccx, node, param_substs); debug!("trans_fn_ref(def_id={}, node={:?}, substs={})", def_id.repr(ccx.tcx()), node, @@ -269,7 +273,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( let _icx = push_ctxt("trans_fn_pointer_shim"); let tcx = ccx.tcx(); - let bare_fn_ty = erase_regions(tcx, &bare_fn_ty); + let bare_fn_ty = common::erase_regions(tcx, &bare_fn_ty); match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty) { Some(&llval) => { return llval; } None => { } @@ -352,7 +356,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( ); bcx = trans_call_inner(bcx, - None, + DebugLoc::None, bare_fn_ty, |bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) }, ArgVals(&llargs[]), @@ -515,7 +519,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( param_substs, &ref_ty); let llptrty = type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to(); - if llptrty != val_ty(val) { + if llptrty != common::val_ty(val) { let val = consts::ptrcast(val, llptrty); return Datum::new(val, ref_ty, Rvalue::new(ByValue)); } @@ -563,7 +567,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( // other weird situations. Annoying. let llty = type_of::type_of_fn_from_ty(ccx, fn_type); let llptrty = llty.ptr_to(); - if val_ty(val) != llptrty { + if common::val_ty(val) != llptrty { debug!("trans_fn_ref_with_vtables(): casting pointer!"); val = consts::ptrcast(val, llptrty); } else { @@ -577,34 +581,34 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( // Translating calls pub fn trans_call<'a, 'blk, 'tcx>(in_cx: Block<'blk, 'tcx>, - call_ex: &ast::Expr, + call_expr: &ast::Expr, f: &ast::Expr, args: CallArgs<'a, 'tcx>, dest: expr::Dest) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_call"); trans_call_inner(in_cx, - Some(common::expr_info(call_ex)), - expr_ty_adjusted(in_cx, f), + call_expr.debug_loc(), + common::expr_ty_adjusted(in_cx, f), |cx, _| trans(cx, f), args, Some(dest)).bcx } pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - call_ex: &ast::Expr, + call_expr: &ast::Expr, rcvr: &ast::Expr, args: CallArgs<'a, 'tcx>, dest: expr::Dest) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_method_call"); - debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx())); - let method_call = MethodCall::expr(call_ex.id); + debug!("trans_method_call(call_expr={})", call_expr.repr(bcx.tcx())); + let method_call = MethodCall::expr(call_expr.id); let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; trans_call_inner( bcx, - Some(common::expr_info(call_ex)), - monomorphize_type(bcx, method_ty), + call_expr.debug_loc(), + common::monomorphize_type(bcx, method_ty), |cx, arg_cleanup_scope| { meth::trans_method_callee(cx, method_call, Some(rcvr), arg_cleanup_scope) }, @@ -615,7 +619,8 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, did: ast::DefId, args: &[ValueRef], - dest: Option) + dest: Option, + debug_loc: DebugLoc) -> Result<'blk, 'tcx> { let fty = if did.krate == ast::LOCAL_CRATE { ty::node_id_to_type(bcx.tcx(), did.node) @@ -623,7 +628,7 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, csearch::get_type(bcx.tcx(), did).ty }; callee::trans_call_inner(bcx, - None, + debug_loc, fty, |bcx, _| { trans_fn_ref_with_substs_to_callee(bcx, @@ -646,7 +651,7 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// For non-lang items, `dest` is always Some, and hence the result is written into memory /// somewhere. Nonetheless we return the actual return value of the function. pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, - call_info: Option, + debug_loc: DebugLoc, callee_ty: Ty<'tcx>, get_callee: F, args: CallArgs<'a, 'tcx>, @@ -687,7 +692,13 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, assert!(abi == synabi::RustIntrinsic); assert!(dest.is_some()); - let call_info = call_info.expect("no call info for intrinsic call?"); + let call_info = match debug_loc { + DebugLoc::At(id, span) => NodeIdAndSpan { id: id, span: span }, + DebugLoc::None => { + bcx.sess().bug("No call info for intrinsic call?") + } + }; + return intrinsic::trans_intrinsic_call(bcx, node, callee_ty, arg_cleanup_scope, args, dest.unwrap(), substs, @@ -703,7 +714,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, disr, args, dest.unwrap(), - call_info.debug_loc()); + debug_loc); } }; @@ -724,12 +735,12 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }; if !is_rust_fn || type_of::return_uses_outptr(ccx, ret_ty) || - type_needs_drop(bcx.tcx(), ret_ty) { + common::type_needs_drop(bcx.tcx(), ret_ty) { // Push the out-pointer if we use an out-pointer for this // return type, otherwise push "undef". - if type_is_zero_size(ccx, ret_ty) { + if common::type_is_zero_size(ccx, ret_ty) { let llty = type_of::type_of(ccx, ret_ty); - Some(C_undef(llty.ptr_to())) + Some(common::C_undef(llty.ptr_to())) } else { Some(alloc_ty(bcx, ret_ty, "__llret")) } @@ -781,7 +792,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, llfn, &llargs[], callee_ty, - call_info.debug_loc()); + debug_loc); bcx = b; llresult = llret; @@ -790,7 +801,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, match (opt_llretslot, ret_ty) { (Some(llretslot), ty::FnConverging(ret_ty)) => { if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) && - !type_is_zero_size(bcx.ccx(), ret_ty) + !common::type_is_zero_size(bcx.ccx(), ret_ty) { store_ty(bcx, llret, llretslot, ret_ty) } @@ -804,7 +815,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let mut llargs = Vec::new(); let arg_tys = match args { - ArgExprs(a) => a.iter().map(|x| expr_ty(bcx, &**x)).collect(), + ArgExprs(a) => a.iter().map(|x| common::expr_ty(bcx, &**x)).collect(), _ => panic!("expected arg exprs.") }; bcx = trans_args(bcx, @@ -831,7 +842,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, bcx = glue::drop_ty(bcx, llretslot, ret_ty, - call_info.debug_loc()); + debug_loc); call_lifetime_end(bcx, llretslot); } _ => {} @@ -892,7 +903,7 @@ fn trans_args_under_call_abi<'blk, 'tcx>( // Now untuple the rest of the arguments. let tuple_expr = &arg_exprs[1]; - let tuple_type = node_id_type(bcx, tuple_expr.id); + let tuple_type = common::node_id_type(bcx, tuple_expr.id); match tuple_type.sty { ty::ty_tup(ref field_types) => { @@ -1014,7 +1025,7 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, } let arg_ty = if i >= num_formal_args { assert!(variadic); - expr_ty_adjusted(cx, &**arg_expr) + common::expr_ty_adjusted(cx, &**arg_expr) } else { arg_tys[i] }; diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index ac76b52598d..bebba151a0d 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -940,11 +940,12 @@ impl<'tcx> Cleanup<'tcx> for FreeValue<'tcx> { bcx: Block<'blk, 'tcx>, debug_loc: DebugLoc) -> Block<'blk, 'tcx> { - debug_loc.apply(bcx.fcx); - match self.heap { HeapExchange => { - glue::trans_exchange_free_ty(bcx, self.ptr, self.content_ty) + glue::trans_exchange_free_ty(bcx, + self.ptr, + self.content_ty, + debug_loc) } } } @@ -975,11 +976,13 @@ impl<'tcx> Cleanup<'tcx> for FreeSlice { bcx: Block<'blk, 'tcx>, debug_loc: DebugLoc) -> Block<'blk, 'tcx> { - debug_loc.apply(bcx.fcx); - match self.heap { HeapExchange => { - glue::trans_exchange_free_dyn(bcx, self.ptr, self.size, self.align) + glue::trans_exchange_free_dyn(bcx, + self.ptr, + self.size, + self.align, + debug_loc) } } } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 651058a5674..8004726d25e 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -28,7 +28,6 @@ use util::ppaux::Repr; use syntax::ast; use syntax::ast::Ident; use syntax::ast_util; -use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::parse::token; use syntax::visit::Visitor; @@ -361,31 +360,32 @@ pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - sp: Span, + call_info: NodeIdAndSpan, fail_str: InternedString) -> Block<'blk, 'tcx> { let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_value"); let v_str = C_str_slice(ccx, fail_str); - let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); + let loc = bcx.sess().codemap().lookup_char_pos(call_info.span.lo); let filename = token::intern_and_get_ident(&loc.file.name[]); let filename = C_str_slice(ccx, filename); let line = C_uint(ccx, loc.line); let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); let expr_file_line = consts::const_addr_of(ccx, expr_file_line_const, ast::MutImmutable); let args = vec!(expr_file_line); - let did = langcall(bcx, Some(sp), "", PanicFnLangItem); + let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem); let bcx = callee::trans_lang_call(bcx, did, &args[], - Some(expr::Ignore)).bcx; + Some(expr::Ignore), + call_info.debug_loc()).bcx; Unreachable(bcx); return bcx; } pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - sp: Span, + call_info: NodeIdAndSpan, index: ValueRef, len: ValueRef) -> Block<'blk, 'tcx> { @@ -393,7 +393,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_fail_bounds_check"); // Extract the file/line from the span - let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); + let loc = bcx.sess().codemap().lookup_char_pos(call_info.span.lo); let filename = token::intern_and_get_ident(&loc.file.name[]); // Invoke the lang item @@ -402,11 +402,12 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let file_line_const = C_struct(ccx, &[filename, line], false); let file_line = consts::const_addr_of(ccx, file_line_const, ast::MutImmutable); let args = vec!(file_line, index, len); - let did = langcall(bcx, Some(sp), "", PanicBoundsCheckFnLangItem); + let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem); let bcx = callee::trans_lang_call(bcx, did, &args[], - Some(expr::Ignore)).bcx; + Some(expr::Ignore), + call_info.debug_loc()).bcx; Unreachable(bcx); return bcx; } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 1e788351172..a6a7422778a 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -1113,7 +1113,7 @@ pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum DebugLoc { At(ast::NodeId, Span), None diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index dea34baad37..154d54c3d73 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -586,7 +586,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let contents_ty = expr_ty(bcx, &**contents); match box_ty.sty { ty::ty_uniq(..) => { - trans_uniq_expr(bcx, box_ty, &**contents, contents_ty) + trans_uniq_expr(bcx, expr, box_ty, &**contents, contents_ty) } _ => bcx.sess().span_bug(expr.span, "expected unique box") @@ -787,7 +787,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, index_expr.debug_loc()); bcx = with_cond(bcx, expected, |bcx| { controlflow::trans_fail_bounds_check(bcx, - index_expr.span, + expr_info(index_expr), ix_val, len) }); @@ -1574,7 +1574,7 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock() } ast::UnUniq => { - trans_uniq_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr)) + trans_uniq_expr(bcx, expr, un_ty, sub_expr, expr_ty(bcx, sub_expr)) } ast::UnDeref => { let datum = unpack_datum!(bcx, trans(bcx, sub_expr)); @@ -1584,6 +1584,7 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + box_expr: &ast::Expr, box_ty: Ty<'tcx>, contents: &ast::Expr, contents_ty: Ty<'tcx>) @@ -1595,7 +1596,12 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let size = llsize_of(bcx.ccx(), llty); let align = C_uint(bcx.ccx(), type_of::align_of(bcx.ccx(), contents_ty)); let llty_ptr = llty.ptr_to(); - let Result { bcx, val } = malloc_raw_dyn(bcx, llty_ptr, box_ty, size, align); + let Result { bcx, val } = malloc_raw_dyn(bcx, + llty_ptr, + box_ty, + size, + align, + box_expr.debug_loc()); // Unique boxes do not allocate for zero-size types. The standard library // may assume that `free` is never called on the pointer returned for // `Box`. @@ -1697,8 +1703,12 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, FDiv(bcx, lhs, rhs, binop_debug_loc) } else { // Only zero-check integers; fp /0 is NaN - bcx = base::fail_if_zero_or_overflows(bcx, binop_expr.span, - op, lhs, rhs, rhs_t); + bcx = base::fail_if_zero_or_overflows(bcx, + expr_info(binop_expr), + op, + lhs, + rhs, + rhs_t); if is_signed { SDiv(bcx, lhs, rhs, binop_debug_loc) } else { @@ -1711,7 +1721,8 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, FRem(bcx, lhs, rhs, binop_debug_loc) } else { // Only zero-check integers; fp %0 is NaN - bcx = base::fail_if_zero_or_overflows(bcx, binop_expr.span, + bcx = base::fail_if_zero_or_overflows(bcx, + expr_info(binop_expr), op, lhs, rhs, rhs_t); if is_signed { SRem(bcx, lhs, rhs, binop_debug_loc) @@ -1845,7 +1856,7 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, -> Result<'blk, 'tcx> { let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; callee::trans_call_inner(bcx, - Some(expr_info(expr)), + expr.debug_loc(), monomorphize_type(bcx, method_ty), |bcx, arg_cleanup_scope| { meth::trans_method_callee(bcx, @@ -1872,7 +1883,7 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, all_args.extend(args.iter().map(|e| &**e)); unpack_result!(bcx, callee::trans_call_inner(bcx, - Some(expr_info(expr)), + expr.debug_loc(), monomorphize_type(bcx, method_type), |bcx, arg_cleanup_scope| { diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 5d26daab5cd..aefa0978dd4 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -45,25 +45,39 @@ use std::ffi::CString; use syntax::ast; use syntax::parse::token; -pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, - size: ValueRef, align: ValueRef) +pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, + v: ValueRef, + size: ValueRef, + align: ValueRef, + debug_loc: DebugLoc) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_exchange_free"); let ccx = cx.ccx(); callee::trans_lang_call(cx, langcall(cx, None, "", ExchangeFreeFnLangItem), &[PointerCast(cx, v, Type::i8p(ccx)), size, align], - Some(expr::Ignore)).bcx + Some(expr::Ignore), + debug_loc).bcx } -pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, - size: u64, align: u32) -> Block<'blk, 'tcx> { - trans_exchange_free_dyn(cx, v, C_uint(cx.ccx(), size), - C_uint(cx.ccx(), align)) +pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>, + v: ValueRef, + size: u64, + align: u32, + debug_loc: DebugLoc) + -> Block<'blk, 'tcx> { + trans_exchange_free_dyn(cx, + v, + C_uint(cx.ccx(), size), + C_uint(cx.ccx(), align), + debug_loc) } -pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, - content_ty: Ty<'tcx>) -> Block<'blk, 'tcx> { +pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + ptr: ValueRef, + content_ty: Ty<'tcx>, + debug_loc: DebugLoc) + -> Block<'blk, 'tcx> { assert!(type_is_sized(bcx.ccx().tcx(), content_ty)); let sizing_type = sizing_type_of(bcx.ccx(), content_ty); let content_size = llsize_of_alloc(bcx.ccx(), sizing_type); @@ -71,7 +85,7 @@ pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, // `Box` does not allocate. if content_size != 0 { let content_align = align_of(bcx.ccx(), content_ty); - trans_exchange_free(bcx, ptr, content_size, content_align) + trans_exchange_free(bcx, ptr, content_size, content_align, debug_loc) } else { bcx } @@ -394,7 +408,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]); let info = Load(bcx, info); let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info); - trans_exchange_free_dyn(bcx, llbox, llsize, llalign) + trans_exchange_free_dyn(bcx, llbox, llsize, llalign, DebugLoc::None) }) } _ => { @@ -404,7 +418,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) let not_null = IsNotNull(bcx, llbox); with_cond(bcx, not_null, |bcx| { let bcx = drop_ty(bcx, llbox, content_ty, DebugLoc::None); - trans_exchange_free_ty(bcx, llbox, content_ty) + trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None) }) } } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 9c440d4509e..5161382a927 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -667,7 +667,7 @@ pub fn trans_object_shim<'a, 'tcx>( method_offset_in_vtable); bcx = trans_call_inner(bcx, - None, + DebugLoc::None, method_bare_fn_ty, |bcx, _| trans_trait_callee_from_llval(bcx, method_bare_fn_ty, diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 66f603cbe07..5930876d15c 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -77,7 +77,11 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, with_cond(bcx, not_empty, |bcx| { let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty)); let size = Mul(bcx, C_uint(ccx, unit_size), len, DebugLoc::None); - glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign) + glue::trans_exchange_free_dyn(bcx, + dataptr, + size, + llalign, + DebugLoc::None) }) } else { bcx From 0eec22640c1f1b6d9360f5a05961f19465ca9e14 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 4 Feb 2015 17:42:32 +0100 Subject: [PATCH 2/3] debuginfo: Implement direct debuginfo source location application for ICmp, FCmp, and CallWithConv. --- src/librustc_trans/trans/_match.rs | 27 +++++++++++++++------- src/librustc_trans/trans/adt.rs | 4 ++-- src/librustc_trans/trans/base.rs | 35 ++++++++++++++++------------- src/librustc_trans/trans/build.rs | 32 ++++++++++++++++++++------ src/librustc_trans/trans/callee.rs | 10 ++++++--- src/librustc_trans/trans/expr.rs | 26 +++++++++++++++++---- src/librustc_trans/trans/foreign.rs | 7 ++++-- src/librustc_trans/trans/glue.rs | 6 ++++- src/librustc_trans/trans/tvec.rs | 10 ++++++--- 9 files changed, 112 insertions(+), 45 deletions(-) diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index b171f00d74f..feea8282f39 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -819,7 +819,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, let _icx = push_ctxt("compare_values"); if ty::type_is_scalar(rhs_t) { - let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq); + let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq, debug_loc); return Result::new(rs.bcx, rs.val); } @@ -1149,17 +1149,28 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, RangeResult(Result { val: vbegin, .. }, Result { bcx, val: vend }) => { let Result { bcx, val: llge } = - compare_scalar_types( - bcx, test_val, - vbegin, t, ast::BiGe); + compare_scalar_types(bcx, + test_val, + vbegin, + t, + ast::BiGe, + debug_loc); let Result { bcx, val: llle } = - compare_scalar_types( - bcx, test_val, vend, - t, ast::BiLe); + compare_scalar_types(bcx, + test_val, + vend, + t, + ast::BiLe, + debug_loc); Result::new(bcx, And(bcx, llge, llle, debug_loc)) } LowerBound(Result { bcx, val }) => { - compare_scalar_types(bcx, test_val, val, t, ast::BiGe) + compare_scalar_types(bcx, + test_val, + val, + t, + ast::BiGe, + debug_loc) } } }; diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 21e52e5fffe..8bb60eca8b1 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -751,7 +751,7 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, RawNullablePointer { nndiscr, nnty, .. } => { let cmp = if nndiscr == 0 { IntEQ } else { IntNE }; let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty); - val = ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty)); + val = ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty), DebugLoc::None); signed = false; } StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => { @@ -770,7 +770,7 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc let llptrptr = GEPi(bcx, scrutinee, &discrfield[]); let llptr = Load(bcx, llptrptr); let cmp = if nndiscr == 0 { IntEQ } else { IntNE }; - ICmp(bcx, cmp, llptr, C_null(val_ty(llptr))) + ICmp(bcx, cmp, llptr, C_null(val_ty(llptr)), DebugLoc::None) } /// Helper for cases where the discriminant is simply loaded. diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 6f9dc12a26d..0aef00e69e3 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -66,7 +66,7 @@ use trans::consts; use trans::context::SharedCrateContext; use trans::controlflow; use trans::datum; -use trans::debuginfo::{self, DebugLoc}; +use trans::debuginfo::{self, DebugLoc, ToDebugLoc}; use trans::expr; use trans::foreign; use trans::glue; @@ -540,9 +540,10 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, t: Ty<'tcx>, - op: ast::BinOp_) + op: ast::BinOp_, + debug_loc: DebugLoc) -> Result<'blk, 'tcx> { - let f = |a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op)); + let f = |a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op, debug_loc)); match t.sty { ty::ty_tup(ref tys) if tys.is_empty() => f(nil_type), @@ -561,7 +562,8 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, nt: scalar_type, - op: ast::BinOp_) + op: ast::BinOp_, + debug_loc: DebugLoc) -> ValueRef { let _icx = push_ctxt("compare_scalar_values"); fn die(cx: Block) -> ! { @@ -588,7 +590,7 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ast::BiGe => llvm::RealOGE, _ => die(cx) }; - return FCmp(cx, cmp, lhs, rhs); + return FCmp(cx, cmp, lhs, rhs, debug_loc); } signed_int => { let cmp = match op { @@ -600,7 +602,7 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ast::BiGe => llvm::IntSGE, _ => die(cx) }; - return ICmp(cx, cmp, lhs, rhs); + return ICmp(cx, cmp, lhs, rhs, debug_loc); } unsigned_int => { let cmp = match op { @@ -612,7 +614,7 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ast::BiGe => llvm::IntUGE, _ => die(cx) }; - return ICmp(cx, cmp, lhs, rhs); + return ICmp(cx, cmp, lhs, rhs, debug_loc); } } } @@ -623,7 +625,8 @@ pub fn compare_simd_types<'blk, 'tcx>( rhs: ValueRef, t: Ty<'tcx>, size: uint, - op: ast::BinOp) + op: ast::BinOp_, + debug_loc: DebugLoc) -> ValueRef { let cmp = match t.sty { ty::ty_float(_) => { @@ -634,7 +637,7 @@ pub fn compare_simd_types<'blk, 'tcx>( cx.sess().bug("compare_simd_types: comparison operators \ not supported for floating point SIMD types") }, - ty::ty_uint(_) => match op.node { + ty::ty_uint(_) => match op { ast::BiEq => llvm::IntEQ, ast::BiNe => llvm::IntNE, ast::BiLt => llvm::IntULT, @@ -643,7 +646,7 @@ pub fn compare_simd_types<'blk, 'tcx>( ast::BiGe => llvm::IntUGE, _ => cx.sess().bug("compare_simd_types: must be a comparison operator"), }, - ty::ty_int(_) => match op.node { + ty::ty_int(_) => match op { ast::BiEq => llvm::IntEQ, ast::BiNe => llvm::IntNE, ast::BiLt => llvm::IntSLT, @@ -659,7 +662,7 @@ pub fn compare_simd_types<'blk, 'tcx>( // to get the correctly sized type. This will compile to a single instruction // once the IR is converted to assembly if the SIMD instruction is supported // by the target architecture. - SExt(cx, ICmp(cx, cmp, lhs, rhs), return_ty) + SExt(cx, ICmp(cx, cmp, lhs, rhs, debug_loc), return_ty) } // Iterates through the elements of a structural type. @@ -866,14 +869,16 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( ("attempted remainder with a divisor of zero", "attempted remainder with overflow") }; + let debug_loc = call_info.debug_loc(); + let (is_zero, is_signed) = match rhs_t.sty { ty::ty_int(t) => { let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0u64, false); - (ICmp(cx, llvm::IntEQ, rhs, zero), true) + (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), true) } ty::ty_uint(t) => { let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0u64, false); - (ICmp(cx, llvm::IntEQ, rhs, zero), false) + (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false) } _ => { cx.sess().bug(&format!("fail-if-zero on unexpected type: {}", @@ -910,10 +915,10 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( _ => unreachable!(), }; let minus_one = ICmp(bcx, llvm::IntEQ, rhs, - C_integral(llty, -1, false)); + C_integral(llty, -1, false), debug_loc); with_cond(bcx, minus_one, |bcx| { let is_min = ICmp(bcx, llvm::IntEQ, lhs, - C_integral(llty, min, true)); + C_integral(llty, min, true), debug_loc); with_cond(bcx, is_min, |bcx| { controlflow::trans_fail(bcx, call_info, diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs index c288a8196e6..2fcfc5e4393 100644 --- a/src/librustc_trans/trans/build.rs +++ b/src/librustc_trans/trans/build.rs @@ -856,22 +856,32 @@ pub fn FPCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { /* Comparisons */ -pub fn ICmp(cx: Block, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) - -> ValueRef { +pub fn ICmp(cx: Block, + op: IntPredicate, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); } + debug_loc.apply(cx.fcx); B(cx).icmp(op, lhs, rhs) } } -pub fn FCmp(cx: Block, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) - -> ValueRef { +pub fn FCmp(cx: Block, + op: RealPredicate, + lhs: ValueRef, + rhs: ValueRef, + debug_loc: DebugLoc) + -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); } + debug_loc.apply(cx.fcx); B(cx).fcmp(op, lhs, rhs) } } @@ -941,9 +951,17 @@ pub fn Call(cx: Block, B(cx).call(fn_, args, attributes) } -pub fn CallWithConv(cx: Block, fn_: ValueRef, args: &[ValueRef], conv: CallConv, - attributes: Option) -> ValueRef { - if cx.unreachable.get() { return _UndefReturn(cx, fn_); } +pub fn CallWithConv(cx: Block, + fn_: ValueRef, + args: &[ValueRef], + conv: CallConv, + attributes: Option, + debug_loc: DebugLoc) + -> ValueRef { + if cx.unreachable.get() { + return _UndefReturn(cx, fn_); + } + debug_loc.apply(cx.fcx); B(cx).call_with_conv(fn_, args, conv, attributes) } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 4a0c2147ddb..e45918ce5a7 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -827,9 +827,13 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, abi); fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); - bcx = foreign::trans_native_call(bcx, callee_ty, - llfn, opt_llretslot.unwrap(), - &llargs[], arg_tys); + bcx = foreign::trans_native_call(bcx, + callee_ty, + llfn, + opt_llretslot.unwrap(), + &llargs[], + arg_tys, + debug_loc); } fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_cleanup_scope); diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 154d54c3d73..9ea7a276d97 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -696,6 +696,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let ccx = bcx.ccx(); let mut bcx = bcx; + let index_expr_debug_loc = index_expr.debug_loc(); + // Check for overloaded index. let method_ty = ccx.tcx() .method_map @@ -778,13 +780,17 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!("trans_index: base {}", bcx.val_to_string(base)); debug!("trans_index: len {}", bcx.val_to_string(len)); - let bounds_check = ICmp(bcx, llvm::IntUGE, ix_val, len); + let bounds_check = ICmp(bcx, + llvm::IntUGE, + ix_val, + len, + index_expr_debug_loc); let expect = ccx.get_intrinsic(&("llvm.expect.i1")); let expected = Call(bcx, expect, &[bounds_check, C_bool(ccx, false)], None, - index_expr.debug_loc()); + index_expr_debug_loc); bcx = with_cond(bcx, expected, |bcx| { controlflow::trans_fail_bounds_check(bcx, expr_info(index_expr), @@ -1744,9 +1750,21 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => { if ty::type_is_scalar(rhs_t) { - unpack_result!(bcx, base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op.node)) + unpack_result!(bcx, + base::compare_scalar_types(bcx, + lhs, + rhs, + rhs_t, + op.node, + binop_debug_loc)) } else if is_simd { - base::compare_simd_types(bcx, lhs, rhs, intype, ty::simd_size(tcx, lhs_t), op) + base::compare_simd_types(bcx, + lhs, + rhs, + intype, + ty::simd_size(tcx, lhs_t), + op.node, + binop_debug_loc) } else { bcx.tcx().sess.span_bug(binop_expr.span, "comparison operator unsupported for type") } diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 48f519398ce..7844594a24d 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -18,6 +18,7 @@ use trans::base; use trans::build::*; use trans::cabi; use trans::common::*; +use trans::debuginfo::DebugLoc; use trans::machine; use trans::monomorphize; use trans::type_::Type; @@ -218,7 +219,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llfn: ValueRef, llretptr: ValueRef, llargs_rust: &[ValueRef], - passed_arg_tys: Vec>) + passed_arg_tys: Vec>, + call_debug_loc: DebugLoc) -> Block<'blk, 'tcx> { let ccx = bcx.ccx(); @@ -370,7 +372,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llfn, &llargs_foreign[], cc, - Some(attrs)); + Some(attrs), + call_debug_loc); // If the function we just called does not use an outpointer, // store the result into the rust outpointer. Cast the outpointer diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index aefa0978dd4..8cf9a51b3bf 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -342,7 +342,11 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: // Return the sum of sizes and max of aligns. let size = Add(bcx, sized_size, unsized_size, DebugLoc::None); let align = Select(bcx, - ICmp(bcx, llvm::IntULT, sized_align, unsized_align), + ICmp(bcx, + llvm::IntULT, + sized_align, + unsized_align, + DebugLoc::None), sized_align, unsized_align); (size, align) diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 5930876d15c..441a5e899ff 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -73,7 +73,11 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let unit_size = llsize_of_alloc(ccx, llty); if unit_size != 0 { let len = get_len(bcx, vptr); - let not_empty = ICmp(bcx, llvm::IntNE, len, C_uint(ccx, 0us)); + let not_empty = ICmp(bcx, + llvm::IntNE, + len, + C_uint(ccx, 0us), + DebugLoc::None); with_cond(bcx, not_empty, |bcx| { let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty)); let size = Mul(bcx, C_uint(ccx, unit_size), len, DebugLoc::None); @@ -443,7 +447,7 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, { // i < count let lhs = Load(cond_bcx, loop_counter); let rhs = count; - let cond_val = ICmp(cond_bcx, llvm::IntULT, lhs, rhs); + let cond_val = ICmp(cond_bcx, llvm::IntULT, lhs, rhs, DebugLoc::None); CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb, DebugLoc::None); } @@ -497,7 +501,7 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let data_ptr = Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.llbb]); let not_yet_at_end = - ICmp(header_bcx, llvm::IntULT, data_ptr, data_end_ptr); + ICmp(header_bcx, llvm::IntULT, data_ptr, data_end_ptr, DebugLoc::None); let body_bcx = fcx.new_temp_block("iter_vec_loop_body"); let next_bcx = fcx.new_temp_block("iter_vec_next"); CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb, DebugLoc::None); From 93edb7c17bd4d2d56b0f1f510de5f820cf61bb5f Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 5 Feb 2015 18:26:58 +0100 Subject: [PATCH 3/3] debuginfo: Fix problem with debug locations of constants in match patterns. --- src/librustc/middle/check_match.rs | 65 ++++++++++--- src/librustc/middle/const_eval.rs | 17 ++-- src/librustc_trans/trans/_match.rs | 45 +++++++-- .../debuginfo/constant-in-match-pattern.rs | 92 +++++++++++++++++++ 4 files changed, 189 insertions(+), 30 deletions(-) create mode 100644 src/test/debuginfo/constant-in-match-pattern.rs diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 418cdf95718..0d2af78ed06 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -28,7 +28,7 @@ use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat}; use std::num::Float; use std::slice; use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat}; -use syntax::ast_util::walk_pat; +use syntax::ast_util; use syntax::codemap::{Span, Spanned, DUMMY_SP}; use syntax::fold::{Folder, noop_fold_pat}; use syntax::print::pprust::pat_to_string; @@ -36,6 +36,7 @@ use syntax::parse::token; use syntax::ptr::P; use syntax::visit::{self, Visitor, FnKind}; use util::ppaux::ty_to_string; +use util::nodemap::FnvHashMap; pub const DUMMY_WILD_PAT: &'static Pat = &Pat { id: DUMMY_NODE_ID, @@ -171,7 +172,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { } } - let mut static_inliner = StaticInliner::new(cx.tcx); + let mut static_inliner = StaticInliner::new(cx.tcx, None); let inlined_arms = arms.iter().map(|arm| { (arm.pats.iter().map(|pat| { static_inliner.fold_pat((*pat).clone()) @@ -235,7 +236,7 @@ fn is_expr_const_nan(tcx: &ty::ctxt, expr: &ast::Expr) -> bool { } fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) { - walk_pat(pat, |p| { + ast_util::walk_pat(pat, |p| { match p.node { ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => { let pat_ty = ty::pat_ty(cx.tcx, p); @@ -266,7 +267,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) // Check that we do not match against a static NaN (#6804) fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) { - walk_pat(pat, |p| { + ast_util::walk_pat(pat, |p| { match p.node { ast::PatLit(ref expr) if is_expr_const_nan(cx.tcx, &**expr) => { span_warn!(cx.tcx.sess, p.span, E0003, @@ -399,28 +400,50 @@ fn const_val_to_expr(value: &const_val) -> P { pub struct StaticInliner<'a, 'tcx: 'a> { pub tcx: &'a ty::ctxt<'tcx>, - pub failed: bool + pub failed: bool, + pub renaming_map: Option<&'a mut FnvHashMap<(NodeId, Span), NodeId>>, } impl<'a, 'tcx> StaticInliner<'a, 'tcx> { - pub fn new<'b>(tcx: &'b ty::ctxt<'tcx>) -> StaticInliner<'b, 'tcx> { + pub fn new<'b>(tcx: &'b ty::ctxt<'tcx>, + renaming_map: Option<&'b mut FnvHashMap<(NodeId, Span), NodeId>>) + -> StaticInliner<'b, 'tcx> { StaticInliner { tcx: tcx, - failed: false + failed: false, + renaming_map: renaming_map } } } +struct RenamingRecorder<'map> { + substituted_node_id: NodeId, + origin_span: Span, + renaming_map: &'map mut FnvHashMap<(NodeId, Span), NodeId> +} + +impl<'map> ast_util::IdVisitingOperation for RenamingRecorder<'map> { + fn visit_id(&mut self, node_id: NodeId) { + let key = (node_id, self.origin_span); + self.renaming_map.insert(key, self.substituted_node_id); + } +} + impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { fn fold_pat(&mut self, pat: P) -> P { - match pat.node { + return match pat.node { ast::PatIdent(..) | ast::PatEnum(..) => { let def = self.tcx.def_map.borrow().get(&pat.id).cloned(); match def { Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) { Some(const_expr) => { - const_expr_to_pat(self.tcx, const_expr).map(|mut new_pat| { - new_pat.span = pat.span; + const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| { + + if let Some(ref mut renaming_map) = self.renaming_map { + // Record any renamings we do here + record_renamings(const_expr, &pat, renaming_map); + } + new_pat }) } @@ -435,6 +458,24 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { } } _ => noop_fold_pat(pat, self) + }; + + fn record_renamings(const_expr: &ast::Expr, + substituted_pat: &ast::Pat, + renaming_map: &mut FnvHashMap<(NodeId, Span), NodeId>) { + let mut renaming_recorder = RenamingRecorder { + substituted_node_id: substituted_pat.id, + origin_span: substituted_pat.span, + renaming_map: renaming_map, + }; + + let mut id_visitor = ast_util::IdVisitor { + operation: &mut renaming_recorder, + pass_through_items: true, + visited_outermost: false, + }; + + id_visitor.visit_expr(const_expr); } } } @@ -953,7 +994,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) { ast::LocalFor => "`for` loop" }; - let mut static_inliner = StaticInliner::new(cx.tcx); + let mut static_inliner = StaticInliner::new(cx.tcx, None); is_refutable(cx, &*static_inliner.fold_pat(loc.pat.clone()), |pat| { span_err!(cx.tcx.sess, loc.pat.span, E0005, "refutable pattern in {} binding: `{}` not covered", @@ -1040,7 +1081,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, }; for pat in pats { - walk_pat(&**pat, |p| { + ast_util::walk_pat(&**pat, |p| { if pat_is_binding(def_map, &*p) { match p.node { ast::PatIdent(ast::BindByValue(_), _, ref sub) => { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index fa5d5227be5..2d764518a47 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -22,6 +22,7 @@ use middle::astconv_util::{ast_ty_to_prim_ty}; use util::nodemap::DefIdMap; use syntax::ast::{self, Expr}; +use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::visit::{self, Visitor}; @@ -304,10 +305,10 @@ pub enum const_val { const_bool(bool) } -pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { +pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P { let pat = match expr.node { ast::ExprTup(ref exprs) => - ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect()), + ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()), ast::ExprCall(ref callee, ref args) => { let def = tcx.def_map.borrow()[callee.id].clone(); @@ -319,7 +320,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did), _ => unreachable!() }; - let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect(); + let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect(); ast::PatEnum(path, Some(pats)) } @@ -328,7 +329,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { span: codemap::DUMMY_SP, node: ast::FieldPat { ident: field.ident.node, - pat: const_expr_to_pat(tcx, &*field.expr), + pat: const_expr_to_pat(tcx, &*field.expr, span), is_shorthand: false, }, }).collect(); @@ -336,7 +337,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { } ast::ExprVec(ref exprs) => { - let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect(); + let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect(); ast::PatVec(pats, None, vec![]) } @@ -349,7 +350,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { ast::PatEnum(path.clone(), None), _ => { match lookup_const(tcx, expr) { - Some(actual) => return const_expr_to_pat(tcx, actual), + Some(actual) => return const_expr_to_pat(tcx, actual, span), _ => unreachable!() } } @@ -358,14 +359,14 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { ast::ExprQPath(_) => { match lookup_const(tcx, expr) { - Some(actual) => return const_expr_to_pat(tcx, actual), + Some(actual) => return const_expr_to_pat(tcx, actual, span), _ => unreachable!() } } _ => ast::PatLit(P(expr.clone())) }; - P(ast::Pat { id: expr.id, node: pat, span: expr.span }) + P(ast::Pat { id: expr.id, node: pat, span: span }) } pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val { diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index feea8282f39..610b6e1aa38 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -213,7 +213,7 @@ use trans::expr::{self, Dest}; use trans::tvec; use trans::type_of; use middle::ty::{self, Ty}; -use session::config::FullDebugInfo; +use session::config::{NoDebugInfo, FullDebugInfo}; use util::common::indenter; use util::nodemap::FnvHashMap; use util::ppaux::{Repr, vec_map_to_string}; @@ -222,7 +222,7 @@ use std; use std::iter::AdditiveIterator; use std::rc::Rc; use syntax::ast; -use syntax::ast::{DUMMY_NODE_ID, Ident}; +use syntax::ast::{DUMMY_NODE_ID, Ident, NodeId}; use syntax::codemap::Span; use syntax::fold::Folder; use syntax::ptr::P; @@ -366,6 +366,9 @@ struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> { pats: Vec<&'p ast::Pat>, data: &'a ArmData<'p, 'blk, 'tcx>, bound_ptrs: Vec<(Ident, ValueRef)>, + // Thread along renamings done by the check_match::StaticInliner, so we can + // map back to original NodeIds + pat_renaming_map: Option<&'a FnvHashMap<(NodeId, Span), NodeId>> } impl<'a, 'p, 'blk, 'tcx> Repr<'tcx> for Match<'a, 'p, 'blk, 'tcx> { @@ -419,7 +422,8 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Match { pats: pats, data: &*br.data, - bound_ptrs: bound_ptrs + bound_ptrs: bound_ptrs, + pat_renaming_map: br.pat_renaming_map, } }).collect() } @@ -463,7 +467,8 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, Match { pats: pats, data: br.data, - bound_ptrs: bound_ptrs + bound_ptrs: bound_ptrs, + pat_renaming_map: br.pat_renaming_map, } }) }).collect() @@ -570,14 +575,23 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( // needs to be conditionally matched at runtime; for example, the discriminant // on a set of enum variants or a literal. fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - m: &[Match<'a, 'p, 'blk, 'tcx>], col: uint) + m: &[Match<'a, 'p, 'blk, 'tcx>], + col: uint) -> Vec> { let tcx = bcx.tcx(); let mut found: Vec = vec![]; for br in m { let cur = br.pats[col]; - let debug_loc = DebugLoc::At(cur.id, cur.span); + let debug_loc = match br.pat_renaming_map { + Some(pat_renaming_map) => { + match pat_renaming_map.get(&(cur.id, cur.span)) { + Some(&id) => DebugLoc::At(id, cur.span), + None => DebugLoc::At(cur.id, cur.span), + } + } + None => DebugLoc::None + }; let opt = match cur.node { ast::PatLit(ref l) => { @@ -1419,16 +1433,27 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, bindings_map: create_bindings_map(bcx, &*arm.pats[0], discr_expr, &*arm.body) }).collect(); - let mut static_inliner = StaticInliner::new(scope_cx.tcx()); - let arm_pats: Vec>> = arm_datas.iter().map(|arm_data| { - arm_data.arm.pats.iter().map(|p| static_inliner.fold_pat((*p).clone())).collect() - }).collect(); + let mut pat_renaming_map = if scope_cx.sess().opts.debuginfo != NoDebugInfo { + Some(FnvHashMap()) + } else { + None + }; + + let arm_pats: Vec>> = { + let mut static_inliner = StaticInliner::new(scope_cx.tcx(), + pat_renaming_map.as_mut()); + arm_datas.iter().map(|arm_data| { + arm_data.arm.pats.iter().map(|p| static_inliner.fold_pat((*p).clone())).collect() + }).collect() + }; + let mut matches = Vec::new(); for (arm_data, pats) in arm_datas.iter().zip(arm_pats.iter()) { matches.extend(pats.iter().map(|p| Match { pats: vec![&**p], data: arm_data, bound_ptrs: Vec::new(), + pat_renaming_map: pat_renaming_map.as_ref() })); } diff --git a/src/test/debuginfo/constant-in-match-pattern.rs b/src/test/debuginfo/constant-in-match-pattern.rs new file mode 100644 index 00000000000..487c69a85d6 --- /dev/null +++ b/src/test/debuginfo/constant-in-match-pattern.rs @@ -0,0 +1,92 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android: FIXME(#10381) +// min-lldb-version: 310 + +// compile-flags:-g + +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] + +// This test makes sure that the compiler doesn't crash when trying to assign +// debug locations to 'constant' patterns in match expressions. + +const CONSTANT: u64 = 3; + +struct Struct { + a: isize, + b: usize, +} +const STRUCT: Struct = Struct { a: 1, b: 2 }; + +struct TupleStruct(u32); +const TUPLE_STRUCT: TupleStruct = TupleStruct(4); + +enum Enum { + Variant1(char), + Variant2 { a: u8 }, + Variant3 +} +const VARIANT1: Enum = Enum::Variant1('v'); +const VARIANT2: Enum = Enum::Variant2 { a: 2 }; +const VARIANT3: Enum = Enum::Variant3; + +const STRING: &'static str = "String"; + +fn main() { + + match 1 { + CONSTANT => {} + _ => {} + }; + + // if let 3 = CONSTANT {} + + match (Struct { a: 2, b: 2 }) { + STRUCT => {} + _ => {} + }; + + // if let STRUCT = STRUCT {} + + match TupleStruct(3) { + TUPLE_STRUCT => {} + _ => {} + }; + + // if let TupleStruct(4) = TUPLE_STRUCT {} + + match VARIANT3 { + VARIANT1 => {}, + VARIANT2 => {}, + VARIANT3 => {}, + _ => {} + }; + + match (VARIANT3, VARIANT2) { + (VARIANT1, VARIANT3) => {}, + (VARIANT2, VARIANT2) => {}, + (VARIANT3, VARIANT1) => {}, + _ => {} + }; + + // if let VARIANT1 = Enum::Variant3 {} + // if let VARIANT2 = Enum::Variant3 {} + // if let VARIANT3 = Enum::Variant3 {} + + match "abc" { + STRING => {}, + _ => {} + } + + if let STRING = "def" {} +}