[clang] [WIP][CLANG][AArch64] Add the modal 8 bit floating-point scalar type (PR #97277)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 1 03:21:34 PDT 2024


https://github.com/CarolineConcatto created https://github.com/llvm/llvm-project/pull/97277

ARM ACLE PR#323[1] adds new modal types for 8-bit floating point intrinsic.

>From the PR#323:
```
ACLE defines the `__fpm8` type, which can be used for the E5M2 and E4M3
8-bit floating-point formats. It is a storage and interchange only type
with no arithmetic operations other than intrinsic calls.
````

The type should be an opaque type and its format in undefined in Clang. Only defined in the backend by a status/format register, for AArch64 the FPMR.

This patch is an attempt to the add the fpm8_t scalar type. It has a parser and codegen for the new scalar type.

The patch it is lowering to and 8bit unsigned as it has no format. But maybe we should add another opaque type.

[1]  https://github.com/ARM-software/acle/pull/323

>From fbeca5c357b1a5589757bbb2cac8208f8c9027ab Mon Sep 17 00:00:00 2001
From: Caroline Concatto <caroline.concatto at arm.com>
Date: Mon, 24 Jun 2024 09:59:24 +0000
Subject: [PATCH] [WIP][CLANG][AArch64] Add the  modal 8 bit floating-point
 scalar type

ARM ACLE PR#323[1] adds new modal types for 8-bit floating point intrinsic.

>From the PR#323:
```
ACLE defines the `__fpm8` type, which can be used for the E5M2 and E4M3
8-bit floating-point formats. It is a storage and interchange only type
with no arithmetic operations other than intrinsic calls.
````

The type should be an opaque type and its format in undefined in Clang.
Only defined in the backend by a status/format register, for AArch64 the FPMR.

This patch is an attempt to the add the fpm8_t scalar type.
It has a parser and codegen for the new scalar type.

The patch it is lowering to and 8bit unsigned as it has no format.
But maybe we should add another opaque type.

[1]  https://github.com/ARM-software/acle/pull/323
---
 clang/include/clang/AST/ASTContext.h          |  1 +
 clang/include/clang/AST/BuiltinTypes.def      |  4 +
 clang/include/clang/AST/Type.h                |  5 +
 clang/include/clang/Basic/Specifiers.h        |  1 +
 clang/include/clang/Basic/TokenKinds.def      |  1 +
 clang/include/clang/Sema/DeclSpec.h           |  1 +
 .../include/clang/Serialization/ASTBitCodes.h |  4 +-
 clang/lib/AST/ASTContext.cpp                  |  7 ++
 clang/lib/AST/ItaniumMangle.cpp               |  1 +
 clang/lib/AST/Type.cpp                        |  2 +
 clang/lib/AST/TypeLoc.cpp                     |  1 +
 clang/lib/CodeGen/CodeGenTypes.cpp            |  4 +-
 clang/lib/CodeGen/ItaniumCXXABI.cpp           |  1 +
 clang/lib/Index/USRGeneration.cpp             |  1 +
 clang/lib/Lex/Lexer.cpp                       |  1 +
 clang/lib/Parse/ParseDecl.cpp                 |  7 ++
 clang/lib/Parse/ParseExpr.cpp                 |  1 +
 clang/lib/Parse/ParseExprCXX.cpp              |  3 +
 clang/lib/Parse/ParseTentative.cpp            |  2 +
 clang/lib/Sema/DeclSpec.cpp                   |  3 +
 clang/lib/Sema/SemaTemplateVariadic.cpp       |  1 +
 clang/lib/Sema/SemaType.cpp                   |  3 +
 clang/lib/Serialization/ASTCommon.cpp         |  3 +
 clang/test/AST/fpm8_opaque.cpp                | 91 +++++++++++++++++++
 clang/test/CodeGen/fpm8_opaque.c              | 24 +++++
 25 files changed, 171 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/AST/fpm8_opaque.cpp
 create mode 100644 clang/test/CodeGen/fpm8_opaque.c

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 53ece996769a8..532ec05ab90a6 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1115,6 +1115,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
   CanQualType SatShortFractTy, SatFractTy, SatLongFractTy;
   CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy,
       SatUnsignedLongFractTy;
+  CanQualType Fpm8Ty;
   CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
   CanQualType BFloat16Ty;
   CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def
index 444be4311a743..0c1cccf4f73b8 100644
--- a/clang/include/clang/AST/BuiltinTypes.def
+++ b/clang/include/clang/AST/BuiltinTypes.def
@@ -221,6 +221,10 @@ FLOATING_TYPE(Float128, Float128Ty)
 // '__ibm128'
 FLOATING_TYPE(Ibm128, Ibm128Ty)
 
+
+// '__fpm8'
+UNSIGNED_TYPE(Fpm8, Fpm8Ty)
+
 //===- Language-specific types --------------------------------------------===//
 
 // This is the type of C++0x 'nullptr'.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index fab233b62d8d1..9f835b8459847 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2492,6 +2492,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
   bool isDoubleType() const;
   bool isBFloat16Type() const;
   bool isFloat128Type() const;
+  bool isFpm8Type() const;
   bool isIbm128Type() const;
   bool isRealType() const;         // C99 6.2.5p17 (real floating + integer)
   bool isArithmeticType() const;   // C99 6.2.5p18 (integer + floating)
@@ -7944,6 +7945,10 @@ inline bool Type::isBFloat16Type() const {
   return isSpecificBuiltinType(BuiltinType::BFloat16);
 }
 
+inline bool Type::isFpm8Type() const {
+  return isSpecificBuiltinType(BuiltinType::Fpm8);
+}
+
 inline bool Type::isFloat128Type() const {
   return isSpecificBuiltinType(BuiltinType::Float128);
 }
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index fb11e8212f8b6..b4db94d273949 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -68,6 +68,7 @@ namespace clang {
     TST_Accum,   // ISO/IEC JTC1 SC22 WG14 N1169 Extension
     TST_Fract,
     TST_BFloat16,
+    TST_Fpm8,
     TST_float,
     TST_double,
     TST_float128,
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 9c4b17465e18a..c08cf760962f3 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -655,6 +655,7 @@ KEYWORD(__bool                      , KEYALTIVEC|KEYZVECTOR)
 // ARM NEON extensions.
 ALIAS("__fp16", half                , KEYALL)
 KEYWORD(__bf16                      , KEYALL)
+KEYWORD(__fpm8                      , KEYALL)
 
 // OpenCL Extension.
 KEYWORD(half                        , HALFSUPPORT)
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 23bc780e04979..097cb8eb642ac 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -287,6 +287,7 @@ class DeclSpec {
   static const TST TST_bitint = clang::TST_bitint;
   static const TST TST_half = clang::TST_half;
   static const TST TST_BFloat16 = clang::TST_BFloat16;
+  static const TST TST_Fpm8 = clang::TST_Fpm8;
   static const TST TST_float = clang::TST_float;
   static const TST TST_double = clang::TST_double;
   static const TST TST_float16 = clang::TST_Float16;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index a4728b1c06b3f..b2853c5e787d6 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1078,6 +1078,8 @@ enum PredefinedTypeIDs {
   /// \brief The '__ibm128' type
   PREDEF_TYPE_IBM128_ID = 74,
 
+  PREDEF_TYPE_FPM8_ID = 75,
+
 /// OpenCL image types with auto numeration
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
   PREDEF_TYPE_##Id##_ID,
@@ -1109,7 +1111,7 @@ enum PredefinedTypeIDs {
 ///
 /// Type IDs for non-predefined types will start at
 /// NUM_PREDEF_TYPE_IDs.
-const unsigned NUM_PREDEF_TYPE_IDS = 503;
+const unsigned NUM_PREDEF_TYPE_IDS = 504;
 
 // Ensure we do not overrun the predefined types we reserved
 // in the enum PredefinedTypeIDs above.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 34aa399fda2f8..7d810c1f8751e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1408,6 +1408,8 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
   // half type (OpenCL 6.1.1.1) / ARM NEON __fp16
   InitBuiltinType(HalfTy, BuiltinType::Half);
 
+  InitBuiltinType(Fpm8Ty, BuiltinType::Fpm8);
+
   InitBuiltinType(BFloat16Ty, BuiltinType::BFloat16);
 
   // Builtin type used to help define __builtin_va_list.
@@ -1977,6 +1979,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
       Width = Target->getBoolWidth();
       Align = Target->getBoolAlign();
       break;
+    case BuiltinType::Fpm8:
     case BuiltinType::Char_S:
     case BuiltinType::Char_U:
     case BuiltinType::UChar:
@@ -8129,6 +8132,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
     case BuiltinType::LongDouble: return 'D';
     case BuiltinType::NullPtr:    return '*'; // like char*
 
+    case BuiltinType::Fpm8:
     case BuiltinType::BFloat16:
     case BuiltinType::Float16:
     case BuiltinType::Float128:
@@ -11466,6 +11470,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
     else
       Type = Context.CharTy;
     break;
+  case '£':
+    Type = Context.Fpm8Ty;
+    break;
   case 'b': // boolean
     assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
     Type = Context.BoolTy;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ed9e6eeb36c75..f974cf1b5f8a8 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3181,6 +3181,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
   case BuiltinType::SChar:
     Out << 'a';
     break;
+  case BuiltinType::Fpm8:
   case BuiltinType::WChar_S:
   case BuiltinType::WChar_U:
     Out << 'w';
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 33acae2cbafac..f629ae6d7b016 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3372,6 +3372,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
     return "unsigned __int128";
   case Half:
     return Policy.Half ? "half" : "__fp16";
+  case Fpm8:
+    return "__fpm8";
   case BFloat16:
     return "__bf16";
   case Float:
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 9dd90d9bf4e54..8df92d3921c44 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -361,6 +361,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
   case BuiltinType::Long:
   case BuiltinType::LongLong:
   case BuiltinType::Int128:
+  case BuiltinType::Fpm8:
   case BuiltinType::Half:
   case BuiltinType::Float:
   case BuiltinType::Double:
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 0a926e4ac27fe..626525f66e3e7 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -419,7 +419,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
                                     Context.getFloatTypeSemantics(T),
                                     /* UseNativeHalf = */ false);
       break;
-
+    case BuiltinType::Fpm8:
+      ResultType = llvm::Type::getInt8Ty(getLLVMContext());
+      break;
     case BuiltinType::NullPtr:
       // Model std::nullptr_t as i8*
       ResultType = llvm::PointerType::getUnqual(getLLVMContext());
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 5a3e83de625c9..8ae3c1c38b3e5 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3331,6 +3331,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
     case BuiltinType::Float:
     case BuiltinType::Double:
     case BuiltinType::LongDouble:
+    case BuiltinType::Fpm8:
     case BuiltinType::Float16:
     case BuiltinType::Float128:
     case BuiltinType::Ibm128:
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 31c4a3345c09d..553b788ee0e75 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -691,6 +691,7 @@ void USRGenerator::VisitType(QualType T) {
           Out << 'v'; break;
         case BuiltinType::Bool:
           Out << 'b'; break;
+        case BuiltinType::Fpm8:
         case BuiltinType::UChar:
           Out << 'c'; break;
         case BuiltinType::Char8:
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..7806ea9d8604f 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -97,6 +97,7 @@ bool Token::isSimpleTypeSpecifier(const LangOptions &LangOpts) const {
   case tok::kw___bf16:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___fpm8:
   case tok::kw___ibm128:
   case tok::kw_wchar_t:
   case tok::kw_bool:
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index c528917437332..25838d65f3e51 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4477,6 +4477,10 @@ void Parser::ParseDeclarationSpecifiers(
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
                                      DiagID, Policy);
       break;
+    case tok::kw___fpm8:
+      isInvalid =
+          DS.SetTypeSpecType(DeclSpec::TST_Fpm8, Loc, PrevSpec, DiagID, Policy);
+      break;
     case tok::kw_half:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
                                      DiagID, Policy);
@@ -5752,6 +5756,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
   case tok::kw__ExtInt:
   case tok::kw__BitInt:
   case tok::kw___bf16:
+  case tok::kw___fpm8:
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:
@@ -5835,6 +5840,7 @@ bool Parser::isTypeSpecifierQualifier() {
   case tok::kw_int:
   case tok::kw__ExtInt:
   case tok::kw__BitInt:
+  case tok::kw___fpm8:
   case tok::kw_half:
   case tok::kw___bf16:
   case tok::kw_float:
@@ -6057,6 +6063,7 @@ bool Parser::isDeclarationSpecifier(
   case tok::kw_int:
   case tok::kw__ExtInt:
   case tok::kw__BitInt:
+  case tok::kw___fpm8:
   case tok::kw_half:
   case tok::kw___bf16:
   case tok::kw_float:
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index eb7447fa038e4..9103275aa9772 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1594,6 +1594,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
   case tok::kw__BitInt:
   case tok::kw_signed:
   case tok::kw_unsigned:
+  case tok::kw___fpm8:
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 1d364f77a8146..72c4782cb53b3 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2405,6 +2405,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
   case tok::kw___int128:
     DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID, Policy);
     break;
+  case tok::kw___fpm8:
+    DS.SetTypeSpecType(DeclSpec::TST_Fpm8, Loc, PrevSpec, DiagID, Policy);
+    break;
   case tok::kw___bf16:
     DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec, DiagID, Policy);
     break;
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index ea17c3e3252ec..695bbbba9433d 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1779,6 +1779,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
   case tok::kw_short:
   case tok::kw_int:
   case tok::kw_long:
+  case tok::kw___fpm8:
   case tok::kw___int64:
   case tok::kw___int128:
   case tok::kw_signed:
@@ -1907,6 +1908,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
   case tok::kw_long:
   case tok::kw___int64:
   case tok::kw___int128:
+  case tok::kw___fpm8:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw_half:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 60e8189025700..168b98e90e6ec 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -358,6 +358,7 @@ bool Declarator::isDeclarationOfFunction() const {
     case TST_Fract:
     case TST_Float16:
     case TST_float128:
+    case TST_Fpm8:
     case TST_ibm128:
     case TST_enum:
     case TST_error:
@@ -575,6 +576,8 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
   case DeclSpec::TST_fract:       return "_Fract";
   case DeclSpec::TST_float16:     return "_Float16";
   case DeclSpec::TST_float128:    return "__float128";
+  case DeclSpec::TST_Fpm8:
+    return "fpm8_t";
   case DeclSpec::TST_ibm128:      return "__ibm128";
   case DeclSpec::TST_bool:        return Policy.Bool ? "bool" : "_Bool";
   case DeclSpec::TST_decimal32:   return "_Decimal32";
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 7a44b978aacdb..d7c4c04c130ef 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -908,6 +908,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
   case TST_char32:
   case TST_int:
   case TST_int128:
+  case TST_Fpm8:
   case TST_half:
   case TST_float:
   case TST_double:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 441fdcca0758f..89c523990ce52 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1134,6 +1134,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
       S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) << "__bf16";
     Result = Context.BFloat16Ty;
     break;
+  case DeclSpec::TST_Fpm8:
+    Result = Context.Fpm8Ty;
+    break;
   case DeclSpec::TST_float:   Result = Context.FloatTy; break;
   case DeclSpec::TST_double:
     if (DS.getTypeSpecWidth() == TypeSpecifierWidth::Long)
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index bc662a87a7bf3..a01d57cc1fcab 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -35,6 +35,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
   case BuiltinType::Char_U:
     ID = PREDEF_TYPE_CHAR_U_ID;
     break;
+  case BuiltinType::Fpm8:
+    ID = PREDEF_TYPE_FPM8_ID;
+    break;
   case BuiltinType::UChar:
     ID = PREDEF_TYPE_UCHAR_ID;
     break;
diff --git a/clang/test/AST/fpm8_opaque.cpp b/clang/test/AST/fpm8_opaque.cpp
new file mode 100644
index 0000000000000..3aeb3159ddc6a
--- /dev/null
+++ b/clang/test/AST/fpm8_opaque.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type __fpm8 can appear. */
+
+/*  Namespace */
+namespace {
+  __fpm8 f2n;
+  __fpm8 arr1n[10];
+}
+
+//CHECK:       |-NamespaceDecl {{.*}}
+//CHECK-NEXT:  | |-VarDecl {{.*}} f2n '__fpm8'
+//CHECK-NEXT:  | `-VarDecl {{.*}} arr1n '__fpm8[10]'
+
+  __fpm8 arr1[10];
+  //__fpm8 arr2n[] { 1, 3, 3 }; cannot initialize
+  
+  const __fpm8 func1n(const __fpm8 fpm8) {
+    // this should fail
+    __fpm8 f1n;
+    f1n  = fpm8;
+    return f1n;
+  }
+
+//CHECK:        |-VarDecl {{.*}} '__fpm8[10]'
+
+//CHECK:            | `-VarDecl {{.*}} f1n '__fpm8'
+//CHECK-NEXT:       |-BinaryOperator {{.*}} '__fpm8' lvalue '='
+//CHECK-NEXT:       | |-DeclRefExpr {{.*}} '__fpm8' lvalue Var {{.*}} 'f1n' '__fpm8'
+//CHECK-NEXT:       | `-ImplicitCastExpr {{.*}} '__fpm8' <LValueToRValue>
+//CHECK-NEXT:       |   `-DeclRefExpr {{.*}} 'const __fpm8' lvalue ParmVar {{.*}} 'fpm8' 'const __fpm8'
+//CHECK-NEXT:        `-ReturnStmt {{.*}}
+//CHECK-NEXT:         `-ImplicitCastExpr {{.*}} '__fpm8' <LValueToRValue>
+//CHECK-NEXT:           `-DeclRefExpr {{.*}} '__fpm8' lvalue Var {{.*}} 'f1n' '__fpm8'
+
+
+/* Class */
+
+class C1 {
+  __fpm8 f1c;
+  static const __fpm8 f2c;
+  volatile __fpm8 f3c;
+public:
+  C1(__fpm8 arg) : f1c(arg), f3c(arg) { }
+  __fpm8 func1c(__fpm8 arg ) {
+    return  arg;
+  }
+  static __fpm8 func2c(__fpm8 arg) {
+    return arg;
+  }
+};
+
+//CHECK:       | |-CXXRecordDecl {{.*}} referenced class C1
+//CHECK-NEXT:  | |-FieldDecl {{.*}} f1c '__fpm8'
+//CHECK-NEXT:  | |-VarDecl {{.*}} f2c 'const __fpm8' static
+//CHECK-NEXT:  | |-FieldDecl {{.*}} f3c 'volatile __fpm8'
+//CHECK-NEXT:  | |-AccessSpecDecl {{.*}}
+//CHECK-NEXT:  | |-CXXConstructorDecl {{.*}} C1 'void (__fpm8)' implicit-inline
+//CHECK-NEXT:  | | |-ParmVarDecl {{.*}} arg '__fpm8'
+//CHECK-NEXT:  | | |-CXXCtorInitializer {{.*}} 'f1c' '__fpm8'
+//CHECK-NEXT:  | | | `-ImplicitCastExpr {{.*}} '__fpm8' <LValueToRValue>
+//CHECK-NEXT:  | | |   `-DeclRefExpr {{.*}} '__fpm8' lvalue ParmVar {{.*}} 'arg' '__fpm8'
+//CHECK-NEXT:  | | |-CXXCtorInitializer {{.*}} 'f3c' 'volatile __fpm8'
+//CHECK-NEXT:  | | | `-ImplicitCastExpr {{.*}} '__fpm8' <LValueToRValue>
+//CHECK-NEXT:  | | |   `-DeclRefExpr {{.*}} '__fpm8' lvalue ParmVar {{.*}} 'arg' '__fpm8'
+//CHECK-NEXT:  | | `-CompoundStmt {{.*}}
+//CHECK-NEXT:  | |-CXXMethodDecl {{.*}} func1c '__fpm8 (__fpm8)' implicit-inline
+//CHECK-NEXT:  | | |-ParmVarDecl {{.*}} arg '__fpm8'
+//CHECK-NEXT:  | | `-CompoundStmt {{.*}}
+//CHECK-NEXT:  | |   `-ReturnStmt {{.*}}
+//CHECK-NEXT:  | |     `-ImplicitCastExpr {{.*}} '__fpm8' <LValueToRValue>
+//CHECK-NEXT:  | |       `-DeclRefExpr {{.*}} '__fpm8' lvalue ParmVar {{.*}}8 'arg' '__fpm8'
+//CHECK-NEXT:  | `-CXXMethodDecl {{.*}} func2c '__fpm8 (__fpm8)' static implicit-inline
+//CHECK-NEXT:  |   |-ParmVarDecl {{.*}} arg '__fpm8'
+//CHECK-NEXT:  |   `-CompoundStmt {{.*}}
+//CHECK-NEXT:  |     `-ReturnStmt {{.*}}
+//CHECK-NEXT:  |       `-ImplicitCastExpr {{.*}} '__fpm8' <LValueToRValue>
+//CHECK-NEXT:  |         `-DeclRefExpr {{.*}} '__fpm8' lvalue ParmVar {{.*}} 'arg' '__fpm8'
+
+template <class C> struct S1 {
+  C mem1;
+};
+
+template <> struct S1<__fpm8> {
+  __fpm8 mem2;
+};
+
+//CHECK:       |-TemplateArgument type '__fpm8'
+//CHECK-NEXT:  | `-BuiltinType {{.*}} '__fpm8'
+//CHECK-NEXT:  |-CXXRecordDecl {{.*}} implicit struct S1
+//CHECK-NEXT:  `-FieldDecl {{.*}} mem2 '__fpm8'
diff --git a/clang/test/CodeGen/fpm8_opaque.c b/clang/test/CodeGen/fpm8_opaque.c
new file mode 100644
index 0000000000000..19b5128b8eff9
--- /dev/null
+++ b/clang/test/CodeGen/fpm8_opaque.c
@@ -0,0 +1,24 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define dso_local i8 @func1n(
+// CHECK-SAME: i8 noundef [[FPM8:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[FPM8_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[F1N:%.*]] = alloca [10 x i8], align 1
+// CHECK-NEXT:    store i8 [[FPM8]], ptr [[FPM8_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[FPM8_ADDR]], align 1
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-NEXT:    store i8 [[TMP0]], ptr [[ARRAYIDX]], align 1
+// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
+// CHECK-NEXT:    ret i8 [[TMP1]]
+//
+__fpm8 func1n(__fpm8 fpm8) {
+  __fpm8 f1n[10];
+  f1n[2] = fpm8;
+  return f1n[2];
+}
+
+
+



More information about the cfe-commits mailing list