-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Rustc 1.34 on Solaris SPARC fails with - Expected no forward declarations! #61306
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
Comments
@glaubitz have you seen something like this on SPARC Linux? |
@glaubitz have you seen something like this on SPARC Linux?
Not that I know of. 1.34.2 builds fine for us on Linux/sparc64 although the last upload failed to build because of a packaging problem.
|
Both Rust 1.34.0 and 1.34.2 builds fine. But I'm not able to use them to build Rust 1.35.0. |
Okay, I guess the title is misleading then. I haven't tested 1.35 yet as this isn't part of Debian yet. You can always see the latest build logs for
|
I have seen the issue now with the
Full log at: https://buildd.debian.org/status/fetch.php?pkg=rust-autocfg&arch=sparc64&ver=0.1.4-1&stamp=1559286795&raw=0 |
Okay, I can confirm we are seeing the same issue on Linux/sparc64 when building Rust 1.35 with 1.34.2. Wasn't LLVM switched from 7 to 8 for Rust 1.34? If yes, that would probably explain it as we had similar breakage on 32-bit powerpc back then when LLVM was upgraded. I'm testing with the embedded LLVM copy first. |
My testing was with usage of Solaris bundled LLVM (which is still version 6.0.1). |
Okay, it's not an issue with the system LLVM compiler. Using Rust's embedded LLVM shows the same problem. I'll try to bisect the problem now. |
I have bi-sected this issue down to the commit which replaced LLVM (df0466d):
Since using the system LLVM doesn't usually cause problems, I don't suspect there is a bug in the LLVM bug but rather somewhere in the glue code between Rust and LLVM, i.e. |
That makes sense; that commit swapped the |
Okay, it looks like then this isn't something that can be trivially partially reverted then. I would have hoped, we could just use But I guess we will have to find out what's wrong with the C-ABI. |
I have tried to write simple Rust program which calls C function with 17 integer arguments which are printed out. And I don't see any issue there... |
Likewise, I tried various things with lots of 32-bit integer arguments and checked the assembly output was correct. |
How did you compile the programs? Cross-compiled from x86_64? |
Natively with rustc 1.34.2+dfsg1-1 on gcc202. |
I really don't know how to partially revert the commit. Any idea? What to try? Do I understand it correctly that version 1.34 is broken (even it builds successfully)? I haven't tried to really use it. Though Firefox 68 seems to require this version... |
Yes. Other Rust packages fail to build with 1.34.2 on sparc64 and the commit in question is part of the 1.34.x releases. I don't understand though why 1.34.2 itself builds fine. |
The issue can be seen with -Cdebuginfo=n with n other than 0.
|
I have to admit I don't have enough background knowledge on the fundamental workings of LLVM, so this is more something for @karcherm who has a much better understanding on these things and has helped debugging such issues in the past. I have already nudged him ;). |
There is indeed problem with With following hack It works:
|
It's definitely an ABI problem: Rust passes the flags in the high 32 bits of the stack slot:
Whereas C++ expects the flags in the low half:
This shows that SPFlags is not 64-bit aligned, as it is a 32 bit variable assumed in the low word of the stack slot. The word before SPFlags (the first in the |
It seems the culprit is the #![feature(rustc_private)]
extern crate libc;
#[macro_use]
extern crate bitflags;
use libc::uint32_t;
use libc::uint64_t;
bitflags! {
#[repr(C)]
struct E1 : uint32_t {
const V1 = 1;
const V2 = 2;
const V3 = 4;
}
}
bitflags! {
#[repr(C)]
struct E2 : uint64_t {
const V1 = 1;
const V2 = 2;
const V3 = 4;
}
}
#[repr(u32)]
enum E3 { V1 = 1, V2 = 2, V3 = 4, }
extern {
fn test(val_e1: E1, val_e2: E2, val_e3: E3, val_u: uint32_t);
}
fn main() {
unsafe {
test(E1::V1, E2::V1,E3::V1, 1);
test(E1::V3, E2::V3,E3::V3, 4);
}
} #include <stdio.h>
#include <stdint.h>
enum E1 : uint32_t {
E1v1 = 1,
E1v2 = 2,
E1v3 = 4,
};
enum E2 : uint64_t {
E2v1 = 1,
E2v2 = 2,
E2v3 = 4,
};
enum E3 : uint32_t {
E3v1 = 1,
E3v2 = 2,
E3v3 = 4,
};
extern "C" void test(E1 val_e1, E2 val_e2, E3 val_e3, uint32_t val_u)
{
printf("%d %d %d %d\n", static_cast<uint32_t>(val_e1),
static_cast<uint64_t>(val_e2),
static_cast<uint32_t>(val_e3),
val_u);
} RUSTC=/home/glaubitz/stage2/bin/rustc
main: main.rs libtest.a
$(RUSTC) main.rs -L. -ltest
libtest.a: test.o
ar rc $@ $<
.PHONY: test
test: main
./main Output:
|
In fact, the problem is caused by When you write bitflags! {
#[repr(C)]
struct Flags : u32 {
const f1 = 1;
}
} this generates a type that is compatible to the following C language type: struct dummy {
enum Flags : uint32_t {
Flags_f1 = 1;
}
} The type There seems to be no way to use bitflags to create a rust |
…ust-lang#61306) The C++ side uses enums with underlying integral types. However, Rust's bitflags types are a single-field struct containing an integral type, which are not always passed the same way in the C ABI. In particular, sparc64's ABI extends integral types to a full 64-bit value, but does not do the same for single-field structs. Thanks to Michael Karcher for finding this bug.
The latest patch from #61867 fixes the issue for me. |
An easier patch which seems to fix the problem as well:
@jrtc27 @karcherm What do you think? From the documentation, it seems that The idea to use it came from @petrochenkov. |
rust-lang#61306) In order to make sure that Rust's bitflags types are passed the same way in the Rust ABI as they are in the C ABI, we need to use the attribute repr(transparent) over the repr(C) attribute for the single-field bitflags structs in in order to prevent ABI mismatches. Thanks to Michael Karcher for finding this bug.
librustc_codegen_llvm: Use repr(transparent) for bitflags over repr(C… …) (#61306) In order to make sure that Rust's bitflags types are passed the same way in the Rust ABI as they are in the C ABI, we need to use the attribute repr(transparent) over the repr(C) attribute for the single-field bitflags structs in in order to prevent ABI mismatches. Thanks to Michael Karcher for finding this bug.
This sounds like the best tool for the job. Actually, I don't see the point in bitflags not forcing |
I can confirm that the following helps (e.g. : to build hello world with
But when using it to build Firefox it seems to be slow and eventually to hang!? |
I cannot speak for Firefox, but Thunderbird seems to build normally. |
It's not related as I see it on both SPARC and Intel (#62001) |
Seems that LLVM 8 resolved the issue. But still gets a lot of "scope points into the type hierarchy". Any idea? |
@psumbera Does that affect SPARC only or both Intel and SPARC? At least on Debian/sparc64, the patch I pushed fixed the issue for us. Make sure you compile Rust from a known working compiler (i.e. not with 1.34.x) or cross-compile from an Intel host. |
I was able to build Rust 1.34 on Solaris SPARC without any issue. But when I try it to build Rust 1.35 it fails like this:
Note that when I change in above line Rustc version to 1.33 it passes.
The generated core dump has following stack:
The text was updated successfully, but these errors were encountered: