Skip to content

Commit 11e0635

Browse files
committed
---
yaml --- r: 276799 b: refs/heads/try c: 6a3b558 h: refs/heads/master i: 276797: 8ab4868 276795: 1ca5ea9 276791: bd7021b 276783: 2631ef8 276767: dd40690 276735: c449fb3
1 parent a1949b3 commit 11e0635

File tree

15 files changed

+554
-57
lines changed

15 files changed

+554
-57
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 6dbb0e86aec11050480beb76eade6fb805010ba7
33
refs/heads/snap-stage3: 235d77457d80b549dad3ac36d94f235208a1eafb
4-
refs/heads/try: 913a2b4b0525c75ecf915076c4fd1e16187f8b51
4+
refs/heads/try: 6a3b5585061e34bc87374adec993a6b1f0ec2a55
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/configure

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ opt inject-std-version 1 "inject the current compiler version of libstd into pro
608608
opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
609609
opt rustbuild 0 "use the rust and cargo based build system"
610610
opt orbit 0 "get MIR where it belongs - everywhere; most importantly, in orbit"
611+
opt codegen-tests 1 "run the src/test/codegen tests"
611612

612613
# Optimization and debugging options. These may be overridden by the release channel, etc.
613614
opt_nosave optimize 1 "build optimized rust code"
@@ -1497,7 +1498,9 @@ do
14971498
LLVM_INST_DIR=$CFG_LLVM_ROOT
14981499
do_reconfigure=0
14991500
# Check that LLVm FileCheck is available. Needed for the tests
1500-
need_cmd $LLVM_INST_DIR/bin/FileCheck
1501+
if [ -z "$CFG_DISABLE_CODEGEN_TESTS" ]; then
1502+
need_cmd $LLVM_INST_DIR/bin/FileCheck
1503+
fi
15011504
fi
15021505

15031506
if [ ${do_reconfigure} -ne 0 ]

branches/try/mk/tests.mk

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,15 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
305305
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
306306
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \
307307
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \
308-
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
309-
check-stage$(1)-T-$(2)-H-$(3)-codegen-units-exec \
310308
check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
311309
check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
312310

311+
ifndef CFG_DISABLE_CODEGEN_TESTS
312+
check-stage$(1)-T-$(2)-H-$(3)-exec: \
313+
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
314+
check-stage$(1)-T-$(2)-H-$(3)-codegen-units-exec
315+
endif
316+
313317
# Only test the compiler-dependent crates when the target is
314318
# able to build a compiler (when the target triple is in the set of host triples)
315319
ifneq ($$(findstring $(2),$$(CFG_HOST)),)

branches/try/src/libcore/num/dec2flt/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ from_str_float_impl!(f64);
154154
/// for [`f32`] and [`f64`].
155155
///
156156
/// [`FromStr`]: ../str/trait.FromStr.html
157-
/// [`f32`]: ../primitive.f32.html
158-
/// [`f64`]: ../primitive.f64.html
157+
/// [`f32`]: ../../std/primitive.f32.html
158+
/// [`f64`]: ../../std/primitive.f64.html
159159
#[derive(Debug, Clone, PartialEq)]
160160
#[stable(feature = "rust1", since = "1.0.0")]
161161
pub struct ParseFloatError {

branches/try/src/librustc_data_structures/bitvec.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::iter::FromIterator;
12+
1113
/// A very simple BitVector type.
14+
#[derive(Clone)]
1215
pub struct BitVector {
1316
data: Vec<u64>,
1417
}
@@ -50,7 +53,9 @@ impl BitVector {
5053
pub fn grow(&mut self, num_bits: usize) {
5154
let num_words = u64s(num_bits);
5255
let extra_words = self.data.len() - num_words;
53-
self.data.extend((0..extra_words).map(|_| 0));
56+
if extra_words > 0 {
57+
self.data.extend((0..extra_words).map(|_| 0));
58+
}
5459
}
5560

5661
/// Iterates over indexes of set bits in a sorted order
@@ -93,6 +98,27 @@ impl<'a> Iterator for BitVectorIter<'a> {
9398
}
9499
}
95100

101+
impl FromIterator<bool> for BitVector {
102+
fn from_iter<I>(iter: I) -> BitVector where I: IntoIterator<Item=bool> {
103+
let iter = iter.into_iter();
104+
let (len, _) = iter.size_hint();
105+
// Make the minimum length for the bitvector 64 bits since that's
106+
// the smallest non-zero size anyway.
107+
let len = if len < 64 { 64 } else { len };
108+
let mut bv = BitVector::new(len);
109+
for (idx, val) in iter.enumerate() {
110+
if idx > len {
111+
bv.grow(idx);
112+
}
113+
if val {
114+
bv.insert(idx);
115+
}
116+
}
117+
118+
bv
119+
}
120+
}
121+
96122
/// A "bit matrix" is basically a square matrix of booleans
97123
/// represented as one gigantic bitvector. In other words, it is as if
98124
/// you have N bitvectors, each of length N. Note that `elements` here is `N`/

branches/try/src/librustc_driver/driver.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -881,10 +881,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
881881
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
882882
passes.push_pass(box mir::transform::type_check::TypeckMir);
883883
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg);
884-
// Late passes
885-
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
886884
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
887-
passes.push_pass(box mir::transform::erase_regions::EraseRegions);
888885
// And run everything.
889886
passes.run_passes(tcx, &mut mir_map);
890887
});
@@ -937,16 +934,25 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
937934

938935
/// Run the translation phase to LLVM, after which the AST and analysis can
939936
pub fn phase_4_translate_to_llvm<'tcx>(tcx: &TyCtxt<'tcx>,
940-
mir_map: MirMap<'tcx>,
941-
analysis: ty::CrateAnalysis)
942-
-> trans::CrateTranslation {
937+
mut mir_map: MirMap<'tcx>,
938+
analysis: ty::CrateAnalysis) -> trans::CrateTranslation {
943939
let time_passes = tcx.sess.time_passes();
944940

945941
time(time_passes,
946942
"resolving dependency formats",
947943
|| dependency_format::calculate(&tcx.sess));
948944

949-
// Option dance to work around the lack of stack once closures.
945+
// Run the passes that transform the MIR into a more suitable for translation
946+
// to LLVM code.
947+
time(time_passes, "Prepare MIR codegen passes", || {
948+
let mut passes = ::rustc::mir::transform::Passes::new();
949+
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
950+
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
951+
passes.push_pass(box mir::transform::erase_regions::EraseRegions);
952+
passes.push_pass(box mir::transform::break_critical_edges::BreakCriticalEdges);
953+
passes.run_passes(tcx, &mut mir_map);
954+
});
955+
950956
time(time_passes,
951957
"translation",
952958
move || trans::trans_crate(tcx, &mir_map, analysis))

branches/try/src/librustc_mir/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ mod hair;
4242
pub mod mir_map;
4343
pub mod pretty;
4444
pub mod transform;
45+
pub mod traversal;
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use rustc::ty::TyCtxt;
12+
use rustc::mir::repr::*;
13+
use rustc::mir::transform::{MirPass, Pass};
14+
use syntax::ast::NodeId;
15+
16+
use rustc_data_structures::bitvec::BitVector;
17+
18+
use traversal;
19+
20+
pub struct BreakCriticalEdges;
21+
22+
/**
23+
* Breaks critical edges in the MIR.
24+
*
25+
* Critical edges are edges that are neither the only edge leaving a
26+
* block, nor the only edge entering one.
27+
*
28+
* When you want something to happen "along" an edge, you can either
29+
* do at the end of the predecessor block, or at the start of the
30+
* successor block. Critical edges have to be broken in order to prevent
31+
* "edge actions" from affecting other edges.
32+
*
33+
* This function will break those edges by inserting new blocks along them.
34+
*
35+
* A special case is Drop and Call terminators with unwind/cleanup successors,
36+
* They use `invoke` in LLVM, which terminates a block, meaning that code cannot
37+
* be inserted after them, so even if an edge is the only edge leaving a block
38+
* like that, we still insert blocks if the edge is one of many entering the
39+
* target.
40+
*
41+
* NOTE: Simplify CFG will happily undo most of the work this pass does.
42+
*
43+
*/
44+
45+
impl<'tcx> MirPass<'tcx> for BreakCriticalEdges {
46+
fn run_pass(&mut self, _: &TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) {
47+
break_critical_edges(mir);
48+
}
49+
}
50+
51+
impl Pass for BreakCriticalEdges {}
52+
53+
fn break_critical_edges(mir: &mut Mir) {
54+
let mut pred_count = vec![0u32; mir.basic_blocks.len()];
55+
56+
// Build the precedecessor map for the MIR
57+
for (_, data) in traversal::preorder(mir) {
58+
if let Some(ref term) = data.terminator {
59+
for &tgt in term.successors().iter() {
60+
pred_count[tgt.index()] += 1;
61+
}
62+
}
63+
}
64+
65+
let cleanup_map : BitVector = mir.basic_blocks
66+
.iter().map(|bb| bb.is_cleanup).collect();
67+
68+
// We need a place to store the new blocks generated
69+
let mut new_blocks = Vec::new();
70+
71+
let bbs = mir.all_basic_blocks();
72+
let cur_len = mir.basic_blocks.len();
73+
74+
for &bb in &bbs {
75+
let data = mir.basic_block_data_mut(bb);
76+
77+
if let Some(ref mut term) = data.terminator {
78+
let is_invoke = term_is_invoke(term);
79+
let term_span = term.span;
80+
let term_scope = term.scope;
81+
let succs = term.successors_mut();
82+
if succs.len() > 1 || (succs.len() > 0 && is_invoke) {
83+
for tgt in succs {
84+
let num_preds = pred_count[tgt.index()];
85+
if num_preds > 1 {
86+
// It's a critical edge, break it
87+
let goto = Terminator {
88+
span: term_span,
89+
scope: term_scope,
90+
kind: TerminatorKind::Goto { target: *tgt }
91+
};
92+
let mut data = BasicBlockData::new(Some(goto));
93+
data.is_cleanup = cleanup_map.contains(tgt.index());
94+
95+
// Get the index it will be when inserted into the MIR
96+
let idx = cur_len + new_blocks.len();
97+
new_blocks.push(data);
98+
*tgt = BasicBlock::new(idx);
99+
}
100+
}
101+
}
102+
}
103+
}
104+
105+
debug!("Broke {} N edges", new_blocks.len());
106+
107+
mir.basic_blocks.extend_from_slice(&new_blocks);
108+
}
109+
110+
// Returns true if the terminator would use an invoke in LLVM.
111+
fn term_is_invoke(term: &Terminator) -> bool {
112+
match term.kind {
113+
TerminatorKind::Call { cleanup: Some(_), .. } |
114+
TerminatorKind::Drop { unwind: Some(_), .. } => true,
115+
_ => false
116+
}
117+
}

branches/try/src/librustc_mir/transform/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ pub mod simplify_cfg;
1313
pub mod erase_regions;
1414
pub mod no_landing_pads;
1515
pub mod type_check;
16+
pub mod break_critical_edges;

0 commit comments

Comments
 (0)