Skip to content

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

Open
psumbera opened this issue May 29, 2019 · 31 comments
Open
Labels
C-bug Category: This is a bug. O-solaris Operating system: Solaris O-SPARC Target: SPARC processors T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@psumbera
Copy link
Contributor

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:

/builds/psumbera/rustc-1.34.0/bin//rustc --crate-name unicode_xid /builds/psumbera/userland-rust/components/rust/rustc/rustc-1.35.0-src-vendored-sources/unicode-xid/src/lib.rs --color always --crate-type lib --emit=dep-info,link -C debug-assertions=off -C overflow-checks=on --cfg 'feature="default"' -C metadata=71eab7b4d85734ec -C extra-filename=-71eab7b4d85734ec --out-dir /builds/psumbera/userland-rust/components/rust/rustc/build/sparcv9/build/bootstrap/debug/deps -L dependency=/builds/psumbera/userland-rust/components/rust/rustc/build/sparcv9/build/bootstrap/debug/deps --cap-lints allow -Cdebuginfo=2
Expected no forward declarations!Expected no forward declarations!
!13 = <temporary!> !{}

scope points into the type hierarchy
!19 = !<temporary!> 15!{} =
!DILocation(Expected no forward declarations!scope points into the type hierarchyline:
Expected no forward declarations!

1, scope: !!424) = !20!DILocation(line
: 1,  = Expected no forward declarations!<temporary!> !!{scope
: 32Expected no forward declarations! = !<temporary!> 4
)!{}
!
34scope points into the type hierarchy =
<temporary!> scope points into the type hierarchy!{scope points into the type hierarchy
}
!26
 = !DILocation(line!: 16scope points into the type hierarchy! = 1297!DILocation(
34line = , : !DILocation(column!: line241, 8: 37column, 1scope: ,  = 35scope: , !DILocation(!scope: line: !: 4!131), )4
)
scope points into the type hierarchyscope

: scope points into the type hierarchy!!1227
) =
scope points into the type hierarchy!DILocation(
scope points into the type hierarchy!
line: 381297!!, 36! = column = 1838: <temporary!> !DILocation( =  = 20line!{!DILocation(!DILocation(}, : 22linescopeline: : : 284
, 241!column4, , column)column: : :
1248, , , scope points into the type hierarchyscopescopescope: : !: !
!412scope points into the type hierarchy)13))


scope points into the type hierarchyscope points into the type hierarchy


!scope points into the type hierarchy28
 = !DILocation(!!line41: 19 = 1298 = !DILocation(!, !DILocation(linecolumnline44!: : 37: 5 = 287242, , !DILocation( = scopecolumnline!DILocation(: , line: !column41: : 22: ), 5, 5column,
scope, scopescope: : 23: : , !!412))scope!: !
19
13)scope points into the type hierarchy)


scope points into the type hierarchy!42
 = scope points into the type hierarchy!DILocation(line
: 284, column: !LLVM ERROR: 38LLVM ERROR: 21 = , !DILocation(linescope!: 46:  = 27!12, !DILocation(columnline): : 1
325scope points into the type hierarchy, , scopecolumn
Broken function found, compilation aborted!: : !8Broken function found, compilation aborted!, 13!)scope43
:  = !DILocation(!LLVM ERROR: 19lineBroken function found, compilation aborted!: )283,
scope points into the type hierarchycolumn: 8
, scope
:
!12)
pure virtual method called
pure virtual method called
terminate called recursively
terminate called without an active exception

pure virtual method called
terminate called recursively
Abort (core dumped)

Note that when I change in above line Rustc version to 1.33 it passes.

The generated core dump has following stack:

0007fff7398ec861 libc.so.1`__lwp_sigqueue+8(6, ffffffffffffffec, 7fff7398ed100, 5, 0, 0)
0007fff7398ec911 libc.so.1`abort+0xfc(1, 1210, 0, 1000, 0, 0)
0007fff7398ec9f1 libstdc++.so.6.0.24`__gnu_cxx::__verbose_terminate_handler+0x14c(0, 0, 0, 0, 0, 0)
0007fff7398ecab1 libstdc++.so.6.0.24`__cxxabiv1::__terminate+4(7fff7261bf1ec, 300001dc000, 1b, 0, 1, 194)
0007fff7398ecb61 libstdc++.so.6.0.24`std::terminate+0xc(1b, 7fff7261b4fc8, 1b, 0, 1, 7fff73e3b1a40)
0007fff7398ecc11 libstdc++.so.6.0.24`__cxa_pure_virtual+0x28(7fff728bec088, 7fff7398ed6ff, 1, 3567f8dd70, 6b5d509, 80)
0007fff7398eccc1 libLLVM-6.0.so`llvm::raw_ostream::write+0x160(7fff728bec088, 7fff7398ed6ff, 1, 648424d, 0, 7fff73bb04430)
0007fff7398ecd81 libLLVM-6.0.so`llvm::formatted_raw_ostream::write_impl+0x4c(7fff7398ed898, 7fff7398ed6ff, 1, 7fff73bb04430, 1, 7fff73bb04430)
0007fff7398ece41 libLLVM-6.0.so`llvm::raw_ostream::write+0xc4(7fff7398ed898, 21, 356800bc60, 7fff7398ed6f8, 7fff7398ed898, 7fff73bb04430)
0007fff7398ecf11 libLLVM-6.0.so`WriteAsOperandInternal.isra.778+0x26c(7fff7398ed898, 356806cd38, 7fff7398ed8d8, 356801df40, 2e, 7fff73bb04430)
0007fff7398ecfe1 libLLVM-6.0.so`printMetadataImpl+0x160(7fff728bec088, 356806cd38, 35683af930, 35681de470, 0, 7fff728b25da8)
0007fff7398ed161 libLLVM-6.0.so`llvm::Metadata::printconst+0x40(356806cd38, 7fff728bec088, 35683af930, 35681de470, 0, 7fff73bb04430)
0007fff7398ed221 libLLVM-6.0.so`llvm::VerifierSupport::Write.part.107+0x40(35683af920, 356806cd38, 7fff73bb04430, 0, 7fff728bec088, 7fff73bb04430)
0007fff7398ed2e1 libLLVM-6.0.so`.part.1042+0xb10(35683af920, 356806cd38, 0, 3568241560, 7fff73bb04430, fffffffffffffff8)
0007fff7398ed431 libLLVM-6.0.so`+0xdc(35683af920, 356806cd38, 0, 3567bdbe00, 20, 7fff73bb04430)
0007fff7398ed501 libLLVM-6.0.so`+0x1564(35683af920, 3568247dc8, fffffff, 1, 356806cd38, 7fff73bb04430)
0007fff7398ed6b1 libLLVM-6.0.so`+0x184(35683af920, 3568247dc8, 7fff7398edef8, 35681dbd90, 1, 7fff73bb04430)
0007fff7398ed781 libLLVM-6.0.so`.part.1265+0xcc8(35683af920, 3568235380, 35682473b8, fffffff, 3568247dc8, 3568247de0)
0007fff7398ed9d1 libLLVM-6.0.so`+0x208(35683af920, 35682318e8, 7fff73e2ebdc0, 3568231930, 7fff73bb04430, 3568231930)
0007fff7398edaa1 libLLVM-6.0.so`+0x34(3567b74440, 35682318e8, 0, 0, 0, 7fff73bb04430)
0007fff7398edb61 libLLVM-6.0.so`llvm::FPPassManager::runOnFunction+0x360(35682818d0, 35682318e8, 7fff73bb04430, 3, 35682818f0, 3567b74440)
0007fff7398edc71 libLLVM-6.0.so`llvm::FPPassManager::runOnModule+0x54(35682818d0, 35681de488, 0, 7fff73bb04430, 0, 3568231920)
0007fff7398edd31 libLLVM-6.0.so`llvm::legacy::PassManagerImpl::run+0x35c(356823e320, 35681de470, 1, 0, 35682818d0, 35682616d0)
0007fff7398ede21 libLLVM-6.0.so`llvm::legacy::PassManager::run+0x34(3567ba2940, 35681de470, 7fff7398ee7b8, 1, 1, 7fff73bb04430)
0007fff7398edee1 librustc_codegen_llvm-llvm.so`LLVMRustWriteOutputFile+0x1a0(35682155c0, 3567ba2940, 35681de470, 356822b970, 7fff7398ee7b8, 7fff73bb04430)
0007fff7398ee051 librustc_codegen_llvm-llvm.so`rustc_codegen_llvm::back::write::write_output_file::h06f62ffa85513e02.llvm.6134306529257019547+0x40(7fff7398ef0b0, 35682155c0, 3567ba2940,
35681de470, 356822aa00, 9c)
0007fff7398ee181 librustc_codegen_llvm-llvm.so`rustc_codegen_llvm::back::write::codegen::_$u7b$$u7b$closure$u7d$$u7d$::hb89b8dc96d0d6653.llvm.67276690187451607+0x33c(7fff7398eeb30,
7fff7398ef0b0, 35682155c0, 356822aa00, 35681de470, 3567ba2940)
0007fff7398ee271 librustc_codegen_llvm-llvm.so`rustc::util::common::time_ext::h203241132f3eb1ac+0x70(7fff7398eeb30, 0, 3567ba1cd0, 2b, 7fff7398eedb0, 7fff72fd84000)
0007fff7398ee381
librustc_codegen_llvm-llvm.so`_$LT$rustc_codegen_llvm..LlvmCodegenBackend$u20$as$u20$rustc_codegen_ssa..traits..write..WriteBackendMethods$GT$::codegen::h52f8e70916952150+0x97c(3567ba1cd0, 0, 7fff7398eed88, 7fff7398eed17, 3568075e00, 35681d7240)
0007fff7398ee651 librustc_codegen_llvm-llvm.so`rustc_codegen_ssa::back::write::execute_work_item::h9629fd05538e626e+0x11b4(35681ccf40, 3567b8aa20, 7fff7398ef508, 7fff7398ef598, 7fff7398ef300, 1)
0007fff7398eea31 librustc_codegen_llvm-llvm.so`std::sys_common::backtrace::__rust_begin_short_backtrace::h5c4ce3df3c5c3c41+0x1e4(7fff7398ef5c0, 7fff7398ef508, 7fff7398ef300, 7fff7398ef420,
7fff7398ef2f8, 0)
0007fff7398eee31 librustc_codegen_llvm-llvm.so`std::panicking::try::do_call::hd0b71df38ab7dc19.llvm.4807897764851716782+0x18(7fff7398efb88, 7fff7398ef6e8, 356822d0b0, 7fff7396ee000, 1,
3567f8eaa0)
0007fff7398ef071 libstd-78276fe13ee991a5.so`__rust_maybe_catch_panic+0x14(7fff72fae6700, 7fff7398efb88, 7fff7398efb78, 7fff7398efb80, 7fff73d644000, 0)
0007fff7398ef131 librustc_codegen_llvm-llvm.so`_$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::h0a7257b312ec8281+0x94(7fff7398efb88, 7fff72fd84000, 35681e2e80, 7fff7398ef9e0,
1930, 0)
0007fff7398ef511 libstd-78276fe13ee991a5.so`std::sys_common::thread::start_thread::he12a8bd23d4ffc25+0xa8(7fff73e404000, 7fff72faa0efc, 3567b95f40, 2, 7fff73e3b1a40, ff000000)
0007fff7398ef5e1 libstd-78276fe13ee991a5.so`std::sys::unix::thread::Thread::new::thread_start::h0204f2da04a5dd90+4(3567b95f40, 0, 1, 7fff73d4c1f28, 0, 0)
0007fff7398ef691 libc.so.1`_lwp_start(0, 0, 0, 0, 0, 0)
@psumbera
Copy link
Contributor Author

@glaubitz have you seen something like this on SPARC Linux?

@glaubitz
Copy link
Contributor

glaubitz commented May 29, 2019 via email

@jonas-schievink jonas-schievink added C-bug Category: This is a bug. O-solaris Operating system: Solaris O-SPARC Target: SPARC processors T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 29, 2019
@psumbera
Copy link
Contributor Author

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.
Maybe I should try to use bundled llvm (not to use system one).

@glaubitz
Copy link
Contributor

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 rustc Linux/sparc64 on these pages:

https://buildd.debian.org/status/package.php?p=rustc&suite=sid
https://buildd.debian.org/status/package.php?p=rustc&suite=experimental

@glaubitz
Copy link
Contributor

glaubitz commented Jun 1, 2019

I have seen the issue now with the rust-autocfg package when building with Rust 1.34.2:

Compiling autocfg v0.1.4 (/<<PKGBUILDDIR>>)
     Running `rustc --crate-name autocfg src/lib.rs --color never --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=ddf4bb248d75a26c -C extra-filename=-ddf4bb248d75a26c --out-dir /<<PKGBUILDDIR>>/target/sparc64-unknown-linux-gnu/debug/deps --target sparc64-unknown-linux-gnu -C incremental=/<<PKGBUILDDIR>>/target/sparc64-unknown-linux-gnu/debug/incremental -L dependency=/<<PKGBUILDDIR>>/target/sparc64-unknown-linux-gnu/debug/deps -L dependency=/<<PKGBUILDDIR>>/target/debug/deps -C debuginfo=2 --cap-lints warn -C linker=sparc64-linux-gnu-gcc -C link-arg=-Wl,-z,relro --remap-path-prefix /<<PKGBUILDDIR>>=/usr/share/cargo/registry/autocfg-0.1.4`
Expected no forward declarations!
!180 = <temporary!> !{}
scope points into the type hierarchy
!184 = !DILocation(line: 1, scope: !21)
scope points into the type hierarchy
!186 = distinct !DILexicalBlock(scope: !21, file: !22, line: 357, column: 8)
scope points into the type hierarchy
!188 = !DILocation(line: 360, column: 5, scope: !21)
LLVM ERROR: Broken function found, compilation aborted!
error: Could not compile `autocfg`.

Full log at: https://buildd.debian.org/status/fetch.php?pkg=rust-autocfg&arch=sparc64&ver=0.1.4-1&stamp=1559286795&raw=0

CC @karcherm @jrtc27

@glaubitz
Copy link
Contributor

glaubitz commented Jun 1, 2019

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.

@psumbera
Copy link
Contributor Author

psumbera commented Jun 1, 2019

My testing was with usage of Solaris bundled LLVM (which is still version 6.0.1).

@glaubitz
Copy link
Contributor

glaubitz commented Jun 1, 2019

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.

@glaubitz
Copy link
Contributor

glaubitz commented Jun 2, 2019

I have bi-sected this issue down to the commit which replaced LLVM (df0466d):

df0466d0bb807a7266cc8ac9931cd43b3e84b62e is the first bad commit
commit df0466d0bb807a7266cc8ac9931cd43b3e84b62e
Author: Josh Stone <jistone@redhat.com>
Date:   Wed Jan 16 09:59:03 2019 -0800

    Rebase to the llvm-project monorepo
    
    The new git submodule src/llvm-project is a monorepo replacing src/llvm
    and src/tools/{clang,lld,lldb}.  This also serves as a rebase for these
    projects to the new 8.x branch from trunk.
    
    The src/llvm-emscripten fork is unchanged for now.

:100644 100644 c4763612dbf3cc85d8682775b79d3297e6ec8c69 4e368c3ebafd8ba3b766ffd4d21d2339ec4f1852 M      .gitmodules
:100644 100644 6596c5a3d9aff0e5f450ba05c826cb34bcabf3b4 dc9abf84b8e5a4d3b6ab5472883f0997fa0454cc M      COPYRIGHT
:040000 040000 d28fae50cd16a7552c46d90c861785b8f9e24f63 1d444fc6305f36cd4e9a429b32387a5737ec7805 M      src

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. Rustwrapper.cpp or something like that.

@jrtc27
Copy link

jrtc27 commented Jun 2, 2019

That makes sense; that commit swapped the bool IsDefinition for LLVMRustDISPFlags SPFlags in LLVMRustDIBuilderCreateFunction. RustWrapper.cpp looks sensible and doesn't cause issues elsewhere. If I had to guess, I would say that there's something wrong with the C ABI code for passing a uint32_t on the stack (since SPFlags is beyond the 6th argument), since the call site that was changed unconditionally sets SPFlagDefinition.

@glaubitz
Copy link
Contributor

glaubitz commented Jun 3, 2019

Okay, it looks like then this isn't something that can be trivially partially reverted then. I would have hoped, we could just use bool IsDefinition again on sparc64 as a workaround and see if that fixes the problem.

But I guess we will have to find out what's wrong with the C-ABI.

@psumbera
Copy link
Contributor Author

psumbera commented Jun 4, 2019

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...

@jrtc27
Copy link

jrtc27 commented Jun 4, 2019

Likewise, I tried various things with lots of 32-bit integer arguments and checked the assembly output was correct.

@glaubitz
Copy link
Contributor

glaubitz commented Jun 4, 2019

How did you compile the programs? Cross-compiled from x86_64?

@jrtc27
Copy link

jrtc27 commented Jun 4, 2019

Natively with rustc 1.34.2+dfsg1-1 on gcc202.

@psumbera
Copy link
Contributor Author

Okay, it looks like then this isn't something that can be trivially partially reverted then. I would have hoped, we could just use bool IsDefinition again on sparc64 as a workaround and see if that fixes the problem.

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...

@glaubitz
Copy link
Contributor

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.

@psumbera
Copy link
Contributor Author

The issue can be seen with -Cdebuginfo=n with n other than 0.

cat test.rs
fn main() {
    println!("Hello World!");
}
/builds/rustc-1.34.2/bin/rustc test.rs  -Cdebuginfo=2
Expected no forward declarations!
!26 = <temporary!> !{}
..

@glaubitz
Copy link
Contributor

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 ;).

@psumbera
Copy link
Contributor Author

There is indeed problem with SPFlags. In librustc_codegen_llvm I see SPFlags set to: SPFlagLocalToUnit | SPFlagDefinition. But in RustWrapper.cpp it gets 0. And it doesn't help to move SPFlags as first argument of LLVMRustDIBuilderCreateFunction().

With following hack It works:

--- rustc-1.34.2-src/src/rustllvm/RustWrapper.cpp
+++ rustc-1.34.2-src/src/rustllvm/RustWrapper.cpp
@@ -676,8 +677,8 @@
       LineNo, unwrapDI<DISubroutineType>(Ty), ScopeLine, fromRust(Flags),
       fromRust(SPFlags), TParams, unwrapDIPtr<DISubprogram>(Decl));
 #else
-  bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
-  bool IsDefinition = isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition);
+  bool IsLocalToUnit = true; //isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
+  bool IsDefinition = true; //isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition);
   bool IsOptimized = isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized);
   DISubprogram *Sub = Builder->createFunction(
       unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),

@karcherm
Copy link
Contributor

It's definitely an ABI problem: Rust passes the flags in the high 32 bits of the stack slot:

   ; SPFlagOptimized is 16, $g2 contains the previous value of spflags
   ; if self.sess().opts.optimize != config::OptLevel::No {
   ;           spflags |= DISPFlags::SPFlagOptimized;
   ; }
   or  %g2, 0x10, %i3
   cmp  %g3, 0
   move  %icc, %g2, %i3
   ; move to high word and pass as parameter
   sllx  %i3, 0x20, %i3
   stx  %l3, [ %sp + 0x8d7 ]
   ; ...
   call  0xfff800010c44d920 <LLVMRustDIBuilderCreateFunction@got.plt>

Whereas C++ expects the flags in the low half:

(gdb) print SPFlags
$22 = LLVMRustDISPFlags::SPFlagZero
(gdb) print &SPFlags
$23 = (LLVMRustDISPFlags *) 0xfff8000107f03afc
(gdb) x/2wx &SPFlags-1
0xfff8000107f03af8:     0x0000000c      0x00000000

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 x command output) contains the correct value.

@karcherm
Copy link
Contributor

karcherm commented Jun 15, 2019

It seems the culprit is the bitflags! macro. Test program (should output "1 1 1 1" "4 4 4 4"):

#![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:

glaubitz@gcc202:~/rtest$ make test
./main
0 1 1 1
-1 4 4 4

@karcherm
Copy link
Contributor

In fact, the problem is caused by bitflags! used in an inappropriate way.

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 dummy and the inner type dummy::Flags may or may not be compatible in function parameter lists. As it turns out, on Sparc64, they are not. RustWrapper.cpp expects an enum like dummy::Flags, but the extern declaration claims that the function would like to receive a structure like dummy.

There seems to be no way to use bitflags to create a rust enum instead of a rust struct, which would be the correct rust-side type for the C++-side enum.

jrtc27 added a commit to jrtc27/rust that referenced this issue Jun 15, 2019
…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.
@glaubitz
Copy link
Contributor

The latest patch from #61867 fixes the issue for me.

@glaubitz
Copy link
Contributor

glaubitz commented Jun 16, 2019

An easier patch which seems to fix the problem as well:

diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index a71243c7c8..a5c295cd45 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -564,7 +564,7 @@ pub mod debuginfo {
 
     // These values **must** match with LLVMRustDIFlags!!
     bitflags! {
-        #[repr(C)]
+        #[repr(transparent)]
         #[derive(Default)]
         pub struct DIFlags: ::libc::uint32_t {
             const FlagZero                = 0;
@@ -593,7 +593,7 @@ pub mod debuginfo {
 
     // These values **must** match with LLVMRustDISPFlags!!
     bitflags! {
-        #[repr(C)]
+        #[repr(transparent)]
         #[derive(Default)]
         pub struct DISPFlags: ::libc::uint32_t {
             const SPFlagZero              = 0;

@jrtc27 @karcherm What do you think?

From the documentation, it seems that #[repr(transparent)] was pretty much designed for our purpose (see: https://doc.rust-lang.org/1.26.2/unstable-book/language-features/repr-transparent.html).

The idea to use it came from @petrochenkov.

glaubitz added a commit to glaubitz/rust that referenced this issue Jun 16, 2019
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.
bors added a commit that referenced this issue Jun 16, 2019
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.
@karcherm
Copy link
Contributor

From the documentation, it seems that #[repr(transparent)] was pretty much designed for our purpose (see: https://doc.rust-lang.org/1.26.2/unstable-book/language-features/repr-transparent.html).

This sounds like the best tool for the job. Actually, I don't see the point in bitflags not forcing #[repr(transparent)] on all of their types, but there may be some reason. The documentation of bitflags should point out that #[repr(transparent)] is most likely what you want if you use the bitflags in FFI.

@psumbera
Copy link
Contributor Author

psumbera commented Jun 18, 2019

I can confirm that the following helps (e.g. : to build hello world with -Cdebuginfo=2 and build Rust 1.35 with Rust 1.34.2+patch).

-        #[repr(C)]
+        #[repr(transparent)]

But when using it to build Firefox it seems to be slow and eventually to hang!?

@glaubitz
Copy link
Contributor

I cannot speak for Firefox, but Thunderbird seems to build normally.

@psumbera
Copy link
Contributor Author

But when using it to build Firefox it seems to be slow and eventually to hang!?

It's not related as I see it on both SPARC and Intel (#62001)

@psumbera
Copy link
Contributor Author

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?

@glaubitz
Copy link
Contributor

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. O-solaris Operating system: Solaris O-SPARC Target: SPARC processors T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants