diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -2059,6 +2059,7 @@ 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 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -3298,8 +3298,9 @@ 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 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1076,7 +1076,7 @@ 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 --- a/clang/include/clang/AST/BuiltinTypes.def +++ b/clang/include/clang/AST/BuiltinTypes.def @@ -218,6 +218,9 @@ // '__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 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2003,6 +2003,7 @@ 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 @@ } 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 @@ 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 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -581,10 +581,9 @@ 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 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -59,6 +59,7 @@ 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 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -64,7 +64,7 @@ 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 @@ 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 @@ Float = 0, Double, LongDouble, - Float128 + Float128, + Ibm128 }; + protected: IntType SizeType, IntMaxType, PtrDiffType, IntPtrType, WCharType, WIntType, Char16Type, Char32Type, Int64Type, Int16Type, SigAtomicType, @@ -200,6 +202,7 @@ bool HasFloat128; bool HasFloat16; bool HasBFloat16; + bool HasIbm128; bool HasStrictFP; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; @@ -594,6 +597,9 @@ /// 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 @@ 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 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -438,6 +438,7 @@ 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 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -275,6 +275,7 @@ 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 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1064,6 +1064,9 @@ /// \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 --- 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 @@ // 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 @@ 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 @@ 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 @@ case BuiltinType::LongDouble: return LongDoubleRank; case BuiltinType::Float128: return Float128Rank; case BuiltinType::BFloat16: return BFloat16Rank; + case BuiltinType::Ibm128: return Ibm128Rank; } } @@ -6324,6 +6341,7 @@ 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 @@ 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 @@ 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 @@ 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 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2860,6 +2860,7 @@ // ::= 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 @@ 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 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2466,6 +2466,7 @@ 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 --- a/clang/lib/AST/NSAPI.cpp +++ b/clang/lib/AST/NSAPI.cpp @@ -456,6 +456,7 @@ 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 --- a/clang/lib/AST/PrintfFormatString.cpp +++ b/clang/lib/AST/PrintfFormatString.cpp @@ -755,6 +755,7 @@ 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 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1183,6 +1183,7 @@ switch (Node->getType()->castAs()->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 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2097,7 +2097,7 @@ bool Type::isFloatingType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Half && - BT->getKind() <= BuiltinType::Float128; + BT->getKind() <= BuiltinType::Ibm128; if (const auto *CT = dyn_cast(CanonicalType)) return CT->getElementType()->isFloatingType(); return false; @@ -2119,7 +2119,7 @@ bool Type::isRealType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Float128; + BT->getKind() <= BuiltinType::Ibm128; if (const auto *ET = dyn_cast(CanonicalType)) return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); return isExtIntType(); @@ -2128,7 +2128,7 @@ bool Type::isArithmeticType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Float128 && + BT->getKind() <= BuiltinType::Ibm128 && BT->getKind() != BuiltinType::BFloat16; if (const auto *ET = dyn_cast(CanonicalType)) // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). @@ -3030,6 +3030,8 @@ 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 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -351,6 +351,7 @@ 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 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -34,6 +34,7 @@ NoAsmVariants = false; HasLegalHalfType = false; HasFloat128 = false; + HasIbm128 = false; HasFloat16 = false; HasBFloat16 = false; HasStrictFP = false; @@ -83,6 +84,7 @@ LongDoubleWidth = 64; LongDoubleAlign = 64; Float128Align = 128; + Ibm128Align = 128; LargeArrayMinWidth = 0; LargeArrayAlign = 0; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0; @@ -113,6 +115,7 @@ 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 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -89,6 +89,7 @@ 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 @@ : "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 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -830,11 +830,12 @@ 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 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2680,7 +2680,8 @@ amt = llvm::ConstantFP::get(VMContext, llvm::APFloat(static_cast(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(amount)); bool ignored; const llvm::fltSemantics *FS; @@ -2690,6 +2691,8 @@ 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 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -512,6 +512,7 @@ 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 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3269,6 +3269,7 @@ 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 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5226,8 +5226,9 @@ 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 --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -53,6 +53,7 @@ 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 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -705,6 +705,7 @@ 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 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3929,6 +3929,10 @@ 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 @@ 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 @@ 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 @@ 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 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1521,6 +1521,7 @@ 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 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -2226,6 +2226,9 @@ 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 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1637,6 +1637,7 @@ 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 @@ 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 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -358,6 +358,7 @@ 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 @@ 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 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1887,12 +1887,22 @@ return; } + // Check if we are dealing with two 'long double' but with different + // 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(Context.getTypeSize(Ty)) << Ty diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -141,6 +141,7 @@ 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 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1197,45 +1197,32 @@ /*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(); auto *RHSComplex = RHSType->getAs(); - 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 @@ // At this point, we have two different 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 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 @@ 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 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1869,24 +1869,25 @@ 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 different until there is back end support + // FIXME: disable conversions between long double, __ibm128 and __float128 + // if their representation is different 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 @@ (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 @@ 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 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -893,6 +893,7 @@ 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 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1547,6 +1547,13 @@ << "__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 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -168,6 +168,9 @@ 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 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6940,6 +6940,9 @@ 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 --- /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 --- /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@+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 --- /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 + +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 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 --- a/clang/test/Sema/128bitfloat.cpp +++ b/clang/test/Sema/128bitfloat.cpp @@ -20,7 +20,7 @@ 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 @@ #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 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -60,6 +60,7 @@ BTCASE(ULongAccum); BTCASE(Float16); BTCASE(Float128); + BTCASE(Ibm128); BTCASE(NullPtr); BTCASE(Overload); BTCASE(Dependent); @@ -577,6 +578,7 @@ TKIND(ULongAccum); TKIND(Float16); TKIND(Float128); + TKIND(Ibm128); TKIND(NullPtr); TKIND(Overload); TKIND(Dependent);