Skip to content

Commit

Permalink
[clang][DFP] Add basic builtin type representation for decimal floati…
Browse files Browse the repository at this point in the history
…ng point types.

This change adds basic type representation support for the decimal
floating point types defined by ISO/IEC TS 18661-2 and adopted for C23.
These types will also serve as the underlying native types for the
library types defined by ISO/IEC TR 24733 and as implemented in
libstdcxx. This change does not include representation support in
LLVM IR, in debugging information, or in C++ mangling for the MS ABI;
such support will be added in later patches.
  • Loading branch information
tahonermann committed Sep 25, 2023
1 parent 32db121 commit 707f162
Show file tree
Hide file tree
Showing 23 changed files with 168 additions and 3 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
CanQualType SatShortFractTy, SatFractTy, SatLongFractTy;
CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy,
SatUnsignedLongFractTy;
// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
CanQualType DecimalFloat32Ty, DecimalFloat64Ty, DecimalFloat128Ty;
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
CanQualType BFloat16Ty;
CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
Expand Down
17 changes: 17 additions & 0 deletions clang/include/clang/AST/BuiltinTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif

#ifndef DECIMAL_FLOATING_TYPE
#define DECIMAL_FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif

#ifndef PLACEHOLDER_TYPE
#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
Expand Down Expand Up @@ -221,6 +225,18 @@ FLOATING_TYPE(Float128, Float128Ty)
// '__ibm128'
FLOATING_TYPE(Ibm128, Ibm128Ty)

//===- Decimal floating point types ---------------------------------------===//
// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.

// '_Decimal32'
DECIMAL_FLOATING_TYPE(DecimalFloat32, DecimalFloat32Ty)

// '_Decimal64'
DECIMAL_FLOATING_TYPE(DecimalFloat64, DecimalFloat64Ty)

// '_Decimal128'
DECIMAL_FLOATING_TYPE(DecimalFloat128, DecimalFloat128Ty)

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

// This is the type of C++0x 'nullptr'.
Expand Down Expand Up @@ -336,6 +352,7 @@ LAST_BUILTIN_TYPE(OMPIterator)
#undef SHARED_SINGLETON_TYPE
#undef PLACEHOLDER_TYPE
#undef FLOATING_TYPE
#undef DECIMAL_FLOATING_TYPE
#undef SIGNED_TYPE
#undef UNSIGNED_TYPE
#undef BUILTIN_TYPE
17 changes: 17 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ struct TransferrableTargetInfo {
unsigned char LongLongWidth, LongLongAlign;
unsigned char Int128Align;

// Decimal floating-point bit widths and alignment.
unsigned char DecimalFloat32Width, DecimalFloat32Align;
unsigned char DecimalFloat64Width, DecimalFloat64Align;
unsigned char DecimalFloat128Width, DecimalFloat128Align;

// Fixed point bit widths
unsigned char ShortAccumWidth, ShortAccumAlign;
unsigned char AccumWidth, AccumAlign;
Expand Down Expand Up @@ -500,6 +505,18 @@ class TargetInfo : public TransferrableTargetInfo,
/// getInt128Align() - Returns the alignment of Int128.
unsigned getInt128Align() const { return Int128Align; }

/// DecimalFloat32Width/Align - Return the size/align of '_Decimal32'.
unsigned getDecimalFloat32Width() const { return DecimalFloat32Width; }
unsigned getDecimalFloat32Align() const { return DecimalFloat32Align; }

/// DecimalFloat64Width/Align - Return the size/align of '_Decimal64'.
unsigned getDecimalFloat64Width() const { return DecimalFloat64Width; }
unsigned getDecimalFloat64Align() const { return DecimalFloat64Align; }

/// DecimalFloat128Width/Align - Return the size/align of '_Decimal128'.
unsigned getDecimalFloat128Width() const { return DecimalFloat128Width; }
unsigned getDecimalFloat128Align() const { return DecimalFloat128Align; }

/// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and
/// 'unsigned short _Accum' for this target, in bits.
unsigned getShortAccumWidth() const { return ShortAccumWidth; }
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -427,10 +427,12 @@ KEYWORD(_Accum , KEYNOCXX)
KEYWORD(_Fract , KEYNOCXX)
KEYWORD(_Sat , KEYNOCXX)

// GNU Extensions (in impl-reserved namespace)
// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
KEYWORD(_Decimal32 , KEYALL)
KEYWORD(_Decimal64 , KEYALL)
KEYWORD(_Decimal128 , KEYALL)

// GNU Extensions (in impl-reserved namespace)
KEYWORD(__null , KEYCXX)
// __alignof returns the preferred alignment of a type, the alignment
// clang will attempt to give an object of the type if allowed by ABI.
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,15 @@ enum PredefinedTypeIDs {
/// \brief The '__ibm128' type
PREDEF_TYPE_IBM128_ID = 74,

/// \brief The '_Decimal32' type
PREDEF_TYPE_DECIMAL32_ID = 75,

/// \brief The '_Decimal64' type
PREDEF_TYPE_DECIMAL64_ID = 76,

/// \brief The '_Decimal128' type
PREDEF_TYPE_DECIMAL128_ID = 77,

/// OpenCL image types with auto numeration
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,11 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
InitBuiltinType(SatUnsignedFractTy, BuiltinType::SatUFract);
InitBuiltinType(SatUnsignedLongFractTy, BuiltinType::SatULongFract);

// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
InitBuiltinType(DecimalFloat32Ty, BuiltinType::DecimalFloat32);
InitBuiltinType(DecimalFloat64Ty, BuiltinType::DecimalFloat64);
InitBuiltinType(DecimalFloat128Ty, BuiltinType::DecimalFloat128);

// GNU extension, 128-bit integers.
InitBuiltinType(Int128Ty, BuiltinType::Int128);
InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128);
Expand Down Expand Up @@ -2114,6 +2119,18 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getLongFractWidth();
Align = Target->getLongFractAlign();
break;
case BuiltinType::DecimalFloat32:
Width = Target->getDecimalFloat32Width();
Align = Target->getDecimalFloat32Align();
break;
case BuiltinType::DecimalFloat64:
Width = Target->getDecimalFloat64Width();
Align = Target->getDecimalFloat64Align();
break;
case BuiltinType::DecimalFloat128:
Width = Target->getDecimalFloat128Width();
Align = Target->getDecimalFloat128Align();
break;
case BuiltinType::BFloat16:
if (Target->hasBFloat16Type()) {
Width = Target->getBFloat16Width();
Expand Down Expand Up @@ -8066,6 +8083,9 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
case BuiltinType::SatUShortFract:
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
// FIXME: potentially need @encodes for these!
return ' ';

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11416,6 +11416,8 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) {
case BuiltinType::ID: return GCCTypeClass::Integer;
#define FLOATING_TYPE(ID, SINGLETON_ID) \
case BuiltinType::ID: return GCCTypeClass::RealFloat;
#define DECIMAL_FLOATING_TYPE(ID, SINGLETON_ID) \
case BuiltinType::ID: return GCCTypeClass::RealFloat;
#define PLACEHOLDER_TYPE(ID, SINGLETON_ID) \
case BuiltinType::ID: break;
#include "clang/AST/BuiltinTypes.def"
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3165,6 +3165,15 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::NullPtr:
Out << "Dn";
break;
case BuiltinType::DecimalFloat32:
Out << "Df";
break;
case BuiltinType::DecimalFloat64:
Out << "Dd";
break;
case BuiltinType::DecimalFloat128:
Out << "De";
break;

#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2408,6 +2408,9 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
// ::= _U # char32_t
// ::= _W # wchar_t
// ::= _Z # __float80 (Digital Mars)
// ::= FIXME # _Decimal32
// ::= FIXME # _Decimal64
// ::= FIXME # _Decimal128
switch (T->getKind()) {
case BuiltinType::Void:
Out << 'X';
Expand Down Expand Up @@ -2588,6 +2591,9 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
case BuiltinType::Ibm128:
case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
case BuiltinType::Float128: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/NSAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Ibm128:
case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
case BuiltinType::NullPtr:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCId:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/PrintfFormatString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,9 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::SatUShortFract:
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
// Various types which are non-trivial to correct.
return false;

Expand All @@ -805,6 +808,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
#define SIGNED_TYPE(Id, SingletonId)
#define UNSIGNED_TYPE(Id, SingletonId)
#define FLOATING_TYPE(Id, SingletonId)
#define DECIMAL_FLOATING_TYPE(Id, SingletonId)
#define BUILTIN_TYPE(Id, SingletonId) \
case BuiltinType::Id:
#include "clang/AST/BuiltinTypes.def"
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3250,6 +3250,12 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "__float128";
case Ibm128:
return "__ibm128";
case DecimalFloat32:
return "_Decimal32";
case DecimalFloat64:
return "_Decimal64";
case DecimalFloat128:
return "_Decimal128";
case WChar_S:
case WChar_U:
return Policy.MSWChar ? "__wchar_t" : "wchar_t";
Expand Down Expand Up @@ -4434,6 +4440,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
#define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
#define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
#define FLOATING_TYPE(Id, SingletonId) case BuiltinType::Id:
#define DECIMAL_FLOATING_TYPE(Id, SingletonId) case BuiltinType::Id:
#define BUILTIN_TYPE(Id, SingletonId)
#include "clang/AST/BuiltinTypes.def"
return false;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/TypeLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
case BuiltinType::BFloat16:
case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
llvm_unreachable("Builtin type needs extra local data!");
// Fall through, if the impossible happens.

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
LongLongWidth = LongLongAlign = 64;
Int128Align = 128;

// Decimal floating-point default bit widths and alignment.
DecimalFloat32Width = DecimalFloat32Align = 32;
DecimalFloat64Width = DecimalFloat64Align = 64;
DecimalFloat128Width = DecimalFloat128Align = 128;

// Fixed point default bit widths
ShortAccumWidth = ShortAccumAlign = 16;
AccumWidth = AccumAlign = 32;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
Expand Down Expand Up @@ -929,6 +930,12 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::SatULongFract:
Encoding = llvm::dwarf::DW_ATE_unsigned_fixed;
break;
case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
llvm::report_fatal_error("DWARF debugging support for decimal floating "
"point is not yet implemented");
break;
}

BTName = BT->getName(CGM.getLangOpts());
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Error.h"

using namespace clang;
using namespace CodeGen;
Expand Down Expand Up @@ -417,6 +418,13 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
/* UseNativeHalf = */ false);
break;

case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
llvm::report_fatal_error("LLVM type support for decimal floating point "
"is not yet implemented");
break;

case BuiltinType::NullPtr:
// Model std::nullptr_t as i8*
ResultType = llvm::Type::getInt8PtrTy(getLLVMContext());
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3342,6 +3342,9 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::Char32:
case BuiltinType::Int128:
case BuiltinType::UInt128:
case BuiltinType::DecimalFloat32:
case BuiltinType::DecimalFloat64:
case BuiltinType::DecimalFloat128:
return true;

#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Index/USRGeneration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,12 @@ void USRGenerator::VisitType(QualType T) {
Out << "@BT@__bf16"; break;
case BuiltinType::Ibm128:
Out << "@BT@__ibm128"; break;
case BuiltinType::DecimalFloat32:
Out << "@BT@_Decimal32"; break;
case BuiltinType::DecimalFloat64:
Out << "@BT@_Decimal64"; break;
case BuiltinType::DecimalFloat128:
Out << "@BT@_Decimal128"; break;
case BuiltinType::ObjCId:
Out << 'o'; break;
case BuiltinType::ObjCClass:
Expand Down
16 changes: 15 additions & 1 deletion clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,20 @@ TSTToUnaryTransformType(DeclSpec::TST SwitchTST) {
}
}

static CanQualType
TSTToDecimalFloatType(ASTContext &Context, DeclSpec::TST SwitchTST) {
switch (SwitchTST) {
case DeclSpec::TST_decimal32:
return Context.DecimalFloat32Ty;
case DeclSpec::TST_decimal64:
return Context.DecimalFloat64Ty;
case DeclSpec::TST_decimal128:
return Context.DecimalFloat128Ty;
default:
llvm_unreachable("expected a decimal floating point type specifier type");
}
}

/// Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
Expand Down Expand Up @@ -1575,7 +1589,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TST_decimal64: // _Decimal64
case DeclSpec::TST_decimal128: // _Decimal128
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
Result = Context.IntTy;
Result = TSTToDecimalFloatType(Context, DS.getTypeSpecType());
declarator.setInvalidType(true);
break;
case DeclSpec::TST_class:
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Serialization/ASTCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,15 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
case BuiltinType::BFloat16:
ID = PREDEF_TYPE_BFLOAT16_ID;
break;
case BuiltinType::DecimalFloat32:
ID = PREDEF_TYPE_DECIMAL32_ID;
break;
case BuiltinType::DecimalFloat64:
ID = PREDEF_TYPE_DECIMAL64_ID;
break;
case BuiltinType::DecimalFloat128:
ID = PREDEF_TYPE_DECIMAL128_ID;
break;
}

return TypeIdx(ID);
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7276,6 +7276,15 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_OMP_ITERATOR:
T = Context.OMPIteratorTy;
break;
case PREDEF_TYPE_DECIMAL32_ID:
T = Context.DecimalFloat32Ty;
break;
case PREDEF_TYPE_DECIMAL64_ID:
T = Context.DecimalFloat64Ty;
break;
case PREDEF_TYPE_DECIMAL128_ID:
T = Context.DecimalFloat128Ty;
break;
#define SVE_TYPE(Name, Id, SingletonId) \
case PREDEF_TYPE_##Id##_ID: \
T = Context.SingletonId; \
Expand Down
Loading

0 comments on commit 707f162

Please sign in to comment.