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

Constants seem to be broken in nightly Rust on powerpc-unknown-linux-gnu #39061

Closed
dusxmt opened this issue Jan 14, 2017 · 11 comments
Closed

Constants seem to be broken in nightly Rust on powerpc-unknown-linux-gnu #39061

dusxmt opened this issue Jan 14, 2017 · 11 comments

Comments

@dusxmt
Copy link

dusxmt commented Jan 14, 2017

Good day, it appears that something is wrong with constants on the 32-bit powerpc linux flavor of nightly rustc, here's a simple example program:

const TEST_NUM_CONST: u32 = 512;

#[derive(Debug)]
struct Point {
    x: u32,
    y: u32,
}

const TEST_STRUCT_CONST: Point = Point { x: 428, y: 314 };

fn main() {
    println!("The numeric constant is: {}", TEST_NUM_CONST);
    println!("The struct constant is: {:?}", TEST_STRUCT_CONST);
}

What I expect it to output, and what it does indeed output on x86_64, is:

The numeric constant is: 512
The struct constant is: Point { x: 428, y: 314 }

However, on PowerPC, rustc fails with:

error: int literal is too large
 --> main.rs:1:29
  |
1 | const TEST_NUM_CONST: u32 = 512;
  |                             ^^^

error: aborting due to previous error

If I comment out the numeric constant and its use, leaving the structure constant in, rustc reliably crashes due to memory corruption:

*** Error in `/home/dusan/.rustup/toolchains/nightly-powerpc-unknown-linux-gnu/bin/rustc': double free or corruption (out): 0xb7cc57d8 ***
======= Backtrace: =========

(link to full output: https://gist.github.com/dusxmt/1601ecd375e3092955ff8ec9c8a69456 )

$ rustc --version --verbose
rustc 1.16.0-nightly (1a2ed98 2017-01-13)
binary: rustc
commit-hash: 1a2ed98
commit-date: 2017-01-13
host: powerpc-unknown-linux-gnu
release: 1.16.0-nightly
LLVM version: 3.9

$ uname -a
Linux power-dooshki 4.4.39-gentoo #1 Fri Jan 6 23:47:44 CET 2017 ppc 7450, altivec supported PowerBook3,3 GNU/Linux

@est31
Copy link
Member

est31 commented Jan 14, 2017

Most likely the cause of this is i128 support (PR that implemented it: #38482).

At least on windows (both x86_64 and i686), @nagisa and me have experienced the same issue (literal parsing being broken) when doing computations. Literal parsing is one of the areas i128 get used inside the compiler. It turned out to be an ABI mismatch between what LLVM thinks the ABI is, and our own ABI use. It got worked around until LLVM fixes it.

Guess the segfault is also due to this.

@est31
Copy link
Member

est31 commented Jan 14, 2017

cc #35118

@nagisa
Copy link
Member

nagisa commented Jan 14, 2017

@est31’s analysis sounds plausible.

No PPC to validate it on, though and qemu-ppc SIGSEGVs left and right.

@nagisa
Copy link
Member

nagisa commented Jan 15, 2017

I could reproduce the issue, investigating.

@nagisa
Copy link
Member

nagisa commented Jan 15, 2017

So, the ABI seems to be honoured. In the simplest case of

const TEST_NUM_CONST: u128 = 123;

two intrinsics are being called: __multi3 and __divti3 (in order to multiply with overflow checks; __muloti4 intrinsic seems to not be called here).

1st argument is passed in via registers r3:r4:r5:r6 (where 6 are LSB); 2nd argument is passed via r7:r8:r9:r10. Return value is stored in r3:r4:r5:r6 as well. Both caller (LLVM) and callee (rustc-generated code) honour these rules for trivial test cases I’ve constructed.

These functions are called in this way:

__multi3(0:0:0:0, 0:0:0:A) = 0:0:0:0    ; not sure why it is multiplying 0 with anything, but result is correct nevertheless
__udivti3(0:0:0:0, 0:0:0:A) = 0:0:0:0
__multi3(0:0:0:1, 0:0:0:A) = 0:A:0:14  ; result seems wrong?
__udivti3(0:A:0:14, 0:0:0:A) = 0:0:0:3   ; also seems wrong, even considering `0x14 / 0xA` the result is `2`, not `3`.
// error happens after this point.

I did not investigate in depth why this happens yet, but seems to be an issue within the multiplication intrinsic, rather than FFI layer.

@nagisa
Copy link
Member

nagisa commented Jan 15, 2017

I may or may not suspect the byteorder assumptions. PPC are big-endian, which may be invalidating all the “black” magic going on within the intrinsics.

EDIT: I will try to compile rustc with explicit conversion to and from low endian added in tomorrow and see if that fixes it.

@est31
Copy link
Member

est31 commented Jan 16, 2017

Oh, if its an endianness issue, it might be caused by this implementation: https://github.com/rust-lang/rust/blob/master/src/libcompiler_builtins/lib.rs#L407

You can try replacing it with a shift (and below in the from_parts function as well). E.g. the upcoming compiler-builtins does it as well: https://github.com/rust-lang-nursery/compiler-builtins/blob/master/src/int/mod.rs#L54

@est31
Copy link
Member

est31 commented Jan 17, 2017

@dusxmt can you re-try again with the newest nightly 1.16.0-nightly (4ce7accaa 2017-01-17) ?

@nagisa
Copy link
Member

nagisa commented Jan 17, 2017

screenshot from 2017-01-17 17-50-03

I can confirm it works on my qemu. Yay!

@dusxmt
Copy link
Author

dusxmt commented Jan 17, 2017

2017-01-17-172607_1152x768_scrot
Yup, that does indeed solve my problem, thank you kindly for fixing this =3

@aturon
Copy link
Member

aturon commented Jan 17, 2017

Closing as resolved!

@aturon aturon closed this as completed Jan 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants