492 Commits

Author SHA1 Message Date
bors
8cbffc5bcf Auto merge of #33905 - eddyb:mir-overflow, r=nikomatsakis
[MIR] Implement overflow checking

The initial set of changes is from @Aatch's #33255 PR, rebased on master, plus:

Added an `Assert` terminator to MIR, to simplify working with overflow and bounds checks.
With this terminator, error cases can be accounted for directly, instead of looking for lang item calls.
It also keeps the MIR slimmer, with no extra explicit blocks for the actual panic calls.

Warnings can be produced when the `Assert` is known to always panic at runtime, e.g.:
```rust
warning: index out of bounds: the len is 1 but the index is 3
 --> <anon>:1:14
1 |> fn main() { &[std::io::stdout()][3]; }
  |>              ^^^^^^^^^^^^^^^^^^^^^^
```

Generalized the `OperandValue::FatPtr` optimization to any aggregate pair of immediates.
This allows us to generate the same IR for overflow checks as old trans, not something worse.
For example, addition on `i16` calls `llvm.sadd.with.overflow.i16`, which returns `{i16, i1}`.
However, the Rust type `(i16, bool)`, has to be `{i16, i8}`, only an immediate `bool` is `i1`.
But if we split the pair into an `i16` and an `i1`, we can pass them around as such for free.

The latest addition is a rebase of #34054, updated to work for pairs too. Closes #34054, fixes #33873.

Last but not least, the `#[rustc_inherit_overflow_checks]` attribute was introduced to control the
overflow checking behavior of generic or `#[inline]` functions, when translated in another crate.

It is **not** intended to be used by crates other than `libcore`, which is in the unusual position of
being distributed as only an optimized build with no checks, even when used from debug mode.
Before MIR-based translation, this worked out fine, as the decision for overflow was made at
translation time, in the crate being compiled, but MIR stored in `rlib` has to contain the checks.

To avoid always generating the checks and slowing everything down, a decision was made to
use an attribute in the few spots of `libcore` that need it (see #33255 for previous discussion):
* `core::ops::{Add, Sub, Mul, Neg, Shl, Shr}` implementations for integers, which have `#[inline]` methods and can be used in generic abstractions from other crates
* `core::ops::{Add, Sub, Mul, Neg, Shl, Shr}Assign` same as above, for augmented assignment
* `pow` and `abs` methods on integers, which intentionally piggy-back on built-in multiplication and negation, respectively, to get overflow checks
* `core::iter::{Iterator, Chain, Peek}::count` and `core::iter::Enumerate::{next, nth}`, also documented as panicking on overflow, from addition, counting elements of an iterator in an `usize`
2016-06-05 06:08:37 -07:00
Eduard Burtescu
d8dddbf201 Respect #[rustc_inherit_overflow_checks] in mir::build and trans. 2016-06-05 14:41:03 +03:00
Eduard Burtescu
4adc967ed1 mir: report when overflow checks would be missing cross-crate. 2016-06-05 14:41:03 +03:00
Eduard Burtescu
156b1fb9e1 Add a new Assert terminator to MIR for bounds & arithmetic checks. 2016-06-05 14:41:02 +03:00
James Miller
7fbff36d01 Change with_cond to build_cond_br
This is simpler to work with than `with_cond`.
2016-06-05 14:02:24 +03:00
James Miller
f2c983b248 Add a with_cond method
Factors out the common pattern across the several places that do
arithmetic checks
2016-06-05 14:02:24 +03:00
James Miller
73f3054288 Check arithmetic in the MIR
Add, Sub, Mul, Shl, and Shr are checked using a new Rvalue:
CheckedBinaryOp, while Div, Rem and Neg are handled with explicit checks
in the MIR.
2016-06-05 14:02:24 +03:00
bors
22b36c70f9 Auto merge of #33999 - scottcarr:master, r=nikomatsakis
generate fewer basic blocks for variant switches

CC #33567
Adds a new field to TestKind::Switch that tracks the variants that are actually matched against.  The other candidates target a common "otherwise" block.
2016-06-05 03:12:38 -07:00
Ariel Ben-Yehuda
4106ab24d7 break critical edges only when needed
the *only* place where critical edges need to be broken is on Call
instructions, so only break them there.
2016-06-05 09:27:26 +03:00
Ariel Ben-Yehuda
148f8422f3 check for is_cleanup violations in MIR typeck
There weren't any in practice, but as these cause MSVC-only problems, the
check looks like a good idea.
2016-06-03 16:11:18 +03:00
Ariel Ben-Yehuda
de7cb0fdd6 introduce DropAndReplace for translating assignments
this introduces a DropAndReplace terminator as a fix to #30380. That terminator
is suppsoed to be translated by desugaring during drop elaboration, which is
not implemented in this commit, so this breaks `-Z orbit` temporarily.
2016-06-03 16:11:18 +03:00
Scott A Carr
d4551ece5f remove trailing whitespace 2016-06-02 15:40:03 -07:00
bors
12d165352c Auto merge of #33583 - luqmana:tri-bool-mir, r=arielb1
MIR: Don't generate 3-armed boolean switch from match.

Fixes #33540.

Snippet from issue:
```Rust
fn foo(x: bool, y: bool) -> u32 {
    match (x, y) {
         (false, _) => 0,
         (_, false) => 1,
         (true, true) => 2,
    }
}
```

Generated MIR:
```
fn foo(arg0: bool, arg1: bool) -> u32 {
    let var0: bool;                      // "x" in scope 1 at 3bbm.rs:17:8: 17:9
    let var1: bool;                      // "y" in scope 1 at 3bbm.rs:17:17: 17:18
    let mut tmp0: (bool, bool);
    let mut tmp1: bool;
    let mut tmp2: bool;
    let mut tmp3: (&'static str, &'static str, u32);
    let mut tmp4: &'static (&'static str, &'static str, u32);

    bb0: {
        var0 = arg0;                     // scope 1 at 3bbm.rs:17:8: 17:9
        var1 = arg1;                     // scope 1 at 3bbm.rs:17:17: 17:18
        tmp1 = var0;                     // scope 5 at 3bbm.rs:18:12: 18:13
        tmp2 = var1;                     // scope 6 at 3bbm.rs:18:15: 18:16
        tmp0 = (tmp1, tmp2);             // scope 4 at 3bbm.rs:18:11: 18:17
        if((tmp0.0: bool)) -> [true: bb4, false: bb1]; // scope 3 at 3bbm.rs:19:10: 19:15
    }

    bb1: {
        return = const 0u32;             // scope 10 at 3bbm.rs:19:23: 19:24
        goto -> bb7;                     // scope 3 at 3bbm.rs:18:5: 22:6
    }

    bb2: {
        return = const 1u32;             // scope 11 at 3bbm.rs:20:23: 20:24
        goto -> bb7;                     // scope 3 at 3bbm.rs:18:5: 22:6
    }

    bb3: {
        return = const 2u32;             // scope 12 at 3bbm.rs:21:25: 21:26
        goto -> bb7;                     // scope 3 at 3bbm.rs:18:5: 22:6
    }

    bb4: {
        if((tmp0.1: bool)) -> [true: bb5, false: bb2]; // scope 3 at 3bbm.rs:20:13: 20:18
    }

    bb5: {
        if((tmp0.0: bool)) -> [true: bb3, false: bb6]; // scope 3 at 3bbm.rs:21:10: 21:14
    }

    bb6: {
        tmp4 = promoted0;                // scope 3 at 3bbm.rs:18:5: 22:6
        core::panicking::panic(tmp4);    // scope 3 at 3bbm.rs:18:5: 22:6
    }

    bb7: {
        return;                          // scope 0 at 3bbm.rs:17:1: 23:2
    }
}
```

Not sure about this approach. I was also thinking maybe just a standalone pass?

cc @arielb1, @nagisa
2016-06-02 10:55:43 -07:00
Luqman Aden
a97f6b35ac [MIR] Use If terminator for switches on bools rather than SwitchInt. 2016-06-01 21:02:36 -04:00
Scott A Carr
79bf586d4b switch to BitVector, simplify target_block logic
clarify comments and panic message
2016-06-01 10:23:56 -07:00
Scott A Carr
9d34c280d9 generate fewer basic blocks for variant switches 2016-05-31 17:08:00 -07:00
Ariel Ben-Yehuda
e3cff797a7 normalize types in MIR typeck after erasing regions 2016-05-31 18:42:47 +03:00
Vadim Petrochenkov
cf46820694 Refactor away some functions from hir::pat_util 2016-05-28 17:37:58 +03:00
Vadim Petrochenkov
216f5fba04 Separate bindings from other patterns in HIR 2016-05-28 00:54:29 +03:00
Vadim Petrochenkov
35ef09c38b Replace pat_adjust_pos with an iterator adapter 2016-05-26 11:11:58 +03:00
Vadim Petrochenkov
d69aeaf662 Implement .. in tuple (struct) patterns 2016-05-26 11:11:58 +03:00
bors
34fd686681 Auto merge of #33667 - pnkfelix:fixes-to-mir-dataflow, r=arielb1
Fixes to mir dataflow

Fixes to mir dataflow

This collects a bunch of changes to `rustc_borrowck::borrowck::dataflow` (which others have pointed out should probably migrate to some crate that isn't tied to the borrow-checker -- but I have not attempted that here, especially since there are competing approaches to dataflow that we should also evaluate).

These changes:
 1. Provide a family of related analyses: MovingOutStatements (which is what the old AST-based dataflo computed), as well as MaybeInitialized, MaybeUninitalized, and DefinitelyInitialized.
   * (The last two are actually inverses of each other; we should pick one and drop the other.)
 2. Fix bugs in the pre-existing analysis implementation, which was untested and thus some obvious bugs went unnoticed, which brings us to the third point:
 3. Add a unit test infrastructure for the MIR dataflow analysis.
   * The tests work by adding a new intrinsic that is able to query the analysis state for a particular expression (technically, a particular L-value).
   * See the examples in compile-fail/mir-dataflow/inits-1.rs and compile-fail/mir-dataflow/uninits-1.rs
   * These tests are only checking the results for MaybeInitialized, MaybeUninitalized, and DefinitelyInitialized; I am not sure if it will be feasible to generalize this testing strategy to the MovingOutStatements dataflow operator.
2016-05-25 12:34:39 -07:00
Vadim Petrochenkov
aad347c4f7 Remove hir::Ident 2016-05-16 22:25:08 +03:00
Felix S. Klock II
129b371cae One-line doc clarification for representation of unit type (). 2016-05-16 09:13:42 +02:00
Felix S. Klock II
4446e793da Expose pretty print routines that accept just mir (no need for a NodeId). 2016-05-16 09:13:42 +02:00
Felix S. Klock II
90b7a86268 rustc_mir::pretty refactoring: break fn write_fn_intro into two routines.
(The crucial thing these changes are working toward (but are not yet
in this commit) is a way to pretty-print MIR without having the
`NodeId` for that MIR in hand.)
2016-05-16 09:13:42 +02:00
Felix S. Klock II
306ca4ca4f rustc_mir::pretty: factor out scope entry/exit annotation computation. 2016-05-16 09:13:42 +02:00
bors
e7420fbbae Auto merge of #33620 - eddyb:oops-static-is-not-fn, r=dotdash
mir: always allow &mut [...] in static mut regardless of the array length.
2016-05-15 11:01:03 -07:00
bors
1a26d2364f Auto merge of #33607 - jonas-schievink:prettier-mir, r=eddyb
Some simple improvements to MIR pretty printing

In short, this PR changes the MIR printer so that it:

* places an empty line between the MIR for each item
* does *not* write an empty line before the first BB when there are no
  var decls
* aligns the "// Scope" comments 50 chars in (makes the output more
  readable)
* prints the scope comments as "// scope N at ..." instead of "//
  Scope(N) at ..."
* prints a prettier scope tree:
 * no more unbalanced delimiters!
 * no more "Parent" entry (these convey no useful information)
 * drop the "Scope()" and just print scope IDs
 * no braces when the scope is empty

In action: https://gist.github.com/jonas-schievink/1c11226cbb112892a9470ce0f9870b65
2016-05-15 01:14:10 -07:00
Manish Goregaokar
ea68dd8def Rollup merge of #33552 - dotdash:scfg, r=luqmana
[MIR] Enhance the SimplifyCfg pass to merge consecutive blocks

Updated from #30238, including the changes suggested by @Aatch.
2016-05-14 11:57:47 +02:00
Manish Goregaokar
36c4c6d433 Rollup merge of #33544 - dotdash:baby_dont_break_me_no_more, r=Aatch
Only break critical edges where actually needed

Currently, to prepare for MIR trans, we break _all_ critical edges,
although we only actually need to do this for edges originating from a
call that gets translated to an invoke instruction in LLVM.

This has the unfortunate effect of undoing a bunch of the things that
SimplifyCfg has done. A particularly bad case arises when you have a
C-like enum with N variants and a derived PartialEq implementation.

In that case, the match on the (&lhs, &rhs) tuple gets translated into
nested matches with N arms each and a basic block each, resulting in N²
basic blocks. SimplifyCfg reduces that to roughly 2*N basic blocks, but
breaking the critical edges means that we go back to N².

In nickel.rs, there is such an enum with roughly N=800. So we get about
640K basic blocks or 2.5M lines of LLVM IR. LLVM takes a while to
reduce that to the final "disr_a == disr_b".

So before this patch, we had 2.5M lines of IR with 640K basic blocks,
which took about about 3.6s in LLVM to get optimized and translated.
After this patch, we get about 650K lines with about 1.6K basic blocks
and spent a little less than 0.2s in LLVM.

cc #33111

r? @Aatch
2016-05-14 11:57:47 +02:00
Jonas Schievink
2c7e398935 Indent comments less
40 chars is still enough indentation (most common MIR statements don't
take more than 40 chars), and fits more easily in 80-character
terminals.
2016-05-13 23:40:06 +02:00
Jonas Schievink
95a968c426 Much smaller scope tree printing 2016-05-13 23:36:50 +02:00
Eduard Burtescu
55aae6f48e mir: always allow &mut [...] in static mut regardless of the array length. 2016-05-13 22:27:09 +03:00
bors
a581c82bdc Auto merge of #33541 - eddyb:promote-only-temps, r=arielb1
mir: don't attempt to promote Unpromotable constant temps.

Fixes #33537. This was a non-problem in regular functions, but we also promote in `const fn`s.
There we always qualify temps so you can't depend on `Unpromotable` temps being `NOT_CONST`.
2016-05-13 03:10:46 -07:00
Björn Steinbrink
8ad6d27f87 [MIR] Enhance the SimplifyCfg pass to merge consecutive blocks 2016-05-13 01:46:52 +02:00
Jonas Schievink
96b178b131 Some simple improvements to MIR pretty printing
In short, this PR changes the MIR printer so that it:

* places an empty line between the MIR for each item
* does *not* write an empty line before the first BB when there are no
  var decls
* aligns the "// Scope" comments 50 chars in (makes the output more
  readable)
* prints the scope comments as "// scope N at ..." instead of "//
  Scope(N) at ..."
* prints a prettier scope tree:
 * no more unbalanced delimiters!
 * no more "Parent" entry (these convey no useful information)
 * drop the "Scope()" and just print scope IDs
 * no braces when the scope is empty
2016-05-13 00:20:59 +02:00
Björn Steinbrink
00f6513259 Only break critical edges where actually needed
Currently, to prepare for MIR trans, we break _all_ critical edges,
although we only actually need to do this for edges originating from a
call that gets translated to an invoke instruction in LLVM.

This has the unfortunate effect of undoing a bunch of the things that
SimplifyCfg has done. A particularly bad case arises when you have a
C-like enum with N variants and a derived PartialEq implementation.

In that case, the match on the (&lhs, &rhs) tuple gets translated into
nested matches with N arms each and a basic block each, resulting in N²
basic blocks. SimplifyCfg reduces that to roughly 2*N basic blocks, but
breaking the critical edges means that we go back to N².

In nickel.rs, there is such an enum with roughly N=800. So we get about
640K basic blocks or 2.5M lines of LLVM IR. LLVM takes a while to
reduce that to the final "disr_a == disr_b".

So before this patch, we had 2.5M lines of IR with 640K basic blocks,
which took about about 3.6s in LLVM to get optimized and translated.
After this patch, we get about 650K lines with about 1.6K basic blocks
and spent a little less than 0.2s in LLVM.

cc #33111
2016-05-11 18:35:12 +02:00
bors
c049541741 Auto merge of #33239 - eddyb:mir-temp-drops, r=arielb1
mir: drop temps outside-in by scheduling the drops inside-out.

It was backwards all along, but only noticeable with multiple drops in one rvalue scope. Fixes #32433.
2016-05-11 03:15:05 -07:00
Eduard Burtescu
e940de64ca mir: drop temps outside-in by scheduling the drops inside-out. 2016-05-11 10:46:36 +03:00
Eduard Burtescu
a1c170fc35 rustc: Split local type contexts interners from the global one. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
20652162ca rustc: More interning for data used in Ty<'tcx>. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
12e56ea56b rustc: Wrap users of InferCtxt in an anonymous scope. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
8a704f6dc7 rustc: Remove the TyCtxt field from ParameterEnvironment. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
76affa5d6f rustc: Split 'tcx into 'gcx and 'tcx for InferCtxt and its users. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
513d392f7e rustc: Replace &'a TyCtxt<'tcx> with a TyCtxt<'a, 'tcx> wrapper. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
f8ea24edc8 rustc: Avoid free functions taking &TyCtxt and &InferCtxt. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
0907c198c4 infer: Use methods for creating an InferCtxt. 2016-05-11 04:14:58 +03:00
Eduard Burtescu
e5a91b7ba1 mir: don't attempt to promote Unpromotable constant temps. 2016-05-10 21:26:34 +03:00
Eduard Burtescu
ed66fe48e9 Implement RFC 1440 "Allow Drop types in statics/const functions". 2016-05-07 19:14:33 +03:00