The "m" memory constraint in inline assembly is broken (generates incorrect code or triggers LLVM asserts) and should not be used. Instead, indirect memory operands should be used with "\*m", "=\*m" and "+\*m".
Clang does this transparently by transforming "m" constraints into "\*m" indirect constraints, but for now just being able to use "\*m" directly is enough since asm! isn't stable.
While "\*m" works fine as an input operand, "=\*m" and "+\*m" need to be specified as input operands because they take a pointer value as an input. This PR relaxes the constraint checker to allow constraints starting with "=" or "+" if the constraint string contains a "\*", which indicates an indirect operand.
This (indirectly) fixes these issues: #29382, #16383 and #13366. The code will need to be changed to use "\*m" instead of "m".
Function arguments that are small aggregates get passed as integer types
instead. To correctly handle that, we need to use store_ty instead of
plain Store.
This branch implements a variant of trans that is based on MIR. It is very incomplete (intentionally), and had only the goal of laying out enough work to enable more incremental follow-on patches. Currently, only fns tagged with `#[rustc_mir]` use the new trans code. I plan to build up a meta-issue as well that tracks the various "not-yet-implemented" points. The only fn that has been tested so far is this amazingly complex "spike" fn:
```rust
#[rustc_mir]
fn sum(x: i32, y: i32) -> i32 {
x + y
}
```
In general, the most interesting commit is the last one. There are some points on which I would like feedback from @rust-lang/compiler:
- I did not use `Datum`. Originally, I thought that maybe just a `ValueRef` would be enough but I wound up with two very simple structures, `LvalueRef` and `OperandRef`, that just package up a `ValueRef` and a type. Because of MIR's structure, you don't wind up mixing by-ref and by-value so much, and I tend to think that a thinner abstraction layer is better here, but I'm not sure.
- Related to the above, I expect that sooner or later we will analyze temps (and maybe variables too) to find those whose address is never taken and which are word-sized and which perhaps meet a few other criteria. For those, we'll probably want to avoid the alloca, just because it means prettier code.
- I generally tried to re-use data structures from elsewhere in trans, though I'm sure we can trim these down.
- I didn't do any debuginfo primarily because it seems to want node-ids and we have only spans. I haven't really read into that code so I don't know what's going on there.
r? @nrc
`resolve_identifier` used to mark a variable as an upvar when used within a closure. However, the function is also used for the "unnecessary qualification" lint, which would mark paths whose last component had the same name as a local as upvars.
Fixes#29522
r? @eddyb
I think this should fix the test failures in debug mode from #29492
The assertion was written incorrectly, and I don't like the way the new assertion is written, but I _think_ it does the right thing now.
A line may be indented with either spaces or tabs, but not a mix of both. If there is a mix of tabs and spaces, only the kind that occurs first is counted.
This addresses issue #29268.
`Rc::try_unwrap` and `Rc::make_mut` are stable since 1.4.0, but the example code still has `#![feature(rc_unique)]`. Ideally the stable and beta docs would be updated, but I don't think that's possible :(
According to a recent [discussion on IRC](https://botbot.me/mozilla/rust-tools/2015-10-27/?msg=52887517&page=2), there's no good reason for Windows builds to store target libraries under `bin`, when on every other platform they are under `lib`.
This might be a [breaking-change] for some users. I am pretty sure VisualRust has that path hard-coded somewhere.
r? @brson
The public set is expanded with trait items, impls and their items, foreign items, exported macros, variant fields, i.e. all the missing parts. Now it's a subset of the exported set.
This is needed for https://github.com/rust-lang/rust/pull/29083 because stability annotation pass uses the public set and all things listed above need to be annotated.
Rustdoc can now be migrated to the public set as well, I guess.
Exported set is now slightly more correct with regard to exported items in blocks - 1) blocks in foreign items are considered and 2) publicity is not inherited from the block's parent - if a function is public it doesn't mean structures defined in its body are public.
r? @alexcrichton or maybe someone else
Almost all operations on Path are based on the components iterator in one form
or another to handle equivalent paths. The `Hash` implementations, however,
mistakenly just went straight to the underlying `OsStr`, causing these
equivalent paths to not get merged together.
This commit updates the `Hash` implementation to also be based on the iterator
which should ensure that if two paths are equal they hash to the same thing.
cc #29008, but doesn't close it
Almost all operations on Path are based on the components iterator in one form
or another to handle equivalent paths. The `Hash` implementations, however,
mistakenly just went straight to the underlying `OsStr`, causing these
equivalent paths to not get merged together.
This commit updates the `Hash` implementation to also be based on the iterator
which should ensure that if two paths are equal they hash to the same thing.
cc #29008, but doesn't close it
`Rc::try_unwrap` and `Rc::make_mut` are stable since 1.4.0, but the example code still has `#![feature(rc_unique)]`. Ideally the stable and beta docs would be updated, but I don't think that's possible...
I read this section a few times before even having a guess what
was meant, then consulted IRC for confirmation. It may be that I
was thick-headed, but I think this is a useful addition.
I read this section a few times before even having a guess what
was meant, then consulted IRC for confirmation. It may be that I
was thick-headed, but I think this is a useful addition.
Note: for now, this change only affects `-windows-gnu` builds.
So why was this `libgcc` dylib dependency needed in the first place?
The stack unwinder needs to know about locations of unwind tables of all the modules loaded in the current process. The easiest portable way of achieving this is to have each module register itself with the unwinder when loaded into the process. All modules compiled by GCC do this by calling the __register_frame_info() in their startup code (that's `crtbegin.o` and `crtend.o`, which are automatically linked into any gcc output).
Another important piece is that there should be only one copy of the unwinder (and thus unwind tables registry) in the process. This pretty much means that the unwinder must be in a shared library (unless everything is statically linked).
Now, Rust compiler tries very hard to make sure that any given Rust crate appears in the final output just once. So if we link the unwinder statically to one of Rust's crates, everything should be fine.
Unfortunately, GCC startup objects are built under assumption that `libgcc` is the one true place for the unwind info registry, so I couldn't find any better way than to replace them. So out go `crtbegin`/`crtend`, in come `rsbegin`/`rsend`!
A side benefit of this change is that rustc is now more in control of the command line that goes to the linker, so we could stop using `gcc` as the linker driver and just invoke `ld` directly.
Motivation:
- It is not actually a pattern
- It is not actually needed, except for...
Drawback:
- Slice patterns like `[a, _.., b]` are pretty-printed as `[a, .., b]`. Great loss :(
plugin-[breaking-change], as always
Similarly to the simd intrinsics. I believe this is a better solution than #29288, and I could implement it as well for overflowing_add/sub/mul. Also rename from udiv/sdiv to div, and same for rem.
Currently if a print happens while a thread is being torn down it may cause a
panic if the LOCAL_STDOUT TLS slot has been destroyed by that point. This adds a
guard to check and prints to the process stdout if that's the case (as we do for
if the slot is already borrowed).
Closes#29488
These two commits do a few things:
1. reformat to 80 cols
2. use the reference-style links where appropriate for improved in-source readability
3. adds a few links, tweaks a couple of words, `3` -> `three`, stuff like that
While the diff is big due to these edits, there's no significant content change.
r? @brson
Before this patch `reserve` function allocated twice as requested
amount elements (not twice as capacity). It leaded to unnecessary
excessive memory usage in scenarios like this:
```
let mut v = Vec::new();
v.push(17);
v.extend(0..10);
println!("{}", v.capacity());
```
`Vec` allocated 22 elements, while it could allocate just 11.
`reserve` function must have a property of keeping `push` operation
cost (which calls `reserve`) `O(1)`. To achieve this `reserve` must
exponentialy grow its capacity when it does reallocation.
There's better strategy to implement `reserve`:
```
let new_capacity = max(current_capacity * 2, requested_capacity);
```
This strategy still guarantees that capacity grows at `O(1)` with
`reserve`, and fixes the issue with `extend`.
Patch imlpements this strategy.
Before this patch `reserve` function allocated twice as requested
amount elements (not twice as capacity). It leaded to unnecessary
excessive memory usage in scenarios like this:
```
let mut v = Vec::new();
v.push(17);
v.extend(0..10);
println!("{}", v.capacity());
```
`Vec` allocated 22 elements, while it could allocate just 11.
`reserve` function must have a property of keeping `push` operation
cost (which calls `reserve`) `O(1)`. To achieve this `reserve` must
exponentialy grow its capacity when it does reallocation.
There's better strategy to implement `reserve`:
```
let new_capacity = max(current_capacity * 2, requested_capacity);
```
This strategy still guarantees that capacity grows at `O(1)` with
`reserve`, and fixes the issue with `extend`.
Patch imlpements this strategy.
This documentation confused me when trying to use truncate on a project. Originally, it was unclear whether truncate removed the last `len` elements, or whether it cut down the vector to be exactly `len` elements long. The example was also ambiguous.
This fixes#29048 (though I think adding better transactional support would be a better fix for that issue, but that is more difficult). It also simplifies region inference and changes the model to a pure data flow one, as discussed in [this internals thread](https://internals.rust-lang.org/t/rough-thoughts-on-the-impl-of-region-inference-mir-etc/2800). I am not 100% sure though if this PR is the right thing to do -- or at least maybe not at this moment, so thoughts on that would be appreciated.
r? @pnkfelix
cc @arielb1
This is two sentences that have been comma spliced, and should
be split with a full stop. (This error made me stop and re-read,
and I submit this as an actual improvement to readability, not
as a grammar weird-o!)
This helps for the case where a match, such as below:
```rust
let foo = match foo {
Some(x) => x,
None => 0
};
```
gets refactored to no longer need the match, but the match keyword has been left accidentally:
```rust
let foo = match foo.unwrap_or(0);
```
This can be hard to spot as the expression grows more complex.
r? @alexcrichton
This documentation confused me when trying to use truncate on a project. Originally, it was unclear whether truncate removed the last `len` elements, or whether it cut down the vector to be exactly `len` elements long. The example was also ambiguous.
This is two sentences that have been comma spliced, and should
be split with a full stop. (This error made me stop and re-read,
and I submit this as an actual improvement to readability, not
as a grammar weird-o!)
I put the reference under the function return operator `->` rather than near the suggested `!` operators as I thought it was more relevant there.
Resolves#29431
…m message
I recently discovered that this is not mentioned in the docs, only in
the examples, and it's not evident for people coming from C++
r? @steveklabnik