2af8155bee
#16081 fixed an issue where a nested return statement would cause incorrect behaviour due to the inner return writing over the return stack slot that had already been written too. However, the check was very broad and picked many cases that wouldn't ever be affected by this issue. As a result, the number of allocas increased dramatically and therefore stack-size increased. LLVM is not able to remove all of the extraneous allocas. Any code that had multiple return values in a compound expression at the end of a function (including loops) would be hit by the issue. The check now uses a control-flow graph to only consider the case when the inner return is executed conditionally. By itself, this narrowed definition causes #15763 to return, so the control-flow graph is also used to avoid passing the return slot as a destination when the result won't be used. This change allows the stack-size of the main rustc task to be reduced to 8MB from 32MB.
56 lines
1.4 KiB
Rust
56 lines
1.4 KiB
Rust
// Copyright 2012 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.
|
|
|
|
//! Module that constructs a control-flow graph representing an item.
|
|
//! Uses `Graph` as the underlying representation.
|
|
|
|
use middle::graph;
|
|
use middle::ty;
|
|
use syntax::ast;
|
|
use util::nodemap::NodeMap;
|
|
|
|
mod construct;
|
|
pub mod graphviz;
|
|
|
|
pub struct CFG {
|
|
pub exit_map: NodeMap<CFGIndex>,
|
|
pub graph: CFGGraph,
|
|
pub entry: CFGIndex,
|
|
pub exit: CFGIndex,
|
|
}
|
|
|
|
#[deriving(Copy)]
|
|
pub struct CFGNodeData {
|
|
pub id: ast::NodeId
|
|
}
|
|
|
|
pub struct CFGEdgeData {
|
|
pub exiting_scopes: Vec<ast::NodeId>
|
|
}
|
|
|
|
pub type CFGIndex = graph::NodeIndex;
|
|
|
|
pub type CFGGraph = graph::Graph<CFGNodeData, CFGEdgeData>;
|
|
|
|
pub type CFGNode = graph::Node<CFGNodeData>;
|
|
|
|
pub type CFGEdge = graph::Edge<CFGEdgeData>;
|
|
|
|
impl CFG {
|
|
pub fn new(tcx: &ty::ctxt,
|
|
blk: &ast::Block) -> CFG {
|
|
construct::construct(tcx, blk)
|
|
}
|
|
|
|
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
|
|
self.graph.depth_traverse(self.entry).any(|node| node.id == id)
|
|
}
|
|
}
|