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:
commit
d4a66e9b09
@ -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<ast::Expr> {
|
||||
|
||||
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<Pat>) -> P<Pat> {
|
||||
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) => {
|
||||
|
@ -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<ast::Pat> {
|
||||
pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat> {
|
||||
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<ast::Pat> {
|
||||
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<ast::Pat> {
|
||||
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::Pat> {
|
||||
}
|
||||
|
||||
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::Pat> {
|
||||
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::Pat> {
|
||||
|
||||
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 {
|
||||
|
@ -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;
|
||||
@ -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<adt::Repr<'tcx>>, 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<adt::Repr<'tcx>>, 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)]
|
||||
@ -352,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> {
|
||||
@ -405,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()
|
||||
}
|
||||
@ -449,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()
|
||||
@ -527,18 +546,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)
|
||||
};
|
||||
|
||||
@ -556,34 +575,50 @@ 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<Opt<'p, 'tcx>> {
|
||||
let tcx = bcx.tcx();
|
||||
|
||||
let mut found: Vec<Opt> = vec![];
|
||||
for br in m {
|
||||
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 {
|
||||
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,30 +814,32 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option<uint> {
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
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 +849,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"),
|
||||
},
|
||||
@ -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));
|
||||
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
|
||||
@ -1054,12 +1091,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;
|
||||
@ -1068,8 +1105,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 },
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
@ -1095,10 +1132,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) => {
|
||||
@ -1121,22 +1160,33 @@ 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 }) => {
|
||||
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);
|
||||
Result::new(bcx, And(bcx, llge, llle, DebugLoc::None))
|
||||
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)
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -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) {
|
||||
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;
|
||||
@ -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)
|
||||
}).collect();
|
||||
|
||||
let mut static_inliner = StaticInliner::new(scope_cx.tcx());
|
||||
let arm_pats: Vec<Vec<P<ast::Pat>>> = 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<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();
|
||||
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()
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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};
|
||||
@ -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;
|
||||
@ -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))
|
||||
}
|
||||
@ -538,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),
|
||||
@ -559,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) -> ! {
|
||||
@ -586,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 {
|
||||
@ -598,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 {
|
||||
@ -610,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -621,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(_) => {
|
||||
@ -632,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,
|
||||
@ -641,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,
|
||||
@ -657,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.
|
||||
@ -851,7 +856,7 @@ pub fn cast_shift_rhs<F, G>(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,
|
||||
@ -864,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: {}",
|
||||
@ -879,7 +886,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:
|
||||
@ -908,12 +915,13 @@ 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, span,
|
||||
controlflow::trans_fail(bcx,
|
||||
call_info,
|
||||
InternedString::new(overflow_text))
|
||||
})
|
||||
})
|
||||
|
@ -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<AttrBuilder>) -> ValueRef {
|
||||
if cx.unreachable.get() { return _UndefReturn(cx, fn_); }
|
||||
pub fn CallWithConv(cx: Block,
|
||||
fn_: ValueRef,
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -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<expr::Dest>)
|
||||
dest: Option<expr::Dest>,
|
||||
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<NodeIdAndSpan>,
|
||||
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,
|
||||
@ -816,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);
|
||||
@ -831,7 +846,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 +907,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 +1029,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]
|
||||
};
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
@ -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,16 +780,20 @@ 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,
|
||||
index_expr.span,
|
||||
expr_info(index_expr),
|
||||
ix_val,
|
||||
len)
|
||||
});
|
||||
@ -1574,7 +1580,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 +1590,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 +1602,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<ZeroSizeType>`.
|
||||
@ -1697,8 +1709,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 +1727,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)
|
||||
@ -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 => {
|
||||
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")
|
||||
}
|
||||
@ -1845,7 +1874,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 +1901,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| {
|
||||
|
@ -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<Ty<'tcx>>)
|
||||
passed_arg_tys: Vec<Ty<'tcx>>,
|
||||
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
|
||||
|
@ -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<ZeroSizeType>` 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
|
||||
}
|
||||
@ -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.
|
||||
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)
|
||||
@ -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 = 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 +422,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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -73,11 +73,19 @@ 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);
|
||||
glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign)
|
||||
glue::trans_exchange_free_dyn(bcx,
|
||||
dataptr,
|
||||
size,
|
||||
llalign,
|
||||
DebugLoc::None)
|
||||
})
|
||||
} else {
|
||||
bcx
|
||||
@ -439,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);
|
||||
}
|
||||
@ -493,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);
|
||||
|
92
src/test/debuginfo/constant-in-match-pattern.rs
Normal file
92
src/test/debuginfo/constant-in-match-pattern.rs
Normal 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" {}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user