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

Test AVR against all no_std crates in a Crater run #282

Closed
dylanmckay opened this issue Dec 19, 2018 · 11 comments
Closed

Test AVR against all no_std crates in a Crater run #282

dylanmckay opened this issue Dec 19, 2018 · 11 comments

Comments

@dylanmckay
Copy link
Contributor

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
Copy link
Contributor Author

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.

@jplatte jplatte mentioned this issue Dec 19, 2018
8 tasks
@pietroalbini
Copy link

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.

@shepmaster
Copy link

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.

@japaric
Copy link
Member

japaric commented Dec 21, 2018

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");
}

@shepmaster
Copy link

  • 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!

@eddyp
Copy link

eddyp commented Jan 6, 2019

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

@dylanmckay
Copy link
Contributor Author

@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
Copy link
Contributor Author

@japaric those are good suggestions. I've raised avr-rust/rust-legacy-fork#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.

@pietroalbini
Copy link

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

@luqasz
Copy link

luqasz commented Jul 1, 2019

For a simulator you can use:

@Dirbaio
Copy link
Member

Dirbaio commented Jun 11, 2024

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 Dirbaio closed this as completed Jun 11, 2024
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

No branches or pull requests

7 participants