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

crate-ify compiler-rt into compiler-builtins #35021

Merged
merged 7 commits into from
Sep 14, 2016

Conversation

japaric
Copy link
Member

@japaric japaric commented Jul 25, 2016

libcompiler-rt.a is dead, long live libcompiler-builtins.rlib

This commit moves the logic that used to build libcompiler-rt.a into a
compiler-builtins crate on top of the core crate and below the std crate.
This new crate still compiles the compiler-rt instrinsics using gcc-rs
but produces an .rlib instead of a static library.

Also, with this commit rustc no longer passes -lcompiler-rt to the
linker. This effectively makes the "no-compiler-rt" field of target
specifications a no-op. Users of no_std will have to explicitly add
the compiler-builtins crate to their crate dependency graph if they
need the compiler-rt intrinsics - this is a [breaking-change]. Users
of the std have to do nothing extra as the std crate depends
on compiler-builtins.

Finally, this a step towards lazy compilation of std with Cargo as the
compiler-rt intrinsics can now be built by Cargo instead of having to
be supplied by the user by some other method.

closes #34400


r? @alexcrichton

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @eddyb (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

let mut sources = Sources::new();
sources.extend(&["absvdi2.c",
"absvsi2.c",
"adddf3.c",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alignment seems off here.

@eddyb
Copy link
Member

eddyb commented Jul 25, 2016

r? @alexcrichton

@rust-highfive rust-highfive assigned alexcrichton and unassigned eddyb Jul 25, 2016
@eddyb
Copy link
Member

eddyb commented Jul 25, 2016

FWIW, I believe the name should be librustc_builtins, if we're to keep it in line with everything else.

@@ -0,0 +1 @@
../compiler-rt/lib/builtins
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this may be a symlink? We may want to remove this for now and just assume the location of lib/builtins is what we expect

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean having the build.rs directly use the $RUST_REPO/src/compiler-rt/lib/builtins directory?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nah I mean just referencing ../compiler-rt/... in the paths being compiled

@alexcrichton
Copy link
Member

Awesome, thanks @japaric! It's probably fine to remove the no_compiler_rt logic in the compiler as well. I don't think it'll break any custom target specs because we should ignore unknown fields I believe.

@brson so thinking about this again I'd like to touch briefly again on what the organization here should be. Dependency-wise everything in Rust depends on this crate, or in other words everything generated by rustc. In that sense libcore should depend on this, but in another sense that'll get very annoying once we actually want to write all this in Rust (b/c none of libcore is available, including required lang items).

I think I'd personally prefer to have this as a libcore build script for now because:

  • It's already at the base of all Rust crates' dependency tree
  • That way when we write these in Rust it'll be easier to define.
  • We wouldn't accidentally break anyone today compiling libcore by hand by introducing a new dependency that's "not really needed"

It also feels a little weird for libcore to not actually be the core, but that's just a vague feeling of mine :). Curious what you think though!

@eddyb
Copy link
Member

eddyb commented Jul 25, 2016

@alexcrichton I think it would make sense to have the builtins somewhere in libcore. They're effectively "lang items", from rustc's standpoint, although with hardcoded symbol names instead.

@japaric
Copy link
Member Author

japaric commented Jul 25, 2016

@alexcrichton All your points make sense to me. 👍 from me to moving this to a libcore build script.

@brson
Copy link
Contributor

brson commented Jul 25, 2016

My main reasons for not wanting it to be part of core is because it is already a self-contained compilation unit, so it should stay its own compilation unit; it's very much tied to rustc's present compiler backend, making it less likely that core could be used by certain alternate implementations; it's a blob of foreign code that I'd rather not 'infect' core. In other words is, core is about Rust language definitions. rustc-builtins is about the compiler's implementation. They are orthogonal.

I do feel pretty strongly that this code does not belong in core. That said I concede that it would be quite challenging to write it in rust without inverting the dependencies.

@brson
Copy link
Contributor

brson commented Jul 25, 2016

I guess in a certain light you could say that everything in rustc-builtins is a new type of Rust intrinsic, and most intrinsics are defined in core. But I don't consider rustc-builtins to be part of Rust - they are an incidental side effect of having an LLVM backend.

@alexcrichton
Copy link
Member

@brson I'm basically only worried about the barrier we'll have to defining these things in Rust, I wouldn't want to get into a situation where libcore reexports things from rustc-builtins.

I wouldn't mind the alternate route of inverting dependencies and have rustc-builtins depend on libcore. It's only "incorrect" in the sense that libcore may lower to intrinsics that are defined in rustc-builtins. We can paper over that with linker flags, though, so it's solvable and probably won't actually come up in practice.

@brson
Copy link
Contributor

brson commented Jul 25, 2016

Let's go with the core buildscript for now. I've adequately registered my distaste for that solution, but any problems associated with it are theoretical and we can deal with them down the road.

@japaric
Copy link
Member Author

japaric commented Jul 26, 2016

Let's go with the core buildscript for now.

Done. Still missing the Makefiles part.


Upon further testing this, I've found that cross compiling rustc for arm-unknown-linux-gnueabi fails with "undefined reference to __mulodi4" while linking rustc (and also rustdoc). Which seems strange because __mulodi4 is present in libstd.so.

It seems that the problem is that libstd.so contains __mulodi4 as a local symbol (it appears as "001626d4 t __mulodi4" in nm output) whereas __mulodi4 is a global symbol of libcore.rlib (it appears as "00000000 T __mulodi4" in nm output). My evidence is that: Building a binary that's statically linked to std works fine (the linker passes libcore.rlib) but building a binary that's dynamically linked to std fails (the linker passes libstd.so and not libcore.rlib). Though I might be misreading this.

If that's indeed the issue, is there a way to make __mulodi4 (and all the other intrinsics) appear as a global symbol(s) in libstd.so?

@alexcrichton
Copy link
Member

@japaric that's probably because we compile with -fvisibility=hidden. We do that for compiler-rt so it's not exported from any application, but it's available to link it.

That's... an interesting problem! I don't think we want to export the compiler-rt intrinsics from every application, but they need to be available for further linkages. This works today because you'd just link multiple copies of the intrinsic via -lcompiler-rt.

Hmm... I guess the "best" solution is to have libstd.so be special in that it's the only dylib exporting those symbols, but that's not exactly a great solution nor do I know a great way to implement that.

@alexcrichton
Copy link
Member

I talked with @brson over lunch today, and the conclusion we reached was:

  • We probably want to add a new crate type for this (let's say rustc-builtins)
  • This crate type is nightly-only, that is gated by default.
  • This crate type, when found in the DAG, will always be linked as the rlib. That is, the linker will always be passed this rlib becuase duplication of the object file is OK
  • The crate is compiled the equivalent of -fvisibility=hidden

Does that make sense @japaric? This means we'll also have this be a separate crate, but with a custom crate type we can sequence it anywhere on the link line we want so I'm not to worried about the dependency tree.

@brson
Copy link
Contributor

brson commented Jul 26, 2016

Oof. Sorry for all the runaround @japaric .

@eddyb
Copy link
Member

eddyb commented Jul 26, 2016

We probably want to add a new crate type for this (let's say rustc-builtins)

Eek, couldn't this be done as rlib with a #![rustc_visibility = "hidden"] attribute?

@alexcrichton
Copy link
Member

@eddyb that part for sure could be done that way, although it wouldn't solve the linking problem. This object file basically wants to be duplicated, whereas all other libs don't.

@eddyb
Copy link
Member

eddyb commented Jul 26, 2016

@alexcrichton I'm thinking of implying that to be able to reach the symbols, they must be available directly when linking the final crate. There's probably a better name that can be used here, I guess.

@alexcrichton
Copy link
Member

Eh I'd be fine with that. I don't really mind if it's a new crate type or some other rando attribute, the semantics'll end up being the same either way.

@japaric
Copy link
Member Author

japaric commented Jul 29, 2016

This means we'll also have this be a separate crate, but with a custom crate type we can sequence it anywhere on the link line we want so I'm not to worried about the dependency tree.

Done, but I used a crate level attribute instead of a new crate type.

Only the Makefiles part is missing. Guess I can't postpone that anymore. rolls up sleeves

@alexcrichton
Copy link
Member

Looks good to me! Could the dependency between rustc-builtins and libcore be inverted though? If we have rustc-builtins depend on libcore we'll be able to easily define all the builtins using libcore.

@japaric japaric changed the title [WIP] crate-ify compiler-rt into rustc-builtins crate-ify compiler-rt into rustc-builtins Jul 29, 2016
@japaric
Copy link
Member Author

japaric commented Jul 29, 2016

Only the Makefiles part is missing.

Done.

Looks good to me! Could the dependency between rustc-builtins and libcore be inverted though?

If the dependency is inverted, won't all crates have to explicitly depend on rustc_builtins (rustc_builtins has to appear somewhere in the dependency graph)? Or are you that all crates should implicitly depend on rustc_builtins?

@alexcrichton
Copy link
Member

If the dependency is inverted, won't all crates have to explicitly depend on rustc_builtins (rustc_builtins has to appear somewhere in the dependency graph)?

Oh right I was thinking that libstd would depend on rustc-builtins

@japaric
Copy link
Member Author

japaric commented Jul 29, 2016

Oh right I was thinking that libstd would depend on rustc-builtins

In that case, no_std executables would now have to add extern crate rustc_builtins to their root module. Is that an OK breakage? (Guess all those are nightly only because of panic_fmt et al lang items)

@alexcrichton
Copy link
Member

Hm yeah that's a good point. On the other hand though I might also expect that? @brson how do you feel about that?

@alexcrichton
Copy link
Member

@bors: retry

On Tue, Sep 13, 2016 at 8:26 AM, bors notifications@github.com wrote:

💔 Test failed - auto-linux-32-opt
https://buildbot.rust-lang.org/builders/auto-linux-32-opt/builds/10555


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#35021 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAD95HTwN4VC7NVHQEhEAUmmU7qK7yjrks5qpsC0gaJpZM4JTwPg
.

@alexcrichton
Copy link
Member

@bors: retry

@bors
Copy link
Contributor

bors commented Sep 13, 2016

⌛ Testing commit 2656202 with merge 25d34f8...

@bors
Copy link
Contributor

bors commented Sep 13, 2016

💔 Test failed - auto-win-gnu-32-opt-rustbuild

This commit fixes a test which now needs to explicitly link to the
`compiler_builtins` crate as well as makes the `compiler_builtins` crate
unstable.
@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Sep 13, 2016

📌 Commit 848cfe2 has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Sep 13, 2016

⌛ Testing commit 848cfe2 with merge b1363a7...

bors added a commit that referenced this pull request Sep 13, 2016
crate-ify compiler-rt into compiler-builtins

libcompiler-rt.a is dead, long live libcompiler-builtins.rlib

This commit moves the logic that used to build libcompiler-rt.a into a
compiler-builtins crate on top of the core crate and below the std crate.
This new crate still compiles the compiler-rt instrinsics using gcc-rs
but produces an .rlib instead of a static library.

Also, with this commit rustc no longer passes -lcompiler-rt to the
linker. This effectively makes the "no-compiler-rt" field of target
specifications a no-op. Users of `no_std` will have to explicitly add
the compiler-builtins crate to their crate dependency graph *if* they
need the compiler-rt intrinsics - this is a [breaking-change]. Users
of the `std` have to do nothing extra as the std crate depends
on compiler-builtins.

Finally, this a step towards lazy compilation of std with Cargo as the
compiler-rt intrinsics can now be built by Cargo instead of having to
be supplied by the user by some other method.

closes #34400

---

r? @alexcrichton
@frewsxcv
Copy link
Member

I spent all day today doing a git bisect on the compiler trying to find out why the latest Rust nightlies don't work with afl.rs. It turned out the problematic commit is 3fd5fdd from this PR. It looks like these changes have caused the LLVM pass (via compiler plugin) used by afl.rs to stop working (rust-fuzz/afl.rs#101). If anyone has any remote idea about what could have caused it to stop working, let me know, thanks :)

@eddyb
Copy link
Member

eddyb commented Oct 25, 2016

It would help if you would post the linker errors. I'm almost certain that something to do with how we invoke linkers is what ended up hiding the symbols.

@frewsxcv
Copy link
Member

@frewsxcv
Copy link
Member

It would help if you would post the linker errors.

How do I find the linker errors? Are they in the output in my previous comment?

FWIW, I still can't use afl.rs with any nightly ever since this PR landed.

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

Successfully merging this pull request may close these issues.

Move compiler-rt build into a crate dependency of libcore