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

Create a generic AVR target: avr-unknown-unknown #131651

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
},
}
}
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
Loading