about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-06-12 01:28:37 +0000
committerbors <bors@rust-lang.org>2020-06-12 01:28:37 +0000
commite91bf6c881dc8fa50dc18fc2f518a6c22424ddb5 (patch)
tree54be1329599cb0f0c7d7cae62620894009d1b37d
parent14027f3e784de815de726a8fb0e74875781c9caf (diff)
parent0340359b2a3e9af1cd94cbf7831f8b77b9bf77a1 (diff)
downloadrust-e91bf6c881dc8fa50dc18fc2f518a6c22424ddb5.tar.gz
rust-e91bf6c881dc8fa50dc18fc2f518a6c22424ddb5.zip
Auto merge of #69478 - avr-rust:avr-support-upstream, r=jonas-schievink
Enable AVR as a Tier 3 target upstream

Tracking issue: #44052.

Things intentionally left out of the initial upstream:

* The `target_cpu` flag

I have made the cleanup suggestions by @jplatte and @jplatte in https://github.com/avr-rust/rust/commit/043550d9db0582add42e5837f636f61acb26b915.

Anybody feel free to give the branch a test and see how it fares, or make suggestions on the code patch itself.
-rw-r--r--config.toml.example2
-rw-r--r--src/bootstrap/native.rs2
-rw-r--r--src/libcore/ptr/mod.rs14
-rw-r--r--src/librustc_ast_passes/feature_gate.rs8
-rw-r--r--src/librustc_codegen_llvm/abi.rs2
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs2
-rw-r--r--src/librustc_feature/active.rs3
-rw-r--r--src/librustc_llvm/build.rs1
-rw-r--r--src/librustc_llvm/lib.rs8
-rw-r--r--src/librustc_middle/ty/layout.rs2
-rw-r--r--src/librustc_span/symbol.rs1
-rw-r--r--src/librustc_target/abi/call/avr.rs59
-rw-r--r--src/librustc_target/abi/call/mod.rs4
-rw-r--r--src/librustc_target/spec/abi.rs8
-rw-r--r--src/librustc_target/spec/avr_unknown_unknown.rs17
-rw-r--r--src/librustc_target/spec/freestanding_base.rs30
-rw-r--r--src/librustc_target/spec/mod.rs3
-rw-r--r--src/rustllvm/PassWrapper.cpp7
-rw-r--r--src/test/ui/codemap_tests/unicode.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs9
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr12
-rw-r--r--src/test/ui/parser/issue-8537.stderr2
-rw-r--r--src/tools/compiletest/src/header/tests.rs6
-rw-r--r--src/tools/compiletest/src/util.rs3
24 files changed, 201 insertions, 6 deletions
diff --git a/config.toml.example b/config.toml.example
index cf8fe4e082a..d995554913f 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -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
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 5b6e9534843..252a6316e57 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -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" };
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index ecc70adda41..777284ca5c0 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -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)
             }
         }
 
         #[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)
             }
         }
     }
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index ffd741a7b37..a7b0c9cf81b 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -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,
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 8e9c5f25ccb..099c402703d 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -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,
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 3c981af73ab..54cf99e1c6d 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -45,6 +45,8 @@ pub enum CallConv {
     X86_64_Win64 = 79,
     X86_VectorCall = 80,
     X86_Intr = 83,
+    AvrNonBlockingInterrupt = 84,
+    AvrInterrupt = 85,
     AmdGpuKernel = 91,
 }
 
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index fd35cb6c3f7..b4935236b6a 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -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
     // -------------------------------------------------------------------------
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index e97fa4345fe..ada48bc147e 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -78,6 +78,7 @@ fn main() {
         "arm",
         "aarch64",
         "amdgpu",
+        "avr",
         "mips",
         "powerpc",
         "systemz",
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index eca1808de3f..79e1a6cc5dc 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -77,6 +77,14 @@ pub fn initialize_available_targets() {
         LLVMInitializeAMDGPUAsmParser
     );
     init_target!(
+        llvm_component = "avr",
+        LLVMInitializeAVRTargetInfo,
+        LLVMInitializeAVRTarget,
+        LLVMInitializeAVRTargetMC,
+        LLVMInitializeAVRAsmPrinter,
+        LLVMInitializeAVRAsmParser
+    );
+    init_target!(
         llvm_component = "mips",
         LLVMInitializeMipsTargetInfo,
         LLVMInitializeMipsTarget,
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index e93abd3390a..f5bca90c2bd 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -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,
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index d165409696e..fea5880f01e 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -120,6 +120,7 @@ symbols! {
         abi_unadjusted,
         abi_vectorcall,
         abi_x86_interrupt,
+        abi_avr_interrupt,
         abort,
         aborts,
         address,
diff --git a/src/librustc_target/abi/call/avr.rs b/src/librustc_target/abi/call/avr.rs
new file mode 100644
index 00000000000..c1f7a1e3af5
--- /dev/null
+++ b/src/librustc_target/abi/call/avr.rs
@@ -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
+//! 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);
+    }
+}
diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs
index 0303312d057..8f7e2bba5aa 100644
--- a/src/librustc_target/abi/call/mod.rs
+++ b/src/librustc_target/abi/call/mod.rs
@@ -5,6 +5,7 @@ use crate::spec::{self, HasTargetSpec};
 mod aarch64;
 mod amdgpu;
 mod arm;
+mod avr;
 mod hexagon;
 mod mips;
 mod mips64;
@@ -525,6 +526,8 @@ pub enum Conv {
     X86_64Win64,
 
     AmdGpuKernel,
+    AvrInterrupt,
+    AvrNonBlockingInterrupt,
 }
 
 /// 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),
             "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),
diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs
index 226fe0b8bc6..a5c874bb4ac 100644
--- a/src/librustc_target/spec/abi.rs
+++ b/src/librustc_target/spec/abi.rs
@@ -34,6 +34,8 @@ pub enum Abi {
     X86Interrupt,
     AmdGpuKernel,
     EfiApi,
+    AvrInterrupt,
+    AvrNonBlockingInterrupt,
 
     // Multiplatform / generic ABIs
     System,
@@ -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 },
diff --git a/src/librustc_target/spec/avr_unknown_unknown.rs b/src/librustc_target/spec/avr_unknown_unknown.rs
new file mode 100644
index 00000000000..f90a8def0aa
--- /dev/null
+++ b/src/librustc_target/spec/avr_unknown_unknown.rs
@@ -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::freestanding_base::opts(),
+    })
+}
diff --git a/src/librustc_target/spec/freestanding_base.rs b/src/librustc_target/spec/freestanding_base.rs
new file mode 100644
index 00000000000..5402ea074fa
--- /dev/null
+++ b/src/librustc_target/spec/freestanding_base.rs
@@ -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()
+    }
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index f329c8c06cc..29250f21383 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -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;
@@ -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),
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 02dcfb8e829..3d252fe70af 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -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
@@ -249,6 +255,7 @@ void LLVMRustAddLastExtensionPasses(
   SUBTARGET_X86                                                                \
   SUBTARGET_ARM                                                                \
   SUBTARGET_AARCH64                                                            \
+  SUBTARGET_AVR                                                                \
   SUBTARGET_MIPS                                                               \
   SUBTARGET_PPC                                                                \
   SUBTARGET_SYSTEMZ                                                            \
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
index 4d4440fd07f..8b85adb5845 100644
--- a/src/test/ui/codemap_tests/unicode.stderr
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -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
 
diff --git a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
new file mode 100644
index 00000000000..0d7df8182c4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
@@ -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();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
new file mode 100644
index 00000000000..be7040e1491
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
@@ -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`.
diff --git a/src/test/ui/parser/issue-8537.stderr b/src/test/ui/parser/issue-8537.stderr
index 9ff28ce51e0..e33adb239d7 100644
--- a/src/test/ui/parser/issue-8537.stderr
+++ b/src/test/ui/parser/issue-8537.stderr
@@ -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
 
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 31d991e0c2f..f7355433463 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -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 {
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index c61bee0f8d9..ca36a15ffc7 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -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"),
@@ -114,6 +115,8 @@ pub fn matches_env(triple: &str, name: &str) -> bool {
 pub fn get_pointer_width(triple: &str) -> &'static str {
     if (triple.contains("64") && !triple.ends_with("gnux32")) || triple.starts_with("s390x") {
         "64bit"
+    } else if triple.starts_with("avr") {
+        "16bit"
     } else {
         "32bit"
     }