From 8afe59893a7b3586b29b0bb697eba69e1a2b5593 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Wed, 20 Jan 2021 17:06:29 +0000
Subject: [PATCH 1/9] Add big-endian support for AArch64 va_arg

---
 compiler/rustc_codegen_llvm/src/va_arg.rs | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index 07fde27b5a3..39d08fbee3b 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -105,7 +105,6 @@ fn emit_aapcs_va_arg(
     let mut end = bx.build_sibling_block("va_arg.end");
     let zero = bx.const_i32(0);
     let offset_align = Align::from_bytes(4).unwrap();
-    assert_eq!(bx.tcx().sess.target.endian, Endian::Little);
 
     let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
     let (reg_off, reg_top_index, slot_size) = if gr_type {
@@ -144,9 +143,14 @@ fn emit_aapcs_va_arg(
     let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi);
 
     // reg_value = *(@top + reg_off_v);
-    let top = in_reg.gep(top, &[reg_off_v]);
-    let top = in_reg.bitcast(top, bx.cx.type_ptr_to(layout.llvm_type(bx)));
-    let reg_value = in_reg.load(top, layout.align.abi);
+    let mut reg_addr = in_reg.gep(top, &[reg_off_v]);
+    if bx.tcx().sess.target.endian == Endian::Big && layout.size.bytes() != slot_size {
+        // On big-endian systems the value is right-aligned in its slot.
+        let offset = bx.const_i32((slot_size - layout.size.bytes()) as i32);
+        reg_addr = in_reg.gep(reg_addr, &[offset]);
+    }
+    let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(layout.llvm_type(bx)));
+    let reg_value = in_reg.load(reg_addr, layout.align.abi);
     in_reg.br(&end.llbb());
 
     // On Stack block

From d53b0a04a6a0f5048b37da2c14ac0cdabae5d348 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Wed, 20 Jan 2021 17:08:47 +0000
Subject: [PATCH 2/9] Fix ARM and AArch64 calling convention for passing small
 composite types

On big-endian the values need to be right-aligned within a 64-bit register, as if the value had been read with a 64-bit load instruction.
---
 compiler/rustc_target/src/abi/call/aarch64.rs | 24 ++-----------------
 compiler/rustc_target/src/abi/call/arm.rs     |  9 +------
 2 files changed, 3 insertions(+), 30 deletions(-)

diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/abi/call/aarch64.rs
index 1ab7722edab..a5e985d4712 100644
--- a/compiler/rustc_target/src/abi/call/aarch64.rs
+++ b/compiler/rustc_target/src/abi/call/aarch64.rs
@@ -40,17 +40,7 @@ where
     let size = ret.layout.size;
     let bits = size.bits();
     if bits <= 128 {
-        let unit = if bits <= 8 {
-            Reg::i8()
-        } else if bits <= 16 {
-            Reg::i16()
-        } else if bits <= 32 {
-            Reg::i32()
-        } else {
-            Reg::i64()
-        };
-
-        ret.cast_to(Uniform { unit, total: size });
+        ret.cast_to(Uniform { unit: Reg::i64(), total: size });
         return;
     }
     ret.make_indirect();
@@ -72,17 +62,7 @@ where
     let size = arg.layout.size;
     let bits = size.bits();
     if bits <= 128 {
-        let unit = if bits <= 8 {
-            Reg::i8()
-        } else if bits <= 16 {
-            Reg::i16()
-        } else if bits <= 32 {
-            Reg::i32()
-        } else {
-            Reg::i64()
-        };
-
-        arg.cast_to(Uniform { unit, total: size });
+        arg.cast_to(Uniform { unit: Reg::i64(), total: size });
         return;
     }
     arg.make_indirect();
diff --git a/compiler/rustc_target/src/abi/call/arm.rs b/compiler/rustc_target/src/abi/call/arm.rs
index 26fed3bae4e..b560e11fe1c 100644
--- a/compiler/rustc_target/src/abi/call/arm.rs
+++ b/compiler/rustc_target/src/abi/call/arm.rs
@@ -45,14 +45,7 @@ where
     let size = ret.layout.size;
     let bits = size.bits();
     if bits <= 32 {
-        let unit = if bits <= 8 {
-            Reg::i8()
-        } else if bits <= 16 {
-            Reg::i16()
-        } else {
-            Reg::i32()
-        };
-        ret.cast_to(Uniform { unit, total: size });
+        ret.cast_to(Uniform { unit: Reg::i32(), total: size });
         return;
     }
     ret.make_indirect();

From 06f14df43bd92a7ccbb5d09fc476e6926fe4d161 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Wed, 20 Jan 2021 17:10:14 +0000
Subject: [PATCH 3/9] Support AArch64 ILP32 in libunwind bindings

---
 library/unwind/src/libunwind.rs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index ff1d82fc990..faf554d285a 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -36,9 +36,12 @@ pub const unwinder_private_data_size: usize = 20;
 #[cfg(all(target_arch = "arm", target_os = "ios"))]
 pub const unwinder_private_data_size: usize = 5;
 
-#[cfg(target_arch = "aarch64")]
+#[cfg(all(target_arch = "aarch64", target_pointer_width = "64"))]
 pub const unwinder_private_data_size: usize = 2;
 
+#[cfg(all(target_arch = "aarch64", target_pointer_width = "32"))]
+pub const unwinder_private_data_size: usize = 5;
+
 #[cfg(target_arch = "mips")]
 pub const unwinder_private_data_size: usize = 2;
 

From a112c4d61da8f3cdff27c68a787d8e1a23cc6d25 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Wed, 20 Jan 2021 17:11:21 +0000
Subject: [PATCH 4/9] Support AArch64 big-endian and ILP32 in compiletest

---
 src/tools/compiletest/src/util.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 1647df8044c..292850bd9e2 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -38,6 +38,7 @@ const OS_TABLE: &[(&str, &str)] = &[
 
 const ARCH_TABLE: &[(&str, &str)] = &[
     ("aarch64", "aarch64"),
+    ("aarch64_be", "aarch64"),
     ("amd64", "x86_64"),
     ("arm", "arm"),
     ("arm64", "aarch64"),
@@ -110,6 +111,7 @@ pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[
 ];
 
 const BIG_ENDIAN: &[&str] = &[
+    "aarch64_be",
     "armebv7r",
     "mips",
     "mips64",
@@ -160,7 +162,9 @@ pub fn matches_env(triple: &str, name: &str) -> bool {
 }
 
 pub fn get_pointer_width(triple: &str) -> &'static str {
-    if (triple.contains("64") && !triple.ends_with("gnux32")) || triple.starts_with("s390x") {
+    if (triple.contains("64") && !triple.ends_with("gnux32") && !triple.ends_with("gnu_ilp32"))
+        || triple.starts_with("s390x")
+    {
         "64bit"
     } else if triple.starts_with("avr") {
         "16bit"

From 8783d1a47eeaf04635e29b2418795bd36ac49605 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Wed, 20 Jan 2021 17:13:49 +0000
Subject: [PATCH 5/9] Add big-endian and ILP32 AArch64 targets

---
 .../src/spec/aarch64_be_unknown_linux_gnu.rs  | 20 +++++++++++++++++++
 .../aarch64_be_unknown_linux_gnu_ilp32.rs     | 20 +++++++++++++++++++
 .../spec/aarch64_unknown_linux_gnu_ilp32.rs   | 18 +++++++++++++++++
 compiler/rustc_target/src/spec/mod.rs         |  4 ++++
 4 files changed, 62 insertions(+)
 create mode 100644 compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
 create mode 100644 compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
 create mode 100644 compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs

diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..192c4661c7c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
@@ -0,0 +1,20 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::linux_gnu_base::opts();
+    base.max_atomic_width = Some(128);
+
+    Target {
+        llvm_target: "aarch64_be-unknown-linux-gnu".to_string(),
+        pointer_width: 64,
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        options: TargetOptions {
+            unsupported_abis: super::arm_base::unsupported_abis(),
+            mcount: "\u{1}_mcount".to_string(),
+            endian: Endian::Big,
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
new file mode 100644
index 00000000000..5b9e9c9519c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -0,0 +1,20 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::linux_gnu_base::opts();
+    base.max_atomic_width = Some(128);
+
+    Target {
+        llvm_target: "aarch64_be-unknown-linux-gnu_ilp32".to_string(),
+        pointer_width: 32,
+        data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        options: TargetOptions {
+            unsupported_abis: super::arm_base::unsupported_abis(),
+            mcount: "\u{1}_mcount".to_string(),
+            endian: Endian::Big,
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
new file mode 100644
index 00000000000..f2d7576280f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
@@ -0,0 +1,18 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::linux_gnu_base::opts();
+    base.max_atomic_width = Some(128);
+
+    Target {
+        llvm_target: "aarch64-unknown-linux-gnu_ilp32".to_string(),
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        options: TargetOptions {
+            unsupported_abis: super::arm_base::unsupported_abis(),
+            mcount: "\u{1}_mcount".to_string(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 90d35efaa25..8d6b2e3307b 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -745,6 +745,10 @@ supported_targets! {
     ("mipsel-sony-psp", mipsel_sony_psp),
     ("mipsel-unknown-none", mipsel_unknown_none),
     ("thumbv4t-none-eabi", thumbv4t_none_eabi),
+
+    ("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),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.

From 69e632656441e8a6ddb892e27a9196af7b4343f2 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Tue, 26 Jan 2021 20:32:22 +0000
Subject: [PATCH 6/9] Add new aarch64 targets to platform-support.md

---
 src/doc/rustc/src/platform-support.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index ce8caae375e..eb740419647 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -156,11 +156,14 @@ target | std | host | notes
 `aarch64-apple-tvos` | * |  | ARM64 tvOS
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
 `aarch64-unknown-hermit` | ? |  |
+`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
 `aarch64-unknown-netbsd` | ✓ | ✓ |
 `aarch64-unknown-openbsd` | ✓ | ✓ | ARM64 OpenBSD
 `aarch64-unknown-redox` | ? |  | ARM64 Redox OS
 `aarch64-uwp-windows-msvc` | ? |  |
 `aarch64-wrs-vxworks` | ? |  |
+`aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
+`aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
 `armv4t-unknown-linux-gnueabi` | ? |  |
 `armv5te-unknown-linux-uclibceabi` | ? |  | ARMv5TE Linux with uClibc
 `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD

From 530723036aa1cbb1db7b5ac091220ab4c6dc05da Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Thu, 21 Jan 2021 00:12:24 +0000
Subject: [PATCH 7/9] Bump LLVM submodule

---
 src/llvm-project | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/llvm-project b/src/llvm-project
index f9a8d70b6e0..70d09f218d1 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit f9a8d70b6e0365ac2172ca6b7f1de0341297458d
+Subproject commit 70d09f218d1c84fedabdb74881e214dacd5b0c3d

From c3dedd0d816ae66be6c9971c9c3e2da122d4d3a4 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu.dantras@huawei.com>
Date: Thu, 21 Jan 2021 00:12:40 +0000
Subject: [PATCH 8/9] Upgrade libc to 0.2.85

---
 Cargo.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 9d726b240da..6ee096ad5df 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1783,9 +1783,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.79"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
+checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
 dependencies = [
  "rustc-std-workspace-core",
 ]

From 3408c58bdfc923f9b1b7fbab271a791442de682a Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu@gmail.com>
Date: Mon, 1 Feb 2021 22:29:04 +0000
Subject: [PATCH 9/9] Fix AArch64 types in std::os::raw

---
 library/std/src/os/linux/raw.rs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index 617c4098aa9..525102212c4 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -247,17 +247,17 @@ mod arch {
     use crate::os::raw::{c_int, c_long};
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blkcnt_t = u64;
+    pub type blkcnt_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blksize_t = u64;
+    pub type blksize_t = i32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub type ino_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type nlink_t = u64;
+    pub type nlink_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type off_t = u64;
+    pub type off_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type time_t = i64;
+    pub type time_t = c_long;
 
     #[repr(C)]
     #[derive(Clone)]
@@ -288,15 +288,15 @@ mod arch {
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_blocks: i64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime: i64,
+        pub st_atime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_atime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime: i64,
+        pub st_mtime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_mtime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime: i64,
+        pub st_ctime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_ctime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]