about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-07-10 05:14:10 +0200
committerGitHub <noreply@github.com>2019-07-10 05:14:10 +0200
commit6c0a406b1c9e4c518586ac3cc2fe96c21840a5dc (patch)
tree7abf65e94dcccf7f9b813037d5d6b3d3d7c54b24
parentfe26fc9a1cada15beb553adf0922286eb0bce274 (diff)
parentac560258e36659d542850651fc1b79e4db2eb29d (diff)
downloadrust-6c0a406b1c9e4c518586ac3cc2fe96c21840a5dc.tar.gz
rust-6c0a406b1c9e4c518586ac3cc2fe96c21840a5dc.zip
Rollup merge of #62474 - nikic:update-llvm, r=alexcrichton
Prepare for LLVM 9 update

Main changes:

 * In preparation for opaque pointer types, the `byval` attribute now takes a type. As such, the argument type needs to be threaded through to the function/callsite attribute application logic.
 * On ARM the `+fp-only-sp` and `+d16` features have become `-fp64` and `-d32`. I've switched the target definitions to use the new names, but also added bidirectional emulation so either can be used on any LLVM version for backwards compatibility.
 * The datalayout can now specify function pointer alignment. In particular on ARM `Fi8` is specified, which means that function pointer alignment is independent of function alignment. I've added this to our datalayouts to match LLVM (which is something we check) and strip the fnptr alignment for older LLVM versions.
 * The fmul/fadd reductions now always respect the accumulator (including for unordered reductions), so we should pass the identity instead of undef.

Open issues:

 * https://reviews.llvm.org/D62106 causes linker errors with ld.bdf due to https://sourceware.org/bugzilla/show_bug.cgi?id=24784. To avoid this I've enabled `RelaxELFRelocations`, which results in a GOTPCRELX relocation for `__tls_get_addr` and avoids the issue. However, this is likely not acceptable because relax relocations are not supported by older linker versions. We may need an LLVM option to keep using PLT for `__tls_get_addr` despite `RtLibUseGOT`.

The corresponding llvm-project PR is https://github.com/rust-lang/llvm-project/pull/19.

r? @ghost
-rw-r--r--src/librustc_codegen_llvm/abi.rs64
-rw-r--r--src/librustc_codegen_llvm/attributes.rs24
-rw-r--r--src/librustc_codegen_llvm/common.rs4
-rw-r--r--src/librustc_codegen_llvm/context.rs23
-rw-r--r--src/librustc_codegen_llvm/declare.rs2
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs5
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs3
-rw-r--r--src/librustc_codegen_ssa/traits/consts.rs1
-rw-r--r--src/librustc_target/spec/arm_linux_androideabi.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_musleabi.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_musleabihf.rs2
-rw-r--r--src/librustc_target/spec/armebv7r_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/armebv7r_none_eabihf.rs4
-rw-r--r--src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs2
-rw-r--r--src/librustc_target/spec/armv6_unknown_freebsd.rs2
-rw-r--r--src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs2
-rw-r--r--src/librustc_target/spec/armv7_apple_ios.rs2
-rw-r--r--src/librustc_target/spec/armv7_linux_androideabi.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs2
-rw-r--r--src/librustc_target/spec/armv7_unknown_freebsd.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7r_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/armv7r_none_eabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7s_apple_ios.rs2
-rw-r--r--src/librustc_target/spec/thumbv6m_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs2
-rw-r--r--src/librustc_target/spec/thumbv7em_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7em_none_eabihf.rs10
-rw-r--r--src/librustc_target/spec/thumbv7m_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7neon_linux_androideabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs2
-rw-r--r--src/librustc_target/spec/thumbv8m_base_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv8m_main_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv8m_main_none_eabihf.rs4
-rw-r--r--src/rustllvm/PassWrapper.cpp5
-rw-r--r--src/rustllvm/RustWrapper.cpp22
-rw-r--r--src/test/codegen/mainsubprogram.rs2
-rw-r--r--src/test/codegen/mainsubprogramstart.rs2
44 files changed, 160 insertions, 85 deletions
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 38d4b7e3f9d..ff87afe0c44 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -34,17 +34,17 @@ trait ArgAttributeExt {
 impl ArgAttributeExt for ArgAttribute {
     fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
         for_each_kind!(self, f,
-                       ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
+                       NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
     }
 }
 
 pub trait ArgAttributesExt {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value);
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value);
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
 }
 
 impl ArgAttributesExt for ArgAttributes {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -65,11 +65,14 @@ impl ArgAttributesExt for ArgAttributes {
                                                idx.as_uint(),
                                                align.bytes() as u32);
             }
+            if regular.contains(ArgAttribute::ByVal) {
+                llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap());
+            }
             regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
         }
     }
 
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -90,6 +93,9 @@ impl ArgAttributesExt for ArgAttributes {
                                                        idx.as_uint(),
                                                        align.bytes() as u32);
             }
+            if regular.contains(ArgAttribute::ByVal) {
+                llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap());
+            }
             regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
         }
     }
@@ -298,7 +304,7 @@ pub trait FnTypeLlvmExt<'tcx> {
     fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
-    fn apply_attrs_llfn(&self, llfn: &'ll Value);
+    fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value);
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
 }
 
@@ -384,51 +390,51 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn apply_attrs_llfn(&self, llfn: &'ll Value) {
+    fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes| {
-            attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
+        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
+            attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
             i += 1;
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
+                attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs),
+            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))),
             _ => {}
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new());
+                apply(&ArgAttributes::new(), None);
             }
             match arg.mode {
                 PassMode::Ignore(_) => {}
                 PassMode::Direct(ref attrs) |
-                PassMode::Indirect(ref attrs, None) => apply(attrs),
+                PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))),
                 PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs);
-                    apply(extra_attrs);
+                    apply(attrs, None);
+                    apply(extra_attrs, None);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a);
-                    apply(b);
+                    apply(a, None);
+                    apply(b, None);
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new()),
+                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
     }
 
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes| {
-            attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
+        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
+            attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
             i += 1;
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite);
+                attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs),
+            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
             _ => {}
         }
         if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
@@ -446,21 +452,21 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new());
+                apply(&ArgAttributes::new(), None);
             }
             match arg.mode {
                 PassMode::Ignore(_) => {}
                 PassMode::Direct(ref attrs) |
-                PassMode::Indirect(ref attrs, None) => apply(attrs),
+                PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))),
                 PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs);
-                    apply(extra_attrs);
+                    apply(attrs, None);
+                    apply(extra_attrs, None);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a);
-                    apply(b);
+                    apply(a, None);
+                    apply(b, None);
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new()),
+                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
 
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 94abf1796d3..33b50401b22 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -119,6 +119,29 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
         const_cstr!("probe-stack"), const_cstr!("__rust_probestack"));
 }
 
+fn translate_obsolete_target_features(feature: &str) -> &str {
+    const LLVM9_FEATURE_CHANGES: &[(&str, &str)] = &[
+        ("+fp-only-sp", "-fp64"),
+        ("-fp-only-sp", "+fp64"),
+        ("+d16", "-d32"),
+        ("-d16", "+d32"),
+    ];
+    if llvm_util::get_major_version() >= 9 {
+        for &(old, new) in LLVM9_FEATURE_CHANGES {
+            if feature == old {
+                return new;
+            }
+        }
+    } else {
+        for &(old, new) in LLVM9_FEATURE_CHANGES {
+            if feature == new {
+                return old;
+            }
+        }
+    }
+    feature
+}
+
 pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
     const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
         "crt-static",
@@ -129,6 +152,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
     sess.target.target.options.features.split(',')
         .chain(cmdline)
         .filter(|l| !l.is_empty())
+        .map(translate_obsolete_target_features)
 }
 
 pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 3b2701b893b..e9f25e6344b 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -249,6 +249,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         self.const_uint(self.type_i8(), i as u64)
     }
 
+    fn const_real(&self, t: &'ll Type, val: f64) -> &'ll Value {
+        unsafe { llvm::LLVMConstReal(t, val) }
+    }
+
     fn const_struct(
         &self,
         elts: &[&'ll Value],
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 6a61b180de4..2b68eb53a4a 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -1,5 +1,6 @@
 use crate::attributes;
 use crate::llvm;
+use crate::llvm_util;
 use crate::debuginfo;
 use crate::value::Value;
 use rustc::dep_graph::DepGraphSafe;
@@ -140,6 +141,11 @@ pub fn is_pie_binary(sess: &Session) -> bool {
     !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
 }
 
+fn strip_function_ptr_alignment(data_layout: String) -> String {
+    // FIXME: Make this more general.
+    data_layout.replace("-Fi8-", "-")
+}
+
 pub unsafe fn create_module(
     tcx: TyCtxt<'_>,
     llcx: &'ll llvm::Context,
@@ -149,14 +155,19 @@ pub unsafe fn create_module(
     let mod_name = SmallCStr::new(mod_name);
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
+    let mut target_data_layout = sess.target.target.data_layout.clone();
+    if llvm_util::get_major_version() < 9 {
+        target_data_layout = strip_function_ptr_alignment(target_data_layout);
+    }
+
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
         let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
         llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
         llvm::LLVMRustDisposeTargetMachine(tm);
 
-        let data_layout = llvm::LLVMGetDataLayout(llmod);
-        let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
+        let llvm_data_layout = llvm::LLVMGetDataLayout(llmod);
+        let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
             .ok().expect("got a non-UTF8 data-layout from LLVM");
 
         // Unfortunately LLVM target specs change over time, and right now we
@@ -177,16 +188,16 @@ pub unsafe fn create_module(
         let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
         let custom_llvm_used = cfg_llvm_root.trim() != "";
 
-        if !custom_llvm_used && sess.target.target.data_layout != data_layout {
+        if !custom_llvm_used && target_data_layout != llvm_data_layout {
             bug!("data-layout for builtin `{}` target, `{}`, \
                   differs from LLVM default, `{}`",
                  sess.target.target.llvm_target,
-                 sess.target.target.data_layout,
-                 data_layout);
+                 target_data_layout,
+                 llvm_data_layout);
         }
     }
 
-    let data_layout = SmallCStr::new(&sess.target.target.data_layout);
+    let data_layout = SmallCStr::new(&target_data_layout);
     llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
 
     let llvm_target = SmallCStr::new(&sess.target.target.llvm_target);
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index bcb14b8899e..62eab0f3d4e 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -107,7 +107,7 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
         }
 
-        fty.apply_attrs_llfn(llfn);
+        fty.apply_attrs_llfn(self, llfn);
 
         llfn
     }
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 69f8356f669..dd6cfd7e29e 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1663,9 +1663,10 @@ fn generic_simd_intrinsic(
                             acc
                         } else {
                             // unordered arithmetic reductions do not:
+                            let identity_acc = if $name.contains("mul") { 1.0 } else { 0.0 };
                             match f.bit_width() {
-                                32 => bx.const_undef(bx.type_f32()),
-                                64 => bx.const_undef(bx.type_f64()),
+                                32 => bx.const_real(bx.type_f32(), identity_acc),
+                                64 => bx.const_real(bx.type_f64(), identity_acc),
                                 v => {
                                     return_error!(r#"
 unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 708ba79ec3a..2b22925f449 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -715,6 +715,7 @@ extern "C" {
     // Operations on scalar constants
     pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
     pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value;
+    pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
     pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong;
     pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool,
                                   high: &mut u64, low: &mut u64) -> bool;
@@ -794,6 +795,7 @@ extern "C" {
     pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
     pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
     pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddByValAttr(Fn: &Value, index: c_uint, ty: &Type);
     pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
     pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
                                               index: c_uint,
@@ -824,6 +826,7 @@ extern "C" {
     pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
                                                         index: c_uint,
                                                         bytes: u64);
+    pub fn LLVMRustAddByValCallSiteAttr(Instr: &Value, index: c_uint, ty: &Type);
 
     // Operations on load/store instructions (only)
     pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs
index 46286b5329e..248fadfaf0f 100644
--- a/src/librustc_codegen_ssa/traits/consts.rs
+++ b/src/librustc_codegen_ssa/traits/consts.rs
@@ -17,6 +17,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     fn const_u64(&self, i: u64) -> Self::Value;
     fn const_usize(&self, i: u64) -> Self::Value;
     fn const_u8(&self, i: u8) -> Self::Value;
+    fn const_real(&self, t: Self::Type, val: f64) -> Self::Value;
 
     fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;
 
diff --git a/src/librustc_target/spec/arm_linux_androideabi.rs b/src/librustc_target/spec/arm_linux_androideabi.rs
index bb066dc9ad8..c02edabd886 100644
--- a/src/librustc_target/spec/arm_linux_androideabi.rs
+++ b/src/librustc_target/spec/arm_linux_androideabi.rs
@@ -11,7 +11,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
index 2f835420148..1d5751c1f71 100644
--- a/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
index cd4b2e1c922..8eb19a6518a 100644
--- a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_musleabi.rs b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
index 606c3f19060..5c40b6fb89f 100644
--- a/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
index d22156bc328..496a0c4a43a 100644
--- a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/armebv7r_none_eabi.rs b/src/librustc_target/spec/armebv7r_none_eabi.rs
index 86c62daa618..0b41b920e58 100644
--- a/src/librustc_target/spec/armebv7r_none_eabi.rs
+++ b/src/librustc_target/spec/armebv7r_none_eabi.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: "".to_string(),
diff --git a/src/librustc_target/spec/armebv7r_none_eabihf.rs b/src/librustc_target/spec/armebv7r_none_eabihf.rs
index 50ee76414ef..5f1bfdce355 100644
--- a/src/librustc_target/spec/armebv7r_none_eabihf.rs
+++ b/src/librustc_target/spec/armebv7r_none_eabihf.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
             linker: Some("rust-lld".to_owned()),
             relocation_model: "static".to_string(),
             panic_strategy: PanicStrategy::Abort,
-            features: "+vfp3,+d16,+fp-only-sp".to_string(),
+            features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
             emit_debug_gdb_scripts: false,
diff --git a/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
index e7da24843cc..264bf8d871d 100644
--- a/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
index ea586f42c26..d0f1222d87a 100644
--- a/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
index dae5c8c3d75..9c08a7741a6 100644
--- a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
+++ b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
@@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/armv6_unknown_freebsd.rs b/src/librustc_target/spec/armv6_unknown_freebsd.rs
index a90590a39e7..efbbee959ed 100644
--- a/src/librustc_target/spec/armv6_unknown_freebsd.rs
+++ b/src/librustc_target/spec/armv6_unknown_freebsd.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "freebsd".to_string(),
         target_env: "gnueabihf".to_string(),
diff --git a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
index b056776bdfb..b76c39ac75b 100644
--- a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
+++ b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "netbsd".to_string(),
         target_env: "eabihf".to_string(),
diff --git a/src/librustc_target/spec/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs
index 2052d17403d..c1e1caf8e2e 100644
--- a/src/librustc_target/spec/armv7_apple_ios.rs
+++ b/src/librustc_target/spec/armv7_apple_ios.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
+        data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/armv7_linux_androideabi.rs b/src/librustc_target/spec/armv7_linux_androideabi.rs
index 92f1a55e024..e22a853814a 100644
--- a/src/librustc_target/spec/armv7_linux_androideabi.rs
+++ b/src/librustc_target/spec/armv7_linux_androideabi.rs
@@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
-    base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+d16,-neon".to_string();
+    base.features = "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args
         .get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string());
@@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
index c03f4b544ed..7065d30a5be 100644
--- a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
@@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "cloudabi".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/armv7_unknown_freebsd.rs b/src/librustc_target/spec/armv7_unknown_freebsd.rs
index ca7ab474bef..219b06362f3 100644
--- a/src/librustc_target/spec/armv7_unknown_freebsd.rs
+++ b/src/librustc_target/spec/armv7_unknown_freebsd.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "freebsd".to_string(),
         target_env: "gnueabihf".to_string(),
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
             target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
diff --git a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
index f0952cccb20..1dd53b1b422 100644
--- a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
@@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
@@ -19,7 +19,7 @@ pub fn target() -> TargetResult {
 
         options: TargetOptions {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
index a9974f6b80c..ee8e48e3e75 100644
--- a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
@@ -12,7 +12,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
@@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
         // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs b/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
index e2d55e9317b..1d63b0261c1 100644
--- a/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "netbsd".to_string(),
         target_env: "eabihf".to_string(),
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armv7r_none_eabi.rs b/src/librustc_target/spec/armv7r_none_eabi.rs
index 19d332467de..814ca1d77ac 100644
--- a/src/librustc_target/spec/armv7r_none_eabi.rs
+++ b/src/librustc_target/spec/armv7r_none_eabi.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: "".to_string(),
diff --git a/src/librustc_target/spec/armv7r_none_eabihf.rs b/src/librustc_target/spec/armv7r_none_eabihf.rs
index 06ef9f3ec4e..decf1a01e0b 100644
--- a/src/librustc_target/spec/armv7r_none_eabihf.rs
+++ b/src/librustc_target/spec/armv7r_none_eabihf.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: "".to_string(),
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
             linker: Some("rust-lld".to_owned()),
             relocation_model: "static".to_string(),
             panic_strategy: PanicStrategy::Abort,
-            features: "+vfp3,+d16,+fp-only-sp".to_string(),
+            features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
             emit_debug_gdb_scripts: false,
diff --git a/src/librustc_target/spec/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs
index 29e290285e4..55e2a876865 100644
--- a/src/librustc_target/spec/armv7s_apple_ios.rs
+++ b/src/librustc_target/spec/armv7s_apple_ios.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
+        data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv6m_none_eabi.rs b/src/librustc_target/spec/thumbv6m_none_eabi.rs
index 2ab61b57f6b..28353552fc7 100644
--- a/src/librustc_target/spec/thumbv6m_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv6m_none_eabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs b/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs
index 310fac31c0c..886e3188272 100644
--- a/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs
@@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:w-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/thumbv7em_none_eabi.rs b/src/librustc_target/spec/thumbv7em_none_eabi.rs
index 97114c342cd..4e2f9b91b0d 100644
--- a/src/librustc_target/spec/thumbv7em_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv7em_none_eabi.rs
@@ -17,7 +17,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv7em_none_eabihf.rs b/src/librustc_target/spec/thumbv7em_none_eabihf.rs
index e4358bdd799..c510be519c0 100644
--- a/src/librustc_target/spec/thumbv7em_none_eabihf.rs
+++ b/src/librustc_target/spec/thumbv7em_none_eabihf.rs
@@ -6,7 +6,7 @@
 // Additionally, this target uses the "hard" floating convention (ABI) where floating point values
 // are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
 //
-// To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.
+// To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
 
 use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};
 
@@ -16,7 +16,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
@@ -26,14 +26,14 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
             // Cortex-M7 (vfp5)
-            // `+d16` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
+            // `-d32` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
             // available
-            // `+fp-only-sp` The Cortex-M4 only supports single precision floating point operations
+            // `-fp64` The Cortex-M4 only supports single precision floating point operations
             // whereas in the Cortex-M7 double precision is optional
             //
             // Reference:
             // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension
-            features: "+vfp4,+d16,+fp-only-sp".to_string(),
+            features: "+vfp4,-d32,-fp64".to_string(),
             max_atomic_width: Some(32),
             .. super::thumb_base::opts()
         }
diff --git a/src/librustc_target/spec/thumbv7m_none_eabi.rs b/src/librustc_target/spec/thumbv7m_none_eabi.rs
index daf25b16d58..9c9868ef37c 100644
--- a/src/librustc_target/spec/thumbv7m_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv7m_none_eabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs b/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs
index e248b930e6e..f3142ef6002 100644
--- a/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs
+++ b/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs
@@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         target_env: "".to_string(),
diff --git a/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs
index bef62b0a2eb..5524bc9ab66 100644
--- a/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/thumbv8m_base_none_eabi.rs b/src/librustc_target/spec/thumbv8m_base_none_eabi.rs
index be8a476db4d..0b4750093cc 100644
--- a/src/librustc_target/spec/thumbv8m_base_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv8m_base_none_eabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv8m_main_none_eabi.rs b/src/librustc_target/spec/thumbv8m_main_none_eabi.rs
index 49ab643d484..acce424136d 100644
--- a/src/librustc_target/spec/thumbv8m_main_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv8m_main_none_eabi.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs b/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs
index 6a3d8e61d7f..455d56b095b 100644
--- a/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs
+++ b/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
@@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
             // the FPU uses the FPv5 architecture, single-precision instructions
             // and 16 D registers.
             // These parameters map to the following LLVM features.
-            features: "+fp-armv8,+fp-only-sp,+d16".to_string(),
+            features: "+fp-armv8,-fp64,-d32".to_string(),
             max_atomic_width: Some(32),
             .. super::thumb_base::opts()
         },
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 0ebef82d376..cea88f14dcc 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -913,7 +913,10 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
                               GlobalValue::LinkageTypes NewLinkage) {
     ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
   };
-#if LLVM_VERSION_GE(8, 0)
+#if LLVM_VERSION_GE(9, 0)
+  thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
+                                  Ret->GUIDPreservedSymbols);
+#elif LLVM_VERSION_GE(8, 0)
   thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage);
 #else
   thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage);
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 66453c08a66..16d08ee534e 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -237,6 +237,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
       Call->getContext(), Index, B));
 }
 
+extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
+                                             LLVMTypeRef Ty) {
+  CallSite Call = CallSite(unwrap<Instruction>(Instr));
+#if LLVM_VERSION_GE(9, 0)
+  Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
+#else
+  Attribute Attr = Attribute::get(Call->getContext(), Attribute::ByVal);
+#endif
+  Call.addAttribute(Index, Attr);
+}
+
 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   Function *A = unwrap<Function>(Fn);
@@ -271,6 +282,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
   A->addAttributes(Index, B);
 }
 
+extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
+                                     LLVMTypeRef Ty) {
+  Function *F = unwrap<Function>(Fn);
+#if LLVM_VERSION_GE(9, 0)
+  Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
+#else
+  Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal);
+#endif
+  F->addAttribute(Index, Attr);
+}
+
 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
                                                    unsigned Index,
                                                    const char *Name,
diff --git a/src/test/codegen/mainsubprogram.rs b/src/test/codegen/mainsubprogram.rs
index 7f1b0e17f87..790db33437b 100644
--- a/src/test/codegen/mainsubprogram.rs
+++ b/src/test/codegen/mainsubprogram.rs
@@ -7,7 +7,7 @@
 // compile-flags: -g -C no-prepopulate-passes
 
 // CHECK-LABEL: @main
-// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DIFlagMainSubprogram{{.*}}
+// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
 
 pub fn main() {
 }
diff --git a/src/test/codegen/mainsubprogramstart.rs b/src/test/codegen/mainsubprogramstart.rs
index b03290af0e3..d4de9f59ac2 100644
--- a/src/test/codegen/mainsubprogramstart.rs
+++ b/src/test/codegen/mainsubprogramstart.rs
@@ -6,7 +6,7 @@
 #![feature(start)]
 
 // CHECK-LABEL: @main
-// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DIFlagMainSubprogram{{.*}}
+// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
 
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {