Skip to content

Commit

Permalink
[Clang] Add __ibm128 type to represent ppc_fp128
Browse files Browse the repository at this point in the history
Currently, we have no front-end type for ppc_fp128 type in IR. PowerPC
target generates ppc_fp128 type from long double now, but there's option
(-mabi=(ieee|ibm)longdouble) to control it and we're going to do
transition from IBM extended double-double ppc_fp128 to IEEE fp128 in
the future.

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

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

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

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

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D93377
  • Loading branch information
ecnelises committed Sep 6, 2021
1 parent 96f6785 commit fae0dfa
Show file tree
Hide file tree
Showing 46 changed files with 450 additions and 75 deletions.
1 change: 1 addition & 0 deletions clang/bindings/python/clang/cindex.py
Expand Up @@ -2059,6 +2059,7 @@ def __repr__(self):
TypeKind.OBJCSEL = TypeKind(29)
TypeKind.FLOAT128 = TypeKind(30)
TypeKind.HALF = TypeKind(31)
TypeKind.IBM128 = TypeKind(40)
TypeKind.COMPLEX = TypeKind(100)
TypeKind.POINTER = TypeKind(101)
TypeKind.BLOCKPOINTER = TypeKind(102)
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang-c/Index.h
Expand Up @@ -3298,8 +3298,9 @@ enum CXTypeKind {
CXType_UAccum = 37,
CXType_ULongAccum = 38,
CXType_BFloat16 = 39,
CXType_Ibm128 = 40,
CXType_FirstBuiltin = CXType_Void,
CXType_LastBuiltin = CXType_BFloat16,
CXType_LastBuiltin = CXType_Ibm128,

CXType_Complex = 100,
CXType_Pointer = 101,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/ASTContext.h
Expand Up @@ -1076,7 +1076,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty;
CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty, Ibm128Ty;
CanQualType ShortAccumTy, AccumTy,
LongAccumTy; // ISO/IEC JTC1 SC22 WG14 N1169 Extension
CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/BuiltinTypes.def
Expand Up @@ -218,6 +218,9 @@ FLOATING_TYPE(BFloat16, BFloat16Ty)
// '__float128'
FLOATING_TYPE(Float128, Float128Ty)

// '__ibm128'
FLOATING_TYPE(Ibm128, Ibm128Ty)

//===- Language-specific types --------------------------------------------===//

// This is the type of C++0x 'nullptr'.
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/AST/Type.h
Expand Up @@ -2003,6 +2003,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661
bool isBFloat16Type() const;
bool isFloat128Type() const;
bool isIbm128Type() const;
bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
bool isVoidType() const; // C99 6.2.5p19
Expand Down Expand Up @@ -2550,7 +2551,7 @@ class BuiltinType : public Type {
}

bool isFloatingPoint() const {
return getKind() >= Half && getKind() <= Float128;
return getKind() >= Half && getKind() <= Ibm128;
}

/// Determines whether the given kind corresponds to a placeholder type.
Expand Down Expand Up @@ -6973,6 +6974,10 @@ inline bool Type::isFloat128Type() const {
return isSpecificBuiltinType(BuiltinType::Float128);
}

inline bool Type::isIbm128Type() const {
return isSpecificBuiltinType(BuiltinType::Ibm128);
}

inline bool Type::isNullPtrType() const {
return isSpecificBuiltinType(BuiltinType::NullPtr);
}
Expand Down
7 changes: 3 additions & 4 deletions clang/include/clang/AST/TypeLoc.h
Expand Up @@ -581,10 +581,9 @@ class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,

bool needsExtraLocalData() const {
BuiltinType::Kind bk = getTypePtr()->getKind();
return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128)
|| (bk >= BuiltinType::Short && bk <= BuiltinType::Float128)
|| bk == BuiltinType::UChar
|| bk == BuiltinType::SChar;
return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) ||
(bk >= BuiltinType::Short && bk <= BuiltinType::Ibm128) ||
bk == BuiltinType::UChar || bk == BuiltinType::SChar;
}

unsigned getExtraLocalDataSize() const {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Specifiers.h
Expand Up @@ -59,6 +59,7 @@ namespace clang {
TST_float,
TST_double,
TST_float128,
TST_ibm128,
TST_bool, // _Bool
TST_decimal32, // _Decimal32
TST_decimal64, // _Decimal64
Expand Down
23 changes: 20 additions & 3 deletions clang/include/clang/Basic/TargetInfo.h
Expand Up @@ -64,7 +64,7 @@ struct TransferrableTargetInfo {
unsigned char BFloat16Width, BFloat16Align;
unsigned char FloatWidth, FloatAlign;
unsigned char DoubleWidth, DoubleAlign;
unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align;
unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align, Ibm128Align;
unsigned char LargeArrayMinWidth, LargeArrayAlign;
unsigned char LongWidth, LongAlign;
unsigned char LongLongWidth, LongLongAlign;
Expand Down Expand Up @@ -104,7 +104,7 @@ struct TransferrableTargetInfo {
unsigned MaxTLSAlign;

const llvm::fltSemantics *HalfFormat, *BFloat16Format, *FloatFormat,
*DoubleFormat, *LongDoubleFormat, *Float128Format;
*DoubleFormat, *LongDoubleFormat, *Float128Format, *Ibm128Format;

///===---- Target Data Type Query Methods -------------------------------===//
enum IntType {
Expand All @@ -126,8 +126,10 @@ struct TransferrableTargetInfo {
Float = 0,
Double,
LongDouble,
Float128
Float128,
Ibm128
};

protected:
IntType SizeType, IntMaxType, PtrDiffType, IntPtrType, WCharType, WIntType,
Char16Type, Char32Type, Int64Type, Int16Type, SigAtomicType,
Expand Down Expand Up @@ -200,6 +202,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
bool HasFloat128;
bool HasFloat16;
bool HasBFloat16;
bool HasIbm128;
bool HasStrictFP;

unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
Expand Down Expand Up @@ -594,6 +597,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
/// Determine whether the _BFloat16 type is supported on this target.
virtual bool hasBFloat16Type() const { return HasBFloat16; }

/// Determine whether the __ibm128 type is supported on this target.
virtual bool hasIbm128Type() const { return HasIbm128; }

/// Determine whether constrained floating point is supported on this target.
virtual bool hasStrictFP() const { return HasStrictFP; }

Expand Down Expand Up @@ -672,12 +678,23 @@ class TargetInfo : public virtual TransferrableTargetInfo,
return *Float128Format;
}

/// getIbm128Width/Align/Format - Return the size/align/format of
/// '__ibm128'.
unsigned getIbm128Width() const { return 128; }
unsigned getIbm128Align() const { return Ibm128Align; }
const llvm::fltSemantics &getIbm128Format() const { return *Ibm128Format; }

/// Return the mangled code of long double.
virtual const char *getLongDoubleMangling() const { return "e"; }

/// Return the mangled code of __float128.
virtual const char *getFloat128Mangling() const { return "g"; }

/// Return the mangled code of __ibm128.
virtual const char *getIbm128Mangling() const {
llvm_unreachable("ibm128 not implemented on this target");
}

/// Return the mangled code of bfloat.
virtual const char *getBFloat16Mangling() const {
llvm_unreachable("bfloat not implemented on this target");
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TokenKinds.def
Expand Up @@ -438,6 +438,7 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX)
KEYWORD(__builtin_va_arg , KEYALL)
KEYWORD(__extension__ , KEYALL)
KEYWORD(__float128 , KEYALL)
KEYWORD(__ibm128 , KEYALL)
KEYWORD(__imag , KEYALL)
KEYWORD(__int128 , KEYALL)
KEYWORD(__label__ , KEYALL)
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/DeclSpec.h
Expand Up @@ -275,6 +275,7 @@ class DeclSpec {
static const TST TST_accum = clang::TST_Accum;
static const TST TST_fract = clang::TST_Fract;
static const TST TST_float128 = clang::TST_float128;
static const TST TST_ibm128 = clang::TST_ibm128;
static const TST TST_bool = clang::TST_bool;
static const TST TST_decimal32 = clang::TST_decimal32;
static const TST TST_decimal64 = clang::TST_decimal64;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Expand Up @@ -1064,6 +1064,9 @@ enum PredefinedTypeIDs {
/// \brief The '__bf16' type
PREDEF_TYPE_BFLOAT16_ID = 73,

/// \brief The '__ibm128' type
PREDEF_TYPE_IBM128_ID = 74,

/// OpenCL image types with auto numeration
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
Expand Down
25 changes: 24 additions & 1 deletion clang/lib/AST/ASTContext.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -1307,6 +1314,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
// GNU extension, __float128 for IEEE quadruple precision
InitBuiltinType(Float128Ty, BuiltinType::Float128);

// __ibm128 for IBM extended precision
InitBuiltinType(Ibm128Ty, BuiltinType::Ibm128);

// C11 extension ISO/IEC TS 18661-3
InitBuiltinType(Float16Ty, BuiltinType::Float16);

Expand Down Expand Up @@ -1703,6 +1713,8 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
return Target->getHalfFormat();
case BuiltinType::Float: return Target->getFloatFormat();
case BuiltinType::Double: return Target->getDoubleFormat();
case BuiltinType::Ibm128:
return Target->getIbm128Format();
case BuiltinType::LongDouble:
if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice)
return AuxTarget->getLongDoubleFormat();
Expand Down Expand Up @@ -2129,6 +2141,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getDoubleWidth();
Align = Target->getDoubleAlign();
break;
case BuiltinType::Ibm128:
Width = Target->getIbm128Width();
Align = Target->getIbm128Align();
break;
case BuiltinType::LongDouble:
if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
(Target->getLongDoubleWidth() != AuxTarget->getLongDoubleWidth() ||
Expand Down Expand Up @@ -6309,6 +6325,7 @@ static FloatingRank getFloatingRank(QualType T) {
case BuiltinType::LongDouble: return LongDoubleRank;
case BuiltinType::Float128: return Float128Rank;
case BuiltinType::BFloat16: return BFloat16Rank;
case BuiltinType::Ibm128: return Ibm128Rank;
}
}

Expand All @@ -6324,6 +6341,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
case BFloat16Rank: llvm_unreachable("Complex bfloat16 is not supported");
case Float16Rank:
case HalfRank: llvm_unreachable("Complex half is not supported");
case Ibm128Rank: llvm_unreachable("Complex __ibm128 is not supported");
case FloatRank: return FloatComplexTy;
case DoubleRank: return DoubleComplexTy;
case LongDoubleRank: return LongDoubleComplexTy;
Expand All @@ -6340,6 +6358,8 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
case DoubleRank: return DoubleTy;
case LongDoubleRank: return LongDoubleTy;
case Float128Rank: return Float128Ty;
case Ibm128Rank:
return Ibm128Ty;
}
llvm_unreachable("getFloatingRank(): illegal value for rank");
}
Expand Down Expand Up @@ -7315,6 +7335,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
case BuiltinType::BFloat16:
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Ibm128:
case BuiltinType::Half:
case BuiltinType::ShortAccum:
case BuiltinType::Accum:
Expand Down Expand Up @@ -11250,6 +11271,8 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth,
return LongDoubleTy;
case TargetInfo::Float128:
return Float128Ty;
case TargetInfo::Ibm128:
return Ibm128Ty;
case TargetInfo::NoFloat:
return {};
}
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Expand Up @@ -2860,6 +2860,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
// ::= d # double
// ::= e # long double, __float80
// ::= g # __float128
// ::= g # __ibm128
// UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
// UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
// UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
Expand Down Expand Up @@ -2988,6 +2989,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
Out << TI->getBFloat16Mangling();
break;
}
case BuiltinType::Ibm128: {
const TargetInfo *TI = &getASTContext().getTargetInfo();
Out << TI->getIbm128Mangling();
break;
}
case BuiltinType::NullPtr:
Out << "Dn";
break;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/MicrosoftMangle.cpp
Expand Up @@ -2466,6 +2466,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
case BuiltinType::BFloat16:
case BuiltinType::Ibm128:
case BuiltinType::Float128: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/NSAPI.cpp
Expand Up @@ -456,6 +456,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::UInt128:
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Ibm128:
case BuiltinType::NullPtr:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCId:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/PrintfFormatString.cpp
Expand Up @@ -755,6 +755,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::BFloat16:
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Ibm128:
case BuiltinType::ShortAccum:
case BuiltinType::Accum:
case BuiltinType::LongAccum:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/StmtPrinter.cpp
Expand Up @@ -1183,6 +1183,7 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
default: llvm_unreachable("Unexpected type for float literal!");
case BuiltinType::Half: break; // FIXME: suffix?
case BuiltinType::Ibm128: break; // FIXME: No suffix for ibm128 literal
case BuiltinType::Double: break; // no suffix.
case BuiltinType::Float16: OS << "F16"; break;
case BuiltinType::Float: OS << 'F'; break;
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/AST/Type.cpp
Expand Up @@ -2097,7 +2097,7 @@ bool Type::hasUnsignedIntegerRepresentation() const {
bool Type::isFloatingType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Half &&
BT->getKind() <= BuiltinType::Float128;
BT->getKind() <= BuiltinType::Ibm128;
if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
Expand All @@ -2119,7 +2119,7 @@ bool Type::isRealFloatingType() const {
bool Type::isRealType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Float128;
BT->getKind() <= BuiltinType::Ibm128;
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
return isExtIntType();
Expand All @@ -2128,7 +2128,7 @@ bool Type::isRealType() const {
bool Type::isArithmeticType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Float128 &&
BT->getKind() <= BuiltinType::Ibm128 &&
BT->getKind() != BuiltinType::BFloat16;
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
Expand Down Expand Up @@ -3030,6 +3030,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "_Float16";
case Float128:
return "__float128";
case Ibm128:
return "__ibm128";
case WChar_S:
case WChar_U:
return Policy.MSWChar ? "__wchar_t" : "wchar_t";
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/TypeLoc.cpp
Expand Up @@ -351,6 +351,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::LongDouble:
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Ibm128:
case BuiltinType::ShortAccum:
case BuiltinType::Accum:
case BuiltinType::LongAccum:
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/TargetInfo.cpp
Expand Up @@ -34,6 +34,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
NoAsmVariants = false;
HasLegalHalfType = false;
HasFloat128 = false;
HasIbm128 = false;
HasFloat16 = false;
HasBFloat16 = false;
HasStrictFP = false;
Expand Down Expand Up @@ -83,6 +84,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
LongDoubleWidth = 64;
LongDoubleAlign = 64;
Float128Align = 128;
Ibm128Align = 128;
LargeArrayMinWidth = 0;
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
Expand Down Expand Up @@ -113,6 +115,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
DoubleFormat = &llvm::APFloat::IEEEdouble();
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
Float128Format = &llvm::APFloat::IEEEquad();
Ibm128Format = &llvm::APFloat::PPCDoubleDouble();
MCountName = "mcount";
UserLabelPrefix = "_";
RegParmMax = 0;
Expand Down

0 comments on commit fae0dfa

Please sign in to comment.