wg icon indicating copy to clipboard operation
wg copied to clipboard

Test AVR against all no_std crates in a Crater run

Open dylanmckay opened this issue 6 years ago • 10 comments

The AVR fork can now fully compile libcore to machine code in all the programs we've tested. It is unclear if there are other, yet unexercised parts of libcore that have issues with AVR.

On top of this, we don't have a clear idea of which existing crates are compatible with 16-bit targets.

Many of the hundreds of common Rust libraries have not been tested against AVR. It would be pertinent to know if there are any current AVR troubles with the existing crate ecosystem before we progress with merging the backend upstream.

Upstream Rust use a tool called crater to assess the impact of breaking changes on every crate publishes to crates.io.

We should perform a crater run with AVR so we will have a precise breakdown of exactly which crates will work, which crates will break, and what bugs we may need to fix before upstream.

Is it possible to use Crater on a rustc fork, constrained to no_std crates? Does a crater run require heavy infrastructure, and if so, can we plug in something like a docker host and use it on our own machines? I don't really know how it works internally.

Does anyone know if this is feasible?

dylanmckay avatar Dec 19 '18 06:12 dylanmckay

I guess, in the Crater run, the no_std feature of every crate will need to be enabled if it exists, otherwise compilation is impossible.

dylanmckay avatar Dec 19 '18 06:12 dylanmckay

Hi! Main Crater developer here!

We should perform a crater run with AVR so we will have a precise breakdown of exactly which crates will work, which crates will break, and what bugs we may need to fix before upstream.

Is it possible to use Crater on a rustc fork

As long as you have a PR on the rust-lang/rust repo buildable on CI it's straightforward to start a Crater run with that. It doesn't need to be a PR you intend to merge, it can also be just a raw dump of the code you have right now.

constrained to no_std crates?

I guess, in the Crater run, the no_std feature of every crate will need to be enabled if it exists, otherwise compilation is impossible.

Crater already has some code to inspect/edit a crate's Cargo.toml before it's tested, so it shouldn't be too hard to implement.

Does a crater run require heavy infrastructure, and if so, can we plug in something like a docker host and use it on our own machines?

Crater uses docker to sandbox builds, and it's not a problem to hook custom machines to it. As far as infrastructure goes, at the moment a Crater run is executed on a c5.2xlarge AWS instance (8 threads @ 3.5GHz, 16GB RAM) with 4TB of storage attached. With that configuration a cargo check takes a day and half, and a cargo test takes three days.

Does anyone know if this is feasible?

Do you need to build/run stuff on embedded hardware or can it run on a x86_64 machine? (not too familiar with the embedded world, sorry!) If everything can be done on x86_64 we can execute the run on our Crater machines.

Unfortunately I won't have time to do the changes to the Crater codebase needed to do this run, but I'd be happy to mentor! You can find me in the #crater channel on Discord.

pietroalbini avatar Dec 19 '18 14:12 pietroalbini

Do you need to build/run stuff on embedded hardware or can it run on a x86_64 machine? (not too familiar with the embedded world, sorry!) If everything can be done on x86_64 we can execute the run on our Crater machines.

I believe that the goal here would be to simply compile the code, doing the equivalent of cargo build --target=avr-none-none. Actually running on an embedded device (or even an emulator) would require quite a bit of work.

We should look into running tests on an AVR emulator/device, of course, but I think that's future work.

shepmaster avatar Dec 19 '18 15:12 shepmaster

It is unclear if there are other, yet unexercised parts of libcore that have issues with AVR.

#[inline] and generic functions / methods in libraries are lowered to metadata and won't be lowered to machine code until they are actually called from a different crate. So the best way to encounter codegen bugs is by compiling binary crates. Most codegen bugs I have seen are in atomics and compiler intrinsics so in addition to a crater run I would suggest these compile tests:

  • Compile and link this crate (you'll have to tweak a bit the entry point), which exercises most of the 32-bit and 64-bit compiler intrinsics. You'll likely want to add code to that file to test 16-bit compiler intrinsics (operations not available natively; e.g. u16 / u16 (maybe? I'm not familiar with the instruction set)).

  • That file doesn't exercise intrinsics like memcpy so also write and compile (--emit=obj) a crate that uses ptr::copy_nonoverlapping (memcpy), ptr::write_bytes (memset, memclr) and [T].eq (memcmp). Check that the generated machine code contains calls to mem{cpy,clr,set,cmp}. Also check that compiler_builtins.rlib contains those symbols.

  • Write and compile a file that exercises atomic::compiler_fence and AtomicUsize.{load,store,$some_cas_api} (if max-atomic-width is non-zero). I usually write something like this:

#![crate_type = "lib"]
#![no_std]

#[no_mangle]
fn foo(x: &AtomicUsize) -> usize {
    x.load(Ordering::Acquire) // TODO try all orderings;
}

#[no_mangle]
fn bar(x: &AtomicUsize) -> usize {
    x.fetch_add(1, Ordering::Acquire) // TODO try all orderings;
}

// TODO try compiler_fence and AtomicUsize.store
$ cargo objdump --target thumbv7m-none-eabi --lib --release -- -d -no-show-raw-insn
Disassembly of section .text.foo:
foo:
       0:       ldr     r0, [r0]
       2:       dmb     sy
       6:       bx      lr
Disassembly of section .text.bar:
bar:
       0:       mov     r1, r0
       2:       ldrex   r0, [r1]
       6:       adds    r2, r0, #1
       8:       strex   r3, r2, [r1]
       c:       cmp     r3, #0
       e:       bne     #-16 <bar+0x2>
      10:       dmb     sy
      14:       bx      lr
  • I have never seen this break before but you may also want to exercise register allocation. Something like this should do the trick (but note that this will error on any target if too many registers are used; so you should have a rough idea of how many registers can be used):
// TODO also try `fn() -> !` (it can use more registers) and `#[naked]` (it has a weird ABI)
#[no_mangle]
unsafe fn foo() {
    asm!("" :: "r"(0) "r"(1) "r"(2) "r"(3) "r"(4) "r"(5) /* .. */ :: "volatile");
}

japaric avatar Dec 21 '18 00:12 japaric

  • I have never seen this break before but you may also want to exercise register allocation.

Hahahaha. I think this has been the single most difficult part of the AVR port; we've run into so many issues around this. I'm sure we haven't seen the last of them!

shepmaster avatar Dec 21 '18 00:12 shepmaster

What is the status of this? It would be really interesting to be able to publish Arduino libraries written in Rust

eddyp avatar Jan 06 '19 14:01 eddyp

@pietroalbini that's good to hear, thanks!

I will create a DO NOT MERGE PR to upstream Rust including the changes required to run the AVR rustc fork.

Do you have any links to existing crater PRs that include Cargo.toml introspection?

Thanks for the help!

dylanmckay avatar Jan 16 '19 07:01 dylanmckay

@japaric those are good suggestions. I've raised avr-rust/rust#125 to track testing of compiler-builtins.

Unfortunately, we can't use compiler-builtins with AVR yet because the libgcc library from avr-libc contains a few functions with nonstandard calling conventions, which the LLVM AVR backend currently emits code to match. This is mostly around the division and multiplication routines.

We should make the libgcc-specific calling convention logic optional somehow, then compiler-builtins could be enabled for AVR proper.

dylanmckay avatar Jan 16 '19 07:01 dylanmckay

Do you have any links to existing crater PRs that include Cargo.toml introspection?

The Cargo.toml changes are done here in Crater: https://github.com/rust-lang-nursery/crater/blob/master/src/runner/toml_frobber.rs

pietroalbini avatar Jan 16 '19 16:01 pietroalbini

For a simulator you can use:

luqasz avatar Jul 01 '19 17:07 luqasz

Closing this as part of 2024 triage.

AVR support is in upstream rustc now, there's no rustc fork maintained by the WG anymore.

Dirbaio avatar Jun 11 '24 18:06 Dirbaio