Index: bindings/python/clang/cindex.py =================================================================== --- bindings/python/clang/cindex.py +++ bindings/python/clang/cindex.py @@ -1682,6 +1682,7 @@ TypeKind.OBJCID = TypeKind(27) TypeKind.OBJCCLASS = TypeKind(28) TypeKind.OBJCSEL = TypeKind(29) +TypeKind.FLOAT128 = TypeKind(30) TypeKind.COMPLEX = TypeKind(100) TypeKind.POINTER = TypeKind(101) TypeKind.BLOCKPOINTER = TypeKind(102) Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -2883,6 +2883,7 @@ CXType_ObjCId = 27, CXType_ObjCClass = 28, CXType_ObjCSel = 29, + CXType_Float128 = 30, CXType_FirstBuiltin = CXType_Void, CXType_LastBuiltin = CXType_ObjCSel, Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -887,9 +887,10 @@ CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; - CanQualType FloatTy, DoubleTy, LongDoubleTy; + CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; + CanQualType Float128ComplexTy; CanQualType VoidPtrTy, NullPtrTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType BuiltinFnTy; @@ -964,9 +965,6 @@ /// \brief Retrieve the declaration for the 128-bit unsigned integer type. TypedefDecl *getUInt128Decl() const; - /// \brief Retrieve the declaration for a 128-bit float stub type. - TypeDecl *getFloat128StubType() const; - //===--------------------------------------------------------------------===// // Type Constructors //===--------------------------------------------------------------------===// Index: include/clang/AST/BuiltinTypes.def =================================================================== --- include/clang/AST/BuiltinTypes.def +++ include/clang/AST/BuiltinTypes.def @@ -133,6 +133,9 @@ // 'long double' FLOATING_TYPE(LongDouble, LongDoubleTy) +// '__float128' +FLOATING_TYPE(Float128, Float128Ty) + //===- Language-specific types --------------------------------------------===// // This is the type of C++0x 'nullptr'. Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -2049,7 +2049,7 @@ } bool isFloatingPoint() const { - return getKind() >= Half && getKind() <= LongDouble; + return getKind() >= Half && getKind() <= Float128; } /// Determines whether the given kind corresponds to a placeholder type. Index: include/clang/AST/TypeLoc.h =================================================================== --- include/clang/AST/TypeLoc.h +++ include/clang/AST/TypeLoc.h @@ -538,7 +538,7 @@ bool needsExtraLocalData() const { BuiltinType::Kind bk = getTypePtr()->getKind(); return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) - || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble) + || (bk >= BuiltinType::Short && bk <= BuiltinType::Float128) || bk == BuiltinType::UChar || bk == BuiltinType::SChar; } Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5158,8 +5158,6 @@ "arithmetic on%select{ a|}0 pointer%select{|s}0 to void">; def err_typecheck_decl_incomplete_type : Error< "variable has incomplete type %0">; -def err_typecheck_decl_incomplete_type___float128 : Error< - "support for type '__float128' is not yet implemented">; def ext_typecheck_decl_incomplete_type : ExtWarn< "tentative definition of variable with internal linkage has incomplete non-array type %0">, InGroup>; @@ -7459,8 +7457,8 @@ "feature, not permitted in C++">; def err_type_requires_extension : Error< "use of type %0 requires %1 extension to be enabled">; -def err_int128_unsupported : Error< - "__int128 is not supported on this target">; +def err_type_unsupported : Error< + "%0 is not supported on this target">; def err_nsconsumed_attribute_mismatch : Error< "overriding method has mismatched ns_consumed attribute on its" " parameter">; Index: include/clang/Basic/Specifiers.h =================================================================== --- include/clang/Basic/Specifiers.h +++ include/clang/Basic/Specifiers.h @@ -49,6 +49,7 @@ TST_half, // OpenCL half, ARM NEON __fp16 TST_float, TST_double, + TST_float128, TST_bool, // _Bool TST_decimal32, // _Decimal32 TST_decimal64, // _Decimal64 Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -78,7 +78,7 @@ const char *UserLabelPrefix; const char *MCountName; const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat, - *LongDoubleFormat; + *LongDoubleFormat, *Float128Format; unsigned char RegParmMax, SSERegParmMax; TargetCXXABI TheCXXABI; const LangAS::Map *AddrSpaceMap; @@ -132,7 +132,8 @@ NoFloat = 255, Float = 0, Double, - LongDouble + LongDouble, + Float128 }; /// \brief The different kinds of __builtin_va_list types defined by @@ -320,6 +321,11 @@ return getPointerWidth(0) >= 64; } // FIXME + /// \brief Determine whether the __float128 type is supported on this target. + virtual bool hasFloat128Type() const { + return false; + } + /// \brief Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } @@ -372,6 +378,14 @@ return *LongDoubleFormat; } + /// getFloat128Width/Align/Format - Return the size/align/format of + /// '__float128'. + unsigned getFloat128Width() const { return 128; } + unsigned getFloat128Align() const { return 128; } + const llvm::fltSemantics &getFloat128Format() const { + return *Float128Format; + } + /// \brief Return true if the 'long double' type should be mangled like /// __float128. virtual bool useFloat128ManglingForLongDouble() const { return false; } Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -377,6 +377,7 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX) KEYWORD(__builtin_va_arg , KEYALL) KEYWORD(__extension__ , KEYALL) +KEYWORD(__float128 , KEYALL) KEYWORD(__imag , KEYALL) KEYWORD(__int128 , KEYALL) KEYWORD(__label__ , KEYALL) Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1420,6 +1420,10 @@ def mno_invariant_function_descriptors : Flag<["-"], "mno-invariant-function-descriptors">, Group; +def mfloat128: Flag<["-"], "mfloat128">, + Group; +def mnofloat128 : Flag<["-"], "mno-float128">, + Group; def faltivec : Flag<["-"], "faltivec">, Group, Flags<[CC1Option]>, HelpText<"Enable AltiVec vector initializer syntax">; Index: include/clang/Lex/LiteralSupport.h =================================================================== --- include/clang/Lex/LiteralSupport.h +++ include/clang/Lex/LiteralSupport.h @@ -63,6 +63,7 @@ bool isLongLong : 1; bool isFloat : 1; // 1.0f bool isImaginary : 1; // 1.0i + bool isFloat128 : 1; // 1.0q uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. bool isIntegerLiteral() const { Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -280,6 +280,7 @@ static const TST TST_half = clang::TST_half; static const TST TST_float = clang::TST_float; static const TST TST_double = clang::TST_double; + static const TST TST_float128 = clang::TST_float128; static const TST TST_bool = clang::TST_bool; static const TST TST_decimal32 = clang::TST_decimal32; static const TST TST_decimal64 = clang::TST_decimal64; Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -809,7 +809,9 @@ /// \brief OpenCL reserve_id type. PREDEF_TYPE_RESERVE_ID_ID = 54, /// \brief The placeholder type for OpenMP array section. - PREDEF_TYPE_OMP_ARRAY_SECTION = 55 + PREDEF_TYPE_OMP_ARRAY_SECTION = 55, + /// \brief The '__float128' type + PREDEF_TYPE_FLOAT128_ID = 56 }; /// \brief The number of predefined type IDs that are reserved for Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -57,7 +57,7 @@ unsigned ASTContext::NumImplicitDestructorsDeclared; enum FloatingRank { - HalfRank, FloatRank, DoubleRank, LongDoubleRank + HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { @@ -968,14 +968,6 @@ return UInt128Decl; } -TypeDecl *ASTContext::getFloat128StubType() const { - assert(LangOpts.CPlusPlus && "should only be called for c++"); - if (!Float128StubDecl) - Float128StubDecl = buildImplicitRecord("__float128"); - - return Float128StubDecl; -} - void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); R = CanQualType::CreateUnsafe(QualType(Ty, 0)); @@ -1024,6 +1016,9 @@ InitBuiltinType(DoubleTy, BuiltinType::Double); InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble); + // GNU extension, __float128 for IEEE quadruple precision + InitBuiltinType(Float128Ty, BuiltinType::Float128); + // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); @@ -1085,6 +1080,7 @@ FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); LongDoubleComplexTy = getComplexType(LongDoubleTy); + Float128ComplexTy = getComplexType(Float128Ty); // Builtin types for 'id', 'Class', and 'SEL'. InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); @@ -1352,6 +1348,7 @@ case BuiltinType::Float: return Target->getFloatFormat(); case BuiltinType::Double: return Target->getDoubleFormat(); case BuiltinType::LongDouble: return Target->getLongDoubleFormat(); + case BuiltinType::Float128: return Target->getFloat128Format(); } } @@ -1662,6 +1659,10 @@ Width = Target->getLongDoubleWidth(); Align = Target->getLongDoubleAlign(); break; + case BuiltinType::Float128: + Width = Target->getFloat128Width(); + Align = Target->getFloat128Align(); + break; case BuiltinType::NullPtr: Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) Align = Target->getPointerAlign(0); // == sizeof(void*) @@ -4582,6 +4583,7 @@ case BuiltinType::Float: return FloatRank; case BuiltinType::Double: return DoubleRank; case BuiltinType::LongDouble: return LongDoubleRank; + case BuiltinType::Float128: return Float128Rank; } } @@ -4598,6 +4600,7 @@ case FloatRank: return FloatComplexTy; case DoubleRank: return DoubleComplexTy; case LongDoubleRank: return LongDoubleComplexTy; + case Float128Rank: return Float128ComplexTy; } } @@ -4607,6 +4610,7 @@ case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; case LongDoubleRank: return LongDoubleTy; + case Float128Rank: return Float128Ty; } llvm_unreachable("getFloatingRank(): illegal value for rank"); } @@ -5409,6 +5413,7 @@ case BuiltinType::LongDouble: return 'D'; case BuiltinType::NullPtr: return '*'; // like char* + case BuiltinType::Float128: case BuiltinType::Half: // FIXME: potentially need @encodes for these! return ' '; @@ -8562,6 +8567,8 @@ return DoubleTy; case TargetInfo::LongDouble: return LongDoubleTy; + case TargetInfo::Float128: + return Float128Ty; case TargetInfo::NoFloat: return QualType(); } Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -1979,7 +1979,7 @@ // ::= f # float // ::= d # double // ::= e # long double, __float80 - // UNSUPPORTED: ::= g # __float128 + // ::= g # __float128 // 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) @@ -2059,6 +2059,12 @@ ? 'g' : 'e'); break; + case BuiltinType::Float128: + if (getASTContext().getTargetInfo().useFloat128ManglingForLongDouble()) + Out << "U10__float128"; // Match the GCC mangling + else + Out << 'g'; + break; case BuiltinType::NullPtr: Out << "Dn"; break; Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1705,6 +1705,7 @@ Out << "$$T"; break; + case BuiltinType::Float128: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( Index: lib/AST/NSAPI.cpp =================================================================== --- lib/AST/NSAPI.cpp +++ lib/AST/NSAPI.cpp @@ -441,6 +441,7 @@ case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::UInt128: + case BuiltinType::Float128: case BuiltinType::NullPtr: case BuiltinType::ObjCClass: case BuiltinType::ObjCId: Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1231,6 +1231,7 @@ case BuiltinType::Double: break; // no suffix. case BuiltinType::Float: OS << 'F'; break; case BuiltinType::LongDouble: OS << 'L'; break; + case BuiltinType::Float128: OS << 'Q'; break; } } Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -1777,7 +1777,7 @@ bool Type::isFloatingType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Half && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const ComplexType *CT = dyn_cast(CanonicalType)) return CT->getElementType()->isFloatingType(); return false; @@ -1799,7 +1799,7 @@ bool Type::isRealType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const EnumType *ET = dyn_cast(CanonicalType)) return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); return false; @@ -1808,7 +1808,7 @@ bool Type::isArithmeticType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const EnumType *ET = dyn_cast(CanonicalType)) // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. @@ -2552,6 +2552,8 @@ return "double"; case LongDouble: return "long double"; + case Float128: + return "__float128"; case WChar_S: case WChar_U: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; Index: lib/AST/TypeLoc.cpp =================================================================== --- lib/AST/TypeLoc.cpp +++ lib/AST/TypeLoc.cpp @@ -320,6 +320,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float128: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. Index: lib/Analysis/PrintfFormatString.cpp =================================================================== --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -611,6 +611,7 @@ case BuiltinType::UInt128: case BuiltinType::Int128: case BuiltinType::Half: + case BuiltinType::Float128: // Various types which are non-trivial to correct. return false; Index: lib/Basic/TargetInfo.cpp =================================================================== --- lib/Basic/TargetInfo.cpp +++ lib/Basic/TargetInfo.cpp @@ -71,6 +71,7 @@ FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEdouble; LongDoubleFormat = &llvm::APFloat::IEEEdouble; + Float128Format = &llvm::APFloat::IEEEquad; DataLayoutString = nullptr; UserLabelPrefix = "_"; MCountName = "mcount"; @@ -224,6 +225,8 @@ if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble || &getLongDoubleFormat() == &llvm::APFloat::IEEEquad) return LongDouble; + if (hasFloat128Type()) + return Float128; break; } Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -786,6 +786,7 @@ bool HasHTM; bool HasBPERMD; bool HasExtDiv; + bool HasFloat128; protected: std::string ABI; @@ -794,7 +795,7 @@ PPCTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple), HasVSX(false), HasP8Vector(false), HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false), - HasBPERMD(false), HasExtDiv(false) { + HasBPERMD(false), HasExtDiv(false), HasFloat128(false) { BigEndian = (Triple.getArch() != llvm::Triple::ppc64le); SimdDefaultAlign = 128; LongDoubleWidth = LongDoubleAlign = 128; @@ -1038,6 +1039,9 @@ LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble && getTriple().isOSBinFormatELF(); } + bool hasFloat128Type() const override { + return HasFloat128; + } }; const Builtin::Info PPCTargetInfo::BuiltinInfo[] = { @@ -1069,6 +1073,8 @@ HasQPX = true; } else if (Feature == "+htm") { HasHTM = true; + } else if (Feature == "+float128") { + HasFloat128 = true; } // TODO: Finish this list and add an assert that we've handled them // all. @@ -1226,6 +1232,8 @@ Builder.defineMacro("__CRYPTO__"); if (HasHTM) Builder.defineMacro("__HTM__"); + if (HasFloat128) + Builder.defineMacro("__FLOAT128__"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); @@ -1276,6 +1284,13 @@ << "-mno-vsx"; return false; } + + if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") != + FeaturesVec.end()) { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" + << "-mno-vsx"; + return false; + } } return true; @@ -1344,6 +1359,7 @@ .Case("htm", HasHTM) .Case("bpermd", HasBPERMD) .Case("extdiv", HasExtDiv) + .Case("float128", HasFloat128) .Default(false); } @@ -1353,19 +1369,19 @@ // as well. Do the inverse if we're disabling vsx. We'll diagnose any user // incompatible options. if (Enabled) { - if (Name == "vsx") { - Features[Name] = true; - } else if (Name == "direct-move") { + if (Name == "direct-move") { Features[Name] = Features["vsx"] = true; } else if (Name == "power8-vector") { Features[Name] = Features["vsx"] = true; + } else if (Name == "float128") { + Features[Name] = Features["vsx"] = true; } else { Features[Name] = true; } } else { if (Name == "vsx") { Features[Name] = Features["direct-move"] = Features["power8-vector"] = - false; + Features["float128"] = false; } else { Features[Name] = false; } Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -536,6 +536,7 @@ case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::LongDouble: + case BuiltinType::Float128: case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break; Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -1796,15 +1796,17 @@ amt = llvm::ConstantFP::get(VMContext, llvm::APFloat(static_cast(amount))); else { - // Remaining types are either Half or LongDouble. Convert from float. + // Remaining types are Half, LongDouble or __float128. Convert from float. llvm::APFloat F(static_cast(amount)); bool ignored; + const llvm::fltSemantics *FS = &CGF.getTarget().getLongDoubleFormat(); // Don't use getFloatTypeSemantics because Half isn't // necessarily represented using the "half" LLVM type. - F.convert(value->getType()->isHalfTy() - ? CGF.getTarget().getHalfFormat() - : CGF.getTarget().getLongDoubleFormat(), - llvm::APFloat::rmTowardZero, &ignored); + if (value->getType()->isFP128Ty()) + FS = &CGF.getTarget().getFloat128Format(); + else if (value->getType()->isHalfTy()) + FS = &CGF.getTarget().getHalfFormat(); + F.convert(*FS, llvm::APFloat::rmTowardZero, &ignored); amt = llvm::ConstantFP::get(VMContext, F); } value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec"); Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -438,6 +438,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float128: ResultType = getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T), /* UseNativeHalf = */ false); Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -2505,6 +2505,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float128: case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::Int128: @@ -3324,7 +3325,7 @@ getContext().UnsignedLongLongTy, getContext().HalfTy, getContext().FloatTy, getContext().DoubleTy, getContext().LongDoubleTy, getContext().Char16Ty, - getContext().Char32Ty, + getContext().Char32Ty, getContext().Float128Ty }; for (const QualType &FundamentalType : FundamentalTypes) EmitFundamentalRTTIDescriptor(FundamentalType); Index: lib/Format/FormatToken.cpp =================================================================== --- lib/Format/FormatToken.cpp +++ lib/Format/FormatToken.cpp @@ -53,6 +53,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: Index: lib/Frontend/InitPreprocessor.cpp =================================================================== --- lib/Frontend/InitPreprocessor.cpp +++ lib/Frontend/InitPreprocessor.cpp @@ -714,6 +714,8 @@ DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F"); DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), ""); DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L"); + if (TI.hasFloat128Type()) + DefineFloatMacros(Builder, "FLT128", &TI.getFloat128Format(), "Q"); // Define a __POINTER_WIDTH__ macro for stdint.h. Builder.defineMacro("__POINTER_WIDTH__", Index: lib/Index/USRGeneration.cpp =================================================================== --- lib/Index/USRGeneration.cpp +++ lib/Index/USRGeneration.cpp @@ -599,6 +599,8 @@ c = 'd'; break; case BuiltinType::LongDouble: c = 'D'; break; + case BuiltinType::Float128: + c = 'Q'; break; case BuiltinType::NullPtr: c = 'n'; break; #define BUILTIN_TYPE(Id, SingletonId) Index: lib/Lex/LiteralSupport.cpp =================================================================== --- lib/Lex/LiteralSupport.cpp +++ lib/Lex/LiteralSupport.cpp @@ -524,6 +524,7 @@ isLongLong = false; isFloat = false; isImaginary = false; + isFloat128 = false; MicrosoftInteger = 0; hadError = false; @@ -582,9 +583,15 @@ case 'f': // FP Suffix for "float" case 'F': if (!isFPConstant) break; // Error for integer constant. - if (isFloat || isLong) break; // FF, LF invalid. + if (isFloat || isLong || isFloat128) break; // FF, LF, QF invalid. isFloat = true; continue; // Success. + case 'q': // FP Suffix for "__float128" + case 'Q': + if (!isFPConstant) break; // Error for integer constant. + if (isFloat || isLong || isFloat128) break; // FQ, LQ, QQ invalid. + isFloat128 = true; + continue; // Success. case 'u': case 'U': if (isFPConstant) break; // Error for floating constant. @@ -594,7 +601,7 @@ case 'l': case 'L': if (isLong || isLongLong) break; // Cannot be repeated. - if (isFloat) break; // LF invalid. + if (isFloat || isFloat128) break; // LF, QL invalid. // Check for long long. The L's need to be adjacent and the same case. if (s[1] == s[0]) { Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3280,6 +3280,10 @@ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___float128: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw_wchar_t: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); @@ -4257,6 +4261,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: case tok::kw__Decimal32: @@ -4329,6 +4334,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: case tok::kw__Decimal32: @@ -4478,6 +4484,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: case tok::kw__Decimal32: Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -1148,6 +1148,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_void: case tok::kw_typename: case tok::kw_typeof: Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1863,6 +1863,9 @@ case tok::kw_double: DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___float128: + DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw_wchar_t: DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); break; Index: lib/Parse/ParseTentative.cpp =================================================================== --- lib/Parse/ParseTentative.cpp +++ lib/Parse/ParseTentative.cpp @@ -946,6 +946,7 @@ case tok::kw_char: case tok::kw_const: case tok::kw_double: + case tok::kw___float128: case tok::kw_enum: case tok::kw_half: case tok::kw_float: @@ -1424,6 +1425,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_void: case tok::annot_decltype: if (NextToken().is(tok::l_paren)) @@ -1515,6 +1517,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_void: case tok::kw___unknown_anytype: case tok::kw___auto_type: Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -288,6 +288,7 @@ case TST_decimal32: case TST_decimal64: case TST_double: + case TST_float128: case TST_enum: case TST_error: case TST_float: @@ -454,6 +455,7 @@ case DeclSpec::TST_half: return "half"; case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; + case DeclSpec::TST_float128: return "__float128"; case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool"; case DeclSpec::TST_decimal32: return "_Decimal32"; case DeclSpec::TST_decimal64: return "_Decimal64"; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -107,6 +107,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -3301,10 +3301,12 @@ QualType Ty; if (Literal.isFloat) Ty = Context.FloatTy; - else if (!Literal.isLong) - Ty = Context.DoubleTy; - else + else if (Literal.isLong) Ty = Context.LongDoubleTy; + else if (Literal.isFloat128) + Ty = Context.Float128Ty; + else + Ty = Context.DoubleTy; Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation()); Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -662,13 +662,6 @@ NameKind == Sema::LookupRedeclarationWithLinkage) { IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); if (II) { - if (S.getLangOpts().CPlusPlus11 && S.getLangOpts().GNUMode && - II == S.getFloat128Identifier()) { - // libstdc++4.7's type_traits expects type __float128 to exist, so - // insert a dummy type to make that header build in gnu++11 mode. - R.addDecl(S.getASTContext().getFloat128StubType()); - return true; - } if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName && II == S.getASTContext().getMakeIntegerSeqName()) { R.addDecl(S.getASTContext().getMakeIntegerSeqDecl()); Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -1923,7 +1923,14 @@ if (!getLangOpts().CPlusPlus && (FromBuiltin->getKind() == BuiltinType::Float || FromBuiltin->getKind() == BuiltinType::Double) && - (ToBuiltin->getKind() == BuiltinType::LongDouble)) + (ToBuiltin->getKind() == BuiltinType::LongDouble || + ToBuiltin->getKind() == BuiltinType::Float128)) + return true; + + // A long double can be promoted to __float128 + if (!getLangOpts().CPlusPlus && + FromBuiltin->getKind() == BuiltinType::LongDouble && + ToBuiltin->getKind() == BuiltinType::Float128) return true; // Half can be promoted to float. @@ -7150,13 +7157,13 @@ // provided via the getArithmeticType() method below. // The "promoted arithmetic types" are the arithmetic // types are that preserved by promotion (C++ [over.built]p2). - static const unsigned FirstIntegralType = 3; - static const unsigned LastIntegralType = 20; - static const unsigned FirstPromotedIntegralType = 3, - LastPromotedIntegralType = 11; + static const unsigned FirstIntegralType = 4; + static const unsigned LastIntegralType = 21; + static const unsigned FirstPromotedIntegralType = 4, + LastPromotedIntegralType = 12; static const unsigned FirstPromotedArithmeticType = 0, - LastPromotedArithmeticType = 11; - static const unsigned NumArithmeticTypes = 20; + LastPromotedArithmeticType = 12; + static const unsigned NumArithmeticTypes = 21; /// \brief Get the canonical type for a given arithmetic type index. CanQualType getArithmeticType(unsigned index) { @@ -7167,6 +7174,7 @@ &ASTContext::FloatTy, &ASTContext::DoubleTy, &ASTContext::LongDoubleTy, + &ASTContext::Float128Ty, // Start of integral types. &ASTContext::IntTy, Index: lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -727,6 +727,7 @@ case TST_half: case TST_float: case TST_double: + case TST_float128: case TST_bool: case TST_decimal32: case TST_decimal64: Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1323,7 +1323,8 @@ } case DeclSpec::TST_int128: if (!S.Context.getTargetInfo().hasInt128Type()) - S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported); + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__int128"; if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) Result = Context.UnsignedInt128Ty; else @@ -1345,6 +1346,12 @@ declarator.setInvalidType(true); } break; + case DeclSpec::TST_float128: + if (!S.Context.getTargetInfo().hasFloat128Type()) + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__float128"; + Result = Context.Float128Ty; + break; case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool case DeclSpec::TST_decimal32: // _Decimal32 case DeclSpec::TST_decimal64: // _Decimal64 @@ -6689,13 +6696,6 @@ if (Diagnoser.Suppressed) return true; - // We have an incomplete type. Produce a diagnostic. - if (Ident___float128 && - T == Context.getTypeDeclType(Context.getFloat128StubType())) { - Diag(Loc, diag::err_typecheck_decl_incomplete_type___float128); - return true; - } - Diagnoser.diagnose(*this, Loc, T); // If the type was a forward declaration of a class/struct/union Index: lib/Serialization/ASTCommon.cpp =================================================================== --- lib/Serialization/ASTCommon.cpp +++ lib/Serialization/ASTCommon.cpp @@ -91,6 +91,9 @@ case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break; + case BuiltinType::Float128: + ID = PREDEF_TYPE_FLOAT128_ID; + break; case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break; Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -5992,6 +5992,9 @@ case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break; + case PREDEF_TYPE_FLOAT128_ID: + T = Context.Float128Ty; + break; case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break; Index: test/CodeGenCXX/float128-declarations.cpp =================================================================== --- test/CodeGenCXX/float128-declarations.cpp +++ test/CodeGenCXX/float128-declarations.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -emit-llvm -triple powerpc64-unknown-unknown \ +// RUN: -target-feature +float128 -std=c++11 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown \ +// RUN: -target-feature +float128 -std=c++11 %s -o - | FileCheck %s +// +/* Various contexts where type __float128 can appear. */ + +/* Namespace */ +namespace { + __float128 f1n; + __float128 f2n = 33.q; + __float128 arr1n[10]; + __float128 arr2n[] = { 1.2q, 3.0q, 3.e11q }; + const volatile __float128 func1n(const __float128 &arg) { + return arg + f2n + arr1n[4] - arr2n[1]; + } +} + +/* File */ +__float128 f1f; +__float128 f2f = 32.4q; +static __float128 f3f = f2f; +__float128 arr1f[10]; +__float128 arr2f[] = { -1.2q, -3.0q, -3.e11q }; +__float128 func1f(__float128 arg); + +/* Class */ +class C1 { + __float128 f1c; + static const __float128 f2c; + volatile __float128 f3c; +public: + C1(__float128 arg) : f1c(arg), f3c(arg) { } + __float128 func1c(__float128 arg ) { + return f1c + arg; + } + static __float128 func2c(__float128 arg) { + return arg * C1::f2c; + } +}; + +/* Template */ +template C func1t(C arg) { return arg * 2.q; } +template struct S1 { + C mem1; +}; +template <> struct S1<__float128> { + __float128 mem2; +}; + +/* Local */ +int main(void) { + __float128 f1l = 123e220q; + __float128 f2l = -0.q; + __float128 f3l = 1.189731495357231765085759326628007e4932q; + C1 c1(f1l); + S1<__float128> s1 = { 132.q }; + __float128 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + + func1t(f1l) + s1.mem2 - f1n + f2n; +#if (__cplusplus >= 201103L) + auto f5l = -1.q, *f6l = &f2l, f7l = func1t(f3l); +#endif + __float128 f8l = f4l++; + __float128 arr1l[] = { -1.q, -0.q, -11.q }; +} +// CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000 +// CHECK-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000 +// CHECK-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128] +// CHECK-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000] +// CHECK-DAG: define internal fp128 @_ZN12_GLOBAL__N_16func1nERKU10__float128(fp128* +// CHECK-DAG: @f1f = global fp128 0xL00000000000000000000000000000000 +// CHECK-DAG: @f2f = global fp128 0xL33333333333333334004033333333333 +// CHECK-DAG: @arr1f = global [10 x fp128] +// CHECK-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000] +// CHECK-DAG: declare fp128 @_Z6func1fU10__float128(fp128) +// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128 %arg) +// CHECK-DAG: define linkonce_odr fp128 @_ZN2C16func2cEU10__float128(fp128 %arg) +// CHECK-DAG: define linkonce_odr fp128 @_Z6func1tIU10__float128ET_S0_(fp128 %arg) +// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 +// CHECK-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 +// CHECK-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 +// CHECK-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16 +// CHECK-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l +// CHECK-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 +// CHECK-DAG: store fp128 [[INC]], fp128* %f4l Index: test/Preprocessor/init.c =================================================================== --- test/Preprocessor/init.c +++ test/Preprocessor/init.c @@ -5813,6 +5813,23 @@ // PPCPOWER8:#define _ARCH_PWR7 1 // PPCPOWER8:#define _ARCH_PWR8 1 // +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s +// PPC-FLOAT128:#define __FLOAT128__ 1 +// PPC-FLOAT128:#define __FLT128_DECIMAL_DIG__ 36 +// PPC-FLOAT128:#define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966Q +// PPC-FLOAT128:#define __FLT128_DIG__ 33 +// PPC-FLOAT128:#define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34Q +// PPC-FLOAT128:#define __FLT128_HAS_DENORM__ 1 +// PPC-FLOAT128:#define __FLT128_HAS_INFINITY__ 1 +// PPC-FLOAT128:#define __FLT128_HAS_QUIET_NAN__ 1 +// PPC-FLOAT128:#define __FLT128_MANT_DIG__ 113 +// PPC-FLOAT128:#define __FLT128_MAX_10_EXP__ 4932 +// PPC-FLOAT128:#define __FLT128_MAX_EXP__ 16384 +// PPC-FLOAT128:#define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932Q +// PPC-FLOAT128:#define __FLT128_MIN_10_EXP__ (-4931) +// PPC-FLOAT128:#define __FLT128_MIN_EXP__ (-16381) +// PPC-FLOAT128:#define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932Q +// // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -check-prefix PPC64-LINUX %s // // PPC64-LINUX:#define _ARCH_PPC 1 Index: test/Sema/128bitfloat.cpp =================================================================== --- test/Sema/128bitfloat.cpp +++ test/Sema/128bitfloat.cpp @@ -2,23 +2,23 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s #if !defined(__STRICT_ANSI__) -__float128 f; // expected-error {{support for type '__float128' is not yet implemented}} +__float128 f; // expected-error {{__float128 is not supported on this target}} // But this should work: template struct __is_floating_point_helper {}; -template<> struct __is_floating_point_helper<__float128> {}; +template<> struct __is_floating_point_helper<__float128> {}; // expected-error {{__float128 is not supported on this target}} // FIXME: This could have a better diag. -void g(int x, __float128 *y) { - x + *y; // expected-error {{invalid operands to binary expression ('int' and '__float128')}} +int g(int x, __float128 *y) { // expected-error {{__float128 is not supported on this target}} + return x + *y; } #else -__float128 f; // expected-error {{unknown type name '__float128'}} +__float128 f; // expected-error {{__float128 is not supported on this target}} template struct __is_floating_point_helper {}; -template<> struct __is_floating_point_helper<__float128> {}; // expected-error {{use of undeclared identifier '__float128'}} +template<> struct __is_floating_point_helper<__float128> {}; // expected-error {{__float128 is not supported on this target}} -void g(int x, __float128 *y) { // expected-error {{unknown type name '__float128'}} - x + *y; +int g(int x, __float128 *y) { // expected-error {{__float128 is not supported on this target}} + return x + *y; } #endif Index: test/SemaCXX/deleted-operator.cpp =================================================================== --- test/SemaCXX/deleted-operator.cpp +++ test/SemaCXX/deleted-operator.cpp @@ -9,7 +9,7 @@ PR10757 a1; // FIXME: We get a ridiculous number of "built-in candidate" notes here... if(~a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 8 {{built-in candidate}} - if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 121 {{built-in candidate}} + if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 144 {{built-in candidate}} } struct DelOpDel { Index: test/SemaCXX/overloaded-builtin-operators.cpp =================================================================== --- test/SemaCXX/overloaded-builtin-operators.cpp +++ test/SemaCXX/overloaded-builtin-operators.cpp @@ -183,7 +183,7 @@ // FIXME: lots of candidates here! (void)(1.0f * a); // expected-error{{ambiguous}} \ // expected-note 4{{candidate}} \ - // expected-note {{remaining 117 candidates omitted; pass -fshow-overloads=all to show them}} + // expected-note {{remaining 140 candidates omitted; pass -fshow-overloads=all to show them}} } // pr5432 Index: tools/libclang/CXType.cpp =================================================================== --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -51,6 +51,7 @@ BTCASE(Float); BTCASE(Double); BTCASE(LongDouble); + BTCASE(Float128); BTCASE(NullPtr); BTCASE(Overload); BTCASE(Dependent); @@ -460,6 +461,7 @@ TKIND(Float); TKIND(Double); TKIND(LongDouble); + TKIND(Float128); TKIND(NullPtr); TKIND(Overload); TKIND(Dependent);