[clang] fae0dfa - [Clang] Add __ibm128 type to represent ppc_fp128

Qiu Chaofan via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 6 03:02:09 PDT 2021


Author: Qiu Chaofan
Date: 2021-09-06T18:00:58+08:00
New Revision: fae0dfa6421ea6c02f86ba7292fa782e1e2b69d1

URL: https://github.com/llvm/llvm-project/commit/fae0dfa6421ea6c02f86ba7292fa782e1e2b69d1
DIFF: https://github.com/llvm/llvm-project/commit/fae0dfa6421ea6c02f86ba7292fa782e1e2b69d1.diff

LOG: [Clang] Add __ibm128 type to represent ppc_fp128

Currently, we have no front-end type for ppc_fp128 type in IR. PowerPC
target generates ppc_fp128 type from long double now, but there's option
(-mabi=(ieee|ibm)longdouble) to control it and we're going to do
transition from IBM extended double-double ppc_fp128 to IEEE fp128 in
the future.

This patch adds type __ibm128 which always represents ppc_fp128 in IR,
as what GCC did for that type. Without this type in Clang, compilation
will fail if compiling against future version of libstdcxx (which uses
__ibm128 in headers).

Although all operations in backend for __ibm128 is done by software,
only PowerPC enables support for it.

There's something not implemented in this commit, which can be done in
future ones:

- Literal suffix for __ibm128 type. w/W is suitable as GCC documented.
- __attribute__((mode(IF))) should be for __ibm128.
- Complex __ibm128 type.

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D93377

Added: 
    clang/test/CodeGen/ibm128-cast.c
    clang/test/CodeGen/ibm128-unsupported.c
    clang/test/CodeGenCXX/ibm128-declarations.cpp

Modified: 
    clang/bindings/python/clang/cindex.py
    clang/include/clang-c/Index.h
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/AST/BuiltinTypes.def
    clang/include/clang/AST/Type.h
    clang/include/clang/AST/TypeLoc.h
    clang/include/clang/Basic/Specifiers.h
    clang/include/clang/Basic/TargetInfo.h
    clang/include/clang/Basic/TokenKinds.def
    clang/include/clang/Sema/DeclSpec.h
    clang/include/clang/Serialization/ASTBitCodes.h
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/ItaniumMangle.cpp
    clang/lib/AST/MicrosoftMangle.cpp
    clang/lib/AST/NSAPI.cpp
    clang/lib/AST/PrintfFormatString.cpp
    clang/lib/AST/StmtPrinter.cpp
    clang/lib/AST/Type.cpp
    clang/lib/AST/TypeLoc.cpp
    clang/lib/Basic/TargetInfo.cpp
    clang/lib/Basic/Targets/PPC.h
    clang/lib/CodeGen/CGDebugInfo.cpp
    clang/lib/CodeGen/CGExprScalar.cpp
    clang/lib/CodeGen/CodeGenTypes.cpp
    clang/lib/CodeGen/ItaniumCXXABI.cpp
    clang/lib/CodeGen/TargetInfo.cpp
    clang/lib/Format/FormatToken.cpp
    clang/lib/Index/USRGeneration.cpp
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Parse/ParseExpr.cpp
    clang/lib/Parse/ParseExprCXX.cpp
    clang/lib/Parse/ParseTentative.cpp
    clang/lib/Sema/DeclSpec.cpp
    clang/lib/Sema/Sema.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/lib/Sema/SemaTemplateVariadic.cpp
    clang/lib/Sema/SemaType.cpp
    clang/lib/Serialization/ASTCommon.cpp
    clang/lib/Serialization/ASTReader.cpp
    clang/test/Sema/128bitfloat.cpp
    clang/tools/libclang/CXType.cpp

Removed: 
    


################################################################################
diff  --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index aceaa131f1555..44bfba494df21 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -2059,6 +2059,7 @@ def __repr__(self):
 TypeKind.OBJCSEL = TypeKind(29)
 TypeKind.FLOAT128 = TypeKind(30)
 TypeKind.HALF = TypeKind(31)
+TypeKind.IBM128 = TypeKind(40)
 TypeKind.COMPLEX = TypeKind(100)
 TypeKind.POINTER = TypeKind(101)
 TypeKind.BLOCKPOINTER = TypeKind(102)

diff  --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 26844d1c74f39..8afd4c9ff1d05 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3298,8 +3298,9 @@ enum CXTypeKind {
   CXType_UAccum = 37,
   CXType_ULongAccum = 38,
   CXType_BFloat16 = 39,
+  CXType_Ibm128 = 40,
   CXType_FirstBuiltin = CXType_Void,
-  CXType_LastBuiltin = CXType_BFloat16,
+  CXType_LastBuiltin = CXType_Ibm128,
 
   CXType_Complex = 100,
   CXType_Pointer = 101,

diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 5004cb6cb2671..b8f7c3aae2608 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1076,7 +1076,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
   CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
   CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
   CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
-  CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty;
+  CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty, Ibm128Ty;
   CanQualType ShortAccumTy, AccumTy,
       LongAccumTy;  // ISO/IEC JTC1 SC22 WG14 N1169 Extension
   CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy;

diff  --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def
index 039765dfdfea6..c04f6f6f12719 100644
--- a/clang/include/clang/AST/BuiltinTypes.def
+++ b/clang/include/clang/AST/BuiltinTypes.def
@@ -218,6 +218,9 @@ FLOATING_TYPE(BFloat16, BFloat16Ty)
 // '__float128'
 FLOATING_TYPE(Float128, Float128Ty)
 
+// '__ibm128'
+FLOATING_TYPE(Ibm128, Ibm128Ty)
+
 //===- 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 49ff9861d165f..b8d72f904d0b6 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2003,6 +2003,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
   bool isFloat16Type() const;      // C11 extension ISO/IEC TS 18661
   bool isBFloat16Type() const;
   bool isFloat128Type() const;
+  bool isIbm128Type() const;
   bool isRealType() const;         // C99 6.2.5p17 (real floating + integer)
   bool isArithmeticType() const;   // C99 6.2.5p18 (integer + floating)
   bool isVoidType() const;         // C99 6.2.5p19
@@ -2550,7 +2551,7 @@ class BuiltinType : public Type {
   }
 
   bool isFloatingPoint() const {
-    return getKind() >= Half && getKind() <= Float128;
+    return getKind() >= Half && getKind() <= Ibm128;
   }
 
   /// Determines whether the given kind corresponds to a placeholder type.
@@ -6973,6 +6974,10 @@ inline bool Type::isFloat128Type() const {
   return isSpecificBuiltinType(BuiltinType::Float128);
 }
 
+inline bool Type::isIbm128Type() const {
+  return isSpecificBuiltinType(BuiltinType::Ibm128);
+}
+
 inline bool Type::isNullPtrType() const {
   return isSpecificBuiltinType(BuiltinType::NullPtr);
 }

diff  --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 65e95d52c303d..bb668c1980fe4 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -581,10 +581,9 @@ class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
 
   bool needsExtraLocalData() const {
     BuiltinType::Kind bk = getTypePtr()->getKind();
-    return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128)
-      || (bk >= BuiltinType::Short && bk <= BuiltinType::Float128)
-      || bk == BuiltinType::UChar
-      || bk == BuiltinType::SChar;
+    return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) ||
+           (bk >= BuiltinType::Short && bk <= BuiltinType::Ibm128) ||
+           bk == BuiltinType::UChar || bk == BuiltinType::SChar;
   }
 
   unsigned getExtraLocalDataSize() const {

diff  --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 1c38b411e083c..31e3888424e04 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -59,6 +59,7 @@ namespace clang {
     TST_float,
     TST_double,
     TST_float128,
+    TST_ibm128,
     TST_bool,         // _Bool
     TST_decimal32,    // _Decimal32
     TST_decimal64,    // _Decimal64

diff  --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index c0e2b758d3eab..e959108e2ac03 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -64,7 +64,7 @@ struct TransferrableTargetInfo {
   unsigned char BFloat16Width, BFloat16Align;
   unsigned char FloatWidth, FloatAlign;
   unsigned char DoubleWidth, DoubleAlign;
-  unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align;
+  unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align, Ibm128Align;
   unsigned char LargeArrayMinWidth, LargeArrayAlign;
   unsigned char LongWidth, LongAlign;
   unsigned char LongLongWidth, LongLongAlign;
@@ -104,7 +104,7 @@ struct TransferrableTargetInfo {
   unsigned MaxTLSAlign;
 
   const llvm::fltSemantics *HalfFormat, *BFloat16Format, *FloatFormat,
-    *DoubleFormat, *LongDoubleFormat, *Float128Format;
+      *DoubleFormat, *LongDoubleFormat, *Float128Format, *Ibm128Format;
 
   ///===---- Target Data Type Query Methods -------------------------------===//
   enum IntType {
@@ -126,8 +126,10 @@ struct TransferrableTargetInfo {
     Float = 0,
     Double,
     LongDouble,
-    Float128
+    Float128,
+    Ibm128
   };
+
 protected:
   IntType SizeType, IntMaxType, PtrDiffType, IntPtrType, WCharType, WIntType,
       Char16Type, Char32Type, Int64Type, Int16Type, SigAtomicType,
@@ -200,6 +202,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
   bool HasFloat128;
   bool HasFloat16;
   bool HasBFloat16;
+  bool HasIbm128;
   bool HasStrictFP;
 
   unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
@@ -594,6 +597,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
   /// Determine whether the _BFloat16 type is supported on this target.
   virtual bool hasBFloat16Type() const { return HasBFloat16; }
 
+  /// Determine whether the __ibm128 type is supported on this target.
+  virtual bool hasIbm128Type() const { return HasIbm128; }
+
   /// Determine whether constrained floating point is supported on this target.
   virtual bool hasStrictFP() const { return HasStrictFP; }
 
@@ -672,12 +678,23 @@ class TargetInfo : public virtual TransferrableTargetInfo,
     return *Float128Format;
   }
 
+  /// getIbm128Width/Align/Format - Return the size/align/format of
+  /// '__ibm128'.
+  unsigned getIbm128Width() const { return 128; }
+  unsigned getIbm128Align() const { return Ibm128Align; }
+  const llvm::fltSemantics &getIbm128Format() const { return *Ibm128Format; }
+
   /// Return the mangled code of long double.
   virtual const char *getLongDoubleMangling() const { return "e"; }
 
   /// Return the mangled code of __float128.
   virtual const char *getFloat128Mangling() const { return "g"; }
 
+  /// Return the mangled code of __ibm128.
+  virtual const char *getIbm128Mangling() const {
+    llvm_unreachable("ibm128 not implemented on this target");
+  }
+
   /// Return the mangled code of bfloat.
   virtual const char *getBFloat16Mangling() const {
     llvm_unreachable("bfloat not implemented on this target");

diff  --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 48a664e3494e2..2b3dfedd020c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -438,6 +438,7 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX)
 KEYWORD(__builtin_va_arg            , KEYALL)
 KEYWORD(__extension__               , KEYALL)
 KEYWORD(__float128                  , KEYALL)
+KEYWORD(__ibm128                    , KEYALL)
 KEYWORD(__imag                      , KEYALL)
 KEYWORD(__int128                    , KEYALL)
 KEYWORD(__label__                   , KEYALL)

diff  --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 423f4f4ee7b7c..ed5be2da3acd6 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -275,6 +275,7 @@ class DeclSpec {
   static const TST TST_accum = clang::TST_Accum;
   static const TST TST_fract = clang::TST_Fract;
   static const TST TST_float128 = clang::TST_float128;
+  static const TST TST_ibm128 = clang::TST_ibm128;
   static const TST TST_bool = clang::TST_bool;
   static const TST TST_decimal32 = clang::TST_decimal32;
   static const TST TST_decimal64 = clang::TST_decimal64;

diff  --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 027a981df22ca..a08c4615b738a 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1064,6 +1064,9 @@ enum PredefinedTypeIDs {
   /// \brief The '__bf16' type
   PREDEF_TYPE_BFLOAT16_ID = 73,
 
+  /// \brief The '__ibm128' type
+  PREDEF_TYPE_IBM128_ID = 74,
+
 /// OpenCL image types with auto numeration
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
   PREDEF_TYPE_##Id##_ID,

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 41dd9f7e3330b..dc19dd6959049 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -101,7 +101,14 @@
 using namespace clang;
 
 enum FloatingRank {
-  BFloat16Rank, Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank
+  BFloat16Rank,
+  Float16Rank,
+  HalfRank,
+  FloatRank,
+  DoubleRank,
+  LongDoubleRank,
+  Float128Rank,
+  Ibm128Rank
 };
 
 /// \returns location that is relevant when searching for Doc comments related
@@ -1307,6 +1314,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
   // GNU extension, __float128 for IEEE quadruple precision
   InitBuiltinType(Float128Ty,          BuiltinType::Float128);
 
+  // __ibm128 for IBM extended precision
+  InitBuiltinType(Ibm128Ty, BuiltinType::Ibm128);
+
   // C11 extension ISO/IEC TS 18661-3
   InitBuiltinType(Float16Ty,           BuiltinType::Float16);
 
@@ -1703,6 +1713,8 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
     return Target->getHalfFormat();
   case BuiltinType::Float:      return Target->getFloatFormat();
   case BuiltinType::Double:     return Target->getDoubleFormat();
+  case BuiltinType::Ibm128:
+    return Target->getIbm128Format();
   case BuiltinType::LongDouble:
     if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice)
       return AuxTarget->getLongDoubleFormat();
@@ -2129,6 +2141,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
       Width = Target->getDoubleWidth();
       Align = Target->getDoubleAlign();
       break;
+    case BuiltinType::Ibm128:
+      Width = Target->getIbm128Width();
+      Align = Target->getIbm128Align();
+      break;
     case BuiltinType::LongDouble:
       if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
           (Target->getLongDoubleWidth() != AuxTarget->getLongDoubleWidth() ||
@@ -6309,6 +6325,7 @@ static FloatingRank getFloatingRank(QualType T) {
   case BuiltinType::LongDouble: return LongDoubleRank;
   case BuiltinType::Float128:   return Float128Rank;
   case BuiltinType::BFloat16:   return BFloat16Rank;
+  case BuiltinType::Ibm128:     return Ibm128Rank;
   }
 }
 
@@ -6324,6 +6341,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
     case BFloat16Rank: llvm_unreachable("Complex bfloat16 is not supported");
     case Float16Rank:
     case HalfRank: llvm_unreachable("Complex half is not supported");
+    case Ibm128Rank: llvm_unreachable("Complex __ibm128 is not supported");
     case FloatRank:      return FloatComplexTy;
     case DoubleRank:     return DoubleComplexTy;
     case LongDoubleRank: return LongDoubleComplexTy;
@@ -6340,6 +6358,8 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
   case DoubleRank:     return DoubleTy;
   case LongDoubleRank: return LongDoubleTy;
   case Float128Rank:   return Float128Ty;
+  case Ibm128Rank:
+    return Ibm128Ty;
   }
   llvm_unreachable("getFloatingRank(): illegal value for rank");
 }
@@ -7315,6 +7335,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
     case BuiltinType::BFloat16:
     case BuiltinType::Float16:
     case BuiltinType::Float128:
+    case BuiltinType::Ibm128:
     case BuiltinType::Half:
     case BuiltinType::ShortAccum:
     case BuiltinType::Accum:
@@ -11250,6 +11271,8 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth,
     return LongDoubleTy;
   case TargetInfo::Float128:
     return Float128Ty;
+  case TargetInfo::Ibm128:
+    return Ibm128Ty;
   case TargetInfo::NoFloat:
     return {};
   }

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 8cbac66fcf002..b1ac62b0ac983 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2860,6 +2860,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
   //                 ::= d  # double
   //                 ::= e  # long double, __float80
   //                 ::= g  # __float128
+  //                 ::= g  # __ibm128
   // UNSUPPORTED:    ::= Dd # IEEE 754r decimal floating point (64 bits)
   // UNSUPPORTED:    ::= De # IEEE 754r decimal floating point (128 bits)
   // UNSUPPORTED:    ::= Df # IEEE 754r decimal floating point (32 bits)
@@ -2988,6 +2989,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
     Out << TI->getBFloat16Mangling();
     break;
   }
+  case BuiltinType::Ibm128: {
+    const TargetInfo *TI = &getASTContext().getTargetInfo();
+    Out << TI->getIbm128Mangling();
+    break;
+  }
   case BuiltinType::NullPtr:
     Out << "Dn";
     break;

diff  --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index d89cddd2adda0..d3d65087d3adc 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -2466,6 +2466,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
   case BuiltinType::SatUFract:
   case BuiltinType::SatULongFract:
   case BuiltinType::BFloat16:
+  case BuiltinType::Ibm128:
   case BuiltinType::Float128: {
     DiagnosticsEngine &Diags = Context.getDiags();
     unsigned DiagID = Diags.getCustomDiagID(

diff  --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index 861060d7c875c..db7878e18c42d 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -456,6 +456,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
   case BuiltinType::UInt128:
   case BuiltinType::Float16:
   case BuiltinType::Float128:
+  case BuiltinType::Ibm128:
   case BuiltinType::NullPtr:
   case BuiltinType::ObjCClass:
   case BuiltinType::ObjCId:

diff  --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp
index 4806c554a2a1b..e2569c9e20df7 100644
--- a/clang/lib/AST/PrintfFormatString.cpp
+++ b/clang/lib/AST/PrintfFormatString.cpp
@@ -755,6 +755,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
   case BuiltinType::BFloat16:
   case BuiltinType::Float16:
   case BuiltinType::Float128:
+  case BuiltinType::Ibm128:
   case BuiltinType::ShortAccum:
   case BuiltinType::Accum:
   case BuiltinType::LongAccum:

diff  --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 45b15171aa97c..45cdb416cd601 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1183,6 +1183,7 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
   switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
   default: llvm_unreachable("Unexpected type for float literal!");
   case BuiltinType::Half:       break; // FIXME: suffix?
+  case BuiltinType::Ibm128:     break; // FIXME: No suffix for ibm128 literal
   case BuiltinType::Double:     break; // no suffix.
   case BuiltinType::Float16:    OS << "F16"; break;
   case BuiltinType::Float:      OS << 'F'; break;

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 4a2fc5219ef0b..f71c05d639ce3 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2097,7 +2097,7 @@ bool Type::hasUnsignedIntegerRepresentation() const {
 bool Type::isFloatingType() const {
   if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Half &&
-           BT->getKind() <= BuiltinType::Float128;
+           BT->getKind() <= BuiltinType::Ibm128;
   if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
     return CT->getElementType()->isFloatingType();
   return false;
@@ -2119,7 +2119,7 @@ bool Type::isRealFloatingType() const {
 bool Type::isRealType() const {
   if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Bool &&
-           BT->getKind() <= BuiltinType::Float128;
+           BT->getKind() <= BuiltinType::Ibm128;
   if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
       return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
   return isExtIntType();
@@ -2128,7 +2128,7 @@ bool Type::isRealType() const {
 bool Type::isArithmeticType() const {
   if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Bool &&
-           BT->getKind() <= BuiltinType::Float128 &&
+           BT->getKind() <= BuiltinType::Ibm128 &&
            BT->getKind() != BuiltinType::BFloat16;
   if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
     // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
@@ -3030,6 +3030,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
     return "_Float16";
   case Float128:
     return "__float128";
+  case Ibm128:
+    return "__ibm128";
   case WChar_S:
   case WChar_U:
     return Policy.MSWChar ? "__wchar_t" : "wchar_t";

diff  --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 16d953b4bece5..e943c873f1fad 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -351,6 +351,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
   case BuiltinType::LongDouble:
   case BuiltinType::Float16:
   case BuiltinType::Float128:
+  case BuiltinType::Ibm128:
   case BuiltinType::ShortAccum:
   case BuiltinType::Accum:
   case BuiltinType::LongAccum:

diff  --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index bc5f86a28d89d..133391b0d20c4 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -34,6 +34,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
   NoAsmVariants = false;
   HasLegalHalfType = false;
   HasFloat128 = false;
+  HasIbm128 = false;
   HasFloat16 = false;
   HasBFloat16 = false;
   HasStrictFP = false;
@@ -83,6 +84,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
   LongDoubleWidth = 64;
   LongDoubleAlign = 64;
   Float128Align = 128;
+  Ibm128Align = 128;
   LargeArrayMinWidth = 0;
   LargeArrayAlign = 0;
   MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
@@ -113,6 +115,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
   DoubleFormat = &llvm::APFloat::IEEEdouble();
   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
   Float128Format = &llvm::APFloat::IEEEquad();
+  Ibm128Format = &llvm::APFloat::PPCDoubleDouble();
   MCountName = "mcount";
   UserLabelPrefix = "_";
   RegParmMax = 0;

diff  --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index 7c14a4eb9410c..89034682a90e4 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -89,6 +89,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
     LongDoubleWidth = LongDoubleAlign = 128;
     LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
     HasStrictFP = true;
+    HasIbm128 = true;
   }
 
   // Set the language option for altivec based on our value.
@@ -347,6 +348,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
                : "u9__ieee128";
   }
   const char *getFloat128Mangling() const override { return "u9__ieee128"; }
+  const char *getIbm128Mangling() const override { return "g"; }
 
   bool hasExtIntType() const override { return true; }
 

diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 69d054583e630..0b10343f29a61 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -830,11 +830,12 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
   case BuiltinType::BFloat16:
   case BuiltinType::Float128:
   case BuiltinType::Double:
-    // FIXME: For targets where long double and __float128 have the same size,
-    // they are currently indistinguishable in the debugger without some
-    // special treatment. However, there is currently no consensus on encoding
-    // and this should be updated once a DWARF encoding exists for distinct
-    // floating point types of the same size.
+  case BuiltinType::Ibm128:
+    // FIXME: For targets where long double, __ibm128 and __float128 have the
+    // same size, they are currently indistinguishable in the debugger without
+    // some special treatment. However, there is currently no consensus on
+    // encoding and this should be updated once a DWARF encoding exists for
+    // distinct floating point types of the same size.
     Encoding = llvm::dwarf::DW_ATE_float;
     break;
   case BuiltinType::ShortAccum:

diff  --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 6c82fcb1e97fa..fe62e63521a1e 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2680,7 +2680,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
       amt = llvm::ConstantFP::get(VMContext,
                                   llvm::APFloat(static_cast<double>(amount)));
     else {
-      // Remaining types are Half, LongDouble or __float128. Convert from float.
+      // Remaining types are Half, LongDouble, __ibm128 or __float128. Convert
+      // from float.
       llvm::APFloat F(static_cast<float>(amount));
       bool ignored;
       const llvm::fltSemantics *FS;
@@ -2690,6 +2691,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
         FS = &CGF.getTarget().getFloat128Format();
       else if (value->getType()->isHalfTy())
         FS = &CGF.getTarget().getHalfFormat();
+      else if (value->getType()->isPPC_FP128Ty())
+        FS = &CGF.getTarget().getIbm128Format();
       else
         FS = &CGF.getTarget().getLongDoubleFormat();
       F.convert(*FS, llvm::APFloat::rmTowardZero, &ignored);

diff  --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 9cb42941cb968..fb05475a4e8ca 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -512,6 +512,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
     case BuiltinType::Double:
     case BuiltinType::LongDouble:
     case BuiltinType::Float128:
+    case BuiltinType::Ibm128:
       ResultType = getTypeForFormat(getLLVMContext(),
                                     Context.getFloatTypeSemantics(T),
                                     /* UseNativeHalf = */ false);

diff  --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 8ddc2f1885eb1..afc59eb93ec24 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3269,6 +3269,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
     case BuiltinType::LongDouble:
     case BuiltinType::Float16:
     case BuiltinType::Float128:
+    case BuiltinType::Ibm128:
     case BuiltinType::Char8:
     case BuiltinType::Char16:
     case BuiltinType::Char32:

diff  --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 7081b20a20200..b9668607bd3ab 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -5226,8 +5226,9 @@ bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
     if (BT->getKind() == BuiltinType::Float ||
         BT->getKind() == BuiltinType::Double ||
         BT->getKind() == BuiltinType::LongDouble ||
+        BT->getKind() == BuiltinType::Ibm128 ||
         (getContext().getTargetInfo().hasFloat128Type() &&
-          (BT->getKind() == BuiltinType::Float128))) {
+         (BT->getKind() == BuiltinType::Float128))) {
       if (IsSoftFloatABI)
         return false;
       return true;

diff  --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp
index 8e4994f4c0d57..6768f041135c7 100644
--- a/clang/lib/Format/FormatToken.cpp
+++ b/clang/lib/Format/FormatToken.cpp
@@ -53,6 +53,7 @@ bool FormatToken::isSimpleTypeSpecifier() const {
   case tok::kw___bf16:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_wchar_t:
   case tok::kw_bool:
   case tok::kw___underlying_type:

diff  --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 6db763ca6f2b5..41edd431dd5b8 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -705,6 +705,7 @@ void USRGenerator::VisitType(QualType T) {
           c = 'f'; break;
         case BuiltinType::Double:
           c = 'd'; break;
+        case BuiltinType::Ibm128: // FIXME: Need separate tag
         case BuiltinType::LongDouble:
           c = 'D'; break;
         case BuiltinType::Float128:

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 7cec896b5c236..9f660e466aae0 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3929,6 +3929,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
                                      DiagID, Policy);
       break;
+    case tok::kw___ibm128:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_ibm128, Loc, PrevSpec,
+                                     DiagID, Policy);
+      break;
     case tok::kw_wchar_t:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
                                      DiagID, Policy);
@@ -5007,6 +5011,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
   case tok::kw__Fract:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_bool:
   case tok::kw__Bool:
   case tok::kw__Decimal32:
@@ -5088,6 +5093,7 @@ bool Parser::isTypeSpecifierQualifier() {
   case tok::kw__Fract:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_bool:
   case tok::kw__Bool:
   case tok::kw__Decimal32:
@@ -5258,6 +5264,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
   case tok::kw__Fract:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_bool:
   case tok::kw__Bool:
   case tok::kw__Decimal32:

diff  --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 7e2747e8305e8..2c8b4f9f441f5 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1521,6 +1521,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
   case tok::kw___bf16:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_void:
   case tok::kw_typename:
   case tok::kw_typeof:

diff  --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 3f357233f9bb4..5b7e15e1939c0 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2226,6 +2226,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
   case tok::kw___float128:
     DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy);
     break;
+  case tok::kw___ibm128:
+    DS.SetTypeSpecType(DeclSpec::TST_ibm128, Loc, PrevSpec, DiagID, Policy);
+    break;
   case tok::kw_wchar_t:
     DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy);
     break;

diff  --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index c0bfbbde40ac8..73fe5533ec663 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1637,6 +1637,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
   case tok::kw___bf16:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_void:
   case tok::annot_decltype:
 #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
@@ -1751,6 +1752,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
   case tok::kw___bf16:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_void:
   case tok::kw___unknown_anytype:
   case tok::kw___auto_type:

diff  --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 47b9c10773413..d7b4ceac28bb0 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_ibm128:
     case TST_enum:
     case TST_error:
     case TST_float:
@@ -558,6 +559,7 @@ 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_ibm128:      return "__ibm128";
   case DeclSpec::TST_bool:        return Policy.Bool ? "bool" : "_Bool";
   case DeclSpec::TST_decimal32:   return "_Decimal32";
   case DeclSpec::TST_decimal64:   return "_Decimal64";

diff  --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 79f4c874b8ff4..a9867697a4c31 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1887,12 +1887,22 @@ void Sema::checkDeviceDecl(ValueDecl *D, SourceLocation Loc) {
       return;
     }
 
+    // Check if we are dealing with two 'long double' but with 
diff erent
+    // semantics.
+    bool LongDoubleMismatched = false;
+    if (Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128) {
+      const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(Ty);
+      if (!Ty->isIbm128Type() && !Ty->isFloat128Type() &&
+          &Sem != &Context.getTargetInfo().getLongDoubleFormat())
+        LongDoubleMismatched = true;
+    }
+
     if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) ||
-        ((Ty->isFloat128Type() ||
-          (Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128)) &&
-         !Context.getTargetInfo().hasFloat128Type()) ||
+        (Ty->isFloat128Type() && !Context.getTargetInfo().hasFloat128Type()) ||
+        (Ty->isIbm128Type() && !Context.getTargetInfo().hasIbm128Type()) ||
         (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 &&
-         !Context.getTargetInfo().hasInt128Type())) {
+         !Context.getTargetInfo().hasInt128Type()) ||
+        LongDoubleMismatched) {
       if (targetDiag(Loc, diag::err_device_unsupported_type, FD)
           << D << true /*show bit size*/
           << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f9738f0ddfca7..f33811f63c71e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -141,6 +141,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
   case tok::kw___bf16:
   case tok::kw__Float16:
   case tok::kw___float128:
+  case tok::kw___ibm128:
   case tok::kw_wchar_t:
   case tok::kw_bool:
   case tok::kw___underlying_type:

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 11d8c3589c273..7c8d753730a0a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1197,45 +1197,32 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
                                     /*ConvertInt=*/!IsCompAssign);
 }
 
-/// Diagnose attempts to convert between __float128 and long double if
-/// there is no support for such conversion. Helper function of
-/// UsualArithmeticConversions().
+/// Diagnose attempts to convert between __float128, __ibm128 and
+/// long double if there is no support for such conversion.
+/// Helper function of UsualArithmeticConversions().
 static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
                                       QualType RHSType) {
-  /*  No issue converting if at least one of the types is not a floating point
-      type or the two types have the same rank.
-  */
-  if (!LHSType->isFloatingType() || !RHSType->isFloatingType() ||
-      S.Context.getFloatingTypeOrder(LHSType, RHSType) == 0)
+  // No issue if either is not a floating point type.
+  if (!LHSType->isFloatingType() || !RHSType->isFloatingType())
     return false;
 
-  assert(LHSType->isFloatingType() && RHSType->isFloatingType() &&
-         "The remaining types must be floating point types.");
-
+  // No issue if both have the same 128-bit float semantics.
   auto *LHSComplex = LHSType->getAs<ComplexType>();
   auto *RHSComplex = RHSType->getAs<ComplexType>();
 
-  QualType LHSElemType = LHSComplex ?
-    LHSComplex->getElementType() : LHSType;
-  QualType RHSElemType = RHSComplex ?
-    RHSComplex->getElementType() : RHSType;
+  QualType LHSElem = LHSComplex ? LHSComplex->getElementType() : LHSType;
+  QualType RHSElem = RHSComplex ? RHSComplex->getElementType() : RHSType;
 
-  // No issue if the two types have the same representation
-  if (&S.Context.getFloatTypeSemantics(LHSElemType) ==
-      &S.Context.getFloatTypeSemantics(RHSElemType))
-    return false;
+  const llvm::fltSemantics &LHSSem = S.Context.getFloatTypeSemantics(LHSElem);
+  const llvm::fltSemantics &RHSSem = S.Context.getFloatTypeSemantics(RHSElem);
 
-  bool Float128AndLongDouble = (LHSElemType == S.Context.Float128Ty &&
-                                RHSElemType == S.Context.LongDoubleTy);
-  Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy &&
-                            RHSElemType == S.Context.Float128Ty);
+  if ((&LHSSem != &llvm::APFloat::PPCDoubleDouble() ||
+       &RHSSem != &llvm::APFloat::IEEEquad()) &&
+      (&LHSSem != &llvm::APFloat::IEEEquad() ||
+       &RHSSem != &llvm::APFloat::PPCDoubleDouble()))
+    return false;
 
-  // We've handled the situation where __float128 and long double have the same
-  // representation. We allow all conversions for all possible long double types
-  // except PPC's double double.
-  return Float128AndLongDouble &&
-    (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
-     &llvm::APFloat::PPCDoubleDouble());
+  return true;
 }
 
 typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
@@ -1547,8 +1534,8 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
 
   // At this point, we have two 
diff erent arithmetic types.
 
-  // Diagnose attempts to convert between __float128 and long double where
-  // such conversions currently can't be handled.
+  // Diagnose attempts to convert between __ibm128, __float128 and long double
+  // where such conversions currently can't be handled.
   if (unsupportedTypeConversion(*this, LHSType, RHSType))
     return QualType();
 
@@ -8375,8 +8362,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
   QualType LHSTy = LHS.get()->getType();
   QualType RHSTy = RHS.get()->getType();
 
-  // Diagnose attempts to convert between __float128 and long double where
-  // such conversions currently can't be handled.
+  // Diagnose attempts to convert between __ibm128, __float128 and long double
+  // where such conversions currently can't be handled.
   if (unsupportedTypeConversion(*this, LHSTy, RHSTy)) {
     Diag(QuestionLoc,
          diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy
@@ -9310,8 +9297,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
     return Incompatible;
   }
 
-  // Diagnose attempts to convert between __float128 and long double where
-  // such conversions currently can't be handled.
+  // Diagnose attempts to convert between __ibm128, __float128 and long double
+  // where such conversions currently can't be handled.
   if (unsupportedTypeConversion(*this, LHSType, RHSType))
     return Incompatible;
 

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 0bf0818eeccdf..07f50400989e8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1869,24 +1869,25 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
     SCS.Second = ICK_Complex_Real;
     FromType = ToType.getUnqualifiedType();
   } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) {
-    // FIXME: disable conversions between long double and __float128 if
-    // their representation is 
diff erent until there is back end support
+    // FIXME: disable conversions between long double, __ibm128 and __float128
+    // if their representation is 
diff erent until there is back end support
     // We of course allow this conversion if long double is really double.
 
     // Conversions between bfloat and other floats are not permitted.
     if (FromType == S.Context.BFloat16Ty || ToType == S.Context.BFloat16Ty)
       return false;
-    if (&S.Context.getFloatTypeSemantics(FromType) !=
-        &S.Context.getFloatTypeSemantics(ToType)) {
-      bool Float128AndLongDouble = ((FromType == S.Context.Float128Ty &&
-                                    ToType == S.Context.LongDoubleTy) ||
-                                   (FromType == S.Context.LongDoubleTy &&
-                                    ToType == S.Context.Float128Ty));
-      if (Float128AndLongDouble &&
-          (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
-           &llvm::APFloat::PPCDoubleDouble()))
-        return false;
-    }
+
+    // Conversions between IEEE-quad and IBM-extended semantics are not
+    // permitted.
+    const llvm::fltSemantics &FromSem =
+        S.Context.getFloatTypeSemantics(FromType);
+    const llvm::fltSemantics &ToSem = S.Context.getFloatTypeSemantics(ToType);
+    if ((&FromSem == &llvm::APFloat::PPCDoubleDouble() &&
+         &ToSem == &llvm::APFloat::IEEEquad()) ||
+        (&FromSem == &llvm::APFloat::IEEEquad() &&
+         &ToSem == &llvm::APFloat::PPCDoubleDouble()))
+      return false;
+
     // Floating point conversions (C++ 4.8).
     SCS.Second = ICK_Floating_Conversion;
     FromType = ToType.getUnqualifiedType();
@@ -2237,7 +2238,8 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
           (FromBuiltin->getKind() == BuiltinType::Float ||
            FromBuiltin->getKind() == BuiltinType::Double) &&
           (ToBuiltin->getKind() == BuiltinType::LongDouble ||
-           ToBuiltin->getKind() == BuiltinType::Float128))
+           ToBuiltin->getKind() == BuiltinType::Float128 ||
+           ToBuiltin->getKind() == BuiltinType::Ibm128))
         return true;
 
       // Half can be promoted to float.
@@ -8173,6 +8175,8 @@ class BuiltinOperatorOverloadBuilder {
     ArithmeticTypes.push_back(S.Context.LongDoubleTy);
     if (S.Context.getTargetInfo().hasFloat128Type())
       ArithmeticTypes.push_back(S.Context.Float128Ty);
+    if (S.Context.getTargetInfo().hasIbm128Type())
+      ArithmeticTypes.push_back(S.Context.Ibm128Ty);
 
     // Start of integral types.
     FirstIntegralType = ArithmeticTypes.size();

diff  --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 1951aec3d17d9..bda6be195f212 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -893,6 +893,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
   case TST_Fract:
   case TST_Float16:
   case TST_float128:
+  case TST_ibm128:
   case TST_bool:
   case TST_decimal32:
   case TST_decimal64:

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 21ef55bc87f27..69c9de35c68eb 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1547,6 +1547,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
         << "__float128";
     Result = Context.Float128Ty;
     break;
+  case DeclSpec::TST_ibm128:
+    if (!S.Context.getTargetInfo().hasIbm128Type() &&
+        !S.getLangOpts().SYCLIsDevice &&
+        !(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice))
+      S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) << "__ibm128";
+    Result = Context.Ibm128Ty;
+    break;
   case DeclSpec::TST_bool:
     Result = Context.BoolTy; // _Bool or bool
     break;

diff  --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index db118d8b00776..c60f87a239857 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -168,6 +168,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
   case BuiltinType::Float128:
     ID = PREDEF_TYPE_FLOAT128_ID;
     break;
+  case BuiltinType::Ibm128:
+    ID = PREDEF_TYPE_IBM128_ID;
+    break;
   case BuiltinType::NullPtr:
     ID = PREDEF_TYPE_NULLPTR_ID;
     break;

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index dfa7d55af735d..3dbcea766c53e 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6940,6 +6940,9 @@ QualType ASTReader::GetType(TypeID ID) {
     case PREDEF_TYPE_FLOAT128_ID:
       T = Context.Float128Ty;
       break;
+    case PREDEF_TYPE_IBM128_ID:
+      T = Context.Ibm128Ty;
+      break;
     case PREDEF_TYPE_OVERLOAD_ID:
       T = Context.OverloadTy;
       break;

diff  --git a/clang/test/CodeGen/ibm128-cast.c b/clang/test/CodeGen/ibm128-cast.c
new file mode 100644
index 0000000000000..d744ba7a8fc8c
--- /dev/null
+++ b/clang/test/CodeGen/ibm128-cast.c
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown -verify \
+// RUN:   -target-feature +float128 -mabi=ieeelongdouble -fsyntax-only -Wno-unused %s
+// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown -verify \
+// RUN:   -target-feature +float128 -fsyntax-only -Wno-unused %s
+
+__float128 cast1(__ibm128 x) { return x; } // expected-error {{returning '__ibm128' from a function with incompatible result type '__float128'}}
+
+__ibm128 cast2(__float128 x) { return x; } // expected-error {{returning '__float128' from a function with incompatible result type '__ibm128'}}
+
+__ibm128 gf;
+
+void narrow(double *d, float *f) {
+  __ibm128 v = gf;
+  gf = *d;      // expected-no-error {{assigning to '__ibm128' from incompatible type 'double'}}
+  *f = v;       // expected-no-error {{assigning to 'float' from incompatible type '__ibm128'}}
+  *d = gf + *f; // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'float')}}
+}
+
+#ifdef __LONG_DOUBLE_IEEE128__
+long double cast3(__ibm128 x) { return x; } // expected-error {{returning '__ibm128' from a function with incompatible result type 'long double'}}
+
+__ibm128 cast4(long double x) { return x; } // expected-error {{returning 'long double' from a function with incompatible result type '__ibm128'}}
+
+void imp_cast(__ibm128 w, __float128 q, long double l, _Bool b) {
+  w + q;      // expected-error {{invalid operands to binary expression ('__ibm128' and '__float128')}}
+  l + w;      // expected-error {{invalid operands to binary expression ('long double' and '__ibm128')}}
+  q - w;      // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
+  w - l;      // expected-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
+  w *l;       // expected-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
+  q *w;       // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
+  q / w;      // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
+  w / l;      // expected-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
+  w = q;      // expected-error {{assigning to '__ibm128' from incompatible type '__float128'}}
+  q = w;      // expected-error {{assigning to '__float128' from incompatible type '__ibm128'}}
+  l = w;      // expected-error {{assigning to 'long double' from incompatible type '__ibm128'}}
+  w = l;      // expected-error {{assigning to '__ibm128' from incompatible type 'long double'}}
+  b ? q : w;  // expected-error {{incompatible operand types ('__float128' and '__ibm128')}}
+  !b ? w : l; // expected-error {{incompatible operand types ('__ibm128' and 'long double')}}
+}
+#elif __LONG_DOUBLE_IBM128__
+long double cast3(__ibm128 x) { return x; } // expected-no-error {{returning '__ibm128' from a function with incompatible result type 'long double'}}
+
+__ibm128 cast4(long double x) { return x; } // expected-no-error {{returning 'long double' from a function with incompatible result type '__ibm128'}}
+
+void imp_cast(__ibm128 w, __float128 q, long double l, _Bool b) {
+  w + q;      // expected-error {{invalid operands to binary expression ('__ibm128' and '__float128')}}
+  l + w;      // expected-no-error {{invalid operands to binary expression ('long double' and '__ibm128')}}
+  q - w;      // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
+  w - l;      // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
+  w *l;       // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
+  q *w;       // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
+  q / w;      // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
+  w / l;      // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
+  w = q;      // expected-error {{assigning to '__ibm128' from incompatible type '__float128'}}
+  q = w;      // expected-error {{assigning to '__float128' from incompatible type '__ibm128'}}
+  l = w;      // expected-no-error {{assigning to 'long double' from incompatible type '__ibm128'}}
+  w = l;      // expected-no-error {{assigning to '__ibm128' from incompatible type 'long double'}}
+  b ? q : w;  // expected-error {{incompatible operand types ('__float128' and '__ibm128')}}
+  !b ? w : l; // expected-no-error {{incompatible operand types ('__ibm128' and 'long double')}}
+}
+#endif

diff  --git a/clang/test/CodeGen/ibm128-unsupported.c b/clang/test/CodeGen/ibm128-unsupported.c
new file mode 100644
index 0000000000000..4ade7ddaa1e39
--- /dev/null
+++ b/clang/test/CodeGen/ibm128-unsupported.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple powerpc64le -emit-llvm-bc -fopenmp %s \
+// RUN:   -fopenmp-targets=powerpc64le,x86_64 -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -triple x86_64 -aux-triple powerpc64le -fopenmp \
+// RUN:   -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc %s \
+// RUN:   -fsyntax-only
+
+void foo(__ibm128 x); // expected-note {{'foo' defined here}}
+
+void loop(int n, __ibm128 *arr) {
+#pragma omp target parallel
+  for (int i = 0; i < n; ++i) {
+    // expected-error at +1 {{'foo' requires 128 bit size '__ibm128' type support, but device 'x86_64' does not support it}}
+    foo(arr[i]);
+  }
+}

diff  --git a/clang/test/CodeGenCXX/ibm128-declarations.cpp b/clang/test/CodeGenCXX/ibm128-declarations.cpp
new file mode 100644
index 0000000000000..7ff23aa1e0f85
--- /dev/null
+++ b/clang/test/CodeGenCXX/ibm128-declarations.cpp
@@ -0,0 +1,169 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -emit-llvm -triple powerpc64-unknown-unknown \
+// RUN:   -std=c++20 %s -o - -debug-info-kind=limited | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown \
+// RUN:   -std=c++20 %s -o - -debug-info-kind=limited | FileCheck %s
+
+#include <stdarg.h>
+
+static __ibm128 sgf;
+__ibm128 arrgf[10];
+__ibm128 func1(__ibm128 arg);
+
+class CTest {
+  __ibm128 pf;
+  static const __ibm128 scf;
+  volatile __ibm128 vf;
+
+public:
+  CTest(__ibm128 arg) : pf(arg), vf(arg) {}
+  __ibm128 func2(__ibm128 arg) {
+    return pf + arg;
+  }
+  static __ibm128 func3(__ibm128 arg) {
+    return arg * CTest::scf;
+  }
+};
+
+constexpr __ibm128 func_add(__ibm128 a, __ibm128 b) {
+  return a + b;
+}
+
+constinit const __ibm128 ci = func_add(1.0, 2.0);
+__ibm128 gf = ci;
+
+__ibm128 func_arith(__ibm128 a, __ibm128 b, __ibm128 c) {
+  __ibm128 v1 = a + b;
+  __ibm128 v2 = a - c;
+  __ibm128 v3 = v1 * c;
+  __ibm128 v4 = v2 / v3;
+  return v4;
+}
+
+__ibm128 func_vaarg(int n, ...) {
+  va_list ap;
+  va_start(ap, n);
+  __ibm128 r = va_arg(ap, __ibm128);
+  va_end(ap);
+  return r;
+}
+
+template <typename T> struct T1 {
+  T mem1;
+};
+template <> struct T1<__ibm128> {
+  __ibm128 mem2;
+};
+
+template <__ibm128 Q> struct T2 {
+  constexpr static __ibm128 mem = Q;
+};
+
+int main(void) {
+  __ibm128 lf;
+  CTest ct(lf);
+  T1<__ibm128> tf;
+  __ibm128 lfi = tf.mem2 + func1(lf) - CTest::func3(lf);
+}
+
+// CHECK: %class.CTest = type { ppc_fp128, ppc_fp128 }
+// CHECK: %struct.T1 = type { ppc_fp128 }
+
+// CHECK: @arrgf = global [10 x ppc_fp128] zeroinitializer, align 16
+// CHECK: @gf = global ppc_fp128 0xM40080000000000000000000000000000, align 16
+// CHECK: @_ZN5CTest3scfE = external constant ppc_fp128, align 16
+
+// CHECK: define dso_local ppc_fp128 @_Z10func_arithggg(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c)
+// CHECK: entry:
+// CHECK:   store ppc_fp128 %a, ppc_fp128* %a.addr, align 16
+// CHECK:   store ppc_fp128 %b, ppc_fp128* %b.addr, align 16
+// CHECK:   store ppc_fp128 %c, ppc_fp128* %c.addr, align 16
+// CHECK:   %0 = load ppc_fp128, ppc_fp128* %a.addr, align 16
+// CHECK:   %1 = load ppc_fp128, ppc_fp128* %b.addr, align 16
+// CHECK:   %add = fadd ppc_fp128 %0, %1
+// CHECK:   store ppc_fp128 %add, ppc_fp128* %v1, align 16
+// CHECK:   %2 = load ppc_fp128, ppc_fp128* %a.addr, align 16
+// CHECK:   %3 = load ppc_fp128, ppc_fp128* %c.addr, align 16
+// CHECK:   %sub = fsub ppc_fp128 %2, %3
+// CHECK:   store ppc_fp128 %sub, ppc_fp128* %v2, align 16
+// CHECK:   %4 = load ppc_fp128, ppc_fp128* %v1, align 16
+// CHECK:   %5 = load ppc_fp128, ppc_fp128* %c.addr, align 16
+// CHECK:   %mul = fmul ppc_fp128 %4, %5
+// CHECK:   store ppc_fp128 %mul, ppc_fp128* %v3, align 16
+// CHECK:   %6 = load ppc_fp128, ppc_fp128* %v2, align 16
+// CHECK:   %7 = load ppc_fp128, ppc_fp128* %v3, align 16
+// CHECK:   %div = fdiv ppc_fp128 %6, %7
+// CHECK:   store ppc_fp128 %div, ppc_fp128* %v4, align 16
+// CHECK:   %8 = load ppc_fp128, ppc_fp128* %v4, align 16
+// CHECK:   ret ppc_fp128 %8
+// CHECK: }
+
+// CHECK: define dso_local ppc_fp128 @_Z10func_vaargiz(i32 signext %n, ...)
+// CHECK: entry:
+// CHECK:   store i32 %n, i32* %n.addr, align 4
+// CHECK:   %ap1 = bitcast i8** %ap to i8*
+// CHECK:   call void @llvm.va_start(i8* %ap1)
+// CHECK:   %argp.cur = load i8*, i8** %ap, align 8
+// CHECK:   %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 16
+// CHECK:   store i8* %argp.next, i8** %ap, align 8
+// CHECK:   %0 = bitcast i8* %argp.cur to ppc_fp128*
+// CHECK:   %1 = load ppc_fp128, ppc_fp128* %0, align 8
+// CHECK:   store ppc_fp128 %1, ppc_fp128* %r, align 16
+// CHECK:   %ap2 = bitcast i8** %ap to i8*
+// CHECK:   call void @llvm.va_end(i8* %ap2)
+// CHECK:   %2 = load ppc_fp128, ppc_fp128* %r, align 16
+// CHECK:   ret ppc_fp128 %2
+// CHECK: }
+
+// CHECK: define dso_local signext i32 @main()
+// CHECK: entry:
+// CHECK:   %0 = load ppc_fp128, ppc_fp128* %lf, align 16
+// CHECK:   call void @_ZN5CTestC1Eg(%class.CTest* nonnull align 16 dereferenceable(32) %ct, ppc_fp128 %0)
+// CHECK:   %mem2 = getelementptr inbounds %struct.T1, %struct.T1* %tf, i32 0, i32 0
+// CHECK:   %1 = load ppc_fp128, ppc_fp128* %mem2, align 16
+// CHECK:   %2 = load ppc_fp128, ppc_fp128* %lf, align 16
+// CHECK:   %call = call ppc_fp128 @_Z5func1g(ppc_fp128 %2)
+// CHECK:   %add = fadd ppc_fp128 %1, %call
+// CHECK:   %3 = load ppc_fp128, ppc_fp128* %lf, align 16
+// CHECK:   %call1 = call ppc_fp128 @_ZN5CTest5func3Eg(ppc_fp128 %3)
+// CHECK:   %sub = fsub ppc_fp128 %add, %call1
+// CHECK:   store ppc_fp128 %sub, ppc_fp128* %lfi, align 16
+// CHECK:   ret i32 0
+// CHECK: }
+
+// CHECK: define linkonce_odr void @_ZN5CTestC1Eg(%class.CTest* nonnull align 16 dereferenceable(32) %this, ppc_fp128 %arg)
+// CHECK: entry:
+// CHECK:   store %class.CTest* %this, %class.CTest** %this.addr, align 8
+// CHECK:   store ppc_fp128 %arg, ppc_fp128* %arg.addr, align 16
+// CHECK:   %this1 = load %class.CTest*, %class.CTest** %this.addr, align 8
+// CHECK:   %0 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
+// CHECK:   call void @_ZN5CTestC2Eg(%class.CTest* nonnull align 16 dereferenceable(32) %this1, ppc_fp128 %0)
+// CHECK:   ret void
+// CHECK: }
+
+// CHECK: define linkonce_odr ppc_fp128 @_ZN5CTest5func3Eg(ppc_fp128 %arg)
+// CHECK: entry:
+// CHECK:   %arg.addr = alloca ppc_fp128, align 16
+// CHECK:   store ppc_fp128 %arg, ppc_fp128* %arg.addr, align 16
+// CHECK:   %0 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
+// CHECK:   %1 = load ppc_fp128, ppc_fp128* @_ZN5CTest3scfE, align 16
+// CHECK:   %mul = fmul ppc_fp128 %0, %1
+// CHECK:   ret ppc_fp128 %mul
+// CHECK: }
+
+// CHECK: define linkonce_odr void @_ZN5CTestC2Eg(%class.CTest* nonnull align 16 dereferenceable(32) %this, ppc_fp128 %arg)
+// CHECK: entry:
+// CHECK:   store %class.CTest* %this, %class.CTest** %this.addr, align 8
+// CHECK:   store ppc_fp128 %arg, ppc_fp128* %arg.addr, align 16
+// CHECK:   %this1 = load %class.CTest*, %class.CTest** %this.addr, align 8
+// CHECK:   %pf = getelementptr inbounds %class.CTest, %class.CTest* %this1, i32 0, i32 0
+// CHECK:   %0 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
+// CHECK:   store ppc_fp128 %0, ppc_fp128* %pf, align 16
+// CHECK:   %vf = getelementptr inbounds %class.CTest, %class.CTest* %this1, i32 0, i32 1
+// CHECK:   %1 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
+// CHECK:   store volatile ppc_fp128 %1, ppc_fp128* %vf, align 16
+// CHECK:   ret void
+// CHECK: }
+
+// CHECK: !6 = distinct !DIGlobalVariable(name: "gf", scope: !2, file: !7, line: {{[0-9]+}}, type: !8, isLocal: false, isDefinition: true)
+// CHECK: !8 = !DIBasicType(name: "__ibm128", size: 128, encoding: DW_ATE_float)

diff  --git a/clang/test/Sema/128bitfloat.cpp b/clang/test/Sema/128bitfloat.cpp
index 6a9ae743c6f06..6b9d63e6af4cf 100644
--- a/clang/test/Sema/128bitfloat.cpp
+++ b/clang/test/Sema/128bitfloat.cpp
@@ -20,7 +20,7 @@ int g(int x, __float128 *y) {
   return x + *y;
 }
 
-// expected-no-diagnostics
+// expected-no-error {{__float128 is not supported on this target}}
 #else
 #if !defined(__STRICT_ANSI__)
 __float128 f;  // expected-error {{__float128 is not supported on this target}}
@@ -44,3 +44,18 @@ int g(int x, __float128 *y) {  // expected-error {{__float128 is not supported o
 
 #endif
 #endif
+
+#ifdef __ppc__
+__ibm128 i;
+template <> struct __is_floating_point_helper<__ibm128> {};
+int w(int x, __ibm128 *y) {
+  return x + *y;
+}
+// expected-no-error {{__ibm128 is not supported on this target}}
+#else
+__ibm128 i;                                                 // expected-error {{__ibm128 is not supported on this target}}
+template <> struct __is_floating_point_helper<__ibm128> {}; // expected-error {{__ibm128 is not supported on this target}}
+int w(int x, __ibm128 *y) {                                 // expected-error {{__ibm128 is not supported on this target}}
+  return x + *y;
+}
+#endif

diff  --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index 0199c95b356da..822ab3bb64b8e 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -60,6 +60,7 @@ static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
     BTCASE(ULongAccum);
     BTCASE(Float16);
     BTCASE(Float128);
+    BTCASE(Ibm128);
     BTCASE(NullPtr);
     BTCASE(Overload);
     BTCASE(Dependent);
@@ -577,6 +578,7 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
     TKIND(ULongAccum);
     TKIND(Float16);
     TKIND(Float128);
+    TKIND(Ibm128);
     TKIND(NullPtr);
     TKIND(Overload);
     TKIND(Dependent);


        


More information about the cfe-commits mailing list