Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIR trans cannot handle casting for call return values. #33873

Closed
eddyb opened this issue May 26, 2016 · 0 comments · Fixed by #33905
Closed

MIR trans cannot handle casting for call return values. #33873

eddyb opened this issue May 26, 2016 · 0 comments · Fixed by #33905
Labels
A-codegen Area: Code generation A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html

Comments

@eddyb
Copy link
Member

eddyb commented May 26, 2016

In the following example, bar optimizes to ret i8 undef because the return value is cast into an i32 in foo and has to be converted back at the call site. The old trans code does this with a gnarly memcpy which should handle all of the possible situations, if the comment on it is of any indication.
I believe my use of ArgType::store for storing the return value in its destination was unwarranted.
Since then, @Aatch has refactored that logic into its own function, which should do the memcpy.
cc @nagisa @dotdash

#![crate_type = "lib"]
#![feature(rustc_attrs)]

pub extern "C" fn foo() -> (u8, u8, u8) {
    (1, 2, 3)
}

#[rustc_mir]
pub fn bar() -> u8 {
    foo().2
}
@eddyb eddyb added I-wrong A-codegen Area: Code generation A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html labels May 26, 2016
bors added a commit that referenced this issue Jun 5, 2016
[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`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant