1
Fork 0

Auto merge of #21970 - michaelwoerister:lang-item-call-debug-locs, r=brson

Resolves some issues caused by the recent LLVM update (which itself solved some issues).

Closes #19848
Closes #20798
This commit is contained in:
bors 2015-02-08 10:27:58 +00:00
commit d4a66e9b09
16 changed files with 499 additions and 201 deletions

View file

@ -28,7 +28,7 @@ use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat};
use std::num::Float; use std::num::Float;
use std::slice; use std::slice;
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat}; 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::codemap::{Span, Spanned, DUMMY_SP};
use syntax::fold::{Folder, noop_fold_pat}; use syntax::fold::{Folder, noop_fold_pat};
use syntax::print::pprust::pat_to_string; use syntax::print::pprust::pat_to_string;
@ -36,6 +36,7 @@ use syntax::parse::token;
use syntax::ptr::P; use syntax::ptr::P;
use syntax::visit::{self, Visitor, FnKind}; use syntax::visit::{self, Visitor, FnKind};
use util::ppaux::ty_to_string; use util::ppaux::ty_to_string;
use util::nodemap::FnvHashMap;
pub const DUMMY_WILD_PAT: &'static Pat = &Pat { pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
id: DUMMY_NODE_ID, 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| { let inlined_arms = arms.iter().map(|arm| {
(arm.pats.iter().map(|pat| { (arm.pats.iter().map(|pat| {
static_inliner.fold_pat((*pat).clone()) 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) { 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 { match p.node {
ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => { ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
let pat_ty = ty::pat_ty(cx.tcx, p); 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) // Check that we do not match against a static NaN (#6804)
fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) { fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
walk_pat(pat, |p| { ast_util::walk_pat(pat, |p| {
match p.node { match p.node {
ast::PatLit(ref expr) if is_expr_const_nan(cx.tcx, &**expr) => { ast::PatLit(ref expr) if is_expr_const_nan(cx.tcx, &**expr) => {
span_warn!(cx.tcx.sess, p.span, E0003, span_warn!(cx.tcx.sess, p.span, E0003,
@ -399,28 +400,50 @@ fn const_val_to_expr(value: &const_val) -> P<ast::Expr> {
pub struct StaticInliner<'a, 'tcx: 'a> { pub struct StaticInliner<'a, 'tcx: 'a> {
pub tcx: &'a ty::ctxt<'tcx>, 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> { 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 { StaticInliner {
tcx: tcx, 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> { impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> { fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
match pat.node { return match pat.node {
ast::PatIdent(..) | ast::PatEnum(..) => { ast::PatIdent(..) | ast::PatEnum(..) => {
let def = self.tcx.def_map.borrow().get(&pat.id).cloned(); let def = self.tcx.def_map.borrow().get(&pat.id).cloned();
match def { match def {
Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) { Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) {
Some(const_expr) => { Some(const_expr) => {
const_expr_to_pat(self.tcx, const_expr).map(|mut new_pat| { const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
new_pat.span = pat.span;
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 new_pat
}) })
} }
@ -435,6 +458,24 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
} }
} }
_ => noop_fold_pat(pat, self) _ => 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" 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| { is_refutable(cx, &*static_inliner.fold_pat(loc.pat.clone()), |pat| {
span_err!(cx.tcx.sess, loc.pat.span, E0005, span_err!(cx.tcx.sess, loc.pat.span, E0005,
"refutable pattern in {} binding: `{}` not covered", "refutable pattern in {} binding: `{}` not covered",
@ -1040,7 +1081,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
}; };
for pat in pats { for pat in pats {
walk_pat(&**pat, |p| { ast_util::walk_pat(&**pat, |p| {
if pat_is_binding(def_map, &*p) { if pat_is_binding(def_map, &*p) {
match p.node { match p.node {
ast::PatIdent(ast::BindByValue(_), _, ref sub) => { ast::PatIdent(ast::BindByValue(_), _, ref sub) => {

View file

@ -22,6 +22,7 @@ use middle::astconv_util::{ast_ty_to_prim_ty};
use util::nodemap::DefIdMap; use util::nodemap::DefIdMap;
use syntax::ast::{self, Expr}; use syntax::ast::{self, Expr};
use syntax::codemap::Span;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use syntax::ptr::P; use syntax::ptr::P;
use syntax::visit::{self, Visitor}; use syntax::visit::{self, Visitor};
@ -304,10 +305,10 @@ pub enum const_val {
const_bool(bool) const_bool(bool)
} }
pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> { pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat> {
let pat = match expr.node { let pat = match expr.node {
ast::ExprTup(ref exprs) => 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) => { ast::ExprCall(ref callee, ref args) => {
let def = tcx.def_map.borrow()[callee.id].clone(); 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<ast::Pat> {
def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did), def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
_ => unreachable!() _ => 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)) ast::PatEnum(path, Some(pats))
} }
@ -328,7 +329,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
span: codemap::DUMMY_SP, span: codemap::DUMMY_SP,
node: ast::FieldPat { node: ast::FieldPat {
ident: field.ident.node, ident: field.ident.node,
pat: const_expr_to_pat(tcx, &*field.expr), pat: const_expr_to_pat(tcx, &*field.expr, span),
is_shorthand: false, is_shorthand: false,
}, },
}).collect(); }).collect();
@ -336,7 +337,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
} }
ast::ExprVec(ref exprs) => { 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![]) ast::PatVec(pats, None, vec![])
} }
@ -349,7 +350,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
ast::PatEnum(path.clone(), None), ast::PatEnum(path.clone(), None),
_ => { _ => {
match lookup_const(tcx, expr) { 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!() _ => unreachable!()
} }
} }
@ -358,14 +359,14 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
ast::ExprQPath(_) => { ast::ExprQPath(_) => {
match lookup_const(tcx, expr) { 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!() _ => unreachable!()
} }
} }
_ => ast::PatLit(P(expr.clone())) _ => 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 { pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {

View file

@ -213,7 +213,7 @@ use trans::expr::{self, Dest};
use trans::tvec; use trans::tvec;
use trans::type_of; use trans::type_of;
use middle::ty::{self, Ty}; use middle::ty::{self, Ty};
use session::config::FullDebugInfo; use session::config::{NoDebugInfo, FullDebugInfo};
use util::common::indenter; use util::common::indenter;
use util::nodemap::FnvHashMap; use util::nodemap::FnvHashMap;
use util::ppaux::{Repr, vec_map_to_string}; use util::ppaux::{Repr, vec_map_to_string};
@ -222,7 +222,7 @@ use std;
use std::iter::AdditiveIterator; use std::iter::AdditiveIterator;
use std::rc::Rc; use std::rc::Rc;
use syntax::ast; use syntax::ast;
use syntax::ast::{DUMMY_NODE_ID, Ident}; use syntax::ast::{DUMMY_NODE_ID, Ident, NodeId};
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::fold::Folder; use syntax::fold::Folder;
use syntax::ptr::P; use syntax::ptr::P;
@ -244,25 +244,29 @@ impl<'a> ConstantExpr<'a> {
// An option identifying a branch (either a literal, an enum variant or a range) // An option identifying a branch (either a literal, an enum variant or a range)
#[derive(Debug)] #[derive(Debug)]
enum Opt<'a, 'tcx> { enum Opt<'a, 'tcx> {
ConstantValue(ConstantExpr<'a>), ConstantValue(ConstantExpr<'a>, DebugLoc),
ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>), ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>, DebugLoc),
Variant(ty::Disr, Rc<adt::Repr<'tcx>>, ast::DefId), Variant(ty::Disr, Rc<adt::Repr<'tcx>>, ast::DefId, DebugLoc),
SliceLengthEqual(uint), SliceLengthEqual(uint, DebugLoc),
SliceLengthGreaterOrEqual(/* prefix length */ uint, /* suffix length */ uint), SliceLengthGreaterOrEqual(/* prefix length */ uint,
/* suffix length */ uint,
DebugLoc),
} }
impl<'a, 'tcx> Opt<'a, 'tcx> { impl<'a, 'tcx> Opt<'a, 'tcx> {
fn eq(&self, other: &Opt<'a, 'tcx>, tcx: &ty::ctxt<'tcx>) -> bool { fn eq(&self, other: &Opt<'a, 'tcx>, tcx: &ty::ctxt<'tcx>) -> bool {
match (self, other) { match (self, other) {
(&ConstantValue(a), &ConstantValue(b)) => a.eq(b, tcx), (&ConstantValue(a, _), &ConstantValue(b, _)) => a.eq(b, tcx),
(&ConstantRange(a1, a2), &ConstantRange(b1, b2)) => { (&ConstantRange(a1, a2, _), &ConstantRange(b1, b2, _)) => {
a1.eq(b1, tcx) && a2.eq(b2, tcx) 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 a_disr == b_disr && *a_repr == *b_repr && a_def == b_def
} }
(&SliceLengthEqual(a), &SliceLengthEqual(b)) => a == b, (&SliceLengthEqual(a, _), &SliceLengthEqual(b, _)) => a == b,
(&SliceLengthGreaterOrEqual(a1, a2), &SliceLengthGreaterOrEqual(b1, b2)) => { (&SliceLengthGreaterOrEqual(a1, a2, _),
&SliceLengthGreaterOrEqual(b1, b2, _)) => {
a1 == b1 && a2 == b2 a1 == b1 && a2 == b2
} }
_ => false _ => false
@ -273,29 +277,39 @@ impl<'a, 'tcx> Opt<'a, 'tcx> {
let _icx = push_ctxt("match::trans_opt"); let _icx = push_ctxt("match::trans_opt");
let ccx = bcx.ccx(); let ccx = bcx.ccx();
match *self { match *self {
ConstantValue(ConstantExpr(lit_expr)) => { ConstantValue(ConstantExpr(lit_expr), _) => {
let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id); let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id);
let (llval, _) = consts::const_expr(ccx, &*lit_expr); let (llval, _) = consts::const_expr(ccx, &*lit_expr);
let lit_datum = immediate_rvalue(llval, lit_ty); let lit_datum = immediate_rvalue(llval, lit_ty);
let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx)); let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
SingleResult(Result::new(bcx, lit_datum.val)) 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 (l1, _) = consts::const_expr(ccx, &**l1);
let (l2, _) = consts::const_expr(ccx, &**l2); let (l2, _) = consts::const_expr(ccx, &**l2);
RangeResult(Result::new(bcx, l1), Result::new(bcx, 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) adt::trans_case(bcx, &**repr, disr_val)
} }
SliceLengthEqual(length) => { SliceLengthEqual(length, _) => {
SingleResult(Result::new(bcx, C_uint(ccx, length))) SingleResult(Result::new(bcx, C_uint(ccx, length)))
} }
SliceLengthGreaterOrEqual(prefix, suffix) => { SliceLengthGreaterOrEqual(prefix, suffix, _) => {
LowerBound(Result::new(bcx, C_uint(ccx, 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)] #[derive(Copy, PartialEq)]
@ -352,6 +366,9 @@ struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
pats: Vec<&'p ast::Pat>, pats: Vec<&'p ast::Pat>,
data: &'a ArmData<'p, 'blk, 'tcx>, data: &'a ArmData<'p, 'blk, 'tcx>,
bound_ptrs: Vec<(Ident, ValueRef)>, 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> { impl<'a, 'p, 'blk, 'tcx> Repr<'tcx> for Match<'a, 'p, 'blk, 'tcx> {
@ -405,7 +422,8 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
Match { Match {
pats: pats, pats: pats,
data: &*br.data, data: &*br.data,
bound_ptrs: bound_ptrs bound_ptrs: bound_ptrs,
pat_renaming_map: br.pat_renaming_map,
} }
}).collect() }).collect()
} }
@ -449,7 +467,8 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
Match { Match {
pats: pats, pats: pats,
data: br.data, data: br.data,
bound_ptrs: bound_ptrs bound_ptrs: bound_ptrs,
pat_renaming_map: br.pat_renaming_map,
} }
}) })
}).collect() }).collect()
@ -527,18 +546,18 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
let _indenter = indenter(); let _indenter = indenter();
let ctor = match opt { let ctor = match opt {
&ConstantValue(ConstantExpr(expr)) => check_match::ConstantValue( &ConstantValue(ConstantExpr(expr), _) => check_match::ConstantValue(
const_eval::eval_const_expr(bcx.tcx(), &*expr) 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(), &*lo),
const_eval::eval_const_expr(bcx.tcx(), &*hi) const_eval::eval_const_expr(bcx.tcx(), &*hi)
), ),
&SliceLengthEqual(n) => &SliceLengthEqual(n, _) =>
check_match::Slice(n), check_match::Slice(n),
&SliceLengthGreaterOrEqual(before, after) => &SliceLengthGreaterOrEqual(before, after, _) =>
check_match::SliceWithSubslice(before, after), check_match::SliceWithSubslice(before, after),
&Variant(_, _, def_id) => &Variant(_, _, def_id, _) =>
check_match::Constructor::Variant(def_id) check_match::Constructor::Variant(def_id)
}; };
@ -556,34 +575,50 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
// needs to be conditionally matched at runtime; for example, the discriminant // needs to be conditionally matched at runtime; for example, the discriminant
// on a set of enum variants or a literal. // on a set of enum variants or a literal.
fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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<Opt<'p, 'tcx>> { -> Vec<Opt<'p, 'tcx>> {
let tcx = bcx.tcx(); let tcx = bcx.tcx();
let mut found: Vec<Opt> = vec![]; let mut found: Vec<Opt> = vec![];
for br in m { for br in m {
let cur = br.pats[col]; let cur = br.pats[col];
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 { 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(..) => { ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => {
// This is either an enum variant or a variable binding. // This is either an enum variant or a variable binding.
let opt_def = tcx.def_map.borrow().get(&cur.id).cloned(); let opt_def = tcx.def_map.borrow().get(&cur.id).cloned();
match opt_def { match opt_def {
Some(def::DefVariant(enum_id, var_id, _)) => { Some(def::DefVariant(enum_id, var_id, _)) => {
let variant = ty::enum_variant_with_id(tcx, 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 _ => continue
} }
} }
ast::PatRange(ref l1, ref l2) => { 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) => { 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) => { ast::PatVec(ref before, Some(_), ref after) => {
SliceLengthGreaterOrEqual(before.len(), after.len()) SliceLengthGreaterOrEqual(before.len(), after.len(), debug_loc)
} }
_ => continue _ => continue
}; };
@ -779,30 +814,32 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option<uint> {
fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
lhs: ValueRef, lhs: ValueRef,
rhs: ValueRef, rhs: ValueRef,
rhs_t: Ty<'tcx>) rhs_t: Ty<'tcx>,
debug_loc: DebugLoc)
-> Result<'blk, 'tcx> { -> Result<'blk, 'tcx> {
fn compare_str<'blk, 'tcx>(cx: Block<'blk, 'tcx>, fn compare_str<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
lhs: ValueRef, lhs: ValueRef,
rhs: ValueRef, rhs: ValueRef,
rhs_t: Ty<'tcx>) rhs_t: Ty<'tcx>,
debug_loc: DebugLoc)
-> Result<'blk, 'tcx> { -> Result<'blk, 'tcx> {
let did = langcall(cx, let did = langcall(cx,
None, None,
&format!("comparison of `{}`", &format!("comparison of `{}`",
cx.ty_to_string(rhs_t))[], cx.ty_to_string(rhs_t))[],
StrEqFnLangItem); 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"); let _icx = push_ctxt("compare_values");
if ty::type_is_scalar(rhs_t) { 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); return Result::new(rs.bcx, rs.val);
} }
match rhs_t.sty { match rhs_t.sty {
ty::ty_rptr(_, mt) => match mt.ty.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_vec(ty, _) => match ty.sty {
ty::ty_uint(ast::TyU8) => { ty::ty_uint(ast::TyU8) => {
// NOTE: cast &[u8] to &str and abuse the str_eq lang item, // NOTE: cast &[u8] to &str and abuse the str_eq lang item,
@ -812,7 +849,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
ast::MutImmutable); ast::MutImmutable);
let lhs = BitCast(cx, lhs, type_of::type_of(cx.ccx(), t).ptr_to()); 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()); 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"), _ => cx.sess().bug("only byte strings supported in compare_values"),
}, },
@ -1046,7 +1083,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
debug!("test_val={}", bcx.val_to_string(test_val)); debug!("test_val={}", bcx.val_to_string(test_val));
if opts.len() > 0 { if opts.len() > 0 {
match opts[0] { match opts[0] {
ConstantValue(_) | ConstantRange(_, _) => { ConstantValue(..) | ConstantRange(..) => {
test_val = load_if_immediate(bcx, val, left_ty); test_val = load_if_immediate(bcx, val, left_ty);
kind = if ty::type_is_integral(left_ty) { kind = if ty::type_is_integral(left_ty) {
Switch Switch
@ -1054,12 +1091,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
Compare Compare
}; };
} }
Variant(_, ref repr, _) => { 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);
kind = the_kind; kind = the_kind;
if let Some(tval) = val_opt { test_val = tval; } if let Some(tval) = val_opt { test_val = tval; }
} }
SliceLengthEqual(_) | SliceLengthGreaterOrEqual(_, _) => { SliceLengthEqual(..) | SliceLengthGreaterOrEqual(..) => {
let (_, len) = tvec::get_base_and_len(bcx, val, left_ty); let (_, len) = tvec::get_base_and_len(bcx, val, left_ty);
test_val = len; test_val = len;
kind = Switch; kind = Switch;
@ -1068,8 +1105,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
} }
for o in &opts { for o in &opts {
match *o { match *o {
ConstantRange(_, _) => { kind = Compare; break }, ConstantRange(..) => { kind = Compare; break },
SliceLengthGreaterOrEqual(_, _) => { kind = CompareSliceLength; break }, SliceLengthGreaterOrEqual(..) => { kind = CompareSliceLength; break },
_ => () _ => ()
} }
} }
@ -1095,10 +1132,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
// for the current conditional branch. // for the current conditional branch.
let mut branch_chk = None; let mut branch_chk = None;
let mut opt_cx = else_cx; let mut opt_cx = else_cx;
let debug_loc = opt.debug_loc();
if !exhaustive || i + 1 < len { if !exhaustive || i + 1 < len {
opt_cx = bcx.fcx.new_temp_block("match_case"); opt_cx = bcx.fcx.new_temp_block("match_case");
match kind { match kind {
Single => Br(bcx, opt_cx.llbb, DebugLoc::None), Single => Br(bcx, opt_cx.llbb, debug_loc),
Switch => { Switch => {
match opt.trans(bcx) { match opt.trans(bcx) {
SingleResult(r) => { SingleResult(r) => {
@ -1121,22 +1160,33 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let Result { bcx: after_cx, val: matches } = { let Result { bcx: after_cx, val: matches } = {
match opt.trans(bcx) { match opt.trans(bcx) {
SingleResult(Result { bcx, val }) => { SingleResult(Result { bcx, val }) => {
compare_values(bcx, test_val, val, t) compare_values(bcx, test_val, val, t, debug_loc)
} }
RangeResult(Result { val: vbegin, .. }, RangeResult(Result { val: vbegin, .. },
Result { bcx, val: vend }) => { Result { bcx, val: vend }) => {
let Result { bcx, val: llge } = let Result { bcx, val: llge } =
compare_scalar_types( compare_scalar_types(bcx,
bcx, test_val, test_val,
vbegin, t, ast::BiGe); vbegin,
t,
ast::BiGe,
debug_loc);
let Result { bcx, val: llle } = let Result { bcx, val: llle } =
compare_scalar_types( compare_scalar_types(bcx,
bcx, test_val, vend, test_val,
t, ast::BiLe); vend,
Result::new(bcx, And(bcx, llge, llle, DebugLoc::None)) t,
ast::BiLe,
debug_loc);
Result::new(bcx, And(bcx, llge, llle, debug_loc))
} }
LowerBound(Result { bcx, val }) => { 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)
} }
} }
}; };
@ -1151,37 +1201,37 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
if i + 1 < len && (guarded || multi_pats || kind == CompareSliceLength) { if i + 1 < len && (guarded || multi_pats || kind == CompareSliceLength) {
branch_chk = Some(JumpToBasicBlock(bcx.llbb)); 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 { } 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 size = 0;
let mut unpacked = Vec::new(); let mut unpacked = Vec::new();
match *opt { match *opt {
Variant(disr_val, ref repr, _) => { Variant(disr_val, ref repr, _, _) => {
let ExtractedBlock {vals: argvals, bcx: new_bcx} = let ExtractedBlock {vals: argvals, bcx: new_bcx} =
extract_variant_args(opt_cx, &**repr, disr_val, val); extract_variant_args(opt_cx, &**repr, disr_val, val);
size = argvals.len(); size = argvals.len();
unpacked = argvals; unpacked = argvals;
opt_cx = new_bcx; opt_cx = new_bcx;
} }
SliceLengthEqual(len) => { SliceLengthEqual(len, _) => {
let args = extract_vec_elems(opt_cx, left_ty, len, 0, val); let args = extract_vec_elems(opt_cx, left_ty, len, 0, val);
size = args.vals.len(); size = args.vals.len();
unpacked = args.vals.clone(); unpacked = args.vals.clone();
opt_cx = args.bcx; opt_cx = args.bcx;
} }
SliceLengthGreaterOrEqual(before, after) => { SliceLengthGreaterOrEqual(before, after, _) => {
let args = extract_vec_elems(opt_cx, left_ty, before, after, val); let args = extract_vec_elems(opt_cx, left_ty, before, after, val);
size = args.vals.len(); size = args.vals.len();
unpacked = args.vals.clone(); unpacked = args.vals.clone();
opt_cx = args.bcx; opt_cx = args.bcx;
} }
ConstantValue(_) | ConstantRange(_, _) => () ConstantValue(..) | ConstantRange(..) => ()
} }
let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val); let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val);
let mut opt_vals = unpacked; let mut opt_vals = unpacked;
@ -1385,16 +1435,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) bindings_map: create_bindings_map(bcx, &*arm.pats[0], discr_expr, &*arm.body)
}).collect(); }).collect();
let mut static_inliner = StaticInliner::new(scope_cx.tcx()); let mut pat_renaming_map = if scope_cx.sess().opts.debuginfo != NoDebugInfo {
let arm_pats: Vec<Vec<P<ast::Pat>>> = arm_datas.iter().map(|arm_data| { Some(FnvHashMap())
arm_data.arm.pats.iter().map(|p| static_inliner.fold_pat((*p).clone())).collect() } else {
}).collect(); None
};
let arm_pats: Vec<Vec<P<ast::Pat>>> = {
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(); let mut matches = Vec::new();
for (arm_data, pats) in arm_datas.iter().zip(arm_pats.iter()) { for (arm_data, pats) in arm_datas.iter().zip(arm_pats.iter()) {
matches.extend(pats.iter().map(|p| Match { matches.extend(pats.iter().map(|p| Match {
pats: vec![&**p], pats: vec![&**p],
data: arm_data, data: arm_data,
bound_ptrs: Vec::new(), bound_ptrs: Vec::new(),
pat_renaming_map: pat_renaming_map.as_ref()
})); }));
} }

View file

@ -751,7 +751,7 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
RawNullablePointer { nndiscr, nnty, .. } => { RawNullablePointer { nndiscr, nnty, .. } => {
let cmp = if nndiscr == 0 { IntEQ } else { IntNE }; let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty); 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; signed = false;
} }
StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => { 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 llptrptr = GEPi(bcx, scrutinee, &discrfield[]);
let llptr = Load(bcx, llptrptr); let llptr = Load(bcx, llptrptr);
let cmp = if nndiscr == 0 { IntEQ } else { IntNE }; 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. /// Helper for cases where the discriminant is simply loaded.

View file

@ -57,7 +57,7 @@ use trans::closure;
use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral}; 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::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
use trans::common::{CrateContext, ExternMap, FunctionContext}; 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::{node_id_type, return_type_is_void};
use trans::common::{tydesc_info, type_is_immediate}; use trans::common::{tydesc_info, type_is_immediate};
use trans::common::{type_is_zero_size, val_ty}; use trans::common::{type_is_zero_size, val_ty};
@ -66,7 +66,7 @@ use trans::consts;
use trans::context::SharedCrateContext; use trans::context::SharedCrateContext;
use trans::controlflow; use trans::controlflow;
use trans::datum; use trans::datum;
use trans::debuginfo::{self, DebugLoc}; use trans::debuginfo::{self, DebugLoc, ToDebugLoc};
use trans::expr; use trans::expr;
use trans::foreign; use trans::foreign;
use trans::glue; use trans::glue;
@ -379,7 +379,8 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llty_ptr: Type, llty_ptr: Type,
info_ty: Ty<'tcx>, info_ty: Ty<'tcx>,
size: ValueRef, size: ValueRef,
align: ValueRef) align: ValueRef,
debug_loc: DebugLoc)
-> Result<'blk, 'tcx> { -> Result<'blk, 'tcx> {
let _icx = push_ctxt("malloc_raw_exchange"); 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, let r = callee::trans_lang_call(bcx,
require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem), require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem),
&[size, align], &[size, align],
None); None,
debug_loc);
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr)) Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
} }
@ -538,9 +540,10 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
lhs: ValueRef, lhs: ValueRef,
rhs: ValueRef, rhs: ValueRef,
t: Ty<'tcx>, t: Ty<'tcx>,
op: ast::BinOp_) op: ast::BinOp_,
debug_loc: DebugLoc)
-> Result<'blk, 'tcx> { -> 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 { match t.sty {
ty::ty_tup(ref tys) if tys.is_empty() => f(nil_type), ty::ty_tup(ref tys) if tys.is_empty() => f(nil_type),
@ -559,7 +562,8 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
lhs: ValueRef, lhs: ValueRef,
rhs: ValueRef, rhs: ValueRef,
nt: scalar_type, nt: scalar_type,
op: ast::BinOp_) op: ast::BinOp_,
debug_loc: DebugLoc)
-> ValueRef { -> ValueRef {
let _icx = push_ctxt("compare_scalar_values"); let _icx = push_ctxt("compare_scalar_values");
fn die(cx: Block) -> ! { fn die(cx: Block) -> ! {
@ -586,7 +590,7 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
ast::BiGe => llvm::RealOGE, ast::BiGe => llvm::RealOGE,
_ => die(cx) _ => die(cx)
}; };
return FCmp(cx, cmp, lhs, rhs); return FCmp(cx, cmp, lhs, rhs, debug_loc);
} }
signed_int => { signed_int => {
let cmp = match op { let cmp = match op {
@ -598,7 +602,7 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
ast::BiGe => llvm::IntSGE, ast::BiGe => llvm::IntSGE,
_ => die(cx) _ => die(cx)
}; };
return ICmp(cx, cmp, lhs, rhs); return ICmp(cx, cmp, lhs, rhs, debug_loc);
} }
unsigned_int => { unsigned_int => {
let cmp = match op { let cmp = match op {
@ -610,7 +614,7 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
ast::BiGe => llvm::IntUGE, ast::BiGe => llvm::IntUGE,
_ => die(cx) _ => die(cx)
}; };
return ICmp(cx, cmp, lhs, rhs); return ICmp(cx, cmp, lhs, rhs, debug_loc);
} }
} }
} }
@ -621,7 +625,8 @@ pub fn compare_simd_types<'blk, 'tcx>(
rhs: ValueRef, rhs: ValueRef,
t: Ty<'tcx>, t: Ty<'tcx>,
size: uint, size: uint,
op: ast::BinOp) op: ast::BinOp_,
debug_loc: DebugLoc)
-> ValueRef { -> ValueRef {
let cmp = match t.sty { let cmp = match t.sty {
ty::ty_float(_) => { ty::ty_float(_) => {
@ -632,7 +637,7 @@ pub fn compare_simd_types<'blk, 'tcx>(
cx.sess().bug("compare_simd_types: comparison operators \ cx.sess().bug("compare_simd_types: comparison operators \
not supported for floating point SIMD types") not supported for floating point SIMD types")
}, },
ty::ty_uint(_) => match op.node { ty::ty_uint(_) => match op {
ast::BiEq => llvm::IntEQ, ast::BiEq => llvm::IntEQ,
ast::BiNe => llvm::IntNE, ast::BiNe => llvm::IntNE,
ast::BiLt => llvm::IntULT, ast::BiLt => llvm::IntULT,
@ -641,7 +646,7 @@ pub fn compare_simd_types<'blk, 'tcx>(
ast::BiGe => llvm::IntUGE, ast::BiGe => llvm::IntUGE,
_ => cx.sess().bug("compare_simd_types: must be a comparison operator"), _ => 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::BiEq => llvm::IntEQ,
ast::BiNe => llvm::IntNE, ast::BiNe => llvm::IntNE,
ast::BiLt => llvm::IntSLT, ast::BiLt => llvm::IntSLT,
@ -657,7 +662,7 @@ pub fn compare_simd_types<'blk, 'tcx>(
// to get the correctly sized type. This will compile to a single instruction // 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 // once the IR is converted to assembly if the SIMD instruction is supported
// by the target architecture. // 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. // Iterates through the elements of a structural type.
@ -851,7 +856,7 @@ pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
pub fn fail_if_zero_or_overflows<'blk, 'tcx>( pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
cx: Block<'blk, 'tcx>, cx: Block<'blk, 'tcx>,
span: Span, call_info: NodeIdAndSpan,
divrem: ast::BinOp, divrem: ast::BinOp,
lhs: ValueRef, lhs: ValueRef,
rhs: ValueRef, rhs: ValueRef,
@ -864,14 +869,16 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
("attempted remainder with a divisor of zero", ("attempted remainder with a divisor of zero",
"attempted remainder with overflow") "attempted remainder with overflow")
}; };
let debug_loc = call_info.debug_loc();
let (is_zero, is_signed) = match rhs_t.sty { let (is_zero, is_signed) = match rhs_t.sty {
ty::ty_int(t) => { ty::ty_int(t) => {
let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0u64, false); 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) => { ty::ty_uint(t) => {
let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0u64, false); 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: {}", cx.sess().bug(&format!("fail-if-zero on unexpected type: {}",
@ -879,7 +886,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
} }
}; };
let bcx = with_cond(cx, is_zero, |bcx| { 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: // To quote LLVM's documentation for the sdiv instruction:
@ -908,12 +915,13 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
_ => unreachable!(), _ => unreachable!(),
}; };
let minus_one = ICmp(bcx, llvm::IntEQ, rhs, 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| { with_cond(bcx, minus_one, |bcx| {
let is_min = ICmp(bcx, llvm::IntEQ, lhs, 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| { with_cond(bcx, is_min, |bcx| {
controlflow::trans_fail(bcx, span, controlflow::trans_fail(bcx,
call_info,
InternedString::new(overflow_text)) InternedString::new(overflow_text))
}) })
}) })

View file

@ -856,22 +856,32 @@ pub fn FPCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef {
/* Comparisons */ /* Comparisons */
pub fn ICmp(cx: Block, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) pub fn ICmp(cx: Block,
-> ValueRef { op: IntPredicate,
lhs: ValueRef,
rhs: ValueRef,
debug_loc: DebugLoc)
-> ValueRef {
unsafe { unsafe {
if cx.unreachable.get() { if cx.unreachable.get() {
return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref());
} }
debug_loc.apply(cx.fcx);
B(cx).icmp(op, lhs, rhs) B(cx).icmp(op, lhs, rhs)
} }
} }
pub fn FCmp(cx: Block, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) pub fn FCmp(cx: Block,
-> ValueRef { op: RealPredicate,
lhs: ValueRef,
rhs: ValueRef,
debug_loc: DebugLoc)
-> ValueRef {
unsafe { unsafe {
if cx.unreachable.get() { if cx.unreachable.get() {
return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref());
} }
debug_loc.apply(cx.fcx);
B(cx).fcmp(op, lhs, rhs) B(cx).fcmp(op, lhs, rhs)
} }
} }
@ -941,9 +951,17 @@ pub fn Call(cx: Block,
B(cx).call(fn_, args, attributes) B(cx).call(fn_, args, attributes)
} }
pub fn CallWithConv(cx: Block, fn_: ValueRef, args: &[ValueRef], conv: CallConv, pub fn CallWithConv(cx: Block,
attributes: Option<AttrBuilder>) -> ValueRef { fn_: ValueRef,
if cx.unreachable.get() { return _UndefReturn(cx, fn_); } args: &[ValueRef],
conv: CallConv,
attributes: Option<AttrBuilder>,
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) B(cx).call_with_conv(fn_, args, conv, attributes)
} }

View file

@ -36,8 +36,8 @@ use trans::callee;
use trans::cleanup; use trans::cleanup;
use trans::cleanup::CleanupMethods; use trans::cleanup::CleanupMethods;
use trans::closure; use trans::closure;
use trans::common; use trans::common::{self, Block, Result, NodeIdAndSpan, ExprId, CrateContext,
use trans::common::*; ExprOrMethodCall, FunctionContext, MethodCallKey};
use trans::consts; use trans::consts;
use trans::datum::*; use trans::datum::*;
use trans::debuginfo::{DebugLoc, ToDebugLoc}; use trans::debuginfo::{DebugLoc, ToDebugLoc};
@ -136,7 +136,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
ref_expr: &ast::Expr) ref_expr: &ast::Expr)
-> Callee<'blk, 'tcx> { -> Callee<'blk, 'tcx> {
debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.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 { match def {
def::DefFn(did, _) if { def::DefFn(did, _) if {
let maybe_def_id = inline::get_local_instance(bcx.ccx(), did); 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 _ => false
} }
} => { } => {
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), let substs = common::node_id_substs(bcx.ccx(),
bcx.fcx.param_substs); ExprId(ref_expr.id),
bcx.fcx.param_substs);
Callee { Callee {
bcx: bcx, bcx: bcx,
data: NamedTupleConstructor(substs, 0) 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, ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic,
_ => false _ => false
} => { } => {
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), let substs = common::node_id_substs(bcx.ccx(),
bcx.fcx.param_substs); ExprId(ref_expr.id),
bcx.fcx.param_substs);
let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did); let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) } 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, _) => { def::DefVariant(tid, vid, _) => {
let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid); let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), let substs = common::node_id_substs(bcx.ccx(),
bcx.fcx.param_substs); ExprId(ref_expr.id),
bcx.fcx.param_substs);
// Nullary variants are not callable // Nullary variants are not callable
assert!(vinfo.args.len() > 0); assert!(vinfo.args.len() > 0);
@ -190,8 +193,9 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
} }
} }
def::DefStruct(_) => { def::DefStruct(_) => {
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id), let substs = common::node_id_substs(bcx.ccx(),
bcx.fcx.param_substs); ExprId(ref_expr.id),
bcx.fcx.param_substs);
Callee { Callee {
bcx: bcx, bcx: bcx,
data: NamedTupleConstructor(substs, 0) data: NamedTupleConstructor(substs, 0)
@ -226,7 +230,7 @@ pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-> Datum<'tcx, Rvalue> { -> Datum<'tcx, Rvalue> {
let _icx = push_ctxt("trans_fn_ref"); 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={})", debug!("trans_fn_ref(def_id={}, node={:?}, substs={})",
def_id.repr(ccx.tcx()), def_id.repr(ccx.tcx()),
node, node,
@ -269,7 +273,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
let _icx = push_ctxt("trans_fn_pointer_shim"); let _icx = push_ctxt("trans_fn_pointer_shim");
let tcx = ccx.tcx(); 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) { match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty) {
Some(&llval) => { return llval; } Some(&llval) => { return llval; }
None => { } None => { }
@ -352,7 +356,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
); );
bcx = trans_call_inner(bcx, bcx = trans_call_inner(bcx,
None, DebugLoc::None,
bare_fn_ty, bare_fn_ty,
|bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) }, |bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) },
ArgVals(&llargs[]), ArgVals(&llargs[]),
@ -515,7 +519,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
param_substs, param_substs,
&ref_ty); &ref_ty);
let llptrty = type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to(); 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); let val = consts::ptrcast(val, llptrty);
return Datum::new(val, ref_ty, Rvalue::new(ByValue)); 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. // other weird situations. Annoying.
let llty = type_of::type_of_fn_from_ty(ccx, fn_type); let llty = type_of::type_of_fn_from_ty(ccx, fn_type);
let llptrty = llty.ptr_to(); let llptrty = llty.ptr_to();
if val_ty(val) != llptrty { if common::val_ty(val) != llptrty {
debug!("trans_fn_ref_with_vtables(): casting pointer!"); debug!("trans_fn_ref_with_vtables(): casting pointer!");
val = consts::ptrcast(val, llptrty); val = consts::ptrcast(val, llptrty);
} else { } else {
@ -577,34 +581,34 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
// Translating calls // Translating calls
pub fn trans_call<'a, 'blk, 'tcx>(in_cx: Block<'blk, 'tcx>, pub fn trans_call<'a, 'blk, 'tcx>(in_cx: Block<'blk, 'tcx>,
call_ex: &ast::Expr, call_expr: &ast::Expr,
f: &ast::Expr, f: &ast::Expr,
args: CallArgs<'a, 'tcx>, args: CallArgs<'a, 'tcx>,
dest: expr::Dest) dest: expr::Dest)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_call"); let _icx = push_ctxt("trans_call");
trans_call_inner(in_cx, trans_call_inner(in_cx,
Some(common::expr_info(call_ex)), call_expr.debug_loc(),
expr_ty_adjusted(in_cx, f), common::expr_ty_adjusted(in_cx, f),
|cx, _| trans(cx, f), |cx, _| trans(cx, f),
args, args,
Some(dest)).bcx Some(dest)).bcx
} }
pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
call_ex: &ast::Expr, call_expr: &ast::Expr,
rcvr: &ast::Expr, rcvr: &ast::Expr,
args: CallArgs<'a, 'tcx>, args: CallArgs<'a, 'tcx>,
dest: expr::Dest) dest: expr::Dest)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_method_call"); let _icx = push_ctxt("trans_method_call");
debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx())); debug!("trans_method_call(call_expr={})", call_expr.repr(bcx.tcx()));
let method_call = MethodCall::expr(call_ex.id); let method_call = MethodCall::expr(call_expr.id);
let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty;
trans_call_inner( trans_call_inner(
bcx, bcx,
Some(common::expr_info(call_ex)), call_expr.debug_loc(),
monomorphize_type(bcx, method_ty), common::monomorphize_type(bcx, method_ty),
|cx, arg_cleanup_scope| { |cx, arg_cleanup_scope| {
meth::trans_method_callee(cx, method_call, Some(rcvr), 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>, pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
did: ast::DefId, did: ast::DefId,
args: &[ValueRef], args: &[ValueRef],
dest: Option<expr::Dest>) dest: Option<expr::Dest>,
debug_loc: DebugLoc)
-> Result<'blk, 'tcx> { -> Result<'blk, 'tcx> {
let fty = if did.krate == ast::LOCAL_CRATE { let fty = if did.krate == ast::LOCAL_CRATE {
ty::node_id_to_type(bcx.tcx(), did.node) 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 csearch::get_type(bcx.tcx(), did).ty
}; };
callee::trans_call_inner(bcx, callee::trans_call_inner(bcx,
None, debug_loc,
fty, fty,
|bcx, _| { |bcx, _| {
trans_fn_ref_with_substs_to_callee(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 /// 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. /// somewhere. Nonetheless we return the actual return value of the function.
pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
call_info: Option<NodeIdAndSpan>, debug_loc: DebugLoc,
callee_ty: Ty<'tcx>, callee_ty: Ty<'tcx>,
get_callee: F, get_callee: F,
args: CallArgs<'a, 'tcx>, 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!(abi == synabi::RustIntrinsic);
assert!(dest.is_some()); 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, return intrinsic::trans_intrinsic_call(bcx, node, callee_ty,
arg_cleanup_scope, args, arg_cleanup_scope, args,
dest.unwrap(), substs, dest.unwrap(), substs,
@ -703,7 +714,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
disr, disr,
args, args,
dest.unwrap(), 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 || if !is_rust_fn ||
type_of::return_uses_outptr(ccx, ret_ty) || 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 // Push the out-pointer if we use an out-pointer for this
// return type, otherwise push "undef". // 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); let llty = type_of::type_of(ccx, ret_ty);
Some(C_undef(llty.ptr_to())) Some(common::C_undef(llty.ptr_to()))
} else { } else {
Some(alloc_ty(bcx, ret_ty, "__llret")) 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, llfn,
&llargs[], &llargs[],
callee_ty, callee_ty,
call_info.debug_loc()); debug_loc);
bcx = b; bcx = b;
llresult = llret; llresult = llret;
@ -790,7 +801,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
match (opt_llretslot, ret_ty) { match (opt_llretslot, ret_ty) {
(Some(llretslot), ty::FnConverging(ret_ty)) => { (Some(llretslot), ty::FnConverging(ret_ty)) => {
if !type_of::return_uses_outptr(bcx.ccx(), 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) 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 mut llargs = Vec::new();
let arg_tys = match args { 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.") _ => panic!("expected arg exprs.")
}; };
bcx = trans_args(bcx, bcx = trans_args(bcx,
@ -816,9 +827,13 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
abi); abi);
fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean();
bcx = foreign::trans_native_call(bcx, callee_ty, bcx = foreign::trans_native_call(bcx,
llfn, opt_llretslot.unwrap(), callee_ty,
&llargs[], arg_tys); llfn,
opt_llretslot.unwrap(),
&llargs[],
arg_tys,
debug_loc);
} }
fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_cleanup_scope); fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_cleanup_scope);
@ -831,7 +846,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
bcx = glue::drop_ty(bcx, bcx = glue::drop_ty(bcx,
llretslot, llretslot,
ret_ty, ret_ty,
call_info.debug_loc()); debug_loc);
call_lifetime_end(bcx, llretslot); call_lifetime_end(bcx, llretslot);
} }
_ => {} _ => {}
@ -892,7 +907,7 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
// Now untuple the rest of the arguments. // Now untuple the rest of the arguments.
let tuple_expr = &arg_exprs[1]; 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 { match tuple_type.sty {
ty::ty_tup(ref field_types) => { ty::ty_tup(ref field_types) => {
@ -1014,7 +1029,7 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
} }
let arg_ty = if i >= num_formal_args { let arg_ty = if i >= num_formal_args {
assert!(variadic); assert!(variadic);
expr_ty_adjusted(cx, &**arg_expr) common::expr_ty_adjusted(cx, &**arg_expr)
} else { } else {
arg_tys[i] arg_tys[i]
}; };

View file

@ -940,11 +940,12 @@ impl<'tcx> Cleanup<'tcx> for FreeValue<'tcx> {
bcx: Block<'blk, 'tcx>, bcx: Block<'blk, 'tcx>,
debug_loc: DebugLoc) debug_loc: DebugLoc)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
debug_loc.apply(bcx.fcx);
match self.heap { match self.heap {
HeapExchange => { 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>, bcx: Block<'blk, 'tcx>,
debug_loc: DebugLoc) debug_loc: DebugLoc)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
debug_loc.apply(bcx.fcx);
match self.heap { match self.heap {
HeapExchange => { 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)
} }
} }
} }

View file

@ -28,7 +28,6 @@ use util::ppaux::Repr;
use syntax::ast; use syntax::ast;
use syntax::ast::Ident; use syntax::ast::Ident;
use syntax::ast_util; use syntax::ast_util;
use syntax::codemap::Span;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use syntax::parse::token; use syntax::parse::token;
use syntax::visit::Visitor; 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>, pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
sp: Span, call_info: NodeIdAndSpan,
fail_str: InternedString) fail_str: InternedString)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let _icx = push_ctxt("trans_fail_value"); let _icx = push_ctxt("trans_fail_value");
let v_str = C_str_slice(ccx, fail_str); 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 = token::intern_and_get_ident(&loc.file.name[]);
let filename = C_str_slice(ccx, filename); let filename = C_str_slice(ccx, filename);
let line = C_uint(ccx, loc.line); let line = C_uint(ccx, loc.line);
let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); 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 expr_file_line = consts::const_addr_of(ccx, expr_file_line_const, ast::MutImmutable);
let args = vec!(expr_file_line); 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, let bcx = callee::trans_lang_call(bcx,
did, did,
&args[], &args[],
Some(expr::Ignore)).bcx; Some(expr::Ignore),
call_info.debug_loc()).bcx;
Unreachable(bcx); Unreachable(bcx);
return bcx; return bcx;
} }
pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
sp: Span, call_info: NodeIdAndSpan,
index: ValueRef, index: ValueRef,
len: ValueRef) len: ValueRef)
-> Block<'blk, 'tcx> { -> 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"); let _icx = push_ctxt("trans_fail_bounds_check");
// Extract the file/line from the span // 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[]); let filename = token::intern_and_get_ident(&loc.file.name[]);
// Invoke the lang item // 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_const = C_struct(ccx, &[filename, line], false);
let file_line = consts::const_addr_of(ccx, file_line_const, ast::MutImmutable); let file_line = consts::const_addr_of(ccx, file_line_const, ast::MutImmutable);
let args = vec!(file_line, index, len); 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, let bcx = callee::trans_lang_call(bcx,
did, did,
&args[], &args[],
Some(expr::Ignore)).bcx; Some(expr::Ignore),
call_info.debug_loc()).bcx;
Unreachable(bcx); Unreachable(bcx);
return bcx; return bcx;
} }

View file

@ -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 { pub enum DebugLoc {
At(ast::NodeId, Span), At(ast::NodeId, Span),
None None

View file

@ -586,7 +586,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let contents_ty = expr_ty(bcx, &**contents); let contents_ty = expr_ty(bcx, &**contents);
match box_ty.sty { match box_ty.sty {
ty::ty_uniq(..) => { 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, _ => bcx.sess().span_bug(expr.span,
"expected unique box") "expected unique box")
@ -696,6 +696,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let mut bcx = bcx; let mut bcx = bcx;
let index_expr_debug_loc = index_expr.debug_loc();
// Check for overloaded index. // Check for overloaded index.
let method_ty = ccx.tcx() let method_ty = ccx.tcx()
.method_map .method_map
@ -778,16 +780,20 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debug!("trans_index: base {}", bcx.val_to_string(base)); debug!("trans_index: base {}", bcx.val_to_string(base));
debug!("trans_index: len {}", bcx.val_to_string(len)); 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 expect = ccx.get_intrinsic(&("llvm.expect.i1"));
let expected = Call(bcx, let expected = Call(bcx,
expect, expect,
&[bounds_check, C_bool(ccx, false)], &[bounds_check, C_bool(ccx, false)],
None, None,
index_expr.debug_loc()); index_expr_debug_loc);
bcx = with_cond(bcx, expected, |bcx| { bcx = with_cond(bcx, expected, |bcx| {
controlflow::trans_fail_bounds_check(bcx, controlflow::trans_fail_bounds_check(bcx,
index_expr.span, expr_info(index_expr),
ix_val, ix_val,
len) len)
}); });
@ -1574,7 +1580,7 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock() immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
} }
ast::UnUniq => { 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 => { ast::UnDeref => {
let datum = unpack_datum!(bcx, trans(bcx, sub_expr)); let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
@ -1584,6 +1590,7 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
} }
fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
box_expr: &ast::Expr,
box_ty: Ty<'tcx>, box_ty: Ty<'tcx>,
contents: &ast::Expr, contents: &ast::Expr,
contents_ty: Ty<'tcx>) contents_ty: Ty<'tcx>)
@ -1595,7 +1602,12 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let size = llsize_of(bcx.ccx(), llty); let size = llsize_of(bcx.ccx(), llty);
let align = C_uint(bcx.ccx(), type_of::align_of(bcx.ccx(), contents_ty)); let align = C_uint(bcx.ccx(), type_of::align_of(bcx.ccx(), contents_ty));
let llty_ptr = llty.ptr_to(); 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 // Unique boxes do not allocate for zero-size types. The standard library
// may assume that `free` is never called on the pointer returned for // may assume that `free` is never called on the pointer returned for
// `Box<ZeroSizeType>`. // `Box<ZeroSizeType>`.
@ -1697,8 +1709,12 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
FDiv(bcx, lhs, rhs, binop_debug_loc) FDiv(bcx, lhs, rhs, binop_debug_loc)
} else { } else {
// Only zero-check integers; fp /0 is NaN // 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,
op, lhs, rhs, rhs_t); expr_info(binop_expr),
op,
lhs,
rhs,
rhs_t);
if is_signed { if is_signed {
SDiv(bcx, lhs, rhs, binop_debug_loc) SDiv(bcx, lhs, rhs, binop_debug_loc)
} else { } else {
@ -1711,7 +1727,8 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
FRem(bcx, lhs, rhs, binop_debug_loc) FRem(bcx, lhs, rhs, binop_debug_loc)
} else { } else {
// Only zero-check integers; fp %0 is NaN // 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); op, lhs, rhs, rhs_t);
if is_signed { if is_signed {
SRem(bcx, lhs, rhs, binop_debug_loc) SRem(bcx, lhs, rhs, binop_debug_loc)
@ -1733,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 => { ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => {
if ty::type_is_scalar(rhs_t) { 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 { } 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 { } else {
bcx.tcx().sess.span_bug(binop_expr.span, "comparison operator unsupported for type") bcx.tcx().sess.span_bug(binop_expr.span, "comparison operator unsupported for type")
} }
@ -1845,7 +1874,7 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-> Result<'blk, 'tcx> { -> Result<'blk, 'tcx> {
let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty;
callee::trans_call_inner(bcx, callee::trans_call_inner(bcx,
Some(expr_info(expr)), expr.debug_loc(),
monomorphize_type(bcx, method_ty), monomorphize_type(bcx, method_ty),
|bcx, arg_cleanup_scope| { |bcx, arg_cleanup_scope| {
meth::trans_method_callee(bcx, meth::trans_method_callee(bcx,
@ -1872,7 +1901,7 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
all_args.extend(args.iter().map(|e| &**e)); all_args.extend(args.iter().map(|e| &**e));
unpack_result!(bcx, unpack_result!(bcx,
callee::trans_call_inner(bcx, callee::trans_call_inner(bcx,
Some(expr_info(expr)), expr.debug_loc(),
monomorphize_type(bcx, monomorphize_type(bcx,
method_type), method_type),
|bcx, arg_cleanup_scope| { |bcx, arg_cleanup_scope| {

View file

@ -18,6 +18,7 @@ use trans::base;
use trans::build::*; use trans::build::*;
use trans::cabi; use trans::cabi;
use trans::common::*; use trans::common::*;
use trans::debuginfo::DebugLoc;
use trans::machine; use trans::machine;
use trans::monomorphize; use trans::monomorphize;
use trans::type_::Type; use trans::type_::Type;
@ -218,7 +219,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llfn: ValueRef, llfn: ValueRef,
llretptr: ValueRef, llretptr: ValueRef,
llargs_rust: &[ValueRef], llargs_rust: &[ValueRef],
passed_arg_tys: Vec<Ty<'tcx>>) passed_arg_tys: Vec<Ty<'tcx>>,
call_debug_loc: DebugLoc)
-> Block<'blk, 'tcx> -> Block<'blk, 'tcx>
{ {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
@ -370,7 +372,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llfn, llfn,
&llargs_foreign[], &llargs_foreign[],
cc, cc,
Some(attrs)); Some(attrs),
call_debug_loc);
// If the function we just called does not use an outpointer, // If the function we just called does not use an outpointer,
// store the result into the rust outpointer. Cast the outpointer // store the result into the rust outpointer. Cast the outpointer

View file

@ -45,25 +45,39 @@ use std::ffi::CString;
use syntax::ast; use syntax::ast;
use syntax::parse::token; use syntax::parse::token;
pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
size: ValueRef, align: ValueRef) v: ValueRef,
size: ValueRef,
align: ValueRef,
debug_loc: DebugLoc)
-> Block<'blk, 'tcx> { -> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_exchange_free"); let _icx = push_ctxt("trans_exchange_free");
let ccx = cx.ccx(); let ccx = cx.ccx();
callee::trans_lang_call(cx, callee::trans_lang_call(cx,
langcall(cx, None, "", ExchangeFreeFnLangItem), langcall(cx, None, "", ExchangeFreeFnLangItem),
&[PointerCast(cx, v, Type::i8p(ccx)), size, align], &[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, pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
size: u64, align: u32) -> Block<'blk, 'tcx> { v: ValueRef,
trans_exchange_free_dyn(cx, v, C_uint(cx.ccx(), size), size: u64,
C_uint(cx.ccx(), align)) 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, pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
content_ty: Ty<'tcx>) -> Block<'blk, 'tcx> { ptr: ValueRef,
content_ty: Ty<'tcx>,
debug_loc: DebugLoc)
-> Block<'blk, 'tcx> {
assert!(type_is_sized(bcx.ccx().tcx(), content_ty)); assert!(type_is_sized(bcx.ccx().tcx(), content_ty));
let sizing_type = sizing_type_of(bcx.ccx(), content_ty); let sizing_type = sizing_type_of(bcx.ccx(), content_ty);
let content_size = llsize_of_alloc(bcx.ccx(), sizing_type); 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<ZeroSizeType>` does not allocate. // `Box<ZeroSizeType>` does not allocate.
if content_size != 0 { if content_size != 0 {
let content_align = align_of(bcx.ccx(), content_ty); 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 { } else {
bcx bcx
} }
@ -328,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. // Return the sum of sizes and max of aligns.
let size = Add(bcx, sized_size, unsized_size, DebugLoc::None); let size = Add(bcx, sized_size, unsized_size, DebugLoc::None);
let align = Select(bcx, let align = Select(bcx,
ICmp(bcx, llvm::IntULT, sized_align, unsized_align), ICmp(bcx,
llvm::IntULT,
sized_align,
unsized_align,
DebugLoc::None),
sized_align, sized_align,
unsized_align); unsized_align);
(size, align) (size, align)
@ -394,7 +412,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 = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]);
let info = Load(bcx, info); let info = Load(bcx, info);
let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, 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 +422,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
let not_null = IsNotNull(bcx, llbox); let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| { with_cond(bcx, not_null, |bcx| {
let bcx = drop_ty(bcx, llbox, content_ty, DebugLoc::None); 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)
}) })
} }
} }

View file

@ -667,7 +667,7 @@ pub fn trans_object_shim<'a, 'tcx>(
method_offset_in_vtable); method_offset_in_vtable);
bcx = trans_call_inner(bcx, bcx = trans_call_inner(bcx,
None, DebugLoc::None,
method_bare_fn_ty, method_bare_fn_ty,
|bcx, _| trans_trait_callee_from_llval(bcx, |bcx, _| trans_trait_callee_from_llval(bcx,
method_bare_fn_ty, method_bare_fn_ty,

View file

@ -73,11 +73,19 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let unit_size = llsize_of_alloc(ccx, llty); let unit_size = llsize_of_alloc(ccx, llty);
if unit_size != 0 { if unit_size != 0 {
let len = get_len(bcx, vptr); 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| { with_cond(bcx, not_empty, |bcx| {
let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty)); let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty));
let size = Mul(bcx, C_uint(ccx, unit_size), len, DebugLoc::None); 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 { } else {
bcx bcx
@ -439,7 +447,7 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
{ // i < count { // i < count
let lhs = Load(cond_bcx, loop_counter); let lhs = Load(cond_bcx, loop_counter);
let rhs = count; 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); CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb, DebugLoc::None);
} }
@ -493,7 +501,7 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
let data_ptr = let data_ptr =
Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.llbb]); Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.llbb]);
let not_yet_at_end = 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 body_bcx = fcx.new_temp_block("iter_vec_loop_body");
let next_bcx = fcx.new_temp_block("iter_vec_next"); 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); CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb, DebugLoc::None);

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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" {}
}