From a7095af487f468dbad5eb6a3b45a847677f8d9b2 Mon Sep 17 00:00:00 2001
From: Yannick Koehler <ykoehler@arubanetworks.com>
Date: Tue, 24 Nov 2020 09:53:16 -0500
Subject: [PATCH] Add new target armv7-unknown-linux-uclibceabihf

---
 compiler/rustc_codegen_llvm/src/callee.rs     |  1 +
 compiler/rustc_middle/src/ty/layout.rs        |  4 ++--
 .../spec/armv7_unknown_linux_uclibceabihf.rs  | 24 +++++++++++++++++++
 compiler/rustc_target/src/spec/mod.rs         |  2 ++
 library/std/src/sys/unix/args.rs              |  7 ++++--
 library/std/src/sys/unix/mod.rs               |  3 +++
 .../std/src/sys/unix/process/process_unix.rs  |  8 +++----
 library/std/src/sys/unix/thread.rs            |  3 ++-
 library/unwind/src/lib.rs                     |  4 ++--
 src/doc/rustc/src/platform-support.md         |  1 +
 10 files changed, 45 insertions(+), 12 deletions(-)
 create mode 100644 compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs

diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index b26969a50120f..e90eb08fcd6e4 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -177,6 +177,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
             if cx.use_dll_storage_attrs
                 && tcx.is_dllimport_foreign_item(instance_def_id)
                 && tcx.sess.target.env != "gnu"
+                && tcx.sess.target.env != "uclibc"
             {
                 llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
             }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index e7bbdc3ccebdf..8277ff46f9f82 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2743,7 +2743,7 @@ where
         };
 
         let target = &cx.tcx().sess.target;
-        let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl");
+        let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc");
         let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
         let linux_s390x_gnu_like =
             target.os == "linux" && target.arch == "s390x" && target_env_gnu_like;
@@ -2842,7 +2842,7 @@ where
             if arg.layout.is_zst() {
                 // For some forsaken reason, x86_64-pc-windows-gnu
                 // doesn't ignore zero-sized struct arguments.
-                // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl}.
+                // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}.
                 if is_return
                     || rust_abi
                     || (!win_x64_gnu
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs
new file mode 100644
index 0000000000000..c5be50af2d666
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs
@@ -0,0 +1,24 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for glibc Linux on ARMv7 without NEON or
+// thumb-mode. See the thumbv7neon variant for enabling both.
+
+pub fn target() -> Target {
+    let base = super::linux_uclibc_base::opts();
+    Target {
+        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        pointer_width: 32,
+        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(),
+
+        options: TargetOptions {
+            // Info about features at https://wiki.debian.org/ArmHardFloatPort
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
+            cpu: "generic".to_string(),
+            max_atomic_width: Some(64),
+            unsupported_abis: super::arm_base::unsupported_abis(),
+            mcount: "_mcount".to_string(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 801cdd3ebe924..7a15f16f9f092 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -897,6 +897,8 @@ supported_targets! {
     ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
     ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
     ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
+
+    ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index 6967647249390..f4da202c563cd 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -100,13 +100,16 @@ mod imp {
         // On Linux-GNU, we rely on `ARGV_INIT_ARRAY` below to initialize
         // `ARGC` and `ARGV`. But in Miri that does not actually happen so we
         // still initialize here.
-        #[cfg(any(miri, not(all(target_os = "linux", target_env = "gnu"))))]
+        #[cfg(any(
+            miri,
+            not(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))
+        ))]
         really_init(_argc, _argv);
     }
 
     /// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
     /// This allows `std::env::args` to work even in a `cdylib`, as it does on macOS and Windows.
-    #[cfg(all(target_os = "linux", target_env = "gnu"))]
+    #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]
     #[used]
     #[link_section = ".init_array.00099"]
     static ARGV_INIT_ARRAY: extern "C" fn(
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 44328ffc22e5b..234c9fac48b81 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -254,5 +254,8 @@ cfg_if::cfg_if! {
         #[link(name = "zircon")]
         #[link(name = "fdio")]
         extern "C" {}
+    } else if #[cfg(all(target_os = "linux", target_env = "uclibc"))] {
+        #[link(name = "dl")]
+        extern "C" {}
     }
 }
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index ed9044382a898..17567481523a3 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -265,8 +265,7 @@ impl Command {
     #[cfg(not(any(
         target_os = "macos",
         target_os = "freebsd",
-        all(target_os = "linux", target_env = "gnu"),
-        all(target_os = "linux", target_env = "musl"),
+        all(target_os = "linux", any(target_env = "gnu", target_env = "musl")),
     )))]
     fn posix_spawn(
         &mut self,
@@ -281,8 +280,7 @@ impl Command {
     #[cfg(any(
         target_os = "macos",
         target_os = "freebsd",
-        all(target_os = "linux", target_env = "gnu"),
-        all(target_os = "linux", target_env = "musl"),
+        all(target_os = "linux", any(target_env = "gnu", target_env = "musl")),
     ))]
     fn posix_spawn(
         &mut self,
@@ -302,7 +300,7 @@ impl Command {
         }
 
         // Only glibc 2.24+ posix_spawn() supports returning ENOENT directly.
-        #[cfg(all(target_os = "linux", target_env = "gnu"))]
+        #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]
         {
             if let Some(version) = sys::os::glibc_version() {
                 if version < (2, 24) {
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index b8f43caec32a3..6998d9cdd9210 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -434,7 +434,8 @@ pub mod guard {
                 Some(stackaddr - guardsize..stackaddr)
             } else if cfg!(all(target_os = "linux", target_env = "musl")) {
                 Some(stackaddr - guardsize..stackaddr)
-            } else if cfg!(all(target_os = "linux", target_env = "gnu")) {
+            } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))
+            {
                 // glibc used to include the guard area within the stack, as noted in the BUGS
                 // section of `man pthread_attr_getguardsize`.  This has been corrected starting
                 // with glibc 2.27, and in some distro backports, so the guard is now placed at the
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index be5e56c71e36f..0bf68112b7988 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -46,7 +46,7 @@ extern "C" {}
 // don't want to duplicate it here.
 #[cfg(all(
     target_os = "linux",
-    target_env = "gnu",
+    any(target_env = "gnu", target_env = "uclibc"),
     not(feature = "llvm-libunwind"),
     not(feature = "system-llvm-libunwind")
 ))]
@@ -55,7 +55,7 @@ extern "C" {}
 
 #[cfg(all(
     target_os = "linux",
-    target_env = "gnu",
+    any(target_env = "gnu", target_env = "uclibc"),
     not(feature = "llvm-libunwind"),
     feature = "system-llvm-libunwind"
 ))]
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index f352746d3fbe9..d14ccd9435afa 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -169,6 +169,7 @@ target | std | host | notes
 `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
 `armv6-unknown-netbsd-eabihf` | ? |  |
 `armv7-apple-ios` | ✓ |  | ARMv7 iOS, Cortex-a8
+`armv7-unknown-linux-uclibceabihf` | ✓ | ? | ARMv7 Linux uClibc
 `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
 `armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
 `armv7-wrs-vxworks-eabihf` | ? |  |