Giter Site home page Giter Site logo

rust-lang / compiler-builtins Goto Github PK

View Code? Open in Web Editor NEW
346.0 346.0 196.0 1.18 MB

Porting `compiler-rt` intrinsics to Rust

Home Page: https://github.com/rust-lang/rust/issues/35437

License: Other

Rust 87.55% Shell 1.38% Dockerfile 1.38% Assembly 9.70%

compiler-builtins's Introduction

compiler-builtins

Porting compiler-rt intrinsics to Rust

See rust-lang/rust#35437.

When and how to use this crate?

If you are working with a target that doesn't have binary releases of std available via rustup (this probably means you are building the core crate yourself) and need compiler-rt intrinsics (i.e. you are probably getting linker errors when building an executable: undefined reference to __aeabi_memcpy), you can use this crate to get those intrinsics and solve the linker errors. To do that, add this crate somewhere in the dependency graph of the crate you are building:

# Cargo.toml
[dependencies]
compiler_builtins = { git = "https://github.com/rust-lang/compiler-builtins" }
extern crate compiler_builtins;

// ...

If you still get an "undefined reference to $INTRINSIC" error after that change, that means that we haven't ported $INTRINSIC to Rust yet! Please open an issue with the name of the intrinsic and the LLVM triple (e.g. thumbv7m-none-eabi) of the target you are using. That way we can prioritize porting that particular intrinsic.

If you've got a C compiler available for your target then while we implement this intrinsic you can temporarily enable a fallback to the actual compiler-rt implementation as well for unimplemented intrinsics:

[dependencies.compiler_builtins]
git = "https://github.com/rust-lang/compiler-builtins"
features = ["c"]

Contributing

  1. Pick one or more intrinsics from the pending list.
  2. Fork this repository.
  3. Port the intrinsic(s) and their corresponding unit tests from their C implementation to Rust.
  4. Implement a test generator to compare the behavior of the ported intrinsic(s) with their implementation on the testing host. Note that randomized compiler-builtin tests should be run using cargo test --features gen-tests.
  5. Send a Pull Request (PR).
  6. Once the PR passes our extensive testing infrastructure, we'll merge it!
  7. Celebrate ๐ŸŽ‰

Porting Reminders

  1. Rust and C have slightly different operator precedence. C evaluates comparisons (== !=) before bitwise operations (& | ^), while Rust evaluates the other way.
  2. C assumes wrapping operations everywhere. Rust panics on overflow when in debug mode. Consider using the Wrapping type or the explicit wrapping_* functions where applicable.
  3. Note C implicit casts, especially integer promotion. Rust is much more explicit about casting, so be sure that any cast which affects the output is ported to the Rust implementation.
  4. Rust has many functions for integer or floating point manipulation in the standard library. Consider using one of these functions rather than porting a new one.

Testing

The easiest way to test locally is using Docker. This can be done by running ./ci/run-docker.sh [target]. If no target is specified, all targets will be run.

In order to run the full test suite, you will also need the C compiler runtime to test against, located in a directory called compiler-rt. This can be obtained with the following:

curl -L -o rustc-llvm-18.0.tar.gz https://github.com/rust-lang/llvm-project/archive/rustc/18.0-2024-02-13.tar.gz
tar xzf rustc-llvm-18.0.tar.gz --strip-components 1 llvm-project-rustc-18.0-2024-02-13/compiler-rt

Local targets may also be tested with ./ci/run.sh [target].

Note that testing may not work on all hosts, in which cases it is acceptable to rely on CI.

Progress

  • adddf3.c
  • addsf3.c
  • arm/adddf3vfp.S
  • arm/addsf3vfp.S
  • arm/aeabi_dcmp.S
  • arm/aeabi_fcmp.S
  • arm/aeabi_idivmod.S
  • arm/aeabi_ldivmod.S
  • arm/aeabi_memcpy.S
  • arm/aeabi_memmove.S
  • arm/aeabi_memset.S
  • arm/aeabi_uidivmod.S
  • arm/aeabi_uldivmod.S
  • arm/divdf3vfp.S
  • arm/divmodsi4.S (generic version is done)
  • arm/divsf3vfp.S
  • arm/divsi3.S (generic version is done)
  • arm/eqdf2vfp.S
  • arm/eqsf2vfp.S
  • arm/extendsfdf2vfp.S
  • arm/fixdfsivfp.S
  • arm/fixsfsivfp.S
  • arm/fixunsdfsivfp.S
  • arm/fixunssfsivfp.S
  • arm/floatsidfvfp.S
  • arm/floatsisfvfp.S
  • arm/floatunssidfvfp.S
  • arm/floatunssisfvfp.S
  • arm/gedf2vfp.S
  • arm/gesf2vfp.S
  • arm/gtdf2vfp.S
  • arm/gtsf2vfp.S
  • arm/ledf2vfp.S
  • arm/lesf2vfp.S
  • arm/ltdf2vfp.S
  • arm/ltsf2vfp.S
  • arm/modsi3.S (generic version is done)
  • arm/muldf3vfp.S
  • arm/mulsf3vfp.S
  • arm/nedf2vfp.S
  • arm/negdf2vfp.S
  • arm/negsf2vfp.S
  • arm/nesf2vfp.S
  • arm/softfloat-alias.list
  • arm/subdf3vfp.S
  • arm/subsf3vfp.S
  • arm/truncdfsf2vfp.S
  • arm/udivmodsi4.S (generic version is done)
  • arm/udivsi3.S (generic version is done)
  • arm/umodsi3.S (generic version is done)
  • arm/unorddf2vfp.S
  • arm/unordsf2vfp.S
  • ashldi3.c
  • ashrdi3.c
  • comparedf2.c
  • comparesf2.c
  • divdf3.c
  • divdi3.c
  • divmoddi4.c
  • divmodsi4.c
  • divsf3.c
  • divsi3.c
  • extendsfdf2.c
  • fixdfdi.c
  • fixdfsi.c
  • fixsfdi.c
  • fixsfsi.c
  • fixunsdfdi.c
  • fixunsdfsi.c
  • fixunssfdi.c
  • fixunssfsi.c
  • floatdidf.c
  • floatdisf.c
  • floatsidf.c
  • floatsisf.c
  • floatundidf.c
  • floatundisf.c
  • floatunsidf.c
  • floatunsisf.c
  • i386/ashldi3.S
  • i386/ashrdi3.S
  • i386/chkstk.S
  • i386/divdi3.S
  • i386/lshrdi3.S
  • i386/moddi3.S
  • i386/muldi3.S
  • i386/udivdi3.S
  • i386/umoddi3.S
  • lshrdi3.c
  • moddi3.c
  • modsi3.c
  • muldf3.c
  • muldi3.c
  • mulodi4.c
  • mulosi4.c
  • mulsf3.c
  • powidf2.c
  • powisf2.c
  • subdf3.c
  • subsf3.c
  • truncdfsf2.c
  • udivdi3.c
  • udivmoddi4.c
  • udivmodsi4.c
  • udivsi3.c
  • umoddi3.c
  • umodsi3.c
  • x86_64/chkstk.S

These builtins are needed to support 128-bit integers.

  • ashlti3.c
  • ashrti3.c
  • divti3.c
  • fixdfti.c
  • fixsfti.c
  • fixunsdfti.c
  • fixunssfti.c
  • floattidf.c
  • floattisf.c
  • floatuntidf.c
  • floatuntisf.c
  • lshrti3.c
  • modti3.c
  • muloti4.c
  • multi3.c
  • udivmodti4.c
  • udivti3.c
  • umodti3.c

These builtins are needed to support f16 and f128, which are in the process of being added to Rust.

  • addtf3.c
  • comparetf2.c
  • divtf3.c
  • extenddftf2.c
  • extendhfsf2.c
  • extendhftf2.c
  • extendsftf2.c
  • fixtfdi.c
  • fixtfsi.c
  • fixtfti.c
  • fixunstfdi.c
  • fixunstfsi.c
  • fixunstfti.c
  • floatditf.c
  • floatsitf.c
  • floatunditf.c
  • floatunsitf.c
  • multf3.c
  • powitf2.c
  • ppc/fixtfdi.c
  • ppc/fixunstfdi.c
  • ppc/floatditf.c
  • ppc/floatunditf.c
  • subtf3.c
  • truncdfhf2.c
  • truncsfhf2.c
  • trunctfdf2.c
  • trunctfhf2.c
  • trunctfsf2.c

Unimplemented functions

These builtins involve floating-point types ("f80" and complex numbers) that are not supported by Rust.

  • divdc3.c
  • divsc3.c
  • divtc3.c
  • divxc3.c
  • fixunsxfdi.c
  • fixunsxfsi.c
  • fixunsxfti.c
  • fixxfdi.c
  • fixxfti.c
  • floatdixf.c
  • floattixf.c
  • floatundixf.c
  • floatuntixf.c
  • i386/floatdixf.S
  • i386/floatundixf.S
  • muldc3.c
  • mulsc3.c
  • multc3.c
  • mulxc3.c
  • powixf2.c
  • ppc/divtc3.c
  • ppc/gcc_qadd.c
  • ppc/gcc_qdiv.c
  • ppc/gcc_qmul.c
  • ppc/gcc_qsub.c
  • ppc/multc3.c
  • x86_64/floatdixf.c
  • x86_64/floatundixf.S

These builtins are never called by LLVM.

  • absvdi2.c
  • absvsi2.c
  • absvti2.c
  • addvdi3.c
  • addvsi3.c
  • addvti3.c
  • arm/aeabi_cdcmp.S
  • arm/aeabi_cdcmpeq_check_nan.c
  • arm/aeabi_cfcmp.S
  • arm/aeabi_cfcmpeq_check_nan.c
  • arm/aeabi_div0.c
  • arm/aeabi_drsub.c
  • arm/aeabi_frsub.c
  • arm/aeabi_memcmp.S
  • arm/bswapdi2.S
  • arm/bswapsi2.S
  • arm/clzdi2.S
  • arm/clzsi2.S
  • arm/comparesf2.S
  • arm/restore_vfp_d8_d15_regs.S
  • arm/save_vfp_d8_d15_regs.S
  • arm/switch16.S
  • arm/switch32.S
  • arm/switch8.S
  • arm/switchu8.S
  • clzdi2.c
  • clzsi2.c
  • clzti2.c
  • cmpdi2.c
  • cmpti2.c
  • ctzdi2.c
  • ctzsi2.c
  • ctzti2.c
  • ffsdi2.c - this is called by gcc though!
  • ffsti2.c
  • mulvdi3.c
  • mulvsi3.c
  • mulvti3.c
  • negdf2.c
  • negdi2.c
  • negsf2.c
  • negti2.c
  • negvdi2.c
  • negvsi2.c
  • negvti2.c
  • paritydi2.c
  • paritysi2.c
  • parityti2.c
  • popcountdi2.c
  • popcountsi2.c
  • popcountti2.c
  • ppc/restFP.S
  • ppc/saveFP.S
  • subvdi3.c
  • subvsi3.c
  • subvti3.c
  • ucmpdi2.c
  • ucmpti2.c
  • udivmodti4.c

Rust only exposes atomic types on platforms that support them, and therefore does not need to fall back to software implementations.

  • arm/sync_fetch_and_add_4.S
  • arm/sync_fetch_and_add_8.S
  • arm/sync_fetch_and_and_4.S
  • arm/sync_fetch_and_and_8.S
  • arm/sync_fetch_and_max_4.S
  • arm/sync_fetch_and_max_8.S
  • arm/sync_fetch_and_min_4.S
  • arm/sync_fetch_and_min_8.S
  • arm/sync_fetch_and_nand_4.S
  • arm/sync_fetch_and_nand_8.S
  • arm/sync_fetch_and_or_4.S
  • arm/sync_fetch_and_or_8.S
  • arm/sync_fetch_and_sub_4.S
  • arm/sync_fetch_and_sub_8.S
  • arm/sync_fetch_and_umax_4.S
  • arm/sync_fetch_and_umax_8.S
  • arm/sync_fetch_and_umin_4.S
  • arm/sync_fetch_and_umin_8.S
  • arm/sync_fetch_and_xor_4.S
  • arm/sync_fetch_and_xor_8.S
  • arm/sync_synchronize.S
  • atomic.c
  • atomic_flag_clear.c
  • atomic_flag_clear_explicit.c
  • atomic_flag_test_and_set.c
  • atomic_flag_test_and_set_explicit.c
  • atomic_signal_fence.c
  • atomic_thread_fence.c

Miscellaneous functionality that is not used by Rust.

  • apple_versioning.c
  • clear_cache.c
  • emutls.c
  • enable_execute_stack.c
  • eprintf.c
  • gcc_personality_v0.c
  • trampoline_setup.c

Floating-point implementations of builtins that are only called from soft-float code. It would be better to simply use the generic soft-float versions in this case.

  • i386/floatdidf.S
  • i386/floatdisf.S
  • i386/floatundidf.S
  • i386/floatundisf.S
  • x86_64/floatundidf.S
  • x86_64/floatundisf.S
  • x86_64/floatdidf.c
  • x86_64/floatdisf.c

License

The compiler-builtins crate is dual licensed under both the University of Illinois "BSD-Like" license and the MIT license. As a user of this code you may choose to use it under either license. As a contributor, you agree to allow your code to be used under both.

Full text of the relevant licenses is in LICENSE.TXT.

compiler-builtins's People

Contributors

aaronkutch avatar alexcrichton avatar amanieu avatar amjad50 avatar ankane avatar ayrtonm avatar bjorn3 avatar bors avatar demindiro avatar est31 avatar homunkulus avatar japaric avatar jordanrh1 avatar josephlr avatar joshtriplett avatar jyn514 avatar lokathor avatar m-ou-se avatar mattico avatar nbdd0121 avatar nicholasbishop avatar paoloteti avatar patryk27 avatar ralfjung avatar scottmcm avatar tdecking avatar tgross35 avatar thekidofarcrania avatar trevyn avatar whitequark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

compiler-builtins's Issues

Floating point add gives different results than compiler-rt on arm-unknown-linux-gnueabi

I'm still trying to figure out what was wrong with #48, and I'd like another pair of eyes on this because I have no idea what is going on.

I added an implementation of arbitrary_float! again, and ran the tests. Only the arm-unknown-linux-gnueabi target failed. So I grab the arguments that made the test fail and put them into a regular test. On the next build, the test passes because we're actually getting the right answer in this case. It's gcc_s and compiler-rt that have the wrong answer.

Either:

  1. There's some subtle bug in the test infrastructure
  2. gcc_s and libcompiler-rt both have the same bug but we don't despite the code being almost identical to compiler-rt
  3. QEMU is broken but only in this specific way
  4. The C compiler's optimizations cause rounding in very small numbers, but rustc does not
  5. Something else?

fixdfti test fails if float generation gets fixed

In build.rs, there is code to use the random generator to create floats.

It has a little bug though in the way it determines the exponent. The exponent is first &ed with the mask, and then shifted. The issue is though, the mask is already assuming a shifted value. So we end up with the expression always being 0.

Instead it should be first shifted, and then &ed with the mask, like ((exponent << (SIGNIFICAND_BITS -1)) & EXPONENT_MASK) |.

When doing this though, I discovered that the fixdfti test fails. I first thought it was a conversion my PR added, but its in fact already present.

The error looks like:

thread 'fixdfti' panicked at 'assertion failed: `(left == right)` (left: `((5179139571476070400,), -170141183460469231731687303715884105728)`, right: `((5179139571476070400,), 170141183460469231731687303715884105727)`)'

AppVeyor: inspect binaries

like we do on Travis though I'm not sure if the AppVeyor environments contain tools for this (nm, objdump)

CI: Test on Windows

We could use AppVeyor but its build cycles are pretty slow. I guess we can start with 64-bit mingw on Travis to keep the test times small.

Failed to build as a dependency

Added this to my Cargo.toml

[dependencies]
rustc_builtins = { git = "https://github.com/japaric/rustc-builtins" }

tried to compile using

RUST_BACKTRACE=1 xargo build --target=stm32f429zi --verbose

got this error

error: failed to run custom build command for `rustc_builtins v0.1.0 (https://github.com/japaric/rustc-builtins#89ebc46f)`
process didn't exit successfully: `/Users/vadzim/Downloads/rplayground/target/debug/build/rustc_builtins-c925dd23196c1b21/build-script-build` (exit code: 101)
--- stdout
cargo:rerun-if-changed=build.rs

--- stderr
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ()', ../src/libcore/result.rs:799
stack backtrace:
   1:        0x109c560d8 - std::sys::backtrace::tracing::imp::write::h22f199c1dbb72ba2
   2:        0x109c5b56f - std::panicking::default_hook::{{closure}}::h9a389c462b6a22dd
   3:        0x109c5a605 - std::panicking::default_hook::h852b4223c1c00c59
   4:        0x109c5ab56 - std::panicking::rust_panic_with_hook::hcd9d05f53fa0dafc
   5:        0x109c5a9f4 - std::panicking::begin_panic::hf6c488cee66e7f17
   6:        0x109c5a912 - std::panicking::begin_panic_fmt::hb0a7126ee57cdd27
   7:        0x109c5a877 - rust_begin_unwind
   8:        0x109c80c30 - core::panicking::panic_fmt::h9af671b78898cdba
   9:        0x109c05c01 - core::result::unwrap_failed::hb3293571464cc40d
  10:        0x109c01575 - <core::result::Result<T, E>>::unwrap::hebcc09568bcc73ba
  11:        0x109c0fa1a - build_script_build::main::hfbb6c5966e861548
  12:        0x109c5bb2a - __rust_maybe_catch_panic
  13:        0x109c5a146 - std::rt::lang_start::h14cbded5fe3cd915
  14:        0x109c10e69 - main

error: `cargo` process didn't exit successfully

Undefined references to rust_eh_unwind_resume on x86_64-pc-windows-gnu

Originally from rust-lang/rust#43095 the reason this doesn't "just work" is because of rust-lang/rust#43151 and rust-lang/rust#43150. We should find a workaround in this repository for avoiding those bugs and check this into the test suite:

diff --git a/ci/run.sh b/ci/run.sh
index 9a32ee9..1b2cd7f 100755
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -116,7 +116,7 @@ if [ -z "$DEBUG_LTO_BUILD_DOESNT_WORK" ]; then
   RUSTFLAGS="-C debug-assertions=no" \
     $cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics -- -C lto
 fi
 $cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics --release -- -C lto

 # Ensure no references to a panicking function
 for rlib in $(echo $path); do
@@ -126,6 +126,12 @@ for rlib in $(echo $path); do
     if test $? = 0; then
         exit 1
     fi
+
+    $PREFIX$NM -u $rlib 2>&1 | grep unwind_resume
+
+    if test $? = 0; then
+        exit 1
+    fi
     set -ex
 done

One possible workaround may be to make these methods (I think the Int::aborting_* methods) generic with a random type parameter to force codegen to not generate landign pads here. Another "fix" would to actually fix these bugs upstream!

Add the dumbest implementation of mem{cpy,move,set}

I have these (needed for the AVR work), would you like to add them in here for now?

I know we don't have the weak linking situation well-understood, so one (terrible?) possibility is that we could simply include!('mem.rs') in the architectures that need it.

linker error when the "weak" feature is enabled

STR

$ cargo new --bin app && cd $_
$ edit Cargo.toml && tail -n4 $_
[dependencies.compiler_builtins]
branch = "rustbuild"
features = ["weak"]
git = "https://github.com/japaric/compiler-builtins"
$ edit src/main.rs && cat $_
#![feature(compiler_builtins_lib)]
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![no_main]
#![no_std]

extern crate compiler_builtins;

use core::intrinsics;

#[no_mangle]
pub fn _start() {
    unsafe {
        intrinsics::copy_nonoverlapping(0x0 as *const u32, 0x20 as *mut u32, 0x20);
    }
}

#[no_mangle]
pub fn __aeabi_unwind_cpp_pr0() {}

#[lang = "panic_fmt"]
extern "C" fn panic_fmt() {}
$ xargo rustc --target thumbv6m-none-eabi -- -C link-args=-nostartfiles
error: linking with `arm-none-eabi-gcc` failed: exit code: 1
  |
  = note: "arm-none-eabi-gcc" "-L" "/home/japaric/.xargo/lib/rustlib/thumbv6m-none-eabi/lib" "/home/japaric/tmp/app/target/thumbv6m-none-eabi/debug/deps/app-6d9087d3fe6b93f5.0.o" "-o" "/home/japaric/tmp/app/target/thumbv6m-none-eabi/debug/deps/app-6d9087d3fe6b93f5" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "/home/japaric/tmp/app/target/thumbv6m-none-eabi/debug/deps" "-L" "/home/japaric/tmp/app/target/debug/deps" "-L" "/home/japaric/.xargo/lib/rustlib/thumbv6m-none-eabi/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/home/japaric/tmp/app/target/thumbv6m-none-eabi/debug/deps/librlibc-ca4e4855ef16b6a5.rlib" "/home/japaric/.xargo/lib/rustlib/thumbv6m-none-eabi/lib/libcore-539305ece2e53820.rlib" "/home/japaric/tmp/app/target/thumbv6m-none-eabi/debug/deps/libcompiler_builtins-71942e6a7f812dde.rlib" "-nostartfiles"
  = note: /home/japaric/tmp/app/target/thumbv6m-none-eabi/debug/deps/libcompiler_builtins-71942e6a7f812dde.rlib(compiler_builtins-71942e6a7f812dde.0.o): In function `compiler_builtins::arm::__aeabi_memcpy4':
/home/japaric/.cargo/git/checkouts/compiler-builtins-299ea7fa6d11e5d0/b59c789/src/arm.rs:117: undefined reference to `memcpy'
/usr/lib/gcc/arm-none-eabi/6.2.0/../../../../arm-none-eabi/bin/ld: /home/japaric/tmp/app/target/thumbv6m-none-eabi/debug/deps/app-6d9087d3fe6b93f5: hidden symbol `memcpy' isn't defined
/usr/lib/gcc/arm-none-eabi/6.2.0/../../../../arm-none-eabi/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

Note the order of the linker arguments:

  • app.0.o
  • librlibc.rlib
  • libcore.rlib
  • libcompiler_builtins.rlib

And the relevant bits of running nm over these object files:

$ arm-none-eabi-nm -g **/app*.0.o
         U __aeabi_memcpy4

$ arm-none-eabi-nm -g **/librlibc*.rlib
00000000 W memcmp
00000000 W memcpy
00000000 W memmove
00000000 W memset

$ arm-none-eabi-nm -g ~/.xargo/lib/rustlib/thumbv6m-none-eabi/lib/libcore*.rlib
         U __aeabi_memclr4
         U __aeabi_memcpy
         U __aeabi_memcpy4
         U __aeabi_memset

$ arm-none-eabi-nm -g **/libcompiler_builtins*.rlib
         U memcpy
         U memmove
         U memset
00000000 T __aeabi_memclr
00000000 T __aeabi_memclr4
00000000 T __aeabi_memclr8
00000000 T __aeabi_memcpy
00000000 T __aeabi_memcpy4
00000000 T __aeabi_memcpy8
00000000 T __aeabi_memmove
00000000 T __aeabi_memmove4
00000000 T __aeabi_memmove8
00000000 T __aeabi_memset
00000000 T __aeabi_memset4
00000000 T __aeabi_memset8

For this to actually work, librlibc.rlib should be passed to the linker after libcompiler_builtins.rlib but that's not possible because compiler-builtins is marked as #![compiler_builtins] and will always be the last rlib to be passed to the linker.

Not quite sure how to solve this other than copy paste rlibc's mem* functions into compiler-builtins or special case rlibc in rustc ...

May be worth to mention that this is not a problem in no_std programs that link to libc and not use the "weak" Cargo feature as the linker arguments would look look like: libcore.rlib .. libcompiler_builtins.rlib -lc. In that case -lc would provide memcpy et al.

cc @alexcrichton

Trim the list of fallbacks in compiler-rt

Added in #74, the c feature enables building a bunch of compiler-rt intrinsics.

Right now the list is pretty huge and I think we definitely don't need a good number of these like:

  • emutls.c
  • gcc_personality_v0.c

etc

It looks like there's already a list of crossed off functions, maybe those could all be excluded?

Operations not available on ARMv6-M targets

These operations are not available on the thumbv6m-none-eabi target:

  • f64 as i64
  • f64 as u64
  • f64 == f64
  • f64 > f64
  • f64 < f64
  • f32 as i64
  • f32 as u64
  • f32 == f32
  • f32 > f32
  • f32 < f32

and won't be available until these intrinsics:

  • __aeabi_dcmpeq
  • __aeabi_dcmpgt
  • __aeabi_dcmple
  • __aeabi_dcmplt
  • __aeabi_fcmpeq
  • __aeabi_fcmpgt
  • __aeabi_fcmple
  • __aeabi_fcmplt

are ported to Rust because compiler-rt doesn't provide an implementation of these for the thumbv6m-none-eabi target.

umaal instruction

So I was playing with compiler-builtins-snapshot in qemu, and my program was hanging for no apparent reason. Then I looked into the code that was causing problems and found this instruction:

0x3c8a <core::num::flt2dec::strategy::grisu::format_shortest_opt+652>   umaal  r1, r5, r2, r3

This instruction should not be used on thumbv7m-none-eabi target.

Depending on compiler-builtins creates more unresolved symbols.

I am building for arm-none-eabihf (no_std) with the following target file:

{
    "llvm-target": "arm-none-eabihf",
    "target-endian": "little",
    "target-pointer-width": "32",
    "os": "none",
    "env": "eabi",
    "vendor": "unknown",
    "arch": "arm",

    "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
    "executables": true,
    "relocation-model": "static",
    "no-compiler-rt": true
}

I build with RUST_TARGET_PATH=`pwd` xargo build --target arm-none-eabihf.

Before adding a dependency on compiler-builtins, I get the following unresolved symbols, found by arm-none-eabi-nm target/arm-none-eabihf/debug/libtyran.a | grep "U ":

         U _ZN4core9panicking5panic17h86aded962ecadfccE
         U __aeabi_memclr4
         U __aeabi_memcpy
         U __aeabi_memcpy4
         U __aeabi_memset
         U __aeabi_uidiv
         U __aeabi_uidivmod
         U __aeabi_ul2d
         U __aeabi_ul2f
         U __aeabi_uldivmod
         U __aeabi_unwind_cpp_pr0
         U __aeabi_unwind_cpp_pr1
         U memcmp
         U __mulodi4
         U rust_begin_unwind
         U __sync_val_compare_and_swap_1
         U __sync_val_compare_and_swap_2
         U __sync_val_compare_and_swap_4

After adding compiler-builtins to my dependencies, the extern crate statement and corresponding feature in my lib.rs, I get the following undefined symbols found by the same command:

         U _ZN4core9panicking5panic17h86aded962ecadfccE
         U __aeabi_ddiv
         U __aeabi_dmul
         U __aeabi_fdiv
         U __aeabi_fmul
         U __aeabi_unwind_cpp_pr0
         U __aeabi_unwind_cpp_pr1
         U memcpy
         U memmove
         U memset
         U rust_eh_personality
         U _Unwind_Resume
         U _ZN4core9panicking5panic17h86aded962ecadfccE
         U __aeabi_memclr4
         U __aeabi_memcpy
         U __aeabi_memcpy4
         U __aeabi_memset
         U __aeabi_uidiv
         U __aeabi_uidivmod
         U __aeabi_ul2d
         U __aeabi_ul2f
         U __aeabi_uldivmod
         U __aeabi_unwind_cpp_pr0
         U __aeabi_unwind_cpp_pr1
         U memcmp
         U __mulodi4
         U rust_begin_unwind
         U __sync_val_compare_and_swap_1
         U __sync_val_compare_and_swap_2
         U __sync_val_compare_and_swap_4

Am I misusing this crate? What is the expected behavior in this case?

Spurious floattidf failures on mips

This was coming up every so often on #166 so wanted to jot this down before I forgot.

---- floattidf stdout ----

	thread 'floattidf' panicked at 'assertion failed: `(left == right)`

  left: `((-56294995342131100,), 14335762557005848176, 14335762557005848160, true)`,

 right: `((-56294995342131100,), 14335762557005848176, 14335762557005848160, false)`', /target/mips-unknown-linux-gnu/debug/build/compiler_builtins-7252d96c089bca74/out/floattidf.rs:10055

explore using utest for testing the thumb targets

utest is a custom test crate that supports no_std targets like the thumb targets. We could use it to test the thumb targets but there are a few complications:

  • utest-cortex-m-qemu, the test runner for thumb targets that works with QEMU emulation, depends on this crate. This means that this crate will appear twice in the dependency graph and that could cause problems.

  • even if we get #[test] working for the thumb targets, quickcheck still won't work / compile for those targets. So we'll have to create unit tests for the thumb targets that don't rely on quickcheck. We could port the compiler-builtins tests, those don't depend on quickcheck and have the advantage that we could move away from comparing compiler-builtins results to libgcc / libcompiler-rt results as well.

rust-lang/rust integration metabug

  • Build missing intrinsics from compiler-rt (C) source code #63
  • Put weak memcpy et al symbols behind an opt-in Cargo feature #64
  • Test our implementations against libgcc #65
  • Rename this repo to compiler-builtins
  • Transfer to rust-lang-nursery
  • compile functions with hidden visibility
  • i128 support - #133
  • "C" ABI -> "aapcs" on ARM - #116 #141

cc @alexcrichton

modsi3: debug assertion

#[test]
fn modsi3() {
    let (a, b) = (-2147483648, 1798783296);
    let c_ = __modsi3(a, b);
}
running 1 test
test modsi3 ... FAILED

failures:

---- modsi3 stdout ----
        thread 'modsi3' panicked at 'attempt to subtract with overflow', /home/japaric/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/9681358/src/int/sdiv.rs:38
note: Run with `RUST_BACKTRACE=1` for a backtrace.


failures:
    modsi3

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured

error: test failed

mulodi4 debug assertion

STR

#![feature(compiler_builtins_lib)]

extern crate compiler_builtins;

use compiler_builtins::int::mul::__mulodi4;

fn main() {
    let (a, b) = (72113192, -480093263);
    let mut overflow = 2;
    let c = __mulodi4(a, b, &mut overflow);
}
$ cross run --target armv7-unknown-linux-gnueabihf
     Running `/target/armv7-unknown-linux-gnueabihf/debug/foo`
thread 'main' panicked at 'attempt to subtract with overflow', /cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/0507842/src/int/sdiv.rs:13
note: Run with `RUST_BACKTRACE=1` for a backtrace.

The command hangs and doesn't return but that could be a Cross bug ... I don't know.

figure out some mechanism to alias symbols

The problem

Some symbols, like the __aeabi_* ones, are defined as "aliases" of others in the C implementation of compiler-rt. For example: __aeabi_dadd is an alias of __adddf3. This means that both symbols, the original and its alias, refer to the same routine and use of either will result in a call to the same routine.

Rust doesn't have a mechanism for aliasing symbols and right now we are "emulating" aliases like this:

#[no_mangle]
pub extern fn __aeabi_dadd(a: f64, b: f64) -> f64 {
    __adddf3(a, b)
}

Although this works (calling that "alias" does the right thing), it also incurrs in an extra function call everytime the alias is used:

00000a8c <__aeabi_dadd>:
 a8c:   ea00001a        b       afc <__adddf3>

Attempted solutions

Use #[link_args] to ask the linker to duplicate the symbol. See #39. Sadly, this didn't work because #[link_args] is not propagated through crates and also that feature is slated for removal so we can't rely on it anyway.

Possible non-ideal solutions

export_name

Most (all?) ARM builtins have the form __aeabi_*. compiler-rt implements them as aliases to the non-aeabi symbols. For example: __aeabi_dadd is an alias of __adddf3 and both symbols appear in libcompiler-rt.a. Given that ARM executables never use the non-aeabi symbols, we could simply expose the __adddf3 routine as the __aeabi_dadd symbol without providing the __adddf3 symbol. In Rust code this would look like this:

#[cfg_attr(target = "arm", export_name = "__aeabi_dadd")]
#[cfg_attr(not(target = "arm"), no_mangle)]
pub extern fn __adddf3(a: f64, b: f64) -> f64 { ... }

The result would be:

  • rustc_builtins on x86 exposes the __adddf3 symbol
  • rustc_builtins on ARM exposes the __aeabi_dadd symbol

In contrast, libcompiler-rt.a on ARM exposes both the __adddf3 and the __aeabi_dadd symbols

This approach can only be used if the implementation resides in rustc-builtins. For instance, we can't use this to expose the __aeabi_memcpy* symbols which are all aliases to memcpy.

Just duplicate the routine

#[no_mangle]
pub extern fn __adddf3(a: f64, b: f64) -> f64 { impl!() }

#[no_mangle]
pub extern fn __aeabi_dadd(a: f64, b: f64) -> f64 { impl!() }

This would get rid of the extra function call in the "alias" but would probably result in duplicate code/instructions in the final executable (unless LLVM is smart enough to deduplicate two routines that have the same instructions)


Anyone has any other idea about how to solve this?

[RFC] Provide intrinsics necessary to get atomics working on the thumbv6m-none-eabi target

The built-in thumbv6m-none-eabi has max_atomic_width set to 0 because LLVM doesn't know how to lower atomic operations to actual instructions instead it lowers atomic operations to intrinsics like __sync_fetch_and_add_4. The result is that core doesn't expose the Atomic* structs so the alloc crate and any other crate that depends on it can't be compiled for this target.

I propose we implement those intrinsics in this crate (libcompiler-rt.a provides these intrinsics on other architectures) and then change the definition of the thumbv6m target (max_atomic_width = 32) to provide atomics in core; that way alloc, collections and other crates would become compilable for this target.

This is the (incomplete) list of intrinsics that would need to be implemented:

  • __sync_fetch_and_add_4
  • __sync_lock_test_and_set_4

Their implementation would likely use locking by temporarily disabling the interrupts.

The alternative is to do the change in the target definition without implement the intrinsics. This pushes the task of implementing the intrinsics to the downstream users.

cc @alexcrichton @Amanieu @thejpster @whitequark

ARMv7-M: infinite recursion with __divmoddi4 / __mulodi4

STR

let x: i64 = 6940082214040621058;
let y: i64 = 2305846955181360688;

let z = x % y;
// or
let z = sdiv::__divmoddi4(x, y, &mut 0);

with the target: thumbv7m-none-eabi.

The above program works fine (it terminates) with the x86_64-unknown-linux-gnu target.

Meta

$ rustc -V
rustc 1.17.0-nightly (b1e31766d 2017-03-03)

Can't compile for `thumbv6-none-eabi`

Because some of our assembly implementation use thumb2 instructions that aren't available for it.

$ xargo build --target thumbv6m-none-eabi
   Compiling rustc_builtins v0.1.0 (file:///home/japaric/tmp/rustc-builtins)
error: <inline asm>:5:11: error: instruction requires: thumb2
          ldr r1, [sp], #4
          ^

  --> src/arm.rs:8:5
   |
8  |     asm!("push {lr}
   |     ^

error: <inline asm>:2:11: error: instruction requires: thumb2
          sub r12, sp, #12
          ^

  --> src/arm.rs:20:5
   |
20 |     asm!("push {lr}
   |     ^

error: <inline asm>:3:11: error: instruction requires: arm-mode
          str r12, [sp, #-20]!
          ^

  --> src/arm.rs:20:5
   |
20 |     asm!("push {lr}
   |     ^

error: <inline asm>:5:11: error: instruction requires: arm-mode
          ldrd r2, r3, [sp, #8]
          ^

  --> src/arm.rs:20:5
   |
20 |     asm!("push {lr}
   |     ^

error: aborting due to 4 previous errors

error: Could not compile `rustc_builtins`.

To learn more, run the command again with --verbose.
error: `cargo` process didn't exit successfully

Possible solutions:

  • Change the assembly implementations to not use thumb2 instructions.
  • Add a special implementation just for this target. The problem is that, AFAIK, there's no cfg argument that handles this conditional compilation. We'll likely need some way to cfg on the arch component of llvm-target.

cc @Amanieu

LTO causes undefined references to core::panicking::panic

Update

After #80, this only occurs with profile.dev (+debug-assertions) + LTO. To fix this we'll have to create newtypes over primitives types that intrinsics::abort() on bad inputs (division by zero) and overflow.


Getting a funky error when attempting to use rustc-builtins for nintendo 3DS shenanigans instead the prebuilt copy of libcompiler-rt that we've been using up to this point:

   Compiling ctru-rs v0.4.0 (https://github.com/FenrirWolf/ctru-rs?branch=builtins#27eb3caf)
   Compiling rustc_builtins v0.1.0 (https://github.com/japaric/rustc-builtins.git#69e93de9)
   Compiling alloc_system3ds v0.1.0 (https://github.com/rust3ds/alloc_system3ds?rev=da38c94#da38c941)
   Compiling ctru-sys v0.2.0 (https://github.com/FenrirWolf/ctru-rs?branch=builtins#27eb3caf)
   Compiling rust3ds-template v0.1.0 (file:///home/fenrir/projects/rust3ds-template)
error: linking with `arm-none-eabi-gcc` failed: exit code: 1
  |
  = note: "arm-none-eabi-gcc" "-specs=3dsx.specs" "-march=armv6k" "-mtune=mpcore" "-mfloat-abi=hard" "-mtp=soft" "-L" "/home/fenrir/.xargo/lib/rustlib/3ds/lib" "/home/fenrir/projects/rust3ds-template/target/3ds/release/rust3ds_template.0.o" "-o" "/home/fenrir/projects/rust3ds-template/target/3ds/release/rust3ds_template.elf" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "/home/fenrir/projects/rust3ds-template/target/3ds/release/deps" "-L" "/opt/devkitPro/libctru/lib" "-L" "/home/fenrir/.xargo/lib/rustlib/3ds/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/tmp/rustc.n3iL9DJW0uUT/libctru-56422efc011c55b9.rlib" "/tmp/rustc.n3iL9DJW0uUT/librustc_builtins-5c8a87f356eb958c.rlib" "-lc" "-lm" "-lsysbase" "-lc" "-lsysbase" "-lc"
  = note: /tmp/rustc.n3iL9DJW0uUT/librustc_builtins-5c8a87f356eb958c.rlib(rustc_builtins-5c8a87f356eb958c.0.o): In function `__udivmodsi4':
rustc_builtins.cgu-0.rs:(.text.__udivmodsi4+0xb4): undefined reference to `core::panicking::panic::h6d47421a09de1633'
/tmp/rustc.n3iL9DJW0uUT/librustc_builtins-5c8a87f356eb958c.rlib(rustc_builtins-5c8a87f356eb958c.0.o): In function `__udivmoddi4':
rustc_builtins.cgu-0.rs:(.text.__udivmoddi4+0x304): undefined reference to `core::panicking::panic::h6d47421a09de1633'
rustc_builtins.cgu-0.rs:(.text.__udivmoddi4+0x30c): undefined reference to `core::panicking::panic::h6d47421a09de1633'
rustc_builtins.cgu-0.rs:(.text.__udivmoddi4+0x314): undefined reference to `core::panicking::panic::h6d47421a09de1633'
/tmp/rustc.n3iL9DJW0uUT/librustc_builtins-5c8a87f356eb958c.rlib(rustc_builtins-5c8a87f356eb958c.0.o): In function `__aeabi_uidiv':
rustc_builtins.cgu-0.rs:(.text.__aeabi_uidiv+0xa0): undefined reference to `core::panicking::panic::h6d47421a09de1633'
/tmp/rustc.n3iL9DJW0uUT/librustc_builtins-5c8a87f356eb958c.rlib(rustc_builtins-5c8a87f356eb958c.0.o):rustc_builtins.cgu-0.rs:(.text.__divsi3+0x40): more undefined references to `core::panicking::panic::h6d47421a09de1633' follow
collect2: error: ld returned 1 exit status

error: aborting due to previous error

However, the error only occurs if lto = true is set in Cargo.toml. If LTO is disabled, the result is a successful build.

Quickcheck and test coverage

Quickcheck generates integer values in a small range around zero ([-100, 100]) (cf BurntSushi/quickcheck#119). These values are not enough to tests all the branches of some intrinsics implementation. We need better control over the generated values; here's are some possible solutions of the top of my head:

  • Synthesize integer values from two halves. That's is use (u32, u32) as quickcheck argument and then use u64::from_parts(some_u32, another_u32) in the actual test.
  • Create a newtype, e.g. U64(u64), and implement the Arbitrary trait for it, but have the implementation generate values in the [MIN, MAX] range.

Better test harness

I'd like to have results like:

target: thumbv6m-none-eabi

Testing 123 intrinsics...
test muldi ... ok
test mulosi ... ok
test mulodi ... ok
test divdi3 ... ERROR
  input: (-1, INT_MAX)
  results:
    compiler-rt:       32768
    gcc_s:             32768
    compiler-builtins: 32767
test udivmoddi4 ... ERROR
  input: (25, 367)
  results:
    compiler-rt:       3
    gcc_s:             N/A
    compiler-builtins: 365
...
target: thumbv6m-none-eabi

Benchmarking 123 intrinsics...
bench muldi...
  compiler-rt:       16,386 ns/iter (+- 366)
  gcc_s:             14,375 ns/iter (+- 540)
  compiler-builtins: 17,690 ns/iter (+- 750)
bench mulosi...
...

CI: Test on MIPS(el)

We'll need a toolchain but there's none available on precise or trusty. I'm going to build one, tarball it and see if we can use that.

thumbv6m: debug assertion in divmoddi4

#[test]
fn divmoddi4() {
    let (a, b) = (4165187992, 3876330169);
    let mut rem = 0;
    let c = __divmoddi4(a, b, &mut rem_);
}
$ qemu-arm target/thumbv6m-linux-eabi/debug/divmoddi4-04f11ecf75829660
running 1 tests
test divmoddi4 ...
panicked at 'attempt to multiply with overflow', /home/japaric/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/9681358/src/int/udiv.rs:95
qemu: uncaught target signal 4 (Illegal instruction) - core dumped
[1]    21208 illegal hardware instruction (core dumped)  qemu-arm target/thumbv6m-linux-eabi/debug/divmoddi4-04f11ecf75829660

thumbv7m targets don't have this problem.

Spurious segfault on powerpc

From #155

test mulodi4 ... Invalid data memory access: 0xf6fff46c

NIP f66a59b4   LR f669cc3c CTR f66a4724 XER 00000000 CPU#1

MSR 00006040 HID0 00000000  HF 00006000 idx 0

TB 00000133 574871746592

GPR00 00000000f669ca80 00000000f657eb30 00000000f65868c0 00000000f6fff100

GPR04 00000000f6fff190 000000006ff64640 0000000000000024 0000000000000024

GPR08 00000000f6fff194 00000000f6fff448 0000000000000348 0000000000000000

GPR12 0000000028428824 00000000f6fff0f4 00000000f6ecc5bc 00000000f66cd018

GPR16 000000006ff8b2a8 00000000f657f450 00000000f6589488 00000000f6ecacdc

GPR20 00000000f6f3fab8 000000006ff8d2f4 0000000000000000 0000000000000000

GPR24 00000000f6ecace0 00000000f66862a0 00000000f66cc308 00000000f6fff190

GPR28 0000000000130190 00000000f6ecf000 00000000f66ccff4 00000000f66cd910

CR 22428828  [ E  E  G  E  L  L  E  L  ]             RES ffffffff

FPR00 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR04 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR08 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR12 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR16 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR20 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR24 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR28 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPSCR 00000000

Invalid segfault errno (42000000)

NIP f66a59b4   LR f669cc3c CTR f66a4724 XER 00000000 CPU#1

MSR 00006040 HID0 00000000  HF 00006000 idx 0

TB 00000133 574872603121

GPR00 00000000f669ca80 00000000f657eb30 00000000f65868c0 00000000f6fff100

GPR04 00000000f6fff190 000000006ff64640 0000000000000024 0000000000000024

GPR08 00000000f6fff194 00000000f6fff448 0000000000000348 0000000000000000

GPR12 0000000028428824 00000000f6fff0f4 00000000f6ecc5bc 00000000f66cd018

GPR16 000000006ff8b2a8 00000000f657f450 00000000f6589488 00000000f6ecacdc

GPR20 00000000f6f3fab8 000000006ff8d2f4 0000000000000000 0000000000000000

GPR24 00000000f6ecace0 00000000f66862a0 00000000f66cc308 00000000f6fff190

GPR28 0000000000130190 00000000f6ecf000 00000000f66ccff4 00000000f66cd910

CR 22428828  [ E  E  G  E  L  L  E  L  ]             RES ffffffff

FPR00 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR04 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR08 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR12 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR16 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR20 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR24 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPR28 0000000000000000 0000000000000000 0000000000000000 0000000000000000

FPSCR 00000000

thread '<unnamed>' panicked at 'assertion failed: c.borrow().is_none()', /checkout/src/libstd/sys_common/thread_info.rs:51

note: Run with `RUST_BACKTRACE=1` for a backtrace.

fatal runtime error: failed to initiate panic, error 4134036808

qemu: uncaught target signal 6 (Aborted) - core dumped

error: process didn't exit successfully: `/target/powerpc-unknown-linux-gnu/debug/deps/mulodi4-67cf1fbdd87f7066` (signal: 6, SIGABRT: process abort signal)

I have seen this target spuriously segfault while running tests on other project so this may be some QEMU bug.

QEMU issues

Update

Trying to run the test suite on QEMU for some targets crashes QEMU

I'm not quite sure what's the exact problem for each target but some possible causes:

  • The std binaries for the target are "broken". Most likely, some C binding in libc is wrong.
  • We are using the wrong QEMU variant (qemu-ppc64le).
  • "Just" a problem with multithreading. This leads to sporadic failures.

In some cases, using QEMU's system emulation instead of user emulation might fix the problem.


Example.

Emphasis on sometimes. This is weird because (a) as of e5ab308, the test suite is deterministic and (b) I'm using RUST_TEST_THREADS=1 to "prevent" multithreading (QEMU is known to have problems handling multiple threads) but I guess this last part is impossible because detecting a panic requires at least two threads.

Quickcheck: Investigate always testing special cases

Right now we test the intrinsics by feeding them random input arguments. Given that we have full control of the Arbitrary implementation perhaps we can tweak the implementation to always generates special cases at the beginning. In other words, change the generated inputs from:

Today: e.g. i32 inputs: <rand>, <rand>, <rand>, ...
To: i32::MIN, 0, i32::MAX, <rand>, <rand>, ...

Test the i128 related intrinsics on windows

These intrinsics return a U64x2 instead of i128 / u128 because of ABI requirements.

The tests will have to modified somehow to test these. I tried a transmute:

#[test]
fn divti3() {
    for &((a, b), c) in TEST_CASES {
        let c_: i128 = unsafe { mem::transmute(__divti3(a, b)) };
        assert_eq!(((a, b), c), ((a, b), c_));
    }
}

but apparently it didn't work:

running 1 test
test divti3 ... FAILED
failures:
---- divti3 stdout ----
	thread 'divti3' panicked at 'assertion failed: `(left == right)` (left: `((-91225923628555883033450043276019451624, -99173197121162634899222824496910041088), -124760295158389846421118573101029785600)`, right: `((-91225923628555883033450043276019451624, -99173197121162634899222824496910041088), 0)`)', C:\projects\compiler-builtins\target\x86_64-pc-windows-msvc\debug\build\compiler_builtins-89dacbcd722cfc78\out/divti3.rs:10050

So maybe we should test for equality using the U64x2 type without going back to i128 / u128.

For #155 I'm going to ignore these tests on Windows which is what we are already doing.

cc @est31

__aeabi_lmul on thumbv6m-none-eabi

Managed to track a crash when using lmul down to what seems to be a stack overflow, with a loop between the __aeabi_lmul and __muldi3 functions. I think it's due to 0x6ccc in this dump.

Upload CI disassembilies to Pastebin/Gist

The disassembly makes the CI logs really long, which makes the page load slowly, and could obscure errors which happen after them. This problem is only going to get worse as the library gets bigger. Uploading the disassembly to makes it fairly easy to have a disassembly available for every build, but makes the logs more manageable.

Can't publish my crate to crates.io if it depends on compiler-builtins

I get this error trying to publish my crate

$ rustup run nightly cargo publish
    Updating registry `https://github.com/rust-lang/crates.io-index`
error: all dependencies must come from the same source.
dependency `compiler_builtins` comes from https://github.com/rust-lang-nursery/compiler-builtins.git instead

The snapshot on crates.io has a different name, and doesn't have the "mem" feature (so I suspect it is old). Is there a plan to move this onto crates.io, or can we update the snapshot?

Thanks.

cargo test doesn't work

Trying to do cargo test gives me:

$ cargo test
    Updating registry `https://github.com/rust-lang/crates.io-index`
    Updating git repository `https://github.com/japaric/utest`
   Compiling compiler_builtins v0.1.0 (file://~/src/compiler-builtins)
error: couldn't read "~/src/compiler-builtins/target/debug/build/compiler_builtins-c8e6c3e61fa405d0/out/powidf2.rs": No such file or directory (os error 2)
 --> tests/powidf2.rs:8:1
  |
8 | include!(concat!(env!("OUT_DIR"), "/powidf2.rs"));
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: couldn't read "~/src/compiler-builtins/target/debug/build/compiler_builtins-c8e6c3e61fa405d0/out/moddi3.rs": No such file or directory (os error 2)
 --> tests/moddi3.rs:8:1
  |
8 | include!(concat!(env!("OUT_DIR"), "/moddi3.rs"));
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: couldn't read "~/src/compiler-builtins/target/debug/build/compiler_builtins-c8e6c3e61fa405d0/out/fixunsdfdi.rs": No such file or directory (os error 2)
 --> tests/fixunsdfdi.rs:8:1
  |
8 | include!(concat!(env!("OUT_DIR"), "/fixunsdfdi.rs"));
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: Could not compile `compiler_builtins`.
Build failed, waiting for other jobs to finish...
error: Could not compile `compiler_builtins`.
Build failed, waiting for other jobs to finish...
error: Could not compile `compiler_builtins`.
Build failed, waiting for other jobs to finish...
error: build failed

Refactor Float implementation

#166 refactored the integer intrinsics by:

  • Adding wrapping_ functions to the Int trait, removing the need for lots of Wrapping(x) and x.0
  • Using traits to implement the various operations rather than using macros

These can both be applied to some extent to the floating point implementation.

Add #![deny(warnings)] to the crate

With lots of platform specific code it's pretty likely that a whole bunch of various warnings crop up here or there. What do you think about trying to reel these in with a blanket denial of all warnings?

compiler-rt's ARM implementation of udivsi3 seems... wrong?

I updated the compiler-rt submodule in #172 which notably pulled in llvm-mirror/compiler-rt@2fb759f I believe. I merged #172 despite failing tests believing it was a weird nightly thing, but the integration PR also failed with weird errors.

I did some more investigation locally and found I could reproduce the error on #172 locally relatively easily. When forced the compiler-builtins crate to use the Rust implementation of the __udivsi3 intrinsic then the error went away. The only other change to happen to this file since we last updated compiler-rt is llvm-mirror/compiler-rt@2624197 llvm-mirror/compiler-rt@6b34053, which when cherry-picked didn't seem to fix the problem.

I'm going to send a PR to avoid usage of compiler-rt's implementation, but it's presumably faster than what we have in Rust, so this is a tracking issue for closing that perf gap.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.