Skip to content

Acyclic compiler-rt and libc bootstrap #127227

@Ericson2314

Description

@Ericson2314

This is responding to the conversation in #125922, but I am opening a new issue because I would like to disentangle the larger idea from that specific PR.

They way some us Nixpkgs compiler maintainers see it, the ideal bootstrap order is:

  1. Build "true builtins", completely self-contained
  2. Build libc
  3. Build any additional "pseudo-builtins" depending on libc, without rebuilding the "true builtins"
  4. Build additional goodies like sanitizers

To wit, if the builtins and libc are really cyclic, then all sorts of accidental recursion is possible (imagine emutls eventually recurring back into emutls). On the flip side, if no recursion is happening, then the cyclic dep is in fact spurious and the acyclic dependency order already exists and is just waiting to "break free".

Yes, the circular dep is common, but it strikes as a more a historical accident that something anyone would want on purpose.

(For reference. Another such historical accident is building all of GCC twice, once without libc, once with. That is obviously overkill, and people rigged up things like https://github.com/richfelker/musl-cross-make to avoid it. LLVM doesn't engage in such folly, making it easy to build compiler-rt and clang separately. I think if we do disentangle this circle dep, the old "use libc headers" will be looked back upon in hindsight as just as silly.)

BTW, this sort of disentangling would also be good for Rust. Their "compiler builtins" package with bits of compiler-rt when doing a freestanding or WASM (without WASI at least) build ought not to depend on any libc, not even a newlib.


Getting down to brass tacks:

  • Stuff like emutls feels to be like clearly a "pseudo-builtins", it fallback logic in non-trivial software.

  • The builtins that use getauxval are a bit trickier. Can we skip them entirely in the first "true builtins" step? Unclear. And so you want to use features depending on hardware detection in freestanding code? Not sure what the right solution is, but ideally there is some interface that is amendable to OS-leveraging and freestanding approach, and it is more defined than "whatever in libc we happen to use".

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions