| Age | Commit message (Collapse) | Author | Lines |
|
Initially MIR differentiated between arguments and locals, which
introduced a need to add extra copies assigning the argument to a
local, even for simple bindings. This differentiation no longer exists,
but we're still creating those copies, bloating the MIR and LLVM IR we
emit.
Additionally, the current approach means that we create debug info for
both the incoming argument (marking it as an argument), and then
immediately shadow it a local that goes by the same name. This can be
confusing when using e.g. "info args" in gdb, or when e.g. a debugger
with a GUI displays the function arguments separately from the local
variables, especially when the binding is mutable, because the argument
doesn't change, while the local variable does.
|
|
|
|
|
|
Modify MIR testing to require consecutive lines
MIR testing now requires that lines be consecutive. To achive this,
instead of collecting the expected mir as a string, it is now wrapped in
an `ExpectedLine` enum, that is either `Elision` or `Text(T)` where `T:
AsRef<str>`. `Text` lines must be matched in order, unless separated by
`Elision` lines. Elision occurs lazily, that is, an Elision will skip
as few lines as possible.
To add a new elision marker. Put a comment containing only "..." and
whitespace in any MIR testing block. Like so:
```
// fn write_42(_1: *mut i32) -> bool {
// ...
// bb0: {
// Validate(Acquire, [_1: *mut i32]);
// Validate(Release, [_1: *mut i32]);
// ...
// return;
// }
// }
```
Right now, all input before the line right after `// START` is elided,
and all input after the line right before `// END` is also not tested.
Many tests need to be updated. That will follow in the next commit.
cc #45153
r? @nikomatsakis
|
|
|
|
|
|
|
|
|
|
|
|
Driveby fix to end_region_9.rs; it was missing END marker and was
therefore always passing (regardless of output correctness).
|
|
|
|
Debugflag: -Z emit-end-regions
Skip EndRegion emission by default. Use `-Z emit-end-regions` to reenable it.
The main intent is to fix cases where `EndRegion` emission is believed to be causing excess peak memory pressure.
It may also be a welcome change to people inspecting the MIR output who find the EndRegions to be a distraction.
(In later follow-up PR's I will put in safe-guards against using the current mir-borrowck without enabling `EndRegion` emission. But I wanted this PR to be minimal, in part because we may wish to backport it to the beta channel if we find that it reduces peak memory usage significantly.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
We started emitting StorageDead, so we better emit the corrseponding
StorageLive to avoid problems.
|
|
For box expressions, use NZ drop instead of a free block
This falls naturally out of making drop elaboration work with `box`
expressions, which is probably required for sane MIR borrow-checking.
This is a pure refactoring with no intentional functional effects.
r? @nagisa
|
|
test MIR validation statements in closures
r? @nikomatsakis
|
|
This falls naturally out of making drop elaboration work with `box`
expressions, which is probably required for sane MIR borrow-checking.
This is a pure refactoring with no intentional functional effects.
|
|
|
|
APFloat: Rewrite It In Rust and use it for deterministic floating-point CTFE.
As part of the CTFE initiative, we're forced to find a solution for floating-point operations.
By design, IEEE-754 does not explicitly define everything in a deterministic manner, and there is some variability between platforms, at the very least (e.g. NaN payloads).
If types are to evaluate constant expressions involving type (or in the future, const) generics, that evaluation needs to be *fully deterministic*, even across `rustc` host platforms.
That is, if `[T; T::X]` was used in a cross-compiled library, and the evaluation of `T::X` executed a floating-point operation, that operation has to be reproducible on *any other host*, only knowing `T` and the definition of the `X` associated const (as either AST or HIR).
Failure to uphold those rules allows an associated type (e.g. `<Foo as Iterator>::Item`) to be seen as two (or more) different types, depending on the current host, and such type safety violations typically allow writing of a `transmute` in safe code, given enough generics.
The options considered by @rust-lang/compiler were:
1. Ban floating-point operations in generic const-evaluation contexts
2. Emulate floating-point operations in an uniformly deterministic fashion
The former option may seem appealing at first, but floating-point operations *are allowed today*, so they can't be banned wholesale, a distinction has to be made between the code that already works, and future generic contexts. *Moreover*, every computation that succeeded *has to be cached*, otherwise the generic case can be reproduced without any generics. IMO there are too many ways it can go wrong, and a single violation can be enough for an unsoundness hole.
Not to mention we may end up really wanting floating-point operations *anyway*, in CTFE.
I went with the latter option, and seeing how LLVM *already* has a library for this exact purpose (as it needs to perform optimizations independently of host floating-point capabilities), i.e. `APFloat`, that was what I ended up basing this PR on.
But having been burned by the low reusability of bindings that link to LLVM, and because I would *rather* the floating-point operations to be wrong than not deterministic or not memory-safe (`APFloat` does far more pointer juggling than I'm comfortable with), I decided to RIIR.
This way, we have a guarantee of *no* `unsafe` code, a bit more control over the where native floating-point might accidentally be involved, and non-LLVM backends can share it.
I've also ported all the testcases over, *before* any functionality, to catch any mistakes.
Currently the PR replaces all CTFE operations to go through `apfloat::ieee::{Single,Double}`, keeping only the bits of the `f32` / `f64` memory representation in between operations.
Converting from a string also double-checks that `core::num` and `apfloat` agree on the interpretation of a floating-point number literal, in case either of them has any bugs left around.
r? @nikomatsakis
f? @nagisa @est31
<hr/>
Huge thanks to @edef1c for first demoing usable `APFloat` bindings and to @chandlerc for fielding my questions on IRC about `APFloat` peculiarities (also upstreaming some bugfixes).
|
|
|
|
Add MIR Validate statement
This adds statements to MIR that express when types are to be validated (following [Types as Contracts](https://internals.rust-lang.org/t/types-as-contracts/5562)). Obviously nothing is stabilized, and in fact a `-Z` flag has to be passed for behavior to even change at all.
This is meant to make experimentation with Types as Contracts in miri possible. The design is definitely not final.
Cc @nikomatsakis @aturon
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/ unsafe function
|
|
Removing nops can allow more basic blocks to be merged, but merging
basic blocks can't allow for more nops to be removed, so we should
remove nops first.
This doesn't matter *that* much, because normally we run SimplifyCfg
several times, but there's no reason not to do it.
|
|
The unused blocks are removed by SimplifyCfg, but they can cause a
significant performance slowdown before they are removed.
|
|
|
|
|
|
|
|
The tests use `-Z identify_regions` so one can eyeball output for
sanity. The tests with closures use `-Z span_free_formats` so that
host-specific paths do not get embedded into the dumped MIR.
The tests check against MIR dump output immediately prior to borrowck
(determined by hand to be the dump from after the "qualify-consts"
pass) since that is when `EndRegion` will be most relevant in the near
term.
|
|
Fixes #41888.
|
|
introduce local-scope to prevent `StorageLive`/`StorageDead` in statics
In investigating #36799, I found that we were creating storage-live/storage-dead instructions in statics/constants, where they are not needed. This arose due to the fix for local scopes. This PR tries to fix that (and adds a test -- I'm curious if there is a way to make that test more targeted, though).
r? @arielb1
|
|
cc #36799
|
|
|
|
|
|
Overall goal: reduce the amount of context a mir pass needs so that it
resembles a query.
- The hooks are no longer "threaded down" to the pass, but rather run
automatically from the top-level (we also thread down the current pass
number, so that the files are sorted better).
- The hook now receives a *single* callback, rather than a callback per-MIR.
- The traits are no longer lifetime parameters, which moved to the
methods -- given that we required
`for<'tcx>` objecs, there wasn't much point to that.
- Several passes now store a `String` instead of a `&'l str` (again, no
point).
|
|
This avoids creating drop flags in many unnecessary situations.
Fixes #41110.
|
|
Keeps MIR cleaner, `StorageLive(_: !)` makes no sense anyway.
|
|
In MIR construction, operands need to live exactly until they are used,
which is during the (sub)expression that made the call to `as_operand`.
Before this PR, operands lived until the end of the temporary scope,
which was sometimes unnecessarily longer and sometimes too short.
Fixes #38669.
|
|
This reduces the number of dynamic drops in libstd from 1141 to 899.
However, without this change, the next patch would have created much
more dynamic drops.
A basic merge unswitching hack reduced the number of dynamic drops to
644, with no effect on stack usage. I should be writing a more dedicated
drop unswitching pass.
No performance measurements.
|