1
Fork 0

[AVR] Add AVR platform support

This commit is contained in:
Jake Goulding 2016-05-06 09:32:10 -04:00 committed by Dylan McKay
parent 5d39f1fa29
commit 690bb8af51
21 changed files with 158 additions and 2 deletions

View file

@ -69,7 +69,7 @@
# the same format as above, but since these targets are experimental, they are # 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 # 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. # 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. # Cap the number of parallel linker invocations when compiling LLVM.
# This can be useful when building LLVM with debug info, which significantly # This can be useful when building LLVM with debug info, which significantly

View file

@ -144,7 +144,7 @@ impl Step for Llvm {
let llvm_exp_targets = match builder.config.llvm_experimental_targets { let llvm_exp_targets = match builder.config.llvm_experimental_targets {
Some(ref s) => s, Some(ref s) => s,
None => "", None => "AVR",
}; };
let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" }; let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };

View file

@ -121,6 +121,14 @@ impl<'a> PostExpansionVisitor<'a> {
"amdgpu-kernel ABI is experimental and subject to change" "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" => { "efiapi" => {
gate_feature_post!( gate_feature_post!(
&self, &self,

View file

@ -375,6 +375,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
match self.conv { match self.conv {
Conv::C | Conv::Rust => llvm::CCallConv, Conv::C | Conv::Rust => llvm::CCallConv,
Conv::AmdGpuKernel => llvm::AmdGpuKernel, Conv::AmdGpuKernel => llvm::AmdGpuKernel,
Conv::AvrInterrupt => llvm::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
Conv::ArmAapcs => llvm::ArmAapcsCallConv, Conv::ArmAapcs => llvm::ArmAapcsCallConv,
Conv::Msp430Intr => llvm::Msp430Intr, Conv::Msp430Intr => llvm::Msp430Intr,
Conv::PtxKernel => llvm::PtxKernel, Conv::PtxKernel => llvm::PtxKernel,

View file

@ -45,6 +45,8 @@ pub enum CallConv {
X86_64_Win64 = 79, X86_64_Win64 = 79,
X86_VectorCall = 80, X86_VectorCall = 80,
X86_Intr = 83, X86_Intr = 83,
AvrNonBlockingInterrupt = 84,
AvrInterrupt = 85,
AmdGpuKernel = 91, AmdGpuKernel = 91,
} }

View file

@ -347,6 +347,9 @@ declare_features! (
/// Allows `extern "msp430-interrupt" fn()`. /// Allows `extern "msp430-interrupt" fn()`.
(active, abi_msp430_interrupt, "1.16.0", Some(38487), None), (active, abi_msp430_interrupt, "1.16.0", Some(38487), None),
/// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
(active, abi_avr_interrupt, "1.41.0", None, None),
/// Allows declarative macros 2.0 (`macro`). /// Allows declarative macros 2.0 (`macro`).
(active, decl_macro, "1.17.0", Some(39412), None), (active, decl_macro, "1.17.0", Some(39412), None),

View file

@ -78,6 +78,7 @@ fn main() {
"arm", "arm",
"aarch64", "aarch64",
"amdgpu", "amdgpu",
"avr",
"mips", "mips",
"powerpc", "powerpc",
"systemz", "systemz",

View file

@ -76,6 +76,14 @@ pub fn initialize_available_targets() {
LLVMInitializeAMDGPUAsmPrinter, LLVMInitializeAMDGPUAsmPrinter,
LLVMInitializeAMDGPUAsmParser LLVMInitializeAMDGPUAsmParser
); );
init_target!(
llvm_component = "avr",
LLVMInitializeAVRTargetInfo,
LLVMInitializeAVRTarget,
LLVMInitializeAVRTargetMC,
LLVMInitializeAVRAsmPrinter,
LLVMInitializeAVRAsmParser
);
init_target!( init_target!(
llvm_component = "mips", llvm_component = "mips",
LLVMInitializeMipsTargetInfo, LLVMInitializeMipsTargetInfo,

View file

@ -2529,6 +2529,8 @@ where
Msp430Interrupt => Conv::Msp430Intr, Msp430Interrupt => Conv::Msp430Intr,
X86Interrupt => Conv::X86Intr, X86Interrupt => Conv::X86Intr,
AmdGpuKernel => Conv::AmdGpuKernel, AmdGpuKernel => Conv::AmdGpuKernel,
AvrInterrupt => Conv::AvrInterrupt,
AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,
// These API constants ought to be more specific... // These API constants ought to be more specific...
Cdecl => Conv::C, Cdecl => Conv::C,

View file

@ -120,6 +120,7 @@ symbols! {
abi_unadjusted, abi_unadjusted,
abi_vectorcall, abi_vectorcall,
abi_x86_interrupt, abi_x86_interrupt,
abi_avr_interrupt,
abort, abort,
aborts, aborts,
address, address,

View file

@ -0,0 +1,33 @@
#![allow(non_upper_case_globals)]
use crate::abi::call::{ArgAbi, FnAbi};
fn classify_ret_ty<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if ret.layout.is_aggregate() {
ret.make_indirect();
} else {
ret.extend_integer_width_to(8); // Is 8 correct?
}
}
fn classify_arg_ty<Ty>(arg: &mut ArgAbi<'_, Ty>) {
if arg.layout.is_aggregate() {
arg.make_indirect();
} else {
arg.extend_integer_width_to(8);
}
}
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);
}
}

View file

@ -5,6 +5,7 @@ use crate::spec::{self, HasTargetSpec};
mod aarch64; mod aarch64;
mod amdgpu; mod amdgpu;
mod arm; mod arm;
mod avr;
mod hexagon; mod hexagon;
mod mips; mod mips;
mod mips64; mod mips64;
@ -525,6 +526,8 @@ pub enum Conv {
X86_64Win64, X86_64Win64,
AmdGpuKernel, AmdGpuKernel,
AvrInterrupt,
AvrNonBlockingInterrupt,
} }
/// Metadata describing how the arguments to a native function /// Metadata describing how the arguments to a native function
@ -580,6 +583,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
"aarch64" => aarch64::compute_abi_info(cx, self), "aarch64" => aarch64::compute_abi_info(cx, self),
"amdgpu" => amdgpu::compute_abi_info(cx, self), "amdgpu" => amdgpu::compute_abi_info(cx, self),
"arm" => arm::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), "mips" => mips::compute_abi_info(cx, self),
"mips64" => mips64::compute_abi_info(cx, self), "mips64" => mips64::compute_abi_info(cx, self),
"powerpc" => powerpc::compute_abi_info(self), "powerpc" => powerpc::compute_abi_info(self),

View file

@ -34,6 +34,8 @@ pub enum Abi {
X86Interrupt, X86Interrupt,
AmdGpuKernel, AmdGpuKernel,
EfiApi, EfiApi,
AvrInterrupt,
AvrNonBlockingInterrupt,
// Multiplatform / generic ABIs // Multiplatform / generic ABIs
System, System,
@ -73,6 +75,12 @@ const AbiDatas: &[AbiData] = &[
AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false }, AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false },
AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false }, AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false },
AbiData { abi: Abi::EfiApi, name: "efiapi", 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 // Cross-platform ABIs
AbiData { abi: Abi::System, name: "system", generic: true }, AbiData { abi: Abi::System, name: "system", generic: true },
AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true }, AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },

View file

@ -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(),
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::none_base::opts(),
})
}

View file

@ -65,6 +65,7 @@ mod linux_kernel_base;
mod linux_musl_base; mod linux_musl_base;
mod msvc_base; mod msvc_base;
mod netbsd_base; mod netbsd_base;
mod none_base;
mod openbsd_base; mod openbsd_base;
mod redox_base; mod redox_base;
mod riscv_base; mod riscv_base;
@ -579,6 +580,8 @@ supported_targets! {
("aarch64-fuchsia", aarch64_fuchsia), ("aarch64-fuchsia", aarch64_fuchsia),
("x86_64-fuchsia", x86_64_fuchsia), ("x86_64-fuchsia", x86_64_fuchsia),
("avr-unknown-unknown", avr_unknown_unknown),
("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc), ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
("aarch64-unknown-redox", aarch64_unknown_redox), ("aarch64-unknown-redox", aarch64_unknown_redox),

View file

@ -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()
}
}

View file

@ -874,6 +874,7 @@ pub mod consts {
/// - x86_64 /// - x86_64
/// - arm /// - arm
/// - aarch64 /// - aarch64
/// - avr
/// - mips /// - mips
/// - mips64 /// - mips64
/// - powerpc /// - powerpc
@ -986,6 +987,11 @@ mod arch {
pub const ARCH: &str = "aarch64"; pub const ARCH: &str = "aarch64";
} }
#[cfg(target_arch = "avr")]
mod arch {
pub const ARCH: &'static str = "avr";
}
#[cfg(target_arch = "mips")] #[cfg(target_arch = "mips")]
mod arch { mod arch {
pub const ARCH: &str = "mips"; pub const ARCH: &str = "mips";

View file

@ -203,6 +203,12 @@ void LLVMRustAddLastExtensionPasses(
#define SUBTARGET_AARCH64 #define SUBTARGET_AARCH64
#endif #endif
#ifdef LLVM_COMPONENT_AVR
#define SUBTARGET_AVR SUBTARGET(AVR)
#else
#define SUBTARGET_AVR
#endif
#ifdef LLVM_COMPONENT_MIPS #ifdef LLVM_COMPONENT_MIPS
#define SUBTARGET_MIPS SUBTARGET(Mips) #define SUBTARGET_MIPS SUBTARGET(Mips)
#else #else
@ -249,6 +255,7 @@ void LLVMRustAddLastExtensionPasses(
SUBTARGET_X86 \ SUBTARGET_X86 \
SUBTARGET_ARM \ SUBTARGET_ARM \
SUBTARGET_AARCH64 \ SUBTARGET_AARCH64 \
SUBTARGET_AVR \
SUBTARGET_MIPS \ SUBTARGET_MIPS \
SUBTARGET_PPC \ SUBTARGET_PPC \
SUBTARGET_SYSTEMZ \ SUBTARGET_SYSTEMZ \

View file

@ -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();
}

View file

@ -0,0 +1,11 @@
error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
--> $DIR/feature-gate-abi-avr-interrupt.rs:14:1
|
LL | extern "avr-interrupt" fn foo() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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`.

View file

@ -47,6 +47,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
("armv7", "arm"), ("armv7", "arm"),
("armv7s", "arm"), ("armv7s", "arm"),
("asmjs", "asmjs"), ("asmjs", "asmjs"),
("avr", "avr"),
("hexagon", "hexagon"), ("hexagon", "hexagon"),
("i386", "x86"), ("i386", "x86"),
("i586", "x86"), ("i586", "x86"),