Skip to content

Commit

Permalink
Create a generic AVR target: avr-unknown-unknown
Browse files Browse the repository at this point in the history
This commit removes the `avr-unknown-gnu-atmega328` target and replaces
it with a more generic `avr-unknown-unknown` variant that can be
specialized using `-C target-cpu` (e.g. `-C target-cpu=atmega328p`).

I've decided to go with the `-unknown` tag (i.e. `avr-unknown-unknown`
instead of `avr-unknown-gnu`), because that's the name LLVM already uses
- I see no reason to diverge here.

Seizing the day, I'm adding myself as the maintainer of this target -
I've been already fixing the bugs anyway, might as well make it
official.

Related discussion:
rust-lang#131171
  • Loading branch information
Patryk27 committed Oct 19, 2024
1 parent b27f33a commit dcea80a
Show file tree
Hide file tree
Showing 16 changed files with 132 additions and 59 deletions.
14 changes: 12 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1920,10 +1920,20 @@ fn add_post_link_objects(

/// Add arbitrary "pre-link" args defined by the target spec or from command line.
/// FIXME: Determine where exactly these args need to be inserted.
fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
fn add_pre_link_args(
cmd: &mut dyn Linker,
sess: &Session,
flavor: LinkerFlavor,
codegen_results: &CodegenResults,
) {
if let Some(args) = sess.target.pre_link_args.get(&flavor) {
cmd.verbatim_args(args.iter().map(Deref::deref));
}

if sess.target.arch == "avr" {
cmd.verbatim_arg(format!("-mmcu={}", codegen_results.crate_info.target_cpu));
}

cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args);
}

Expand Down Expand Up @@ -2215,7 +2225,7 @@ fn linker_with_args(
// FIXME: In practice built-in target specs use this for arbitrary order-independent options,
// introduce a target spec option for order-independent linker options and migrate built-in
// specs to it.
add_pre_link_args(cmd, sess, flavor);
add_pre_link_args(cmd, sess, flavor, codegen_results);

// ------------ Object code and libraries, order-dependent ------------

Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,5 @@
use object::elf;

use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};

/// A base target for AVR devices using the GNU toolchain.
///
/// Requires GNU avr-gcc and avr-binutils on the host system.
/// FIXME: Remove the second parameter when const string concatenation is possible.
pub(crate) fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
Target {
arch: "avr".into(),
metadata: crate::spec::TargetMetadata {
description: None,
tier: None,
host_tools: None,
std: None,
},
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
llvm_target: "avr-unknown-unknown".into(),
pointer_width: 16,
options: TargetOptions {
env: "gnu".into(),

c_int_width: "16".into(),
cpu: target_cpu.into(),
exe_suffix: ".elf".into(),

linker: Some("avr-gcc".into()),
eh_frame_header: false,
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]),
late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[
"-lgcc",
]),
max_atomic_width: Some(16),
atomic_cas: false,
relocation_model: RelocModel::Static,
..TargetOptions::default()
},
}
}

/// Resolve the value of the EF_AVR_ARCH field for AVR ELF files, given the
/// name of the target CPU / MCU.
///
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/spec/base/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub(crate) mod aix;
pub(crate) mod android;
pub(crate) mod apple;
pub(crate) mod avr_gnu;
pub(crate) mod avr;
pub(crate) mod bpf;
pub(crate) mod dragonfly;
pub(crate) mod freebsd;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub use base::apple::{
deployment_target_for_target as current_apple_deployment_target,
platform as current_apple_platform,
};
pub use base::avr_gnu::ef_avr_arch;
pub use base::avr::ef_avr_arch;

/// Linker is called through a C/C++ compiler.
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
Expand Down Expand Up @@ -1734,7 +1734,7 @@ supported_targets! {
("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),

("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
("avr-unknown-unknown", avr_unknown_unknown),

("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),

Expand Down

This file was deleted.

30 changes: 30 additions & 0 deletions compiler/rustc_target/src/spec/targets/avr_unknown_unknown.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};

pub(crate) fn target() -> Target {
Target {
arch: "avr".into(),
metadata: crate::spec::TargetMetadata {
description: None,
tier: None,
host_tools: None,
std: None,
},
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
llvm_target: "avr-unknown-unknown".into(),
pointer_width: 16,
options: TargetOptions {
c_int_width: "16".into(),
exe_suffix: ".elf".into(),
linker: Some("avr-gcc".into()),
eh_frame_header: false,
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[]),
late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[
"-lgcc",
]),
max_atomic_width: Some(16),
atomic_cas: false,
relocation_model: RelocModel::Static,
..TargetOptions::default()
},
}
}
1 change: 0 additions & 1 deletion compiler/rustc_target/src/spec/tests/tests_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ impl Target {
&self.post_link_args,
] {
for (&flavor, flavor_args) in args {
assert!(!flavor_args.is_empty());
// Check that flavors mentioned in link args are compatible with the default flavor.
match self.linker_flavor {
LinkerFlavor::Gnu(..) => {
Expand Down
2 changes: 1 addition & 1 deletion src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ target | std | host | notes
[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | Armv7-A Apple WatchOS
[`armv7s-apple-ios`](platform-support/apple-ios.md) | ✓ | | Armv7-A Apple-A6 Apple iOS
[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare Armv8-R, hardfloat
`avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core`
`avr-unknown-unknown` | * | | AVR
`bpfeb-unknown-none` | * | | BPF (big endian)
`bpfel-unknown-none` | * | | BPF (little endian)
`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian)
Expand Down
75 changes: 75 additions & 0 deletions src/doc/rustc/src/platform-support/avr-unknown-unknown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# `avr-unknown-unknown`

Series of microcontrollers from Atmel: ATmega8, ATmega328p etc.

**Tier: 3**

## Target maintainers

-[Patryk Wychowaniec](https://github.com/Patryk27) <[email protected]>

## Requirements

This target is only cross-compiled - x86_64 / aarch64 x Lixux / MacOS hosts are
confirmed to work, but in principle any machine able to run rustc and avr-gcc
should be good.

Compiling for this target requires `avr-gcc`, because a couple of intrinsics
(like 32-bit multiplication) rely on [`libgcc`](https://github.com/gcc-mirror/gcc/blob/3269a722b7a03613e9c4e2862bc5088c4a17cc11/libgcc/config/avr/lib1funcs.S)
and can't be provided through `compiler-builtins` yet; this is a limitation that
we hope to lift in the future, see https://github.com/rust-lang/compiler-builtins/issues/711.

## Building the target

Rust comes with AVR support enabled, you don't have to rebuild the compiler
itself.

## Building Rust programs

Install `avr-gcc`:

```console
# Ubuntu:
$ sudo apt-get install gcc-avr

# Mac:
$ brew tap osx-cross/avr && brew install avr-gcc

# NixOS (takes a couple of minutes, since Hydra doesn't build it):
$ nix shell nixpkgs#pkgsCross.avr.buildPackages.gcc11
```

... setup `.cargo/config` for your project:

```toml
[build]
target = "avr-unknown-unknown"
rustflags = ["-C", "target-cpu=atmega328p"]

[unstable]
build-std = ["core"]
```

... and then simply run:

```console
$ cargo build --release
```

The final binary will be placed into
`./target/avr-unknown-unknown/release/your-project.elf`.

Note that since AVRs have rather small amounts of registers, ROM and RAM, it's
recommended to always use `--release` to avoid running out of space.

## Testing

You can use [`simavr`](https://github.com/buserror/simavr) to emulate the
resulting firmware on your machine:

```
simavr -m atmega328p ./target/avr-unknown-unknown/release/your-project.elf
```

Alternatively, if you want to write a couple of actual `#[test]`s, you can use
[`avr-tester`](https://github.com/Patryk27/avr-tester).
3 changes: 3 additions & 0 deletions src/tools/compiletest/src/header/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,10 @@ fn profiler_runtime() {
#[test]
fn asm_support() {
let asms = [
#[cfg(bootstrap)]
("avr-unknown-gnu-atmega328", false),
#[cfg(not(bootstrap))]
("avr-unknown-unknown", false),
("i686-unknown-netbsd", true),
("riscv32gc-unknown-linux-gnu", true),
("riscv64imac-unknown-none-elf", true),
Expand Down
2 changes: 1 addition & 1 deletion tests/assembly/asm/avr-modifiers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target avr-unknown-gnu-atmega328
//@ compile-flags: --target avr-unknown-unknown -C target-cpu=atmega328p
//@ needs-llvm-components: avr

#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
Expand Down
2 changes: 1 addition & 1 deletion tests/assembly/asm/avr-types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target avr-unknown-gnu-atmega328
//@ compile-flags: --target avr-unknown-unknown -C target-cpu=atmega328p
//@ needs-llvm-components: avr

#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
Expand Down
6 changes: 3 additions & 3 deletions tests/assembly/targets/targets-pe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
//@ revisions: arm64ec_pc_windows_msvc
//@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc
//@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64
//@ revisions: avr_unknown_gnu_atmega328
//@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328
//@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr
//@ revisions: avr_unknown_unknown
//@ [avr_unknown_unknown] compile-flags: --target avr-unknown-unknown -C target-cpu=atmega328p
//@ [avr_unknown_unknown] needs-llvm-components: avr
//@ revisions: bpfeb_unknown_none
//@ [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none
//@ [bpfeb_unknown_none] needs-llvm-components: bpf
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/avr/avr-func-addrspace.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@ compile-flags: -O --target=avr-unknown-gnu-atmega328 --crate-type=rlib -C panic=abort
//@ compile-flags: -O --target=avr-unknown-unknown -C target-cpu=atmega328p --crate-type=rlib -C panic=abort
//@ needs-llvm-components: avr

// This test validates that function pointers can be stored in global variables
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ needs-llvm-components: avr
//@ compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
//@ compile-flags: --target=avr-unknown-unknown -C target-cpu=atmega328p --crate-type=rlib
#![no_core]
#![feature(no_core, lang_items)]
#[lang="sized"]
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/repr/16-bit-repr-c-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//@ revisions: avr msp430
//
//@ [avr] needs-llvm-components: avr
//@ [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
//@ [avr] compile-flags: --target=avr-unknown-unknown -C target-cpu=atmega328p --crate-type=rlib
//@ [msp430] needs-llvm-components: msp430
//@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib
#![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)]
Expand Down

0 comments on commit dcea80a

Please sign in to comment.