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 @@ -41,6 +41,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetCXXABI.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/XRayLists.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" @@ -128,7 +129,6 @@ class Stmt; class StoredDeclsMap; class TargetAttr; -class TargetInfo; class TemplateDecl; class TemplateParameterList; class TemplateTemplateParmDecl; @@ -750,7 +750,8 @@ /// getRealTypeForBitwidth - /// sets floating point QualTy according to specified bitwidth. /// Returns empty type if there is no appropriate target types. - QualType getRealTypeForBitwidth(unsigned DestWidth, bool ExplicitIEEE) const; + QualType getRealTypeForBitwidth(unsigned DestWidth, + TargetInfo::RealType ExplicitType) const; bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const; 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 @@ -398,10 +398,8 @@ /// Return floating point type with specified width. On PPC, there are /// three possible types for 128-bit floating point: "PPC double-double", /// IEEE 754R quad precision, and "long double" (which under the covers - /// is represented as one of those two). At this time, there is no support - /// for an explicit "PPC double-double" type (i.e. __ibm128) so we only - /// need to differentiate between "long double" and IEEE quad precision. - RealType getRealTypeByWidth(unsigned BitWidth, bool ExplicitIEEE) const; + /// is represented as one of those two). + RealType getRealTypeByWidth(unsigned BitWidth, RealType ExplicitType) const; /// Return the alignment (in bits) of the specified integer type enum. /// 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 @@ -11260,10 +11260,11 @@ /// getRealTypeForBitwidth - /// sets floating point QualTy according to specified bitwidth. /// Returns empty type if there is no appropriate target types. -QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth, - bool ExplicitIEEE) const { +QualType +ASTContext::getRealTypeForBitwidth(unsigned DestWidth, + TargetInfo::RealType ExplicitType) const { TargetInfo::RealType Ty = - getTargetInfo().getRealTypeByWidth(DestWidth, ExplicitIEEE); + getTargetInfo().getRealTypeByWidth(DestWidth, ExplicitType); switch (Ty) { case TargetInfo::Float: return FloatTy; 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 @@ -279,8 +279,8 @@ return NoInt; } -TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth, - bool ExplicitIEEE) const { +TargetInfo::RealType +TargetInfo::getRealTypeByWidth(unsigned BitWidth, RealType ExplicitType) const { if (getFloatWidth() == BitWidth) return Float; if (getDoubleWidth() == BitWidth) @@ -294,13 +294,10 @@ case 128: // The caller explicitly asked for an IEEE compliant type but we still // have to check if the target supports it. - if (ExplicitIEEE) + if (ExplicitType == Float128) return hasFloat128Type() ? Float128 : NoFloat; - if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble() || - &getLongDoubleFormat() == &llvm::APFloat::IEEEquad()) - return LongDouble; - if (hasFloat128Type()) - return Float128; + if (ExplicitType == Ibm128 || ExplicitType == LongDouble) + return ExplicitType; break; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4203,9 +4203,10 @@ /// attribute. static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, bool &IntegerMode, bool &ComplexMode, - bool &ExplicitIEEE) { + TargetInfo::RealType &ExplicitType) { IntegerMode = true; ComplexMode = false; + ExplicitType = TargetInfo::NoFloat; switch (Str.size()) { case 2: switch (Str[0]) { @@ -4225,13 +4226,17 @@ DestWidth = 96; break; case 'K': // KFmode - IEEE quad precision (__float128) - ExplicitIEEE = true; + ExplicitType = TargetInfo::Float128; DestWidth = Str[1] == 'I' ? 0 : 128; break; case 'T': - ExplicitIEEE = false; + ExplicitType = TargetInfo::LongDouble; DestWidth = 128; break; + case 'I': + ExplicitType = TargetInfo::Ibm128; + DestWidth = Str[1] == 'I' ? 0 : 128; + break; } if (Str[1] == 'F') { IntegerMode = false; @@ -4290,7 +4295,7 @@ unsigned DestWidth = 0; bool IntegerMode = true; bool ComplexMode = false; - bool ExplicitIEEE = false; + TargetInfo::RealType ExplicitType = TargetInfo::NoFloat; llvm::APInt VectorSize(64, 0); if (Str.size() >= 4 && Str[0] == 'V') { // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2). @@ -4303,7 +4308,7 @@ !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && VectorSize.isPowerOf2()) { parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, - IntegerMode, ComplexMode, ExplicitIEEE); + IntegerMode, ComplexMode, ExplicitType); // Avoid duplicate warning from template instantiation. if (!InInstantiation) Diag(AttrLoc, diag::warn_vector_mode_deprecated); @@ -4314,7 +4319,7 @@ if (!VectorSize) parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode, - ExplicitIEEE); + ExplicitType); // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t // and friends, at least with glibc. @@ -4380,7 +4385,7 @@ NewElemTy = Context.getIntTypeForBitwidth(DestWidth, OldElemTy->isSignedIntegerType()); else - NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE); + NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitType); if (NewElemTy.isNull()) { Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name; diff --git a/clang/test/Sema/attr-mode.c b/clang/test/Sema/attr-mode.c --- a/clang/test/Sema/attr-mode.c +++ b/clang/test/Sema/attr-mode.c @@ -92,6 +92,12 @@ void f_ft128_complex_arg(_Complex long double *x); void test_TFtype(f128ibm *a) { f_ft128_arg (a); } void test_TCtype(c128ibm *a) { f_ft128_complex_arg (a); } +typedef float w128ibm __attribute__((mode(IF))); +typedef _Complex float cw128ibm __attribute__((mode(IC))); +void f_ibm128_arg(__ibm128 *x); +void f_ibm128_complex_arg(_Complex __ibm128 *x); +void test_IFtype(w128ibm *a) { f_ibm128_arg(a); } +void test_ICtype(cw128ibm *a) { f_ibm128_complex_arg(a); } #elif TEST_F128_PPC64 typedef int invalid_7 __attribute((mode(KF))); // expected-error{{type of machine mode does not match type of base type}} typedef int invalid_8 __attribute((mode(KI))); // expected-error{{unknown machine mode}}