use middle::const_val::ConstVal;
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
+use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
+use rustc_data_structures::control_flow_graph::ControlFlowGraph;
use hir::def_id::DefId;
use ty::subst::Substs;
use ty::{self, AdtDef, ClosureSubsts, FnOutput, Region, Ty};
use std::fmt::{self, Debug, Formatter, Write};
use std::{iter, u32};
use std::ops::{Index, IndexMut};
+use std::vec::IntoIter;
use syntax::ast::{self, Name};
- use syntax::codemap::Span;
+ use syntax_pos::Span;
use super::cache::Cache;
}
/// Lowered representation of a single function.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Mir<'tcx> {
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
/// that indexes into this vector.
Ref::map(self.predecessors(), |p| &p[bb])
}
+ #[inline]
+ pub fn dominators(&self) -> Dominators<BasicBlock> {
+ dominators(self)
+ }
+
/// Maps locals (Arg's, Var's, Temp's and ReturnPointer, in that order)
/// to their index in the whole list of locals. This is useful if you
/// want to treat all locals the same instead of repeating yourself.
fn item_path_str(def_id: DefId) -> String {
ty::tls::with(|tcx| tcx.item_path_str(def_id))
}
+
+impl<'tcx> ControlFlowGraph for Mir<'tcx> {
+
+ type Node = BasicBlock;
+
+ fn num_nodes(&self) -> usize { self.basic_blocks.len() }
+
+ fn start_node(&self) -> Self::Node { START_BLOCK }
+
+ fn predecessors<'graph>(&'graph self, node: Self::Node)
+ -> <Self as GraphPredecessors<'graph>>::Iter
+ {
+ self.predecessors_for(node).clone().into_iter()
+ }
+ fn successors<'graph>(&'graph self, node: Self::Node)
+ -> <Self as GraphSuccessors<'graph>>::Iter
+ {
+ self.basic_blocks[node].terminator().successors().into_owned().into_iter()
+ }
+}
+
+impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {
+ type Item = BasicBlock;
+ type Iter = IntoIter<BasicBlock>;
+}
+
+impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> {
+ type Item = BasicBlock;
+ type Iter = IntoIter<BasicBlock>;
+}
// except according to those terms.
use ast;
- use codemap::{Pos, Span};
- use codemap;
+ use syntax_pos::{self, Pos, Span};
use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use parse;
use print::pprust;
use ptr::P;
+ use tokenstream;
use util::small_vector::SmallVector;
use std::fs::File;
// a given file into the current one.
/// line!(): expands to the current line number
- pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
base::check_zero_tts(cx, sp, tts, "line!");
}
/* column!(): expands to the current column number */
- pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
base::check_zero_tts(cx, sp, tts, "column!");
/// file!(): expands to the current filename */
/// The filemap (`loc.file`) contains a bunch more information we could spit
/// out if we wanted.
- pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
base::check_zero_tts(cx, sp, tts, "file!");
base::MacEager::expr(cx.expr_str(topmost, filename))
}
- pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
let s = pprust::tts_to_string(tts);
base::MacEager::expr(cx.expr_str(sp,
token::intern_and_get_ident(&s[..])))
}
- pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
base::check_zero_tts(cx, sp, tts, "module_path!");
let string = cx.mod_path()
/// include! : parse the given file as an expr
/// This is generally a bad idea because it's going to behave
/// unhygienically.
- pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'cx> {
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
Some(f) => f,
}
// include_str! : read the given file, insert it as a literal string expr
- pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
Some(f) => f,
}
}
- pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
Some(f) => f,
// resolve a file-system path to an absolute file-system path (if it
// isn't already)
- fn res_rel_file(cx: &mut ExtCtxt, sp: codemap::Span, arg: &Path) -> PathBuf {
+ fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: &Path) -> PathBuf {
// NB: relative paths are resolved relative to the compilation unit
if !arg.is_absolute() {
- let mut cu = PathBuf::from(&cx.codemap().span_to_filename(sp));
+ let callsite = cx.codemap().source_callsite(sp);
+ let mut cu = PathBuf::from(&cx.codemap().span_to_filename(callsite));
cu.pop();
cu.push(arg);
cu