t.p.northover created this revision.
t.p.northover added a reviewer: fhahn.
Herald added subscribers: jfb, kristof.beyls, javed.absar, mcrosier.
Herald added a project: clang.

This adds all of the ABI tweaks we need to match the arm64_32 ABI as it exists 
in the wild. Most cirtically, of course, it makes the triple ILP32. But it also 
covers the usual suspects when defining an ABI.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63131

Files:
  clang/lib/Basic/Targets/AArch64.cpp
  clang/lib/Basic/Targets/AArch64.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/CodeGen/arm64_32-vaarg.c
  clang/test/CodeGen/arm64_32.c
  clang/test/CodeGen/builtins-arm64.c
  clang/test/CodeGen/target-data.c
  clang/test/CodeGenCXX/armv7k.cpp
  clang/test/Preprocessor/arm64_32.c
  clang/test/Preprocessor/init-v7k-compat.c
  clang/test/Preprocessor/stdint.c
  clang/test/Sema/aarch64-neon-vector-types.c

Index: clang/test/Sema/aarch64-neon-vector-types.c
===================================================================
--- clang/test/Sema/aarch64-neon-vector-types.c
+++ clang/test/Sema/aarch64-neon-vector-types.c
@@ -3,6 +3,8 @@
 // RUN: %clang_cc1 %s -triple arm64-none-linux-gnu -target-feature +neon -fsyntax-only -verify
 // RUN: %clang_cc1 %s -triple arm64-none-linux-gnu -target-feature +neon -DUSE_LONG -fsyntax-only -verify
 
+// RUN: %clang_cc1 %s -triple arm64_32-apple-ios -target-feature +neon -fsyntax-only -verify
+
 typedef float float32_t;
 typedef unsigned char poly8_t;
 typedef unsigned short poly16_t;
Index: clang/test/Preprocessor/stdint.c
===================================================================
--- clang/test/Preprocessor/stdint.c
+++ clang/test/Preprocessor/stdint.c
@@ -105,6 +105,113 @@
 // ARM:INTMAX_C_(0) 0LL
 // ARM:UINTMAX_C_(0) 0ULL
 //
+// RUN: %clang_cc1 -E -ffreestanding -triple=arm64_32-apple-ios7.0 %s | FileCheck -check-prefix ARM64_32 %s
+//
+// ARM64_32:typedef long long int int64_t;
+// ARM64_32:typedef long long unsigned int uint64_t;
+// ARM64_32:typedef int64_t int_least64_t;
+// ARM64_32:typedef uint64_t uint_least64_t;
+// ARM64_32:typedef int64_t int_fast64_t;
+// ARM64_32:typedef uint64_t uint_fast64_t;
+//
+// ARM64_32:typedef int int32_t;
+// ARM64_32:typedef unsigned int uint32_t;
+// ARM64_32:typedef int32_t int_least32_t;
+// ARM64_32:typedef uint32_t uint_least32_t;
+// ARM64_32:typedef int32_t int_fast32_t;
+// ARM64_32:typedef uint32_t uint_fast32_t;
+// 
+// ARM64_32:typedef short int16_t;
+// ARM64_32:typedef unsigned short uint16_t;
+// ARM64_32:typedef int16_t int_least16_t;
+// ARM64_32:typedef uint16_t uint_least16_t;
+// ARM64_32:typedef int16_t int_fast16_t;
+// ARM64_32:typedef uint16_t uint_fast16_t;
+//
+// ARM64_32:typedef signed char int8_t;
+// ARM64_32:typedef unsigned char uint8_t;
+// ARM64_32:typedef int8_t int_least8_t;
+// ARM64_32:typedef uint8_t uint_least8_t;
+// ARM64_32:typedef int8_t int_fast8_t;
+// ARM64_32:typedef uint8_t uint_fast8_t;
+//
+// ARM64_32:typedef long int intptr_t;
+// ARM64_32:typedef long unsigned int uintptr_t;
+// 
+// ARM64_32:typedef long long int intmax_t;
+// ARM64_32:typedef long long unsigned int uintmax_t;
+//
+// ARM64_32:INT8_MAX_ 127
+// ARM64_32:INT8_MIN_ (-127 -1)
+// ARM64_32:UINT8_MAX_ 255
+// ARM64_32:INT_LEAST8_MIN_ (-127 -1)
+// ARM64_32:INT_LEAST8_MAX_ 127
+// ARM64_32:UINT_LEAST8_MAX_ 255
+// ARM64_32:INT_FAST8_MIN_ (-127 -1)
+// ARM64_32:INT_FAST8_MAX_ 127
+// ARM64_32:UINT_FAST8_MAX_ 255
+//
+// ARM64_32:INT16_MAX_ 32767
+// ARM64_32:INT16_MIN_ (-32767 -1)
+// ARM64_32:UINT16_MAX_ 65535
+// ARM64_32:INT_LEAST16_MIN_ (-32767 -1)
+// ARM64_32:INT_LEAST16_MAX_ 32767
+// ARM64_32:UINT_LEAST16_MAX_ 65535
+// ARM64_32:INT_FAST16_MIN_ (-32767 -1)
+// ARM64_32:INT_FAST16_MAX_ 32767
+// ARM64_32:UINT_FAST16_MAX_ 65535
+//
+// ARM64_32:INT32_MAX_ 2147483647
+// ARM64_32:INT32_MIN_ (-2147483647 -1)
+// ARM64_32:UINT32_MAX_ 4294967295U
+// ARM64_32:INT_LEAST32_MIN_ (-2147483647 -1)
+// ARM64_32:INT_LEAST32_MAX_ 2147483647
+// ARM64_32:UINT_LEAST32_MAX_ 4294967295U
+// ARM64_32:INT_FAST32_MIN_ (-2147483647 -1)
+// ARM64_32:INT_FAST32_MAX_ 2147483647
+// ARM64_32:UINT_FAST32_MAX_ 4294967295U
+//
+// ARM64_32:INT64_MAX_ 9223372036854775807LL
+// ARM64_32:INT64_MIN_ (-9223372036854775807LL -1)
+// ARM64_32:UINT64_MAX_ 18446744073709551615ULL
+// ARM64_32:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// ARM64_32:INT_LEAST64_MAX_ 9223372036854775807LL
+// ARM64_32:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// ARM64_32:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// ARM64_32:INT_FAST64_MAX_ 9223372036854775807LL
+// ARM64_32:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// ARM64_32:INTPTR_MIN_ (-2147483647L -1)
+// ARM64_32:INTPTR_MAX_ 2147483647L
+// ARM64_32:UINTPTR_MAX_ 4294967295UL
+// ARM64_32:PTRDIFF_MIN_ (-2147483647L -1)
+// ARM64_32:PTRDIFF_MAX_ 2147483647L
+// ARM64_32:SIZE_MAX_ 4294967295UL
+//
+// ARM64_32:INTMAX_MIN_ (-9223372036854775807LL -1)
+// ARM64_32:INTMAX_MAX_ 9223372036854775807LL
+// ARM64_32:UINTMAX_MAX_ 18446744073709551615ULL
+//
+// ARM64_32:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// ARM64_32:SIG_ATOMIC_MAX_ 2147483647
+// ARM64_32:WINT_MIN_ (-2147483647 -1)
+// ARM64_32:WINT_MAX_ 2147483647
+//
+// ARM64_32:WCHAR_MAX_ 2147483647
+// ARM64_32:WCHAR_MIN_ (-2147483647 -1)
+//
+// ARM64_32:INT8_C_(0) 0
+// ARM64_32:UINT8_C_(0) 0U
+// ARM64_32:INT16_C_(0) 0
+// ARM64_32:UINT16_C_(0) 0U
+// ARM64_32:INT32_C_(0) 0
+// ARM64_32:UINT32_C_(0) 0U
+// ARM64_32:INT64_C_(0) 0LL
+// ARM64_32:UINT64_C_(0) 0ULL
+//
+// ARM64_32:INTMAX_C_(0) 0LL
+// ARM64_32:UINTMAX_C_(0) 0ULL
+
 //
 // RUN: %clang_cc1 -E -ffreestanding -triple=i386-none-none %s | FileCheck -check-prefix I386 %s
 //
Index: clang/test/Preprocessor/init-v7k-compat.c
===================================================================
--- clang/test/Preprocessor/init-v7k-compat.c
+++ clang/test/Preprocessor/init-v7k-compat.c
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64_32-apple-ios7.0 < /dev/null | FileCheck %s
 // RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv7k-apple-watchos2.0 < /dev/null | FileCheck %s
 
 // Check that the chosen types for things like size_t, ptrdiff_t etc are as
Index: clang/test/Preprocessor/arm64_32.c
===================================================================
--- /dev/null
+++ clang/test/Preprocessor/arm64_32.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64_32-apple-ios < /dev/null | FileCheck %s --check-prefix=CHECK-32
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64-apple-ios < /dev/null | FileCheck %s --check-prefix=CHECK-64
+
+// CHECK-32: #define __ARM64_ARCH_8_32__ 1
+// CHECK-64: #define __ARM64_ARCH_8__ 1
Index: clang/test/CodeGenCXX/armv7k.cpp
===================================================================
--- clang/test/CodeGenCXX/armv7k.cpp
+++ clang/test/CodeGenCXX/armv7k.cpp
@@ -1,6 +1,9 @@
 // RUN: %clang_cc1 %s -triple=thumbv7k-apple-watchos -emit-llvm -o - -target-abi aapcs16 | FileCheck %s
 // RUN: %clang_cc1 %s -triple=thumbv7k-apple-watchos -emit-llvm -o - -target-abi aapcs16 | FileCheck -check-prefix=CHECK-GLOBALS %s
 
+// RUN: %clang_cc1 %s -triple=arm64_32-apple-ios -emit-llvm -o - -target-abi darwinpcs | FileCheck %s
+// RUN: %clang_cc1 %s -triple=arm64_32-apple-ios -emit-llvm -o - -target-abi darwinpcs | FileCheck -check-prefix=CHECK-GLOBALS %s
+
 // __cxa_guard_acquire argument is 64-bit
 // rdar://11540122
 struct A {
Index: clang/test/CodeGen/target-data.c
===================================================================
--- clang/test/CodeGen/target-data.c
+++ clang/test/CodeGen/target-data.c
@@ -163,6 +163,10 @@
 // RUN: FileCheck %s -check-prefix=AARCH64
 // AARCH64: target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 
+// RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=AARCH64-ILP32
+// AARCH64-ILP32: target datalayout = "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128"
+
 // RUN: %clang_cc1 -triple thumb-unknown-gnueabi -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=THUMB
 // THUMB: target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
Index: clang/test/CodeGen/builtins-arm64.c
===================================================================
--- clang/test/CodeGen/builtins-arm64.c
+++ clang/test/CodeGen/builtins-arm64.c
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple arm64-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LINUX
 // RUN: %clang_cc1 -triple aarch64-windows -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WIN
+// RUN: %clang_cc1 -triple arm64_32-apple-ios -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
 #include <stdint.h>
 
 void f0(void *a, void *b) {
@@ -7,10 +8,12 @@
 // CHECK: call {{.*}} @__clear_cache
 }
 
+#if __LP64__
 void *tp (void) {
   return __builtin_thread_pointer ();
-// CHECK: call {{.*}} @llvm.thread.pointer()
+// CHECK-LINUX: call {{.*}} @llvm.thread.pointer()
 }
+#endif
 
 // CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a)
 unsigned rbit(unsigned a) {
Index: clang/test/CodeGen/arm64_32.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/arm64_32.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -emit-llvm -o - %s | FileCheck %s
+
+struct Foo {
+  char a;
+  int b : 1;
+};
+
+int BitfieldOffset = sizeof(struct Foo);
+// CHECK: @BitfieldOffset = global i32 2
+
+int PointerSize = sizeof(void *);
+// CHECK: @PointerSize = global i32 4
+
+int PointerAlign = __alignof(void *);
+// CHECK: @PointerAlign = global i32 4
+
+int LongSize = sizeof(long);
+// CHECK: @LongSize = global i32 4
+
+int LongAlign = __alignof(long);
+// CHECK: @LongAlign = global i32 4
+
+// Not expected to change, but it's a difference between AAPCS and DarwinPCS
+// that we need to be preserved for compatibility with ARMv7k.
+long double LongDoubleVar = 0.0;
+// CHECK: @LongDoubleVar = global double
+
+typedef float __attribute__((ext_vector_type(16))) v16f32;
+v16f32 func(v16f32 in) { return in; }
+// CHECK: define void @func(<16 x float>* noalias sret {{%.*}}, <16 x float> {{%.*}})
Index: clang/test/CodeGen/arm64_32-vaarg.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/arm64_32-vaarg.c
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - -O1 -ffreestanding %s | FileCheck %s
+
+#include <stdarg.h>
+
+typedef struct {
+  int a;
+} OneInt;
+
+// No realignment should be needed here: slot size is 4 bytes.
+int test_int(OneInt input, va_list *mylist) {
+// CHECK-LABEL: define i32 @test_int(i32 %input
+// CHECK: [[START:%.*]] = load i8*, i8** %mylist
+// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 4
+// CHECK: store i8* [[NEXT]], i8** %mylist
+
+// CHECK: [[ADDR_I32:%.*]] = bitcast i8* [[START]] to i32*
+// CHECK: [[RES:%.*]] = load i32, i32* [[ADDR_I32]]
+// CHECK: ret i32 [[RES]]
+
+  return va_arg(*mylist, OneInt).a;
+}
+
+
+typedef struct {
+  long long a;
+} OneLongLong;
+
+// Minimum slot size is 4 bytes, so address needs rounding up to multiple of 8.
+long long test_longlong(OneLongLong input, va_list *mylist) {
+// CHECK-LABEL: define i64 @test_longlong(i64 %input
+// CHECK: [[STARTPTR:%.*]] = bitcast i8** %mylist to i32*
+// CHECK: [[START:%.*]] = load i32, i32* [[STARTPTR]]
+
+// CHECK: [[ALIGN_TMP:%.*]] = add i32 [[START]], 7
+// CHECK: [[ALIGNED:%.*]] = and i32 [[ALIGN_TMP]], -8
+// CHECK: [[ALIGNED_ADDR:%.*]] = inttoptr i32 [[ALIGNED]] to i8*
+// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[ALIGNED_ADDR]], i32 8
+// CHECK: store i8* [[NEXT]], i8** %mylist
+
+// CHECK: [[ADDR_STRUCT:%.*]] = inttoptr i32 [[ALIGNED]] to %struct.OneLongLong*
+// CHECK: [[ADDR_I64:%.*]] = getelementptr inbounds %struct.OneLongLong, %struct.OneLongLong* [[ADDR_STRUCT]], i32 0, i32 0
+// CHECK: [[RES:%.*]] = load i64, i64* [[ADDR_I64]]
+// CHECK: ret i64 [[RES]]
+
+  return va_arg(*mylist, OneLongLong).a;
+}
+
+
+typedef struct {
+  float arr[4];
+} HFA;
+
+// HFAs take priority over passing large structs indirectly.
+float test_hfa(va_list *mylist) {
+// CHECK-LABEL: define float @test_hfa
+// CHECK: [[START:%.*]] = load i8*, i8** %mylist
+
+// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 16
+// CHECK: store i8* [[NEXT]], i8** %mylist
+
+// CHECK: [[ADDR_FLOAT:%.*]] = bitcast i8* [[START]] to float*
+// CHECK: [[RES:%.*]] = load float, float* [[ADDR_FLOAT]]
+// CHECK: ret float [[RES]]
+
+  return va_arg(*mylist, HFA).arr[0];
+}
+
+// armv7k does not return HFAs normally for variadic functions, so we must match
+// that.
+HFA test_hfa_return(int n, ...) {
+// CHECK-LABEL: define [2 x i64] @test_hfa_return
+  HFA h = {0};
+  return h;
+}
+
+typedef struct {
+  long long a, b;
+  char c;
+} BigStruct;
+
+// Structs bigger than 16 bytes are passed indirectly: a pointer is placed on
+// the stack.
+long long test_bigstruct(BigStruct input, va_list *mylist) {
+// CHECK-LABEL: define i64 @test_bigstruct(%struct.BigStruct*
+// CHECK: [[START:%.*]] = load i8*, i8** %mylist
+// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 4
+// CHECK: store i8* [[NEXT]], i8** %mylist
+
+// CHECK: [[INT_PTR:%.*]] = bitcast i8* [[START]] to %struct.BigStruct**
+// CHECK: [[ADDR:%.*]] = load %struct.BigStruct*, %struct.BigStruct** [[INT_PTR]]
+// CHECK: [[ADDR_I64:%.*]] = getelementptr inbounds %struct.BigStruct, %struct.BigStruct* [[ADDR]], i32 0, i32 0
+// CHECK: [[RES:%.*]] = load i64, i64* [[ADDR_I64]]
+// CHECK: ret i64 [[RES]]
+
+  return va_arg(*mylist, BigStruct).a;
+}
+
+typedef struct {
+  short arr[3];
+} ThreeShorts;
+
+// Slot sizes are 4-bytes on arm64_32, so structs with less than 32-bit
+// alignment must be passed via "[N x i32]" to be correctly allocated in the
+// backend.
+short test_threeshorts(ThreeShorts input, va_list *mylist) {
+// CHECK-LABEL: define signext i16 @test_threeshorts([2 x i32] %input
+
+// CHECK: [[START:%.*]] = load i8*, i8** %mylist
+// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 8
+// CHECK: store i8* [[NEXT]], i8** %mylist
+
+// CHECK: [[ADDR_I32:%.*]] = bitcast i8* [[START]] to i16*
+// CHECK: [[RES:%.*]] = load i16, i16* [[ADDR_I32]]
+// CHECK: ret i16 [[RES]]
+
+  return va_arg(*mylist, ThreeShorts).arr[0];
+}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -7212,6 +7212,7 @@
   // Signed poly is mathematically wrong, but has been baked into some ABIs by
   // now.
   bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 ||
+                        Triple.getArch() == llvm::Triple::aarch64_32 ||
                         Triple.getArch() == llvm::Triple::aarch64_be;
   if (VecKind == VectorType::NeonPolyVector) {
     if (IsPolyUnsigned) {
@@ -7229,10 +7230,10 @@
 
   // Non-polynomial vector types: the usual suspects are allowed, as well as
   // float64_t on AArch64.
-  bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
-                 Triple.getArch() == llvm::Triple::aarch64_be;
-
-  if (Is64Bit && BTy->getKind() == BuiltinType::Double)
+  bool DoubleAllowed = Triple.getArch() == llvm::Triple::aarch64 ||
+                       Triple.getArch() == llvm::Triple::aarch64_be ||
+                       Triple.getArch() == llvm::Triple::aarch64_32;
+  if (DoubleAllowed && BTy->getKind() == BuiltinType::Double)
     return true;
 
   return BTy->getKind() == BuiltinType::SChar ||
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1514,6 +1514,7 @@
           return ExprError();
         break;
       case llvm::Triple::aarch64:
+      case llvm::Triple::aarch64_32:
       case llvm::Triple::aarch64_be:
         if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
           return ExprError();
@@ -1658,6 +1659,7 @@
 
     llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
     bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
+                          Arch == llvm::Triple::aarch64_32 ||
                           Arch == llvm::Triple::aarch64_be;
     bool IsInt64Long =
         Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong;
@@ -5390,7 +5392,8 @@
 static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) {
   const llvm::Triple &TT = S.Context.getTargetInfo().getTriple();
   bool IsX64 = TT.getArch() == llvm::Triple::x86_64;
-  bool IsAArch64 = TT.getArch() == llvm::Triple::aarch64;
+  bool IsAArch64 = (TT.getArch() == llvm::Triple::aarch64 ||
+                    TT.getArch() == llvm::Triple::aarch64_32);
   bool IsWindows = TT.isOSWindows();
   bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start;
   if (IsX64 || IsAArch64) {
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -4938,7 +4938,7 @@
   ABIKind getABIKind() const { return Kind; }
   bool isDarwinPCS() const { return Kind == DarwinPCS; }
 
-  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic) const;
   ABIArgInfo classifyArgumentType(QualType RetTy) const;
   bool isHomogeneousAggregateBaseType(QualType Ty) const override;
   bool isHomogeneousAggregateSmallEnough(const Type *Ty,
@@ -4948,7 +4948,8 @@
 
   void computeInfo(CGFunctionInfo &FI) const override {
     if (!::classifyReturnType(getCXXABI(), FI, *this))
-      FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+      FI.getReturnInfo() =
+          classifyReturnType(FI.getReturnType(), FI.isVariadic());
 
     for (auto &it : FI.arguments())
       it.info = classifyArgumentType(it.type);
@@ -5131,23 +5132,24 @@
       Alignment = getContext().getTypeUnadjustedAlign(Ty);
       Alignment = Alignment < 128 ? 64 : 128;
     } else {
-      Alignment = getContext().getTypeAlign(Ty);
+      Alignment = std::max(getContext().getTypeAlign(Ty),
+                           (unsigned)getTarget().getPointerWidth(0));
     }
-    Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes
+    Size = llvm::alignTo(Size, Alignment);
 
     // We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
     // For aggregates with 16-byte alignment, we use i128.
-    if (Alignment < 128 && Size == 128) {
-      llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext());
-      return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64));
-    }
-    return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
+    llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment);
+    return ABIArgInfo::getDirect(
+        Size == Alignment ? BaseTy
+                          : llvm::ArrayType::get(BaseTy, Size / Alignment));
   }
 
   return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
 }
 
-ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
+ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy,
+                                              bool IsVariadic) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
@@ -5171,7 +5173,9 @@
 
   const Type *Base = nullptr;
   uint64_t Members = 0;
-  if (isHomogeneousAggregate(RetTy, Base, Members))
+  if (isHomogeneousAggregate(RetTy, Base, Members) &&
+      !(getTarget().getTriple().getArch() == llvm::Triple::aarch64_32 &&
+        IsVariadic))
     // Homogeneous Floating-point Aggregates (HFAs) are returned directly.
     return ABIArgInfo::getDirect();
 
@@ -5206,6 +5210,14 @@
     // NumElements should be power of 2.
     if (!llvm::isPowerOf2_32(NumElements))
       return true;
+
+    // arm64_32 has to be compatible with the ARM logic here, which allows huge
+    // vectors for some reason.
+    llvm::Triple Triple = getTarget().getTriple();
+    if (Triple.getArch() == llvm::Triple::aarch64_32 &&
+        Triple.isOSBinFormatMachO())
+      return Size <= 32;
+
     return Size != 64 && (Size != 128 || NumElements == 1);
   }
   return false;
@@ -5497,7 +5509,8 @@
   if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty))
     return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect());
 
-  CharUnits SlotSize = CharUnits::fromQuantity(8);
+  uint64_t PointerSize = getTarget().getPointerWidth(0) / 8;
+  CharUnits SlotSize = CharUnits::fromQuantity(PointerSize);
 
   // Empty records are ignored for parameter passing purposes.
   if (isEmptyRecord(getContext(), Ty, true)) {
@@ -9361,6 +9374,7 @@
     return SetCGInfo(new AVRTargetCodeGenInfo(Types));
 
   case llvm::Triple::aarch64:
+  case llvm::Triple::aarch64_32:
   case llvm::Triple::aarch64_be: {
     AArch64ABIInfo::ABIKind Kind = AArch64ABIInfo::AAPCS;
     if (getTarget().getABI() == "darwinpcs")
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -4196,6 +4196,7 @@
   case llvm::Triple::thumbeb:
     return CGF->EmitARMBuiltinExpr(BuiltinID, E, Arch);
   case llvm::Triple::aarch64:
+  case llvm::Triple::aarch64_32:
   case llvm::Triple::aarch64_be:
     return CGF->EmitAArch64BuiltinExpr(BuiltinID, E, Arch);
   case llvm::Triple::x86:
@@ -5625,7 +5626,8 @@
     llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType());
     // TODO: Currently in AArch32 mode the pointer operand comes first, whereas
     // in AArch64 it comes last. We may want to stick to one or another.
-    if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) {
+    if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be ||
+        Arch == llvm::Triple::aarch64_32) {
       llvm::Type *Tys[2] = { VTy, PTy };
       std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
       return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "");
Index: clang/lib/Basic/Targets/AArch64.h
===================================================================
--- clang/lib/Basic/Targets/AArch64.h
+++ clang/lib/Basic/Targets/AArch64.h
@@ -89,6 +89,8 @@
   }
 
   int getEHDataRegisterNumber(unsigned RegNo) const override;
+
+  bool hasInt128Type() const override;
 };
 
 class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
Index: clang/lib/Basic/Targets/AArch64.cpp
===================================================================
--- clang/lib/Basic/Targets/AArch64.cpp
+++ clang/lib/Basic/Targets/AArch64.cpp
@@ -51,7 +51,11 @@
   HasLegalHalfType = true;
   HasFloat16 = true;
 
-  LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+  if (Triple.isArch64Bit())
+    LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+  else
+    LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
+
   MaxVectorAlign = 128;
   MaxAtomicInlineWidth = 128;
   MaxAtomicPromoteWidth = 128;
@@ -128,7 +132,7 @@
     Builder.defineMacro("__ELF__");
 
   // Target properties.
-  if (!getTriple().isOSWindows()) {
+  if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
     Builder.defineMacro("_LP64");
     Builder.defineMacro("__LP64__");
   }
@@ -447,14 +451,19 @@
   return -1;
 }
 
+bool AArch64TargetInfo::hasInt128Type() const { return true; }
+
 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
                                          const TargetOptions &Opts)
     : AArch64TargetInfo(Triple, Opts) {}
 
 void AArch64leTargetInfo::setDataLayout() {
-  if (getTriple().isOSBinFormatMachO())
-    resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
-  else
+  if (getTriple().isOSBinFormatMachO()) {
+    if(getTriple().isArch32Bit())
+      resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128");
+    else
+      resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
+  } else
     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
 }
 
@@ -578,19 +587,34 @@
                                                  const TargetOptions &Opts)
     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
   Int64Type = SignedLongLong;
+  if (getTriple().isArch32Bit())
+    IntMaxType = SignedLongLong;
+
+  WCharType = SignedInt;
   UseSignedCharForObjCBool = false;
 
   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
 
-  TheCXXABI.set(TargetCXXABI::iOS64);
+  UseZeroLengthBitfieldAlignment = false;
+
+  if (getTriple().isArch32Bit()) {
+    UseBitFieldTypeAlignment = false;
+    ZeroLengthBitfieldBoundary = 32;
+    UseZeroLengthBitfieldAlignment = true;
+    TheCXXABI.set(TargetCXXABI::WatchOS);
+  } else
+    TheCXXABI.set(TargetCXXABI::iOS64);
 }
 
 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
                                            const llvm::Triple &Triple,
                                            MacroBuilder &Builder) const {
   Builder.defineMacro("__AARCH64_SIMD__");
-  Builder.defineMacro("__ARM64_ARCH_8__");
+  if (Triple.isArch32Bit())
+    Builder.defineMacro("__ARM64_ARCH_8_32__");
+  else
+    Builder.defineMacro("__ARM64_ARCH_8__");
   Builder.defineMacro("__ARM_NEON__");
   Builder.defineMacro("__LITTLE_ENDIAN__");
   Builder.defineMacro("__REGISTER_PREFIX__", "");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to