about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-01-23 00:04:33 +0000
committerbors <bors@rust-lang.org>2020-01-23 00:04:33 +0000
commite23dd6687f7677a715765bff1fe5e63b906cb96b (patch)
tree7bbb599260f76a958a7365f8e535bd418020253c
parentd1e594f4029c6ac8feb7c2acf9f9e04c1b9c493c (diff)
parentbfac73c0a6786644d0a58a12347839d442be26ac (diff)
Auto merge of #68474 - tmandry:rollup-6gmbet6, r=tmandry
Rollup of 10 pull requests

Successful merges:

 - #67195 ([experiment] Add `-Z no-link` flag)
 - #68253 (add bare metal ARM Cortex-A targets to rustc)
 - #68361 (Unbreak linking with lld 9 on FreeBSD 13.0-CURRENT i386)
 - #68388 (Make `TooGeneric` error in WF checking a proper error)
 - #68409 (Micro-optimize OutputFilenames)
 - #68410 (Export weak symbols used by MemorySanitizer)
 - #68425 (Fix try-op diagnostic in E0277 for methods)
 - #68440 (bootstrap: update clippy subcmd decription)
 - #68441 (pprust: use as_deref)
 - #68462 (librustc_mir: don't allocate vectors where slices will do.)

Failed merges:

r? @ghost
-rw-r--r--Cargo.lock1
-rw-r--r--src/bootstrap/flags.rs2
-rw-r--r--src/ci/docker/dist-various-1/Dockerfile5
-rw-r--r--src/librustc/middle/cstore.rs5
-rw-r--r--src/librustc/middle/dependency_format.rs2
-rw-r--r--src/librustc/traits/error_reporting/mod.rs34
-rw-r--r--src/librustc/traits/error_reporting/on_unimplemented.rs54
-rw-r--r--src/librustc_codegen_llvm/Cargo.toml1
-rw-r--r--src/librustc_codegen_llvm/lib.rs14
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs1
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs12
-rw-r--r--src/librustc_codegen_ssa/lib.rs14
-rw-r--r--src/librustc_hir/def_id.rs34
-rw-r--r--src/librustc_interface/util.rs33
-rw-r--r--src/librustc_mir/transform/generator.rs4
-rw-r--r--src/librustc_mir/transform/instcombine.rs2
-rw-r--r--src/librustc_session/config.rs33
-rw-r--r--src/librustc_session/options.rs2
-rw-r--r--src/librustc_session/search_paths.rs2
-rw-r--r--src/librustc_target/spec/armv7a_none_eabi.rs48
-rw-r--r--src/librustc_target/spec/armv7a_none_eabihf.rs36
-rw-r--r--src/librustc_target/spec/i686_unknown_freebsd.rs4
-rw-r--r--src/librustc_target/spec/mod.rs3
-rw-r--r--src/libsyntax/print/pprust.rs4
-rw-r--r--src/test/codegen/sanitizer-memory-track-orgins.rs6
-rw-r--r--src/test/codegen/sanitizer-recover.rs56
-rw-r--r--src/test/ui/const-generics/array-size-in-generic-struct-param.rs7
-rw-r--r--src/test/ui/const-generics/array-size-in-generic-struct-param.stderr20
-rw-r--r--src/test/ui/try-on-option-diagnostics.rs29
-rw-r--r--src/test/ui/try-on-option-diagnostics.stderr28
-rw-r--r--src/tools/build-manifest/src/main.rs1
31 files changed, 388 insertions, 109 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0a76aabc3a3..237b3dda670 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3428,6 +3428,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "serialize",
  "smallvec 1.0.0",
  "syntax",
 ]
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 1fbdd50a511..2101ef27f9d 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -104,7 +104,7 @@ Usage: x.py <subcommand> [options] [<paths>...]
 Subcommands:
     build       Compile either the compiler or libraries
     check       Compile either the compiler or libraries, using cargo check
-    clippy      Run clippy
+    clippy      Run clippy (uses rustup/cargo-installed clippy binary)
     fix         Run cargo fix
     fmt         Run rustfmt
     test        Build and run some test suites
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index 546e73e33d7..2a68a25be21 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -160,6 +160,7 @@ ENV TARGETS=$TARGETS,armebv7r-none-eabihf
 ENV TARGETS=$TARGETS,armv7r-none-eabi
 ENV TARGETS=$TARGETS,armv7r-none-eabihf
 ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf
+ENV TARGETS=$TARGETS,armv7a-none-eabi
 
 # riscv targets currently do not need a C compiler, as compiler_builtins
 # doesn't currently have it enabled, and the riscv gcc compiler is not
@@ -173,6 +174,10 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \
     AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \
     CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ \
+    CC_armv7a_none_eabi=arm-none-eabi-gcc \
+    CC_armv7a_none_eabihf=arm-none-eabi-gcc \
+    CFLAGS_armv7a_none_eabi=-march=armv7-a \
+    CFLAGS_armv7a_none_eabihf=-march=armv7-a+vfpv3 \
     CC_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-gcc \
     AR_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-ar \
     CXX_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-g++ \
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 5b1e7673629..0e7ff3a3393 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -27,7 +27,7 @@ pub use rustc_session::utils::NativeLibraryKind;
 
 /// Where a crate came from on the local filesystem. One of these three options
 /// must be non-None.
-#[derive(PartialEq, Clone, Debug, HashStable)]
+#[derive(PartialEq, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
 pub struct CrateSource {
     pub dylib: Option<(PathBuf, PathKind)>,
     pub rlib: Option<(PathBuf, PathKind)>,
@@ -75,7 +75,7 @@ impl DepKind {
     }
 }
 
-#[derive(PartialEq, Clone, Debug)]
+#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum LibSource {
     Some(PathBuf),
     MetadataOnly,
@@ -160,6 +160,7 @@ pub enum ExternCrateSource {
     Path,
 }
 
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct EncodedMetadata {
     pub raw_data: Vec<u8>,
 }
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 8b2bf55ccc1..6ece51fe866 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -19,7 +19,7 @@ pub type DependencyList = Vec<Linkage>;
 /// This is local to the tcx, and is generally relevant to one session.
 pub type Dependencies = Vec<(config::CrateType, DependencyList)>;
 
-#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, RustcEncodable, RustcDecodable)]
 pub enum Linkage {
     NotLinked,
     IncludedFromDylib,
diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs
index d1c369d0abb..cdb50779e00 100644
--- a/src/librustc/traits/error_reporting/mod.rs
+++ b/src/librustc/traits/error_reporting/mod.rs
@@ -919,17 +919,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 report_object_safety_error(self.tcx, span, did, violations)
             }
 
-            // already reported in the query
-            ConstEvalFailure(err) => {
-                if let ErrorHandled::TooGeneric = err {
-                    // Silence this error, as it can be produced during intermediate steps
-                    // when a constant is not yet able to be evaluated (but will be later).
-                    return;
-                }
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    &format!("constant in type had an ignored error: {:?}", err),
-                );
+            ConstEvalFailure(ErrorHandled::TooGeneric) => {
+                // In this instance, we have a const expression containing an unevaluated
+                // generic parameter. We have no idea whether this expression is valid or
+                // not (e.g. it might result in an error), but we don't want to just assume
+                // that it's okay, because that might result in post-monomorphisation time
+                // errors. The onus is really on the caller to provide values that it can
+                // prove are well-formed.
+                let mut err = self
+                    .tcx
+                    .sess
+                    .struct_span_err(span, "constant expression depends on a generic parameter");
+                // FIXME(const_generics): we should suggest to the user how they can resolve this
+                // issue. However, this is currently not actually possible
+                // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
+                err.note("this may fail depending on what value the parameter takes");
+                err
+            }
+
+            // Already reported in the query.
+            ConstEvalFailure(ErrorHandled::Reported) => {
+                self.tcx
+                    .sess
+                    .delay_span_bug(span, &format!("constant in type had an ignored error"));
                 return;
             }
 
diff --git a/src/librustc/traits/error_reporting/on_unimplemented.rs b/src/librustc/traits/error_reporting/on_unimplemented.rs
index 9f3fc91548b..2ba12baaf6d 100644
--- a/src/librustc/traits/error_reporting/on_unimplemented.rs
+++ b/src/librustc/traits/error_reporting/on_unimplemented.rs
@@ -59,31 +59,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
         let hir = &self.tcx.hir();
         let node = hir.find(hir_id)?;
-        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
-            self.describe_generator(*body_id).or_else(|| {
+        match &node {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
+                self.describe_generator(*body_id).or_else(|| {
+                    Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
+                        "an async function"
+                    } else {
+                        "a function"
+                    })
+                })
+            }
+            hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
+            hir::Node::ImplItem(hir::ImplItem {
+                kind: hir::ImplItemKind::Method(sig, body_id),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| {
                 Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                    "an async function"
+                    "an async method"
                 } else {
-                    "a function"
+                    "a method"
                 })
-            })
-        } else if let hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
-            ..
-        }) = &node
-        {
-            self.describe_generator(*body_id).or_else(|| {
+            }),
+            hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| {
                 Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
-            })
-        } else if let hir::Node::Expr(hir::Expr { .. }) = &node {
-            let parent_hid = hir.get_parent_node(hir_id);
-            if parent_hid != hir_id {
-                return self.describe_enclosure(parent_hid);
-            } else {
-                None
+            }),
+            hir::Node::Expr(hir::Expr { .. }) => {
+                let parent_hid = hir.get_parent_node(hir_id);
+                if parent_hid != hir_id {
+                    return self.describe_enclosure(parent_hid);
+                } else {
+                    None
+                }
             }
-        } else {
-            None
+            _ => None,
         }
     }
 
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index 3ff5495e291..dd9eadde098 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -28,6 +28,7 @@ rustc_incremental = { path = "../librustc_incremental" }
 rustc_index = { path = "../librustc_index" }
 rustc_llvm = { path = "../librustc_llvm" }
 rustc_session = { path = "../librustc_session" }
+rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index a6168128c4d..70e3874035b 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -33,6 +33,7 @@ use rustc_codegen_ssa::CompiledModule;
 use rustc_errors::{FatalError, Handler};
 use std::any::Any;
 use std::ffi::CStr;
+use std::fs;
 use std::sync::Arc;
 use syntax::expand::allocator::AllocatorKind;
 
@@ -44,6 +45,7 @@ use rustc::ty::{self, TyCtxt};
 use rustc::util::common::ErrorReported;
 use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_serialize::json;
 
 mod back {
     pub mod archive;
@@ -298,6 +300,18 @@ impl CodegenBackend for LlvmCodegenBackend {
             return Ok(());
         }
 
+        if sess.opts.debugging_opts.no_link {
+            // FIXME: use a binary format to encode the `.rlink` file
+            let rlink_data = json::encode(&codegen_results).map_err(|err| {
+                sess.fatal(&format!("failed to encode rlink: {}", err));
+            })?;
+            let rlink_file = outputs.with_extension("rlink");
+            fs::write(&rlink_file, rlink_data).map_err(|err| {
+                sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err));
+            })?;
+            return Ok(());
+        }
+
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
         sess.time("link_crate", || {
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 4679f650133..695f171dfb4 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -20,6 +20,7 @@ use rustc_target::spec::{LinkerFlavor, LldFlavor};
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct LinkerInfo {
     exports: FxHashMap<CrateType, Vec<String>>,
 }
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index bd44b4a38fd..d680e14bbbd 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
-use rustc::session::config;
+use rustc::session::config::{self, Sanitizer};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::Instance;
@@ -206,6 +206,16 @@ fn exported_symbols_provider_local(
         }));
     }
 
+    if let Some(Sanitizer::Memory) = tcx.sess.opts.debugging_opts.sanitizer {
+        // Similar to profiling, preserve weak msan symbol during LTO.
+        const MSAN_WEAK_SYMBOLS: [&str; 2] = ["__msan_track_origins", "__msan_keep_going"];
+
+        symbols.extend(MSAN_WEAK_SYMBOLS.iter().map(|sym| {
+            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(sym));
+            (exported_symbol, SymbolExportLevel::C)
+        }));
+    }
+
     if tcx.sess.crate_types.borrow().contains(&config::CrateType::Dylib) {
         let symbol_name = metadata_symbol_name(tcx);
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index aba77231268..b69def5428c 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -87,7 +87,7 @@ impl<M> ModuleCodegen<M> {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct CompiledModule {
     pub name: String,
     pub kind: ModuleKind,
@@ -101,7 +101,7 @@ pub struct CachedModuleCodegen {
     pub source: WorkProduct,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum ModuleKind {
     Regular,
     Metadata,
@@ -117,7 +117,14 @@ bitflags::bitflags! {
 }
 
 /// Misc info we load from metadata to persist beyond the tcx.
-#[derive(Debug)]
+///
+/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
+/// is self-contained. `CrateNum` can be viewed as a unique identifier within a `CrateInfo`, where
+/// `used_crate_source` contains all `CrateSource` of the dependents, and maintains a mapping from
+/// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own
+/// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource`
+/// and the corresponding properties without referencing information outside of a `CrateInfo`.
+#[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct CrateInfo {
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
@@ -135,6 +142,7 @@ pub struct CrateInfo {
     pub dependency_formats: Lrc<Dependencies>,
 }
 
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct CodegenResults {
     pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
diff --git a/src/librustc_hir/def_id.rs b/src/librustc_hir/def_id.rs
index f8cacdc6238..7ee778ddd8e 100644
--- a/src/librustc_hir/def_id.rs
+++ b/src/librustc_hir/def_id.rs
@@ -1,7 +1,8 @@
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
+use rustc_serialize::{Decoder, Encoder};
 use std::fmt;
-use std::u32;
+use std::{u32, u64};
 
 rustc_index::newtype_index! {
     pub struct CrateId {
@@ -86,8 +87,18 @@ impl fmt::Display for CrateNum {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for CrateNum {}
-impl rustc_serialize::UseSpecializedDecodable for CrateNum {}
+/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
+/// Therefore, make sure to include the context when encode a `CrateNum`.
+impl rustc_serialize::UseSpecializedEncodable for CrateNum {
+    fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+        e.emit_u32(self.as_u32())
+    }
+}
+impl rustc_serialize::UseSpecializedDecodable for CrateNum {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
+        Ok(CrateNum::from_u32(d.read_u32()?))
+    }
+}
 
 rustc_index::newtype_index! {
     /// A DefIndex is an index into the hir-map for a crate, identifying a
@@ -135,8 +146,21 @@ impl DefId {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for DefId {}
-impl rustc_serialize::UseSpecializedDecodable for DefId {}
+impl rustc_serialize::UseSpecializedEncodable for DefId {
+    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        let krate = u64::from(self.krate.as_u32());
+        let index = u64::from(self.index.as_u32());
+        s.emit_u64((krate << 32) | index)
+    }
+}
+impl rustc_serialize::UseSpecializedDecodable for DefId {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
+        let def_id = d.read_u64()?;
+        let krate = CrateNum::from_u32((def_id >> 32) as u32);
+        let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
+        Ok(DefId { krate, index })
+    }
+}
 
 pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 21f9fa48165..3e65da9c47b 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -550,13 +550,13 @@ pub fn build_output_filenames(
                 .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
                 .unwrap_or_else(|| input.filestem().to_owned());
 
-            OutputFilenames {
-                out_directory: dirpath,
-                out_filestem: stem,
-                single_output_file: None,
-                extra: sess.opts.cg.extra_filename.clone(),
-                outputs: sess.opts.output_types.clone(),
-            }
+            OutputFilenames::new(
+                dirpath,
+                stem,
+                None,
+                sess.opts.cg.extra_filename.clone(),
+                sess.opts.output_types.clone(),
+            )
         }
 
         Some(ref out_file) => {
@@ -578,18 +578,13 @@ pub fn build_output_filenames(
                 sess.warn("ignoring --out-dir flag due to -o flag");
             }
 
-            OutputFilenames {
-                out_directory: out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
-                out_filestem: out_file
-                    .file_stem()
-                    .unwrap_or_default()
-                    .to_str()
-                    .unwrap()
-                    .to_string(),
-                single_output_file: ofile,
-                extra: sess.opts.cg.extra_filename.clone(),
-                outputs: sess.opts.output_types.clone(),
-            }
+            OutputFilenames::new(
+                out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
+                out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(),
+                ofile,
+                sess.opts.cg.extra_filename.clone(),
+                sess.opts.output_types.clone(),
+            )
         }
     }
 }
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 825ac4a28d8..8ac7772ea48 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -117,7 +117,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
                 place,
                 Place {
                     local: self_arg(),
-                    projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]),
+                    projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]),
                 },
                 self.tcx,
             );
@@ -153,7 +153,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
                 place,
                 Place {
                     local: self_arg(),
-                    projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Field(
+                    projection: self.tcx().intern_place_elems(&[ProjectionElem::Field(
                         Field::new(0),
                         self.ref_gen_ty,
                     )]),
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 69eedb1ae18..afe42e63571 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -51,7 +51,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
             let new_place = match rvalue {
                 Rvalue::Ref(_, _, place) => {
                     if let &[ref proj_l @ .., proj_r] = place.projection.as_ref() {
-                        place.projection = self.tcx().intern_place_elems(&vec![proj_r.clone()]);
+                        place.projection = self.tcx().intern_place_elems(&[proj_r.clone()]);
 
                         Place {
                             // Replace with dummy
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index b6b22e298ca..aa492b566e5 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -447,9 +447,8 @@ impl Input {
 #[derive(Clone, Hash)]
 pub struct OutputFilenames {
     pub out_directory: PathBuf,
-    pub out_filestem: String,
+    filestem: String,
     pub single_output_file: Option<PathBuf>,
-    pub extra: String,
     pub outputs: OutputTypes,
 }
 
@@ -458,6 +457,21 @@ impl_stable_hash_via_hash!(OutputFilenames);
 pub const RUST_CGU_EXT: &str = "rcgu";
 
 impl OutputFilenames {
+    pub fn new(
+        out_directory: PathBuf,
+        out_filestem: String,
+        single_output_file: Option<PathBuf>,
+        extra: String,
+        outputs: OutputTypes,
+    ) -> Self {
+        OutputFilenames {
+            out_directory,
+            single_output_file,
+            outputs,
+            filestem: format!("{}{}", out_filestem, extra),
+        }
+    }
+
     pub fn path(&self, flavor: OutputType) -> PathBuf {
         self.outputs
             .get(&flavor)
@@ -477,8 +491,6 @@ impl OutputFilenames {
     /// Like temp_path, but also supports things where there is no corresponding
     /// OutputType, like noopt-bitcode or lto-bitcode.
     pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf {
-        let base = self.out_directory.join(&self.filestem());
-
         let mut extension = String::new();
 
         if let Some(codegen_unit_name) = codegen_unit_name {
@@ -495,16 +507,13 @@ impl OutputFilenames {
             extension.push_str(ext);
         }
 
-        let path = base.with_extension(&extension[..]);
-        path
+        self.with_extension(&extension)
     }
 
     pub fn with_extension(&self, extension: &str) -> PathBuf {
-        self.out_directory.join(&self.filestem()).with_extension(extension)
-    }
-
-    pub fn filestem(&self) -> String {
-        format!("{}{}", self.out_filestem, self.extra)
+        let mut path = self.out_directory.join(&self.filestem);
+        path.set_extension(extension);
+        path
     }
 }
 
@@ -619,7 +628,7 @@ pub enum EntryFnType {
 
 impl_stable_hash_via_hash!(EntryFnType);
 
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum CrateType {
     Executable,
     Dylib,
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 2a0ed27b63b..34da2188a51 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -950,4 +950,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
          (such as entering an empty infinite loop) by inserting llvm.sideeffect"),
     deduplicate_diagnostics: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
         "deduplicate identical diagnostics"),
+    no_link: bool = (false, parse_bool, [TRACKED],
+        "compile without linking"),
 }
diff --git a/src/librustc_session/search_paths.rs b/src/librustc_session/search_paths.rs
index b15f4e8f6c1..06f408b4a8d 100644
--- a/src/librustc_session/search_paths.rs
+++ b/src/librustc_session/search_paths.rs
@@ -9,7 +9,7 @@ pub struct SearchPath {
     pub files: Vec<PathBuf>,
 }
 
-#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, RustcEncodable, RustcDecodable)]
 pub enum PathKind {
     Native,
     Crate,
diff --git a/src/librustc_target/spec/armv7a_none_eabi.rs b/src/librustc_target/spec/armv7a_none_eabi.rs
new file mode 100644
index 00000000000..2fbef154f81
--- /dev/null
+++ b/src/librustc_target/spec/armv7a_none_eabi.rs
@@ -0,0 +1,48 @@
+// Generic ARMv7-A target for bare-metal code - floating point disabled
+//
+// This is basically the `armv7-unknown-linux-gnueabi` target with some changes
+// (listed below) to bring it closer to the bare-metal `thumb` & `aarch64`
+// targets:
+//
+// - `TargetOptions.features`: added `+strict-align`. rationale: unaligned
+// memory access is disabled on boot on these cores
+// - linker changed to LLD. rationale: C is not strictly needed to build
+// bare-metal binaries (the `gcc` linker has the advantage that it knows where C
+// libraries and crt*.o are but it's not much of an advantage here); LLD is also
+// faster
+// - `target_os` set to `none`. rationale: matches `thumb` targets
+// - `target_{env,vendor}` set to an empty string. rationale: matches `thumb`
+// targets
+// - `panic_strategy` set to `abort`. rationale: matches `thumb` targets
+// - `relocation-model` set to `static`; also no PIE, no relro and no dynamic
+// linking. rationale: matches `thumb` targets
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Result<Target, String> {
+    let opts = TargetOptions {
+        linker: Some("rust-lld".to_owned()),
+        features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(),
+        executables: true,
+        relocation_model: "static".to_string(),
+        disable_redzone: true,
+        max_atomic_width: Some(64),
+        panic_strategy: PanicStrategy::Abort,
+        abi_blacklist: super::arm_base::abi_blacklist(),
+        emit_debug_gdb_scripts: false,
+        ..Default::default()
+    };
+    Ok(Target {
+        llvm_target: "armv7a-none-eabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
+        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(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+        options: opts,
+    })
+}
diff --git a/src/librustc_target/spec/armv7a_none_eabihf.rs b/src/librustc_target/spec/armv7a_none_eabihf.rs
new file mode 100644
index 00000000000..f31e68c5bd1
--- /dev/null
+++ b/src/librustc_target/spec/armv7a_none_eabihf.rs
@@ -0,0 +1,36 @@
+// Generic ARMv7-A target for bare-metal code - floating point enabled (assumes
+// FPU is present and emits FPU instructions)
+//
+// This is basically the `armv7-unknown-linux-gnueabihf` target with some
+// changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal
+// `thumb` & `aarch64` targets.
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Result<Target, String> {
+    let opts = TargetOptions {
+        linker: Some("rust-lld".to_owned()),
+        features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(),
+        executables: true,
+        relocation_model: "static".to_string(),
+        disable_redzone: true,
+        max_atomic_width: Some(64),
+        panic_strategy: PanicStrategy::Abort,
+        abi_blacklist: super::arm_base::abi_blacklist(),
+        emit_debug_gdb_scripts: false,
+        ..Default::default()
+    };
+    Ok(Target {
+        llvm_target: "armv7a-none-eabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
+        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(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+        options: opts,
+    })
+}
diff --git a/src/librustc_target/spec/i686_unknown_freebsd.rs b/src/librustc_target/spec/i686_unknown_freebsd.rs
index 88c944a6cb7..60f2188514e 100644
--- a/src/librustc_target/spec/i686_unknown_freebsd.rs
+++ b/src/librustc_target/spec/i686_unknown_freebsd.rs
@@ -4,7 +4,9 @@ pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
+    let pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap();
+    pre_link_args.push("-m32".to_string());
+    pre_link_args.push("-Wl,-znotext".to_string());
     base.stack_probes = true;
 
     Ok(Target {
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 528ffdf93a0..67f45d3d230 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -472,6 +472,9 @@ supported_targets! {
     ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
     ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
 
+    ("armv7a-none-eabi", armv7a_none_eabi),
+    ("armv7a-none-eabihf", armv7a_none_eabihf),
+
     ("msp430-none-elf", msp430_none_elf),
 
     ("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi),
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 3927e4f9030..f0ef33e2f62 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1645,7 +1645,7 @@ impl<'a> State<'a> {
                     self.print_expr_as_cond(i);
                     self.s.space();
                     self.print_block(then);
-                    self.print_else(e.as_ref().map(|e| &**e))
+                    self.print_else(e.as_deref())
                 }
                 // Final `else` block.
                 ast::ExprKind::Block(ref b, _) => {
@@ -1949,7 +1949,7 @@ impl<'a> State<'a> {
                 self.print_let(pat, scrutinee);
             }
             ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
-                self.print_if(test, blk, elseopt.as_ref().map(|e| &**e));
+                self.print_if(test, blk, elseopt.as_deref())
             }
             ast::ExprKind::While(ref test, ref blk, opt_label) => {
                 if let Some(label) = opt_label {
diff --git a/src/test/codegen/sanitizer-memory-track-orgins.rs b/src/test/codegen/sanitizer-memory-track-orgins.rs
index fd8be0bced7..1fd496b35df 100644
--- a/src/test/codegen/sanitizer-memory-track-orgins.rs
+++ b/src/test/codegen/sanitizer-memory-track-orgins.rs
@@ -4,17 +4,21 @@
 // needs-sanitizer-support
 // only-linux
 // only-x86_64
-// revisions:MSAN-0 MSAN-1 MSAN-2
+// revisions:MSAN-0 MSAN-1 MSAN-2 MSAN-1-LTO MSAN-2-LTO
 //
 //[MSAN-0] compile-flags: -Zsanitizer=memory
 //[MSAN-1] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1
 //[MSAN-2] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins
+//[MSAN-1-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1 -C lto=fat
+//[MSAN-2-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins -C lto=fat
 
 #![crate_type="lib"]
 
 // MSAN-0-NOT: @__msan_track_origins
 // MSAN-1:     @__msan_track_origins = weak_odr local_unnamed_addr constant i32 1
 // MSAN-2:     @__msan_track_origins = weak_odr local_unnamed_addr constant i32 2
+// MSAN-1-LTO: @__msan_track_origins = weak_odr local_unnamed_addr constant i32 1
+// MSAN-2-LTO: @__msan_track_origins = weak_odr local_unnamed_addr constant i32 2
 //
 // MSAN-0-LABEL: define void @copy(
 // MSAN-1-LABEL: define void @copy(
diff --git a/src/test/codegen/sanitizer-recover.rs b/src/test/codegen/sanitizer-recover.rs
index a292332667b..9a583725b0b 100644
--- a/src/test/codegen/sanitizer-recover.rs
+++ b/src/test/codegen/sanitizer-recover.rs
@@ -4,31 +4,47 @@
 // needs-sanitizer-support
 // only-linux
 // only-x86_64
-// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER
+// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO
+// no-prefer-dynamic
 //
-//[ASAN]         compile-flags: -Zsanitizer=address
-//[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address
-//[MSAN]         compile-flags: -Zsanitizer=memory
-//[MSAN-RECOVER] compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory
-
-#![crate_type="lib"]
+//[ASAN]             compile-flags: -Zsanitizer=address
+//[ASAN-RECOVER]     compile-flags: -Zsanitizer=address -Zsanitizer-recover=address
+//[MSAN]             compile-flags: -Zsanitizer=memory
+//[MSAN-RECOVER]     compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory
+//[MSAN-RECOVER-LTO] compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory -C lto=fat
+//
+// MSAN-NOT:         @__msan_keep_going
+// MSAN-RECOVER:     @__msan_keep_going = weak_odr {{.*}} constant i32 1
+// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}} constant i32 1
 
-// ASAN-LABEL:         define i32 @penguin(
+// ASAN-LABEL: define i32 @penguin(
+// ASAN:         call void @__asan_report_load4(i64 %0)
+// ASAN:         unreachable
+// ASAN:       }
+//
 // ASAN-RECOVER-LABEL: define i32 @penguin(
-// MSAN-LABEL:         define i32 @penguin(
+// ASAN-RECOVER:         call void @__asan_report_load4_noabort(
+// ASAN-RECOVER-NOT:     unreachable
+// ASAN:               }
+//
+// MSAN-LABEL: define i32 @penguin(
+// MSAN:         call void @__msan_warning_noreturn()
+// MSAN:         unreachable
+// MSAN:       }
+//
 // MSAN-RECOVER-LABEL: define i32 @penguin(
+// MSAN-RECOVER:         call void @__msan_warning()
+// MSAN-RECOVER-NOT:     unreachable
+// MSAN-RECOVER:       }
+//
+// MSAN-RECOVER-LTO-LABEL: define i32 @penguin(
+// MSAN-RECOVER-LTO:          call void @__msan_warning()
+// MSAN-RECOVER-LTO-NOT:      unreachable
+// MSAN-RECOVER-LTO:       }
+//
 #[no_mangle]
 pub fn penguin(p: &mut i32) -> i32 {
-    // ASAN:             call void @__asan_report_load4(i64 %0)
-    // ASAN:             unreachable
-    //
-    // ASAN-RECOVER:     call void @__asan_report_load4_noabort(
-    // ASAN-RECOVER-NOT: unreachable
-    //
-    // MSAN:             call void @__msan_warning_noreturn()
-    // MSAN:             unreachable
-    //
-    // MSAN-RECOVER:     call void @__msan_warning()
-    // MSAN-RECOVER-NOT: unreachable
     *p
 }
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs
index f3be7b56db5..d996bf56fcc 100644
--- a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs
+++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs
@@ -1,10 +1,9 @@
-// run-pass
-
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
 #[allow(dead_code)]
-struct ArithArrayLen<const N: usize>([u32; 0 + N]); // ok
+struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+//~^ ERROR constant expression depends on a generic parameter
 
 #[derive(PartialEq, Eq)]
 struct Config {
@@ -12,7 +11,7 @@ struct Config {
 }
 
 struct B<const CFG: Config> {
-    arr: [u8; CFG.arr_size], // ok
+    arr: [u8; CFG.arr_size], //~ ERROR constant expression depends on a generic parameter
 }
 
 const C: Config = Config { arr_size: 5 };
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr
index 274f9769702..6ae70c493b1 100644
--- a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr
+++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr
@@ -1,8 +1,26 @@
 warning: the feature `const_generics` is incomplete and may cause the compiler to crash
-  --> $DIR/array-size-in-generic-struct-param.rs:3:12
+  --> $DIR/array-size-in-generic-struct-param.rs:1:12
    |
 LL | #![feature(const_generics)]
    |            ^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
 
+error: constant expression depends on a generic parameter
+  --> $DIR/array-size-in-generic-struct-param.rs:5:38
+   |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+   |                                      ^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/array-size-in-generic-struct-param.rs:14:5
+   |
+LL |     arr: [u8; CFG.arr_size],
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/try-on-option-diagnostics.rs b/src/test/ui/try-on-option-diagnostics.rs
index 65d5e29ec2f..63d17414c31 100644
--- a/src/test/ui/try-on-option-diagnostics.rs
+++ b/src/test/ui/try-on-option-diagnostics.rs
@@ -16,3 +16,32 @@ fn a_closure() -> u32 {
     };
     a_closure()
 }
+
+fn a_method() -> u32 {
+    struct S;
+
+    impl S {
+        fn a_method() {
+            let x: Option<u32> = None;
+            x?; //~ ERROR the `?` operator
+        }
+    }
+
+    S::a_method();
+    22
+}
+
+fn a_trait_method() -> u32 {
+    struct S;
+    trait T {
+        fn a_trait_method() {
+            let x: Option<u32> = None;
+            x?; //~ ERROR the `?` operator
+        }
+    }
+
+    impl T for S { }
+
+    S::a_trait_method();
+    22
+}
diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr
index ce3aca39fb8..c9dc3f1b879 100644
--- a/src/test/ui/try-on-option-diagnostics.stderr
+++ b/src/test/ui/try-on-option-diagnostics.stderr
@@ -27,6 +27,32 @@ LL | |     };
    = help: the trait `std::ops::Try` is not implemented for `{integer}`
    = note: required by `std::ops::Try::from_error`
 
-error: aborting due to 2 previous errors
+error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-diagnostics.rs:26:13
+   |
+LL | /         fn a_method() {
+LL | |             let x: Option<u32> = None;
+LL | |             x?;
+   | |             ^^ cannot use the `?` operator in a method that returns `()`
+LL | |         }
+   | |_________- this function should return `Result` or `Option` to accept `?`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `()`
+   = note: required by `std::ops::Try::from_error`
+
+error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-diagnostics.rs:39:13
+   |
+LL | /         fn a_trait_method() {
+LL | |             let x: Option<u32> = None;
+LL | |             x?;
+   | |             ^^ cannot use the `?` operator in a trait method that returns `()`
+LL | |         }
+   | |_________- this function should return `Result` or `Option` to accept `?`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `()`
+   = note: required by `std::ops::Try::from_error`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index cff04e197e4..98e9fe7a8b2 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -69,6 +69,7 @@ static TARGETS: &[&str] = &[
     "thumbv7neon-linux-androideabi",
     "armv7-unknown-linux-gnueabi",
     "armv7-unknown-linux-gnueabihf",
+    "armv7a-none-eabi",
     "thumbv7neon-unknown-linux-gnueabihf",
     "armv7-unknown-linux-musleabi",
     "armv7-unknown-linux-musleabihf",