rsandifo-arm updated this revision to Diff 207991.
rsandifo-arm added a comment.

Changes since last version:

- Define the SVE types only for AArch64 targets
- Use the vendor extension 'u' mangling, as per the spec
- Report an error for @encode on the types
- Fixed the licence text on the new file
- Added more tests

Although I'd originally posted the patch so that the sizeless type
support had specific types to test, it'd be really useful if the patch
could go in independently of the sizeless type stuff, since the
patch contains the common subset of functionality needed by the
sizeless type patches and by the implementation of the intrinsics
(which apart from this patch are essentially separate pieces of work).


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62960/new/

https://reviews.llvm.org/D62960

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/Type.h
  include/clang/Basic/AArch64SVEACLETypes.def
  include/clang/Basic/TargetInfo.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/PrintfFormatString.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Basic/TargetInfo.cpp
  lib/Basic/Targets/AArch64.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/AST/ast-dump-aarch64-sve-types.c
  test/CodeGen/aarch64-sve.c
  test/CodeGenCXX/aarch64-mangle-sve-vectors-msvc.cpp
  test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp
  test/CodeGenCXX/aarch64-sve-typeinfo.cpp
  test/CodeGenObjC/aarch64-sve-types.m
  test/PCH/aarch64-sve-types.c
  test/Sema/aarch64-sve-types.c
  test/SemaObjC/aarch64-sve-types.m
  tools/libclang/CIndex.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===================================================================
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -4574,6 +4574,44 @@
   EXPECT_EQ(Imported->getPreviousDecl(), Friend);
 }
 
+struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
+
+TEST_P(SVEBuiltins, ImportTypes) {
+  static const char *const TypeNames[] = {
+    "__SVInt8_t",
+    "__SVInt16_t",
+    "__SVInt32_t",
+    "__SVInt64_t",
+    "__SVUint8_t",
+    "__SVUint16_t",
+    "__SVUint32_t",
+    "__SVUint64_t",
+    "__SVFloat16_t",
+    "__SVFloat32_t",
+    "__SVFloat64_t",
+    "__SVBool_t"
+  };
+
+  TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX);
+  TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX, "input.cc");
+  for (auto *TypeName : TypeNames) {
+    auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
+      ToTU, typedefDecl(hasName(TypeName)));
+    QualType ToType = ToTypedef->getUnderlyingType();
+
+    auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
+      FromTU, typedefDecl(hasName(TypeName)));
+    QualType FromType = FromTypedef->getUnderlyingType();
+
+    QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX);
+    EXPECT_EQ(ImportedType, ToType);
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
+                        ::testing::Values(ArgVector{"-target",
+                                                    "aarch64-linux-gnu"}), );
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
                         DefaultTestValuesForRunOptions, );
 
Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1527,6 +1527,9 @@
   case BuiltinType::OCLClkEvent:
   case BuiltinType::OCLQueue:
   case BuiltinType::OCLReserveID:
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
 #define BUILTIN_TYPE(Id, SingletonId)
 #define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
 #define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
Index: test/SemaObjC/aarch64-sve-types.m
===================================================================
--- /dev/null
+++ test/SemaObjC/aarch64-sve-types.m
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsyntax-only -verify %s
+
+// Check that we don't abort when SVE types are made nullable.  This
+// interface is invalid anyway, but we won't diagnose that until the
+// sizeless type extension is added.
+@interface foo
+@property(nullable) __SVInt8_t s8; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVInt16_t s16; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVInt32_t s32; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVInt64_t s64; // expected-error {{cannot be applied to non-pointer type}}
+
+@property(nullable) __SVUint8_t u8; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVUint16_t u16; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVUint32_t u32; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVUint64_t u64; // expected-error {{cannot be applied to non-pointer type}}
+
+@property(nullable) __SVFloat16_t f16; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVFloat32_t f32; // expected-error {{cannot be applied to non-pointer type}}
+@property(nullable) __SVFloat64_t f64; // expected-error {{cannot be applied to non-pointer type}}
+
+@property(nullable) __SVBool_t b8; // expected-error {{cannot be applied to non-pointer type}}
+@end
Index: test/Sema/aarch64-sve-types.c
===================================================================
--- /dev/null
+++ test/Sema/aarch64-sve-types.c
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 %s -triple aarch64-none-linux-gnu -target-feature +sve -fsyntax-only -verify
+
+// This test is invalid under the sizeless type extension and is a stop-gap
+// until that extension is added.  The test makes sure that sizeof and
+// alignof queries are handled without assertion failures, since at
+// present there is nothing to prevent such queries being made.
+//
+// Under this scheme, sizeof returns 0 for all built-in sizeless types.
+// This is compatible with correct usage but it relies on the user being
+// careful to avoid constructs that rely directly or indirectly on the
+// value of sizeof.  (The sizeless type extension avoids this by treating
+// such constructs as an error.)
+
+// expected-no-diagnostics
+
+void f() {
+  int size_s8[sizeof(__SVInt8_t) == 0 ? 1 : -1];
+  int align_s8[__alignof__(__SVInt8_t) == 16 ? 1 : -1];
+
+  int size_s16[sizeof(__SVInt16_t) == 0 ? 1 : -1];
+  int align_s16[__alignof__(__SVInt16_t) == 16 ? 1 : -1];
+
+  int size_s32[sizeof(__SVInt32_t) == 0 ? 1 : -1];
+  int align_s32[__alignof__(__SVInt32_t) == 16 ? 1 : -1];
+
+  int size_s64[sizeof(__SVInt64_t) == 0 ? 1 : -1];
+  int align_s64[__alignof__(__SVInt64_t) == 16 ? 1 : -1];
+
+  int size_u8[sizeof(__SVUint8_t) == 0 ? 1 : -1];
+  int align_u8[__alignof__(__SVUint8_t) == 16 ? 1 : -1];
+
+  int size_u16[sizeof(__SVUint16_t) == 0 ? 1 : -1];
+  int align_u16[__alignof__(__SVUint16_t) == 16 ? 1 : -1];
+
+  int size_u32[sizeof(__SVUint32_t) == 0 ? 1 : -1];
+  int align_u32[__alignof__(__SVUint32_t) == 16 ? 1 : -1];
+
+  int size_u64[sizeof(__SVUint64_t) == 0 ? 1 : -1];
+  int align_u64[__alignof__(__SVUint64_t) == 16 ? 1 : -1];
+
+  int size_f16[sizeof(__SVFloat16_t) == 0 ? 1 : -1];
+  int align_f16[__alignof__(__SVFloat16_t) == 16 ? 1 : -1];
+
+  int size_f32[sizeof(__SVFloat32_t) == 0 ? 1 : -1];
+  int align_f32[__alignof__(__SVFloat32_t) == 16 ? 1 : -1];
+
+  int size_f64[sizeof(__SVFloat64_t) == 0 ? 1 : -1];
+  int align_f64[__alignof__(__SVFloat64_t) == 16 ? 1 : -1];
+
+  int size_b8[sizeof(__SVBool_t) == 0 ? 1 : -1];
+  int align_b8[__alignof__(__SVBool_t) == 2 ? 1 : -1];
+}
Index: test/PCH/aarch64-sve-types.c
===================================================================
--- /dev/null
+++ test/PCH/aarch64-sve-types.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -include-pch %t \
+// RUN:   -fsyntax-only -verify %s
+
+// expected-no-diagnostics
+
+__SVInt8_t *s8;
+__SVInt16_t *s16;
+__SVInt32_t *s32;
+__SVInt64_t *s64;
+
+__SVUint8_t *u8;
+__SVUint16_t *u16;
+__SVUint32_t *u32;
+__SVUint64_t *u64;
+
+__SVFloat16_t *f16;
+__SVFloat32_t *f32;
+__SVFloat64_t *f64;
+
+__SVBool_t *b8;
Index: test/CodeGenObjC/aarch64-sve-types.m
===================================================================
--- /dev/null
+++ test/CodeGenObjC/aarch64-sve-types.m
@@ -0,0 +1,32 @@
+// RUN: not %clang_cc1 -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
+// RUN:   2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
+// RUN:   -target-feature +sve 2>&1 | FileCheck %s
+
+// CHECK: error: cannot yet @encode type __SVInt8_t
+const char s8[] = @encode(__SVInt8_t);
+// CHECK: error: cannot yet @encode type __SVInt16_t
+const char s16[] = @encode(__SVInt16_t);
+// CHECK: error: cannot yet @encode type __SVInt32_t
+const char s32[] = @encode(__SVInt32_t);
+// CHECK: error: cannot yet @encode type __SVInt64_t
+const char s64[] = @encode(__SVInt64_t);
+
+// CHECK: error: cannot yet @encode type __SVUint8_t
+const char u8[] = @encode(__SVUint8_t);
+// CHECK: error: cannot yet @encode type __SVUint16_t
+const char u16[] = @encode(__SVUint16_t);
+// CHECK: error: cannot yet @encode type __SVUint32_t
+const char u32[] = @encode(__SVUint32_t);
+// CHECK: error: cannot yet @encode type __SVUint64_t
+const char u64[] = @encode(__SVUint64_t);
+
+// CHECK: error: cannot yet @encode type __SVFloat16_t
+const char f16[] = @encode(__SVFloat16_t);
+// CHECK: error: cannot yet @encode type __SVFloat32_t
+const char f32[] = @encode(__SVFloat32_t);
+// CHECK: error: cannot yet @encode type __SVFloat64_t
+const char f64[] = @encode(__SVFloat64_t);
+
+// CHECK: error: cannot yet @encode type __SVBool_t
+const char b8[] = @encode(__SVBool_t);
Index: test/CodeGenCXX/aarch64-sve-typeinfo.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/aarch64-sve-typeinfo.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
+// RUN:   | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
+// RUN:   -target-feature +sve | FileCheck %s
+
+namespace std { class type_info; };
+
+auto &s8 = typeid(__SVInt8_t);
+auto &s16 = typeid(__SVInt16_t);
+auto &s32 = typeid(__SVInt32_t);
+auto &s64 = typeid(__SVInt64_t);
+
+auto &u8 = typeid(__SVUint8_t);
+auto &u16 = typeid(__SVUint16_t);
+auto &u32 = typeid(__SVUint32_t);
+auto &u64 = typeid(__SVUint64_t);
+
+auto &f16 = typeid(__SVFloat16_t);
+auto &f32 = typeid(__SVFloat32_t);
+auto &f64 = typeid(__SVFloat64_t);
+
+auto &b8 = typeid(__SVBool_t);
+
+// CHECK-DAG: @_ZTSu10__SVInt8_t = {{.*}} c"u10__SVInt8_t\00"
+// CHECK-DAG: @_ZTIu10__SVInt8_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu10__SVInt8_t
+
+// CHECK-DAG: @_ZTSu11__SVInt16_t = {{.*}} c"u11__SVInt16_t\00"
+// CHECK-DAG: @_ZTIu11__SVInt16_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu11__SVInt16_t
+
+// CHECK-DAG: @_ZTSu11__SVInt32_t = {{.*}} c"u11__SVInt32_t\00"
+// CHECK-DAG: @_ZTIu11__SVInt32_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu11__SVInt32_t
+
+// CHECK-DAG: @_ZTSu11__SVInt64_t = {{.*}} c"u11__SVInt64_t\00"
+// CHECK-DAG: @_ZTIu11__SVInt64_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu11__SVInt64_t
+
+// CHECK-DAG: @_ZTSu11__SVUint8_t = {{.*}} c"u11__SVUint8_t\00"
+// CHECK-DAG: @_ZTIu11__SVUint8_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu11__SVUint8_t
+
+// CHECK-DAG: @_ZTSu12__SVUint16_t = {{.*}} c"u12__SVUint16_t\00"
+// CHECK-DAG: @_ZTIu12__SVUint16_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu12__SVUint16_t
+
+// CHECK-DAG: @_ZTSu12__SVUint32_t = {{.*}} c"u12__SVUint32_t\00"
+// CHECK-DAG: @_ZTIu12__SVUint32_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu12__SVUint32_t
+
+// CHECK-DAG: @_ZTSu12__SVUint64_t = {{.*}} c"u12__SVUint64_t\00"
+// CHECK-DAG: @_ZTIu12__SVUint64_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu12__SVUint64_t
+
+// CHECK-DAG: @_ZTSu13__SVFloat16_t = {{.*}} c"u13__SVFloat16_t\00"
+// CHECK-DAG: @_ZTIu13__SVFloat16_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu13__SVFloat16_t
+
+// CHECK-DAG: @_ZTSu13__SVFloat32_t = {{.*}} c"u13__SVFloat32_t\00"
+// CHECK-DAG: @_ZTIu13__SVFloat32_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu13__SVFloat32_t
+
+// CHECK-DAG: @_ZTSu13__SVFloat64_t = {{.*}} c"u13__SVFloat64_t\00"
+// CHECK-DAG: @_ZTIu13__SVFloat64_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu13__SVFloat64_t
+
+// CHECK-DAG: @_ZTSu10__SVBool_t = {{.*}} c"u10__SVBool_t\00"
+// CHECK-DAG: @_ZTIu10__SVBool_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu10__SVBool_t
Index: test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
+// RUN:   | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
+// RUN:   -target-feature +sve | FileCheck %s
+
+template<typename T> struct S {};
+
+// CHECK: _Z2f11SIu10__SVInt8_tE
+void f1(S<__SVInt8_t>) {}
+// CHECK: _Z2f21SIu11__SVInt16_tE
+void f2(S<__SVInt16_t>) {}
+// CHECK: _Z2f31SIu11__SVInt32_tE
+void f3(S<__SVInt32_t>) {}
+// CHECK: _Z2f41SIu11__SVInt64_tE
+void f4(S<__SVInt64_t>) {}
+// CHECK: _Z2f51SIu11__SVUint8_tE
+void f5(S<__SVUint8_t>) {}
+// CHECK: _Z2f61SIu12__SVUint16_tE
+void f6(S<__SVUint16_t>) {}
+// CHECK: _Z2f71SIu12__SVUint32_tE
+void f7(S<__SVUint32_t>) {}
+// CHECK: _Z2f81SIu12__SVUint64_tE
+void f8(S<__SVUint64_t>) {}
+// CHECK: _Z2f91SIu13__SVFloat16_tE
+void f9(S<__SVFloat16_t>) {}
+// CHECK: _Z3f101SIu13__SVFloat32_tE
+void f10(S<__SVFloat32_t>) {}
+// CHECK: _Z3f111SIu13__SVFloat64_tE
+void f11(S<__SVFloat64_t>) {}
+// CHECK: _Z3f121SIu10__SVBool_tE
+void f12(S<__SVBool_t>) {}
Index: test/CodeGenCXX/aarch64-mangle-sve-vectors-msvc.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/aarch64-mangle-sve-vectors-msvc.cpp
@@ -0,0 +1,7 @@
+// RUN: not %clang_cc1 -triple aarch64-unknown-windows-msvc %s -emit-llvm \
+// RUN:   -o - 2>&1 | FileCheck %s
+
+template<typename T> struct S {};
+
+// CHECK: cannot mangle this built-in __SVInt8_t type yet
+void f1(S<__SVInt8_t>) {}
Index: test/CodeGen/aarch64-sve.c
===================================================================
--- /dev/null
+++ test/CodeGen/aarch64-sve.c
@@ -0,0 +1,9 @@
+// RUN: not %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
+// RUN:  -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s
+
+// Placeholder test for SVE types
+
+// CHECK: cannot yet generate code for SVE type '__SVInt8_t'
+// CHECK: cannot yet generate debug info for SVE type '__SVInt8_t'
+
+__SVInt8_t *ptr;
Index: test/AST/ast-dump-aarch64-sve-types.c
===================================================================
--- /dev/null
+++ test/AST/ast-dump-aarch64-sve-types.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -ast-dump \
+// RUN:   -ast-dump-filter __SV %s | FileCheck %s
+
+// CHECK: TypedefDecl {{.*}} implicit __SVInt8_t '__SVInt8_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVInt8_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVInt16_t '__SVInt16_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVInt16_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVInt32_t '__SVInt32_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVInt32_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVInt64_t '__SVInt64_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVInt64_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVUint8_t '__SVUint8_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVUint8_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVUint16_t '__SVUint16_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVUint16_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVUint32_t '__SVUint32_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVUint32_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVUint64_t '__SVUint64_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVUint64_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVFloat16_t '__SVFloat16_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVFloat16_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVFloat32_t '__SVFloat32_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVFloat32_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVFloat64_t '__SVFloat64_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVFloat64_t'
+
+// CHECK: TypedefDecl {{.*}} implicit __SVBool_t '__SVBool_t'
+// CHECK-NEXT: -BuiltinType {{.*}} '__SVBool_t'
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -7037,6 +7037,12 @@
     case PREDEF_TYPE_OMP_ARRAY_SECTION:
       T = Context.OMPArraySectionTy;
       break;
+    // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) \
+    case PREDEF_TYPE_##Id##_ID: \
+      T = Context.SingletonId; \
+      break;
+#include "clang/Basic/AArch64SVEACLETypes.def"
     }
 
     assert(!T.isNull() && "Unknown predefined type");
Index: lib/Serialization/ASTCommon.cpp
===================================================================
--- lib/Serialization/ASTCommon.cpp
+++ lib/Serialization/ASTCommon.cpp
@@ -232,6 +232,12 @@
   case BuiltinType::OCLReserveID:
     ID = PREDEF_TYPE_RESERVE_ID_ID;
     break;
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) \
+  case BuiltinType::Id: \
+    ID = PREDEF_TYPE_##Id##_ID; \
+    break;
+#include "clang/Basic/AArch64SVEACLETypes.def"
   case BuiltinType::BuiltinFn:
     ID = PREDEF_TYPE_BUILTIN_FN;
     break;
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -5243,6 +5243,10 @@
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
   case BuiltinType::Id:
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types.  In practice we'll never use this, since all SVE types are
+  // sugared via TypedefTypes rather than exposed directly as BuiltinTypes.
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
 #define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
 #define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
 #include "clang/AST/BuiltinTypes.def"
@@ -17049,6 +17053,9 @@
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
   case BuiltinType::Id:
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
 #define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id:
 #define PLACEHOLDER_TYPE(Id, SingletonId)
 #include "clang/AST/BuiltinTypes.def"
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -336,7 +336,14 @@
     addImplicitTypedef(#ExtType, Context.Id##Ty); \
     setOpenCLExtensionForType(Context.Id##Ty, #Ext);
 #include "clang/Basic/OpenCLExtensionTypes.def"
-    };
+  }
+
+  // SVE Types
+  if (Context.getTargetInfo().hasAArch64SVETypes()) {
+#define SVE_TYPE(Name, Id, SingletonId) \
+    addImplicitTypedef(Name, Context.SingletonId);
+#include "clang/Basic/AArch64SVEACLETypes.def"
+  }
 
   if (Context.getTargetInfo().hasBuiltinMSVaList()) {
     DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
Index: lib/Index/USRGeneration.cpp
===================================================================
--- lib/Index/USRGeneration.cpp
+++ lib/Index/USRGeneration.cpp
@@ -724,6 +724,9 @@
         case BuiltinType::OCLQueue:
         case BuiltinType::OCLReserveID:
         case BuiltinType::OCLSampler:
+        // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
         case BuiltinType::ShortAccum:
         case BuiltinType::Accum:
         case BuiltinType::LongAccum:
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -2842,6 +2842,9 @@
     case BuiltinType::OCLClkEvent:
     case BuiltinType::OCLQueue:
     case BuiltinType::OCLReserveID:
+    // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
     case BuiltinType::ShortAccum:
     case BuiltinType::Accum:
     case BuiltinType::LongAccum:
Index: lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- lib/CodeGen/CodeGenTypes.cpp
+++ lib/CodeGen/CodeGenTypes.cpp
@@ -511,6 +511,21 @@
     case BuiltinType::OCLReserveID:
       ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
       break;
+    // SVE Types
+    // TODO: Implement real support.
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
+    {
+      unsigned DiagID = CGM.getDiags().getCustomDiagID(
+          DiagnosticsEngine::Error,
+          "cannot yet generate code for SVE type '%0'");
+      auto *BT = cast<BuiltinType>(Ty);
+      auto Name = BT->getName(CGM.getContext().getPrintingPolicy());
+      CGM.getDiags().Report(DiagID) << Name;
+      /* Return something safe.  */
+      ResultType = llvm::IntegerType::get(getLLVMContext(), 32);
+      break;
+    }
 
     case BuiltinType::Dependent:
 #define BUILTIN_TYPE(Id, SingletonId)
Index: lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -700,6 +700,19 @@
   case BuiltinType::Id: \
     return getOrCreateStructPtrType("opencl_" #ExtType, Id##Ty);
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types
+  // TODO: Implement real support.
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
+  {
+    unsigned DiagID = CGM.getDiags().getCustomDiagID(
+        DiagnosticsEngine::Error,
+        "cannot yet generate debug info for SVE type '%0'");
+    auto Name = BT->getName(CGM.getContext().getPrintingPolicy());
+    CGM.getDiags().Report(DiagID) << Name;
+    /* Return something safe.  */
+    return CreateType(cast<const BuiltinType>(CGM.getContext().IntTy));
+  }
 
   case BuiltinType::UChar:
   case BuiltinType::Char_U:
Index: lib/Basic/Targets/AArch64.cpp
===================================================================
--- lib/Basic/Targets/AArch64.cpp
+++ lib/Basic/Targets/AArch64.cpp
@@ -62,6 +62,16 @@
   // Make __builtin_ms_va_list available.
   HasBuiltinMSVaList = true;
 
+  // Make the SVE types available.  Note that this deliberately doesn't
+  // depend on SveMode, since in principle it should be possible to turn
+  // SVE on and off within a translation unit.  It should also be possible
+  // to compile the global declaration:
+  //
+  // __SVInt8_t *ptr;
+  //
+  // even without SVE.
+  HasAArch64SVETypes = true;
+
   // {} in inline assembly are neon specifiers, not assembly variant
   // specifiers.
   NoAsmVariants = true;
Index: lib/Basic/TargetInfo.cpp
===================================================================
--- lib/Basic/TargetInfo.cpp
+++ lib/Basic/TargetInfo.cpp
@@ -111,6 +111,7 @@
   HasAlignMac68kSupport = false;
   HasBuiltinMSVaList = false;
   IsRenderScriptTarget = false;
+  HasAArch64SVETypes = false;
 
   // Default to no types using fpret.
   RealTypeUsesObjCFPRet = 0;
Index: lib/AST/TypeLoc.cpp
===================================================================
--- lib/AST/TypeLoc.cpp
+++ lib/AST/TypeLoc.cpp
@@ -391,6 +391,9 @@
   case BuiltinType::OCLClkEvent:
   case BuiltinType::OCLQueue:
   case BuiltinType::OCLReserveID:
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
   case BuiltinType::BuiltinFn:
   case BuiltinType::OMPArraySection:
     return TST_unspecified;
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -2885,6 +2885,11 @@
   case Id: \
     return #ExtType;
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) \
+  case Id: \
+    return Name;
+#include "clang/Basic/AArch64SVEACLETypes.def"
   }
 
   llvm_unreachable("Invalid builtin type.");
@@ -3885,6 +3890,9 @@
     case BuiltinType::OCLClkEvent:
     case BuiltinType::OCLQueue:
     case BuiltinType::OCLReserveID:
+    // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
     case BuiltinType::BuiltinFn:
     case BuiltinType::NullPtr:
     case BuiltinType::OMPArraySection:
Index: lib/AST/PrintfFormatString.cpp
===================================================================
--- lib/AST/PrintfFormatString.cpp
+++ lib/AST/PrintfFormatString.cpp
@@ -769,6 +769,9 @@
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
   case BuiltinType::Id:
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
 #define SIGNED_TYPE(Id, SingletonId)
 #define UNSIGNED_TYPE(Id, SingletonId)
 #define FLOATING_TYPE(Id, SingletonId)
Index: lib/AST/NSAPI.cpp
===================================================================
--- lib/AST/NSAPI.cpp
+++ lib/AST/NSAPI.cpp
@@ -482,6 +482,9 @@
   case BuiltinType::OCLClkEvent:
   case BuiltinType::OCLQueue:
   case BuiltinType::OCLReserveID:
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
   case BuiltinType::BoundMember:
   case BuiltinType::Dependent:
   case BuiltinType::Overload:
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -2068,6 +2068,9 @@
     mangleArtificialTagType(TTK_Struct, "_Half", {"__clang"});
     break;
 
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
   case BuiltinType::ShortAccum:
   case BuiltinType::Accum:
   case BuiltinType::LongAccum:
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -2666,6 +2666,13 @@
     Out << type_name.size() << type_name; \
     break;
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) \
+  case BuiltinType::Id: \
+    type_name = Name; \
+    Out << 'u' << type_name.size() << type_name; \
+    break;
+#include "clang/Basic/AArch64SVEACLETypes.def"
   }
 }
 
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -8483,6 +8483,9 @@
     case BuiltinType::OCLClkEvent:
     case BuiltinType::OCLQueue:
     case BuiltinType::OCLReserveID:
+    // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
       return GCCTypeClass::None;
 
     case BuiltinType::Dependent:
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -959,6 +959,11 @@
   case BuiltinType::Id: \
     return Importer.getToContext().Id##Ty;
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) \
+  case BuiltinType::Id: \
+    return Importer.getToContext().SingletonId;
+#include "clang/Basic/AArch64SVEACLETypes.def"
 #define SHARED_SINGLETON_TYPE(Expansion)
 #define BUILTIN_TYPE(Id, SingletonId) \
   case BuiltinType::Id: return Importer.getToContext().SingletonId;
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -1296,6 +1296,13 @@
 #include "clang/Basic/OpenCLExtensionTypes.def"
   }
 
+  // SVE Types
+  if (Target.hasAArch64SVETypes()) {
+#define SVE_TYPE(Name, Id, SingletonId) \
+    InitBuiltinType(SingletonId, BuiltinType::Id);
+#include "clang/Basic/AArch64SVEACLETypes.def"
+  }
+
   // Builtin type for __objc_yes and __objc_no
   ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
                        SignedCharTy : BoolTy);
@@ -1946,13 +1953,25 @@
     case BuiltinType::Id:
 #include "clang/Basic/OpenCLImageTypes.def"
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
-  case BuiltinType::Id:
+    case BuiltinType::Id:
 #include "clang/Basic/OpenCLExtensionTypes.def"
       AS = getTargetAddressSpace(
           Target->getOpenCLTypeAddrSpace(getOpenCLTypeKind(T)));
       Width = Target->getPointerWidth(AS);
       Align = Target->getPointerAlign(AS);
       break;
+    // SVE Types
+#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\
+    case BuiltinType::Id: \
+      Width = 0; \
+      Align = 128; \
+      break;
+#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind) \
+    case BuiltinType::Id: \
+      Width = 0; \
+      Align = 16; \
+      break;
+#include "clang/Basic/AArch64SVEACLETypes.def"
     }
     break;
   case Type::ObjCObjectPointer:
@@ -6538,8 +6557,9 @@
                              /*Field=*/nullptr);
 }
 
-static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
-                                            BuiltinType::Kind kind) {
+static char getObjCEncodingForPrimitiveType(const ASTContext *C,
+                                            const BuiltinType *BT) {
+    BuiltinType::Kind kind = BT->getKind();
     switch (kind) {
     case BuiltinType::Void:       return 'v';
     case BuiltinType::Bool:       return 'B';
@@ -6599,6 +6619,17 @@
       // FIXME: potentially need @encodes for these!
       return ' ';
 
+    // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
+    {
+      DiagnosticsEngine &Diags = C->getDiagnostics();
+      unsigned DiagID = Diags.getCustomDiagID(
+          DiagnosticsEngine::Error, "cannot yet @encode type %0");
+      Diags.Report(DiagID) << BT->getName(C->getPrintingPolicy());
+      return ' ';
+    }
+
     case BuiltinType::ObjCId:
     case BuiltinType::ObjCClass:
     case BuiltinType::ObjCSel:
@@ -6635,7 +6666,7 @@
 
   // The encoding of a fixed enum type matches its fixed underlying type.
   const auto *BT = Enum->getIntegerType()->castAs<BuiltinType>();
-  return getObjCEncodingForPrimitiveKind(C, BT->getKind());
+  return getObjCEncodingForPrimitiveType(C, BT);
 }
 
 static void EncodeBitField(const ASTContext *Ctx, std::string& S,
@@ -6675,7 +6706,7 @@
       S += ObjCEncodingForEnumType(Ctx, ET);
     else {
       const auto *BT = T->castAs<BuiltinType>();
-      S += getObjCEncodingForPrimitiveKind(Ctx, BT->getKind());
+      S += getObjCEncodingForPrimitiveType(Ctx, BT);
     }
   }
   S += llvm::utostr(FD->getBitWidthValue(*Ctx));
@@ -6693,7 +6724,7 @@
     if (FD && FD->isBitField())
       return EncodeBitField(this, S, T, FD);
     if (const auto *BT = dyn_cast<BuiltinType>(CT))
-      S += getObjCEncodingForPrimitiveKind(this, BT->getKind());
+      S += getObjCEncodingForPrimitiveType(this, BT);
     else
       S += ObjCEncodingForEnumType(this, cast<EnumType>(CT));
     return;
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -1018,6 +1018,9 @@
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
       PREDEF_TYPE_##Id##_ID,
 #include "clang/Basic/OpenCLExtensionTypes.def"
+      // \brief SVE types with auto numeration
+#define SVE_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
+#include "clang/Basic/AArch64SVEACLETypes.def"
     };
 
     /// The number of predefined type IDs that are reserved for
Index: include/clang/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h
+++ include/clang/Basic/TargetInfo.h
@@ -193,6 +193,8 @@
 
   unsigned IsRenderScriptTarget : 1;
 
+  unsigned HasAArch64SVETypes : 1;
+
   // TargetInfo Constructor.  Default initializes all fields.
   TargetInfo(const llvm::Triple &T);
 
@@ -787,6 +789,10 @@
   /// Returns true for RenderScript.
   bool isRenderScriptTarget() const { return IsRenderScriptTarget; }
 
+  /// Returns whether or not the AArch64 SVE built-in types are
+  /// available on this target.
+  bool hasAArch64SVETypes() const { return HasAArch64SVETypes; }
+
   /// Returns whether the passed in string is a valid clobber in an
   /// inline asm statement.
   ///
Index: include/clang/Basic/AArch64SVEACLETypes.def
===================================================================
--- /dev/null
+++ include/clang/Basic/AArch64SVEACLETypes.def
@@ -0,0 +1,70 @@
+//===-- AArch64SVEACLETypes.def - Metadata about SVE types ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines various SVE builtin types.  The macros are:
+//
+//    SVE_TYPE(Name, Id, SingletonId) - A builtin type that has not been
+//    covered by any other #define.  Defining this macro covers all
+//    the builtins.
+//
+//    SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP) -
+//    An SVE scalable vector.
+//
+//    SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind) - An SVE scalable
+//    predicate.
+//
+// where:
+//
+//  - Name is the name of the builtin type.
+//
+//  - BuiltinType::Id is the enumerator defining the type.
+//
+//  - Context.SingletonId is the global singleton of this type.
+//
+//  - ElKind enumerates the type of the elements.
+//
+//  - ElBits is the size of one element in bits.
+//
+//  - IsSigned is true for vectors of signed integer elements and
+//    for vectors of floating-point elements.
+//
+//  - IsFP is true for vectors of floating-point elements.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SVE_VECTOR_TYPE
+#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\
+  SVE_TYPE(Name, Id, SingletonId)
+#endif
+
+#ifndef SVE_PREDICATE_TYPE
+#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind)\
+  SVE_TYPE(Name, Id, SingletonId)
+#endif
+
+//===- Vector point types -----------------------------------------------===//
+
+SVE_VECTOR_TYPE("__SVInt8_t",  SveInt8, SveInt8Ty, SveElSInt8, 8, true, false)
+SVE_VECTOR_TYPE("__SVInt16_t", SveInt16, SveInt16Ty, SveElSInt16, 16, true, false)
+SVE_VECTOR_TYPE("__SVInt32_t", SveInt32, SveInt32Ty, SveElSInt32, 32, true, false)
+SVE_VECTOR_TYPE("__SVInt64_t", SveInt64, SveInt64Ty, SveElSInt64, 64, true, false)
+
+SVE_VECTOR_TYPE("__SVUint8_t",  SveUint8, SveUint8Ty, SveElUInt8, 8, false, false)
+SVE_VECTOR_TYPE("__SVUint16_t", SveUint16, SveUint16Ty, SveElUInt16, 16, false, false)
+SVE_VECTOR_TYPE("__SVUint32_t", SveUint32, SveUint32Ty, SveElUInt32, 32, false, false)
+SVE_VECTOR_TYPE("__SVUint64_t", SveUint64, SveUint64Ty, SveElUInt64, 64, false, false)
+
+SVE_VECTOR_TYPE("__SVFloat16_t", SveFloat16, SveFloat16Ty, SveElHalf, 16, true, true)
+SVE_VECTOR_TYPE("__SVFloat32_t", SveFloat32, SveFloat32Ty, SveElFloat, 32, true, true)
+SVE_VECTOR_TYPE("__SVFloat64_t", SveFloat64, SveFloat64Ty, SveElDouble, 64, true, true)
+
+SVE_PREDICATE_TYPE("__SVBool_t", SveBool, SveBoolTy, SveElBool)
+
+#undef SVE_VECTOR_TYPE
+#undef SVE_PREDICATE_TYPE
+#undef SVE_TYPE
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -2409,6 +2409,9 @@
 // OpenCL extension types
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) Id,
 #include "clang/Basic/OpenCLExtensionTypes.def"
+// SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) Id,
+#include "clang/Basic/AArch64SVEACLETypes.def"
 // All other builtin types
 #define BUILTIN_TYPE(Id, SingletonId) Id,
 #define LAST_BUILTIN_TYPE(Id) LastKind = Id
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1051,6 +1051,9 @@
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
   CanQualType Id##Ty;
 #include "clang/Basic/OpenCLExtensionTypes.def"
+  // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
+#include "clang/Basic/AArch64SVEACLETypes.def"
 
   // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
   mutable QualType AutoDeductTy;     // Deduction against 'auto'.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to