提交 719a5916 编写于 作者: E Eduard Burtescu

mir: distinguish between variable visibility scopes and SEME scopes.

上级 f3525503
......@@ -32,9 +32,9 @@ pub struct Mir<'tcx> {
/// that indexes into this vector.
pub basic_blocks: Vec<BasicBlockData<'tcx>>,
/// List of lexical scopes; these are referenced by statements and
/// used (eventually) for debuginfo. Indexed by a `ScopeId`.
pub scopes: Vec<ScopeData>,
/// List of visibility (lexical) scopes; these are referenced by statements
/// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`.
pub visibility_scopes: Vec<VisibilityScopeData>,
/// Rvalues promoted from this function, such as borrows of constants.
/// Each of them is the Mir of a constant with the fn's type parameters
......@@ -173,7 +173,7 @@ pub struct VarDecl<'tcx> {
pub ty: Ty<'tcx>,
/// scope in which variable was declared
pub scope: ScopeId,
pub scope: VisibilityScope,
/// span where variable was declared
pub span: Span,
......@@ -276,7 +276,7 @@ pub struct BasicBlockData<'tcx> {
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Terminator<'tcx> {
pub span: Span,
pub scope: ScopeId,
pub scope: VisibilityScope,
pub kind: TerminatorKind<'tcx>
}
......@@ -588,7 +588,7 @@ pub enum AssertMessage<'tcx> {
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct Statement<'tcx> {
pub span: Span,
pub scope: ScopeId,
pub scope: VisibilityScope,
pub kind: StatementKind<'tcx>,
}
......@@ -754,29 +754,32 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
///////////////////////////////////////////////////////////////////////////
// Scopes
impl Index<ScopeId> for Vec<ScopeData> {
type Output = ScopeData;
impl Index<VisibilityScope> for Vec<VisibilityScopeData> {
type Output = VisibilityScopeData;
#[inline]
fn index(&self, index: ScopeId) -> &ScopeData {
fn index(&self, index: VisibilityScope) -> &VisibilityScopeData {
&self[index.index()]
}
}
impl IndexMut<ScopeId> for Vec<ScopeData> {
impl IndexMut<VisibilityScope> for Vec<VisibilityScopeData> {
#[inline]
fn index_mut(&mut self, index: ScopeId) -> &mut ScopeData {
fn index_mut(&mut self, index: VisibilityScope) -> &mut VisibilityScopeData {
&mut self[index.index()]
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct ScopeId(u32);
pub struct VisibilityScope(u32);
impl ScopeId {
pub fn new(index: usize) -> ScopeId {
/// The visibility scope all arguments go into.
pub const ARGUMENT_VISIBILITY_SCOPE: VisibilityScope = VisibilityScope(0);
impl VisibilityScope {
pub fn new(index: usize) -> VisibilityScope {
assert!(index < (u32::MAX as usize));
ScopeId(index as u32)
VisibilityScope(index as u32)
}
pub fn index(self) -> usize {
......@@ -785,9 +788,9 @@ pub fn index(self) -> usize {
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ScopeData {
pub struct VisibilityScopeData {
pub span: Span,
pub parent_scope: Option<ScopeId>,
pub parent_scope: Option<VisibilityScope>,
}
///////////////////////////////////////////////////////////////////////////
......
......@@ -97,9 +97,9 @@ fn visit_basic_block_data(&mut self,
self.super_basic_block_data(block, data);
}
fn visit_scope_data(&mut self,
scope_data: & $($mutability)* ScopeData) {
self.super_scope_data(scope_data);
fn visit_visibility_scope_data(&mut self,
scope_data: & $($mutability)* VisibilityScopeData) {
self.super_visibility_scope_data(scope_data);
}
fn visit_statement(&mut self,
......@@ -236,9 +236,9 @@ fn visit_arg_decl(&mut self,
self.super_arg_decl(arg_decl);
}
fn visit_scope_id(&mut self,
scope_id: & $($mutability)* ScopeId) {
self.super_scope_id(scope_id);
fn visit_visibility_scope(&mut self,
scope: & $($mutability)* VisibilityScope) {
self.super_visibility_scope(scope);
}
// The `super_xxx` methods comprise the default behavior and are
......@@ -248,7 +248,7 @@ fn super_mir(&mut self,
mir: & $($mutability)* Mir<'tcx>) {
let Mir {
ref $($mutability)* basic_blocks,
ref $($mutability)* scopes,
ref $($mutability)* visibility_scopes,
promoted: _, // Visited by passes separately.
ref $($mutability)* return_ty,
ref $($mutability)* var_decls,
......@@ -263,8 +263,8 @@ fn super_mir(&mut self,
self.visit_basic_block_data(block, data);
}
for scope in scopes {
self.visit_scope_data(scope);
for scope in visibility_scopes {
self.visit_visibility_scope_data(scope);
}
self.visit_fn_output(return_ty);
......@@ -302,16 +302,16 @@ fn super_basic_block_data(&mut self,
}
}
fn super_scope_data(&mut self,
scope_data: & $($mutability)* ScopeData) {
let ScopeData {
fn super_visibility_scope_data(&mut self,
scope_data: & $($mutability)* VisibilityScopeData) {
let VisibilityScopeData {
ref $($mutability)* span,
ref $($mutability)* parent_scope,
} = *scope_data;
self.visit_span(span);
if let Some(ref $($mutability)* parent_scope) = *parent_scope {
self.visit_scope_id(parent_scope);
self.visit_visibility_scope(parent_scope);
}
}
......@@ -325,7 +325,7 @@ fn super_statement(&mut self,
} = *statement;
self.visit_span(span);
self.visit_scope_id(scope);
self.visit_visibility_scope(scope);
match *kind {
StatementKind::Assign(ref $($mutability)* lvalue,
ref $($mutability)* rvalue) => {
......@@ -352,7 +352,7 @@ fn super_terminator(&mut self,
} = *terminator;
self.visit_span(span);
self.visit_scope_id(scope);
self.visit_visibility_scope(scope);
self.visit_terminator_kind(block, kind);
}
......@@ -627,7 +627,7 @@ fn super_var_decl(&mut self,
} = *var_decl;
self.visit_ty(ty);
self.visit_scope_id(scope);
self.visit_visibility_scope(scope);
self.visit_span(span);
}
......@@ -651,8 +651,8 @@ fn super_arg_decl(&mut self,
self.visit_ty(ty);
}
fn super_scope_id(&mut self,
_scope_id: & $($mutability)* ScopeId) {
fn super_visibility_scope(&mut self,
_scope: & $($mutability)* VisibilityScope) {
}
fn super_branch(&mut self,
......
......@@ -22,7 +22,7 @@ pub fn ast_block(&mut self,
ast_block: &'tcx hir::Block)
-> BlockAnd<()> {
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
self.in_scope(extent, block, move |this, _| {
self.in_scope(extent, block, move |this| {
// This convoluted structure is to avoid using recursion as we walk down a list
// of statements. Basically, the structure we get back is something like:
//
......@@ -40,27 +40,40 @@ pub fn ast_block(&mut self,
//
// First we build all the statements in the block.
let mut let_extent_stack = Vec::with_capacity(8);
let outer_visibility_scope = this.visibility_scope;
for stmt in stmts {
let Stmt { span: _, kind } = this.hir.mirror(stmt);
match kind {
StmtKind::Expr { scope, expr } => {
unpack!(block = this.in_scope(scope, block, |this, _| {
unpack!(block = this.in_scope(scope, block, |this| {
let expr = this.hir.mirror(expr);
this.stmt_expr(block, expr)
}));
}
StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
let remainder_scope_id = this.push_scope(remainder_scope, block);
let tcx = this.hir.tcx();
// Enter the remainder scope, i.e. the bindings' destruction scope.
this.push_scope(remainder_scope, block);
let_extent_stack.push(remainder_scope);
unpack!(block = this.in_scope(init_scope, block, move |this, _| {
// FIXME #30046 ^~~~
if let Some(init) = initializer {
this.expr_into_pattern(block, remainder_scope_id, pattern, init)
} else {
this.declare_bindings(remainder_scope_id, &pattern);
block.unit()
}
}));
// Declare the bindings, which may create a visibility scope.
let remainder_span = remainder_scope.span(&tcx.region_maps, &tcx.map);
let remainder_span = remainder_span.unwrap_or(span);
let scope = this.declare_bindings(None, remainder_span, &pattern);
// Evaluate the initializer, if present.
if let Some(init) = initializer {
unpack!(block = this.in_scope(init_scope, block, move |this| {
// FIXME #30046 ^~~~
this.expr_into_pattern(block, pattern, init)
}));
}
// Enter the visibility scope, after evaluating the initializer.
if let Some(visibility_scope) = scope {
this.visibility_scope = visibility_scope;
}
}
}
}
......@@ -78,6 +91,8 @@ pub fn ast_block(&mut self,
for extent in let_extent_stack.into_iter().rev() {
unpack!(block = this.pop_scope(extent, block));
}
// Restore the original visibility scope.
this.visibility_scope = outer_visibility_scope;
block.unit()
})
}
......
......@@ -50,7 +50,7 @@ pub fn current_location(&mut self, block: BasicBlock) -> Location {
pub fn push_assign(&mut self,
block: BasicBlock,
scope: ScopeId,
scope: VisibilityScope,
span: Span,
lvalue: &Lvalue<'tcx>,
rvalue: Rvalue<'tcx>) {
......@@ -63,7 +63,7 @@ pub fn push_assign(&mut self,
pub fn push_assign_constant(&mut self,
block: BasicBlock,
scope: ScopeId,
scope: VisibilityScope,
span: Span,
temp: &Lvalue<'tcx>,
constant: Constant<'tcx>) {
......@@ -73,7 +73,7 @@ pub fn push_assign_constant(&mut self,
pub fn push_assign_unit(&mut self,
block: BasicBlock,
scope: ScopeId,
scope: VisibilityScope,
span: Span,
lvalue: &Lvalue<'tcx>) {
self.push_assign(block, scope, span, lvalue, Rvalue::Aggregate(
......@@ -83,7 +83,7 @@ pub fn push_assign_unit(&mut self,
pub fn terminate(&mut self,
block: BasicBlock,
scope: ScopeId,
scope: VisibilityScope,
span: Span,
kind: TerminatorKind<'tcx>) {
debug_assert!(self.block_data(block).terminator.is_none(),
......
......@@ -38,7 +38,7 @@ fn expr_as_lvalue(&mut self,
let expr_span = expr.span;
match expr.kind {
ExprKind::Scope { extent, value } => {
this.in_scope(extent, block, |this, _| this.as_lvalue(block, value))
this.in_scope(extent, block, |this| this.as_lvalue(block, value))
}
ExprKind::Field { lhs, name } => {
let lvalue = unpack!(block = this.as_lvalue(block, lhs));
......
......@@ -35,7 +35,7 @@ fn expr_as_operand(&mut self,
let this = self;
if let ExprKind::Scope { extent, value } = expr.kind {
return this.in_scope(extent, block, |this, _| this.as_operand(block, value));
return this.in_scope(extent, block, |this| this.as_operand(block, value));
}
let category = Category::of(&expr.kind).unwrap();
......
......@@ -46,7 +46,7 @@ fn expr_as_rvalue(&mut self,
match expr.kind {
ExprKind::Scope { extent, value } => {
this.in_scope(extent, block, |this, _| this.as_rvalue(block, value))
this.in_scope(extent, block, |this| this.as_rvalue(block, value))
}
ExprKind::InlineAsm { asm, outputs, inputs } => {
let outputs = outputs.into_iter().map(|output| {
......@@ -100,7 +100,7 @@ fn expr_as_rvalue(&mut self,
let result = this.temp(expr.ty);
// to start, malloc some memory of suitable type (thus far, uninitialized):
this.cfg.push_assign(block, scope_id, expr_span, &result, Rvalue::Box(value.ty));
this.in_scope(value_extents, block, |this, _| {
this.in_scope(value_extents, block, |this| {
// schedule a shallow free of that memory, lest we unwind:
this.schedule_box_free(expr_span, value_extents, &result, value.ty);
// initialize the box contents:
......
......@@ -30,7 +30,7 @@ fn expr_as_temp(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<
let this = self;
if let ExprKind::Scope { extent, value } = expr.kind {
return this.in_scope(extent, block, |this, _| this.as_temp(block, value));
return this.in_scope(extent, block, |this| this.as_temp(block, value));
}
let expr_ty = expr.ty.clone();
......
......@@ -37,7 +37,7 @@ pub fn into_expr(&mut self,
match expr.kind {
ExprKind::Scope { extent, value } => {
this.in_scope(extent, block, |this, _| this.into(destination, block, value))
this.in_scope(extent, block, |this| this.into(destination, block, value))
}
ExprKind::Block { body: ast_block } => {
this.ast_block(destination, expr.ty.is_nil(), block, ast_block)
......
......@@ -26,7 +26,7 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
match expr.kind {
ExprKind::Scope { extent, value } => {
let value = this.hir.mirror(value);
this.in_scope(extent, block, |this, _| this.stmt_expr(block, value))
this.in_scope(extent, block, |this| this.stmt_expr(block, value))
}
ExprKind::Assign { lhs, rhs } => {
let lhs = this.hir.mirror(lhs);
......
......@@ -44,21 +44,11 @@ pub fn match_expr(&mut self,
.collect(),
};
// Get the body expressions and their scopes, while declaring bindings.
let arm_bodies: Vec<_> = arms.iter().enumerate().map(|(i, arm)| {
// Assume that all expressions are wrapped in Scope.
// Get the arm bodies and their scopes, while declaring bindings.
let arm_bodies: Vec<_> = arms.iter().map(|arm| {
let body = self.hir.mirror(arm.body.clone());
match body.kind {
ExprKind::Scope { extent, value } => {
let scope_id = self.push_scope(extent, arm_blocks.blocks[i]);
self.declare_bindings(scope_id, &arm.patterns[0]);
(extent, self.scopes.pop().unwrap(), value)
}
_ => {
span_bug!(body.span, "arm body is not wrapped in Scope {:?}",
body.kind);
}
}
let scope = self.declare_bindings(None, body.span, &arm.patterns[0]);
(body, scope.unwrap_or(self.visibility_scope))
}).collect();
// assemble a list of candidates: there is one candidate per
......@@ -99,63 +89,48 @@ pub fn match_expr(&mut self,
// all the arm blocks will rejoin here
let end_block = self.cfg.start_new_block();
let scope_id = self.innermost_scope_id();
for (arm_index, (extent, scope, body)) in arm_bodies.into_iter().enumerate() {
let outer_visibility_scope = self.innermost_scope_id();
for (arm_index, (body, visibility_scope)) in arm_bodies.into_iter().enumerate() {
let mut arm_block = arm_blocks.blocks[arm_index];
// Re-enter the scope we created the bindings in.
self.scopes.push(scope);
// Re-enter the visibility scope we created the bindings in.
self.visibility_scope = visibility_scope;
unpack!(arm_block = self.into(destination, arm_block, body));
unpack!(arm_block = self.pop_scope(extent, arm_block));
self.cfg.terminate(arm_block,
scope_id,
outer_visibility_scope,
span,
TerminatorKind::Goto { target: end_block });
}
self.visibility_scope = outer_visibility_scope;
end_block.unit()
}
pub fn expr_into_pattern(&mut self,
mut block: BasicBlock,
var_scope_id: ScopeId, // lifetime of vars
irrefutable_pat: Pattern<'tcx>,
initializer: ExprRef<'tcx>)
-> BlockAnd<()> {
// optimize the case of `let x = ...`
match *irrefutable_pat.kind {
PatternKind::Binding { mutability,
name,
mode: BindingMode::ByValue,
PatternKind::Binding { mode: BindingMode::ByValue,
var,
ty,
subpattern: None } => {
let index = self.declare_binding(var_scope_id,
mutability,
name,
var,
ty,
irrefutable_pat.span);
let lvalue = Lvalue::Var(index);
subpattern: None, .. } => {
let lvalue = Lvalue::Var(self.var_indices[&var]);
return self.into(&lvalue, block, initializer);
}
_ => {}
}
let lvalue = unpack!(block = self.as_lvalue(block, initializer));
self.lvalue_into_pattern(block,
var_scope_id,
irrefutable_pat,
&lvalue)
}
pub fn lvalue_into_pattern(&mut self,
mut block: BasicBlock,
var_scope_id: ScopeId,
irrefutable_pat: Pattern<'tcx>,
initializer: &Lvalue<'tcx>)
-> BlockAnd<()> {
// first, creating the bindings
self.declare_bindings(var_scope_id, &irrefutable_pat);
// create a dummy candidate
let mut candidate = Candidate {
span: irrefutable_pat.span,
......@@ -182,32 +157,43 @@ pub fn lvalue_into_pattern(&mut self,
block.unit()
}
pub fn declare_bindings(&mut self, var_scope_id: ScopeId, pattern: &Pattern<'tcx>) {
/// Declares the bindings of the given pattern and returns the visibility scope
/// for the bindings in this patterns, if such a scope had to be created.
/// NOTE: Declaring the bindings should always be done in their drop scope.
pub fn declare_bindings(&mut self,
mut var_scope: Option<VisibilityScope>,
scope_span: Span,
pattern: &Pattern<'tcx>)
-> Option<VisibilityScope> {
match *pattern.kind {
PatternKind::Binding { mutability, name, mode: _, var, ty, ref subpattern } => {
self.declare_binding(var_scope_id, mutability, name, var, ty, pattern.span);
if var_scope.is_none() {
var_scope = Some(self.new_visibility_scope(scope_span));
}
self.declare_binding(var_scope.unwrap(), mutability, name, var, ty, pattern.span);
if let Some(subpattern) = subpattern.as_ref() {
self.declare_bindings(var_scope_id, subpattern);
var_scope = self.declare_bindings(var_scope, scope_span, subpattern);
}
}
PatternKind::Array { ref prefix, ref slice, ref suffix } |
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
for subpattern in prefix.iter().chain(slice).chain(suffix) {
self.declare_bindings(var_scope_id, subpattern);
var_scope = self.declare_bindings(var_scope, scope_span, subpattern);
}
}
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
}
PatternKind::Deref { ref subpattern } => {
self.declare_bindings(var_scope_id, subpattern);
var_scope = self.declare_bindings(var_scope, scope_span, subpattern);
}
PatternKind::Leaf { ref subpatterns } |
PatternKind::Variant { ref subpatterns, .. } => {
for subpattern in subpatterns {
self.declare_bindings(var_scope_id, &subpattern.pattern);
var_scope = self.declare_bindings(var_scope, scope_span, &subpattern.pattern);
}
}
}
var_scope
}
}
......@@ -635,7 +621,7 @@ fn bind_matched_candidate(&mut self,
}
fn declare_binding(&mut self,
var_scope_id: ScopeId,
var_scope_id: VisibilityScope,
mutability: Mutability,
name: Name,
var_id: NodeId,
......@@ -655,7 +641,7 @@ fn declare_binding(&mut self,
span: span,
});
let index = index as u32;
let extent = self.scope_auxiliary[var_scope_id].extent;
let extent = self.extent_of_innermost_scope();
self.schedule_drop(span, extent, &Lvalue::Var(index), var_ty);
self.var_indices.insert(var_id, index);
......
......@@ -103,7 +103,7 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
pub fn push_usize(&mut self,
block: BasicBlock,
scope_id: ScopeId,
scope_id: VisibilityScope,
span: Span,
value: u64)
-> Lvalue<'tcx> {
......
......@@ -15,6 +15,7 @@
use rustc_data_structures::fnv::FnvHashMap;
use rustc::hir;
use std::ops::{Index, IndexMut};
use std::u32;
use syntax::abi::Abi;
use syntax::ast;
use syntax::codemap::Span;
......@@ -43,7 +44,8 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
/// the vector of all scopes that we have created thus far;
/// we track this for debuginfo later
scope_datas: Vec<ScopeData>,
visibility_scopes: Vec<VisibilityScopeData>,
visibility_scope: VisibilityScope,
var_decls: Vec<VarDecl<'tcx>>,
var_indices: FnvHashMap<ast::NodeId, u32>,
......@@ -61,6 +63,20 @@ struct CFG<'tcx> {
basic_blocks: Vec<BasicBlockData<'tcx>>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ScopeId(u32);
impl ScopeId {
pub fn new(index: usize) -> ScopeId {
assert!(index < (u32::MAX as usize));
ScopeId(index as u32)
}
pub fn index(self) -> usize {
self.0 as usize
}
}
/// For each scope, we track the extent (from the HIR) and a
/// single-entry-multiple-exit subgraph that contains all the
/// statements/terminators within it.
......@@ -179,17 +195,16 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
tcx.region_maps.lookup_code_extent(
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id });
let mut block = START_BLOCK;
let mut arg_decls = unpack!(block = builder.in_scope(call_site_extent, block,
|builder, call_site_scope_id| {
let arg_decls = unpack!(block = builder.in_scope(arg_extent, block,
|builder, arg_scope_id| {
builder.args_and_body(block, return_ty, arguments, arg_scope_id, ast_block)
let mut arg_decls = unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
let arg_decls = unpack!(block = builder.in_scope(arg_extent, block, |builder| {
builder.args_and_body(block, return_ty, arguments, arg_extent, ast_block)
}));
let visibility_scope = builder.visibility_scope;
let return_block = builder.return_block();
builder.cfg.terminate(block, call_site_scope_id, span,
builder.cfg.terminate(block, visibility_scope, span,
TerminatorKind::Goto { target: return_block });
builder.cfg.terminate(return_block, call_site_scope_id, span,
builder.cfg.terminate(return_block, visibility_scope, span,
TerminatorKind::Return);
return_block.and(arg_decls)
}));
......@@ -241,14 +256,15 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
let extent = ROOT_CODE_EXTENT;
let mut block = START_BLOCK;
let _ = builder.in_scope(extent, block, |builder, call_site_scope_id| {
let _ = builder.in_scope(extent, block, |builder| {
let expr = builder.hir.mirror(ast_expr);
unpack!(block = builder.into(&Lvalue::ReturnPointer, block, expr));
let visibility_scope = builder.visibility_scope;
let return_block = builder.return_block();
builder.cfg.terminate(block, call_site_scope_id, span,
builder.cfg.terminate(block, visibility_scope, span,
TerminatorKind::Goto { target: return_block });
builder.cfg.terminate(return_block, call_site_scope_id, span,
builder.cfg.terminate(return_block, visibility_scope, span,
TerminatorKind::Return);
return_block.unit()
......@@ -265,7 +281,8 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span) -> Builder<'a, 'gcx, 'tcx> {
cfg: CFG { basic_blocks: vec![] },
fn_span: span,
scopes: vec![],
scope_datas: vec![],
visibility_scopes: vec![],
visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
scope_auxiliary: ScopeAuxiliaryVec { vec: vec![] },
loop_scopes: vec![],
temp_decls: vec![],
......@@ -277,6 +294,8 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span) -> Builder<'a, 'gcx, 'tcx> {
};
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
assert_eq!(builder.new_visibility_scope(span), ARGUMENT_VISIBILITY_SCOPE);
builder.visibility_scopes[ARGUMENT_VISIBILITY_SCOPE].parent_scope = None;
builder
}
......@@ -294,7 +313,7 @@ fn finish(self,
(Mir {
basic_blocks: self.cfg.basic_blocks,
scopes: self.scope_datas,
visibility_scopes: self.visibility_scopes,
promoted: vec![],
var_decls: self.var_decls,
arg_decls: arg_decls,
......@@ -309,24 +328,22 @@ fn args_and_body<A>(&mut self,
mut block: BasicBlock,
return_ty: ty::FnOutput<'tcx>,
arguments: A,
argument_scope_id: ScopeId,
argument_extent: CodeExtent,
ast_block: &'gcx hir::Block)
-> BlockAnd<Vec<ArgDecl<'tcx>>>
where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
{
// to start, translate the argument patterns and collect the argument types.
let mut scope = None;
let arg_decls = arguments.enumerate().map(|(index, (ty, pattern))| {
let lvalue = Lvalue::Arg(index as u32);
if let Some(pattern) = pattern {
let pattern = self.hir.irrefutable_pat(pattern);
unpack!(block = self.lvalue_into_pattern(block,
argument_scope_id,
pattern,
&lvalue));
scope = self.declare_bindings(scope, ast_block.span, &pattern);
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
}
// Make sure we drop (parts of) the argument even when not matched on.
let argument_extent = self.scope_auxiliary[argument_scope_id].extent;
self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span),
argument_extent, &lvalue, ty);
......@@ -344,6 +361,11 @@ fn args_and_body<A>(&mut self,
}
}).collect();
// Enter the argument pattern bindings visibility scope, if it exists.
if let Some(visibility_scope) = scope {
self.visibility_scope = visibility_scope;
}
// FIXME(#32959): temporary hack for the issue at hand
let return_is_unit = if let ty::FnConverging(t) = return_ty {
t.is_nil()
......
......@@ -86,7 +86,7 @@
*/
use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary};
use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary, ScopeId};
use rustc::middle::region::{CodeExtent, CodeExtentData};
use rustc::middle::lang_items;
use rustc::ty::subst::{Substs, Subst, VecPerParamSpace};
......@@ -98,9 +98,12 @@
use rustc_const_math::ConstInt;
pub struct Scope<'tcx> {
/// the scope-id within the scope_datas
/// the scope-id within the scope_auxiliary
id: ScopeId,
/// The visibility scope this scope was created in.
visibility_scope: VisibilityScope,
/// the extent of this scope within source code; also stored in
/// `ScopeAuxiliary`, but kept here for convenience
extent: CodeExtent,
......@@ -237,11 +240,11 @@ pub fn in_loop_scope<F>(&mut self,
/// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards.
pub fn in_scope<F, R>(&mut self, extent: CodeExtent, mut block: BasicBlock, f: F) -> BlockAnd<R>
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>, ScopeId) -> BlockAnd<R>
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
{
debug!("in_scope(extent={:?}, block={:?})", extent, block);
let id = self.push_scope(extent, block);
let rv = unpack!(block = f(self, id));
self.push_scope(extent, block);
let rv = unpack!(block = f(self));
unpack!(block = self.pop_scope(extent, block));
debug!("in_scope: exiting extent={:?} block={:?}", extent, block);
block.and(rv)
......@@ -251,17 +254,13 @@ pub fn in_scope<F, R>(&mut self, extent: CodeExtent, mut block: BasicBlock, f: F
/// scope and call `pop_scope` afterwards. Note that these two
/// calls must be paired; using `in_scope` as a convenience
/// wrapper maybe preferable.
pub fn push_scope(&mut self, extent: CodeExtent, entry: BasicBlock) -> ScopeId {
pub fn push_scope(&mut self, extent: CodeExtent, entry: BasicBlock) {
debug!("push_scope({:?})", extent);
let parent_id = self.scopes.last().map(|s| s.id);
let id = ScopeId::new(self.scope_datas.len());
let tcx = self.hir.tcx();
self.scope_datas.push(ScopeData {
span: extent.span(&tcx.region_maps, &tcx.map).unwrap_or(DUMMY_SP),
parent_scope: parent_id,
});
let id = ScopeId::new(self.scope_auxiliary.vec.len());
let vis_scope = self.visibility_scope;
self.scopes.push(Scope {
id: id,
visibility_scope: vis_scope,
extent: extent,
drops: vec![],
free: None,
......@@ -272,7 +271,6 @@ pub fn push_scope(&mut self, extent: CodeExtent, entry: BasicBlock) -> ScopeId {
dom: self.cfg.current_location(entry),
postdoms: vec![]
});
id
}
/// Pops a scope, which should have extent `extent`, adding any
......@@ -320,7 +318,7 @@ pub fn exit_scope(&mut self,
if let Some(ref free_data) = scope.free {
let next = self.cfg.start_new_block();
let free = build_free(self.hir.tcx(), &tmp, free_data, next);
self.cfg.terminate(block, scope.id, span, free);
self.cfg.terminate(block, scope.visibility_scope, span, free);
block = next;
}
self.scope_auxiliary[scope.id]
......@@ -334,11 +332,22 @@ pub fn exit_scope(&mut self,
.next()
.unwrap();
self.cfg.terminate(block,
scope.id,
scope.visibility_scope,
span,
TerminatorKind::Goto { target: target });
}
/// Creates a new visibility scope, nested in the current one.
pub fn new_visibility_scope(&mut self, span: Span) -> VisibilityScope {
let parent = self.visibility_scope;
let scope = VisibilityScope::new(self.visibility_scopes.len());
self.visibility_scopes.push(VisibilityScopeData {
span: span,
parent_scope: Some(parent),
});
scope
}
// Finding scopes
// ==============
/// Finds the loop scope for a given label. This is used for
......@@ -363,8 +372,8 @@ pub fn find_loop_scope(&mut self,
}.unwrap_or_else(|| span_bug!(span, "no enclosing loop scope found?"))
}
pub fn innermost_scope_id(&self) -> ScopeId {
self.scopes.last().map(|scope| scope.id).unwrap()
pub fn innermost_scope_id(&self) -> VisibilityScope {
self.visibility_scope
}
pub fn extent_of_innermost_scope(&self) -> CodeExtent {
......@@ -481,7 +490,10 @@ pub fn diverge_cleanup(&mut self) -> Option<BasicBlock> {
target
} else {
let resumeblk = cfg.start_new_cleanup_block();
cfg.terminate(resumeblk, scopes[0].id, self.fn_span, TerminatorKind::Resume);
cfg.terminate(resumeblk,
scopes[0].visibility_scope,
self.fn_span,
TerminatorKind::Resume);
*cached_resume_block = Some(resumeblk);
resumeblk
};
......@@ -658,7 +670,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
earlier_scopes.iter().rev().flat_map(|s| s.cached_block()).next()
});
let next = cfg.start_new_block();
cfg.terminate(block, scope.id, drop_data.span, TerminatorKind::Drop {
cfg.terminate(block, scope.visibility_scope, drop_data.span, TerminatorKind::Drop {
location: drop_data.location.clone(),
target: next,
unwind: on_diverge
......@@ -695,7 +707,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
} else {
let into = cfg.start_new_cleanup_block();
cfg.terminate(into,
scope.id,
scope.visibility_scope,
free_data.span,
build_free(tcx, unit_temp, free_data, target));
free_data.cached_block = Some(into);
......@@ -712,7 +724,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
} else {
let block = cfg.start_new_cleanup_block();
cfg.terminate(block,
scope.id,
scope.visibility_scope,
drop_data.span,
TerminatorKind::Drop {
location: drop_data.location.clone(),
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use build::{Location, ScopeAuxiliaryVec};
use build::{Location, ScopeAuxiliaryVec, ScopeId};
use rustc::hir;
use rustc::mir::repr::*;
use rustc::mir::transform::MirSource;
......@@ -139,20 +139,11 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
write_mir_intro(tcx, src, mir, w)?;
for block in mir.all_basic_blocks() {
write_basic_block(tcx, block, mir, w, &annotations)?;
if block.index() + 1 != mir.basic_blocks.len() {
writeln!(w, "")?;
}
}
// construct a scope tree and write it out
let mut scope_tree: FnvHashMap<Option<ScopeId>, Vec<ScopeId>> = FnvHashMap();
for (index, scope_data) in mir.scopes.iter().enumerate() {
scope_tree.entry(scope_data.parent_scope)
.or_insert(vec![])
.push(ScopeId::new(index));
}
writeln!(w, "{}scope tree:", INDENT)?;
write_scope_tree(tcx, mir, auxiliary, &scope_tree, w, None, 1, false)?;
writeln!(w, "")?;
writeln!(w, "}}")?;
Ok(())
}
......@@ -204,66 +195,59 @@ fn write_basic_block(tcx: TyCtxt,
writeln!(w, "{}}}\n", INDENT)
}
fn comment(tcx: TyCtxt, scope: ScopeId, span: Span) -> String {
fn comment(tcx: TyCtxt, scope: VisibilityScope, span: Span) -> String {
format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
}
fn write_scope_tree(tcx: TyCtxt,
mir: &Mir,
auxiliary: Option<&ScopeAuxiliaryVec>,
scope_tree: &FnvHashMap<Option<ScopeId>, Vec<ScopeId>>,
scope_tree: &FnvHashMap<VisibilityScope, Vec<VisibilityScope>>,
w: &mut Write,
parent: Option<ScopeId>,
depth: usize,
same_line: bool)
parent: VisibilityScope,
depth: usize)
-> io::Result<()> {
let indent = if same_line {
0
} else {
depth * INDENT.len()
};
let indent = depth * INDENT.len();
let children = match scope_tree.get(&parent) {
Some(childs) => childs,
None => return Ok(()),
};
for (index, &child) in children.iter().enumerate() {
if index == 0 && same_line {
// We know we're going to output a scope, so prefix it with a space to separate it from
// the previous scopes on this line
write!(w, " ")?;
}
let data = &mir.scopes[child];
assert_eq!(data.parent_scope, parent);
write!(w, "{0:1$}{2}", "", indent, child.index())?;
for &child in children {
let data = &mir.visibility_scopes[child];
assert_eq!(data.parent_scope, Some(parent));
writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
let indent = indent + INDENT.len();
// User variable types (including the user's name in a comment).
for (i, var) in mir.var_decls.iter().enumerate() {
// Skip if not declared in this scope.
if var.scope != child {
continue;
}
if let Some(auxiliary) = auxiliary {
let extent = auxiliary[child].extent;
let data = tcx.region_maps.code_extent_data(extent);
writeln!(w, "{0:1$}Extent: {2:?}", "", indent, data)?;
let mut_str = if var.mutability == Mutability::Mut {
"mut "
} else {
""
};
let indent = indent + INDENT.len();
let indented_var = format!("{0:1$}let {2}{3:?}: {4};",
INDENT,
indent,
mut_str,
Lvalue::Var(i as u32),
var.ty);
writeln!(w, "{0:1$} // \"{2}\" in {3}",
indented_var,
ALIGN,
var.name,
comment(tcx, var.scope, var.span))?;
}
let child_count = scope_tree.get(&Some(child)).map(Vec::len).unwrap_or(0);
if child_count < 2 {
// Skip the braces when there's no or only a single subscope
write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
Some(child), depth, true)?;
} else {
// 2 or more child scopes? Put them in braces and on new lines.
writeln!(w, " {{")?;
write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
Some(child), depth + 1, false)?;
write!(w, "\n{0:1$}}}", "", depth * INDENT.len())?;
}
write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
if !same_line && index + 1 < children.len() {
writeln!(w, "")?;
}
writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?;
}
Ok(())
......@@ -278,7 +262,23 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-> io::Result<()> {
write_mir_sig(tcx, src, mir, w)?;
writeln!(w, " {{")?;
write_mir_decls(tcx, mir, w)
// construct a scope tree and write it out
let mut scope_tree: FnvHashMap<VisibilityScope, Vec<VisibilityScope>> = FnvHashMap();
for (index, scope_data) in mir.visibility_scopes.iter().enumerate() {
if let Some(parent) = scope_data.parent_scope {
scope_tree.entry(parent)
.or_insert(vec![])
.push(VisibilityScope::new(index));
} else {
// Only the argument scope has no parent, because it's the root.
assert_eq!(index, ARGUMENT_VISIBILITY_SCOPE.index());
}
}
write_scope_tree(tcx, mir, &scope_tree, w, ARGUMENT_VISIBILITY_SCOPE, 1)?;
write_mir_decls(mir, w)
}
fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
......@@ -318,29 +318,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
}
}
fn write_mir_decls(tcx: TyCtxt, mir: &Mir, w: &mut Write)
-> io::Result<()>
{
// User variable types (including the user's name in a comment).
for (i, var) in mir.var_decls.iter().enumerate() {
let mut_str = if var.mutability == Mutability::Mut {
"mut "
} else {
""
};
let indented_var = format!("{}let {}{:?}: {};",
INDENT,
mut_str,
Lvalue::Var(i as u32),
var.ty);
writeln!(w, "{0:1$} // \"{2}\" in {3}",
indented_var,
ALIGN,
var.name,
comment(tcx, var.scope, var.span))?;
}
fn write_mir_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
// Compiler-introduced temporary types.
for (i, temp) in mir.temp_decls.iter().enumerate() {
writeln!(w, "{}let mut {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty)?;
......
......@@ -168,7 +168,7 @@ fn new_block(&mut self) -> BasicBlock {
statements: vec![],
terminator: Some(Terminator {
span: self.promoted.span,
scope: ScopeId::new(0),
scope: VisibilityScope::new(0),
kind: TerminatorKind::Return
}),
is_cleanup: false
......@@ -180,7 +180,7 @@ fn assign(&mut self, dest: Lvalue<'tcx>, rvalue: Rvalue<'tcx>, span: Span) {
let data = self.promoted.basic_blocks.last_mut().unwrap();
data.statements.push(Statement {
span: span,
scope: ScopeId::new(0),
scope: VisibilityScope::new(0),
kind: StatementKind::Assign(dest, rvalue)
});
}
......@@ -367,7 +367,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
source: mir,
promoted: Mir {
basic_blocks: vec![],
scopes: vec![ScopeData {
visibility_scopes: vec![VisibilityScopeData {
span: span,
parent_scope: None
}],
......
......@@ -16,7 +16,7 @@
use llvm::debuginfo::{DIScope, DISubprogram};
use common::{CrateContext, FunctionContext};
use rustc::hir::pat_util;
use rustc::mir::repr::{Mir, ScopeId};
use rustc::mir::repr::{Mir, VisibilityScope};
use rustc::util::nodemap::NodeMap;
use libc::c_uint;
......@@ -71,7 +71,7 @@ pub fn create_scope_map(cx: &CrateContext,
/// If debuginfo is disabled, the returned vector is empty.
pub fn create_mir_scopes(fcx: &FunctionContext) -> Vec<DIScope> {
let mir = fcx.mir.clone().expect("create_mir_scopes: missing MIR for fn");
let mut scopes = vec![ptr::null_mut(); mir.scopes.len()];
let mut scopes = vec![ptr::null_mut(); mir.visibility_scopes.len()];
let fn_metadata = match fcx.debug_context {
FunctionDebugContext::RegularContext(box ref data) => data.fn_metadata,
......@@ -82,14 +82,14 @@ pub fn create_mir_scopes(fcx: &FunctionContext) -> Vec<DIScope> {
};
// Find all the scopes with variables defined in them.
let mut has_variables = BitVector::new(mir.scopes.len());
let mut has_variables = BitVector::new(mir.visibility_scopes.len());
for var in &mir.var_decls {
has_variables.insert(var.scope.index());
}
// Instantiate all scopes.
for idx in 0..mir.scopes.len() {
let scope = ScopeId::new(idx);
for idx in 0..mir.visibility_scopes.len() {
let scope = VisibilityScope::new(idx);
make_mir_scope(fcx.ccx, &mir, &has_variables, fn_metadata, scope, &mut scopes);
}
......@@ -100,14 +100,14 @@ fn make_mir_scope(ccx: &CrateContext,
mir: &Mir,
has_variables: &BitVector,
fn_metadata: DISubprogram,
scope: ScopeId,
scope: VisibilityScope,
scopes: &mut [DIScope]) {
let idx = scope.index();
if !scopes[idx].is_null() {
return;
}
let scope_data = &mir.scopes[scope];
let scope_data = &mir.visibility_scopes[scope];
let parent_scope = if let Some(parent) = scope_data.parent_scope {
make_mir_scope(ccx, mir, has_variables, fn_metadata, parent, scopes);
scopes[parent.index()]
......
......@@ -266,16 +266,13 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
let mut idx = 0;
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
// Get the argument scope assuming ScopeId(0) has no parent.
let arg_scope = mir.scopes.get(0).and_then(|data| {
let scope = scopes[0];
if data.parent_scope.is_none() && !scope.is_null() &&
bcx.sess().opts.debuginfo == FullDebugInfo {
Some(scope)
} else {
None
}
});
// Get the argument scope, if it exists and if we need it.
let arg_scope = scopes[mir::ARGUMENT_VISIBILITY_SCOPE.index()];
let arg_scope = if !arg_scope.is_null() && bcx.sess().opts.debuginfo == FullDebugInfo {
Some(arg_scope)
} else {
None
};
mir.arg_decls.iter().enumerate().map(|(arg_index, arg_decl)| {
let arg_ty = bcx.monomorphize(&arg_decl.ty);
......
......@@ -247,11 +247,10 @@
// lldb-command:continue
#![allow(dead_code, unused_assignments, unused_variables)]
#![feature(omit_gdb_pretty_printer_section, rustc_attrs)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn immediate_args(a: isize, b: bool, c: f64) {
println!("");
}
......@@ -268,51 +267,43 @@ struct BigStruct {
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn non_immediate_args(a: BigStruct, b: BigStruct) {
println!("");
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn binding(a: i64, b: u64, c: f64) {
let x = 0;
println!("");
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn assignment(mut a: u64, b: u64, c: f64) {
a = b;
println!("");
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn function_call(x: u64, y: u64, z: f64) {
println!("Hi!")
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn identifier(x: u64, y: u64, z: f64) -> u64 {
x
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn return_expr(x: u64, y: u64, z: f64) -> u64 {
return x;
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
x + y
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn if_expr(x: u64, y: u64, z: f64) -> u64 {
if x + y < 1000 {
x
......@@ -322,7 +313,6 @@ fn if_expr(x: u64, y: u64, z: f64) -> u64 {
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
while x + y < 1000 {
x += z
......@@ -331,7 +321,6 @@ fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
}
#[no_stack_check]
#[rustc_no_mir] // FIXME(#32949) MIR debuginfo shadows arguments with uninit vars.
fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
loop {
x += z;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册