Skip to content
This repository has been archived by the owner on May 21, 2019. It is now read-only.

Rust: Create 3 logical ARM builds, based on support for VFP & Thumb2 #22

Merged

Conversation

timonvo
Copy link

@timonvo timonvo commented Apr 15, 2016

The three types of compiler-rt builds we now support on ARM are:

  • arm: This is for targets like arm-unknown-linux-gnueabi. It
    assumes the target doesn't support hardware float (VFP), nor
    Thumb2 instructions.
  • armhf: This is for targets like arm-unknown-linux-gnueabihf (but
    also arm-linux-androideabi). It assumes the target supports VFP
    but not Thumb2 instructions.
  • armv7: This is for targets like armv7-unknown-linux-gnueabihf.
    It assumes the target supports both VFP and Thumb2 instructions.

These three types (mostly) mirror the way Rust's ARM targets are
named. The ones starting with arm- and ending with eabi fall in
the arm bucket, the ones starting with arm- and ending with
eabihf fall in the armhf bucket (although Android is an
exception), and the ones starting with armv7- fall in the armv7
bucket.

This CL will have a couple of effects:

  • The CMake-based and plain Make-based builds would previously build
    different builtins for the same target triple. E.g.
    arm-linux-androideabi would have Thumb2 but not VFP builtins with
    the former, but VFP and not Thumb2 builtins with the latter. The
    CMake-based build is now consistent with the plain Make-based
    build.
  • The CMake-based build would always specific -march=armv7-a for
    any ARM build, even if it was for say, an ARMv6 target. This is
    now fixed and the build will use whatever CMAKE_C_FLAGS were
    specified during configuration instead.
  • The plain Make-based builds wouldn't build the ARM-specific
    builtins for targets triples like arm-unknown-linux-gnueabi
    before , because the Arch variable would get set to arm, which
    wasn't in the list of OnlyArchs in the
    lib/builtins/arm/Makefile. This was confusing though, because
    for part of the builtins (the non ARM-specific ones) we would use
    the compiler-rt implementation, while for others we would end up
    using the libgcc implementation. After this change, we'll
    always use the compiler-rt implementation.
  • For similar reasons, target triples like
    arm-unknown-linux-musleabi would not have the ARM-specific
    builtins built. For MUSL targets that is a problem though, since
    they won't link with libgcc at all, and hence the ARM-specific
    builtins symbols would be missing at link time. This is the reason
    why I started working on this change.

This change will need an accompanying change in Rust's
src/bootstrap/build/native.rs file to avoid breaking the Android
build. I have that ready to review next in rust-lang/rust@master...timonvo:update-compiler-rt.

@alexcrichton
Copy link
Member

Thanks for the PR @timonvo! Would it be possible to upstream these patches to LLVM first? I'm pretty wary of having us diverge even more from upstream as we're already pretty far ashore in terms of build systems :(

@timonvo
Copy link
Author

timonvo commented Apr 16, 2016

I'm not sure if they'll want these patches. I'm not 100% clear on how they build libclang_rt.a for ARM for cross-compiling clang toolchains, but our needs already seem pretty different from theirs, at least right now while we still use both CMake and plain Make-based builds at the same time.

Even if they'd take the patches, I'd rather land them here first and then try to upstream. I'm sorry but I'm just trying to finally land these ARM MUSL patches, I've had them lying around for a long time now. My last set of patches to upstream compiler-rt also took quite a while to land, unfortunately.

So WDYT? Any way we can still land these anyway?

@alexcrichton
Copy link
Member

Hm ok, this seems reasonably small enough that we don't need to worry too much about conflicts, should be easy enough to conceptually rebase I guess. It's a little weird that if you don't have thumb you don't get some intrinsics which means you may just flat out fail to compile, but I guess most of the time we use this library those intrinsics aren't actually used?

Could you back out the makefile changes for now as well? In theory any new work into portability and such should go into CMake, which both our build systems will have to migrate to eventually as well.

@timonvo
Copy link
Author

timonvo commented Apr 18, 2016

Yeah, it is a little weird that the presence of thumb2 support dictates whether or not you can use a specific built-in, especially since I don't think these builtins are thumb2 specific, it just so happens they're implemented using thumb 2 instructions (although maybe you can't implement them with plain ARM/Thumb1?). Either way, I think it's better to flat out fail to link rather than fail at runtime with a SIGILL error. If we ever do want to make this builtins available on <ARMv7 I think that'd have to be a separate change that should be upstreamed as well.

As for the Makefiles, I'll revert them. And I'll look into using the cmake build system for our plain Make-based builds as well.

The three types of `compiler-rt` builds we now support on ARM are:
- `arm`: This is for targets like arm-unknown-linux-gnueabi.  It
  assumes the target doesn't support hardware float (VFP), nor
  Thumb2 instructions.
- `armhf`: This is for targets like arm-unknown-linux-gnueabihf (but
  also arm-linux-androideabi). It assumes the target supports VFP
  but not Thumb2 instructions.
- `armv7`: This is for targets like armv7-unknown-linux-gnueabihf.
  It assumes the target supports both VFP and Thumb2 instructions.

These three types (mostly) mirror the way Rust's ARM targets are
named. The ones starting with `arm-` and ending with `eabi` fall in
the `arm` bucket, the ones starting with `arm-` and ending with
`eabihf` fall in the `armhf` bucket (although Android is an
exception), and the ones starting with `armv7-` fall in the `armv7`
bucket.

This CL will have a couple of effects:
- The CMake-based and plain Make-based builds would previously build
  different builtins for the same target triple. E.g.
  arm-linux-androideabi would have Thumb2 but not VFP builtins with
  the former, but VFP and not Thumb2 builtins with the latter. The
  CMake-based build is now consistent with the plain Make-based
  build.
- The CMake-based build would *always* specific `-march=armv7-a` for
  any ARM build, even if it was for say, an ARMv6 target. This is
  now fixed and the build will use whatever CMAKE_C_FLAGS were
  specified during configuration instead.
- The plain Make-based builds wouldn't build the ARM-specific
  builtins for targets triples like `arm-unknown-linux-gnueabi`
  before , because the `Arch` variable would get set to `arm`, which
  wasn't in the list of `OnlyArchs` in the
  `lib/builtins/arm/Makefile`. This was confusing though, because
  for part of the builtins (the non ARM-specific ones) we would use
  the `compiler-rt` implementation, while for others we would end up
  using the `libgcc` implementation.  After this change, we'll
  always use the `compiler-rt` implementation.
- For similar reasons, target triples like
  `arm-unknown-linux-musleabi` would not have the ARM-specific
  builtins built. For MUSL targets that is a problem though, since
  they won't link with `libgcc` at all, and hence the ARM-specific
  builtins symbols would be missing at link time. This is the reason
  why I started working on this change.

This change will need an accompanying change in Rust's
src/bootstrap/build/native.rs file to avoid breaking the Android
build.
@timonvo timonvo force-pushed the fix-arm-vfp-thumb2-builtins branch from af9e2ca to 2a051ea Compare April 18, 2016 16:44
@timonvo
Copy link
Author

timonvo commented Apr 18, 2016

Makefile changes reverted.

@alexcrichton alexcrichton merged commit e3b7e47 into rust-lang:rust-2016-04-04 Apr 18, 2016
@alexcrichton
Copy link
Member

Thanks!

@timonvo timonvo deleted the fix-arm-vfp-thumb2-builtins branch April 27, 2016 03:58
@timonvo
Copy link
Author

timonvo commented Apr 27, 2016

For posterity: I've been thinking, and I think the best way to fix this issue upstream in LLVM may be to:

  • Add an implementation for the __sync_fetch_and_add builtins for ARMv6 (i.e. not based on Thumb2 instructions that are unavailable on non-ARMv7 arches). This fixes having to split off the Thumb2-based builtins from non-ARMv7 arches.
  • Make sure that the build uses the -march specified in the CMAKE_C_FLAGS (instead of unconditionally using -march=armv7-a). This fixes generated code having ARMv7 instructions that would be illegal on non-ARMv7 arches.
  • Somehow always forcing VFP support when building the VFP builtins. This could fix the build failing when attempting to build for non-ARMv7.

That way, we could just always build the whole compiler-rt library with all of the ARM builtins, regardless of the compile target. The VFP builtins would always be included in the library but Rust/LLVM/GCC wouldn't generate any references to them if the compile target doesn't actually support VFP instructions, so they wouldn't have any effect when the library is used with those targets.

timonvo added a commit to timonvo/rust that referenced this pull request Apr 28, 2016
The targets are:
- `arm-unknown-linux-musleabi`
- `arm-unknown-linux-musleabihf`
- `armv7-unknown-linux-musleabihf`

These mirror the existing `gnueabi` targets.

All of these targets produce fully static binaries, similar to the
x86 MUSL targets.

For now these targets can only be used with `--rustbuild` builds, as
rust-lang/compiler-rt#22 only made the
necessary compiler-rt changes in the CMake configs, not the plain
GNU Make configs.

I've tested these targets GCC 5.3.0 compiled again musl-1.1.12
(downloaded from http://musl.codu.org/). An example `./configure`
invocation is:

```
./configure \
    --enable-rustbuild
    --target=arm-unknown-linux-musleabi \
    --musl-root="$MUSL_ROOT"
```

where `MUSL_ROOT` points to the `arm-linux-musleabi` prefix.
Usually that path will be of the form
`/foobar/arm-linux-musleabi/arm-linux-musleabi`.

Usually the cross-compile toolchain will live under
`/foobar/arm-linux-musleabi/bin`. That path should either by added
to your `PATH` variable, or you should add a section to your
`config.toml` as follows:

```
[target.arm-unknown-linux-musleabi]
cc = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-gcc"
cxx = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-g++"
```

As a prerequisite you'll also have to put a cross-compiled static
`libunwind.a` library in `$MUSL_ROOT/lib`. This is similar to [how
the x86_64 MUSL targets are built]
(https://doc.rust-lang.org/book/advanced-linking.html).
japaric pushed a commit to japaric/rust that referenced this pull request Jul 27, 2016
The targets are:
- `arm-unknown-linux-musleabi`
- `arm-unknown-linux-musleabihf`
- `armv7-unknown-linux-musleabihf`

These mirror the existing `gnueabi` targets.

All of these targets produce fully static binaries, similar to the
x86 MUSL targets.

For now these targets can only be used with `--rustbuild` builds, as
rust-lang/compiler-rt#22 only made the
necessary compiler-rt changes in the CMake configs, not the plain
GNU Make configs.

I've tested these targets GCC 5.3.0 compiled again musl-1.1.12
(downloaded from http://musl.codu.org/). An example `./configure`
invocation is:

```
./configure \
    --enable-rustbuild
    --target=arm-unknown-linux-musleabi \
    --musl-root="$MUSL_ROOT"
```

where `MUSL_ROOT` points to the `arm-linux-musleabi` prefix.
Usually that path will be of the form
`/foobar/arm-linux-musleabi/arm-linux-musleabi`.

Usually the cross-compile toolchain will live under
`/foobar/arm-linux-musleabi/bin`. That path should either by added
to your `PATH` variable, or you should add a section to your
`config.toml` as follows:

```
[target.arm-unknown-linux-musleabi]
cc = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-gcc"
cxx = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-g++"
```

As a prerequisite you'll also have to put a cross-compiled static
`libunwind.a` library in `$MUSL_ROOT/lib`. This is similar to [how
the x86_64 MUSL targets are built]
(https://doc.rust-lang.org/book/advanced-linking.html).
japaric pushed a commit to japaric/rust that referenced this pull request Jul 30, 2016
The targets are:
- `arm-unknown-linux-musleabi`
- `arm-unknown-linux-musleabihf`
- `armv7-unknown-linux-musleabihf`

These mirror the existing `gnueabi` targets.

All of these targets produce fully static binaries, similar to the
x86 MUSL targets.

For now these targets can only be used with `--rustbuild` builds, as
rust-lang/compiler-rt#22 only made the
necessary compiler-rt changes in the CMake configs, not the plain
GNU Make configs.

I've tested these targets GCC 5.3.0 compiled again musl-1.1.12
(downloaded from http://musl.codu.org/). An example `./configure`
invocation is:

```
./configure \
    --enable-rustbuild
    --target=arm-unknown-linux-musleabi \
    --musl-root="$MUSL_ROOT"
```

where `MUSL_ROOT` points to the `arm-linux-musleabi` prefix.
Usually that path will be of the form
`/foobar/arm-linux-musleabi/arm-linux-musleabi`.

Usually the cross-compile toolchain will live under
`/foobar/arm-linux-musleabi/bin`. That path should either by added
to your `PATH` variable, or you should add a section to your
`config.toml` as follows:

```
[target.arm-unknown-linux-musleabi]
cc = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-gcc"
cxx = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-g++"
```

As a prerequisite you'll also have to put a cross-compiled static
`libunwind.a` library in `$MUSL_ROOT/lib`. This is similar to [how
the x86_64 MUSL targets are built]
(https://doc.rust-lang.org/book/advanced-linking.html).
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants