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

Enable AVR as a Tier 3 target upstream #69478

Merged
merged 9 commits into from
Jun 12, 2020
2 changes: 1 addition & 1 deletion config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
# the same format as above, but since these targets are experimental, they are
# not built by default and the experimental Rust compilation targets that depend
# on them will not work unless the user opts in to building them.
#experimental-targets = ""
#experimental-targets = "AVR"

# Cap the number of parallel linker invocations when compiling LLVM.
# This can be useful when building LLVM with debug info, which significantly
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl Step for Llvm {

let llvm_exp_targets = match builder.config.llvm_experimental_targets {
Some(ref s) => s,
None => "",
None => "AVR",
};

let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };
Expand Down
14 changes: 12 additions & 2 deletions src/libcore/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1345,14 +1345,24 @@ macro_rules! fnptr_impls_safety_abi {
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&(*self as *const ()), f)
// HACK: The intermediate cast as usize is required for AVR
// so that the address space of the source function pointer
// is preserved in the final function pointer.
//
// https://github.com/avr-rust/rust/issues/143
fmt::Pointer::fmt(&(*self as usize as *const ()), f)
dylanmckay marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&(*self as *const ()), f)
// HACK: The intermediate cast as usize is required for AVR
// so that the address space of the source function pointer
// is preserved in the final function pointer.
//
// https://github.com/avr-rust/rust/issues/143
fmt::Pointer::fmt(&(*self as usize as *const ()), f)
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_ast_passes/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ impl<'a> PostExpansionVisitor<'a> {
"amdgpu-kernel ABI is experimental and subject to change"
);
}
"avr-interrupt" | "avr-non-blocking-interrupt" => {
gate_feature_post!(
&self,
abi_avr_interrupt,
span,
"avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
);
}
"efiapi" => {
gate_feature_post!(
&self,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_codegen_llvm/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
match self.conv {
Conv::C | Conv::Rust => llvm::CCallConv,
Conv::AmdGpuKernel => llvm::AmdGpuKernel,
Conv::AvrInterrupt => llvm::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
Conv::ArmAapcs => llvm::ArmAapcsCallConv,
Conv::Msp430Intr => llvm::Msp430Intr,
Conv::PtxKernel => llvm::PtxKernel,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub enum CallConv {
X86_64_Win64 = 79,
X86_VectorCall = 80,
X86_Intr = 83,
AvrNonBlockingInterrupt = 84,
AvrInterrupt = 85,
AmdGpuKernel = 91,
}

Expand Down
3 changes: 3 additions & 0 deletions src/librustc_feature/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,9 @@ declare_features! (
/// No longer treat an unsafe function as an unsafe block.
(active, unsafe_block_in_unsafe_fn, "1.45.0", Some(71668), None),

/// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
(active, abi_avr_interrupt, "1.45.0", Some(69664), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ fn main() {
"arm",
"aarch64",
"amdgpu",
"avr",
"mips",
"powerpc",
"systemz",
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ pub fn initialize_available_targets() {
LLVMInitializeAMDGPUAsmPrinter,
LLVMInitializeAMDGPUAsmParser
);
init_target!(
llvm_component = "avr",
LLVMInitializeAVRTargetInfo,
LLVMInitializeAVRTarget,
LLVMInitializeAVRTargetMC,
LLVMInitializeAVRAsmPrinter,
LLVMInitializeAVRAsmParser
);
init_target!(
llvm_component = "mips",
LLVMInitializeMipsTargetInfo,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_middle/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2529,6 +2529,8 @@ where
Msp430Interrupt => Conv::Msp430Intr,
X86Interrupt => Conv::X86Intr,
AmdGpuKernel => Conv::AmdGpuKernel,
AvrInterrupt => Conv::AvrInterrupt,
AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,

// These API constants ought to be more specific...
Cdecl => Conv::C,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_span/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ symbols! {
abi_unadjusted,
abi_vectorcall,
abi_x86_interrupt,
abi_avr_interrupt,
abort,
aborts,
address,
Expand Down
59 changes: 59 additions & 0 deletions src/librustc_target/abi/call/avr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! LLVM-frontend specific AVR calling convention implementation.
//!
//! # Current calling convention ABI
//!
//! Inherited from Clang's `clang::DefaultABIInfo` implementation - self described
//! as
//!
//! > the default implementation for ABI specific details. This implementation
//! > provides information which results in
//! > self-consistent and sensible LLVM IR generation, but does not
//! > conform to any particular ABI.
//! >
//! > - Doxygen Doxumentation of `clang::DefaultABIInfo`
//!
//! This calling convention may not match AVR-GCC in all cases.
//!
//! In the future, an AVR-GCC compatible argument classification ABI should be
//! adopted in both Rust and Clang.
//!
//! *NOTE*: Currently, this module implements the same calling convention
//! that clang with AVR currently does - the default, simple, unspecialized
//! ABI implementation available to all targets. This ABI is not
//! binary-compatible with AVR-GCC. Once LLVM [PR46140](https://bugs.llvm.org/show_bug.cgi?id=46140)
//! is completed, this module should be updated to match so that both Clang
//! and Rust emit code to the same AVR-GCC compatible ABI.
//!
//! In particular, both Clang and Rust may not have the same semantics
jonas-schievink marked this conversation as resolved.
Show resolved Hide resolved
//! when promoting arguments to indirect references as AVR-GCC. It is important
//! to note that the core AVR ABI implementation within LLVM itself is ABI
//! compatible with AVR-GCC - Rust and AVR-GCC only differ in the small amount
//! of compiler frontend specific calling convention logic implemented here.

use crate::abi::call::{ArgAbi, FnAbi};

fn classify_ret_ty<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if ret.layout.is_aggregate() {
ret.make_indirect();
}
}

fn classify_arg_ty<Ty>(arg: &mut ArgAbi<'_, Ty>) {
if arg.layout.is_aggregate() {
arg.make_indirect();
}
}

pub fn compute_abi_info<Ty>(fty: &mut FnAbi<'_, Ty>) {
if !fty.ret.is_ignore() {
classify_ret_ty(&mut fty.ret);
}

for arg in &mut fty.args {
if arg.is_ignore() {
continue;
}

classify_arg_ty(arg);
}
}
4 changes: 4 additions & 0 deletions src/librustc_target/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::spec::{self, HasTargetSpec};
mod aarch64;
mod amdgpu;
mod arm;
mod avr;
mod hexagon;
mod mips;
mod mips64;
Expand Down Expand Up @@ -525,6 +526,8 @@ pub enum Conv {
X86_64Win64,

AmdGpuKernel,
AvrInterrupt,
AvrNonBlockingInterrupt,
}

/// Metadata describing how the arguments to a native function
Expand Down Expand Up @@ -580,6 +583,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
"aarch64" => aarch64::compute_abi_info(cx, self),
"amdgpu" => amdgpu::compute_abi_info(cx, self),
"arm" => arm::compute_abi_info(cx, self),
"avr" => avr::compute_abi_info(self),
"mips" => mips::compute_abi_info(cx, self),
"mips64" => mips64::compute_abi_info(cx, self),
"powerpc" => powerpc::compute_abi_info(self),
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_target/spec/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub enum Abi {
X86Interrupt,
AmdGpuKernel,
EfiApi,
AvrInterrupt,
AvrNonBlockingInterrupt,

// Multiplatform / generic ABIs
System,
Expand Down Expand Up @@ -73,6 +75,12 @@ const AbiDatas: &[AbiData] = &[
AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false },
AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false },
AbiData { abi: Abi::EfiApi, name: "efiapi", generic: false },
AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt", generic: false },
AbiData {
abi: Abi::AvrNonBlockingInterrupt,
name: "avr-non-blocking-interrupt",
generic: false,
},
// Cross-platform ABIs
AbiData { abi: Abi::System, name: "system", generic: true },
AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
Expand Down
17 changes: 17 additions & 0 deletions src/librustc_target/spec/avr_unknown_unknown.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
Ok(Target {
llvm_target: "avr-unknown-unknown".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "16".to_string(),
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".to_string(),
dylanmckay marked this conversation as resolved.
Show resolved Hide resolved
arch: "avr".to_string(),
linker_flavor: LinkerFlavor::Gcc,
target_os: "unknown".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
target_c_int_width: 16.to_string(),
options: super::freestanding_base::opts(),
})
}
30 changes: 30 additions & 0 deletions src/librustc_target/spec/freestanding_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();

args.insert(
LinkerFlavor::Gcc,
vec![
// We want to be able to strip as much executable code as possible
// from the linker command line, and this flag indicates to the
// linker that it can avoid linking in dynamic libraries that don't
// actually satisfy any symbols up to that point (as with many other
// resolutions the linker does). This option only applies to all
// following libraries so we're sure to pass it as one of the first
// arguments.
"-Wl,--as-needed".to_string(),
],
);

TargetOptions {
dynamic_linking: false,
executables: true,
linker_is_gnu: true,
has_rpath: false,
pre_link_args: args,
position_independent_executables: false,
..Default::default()
}
}
3 changes: 3 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ mod arm_base;
mod cloudabi_base;
mod dragonfly_base;
mod freebsd_base;
mod freestanding_base;
mod fuchsia_base;
mod haiku_base;
mod hermit_base;
Expand Down Expand Up @@ -579,6 +580,8 @@ supported_targets! {
("aarch64-fuchsia", aarch64_fuchsia),
("x86_64-fuchsia", x86_64_fuchsia),

("avr-unknown-unknown", avr_unknown_unknown),

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

("aarch64-unknown-redox", aarch64_unknown_redox),
Expand Down
7 changes: 7 additions & 0 deletions src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ void LLVMRustAddLastExtensionPasses(
#define SUBTARGET_AARCH64
#endif

#ifdef LLVM_COMPONENT_AVR
#define SUBTARGET_AVR SUBTARGET(AVR)
#else
#define SUBTARGET_AVR
#endif

#ifdef LLVM_COMPONENT_MIPS
#define SUBTARGET_MIPS SUBTARGET(Mips)
#else
Expand Down Expand Up @@ -249,6 +255,7 @@ void LLVMRustAddLastExtensionPasses(
SUBTARGET_X86 \
SUBTARGET_ARM \
SUBTARGET_AARCH64 \
SUBTARGET_AVR \
SUBTARGET_MIPS \
SUBTARGET_PPC \
SUBTARGET_SYSTEMZ \
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/codemap_tests/unicode.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́`
LL | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^^ invalid ABI
|
= help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
= help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted

error: aborting due to previous error

Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Test that the AVR interrupt ABI cannot be used when avr_interrupt
// feature gate is not used.

extern "avr-interrupt" fn foo() {}
//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change

fn main() {
foo();
}
12 changes: 12 additions & 0 deletions src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
--> $DIR/feature-gate-abi-avr-interrupt.rs:4:8
|
LL | extern "avr-interrupt" fn foo() {}
| ^^^^^^^^^^^^^^^
|
= note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
= help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
2 changes: 1 addition & 1 deletion src/test/ui/parser/issue-8537.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize`
LL | "invalid-ab_isize"
| ^^^^^^^^^^^^^^^^^^ invalid ABI
|
= help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
= help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted

error: aborting due to previous error

Expand Down
6 changes: 6 additions & 0 deletions src/tools/compiletest/src/header/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ fn test_parse_normalization_string() {
let first = parse_normalization_string(&mut s);
assert_eq!(first, Some("something (32 bits)".to_owned()));
assert_eq!(s, " -> \"something ($WORD bits).");

// Nothing to normalize (No quotes, 16-bit)
let mut s = "normalize-stderr-16bit: something (16 bits) -> something ($WORD bits).";
let first = parse_normalization_string(&mut s);
assert_eq!(first, None);
assert_eq!(s, r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)."#);
}

fn config() -> Config {
Expand Down
3 changes: 3 additions & 0 deletions src/tools/compiletest/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
("armv7", "arm"),
("armv7s", "arm"),
("asmjs", "asmjs"),
("avr", "avr"),
("hexagon", "hexagon"),
("i386", "x86"),
("i586", "x86"),
Expand Down Expand Up @@ -114,6 +115,8 @@ pub fn matches_env(triple: &str, name: &str) -> bool {
pub fn get_pointer_width(triple: &str) -> &'static str {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh I would've expected compiletest to get this from rustc (using --print).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah - writing this line made me feel very dirty.

if (triple.contains("64") && !triple.ends_with("gnux32")) || triple.starts_with("s390x") {
"64bit"
} else if triple.starts_with("avr") {
"16bit"
} else {
"32bit"
}
Expand Down