[clang] [llvm] Option decimal float (PR #105506)
Zahira Ammarguellat via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 21 05:07:08 PDT 2024
https://github.com/zahiraam created https://github.com/llvm/llvm-project/pull/105506
None
>From 707f1625a626faae14b8e24f7e3cf10a2ed621ce Mon Sep 17 00:00:00 2001
From: Tom Honermann <tom at honermann.net>
Date: Sun, 24 Sep 2023 22:38:01 -0400
Subject: [PATCH 1/7] [clang][DFP] Add basic builtin type representation for
decimal floating 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.
---
clang/include/clang/AST/ASTContext.h | 2 ++
clang/include/clang/AST/BuiltinTypes.def | 17 ++++++++++++++++
clang/include/clang/Basic/TargetInfo.h | 17 ++++++++++++++++
clang/include/clang/Basic/TokenKinds.def | 4 +++-
.../include/clang/Serialization/ASTBitCodes.h | 9 +++++++++
clang/lib/AST/ASTContext.cpp | 20 +++++++++++++++++++
clang/lib/AST/ExprConstant.cpp | 2 ++
clang/lib/AST/ItaniumMangle.cpp | 9 +++++++++
clang/lib/AST/MicrosoftMangle.cpp | 6 ++++++
clang/lib/AST/NSAPI.cpp | 3 +++
clang/lib/AST/PrintfFormatString.cpp | 4 ++++
clang/lib/AST/Type.cpp | 7 +++++++
clang/lib/AST/TypeLoc.cpp | 3 +++
clang/lib/Basic/TargetInfo.cpp | 5 +++++
clang/lib/CodeGen/CGDebugInfo.cpp | 7 +++++++
clang/lib/CodeGen/CodeGenTypes.cpp | 8 ++++++++
clang/lib/CodeGen/ItaniumCXXABI.cpp | 3 +++
clang/lib/Index/USRGeneration.cpp | 6 ++++++
clang/lib/Sema/SemaType.cpp | 16 ++++++++++++++-
clang/lib/Serialization/ASTCommon.cpp | 9 +++++++++
clang/lib/Serialization/ASTReader.cpp | 9 +++++++++
clang/test/Sema/types.c | 4 +++-
clang/tools/libclang/CIndex.cpp | 1 +
23 files changed, 168 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 4ee32c76a95d8e..f862456797b5f9 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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
diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def
index c04f6f6f127191..3a0f78fb6a33fa 100644
--- a/clang/include/clang/AST/BuiltinTypes.def
+++ b/clang/include/clang/AST/BuiltinTypes.def
@@ -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
@@ -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'.
@@ -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
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 61be52149341f0..ddf166c971fec9 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -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;
@@ -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; }
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 72e8df8c793a7b..fdbeaddd9ab9c3 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -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.
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 9e115f2a5cce3f..e83c8cafcac36f 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -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,
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 4b1d9e86797b77..1a411232cab9db 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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);
@@ -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();
@@ -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 ' ';
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fea06b97259fe3..b048ef1c2c4421 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -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"
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 53963d2a91752a..7641f44d722546 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -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) \
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 79175c79de96bf..0e68e6acf6291e 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -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';
@@ -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(
diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index 86dee540e9e299..adcae62f81d163 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -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:
diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp
index f0b9d0ecaf2346..d7d6bd94c387be 100644
--- a/clang/lib/AST/PrintfFormatString.cpp
+++ b/clang/lib/AST/PrintfFormatString.cpp
@@ -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;
@@ -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"
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index c08ebfb7f142b3..91de51add303e4 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -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";
@@ -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;
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index e12b9b50f6e722..8556488ab67dc2 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -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.
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 6cd5d618a4acaa..5cd7e259db90de 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -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;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 36e29285141b59..283d7bb4645b9b 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -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"
@@ -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());
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 30021794a0bb3d..9ec3d309684450 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -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;
@@ -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());
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 385dcf21f724e9..797103257ed89e 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -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) \
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index f778a6208d5122..4ab9370e8a8045 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -803,6 +803,12 @@ void USRGenerator::VisitType(QualType T) {
Out << "@BT at __bf16"; break;
case BuiltinType::Ibm128:
Out << "@BT at __ibm128"; break;
+ case BuiltinType::DecimalFloat32:
+ Out << "@BT at _Decimal32"; break;
+ case BuiltinType::DecimalFloat64:
+ Out << "@BT at _Decimal64"; break;
+ case BuiltinType::DecimalFloat128:
+ Out << "@BT at _Decimal128"; break;
case BuiltinType::ObjCId:
Out << 'o'; break;
case BuiltinType::ObjCClass:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index ffd29446b4f2ed..fa515dd3bc9357 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -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
@@ -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:
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 72e58210748097..17abf2188af9a9 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -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);
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0952244d037a77..9d6a018177b098 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -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; \
diff --git a/clang/test/Sema/types.c b/clang/test/Sema/types.c
index e0a6ba4f0691b9..4ce8d5ffffb76e 100644
--- a/clang/test/Sema/types.c
+++ b/clang/test/Sema/types.c
@@ -48,7 +48,9 @@ enum e { e_1 };
extern int j[sizeof(enum e)]; // expected-note {{previous declaration}}
int j[42]; // expected-error {{redefinition of 'j' with a different type: 'int[42]' vs 'int[4]'}}
-_Decimal32 x; // expected-error {{GNU decimal type extension not supported}}
+_Decimal32 d32; // expected-error {{GNU decimal type extension not supported}}
+_Decimal64 d64; // expected-error {{GNU decimal type extension not supported}}
+_Decimal128 d128; // expected-error {{GNU decimal type extension not supported}}
int __attribute__ ((vector_size (8), vector_size (8))) v; // expected-error {{invalid vector element type}}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index f0c8ecfcb6264f..e9d97d55028234 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1645,6 +1645,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
#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 PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
#include "clang/AST/BuiltinTypes.def"
break;
>From f06fce6d01508456a91dc702d4a92e313bc06f47 Mon Sep 17 00:00:00 2001
From: Tom Honermann <tom at honermann.net>
Date: Wed, 4 Oct 2023 09:58:48 -0400
Subject: [PATCH 2/7] [clang][DFP] Add support for
-fexperimental-decimal-floating-point.
Though the ISO/IEC TS 18661-2:2015 decimal floating-point (DFP)
extension has been adopted for the upcoming C23 standard, it will
remain necessary to be able to explicitly enable and disable support
for the extension for the foreseeable future for use with previous
C standards and with C++. This change adds a driver and cc1 option
to enable language support. Since support for the feature is not yet
complete, the option name explicitly reflects its status as
experimental and only serves to enable testing at this point.
No target considerations have been implemented yet. The option only
serves to enable the _Decimal32, _Decimal64, and _Decimal128 keywords
to be used as DFP type specifiers in C; these keywords are not enabled
for C++ since, per ISO/IEC TR 24733:2011 and the gcc implementation,
DFP support in C++ is provided via standard library types (that are
expected to wrap a builtin type exposed by other means).
The C23 standard specifies that the __STDC_IEC_60559_DFP__ macro be
predefined when the DFP extensions are available. This change adds
that macro with a placeholder value for use in testing.
---
.../clang/Basic/DiagnosticSemaKinds.td | 4 +--
clang/include/clang/Basic/LangOptions.def | 3 ++
clang/include/clang/Basic/TokenKinds.def | 6 ++--
clang/include/clang/Driver/Options.td | 5 +++
clang/lib/Driver/ToolChains/Clang.cpp | 3 ++
clang/lib/Frontend/InitPreprocessor.cpp | 6 ++++
clang/lib/Sema/SemaType.cpp | 10 ++++--
clang/test/Driver/dfp-enablement-lang.c | 36 +++++++++++++++++++
clang/test/Sema/dfp-types.c | 9 +++++
clang/test/Sema/types.c | 6 ++--
10 files changed, 77 insertions(+), 11 deletions(-)
create mode 100644 clang/test/Driver/dfp-enablement-lang.c
create mode 100644 clang/test/Sema/dfp-types.c
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0ac4df8edb242f..d5c798b658e72f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10232,8 +10232,8 @@ def ext_missing_type_specifier : ExtWarn<
"implicit int">, InGroup<ImplicitInt>, DefaultError;
def err_missing_type_specifier : Error<
"a type specifier is required for all declarations">;
-def err_decimal_unsupported : Error<
- "GNU decimal type extension not supported">;
+def err_dfp_disabled : Error<
+ "decimal floating-point extensions are not enabled">;
def err_objc_array_of_interfaces : Error<
"array of interface %0 is invalid (probably should be an array of pointers)">;
def ext_c99_array_usage : Extension<
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index e18b5b80a34e71..2902c4d891c5a7 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -427,6 +427,9 @@ LANGOPT(FixedPoint, 1, 0, "fixed point types")
LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0,
"unsigned fixed point types having one extra padding bit")
+// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
+LANGOPT(DecimalFloatingPoint, 1, 0, "decimal floating-point extensions")
+
LANGOPT(RegisterStaticDestructors, 1, 1, "Register C++ static destructors")
LANGOPT(RegCall4, 1, 0, "Set __regcall4 as a default calling convention to respect __regcall ABI v.4")
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index fdbeaddd9ab9c3..12f80e38ded9bb 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -428,9 +428,9 @@ KEYWORD(_Fract , KEYNOCXX)
KEYWORD(_Sat , KEYNOCXX)
// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
-KEYWORD(_Decimal32 , KEYALL)
-KEYWORD(_Decimal64 , KEYALL)
-KEYWORD(_Decimal128 , KEYALL)
+KEYWORD(_Decimal32 , KEYNOCXX)
+KEYWORD(_Decimal64 , KEYNOCXX)
+KEYWORD(_Decimal128 , KEYNOCXX)
// GNU Extensions (in impl-reserved namespace)
KEYWORD(__null , KEYCXX)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 553c7928c4f949..8a510295d34410 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2055,6 +2055,11 @@ defm fixed_point : BoolFOption<"fixed-point",
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
NegFlag<SetFalse, [], [ClangOption], "Disable">,
BothFlags<[], [ClangOption], " fixed point types">>, ShouldParseIf<!strconcat("!", cplusplus.KeyPath)>;
+defm decimal_floating_point : BoolFOption<"experimental-decimal-floating-point",
+ LangOpts<"DecimalFloatingPoint">, DefaultFalse,
+ PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
+ NegFlag<SetFalse, [], [ClangOption], "Disable">,
+ BothFlags<[], [ClangOption], " decimal floating-point extensions">>;
defm cxx_static_destructors : BoolFOption<"c++-static-destructors",
LangOpts<"RegisterStaticDestructors">, DefaultTrue,
NegFlag<SetFalse, [], [ClangOption, CC1Option],
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 40e60585a8b8d6..d98574def75de7 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6004,6 +6004,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.addOptInFlag(CmdArgs, options::OPT_ffixed_point,
options::OPT_fno_fixed_point);
+ Args.addOptInFlag(CmdArgs, options::OPT_fdecimal_floating_point,
+ options::OPT_fno_decimal_floating_point);
+
if (Arg *A = Args.getLastArg(options::OPT_fcxx_abi_EQ))
A->render(Args, CmdArgs);
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index e5db8a654e6707..ffa0eccce59b5e 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -498,6 +498,12 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__STDC_UTF_16__", "1");
Builder.defineMacro("__STDC_UTF_32__", "1");
+ // C23 decimal floating point extensions.
+ // FIXME: Define to 202311L when support for C23 decimal floating point
+ // FIXME: extensions is feature complete.
+ if (!LangOpts.CPlusPlus && LangOpts.DecimalFloatingPoint)
+ Builder.defineMacro("__STDC_IEC_60559_DFP__", "197001L");
+
if (LangOpts.ObjC)
Builder.defineMacro("__OBJC__");
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index fa515dd3bc9357..c3ab0d000f4d3c 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1588,9 +1588,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TST_decimal32: // _Decimal32
case DeclSpec::TST_decimal64: // _Decimal64
case DeclSpec::TST_decimal128: // _Decimal128
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
- Result = TSTToDecimalFloatType(Context, DS.getTypeSpecType());
- declarator.setInvalidType(true);
+ if (!S.getLangOpts().DecimalFloatingPoint) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_dfp_disabled);
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ } else {
+ Result = TSTToDecimalFloatType(Context, DS.getTypeSpecType());
+ }
break;
case DeclSpec::TST_class:
case DeclSpec::TST_enum:
diff --git a/clang/test/Driver/dfp-enablement-lang.c b/clang/test/Driver/dfp-enablement-lang.c
new file mode 100644
index 00000000000000..fe566e6cef848d
--- /dev/null
+++ b/clang/test/Driver/dfp-enablement-lang.c
@@ -0,0 +1,36 @@
+// This test is intended to validate whether decimal floating-point (DFP)
+// extensions are enabled based on language standard and to ensure a proper
+// diagnostic is issued for any use of DFP features otherwise.
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -std=c17 -fsyntax-only -Xclang -verify=dfp-off,c-dfp-off %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -std=c17 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify %s
+// FIXME: Remove -fexperimental-decimal-floating-point once -std=c23 implies DFP enablement.
+// RUN: %clang -target x86_64-unknown-linux-gnu -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -std=c23 -fsyntax-only -fno-experimental-decimal-floating-point -Xclang -verify=dfp-off,c-dfp-off %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -x c++ -std=c++23 -fsyntax-only -Xclang -verify=cxx,dfp-off %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -x c++ -std=c++23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=cxx %s
+// FIXME: Remove -fexperimental-decimal-floating-point once -std=c++2c (or later) implies DFP enablement.
+// RUN: %clang -target x86_64-unknown-linux-gnu -x c++ -std=c++2c -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=cxx %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -x c++ -std=c++2c -fsyntax-only -fno-experimental-decimal-floating-point -Xclang -verify=cxx,dfp-off %s
+
+// expected-no-diagnostics
+
+#if defined(__cplusplus)
+ #if defined(__STDC_IEC_60559_DFP__)
+ #error __STDC_IEC_60559_DFP__ should never be defined for C++
+ #endif
+#else
+ #if !defined(__STDC_IEC_60559_DFP__)
+ // c-dfp-off-error at +1 {{__STDC_IEC_60559_DFP__ should be defined}}
+ #error __STDC_IEC_60559_DFP__ should be defined for C when DFP support is enabled
+ #elif __STDC_IEC_60559_DFP__ != 197001L
+ #error __STDC_IEC_60559_DFP__ has the wrong value
+ #endif
+#endif
+
+_Decimal32 d32; // cxx-error {{unknown type name '_Decimal32'}} \
+ // c-dfp-off-error {{decimal floating-point extensions are not enabled}}
+_Decimal64 d64; // cxx-error {{unknown type name '_Decimal64'}} \
+ // c-dfp-off-error {{decimal floating-point extensions are not enabled}}
+_Decimal128 d128; // cxx-error {{unknown type name '_Decimal128'}} \
+ // c-dfp-off-error {{decimal floating-point extensions are not enabled}}
diff --git a/clang/test/Sema/dfp-types.c b/clang/test/Sema/dfp-types.c
new file mode 100644
index 00000000000000..86bb5ce945ca11
--- /dev/null
+++ b/clang/test/Sema/dfp-types.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c23 -fexperimental-decimal-floating-point -fsyntax-only -verify=c %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x c++ -std=c++2c -fexperimental-decimal-floating-point -fsyntax-only -verify=cxx %s
+
+// c-no-diagnostics
+
+// _Decimal32, _Decimal64, and _Decimal128 are never keywords in C++.
+_Decimal32 d32; // cxx-error {{unknown type name '_Decimal32'}}
+_Decimal64 d64; // cxx-error {{unknown type name '_Decimal64'}}
+_Decimal128 d28; // cxx-error {{unknown type name '_Decimal128'}}
diff --git a/clang/test/Sema/types.c b/clang/test/Sema/types.c
index 4ce8d5ffffb76e..9f7e1f48d5631f 100644
--- a/clang/test/Sema/types.c
+++ b/clang/test/Sema/types.c
@@ -48,9 +48,9 @@ enum e { e_1 };
extern int j[sizeof(enum e)]; // expected-note {{previous declaration}}
int j[42]; // expected-error {{redefinition of 'j' with a different type: 'int[42]' vs 'int[4]'}}
-_Decimal32 d32; // expected-error {{GNU decimal type extension not supported}}
-_Decimal64 d64; // expected-error {{GNU decimal type extension not supported}}
-_Decimal128 d128; // expected-error {{GNU decimal type extension not supported}}
+_Decimal32 d32; // expected-error {{decimal floating-point extensions are not enabled}}
+_Decimal64 d64; // expected-error {{decimal floating-point extensions are not enabled}}
+_Decimal128 d128; // expected-error {{decimal floating-point extensions are not enabled}}
int __attribute__ ((vector_size (8), vector_size (8))) v; // expected-error {{invalid vector element type}}
>From ef6273c1e72f4b57810a4fa661165fb7c9ecc393 Mon Sep 17 00:00:00 2001
From: Tom Honermann <tom at honermann.net>
Date: Mon, 9 Oct 2023 17:58:38 -0400
Subject: [PATCH 3/7] [clang][DFP] Add __attribute__((mode(*D))) support for
declaring decimal floating-point types.
Current proposals for supporting decimal floating-point (DFP) types in
C++, e.g., ISO/IEC TR 24733:2011, do not specify keywords to be used as
type specifiers. Rather, DFP types are specified as standard library
types that, in practice, wrap a builtin type that is not otherwise
exposed with a simple name. Gcc enables builtin DFP types to be
declared using the GNU mode attribute as follows:
float __attribute__((mode(SD))) // _Decimal32
float __attribute__((mode(DD))) // _Decimal64
float __attribute__((mode(TD))) // _Decimal128
This change implements support for these additional machine modes.
This change also extends several of the clang::Type AST node attributes
to include DFP types in addition to other floating-point types. These
extensions match extensions to terms of the same name made in C23. The
directly affected predicates includes:
Type::isRealFloatingType()
Type::isFloatingType()
Type::isRealType()
Type::isArithmeticType()
The following new predicate can be used to differentiate DFP types
where needed.
Type::isDecimalFloatingType()
The existing DFP specifications, including C23, do not include support
for complex DFP types. Gcc does not provide such support either. These
changes follow that existing precedent and do not enable support for
complex DFP types as well. However, vector types are allowed to have
DFP types as their element type.
---
clang/include/clang/AST/Type.h | 11 +++-
clang/include/clang/Basic/TargetInfo.h | 16 ++++-
clang/lib/AST/ASTContext.cpp | 6 ++
clang/lib/AST/Type.cpp | 12 +++-
clang/lib/Basic/TargetInfo.cpp | 3 +
clang/lib/Sema/SemaChecking.cpp | 9 ++-
clang/lib/Sema/SemaDeclAttr.cpp | 14 ++++
clang/test/Driver/dfp-enablement-lang.c | 8 +++
clang/test/Sema/dfp-types.c | 87 +++++++++++++++++++++++--
clang/test/SemaCXX/dfp-types.cpp | 14 ++++
10 files changed, 169 insertions(+), 11 deletions(-)
create mode 100644 clang/test/SemaCXX/dfp-types.cpp
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 46dbadd8b878bf..3fcec7b594abc9 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2176,9 +2176,14 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
bool isUnscopedEnumerationType() const;
/// Floating point categories.
+ bool isDecimalFloatingType() const;
+ // C23 6.2.5p13 (_Decimal32/64/128)
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
+ // C23 6.2.5p14 (standard + decimal float)
+ // C23 H.2.4p5 (+interchange +extended FP)
/// isComplexType() does *not* include complex integers (a GCC extension).
/// isComplexIntegerType() can be used to test for complex integers.
+ /// C23 did not add complex decimal floating-point.
bool isComplexType() const; // C99 6.2.5p11 (complex)
bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int.
bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex)
@@ -2746,8 +2751,12 @@ class BuiltinType : public Type {
return getKind() >= Bool && getKind() <= UInt128;
}
+ bool isDecimalFloatingPoint() const {
+ return getKind() >= DecimalFloat32 && getKind() <= DecimalFloat128;
+ }
+
bool isFloatingPoint() const {
- return getKind() >= Half && getKind() <= Ibm128;
+ return getKind() >= Half && getKind() <= DecimalFloat128;
}
bool isSVEBool() const { return getKind() == Kind::SveBool; }
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index ddf166c971fec9..f8734dcda10c72 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -75,9 +75,23 @@ enum class FloatModeKind {
LongDouble = 1 << 3,
Float128 = 1 << 4,
Ibm128 = 1 << 5,
- LLVM_MARK_AS_BITMASK_ENUM(Ibm128)
+ Decimal32 = 1 << 6,
+ Decimal64 = 1 << 7,
+ Decimal128 = 1 << 8,
+ LLVM_MARK_AS_BITMASK_ENUM(Decimal128)
};
+inline bool isDecimalFloatModeKind(FloatModeKind FMK) {
+ switch (FMK) {
+ case FloatModeKind::Decimal32:
+ case FloatModeKind::Decimal64:
+ case FloatModeKind::Decimal128:
+ return true;
+ default:
+ return false;
+ }
+}
+
/// Fields controlling how types are laid out in memory; these may need to
/// be copied for targets like AMDGPU that base their ABIs on an auxiliary
/// CPU target.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 1a411232cab9db..0aef78b685460d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -12164,6 +12164,12 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth,
return Float128Ty;
case FloatModeKind::Ibm128:
return Ibm128Ty;
+ case FloatModeKind::Decimal32:
+ return DecimalFloat32Ty;
+ case FloatModeKind::Decimal64:
+ return DecimalFloat64Ty;
+ case FloatModeKind::Decimal128:
+ return DecimalFloat128Ty;
case FloatModeKind::NoFloat:
return {};
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 91de51add303e4..26d813b160bc3d 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2190,7 +2190,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::Ibm128;
+ BT->getKind() <= BuiltinType::DecimalFloat128;
if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
@@ -2204,6 +2204,12 @@ bool Type::hasFloatingRepresentation() const {
return isFloatingType();
}
+bool Type::isDecimalFloatingType() const {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->isDecimalFloatingPoint();
+ return false;
+}
+
bool Type::isRealFloatingType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->isFloatingPoint();
@@ -2213,7 +2219,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::Ibm128;
+ BT->getKind() <= BuiltinType::DecimalFloat128;
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
return isBitIntType();
@@ -2222,7 +2228,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::Ibm128;
+ BT->getKind() <= BuiltinType::DecimalFloat128;
if (const auto *ET = dyn_cast<EnumType>(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.
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 5cd7e259db90de..6b34c9e8d33eb1 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -319,6 +319,9 @@ TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth,
FloatModeKind TargetInfo::getRealTypeByWidth(unsigned BitWidth,
FloatModeKind ExplicitType) const {
+ if (isDecimalFloatModeKind(ExplicitType))
+ return ExplicitType;
+
if (getHalfWidth() == BitWidth)
return FloatModeKind::Half;
if (getFloatWidth() == BitWidth)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index fad70223362edd..97f175f770ca30 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -8531,8 +8531,8 @@ bool Sema::SemaBuiltinComplex(CallExpr *TheCall) {
<< Real->getSourceRange() << Imag->getSourceRange();
}
- // We don't allow _Complex _Float16 nor _Complex __fp16 as type specifiers;
- // don't allow this builtin to form those types either.
+ // We don't allow _Complex _Float16, _Complex __fp16, or _Complex _DecimalXX
+ // as type specifiers; don't allow this builtin to form those types either.
// FIXME: Should we allow these types?
if (Real->getType()->isFloat16Type())
return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec)
@@ -8540,6 +8540,11 @@ bool Sema::SemaBuiltinComplex(CallExpr *TheCall) {
if (Real->getType()->isHalfType())
return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec)
<< "half";
+ if (Real->getType()->isDecimalFloatingType()) {
+ const BuiltinType *BT = Real->getType()->getAs<BuiltinType>();
+ return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec)
+ << BT->getName(Context.getPrintingPolicy());
+ }
TheCall->setType(Context.getComplexType(Real->getType()));
return false;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index cc98713241395e..cf9c51329577ef 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4668,6 +4668,7 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
IntegerMode = true;
ComplexMode = false;
ExplicitType = FloatModeKind::NoFloat;
+ FloatModeKind ExplicitDFPType = FloatModeKind::NoFloat;
switch (Str.size()) {
case 2:
switch (Str[0]) {
@@ -4678,9 +4679,11 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
DestWidth = 16;
break;
case 'S':
+ ExplicitDFPType = FloatModeKind::Decimal32;
DestWidth = 32;
break;
case 'D':
+ ExplicitDFPType = FloatModeKind::Decimal64;
DestWidth = 64;
break;
case 'X':
@@ -4692,6 +4695,7 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
break;
case 'T':
ExplicitType = FloatModeKind::LongDouble;
+ ExplicitDFPType = FloatModeKind::Decimal128;
DestWidth = 128;
break;
case 'I':
@@ -4704,6 +4708,9 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
} else if (Str[1] == 'C') {
IntegerMode = false;
ComplexMode = true;
+ } else if (Str[1] == 'D') {
+ IntegerMode = false;
+ ExplicitType = ExplicitDFPType;
} else if (Str[1] != 'I') {
DestWidth = 0;
}
@@ -4853,6 +4860,13 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
return;
}
+ if (NewElemTy->isDecimalFloatingType()) {
+ if (!getLangOpts().DecimalFloatingPoint) {
+ Diag(AttrLoc, diag::err_dfp_disabled);
+ return;
+ }
+ }
+
if (ComplexMode) {
NewElemTy = Context.getComplexType(NewElemTy);
}
diff --git a/clang/test/Driver/dfp-enablement-lang.c b/clang/test/Driver/dfp-enablement-lang.c
index fe566e6cef848d..05406d653a69f5 100644
--- a/clang/test/Driver/dfp-enablement-lang.c
+++ b/clang/test/Driver/dfp-enablement-lang.c
@@ -34,3 +34,11 @@ _Decimal64 d64; // cxx-error {{unknown type name '_Decimal64'}} \
// c-dfp-off-error {{decimal floating-point extensions are not enabled}}
_Decimal128 d128; // cxx-error {{unknown type name '_Decimal128'}} \
// c-dfp-off-error {{decimal floating-point extensions are not enabled}}
+
+typedef float __attribute__((mode(SD))) D32; // dfp-off-error {{decimal floating-point extensions are not enabled}}
+typedef float __attribute__((mode(DD))) D64; // dfp-off-error {{decimal floating-point extensions are not enabled}}
+typedef float __attribute__((mode(TD))) D128; // dfp-off-error {{decimal floating-point extensions are not enabled}}
+
+float __attribute__((mode(SD))) famsd; // dfp-off-error {{decimal floating-point extensions are not enabled}}
+float __attribute__((mode(DD))) famdd; // dfp-off-error {{decimal floating-point extensions are not enabled}}
+float __attribute__((mode(TD))) famtd; // dfp-off-error {{decimal floating-point extensions are not enabled}}
diff --git a/clang/test/Sema/dfp-types.c b/clang/test/Sema/dfp-types.c
index 86bb5ce945ca11..330fb898f9414e 100644
--- a/clang/test/Sema/dfp-types.c
+++ b/clang/test/Sema/dfp-types.c
@@ -1,9 +1,88 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c23 -fexperimental-decimal-floating-point -fsyntax-only -verify=c %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x c++ -std=c++2c -fexperimental-decimal-floating-point -fsyntax-only -verify=cxx %s
-
-// c-no-diagnostics
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c23 -fexperimental-decimal-floating-point -fsyntax-only -verify=expected,c %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x c++ -std=c++2c -fexperimental-decimal-floating-point -fsyntax-only -verify=expected,cxx %s
// _Decimal32, _Decimal64, and _Decimal128 are never keywords in C++.
_Decimal32 d32; // cxx-error {{unknown type name '_Decimal32'}}
_Decimal64 d64; // cxx-error {{unknown type name '_Decimal64'}}
_Decimal128 d28; // cxx-error {{unknown type name '_Decimal128'}}
+
+// DFP types are available via the GNU mode attribute in both C and C++.
+typedef float __attribute__((mode(SD))) D32;
+typedef float __attribute__((mode(DD))) D64;
+typedef float __attribute__((mode(TD))) D128;
+
+// The GNU mode attribute requires a floating point base type for DFP types.
+// These are ok.
+long double __attribute((mode(SD))) ldamsd;
+double __attribute((mode(DD))) damdd;
+_Float16 __attribute((mode(SD))) f16amsd;
+__bf16 __attribute((mode(SD))) bf16amsd;
+__float128 __attribute((mode(TD))) f128amtd;
+// These are not ok.
+void __attribute((mode(SD))) vamsd; // expected-error {{type of machine mode does not match type of base type}}
+int __attribute((mode(DD))) iamdd; // expected-error {{type of machine mode does not match type of base type}}
+int* __attribute((mode(TD))) ipamtd; // expected-error {{mode attribute only supported for integer and floating-point types}}
+float __attribute((mode(TD))) *fapmtd; // expected-error {{mode attribute only supported for integer and floating-point types}}
+
+// DFP types may be used as vector elements, but declaration form is restricted.
+float __attribute__((mode(V4SD))) famv4sd; // expected-warning {{deprecated; use the 'vector_size' attribute instead}}
+float __attribute__((mode(SD))) __attribute__((vector_size(16))) famsdv16;
+D64 __attribute__((vector_size(16))) d64av16;
+
+// DFP types are not allowed as elements of complex types.
+D32 _Complex d32c; // expected-error {{'_Complex type-name' is invalid}}
+_Decimal32 _Complex kd32c; // c-error {{'_Complex _Decimal32' is invalid}} \
+ cxx-error {{unknown type name '_Decimal32'}}
+
+_Static_assert(sizeof(D32) == 4);
+_Static_assert(sizeof(D64) == 8);
+_Static_assert(sizeof(D128) == 16);
+
+_Static_assert(_Alignof(D32) == 4);
+_Static_assert(_Alignof(D64) == 8);
+_Static_assert(_Alignof(D128) == 16);
+
+struct s {
+ D32 d32;
+ D64 d64;
+ D128 d128;
+ union {
+ D32 ud32;
+ D64 ud64;
+ D128 ud128;
+ };
+};
+
+struct bitfield {
+ D32 d32 : 32; // expected-error {{bit-field 'd32' has non-integral type}}
+ D64 d64 : 64; // expected-error {{bit-field 'd64' has non-integral type}}
+ D128 d128 : 128; // expected-error {{bit-field 'd128' has non-integral type}}
+};
+
+D32 test_d32(D32 d32) {
+ return d32;
+}
+
+D64 test_d64(D64 d64) {
+ return d64;
+}
+
+D128 test_d128(D128 d128) {
+ return d128;
+}
+
+void test_builtin_complex(D32 d32) {
+ __auto_type lv = __builtin_complex(d32, d32); // expected-error {{'_Complex _Decimal32' is invalid}}
+}
+
+void test_generic(D32 d32, D64 d64, D128 d128) {
+ (void)_Generic(d32, D64 : 0, D128 : 0); // expected-error-re {{controlling expression type {{.*}} not compatible with any generic association type}}
+ (void)_Generic(d64, D32 : 0, D128 : 0); // expected-error-re {{controlling expression type {{.*}} not compatible with any generic association type}}
+ (void)_Generic(d128, D32 : 0, D64 : 0); // expected-error-re {{controlling expression type {{.*}} not compatible with any generic association type}}
+ _Static_assert(_Generic(d32, D64 : 0, D128 : 0, default : 1) == 1);
+ _Static_assert(_Generic(d64, D32 : 0, D128 : 0, default : 1) == 1);
+ _Static_assert(_Generic(d128, D32 : 0, D64 : 0, default : 1) == 1);
+ _Static_assert(_Generic(d32, D32 : 1, D64 : 0, D128 : 0) == 1);
+ _Static_assert(_Generic(d64, D32 : 0, D64 : 1, D128 : 0) == 1);
+ _Static_assert(_Generic(d128, D32 : 0, D64 : 0, D128 : 1) == 1);
+}
diff --git a/clang/test/SemaCXX/dfp-types.cpp b/clang/test/SemaCXX/dfp-types.cpp
new file mode 100644
index 00000000000000..9a26aefab20f6d
--- /dev/null
+++ b/clang/test/SemaCXX/dfp-types.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++2c -fexperimental-decimal-floating-point -fsyntax-only -verify %s
+
+using D32 = float __attribute__((mode(SD)));
+using D64 = float __attribute__((mode(DD)));
+using D128 = float __attribute__((mode(TD)));
+
+// Dependent type specifiers for the GNU mode attribute base type are ok, but
+// must be of a valid type when instantiated.
+template<typename T>
+T __attribute((mode(SD))) dtamsd; // expected-error {{type of machine mode does not match type of base type}}
+auto g1 = dtamsd<float>;
+auto g2 = dtamsd<double>;
+auto g3 = dtamsd<long double>;
+auto g4 = dtamsd<int>; // expected-note {{in instantiation of variable template specialization 'dtamsd' requested here}}
>From 3b2cb1f96976e6cbd712ff8062b24e326784b486 Mon Sep 17 00:00:00 2001
From: Tom Honermann <tom at honermann.net>
Date: Wed, 1 Nov 2023 16:58:47 -0400
Subject: [PATCH 4/7] [clang][DFP] Enable target dependent support for decimal
floating-point extensions.
Support for decimal floating-point (DFP) extensions will, for most
targets, require run-time library support that, for many targets, is
not yet available. This change adds basic infrastructure support to
enable DFP support to be conditional on the target.
Some targets support more than one possible encoding of DFP values.
It is therefore necessary for a target to not just indicate that
DFP support is available, but also the encoding to be used. This
change recognizes the two known encodings that are used in practice
and ties DFP enablement to the selection of one of these modes.
The known encodings are:
BID: Binary Integer Decimal
DPD: Densely Packed Decimal
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 +
clang/include/clang/Basic/TargetInfo.h | 27 ++++++
clang/lib/Basic/TargetInfo.cpp | 6 ++
clang/lib/Basic/Targets/OSTargets.h | 6 ++
clang/lib/Frontend/InitPreprocessor.cpp | 3 +-
clang/lib/Sema/SemaDeclAttr.cpp | 4 +
clang/lib/Sema/SemaType.cpp | 4 +
clang/test/Driver/dfp-enablement-target.c | 82 +++++++++++++++++++
8 files changed, 133 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Driver/dfp-enablement-target.c
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d5c798b658e72f..b79f4cc2c6e659 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10234,6 +10234,8 @@ def err_missing_type_specifier : Error<
"a type specifier is required for all declarations">;
def err_dfp_disabled : Error<
"decimal floating-point extensions are not enabled">;
+def err_dfp_not_supported : Error<
+ "decimal floating-point extensions are not supported on the current target">;
def err_objc_array_of_interfaces : Error<
"array of interface %0 is invalid (probably should be an array of pointers)">;
def ext_c99_array_usage : Extension<
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index f8734dcda10c72..f7c7ffe9671296 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -220,6 +220,15 @@ enum OpenCLTypeKind : uint8_t {
OCLTK_Sampler,
};
+// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
+// Multiple encoding forms for the storage of decimal floating-point values
+// have been defined for use on various platforms. This enumeration provides
+// an enumerator for each known encoding.
+enum class DecimalFloatMode : uint8_t {
+ BID, // Binary Integer Decimal.
+ DPD, // Densely Packed Decimal.
+};
+
/// Exposes information about the current target.
///
class TargetInfo : public TransferrableTargetInfo,
@@ -278,6 +287,10 @@ class TargetInfo : public TransferrableTargetInfo,
std::optional<unsigned> MaxBitIntWidth;
+ // If disengaged, decimal floating-point extensions are not supported,
+ // otherwise, the decimal floating-point mode that is enabled.
+ std::optional<DecimalFloatMode> DecimalFloatEnablementAndMode;
+
std::optional<llvm::Triple> DarwinTargetVariantTriple;
// TargetInfo Constructor. Default initializes all fields.
@@ -710,6 +723,20 @@ class TargetInfo : public TransferrableTargetInfo,
/// Determine whether constrained floating point is supported on this target.
virtual bool hasStrictFP() const { return HasStrictFP; }
+ /// Determine whether decimal floating-point extensions are enabled on this
+ /// target.
+ bool hasDecimalFloatingPoint() const {
+ return DecimalFloatEnablementAndMode.has_value();
+ }
+
+ /// Determine the encoding used for decimal floating-point values on this
+ /// target if decimal floating-point extensions are enabled.
+ DecimalFloatMode getDecimalFloatingPointMode() const {
+ assert(hasDecimalFloatingPoint() &&
+ "Decimal floating-point extensions are not enabled");
+ return DecimalFloatEnablementAndMode.value();
+ }
+
/// Return the alignment that is the largest alignment ever used for any
/// scalar/SIMD data type on the target machine you are compiling for
/// (including types with an extended alignment requirement).
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 6b34c9e8d33eb1..e62b215240ad36 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -524,6 +524,12 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
if (Opts.FakeAddressSpaceMap)
AddrSpaceMap = &FakeAddrSpaceMap;
+
+ // If decimal floating-point extensions are not enabled at the language
+ // level, reset the target dependent DFP mode configuration in order to
+ // avoid surprises.
+ if (!Opts.DecimalFloatingPoint)
+ DecimalFloatEnablementAndMode.reset();
}
bool TargetInfo::initFeatureMap(
diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h
index f2bd846e670d14..41abb01c427077 100644
--- a/clang/lib/Basic/Targets/OSTargets.h
+++ b/clang/lib/Basic/Targets/OSTargets.h
@@ -352,6 +352,12 @@ class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->HasFloat128 = true;
+ if (!Triple.isAndroid()) {
+ // Android NDK r23 and later no longer provide libgcc. DFP support
+ // for Android is therefore not enabled by default pending the
+ // availability of a different DFP run-time library.
+ this->DecimalFloatEnablementAndMode = DecimalFloatMode::BID;
+ }
break;
}
}
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index ffa0eccce59b5e..f0d0260625c175 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -501,7 +501,8 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// C23 decimal floating point extensions.
// FIXME: Define to 202311L when support for C23 decimal floating point
// FIXME: extensions is feature complete.
- if (!LangOpts.CPlusPlus && LangOpts.DecimalFloatingPoint)
+ if (!LangOpts.CPlusPlus && LangOpts.DecimalFloatingPoint &&
+ TI.hasDecimalFloatingPoint())
Builder.defineMacro("__STDC_IEC_60559_DFP__", "197001L");
if (LangOpts.ObjC)
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index cf9c51329577ef..091b247f4794c2 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4865,6 +4865,10 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
Diag(AttrLoc, diag::err_dfp_disabled);
return;
}
+ if (!Context.getTargetInfo().hasDecimalFloatingPoint()) {
+ Diag(AttrLoc, diag::err_dfp_not_supported);
+ return;
+ }
}
if (ComplexMode) {
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index c3ab0d000f4d3c..13c50b56972b7b 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1592,6 +1592,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_dfp_disabled);
Result = Context.IntTy;
declarator.setInvalidType(true);
+ } else if (!S.Context.getTargetInfo().hasDecimalFloatingPoint()) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_dfp_not_supported);
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
} else {
Result = TSTToDecimalFloatType(Context, DS.getTypeSpecType());
}
diff --git a/clang/test/Driver/dfp-enablement-target.c b/clang/test/Driver/dfp-enablement-target.c
new file mode 100644
index 00000000000000..bd7e3e2a740a81
--- /dev/null
+++ b/clang/test/Driver/dfp-enablement-target.c
@@ -0,0 +1,82 @@
+// This test is intended to validate whether decimal floating-point (DFP)
+// extensions are supported and working for a given target and to ensure
+// that an appropriate diagnostic is issued when DFP features are used
+// otherwise.
+
+// FIXME: Remove all uses of -fexperimental-decimal-floating-point once -std=c23 implies DFP enablement.
+// RUN: %clang -target aarch64-unknown-freebsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target aarch64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target aarch64-unknown-linux-android -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target aarch64-unknown-windows-gnu -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target aarch64-unknown-windows-msvc -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target arm64-apple-darwin -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target arm64-apple-ios -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target arm64-apple-macos -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target arm64-apple-tvos -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target arm64-apple-watchos -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target arm64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target arm64-unknown-linux-android -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target armv7-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target armv7-unknown-linux-android -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target armv7-unknown-netbsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target armv7-unknown-openbsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target armv7-unknown-windows-gnu -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target armv7-unknown-windows-msvc -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target hexagon-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target i686-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify %s
+// RUN: %clang -target i686-unknown-linux-android -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target i686-unknown-windows-gnu -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target i686-unknown-windows-msvc -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target loongarch32-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target loongarch64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target m68k-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target mips-unknown-freebsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target mips-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target mips64-unknown-freebsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target mips64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target powerpc64-ibm-aix -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target powerpc64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target powerpc-ibm-aix -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target powerpc-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target riscv32-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target riscv64-unknown-freebsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target riscv64-unknown-fuchsia -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target riscv64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target riscv64-unknown-openbsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target s390x-ibm-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target s390x-ibm-zos -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparc-sun-solaris -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparc-unknown-freebsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparc-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparc-unknown-netbsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparcv9-sun-solaris -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparc64-unknown-freebsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparc64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target sparc64-unknown-netbsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-apple-darwin -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-apple-ios -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-apple-macos -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-apple-tvos -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-apple-watchos -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-unknown-freebsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-unknown-fuchsia -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-unknown-haiku -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-unknown-linux -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify %s
+// RUN: %clang -target x86_64-unknown-netbsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-unknown-openbsd -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-unknown-windows-gnu -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+// RUN: %clang -target x86_64-unknown-windows-msvc -std=c23 -fsyntax-only -fexperimental-decimal-floating-point -Xclang -verify=unsupported %s
+
+// expected-no-diagnostics
+
+_Decimal32 d32; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+_Decimal64 d64; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+_Decimal128 d128; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+
+typedef float __attribute__((mode(SD))) D32; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+typedef float __attribute__((mode(DD))) D64; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+typedef float __attribute__((mode(TD))) D128; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+
+float __attribute__((mode(SD))) famsd; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+float __attribute__((mode(DD))) famdd; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
+float __attribute__((mode(TD))) famtd; // unsupported-error {{decimal floating-point extensions are not supported on the current target}}
>From 738500fa611d8c730e8b0a6dd4b3539018c99fd4 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 14 Nov 2023 14:31:40 -0800
Subject: [PATCH 5/7] [llvm] [DFP] Add support for decimal floating point IR
types. (#33)
* Add support for DFP IR type.
* Fixed BitCodeFormat.rst format.
* Addressed review comments.
* Addressed review comments.
* Addressed review comments.
* Addressed review comments.
* Put all the Decimal* code together.
* Put all the Decimal* code together and removed unrelated
changes.
* Fixed comment.
* Addressed review comments.
* Addressed review comments.
* Addressed review comments.
* Fixed reference.
* Fixed format.
---
clang/lib/CodeGen/CodeGenTypes.cpp | 7 +++--
llvm/docs/BitCodeFormat.rst | 24 +++++++++++++++
llvm/docs/LangRef.rst | 9 ++++++
llvm/include/llvm-c/Core.h | 27 +++++++++++++++--
llvm/include/llvm/Bitcode/LLVMBitCodes.h | 4 +++
llvm/include/llvm/IR/DataLayout.h | 6 ++++
llvm/include/llvm/IR/IRBuilder.h | 15 ++++++++++
llvm/include/llvm/IR/Type.h | 36 ++++++++++++++++++++---
llvm/lib/AsmParser/LLLexer.cpp | 3 ++
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 9 ++++++
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 ++
llvm/lib/IR/AsmWriter.cpp | 3 ++
llvm/lib/IR/Core.cpp | 6 ++++
llvm/lib/IR/LLVMContextImpl.cpp | 4 ++-
llvm/lib/IR/LLVMContextImpl.h | 1 +
llvm/lib/IR/Type.cpp | 22 ++++++++++++++
llvm/test/Assembler/dfp.ll | 16 ++++++++++
17 files changed, 185 insertions(+), 10 deletions(-)
create mode 100644 llvm/test/Assembler/dfp.ll
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 9ec3d309684450..eb3f43ed149c4e 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -419,10 +419,13 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
break;
case BuiltinType::DecimalFloat32:
+ ResultType = llvm::Type::getDecimal32Ty(getLLVMContext());
+ break;
case BuiltinType::DecimalFloat64:
+ ResultType = llvm::Type::getDecimal64Ty(getLLVMContext());
+ break;
case BuiltinType::DecimalFloat128:
- llvm::report_fatal_error("LLVM type support for decimal floating point "
- "is not yet implemented");
+ ResultType = llvm::Type::getDecimal128Ty(getLLVMContext());
break;
case BuiltinType::NullPtr:
diff --git a/llvm/docs/BitCodeFormat.rst b/llvm/docs/BitCodeFormat.rst
index 70be73abef19d6..2a91f64e2a6e00 100644
--- a/llvm/docs/BitCodeFormat.rst
+++ b/llvm/docs/BitCodeFormat.rst
@@ -1358,6 +1358,30 @@ The operand fields are
* *int_params*: Numbers that correspond to the integer parameters.
+TYPE_CODE_DECIMAL32 Record
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``[DECIMAL32]``
+
+The ``DECIMAL32`` record (code 27) adds a ``decimal32`` (32-bit
+decimal floating point) type to the type table.
+
+TYPE_CODE_DECIMAL64 Record
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``[DECIMAL64]``
+
+The ``DECIMAL64`` record (code 28) adds a ``decimal64`` (64-bit
+decimal floating point) type to the type table.
+
+TYPE_CODE_DECIMAL128 Record
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``[DECIMAL128]``
+
+The ``DECIMAL128`` record (code 29) adds a ``decimal128`` (128-bit
+decimal floating point) type to the type table.
+
.. _CONSTANTS_BLOCK:
CONSTANTS_BLOCK Contents
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index f542e70bcfee81..e545f575f72b5f 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -3672,6 +3672,15 @@ Floating-Point Types
* - ``ppc_fp128``
- 128-bit floating-point value (two 64-bits)
+ * - ``decimal32``
+ - 32-bit decimal floating-point value
+
+ * - ``decimal64``
+ - 64-bit decimal floating-point value
+
+ * - ``decimal128``
+ - 128-bit decimal floating-point value
+
The binary format of half, float, double, and fp128 correspond to the
IEEE-754-2008 specifications for binary16, binary32, binary64, and binary128
respectively.
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 7ee46cac43042a..f821d465b59a18 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -164,9 +164,12 @@ typedef enum {
LLVMX86_MMXTypeKind, /**< X86 MMX */
LLVMTokenTypeKind, /**< Tokens */
LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */
- LLVMBFloatTypeKind, /**< 16 bit brain floating point type */
- LLVMX86_AMXTypeKind, /**< X86 AMX */
- LLVMTargetExtTypeKind, /**< Target extension type */
+ LLVMBFloatTypeKind, /**< 16 bit brain floating point type */
+ LLVMX86_AMXTypeKind, /**< X86 AMX */
+ LLVMTargetExtTypeKind, /**< Target extension type */
+ LLVMDecimal32TypeKind, /**< 32 bit decimal floating point type */
+ LLVMDecimal64TypeKind, /**< 64 bit decimal floating point type */
+ LLVMDecimal128TypeKind, /**< 128 bit decimal floating point type */
} LLVMTypeKind;
typedef enum {
@@ -1290,6 +1293,21 @@ LLVMTypeRef LLVMFP128TypeInContext(LLVMContextRef C);
*/
LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C);
+/**
+ * Obtain a 32-bit decimal floating point type from a context.
+ */
+LLVMTypeRef LLVMDecimal32TypeInContext(LLVMContextRef C);
+
+/**
+ * Obtain a 64-bit decimal floating point type from a context.
+ */
+LLVMTypeRef LLVMDecimal64TypeInContext(LLVMContextRef C);
+
+/**
+ * Obtain a 128-bit decimal floating point type from a context.
+ */
+LLVMTypeRef LLVMDecimal128TypeInContext(LLVMContextRef C);
+
/**
* Obtain a floating point type from the global context.
*
@@ -1302,6 +1320,9 @@ LLVMTypeRef LLVMDoubleType(void);
LLVMTypeRef LLVMX86FP80Type(void);
LLVMTypeRef LLVMFP128Type(void);
LLVMTypeRef LLVMPPCFP128Type(void);
+LLVMTypeRef LLVMDecimal32Type(void);
+LLVMTypeRef LLVMDecimal64Type(void);
+LLVMTypeRef LLVMDecimal128Type(void);
/**
* @}
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 52e76356a892e4..d19978a08207bd 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -177,6 +177,10 @@ enum TypeCodes {
TYPE_CODE_OPAQUE_POINTER = 25, // OPAQUE_POINTER: [addrspace]
TYPE_CODE_TARGET_TYPE = 26, // TARGET_TYPE
+
+ TYPE_CODE_DECIMAL32 = 27, // 32-bit decimal floating point
+ TYPE_CODE_DECIMAL64 = 28, // 64-bit decimal floating point
+ TYPE_CODE_DECIMAL128 = 29 // 128-bit decimal floating point
};
enum OperandBundleTagCode {
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index b3633b67b9debd..c1fce09357ee31 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -715,6 +715,12 @@ inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
return getTypeSizeInBits(LayoutTy);
}
+ case Type::Decimal32TyID:
+ return TypeSize::Fixed(32);
+ case Type::Decimal64TyID:
+ return TypeSize::Fixed(64);
+ case Type::Decimal128TyID:
+ return TypeSize::Fixed(128);
default:
llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type");
}
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index ef86eefdf33b83..ccae847c1cf8ca 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -546,6 +546,21 @@ class IRBuilderBase {
return Type::getDoubleTy(Context);
}
+ /// Fetch the type representing a 32-bit decimal floating point value.
+ Type *getDecimal32Ty() {
+ return Type::getDecimal32Ty(Context);
+ }
+
+ /// Fetch the type representing a 64-bit decimal floating point value.
+ Type *getDecimal64Ty() {
+ return Type::getDecimal64Ty(Context);
+ }
+
+ /// Fetch the type representing a 128-bit decimal floating point value.
+ Type *getDecimal128Ty() {
+ return Type::getDecimal128Ty(Context);
+ }
+
/// Fetch the type representing void.
Type *getVoidTy() {
return Type::getVoidTy(Context);
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index c12e899d58fa83..9bebf361ddb63e 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -67,6 +67,11 @@ class Type {
X86_AMXTyID, ///< AMX vectors (8192 bits, X86 specific)
TokenTyID, ///< Tokens
+ // Decimal floating-point types.
+ Decimal32TyID, ///< 32-bit decimal floating point type
+ Decimal64TyID, ///< 64-bit decimal floating point type
+ Decimal128TyID, ///< 128-bit decimal floating point type
+
// Derived types... see DerivedTypes.h file.
IntegerTyID, ///< Arbitrary bit width integers
FunctionTyID, ///< Functions
@@ -165,6 +170,21 @@ class Type {
/// Return true if this is powerpc long double.
bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; }
+ /// Return true if this is 'decimal32'.
+ bool isDecimal32Ty() const { return getTypeID() == Decimal32TyID; }
+
+ /// Return true if this is 'decimal64'.
+ bool isDecimal64Ty() const { return getTypeID() == Decimal64TyID; }
+
+ /// Return true if this is 'decimal128'.
+ bool isDecimal128Ty() const { return getTypeID() == Decimal128TyID; }
+
+ /// Return true if this is a decimal floating point.
+ bool isDecimalFloatingPointTy() const {
+ return getTypeID() == Decimal32TyID || getTypeID() == Decimal64TyID ||
+ getTypeID() == Decimal128TyID;
+ }
+
/// Return true if this is a well-behaved IEEE-like type, which has a IEEE
/// compatible layout as defined by isIEEE(), and does not have unnormal
/// values
@@ -184,7 +204,7 @@ class Type {
/// Return true if this is one of the floating-point types
bool isFloatingPointTy() const {
return isIEEELikeFPTy() || getTypeID() == X86_FP80TyID ||
- getTypeID() == PPC_FP128TyID;
+ getTypeID() == PPC_FP128TyID || isDecimalFloatingPointTy();
}
/// Returns true if this is a floating-point type that is an unevaluated sum
@@ -334,11 +354,16 @@ class Type {
/// type.
unsigned getScalarSizeInBits() const LLVM_READONLY;
- /// Return the width of the mantissa of this type. This is only valid on
- /// floating-point types. If the FP type does not have a stable mantissa (e.g.
- /// ppc long double), this method returns -1.
+ /// Return the width of the mantissa of this type, in bits. This is only valid
+ /// on floating-point types. If the FP type does not have a stable mantissa
+ /// (e.g. ppc long double), this method returns -1.
int getFPMantissaWidth() const;
+ /// Return the precision in digits of a decimal floating-point type
+ /// per the "Decimal interchange format parameters" table of
+ /// C23 annex H.2.1, "Interchange floating types".
+ int getDFPPrecisionInDigits() const;
+
/// Return whether the type is IEEE compatible, as defined by the eponymous
/// method in APFloat.
bool isIEEE() const;
@@ -463,6 +488,9 @@ class Type {
static IntegerType *getInt32Ty(LLVMContext &C);
static IntegerType *getInt64Ty(LLVMContext &C);
static IntegerType *getInt128Ty(LLVMContext &C);
+ static Type *getDecimal32Ty(LLVMContext &C);
+ static Type *getDecimal64Ty(LLVMContext &C);
+ static Type *getDecimal128Ty(LLVMContext &C);
template <typename ScalarTy> static Type *getScalarTy(LLVMContext &C) {
int noOfBits = sizeof(ScalarTy) * CHAR_BIT;
if (std::is_integral<ScalarTy>::value) {
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 466bdebc001f58..271fdbf860d741 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -826,6 +826,9 @@ lltok::Kind LLLexer::LexIdentifier() {
TYPEKEYWORD("x86_amx", Type::getX86_AMXTy(Context));
TYPEKEYWORD("token", Type::getTokenTy(Context));
TYPEKEYWORD("ptr", PointerType::getUnqual(Context));
+ TYPEKEYWORD("decimal32", Type::getDecimal32Ty(Context));
+ TYPEKEYWORD("decimal64", Type::getDecimal64Ty(Context));
+ TYPEKEYWORD("decimal128", Type::getDecimal128Ty(Context));
#undef TYPEKEYWORD
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 1d1ec988a93d84..d6ccf83b484776 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2508,6 +2508,15 @@ Error BitcodeReader::parseTypeTableBody() {
TypeName.clear();
break;
}
+ case bitc::TYPE_CODE_DECIMAL32: // 32-bit DFP
+ ResultTy = Type::getDecimal32Ty(Context);
+ break;
+ case bitc::TYPE_CODE_DECIMAL64: // 64-bit DFP
+ ResultTy = Type::getDecimal64Ty(Context);
+ break;
+ case bitc::TYPE_CODE_DECIMAL128: // 128-bit DFP
+ ResultTy = Type::getDecimal128Ty(Context);
+ break;
case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
if (Record.size() < 2)
return error("Invalid array type record");
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index f53fbd73667762..73d74a4729f4d0 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -976,6 +976,9 @@ void ModuleBitcodeWriter::writeTypeTable() {
case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break;
+ case Type::Decimal32TyID: Code = bitc::TYPE_CODE_DECIMAL32; break;
+ case Type::Decimal64TyID: Code = bitc::TYPE_CODE_DECIMAL64; break;
+ case Type::Decimal128TyID: Code = bitc::TYPE_CODE_DECIMAL128; break;
case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index e190d82127908d..30bc27f5a3ec10 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -561,6 +561,9 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
case Type::IntegerTyID:
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
return;
+ case Type::Decimal32TyID: OS << "decimal32"; return;
+ case Type::Decimal64TyID: OS << "decimal64"; return;
+ case Type::Decimal128TyID: OS << "decimal128"; return;
case Type::FunctionTyID: {
FunctionType *FTy = cast<FunctionType>(Ty);
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 17093fa0ac4ee1..0de684136bd212 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -563,6 +563,12 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
return LLVMFP128TypeKind;
case Type::PPC_FP128TyID:
return LLVMPPC_FP128TypeKind;
+ case Type::Decimal32TyID:
+ return LLVMDecimal32TypeKind;
+ case Type::Decimal64TyID:
+ return LLVMDecimal64TypeKind;
+ case Type::Decimal128TyID:
+ return LLVMDecimal128TypeKind;
case Type::LabelTyID:
return LLVMLabelTypeKind;
case Type::MetadataTyID:
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index 2076eeed941769..20d2766eae22d7 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -42,7 +42,9 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID),
PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_MMXTy(C, Type::X86_MMXTyID),
X86_AMXTy(C, Type::X86_AMXTyID), Int1Ty(C, 1), Int8Ty(C, 8),
- Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128) {}
+ Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128),
+ Decimal32Ty(C, Type::Decimal32TyID), Decimal64Ty(C, Type::Decimal64TyID),
+ Decimal128Ty(C, Type::Decimal128TyID) {}
LLVMContextImpl::~LLVMContextImpl() {
// NOTE: We need to delete the contents of OwnedModules, but Module's dtor
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 4cc3f8da6b75b5..0530cec9700713 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1524,6 +1524,7 @@ class LLVMContextImpl {
TokenTy;
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy, X86_AMXTy;
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty;
+ Type Decimal32Ty, Decimal64Ty, Decimal128Ty;
std::unique_ptr<ConstantTokenNone> TheNoneToken;
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 97febcd99b4114..5cf2ec8faf28f4 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -48,6 +48,9 @@ Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
case X86_MMXTyID : return getX86_MMXTy(C);
case X86_AMXTyID : return getX86_AMXTy(C);
case TokenTyID : return getTokenTy(C);
+ case Decimal32TyID : return getDecimal32Ty(C);
+ case Decimal64TyID : return getDecimal64Ty(C);
+ case Decimal128TyID: return getDecimal128Ty(C);
default:
return nullptr;
}
@@ -179,6 +182,9 @@ TypeSize Type::getPrimitiveSizeInBits() const {
case Type::X86_FP80TyID: return TypeSize::Fixed(80);
case Type::FP128TyID: return TypeSize::Fixed(128);
case Type::PPC_FP128TyID: return TypeSize::Fixed(128);
+ case Decimal32TyID: return TypeSize::Fixed(32);
+ case Decimal64TyID: return TypeSize::Fixed(64);
+ case Decimal128TyID: return TypeSize::Fixed(128);
case Type::X86_MMXTyID: return TypeSize::Fixed(64);
case Type::X86_AMXTyID: return TypeSize::Fixed(8192);
case Type::IntegerTyID:
@@ -214,6 +220,18 @@ int Type::getFPMantissaWidth() const {
return -1;
}
+int Type::getDFPPrecisionInDigits() const {
+ if (auto *VTy = dyn_cast<VectorType>(this))
+ return VTy->getElementType()->getDFPPrecisionInDigits();
+ assert(isDecimalFloatingPointTy() && "Not a decimal floating point type!");
+ // Precision values per the "Decimal interchange format parameters" table of
+ /// C23 annex H.2.1, "Interchange floating types".
+ if (getTypeID() == Decimal32TyID) return 7;
+ if (getTypeID() == Decimal64TyID) return 16;
+ if (getTypeID() == Decimal128TyID) return 34;
+ report_fatal_error("unknown decimal floating point type");
+}
+
bool Type::isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited) const {
if (auto *ATy = dyn_cast<ArrayType>(this))
return ATy->getElementType()->isSized(Visited);
@@ -245,6 +263,10 @@ Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; }
Type *Type::getX86_MMXTy(LLVMContext &C) { return &C.pImpl->X86_MMXTy; }
Type *Type::getX86_AMXTy(LLVMContext &C) { return &C.pImpl->X86_AMXTy; }
+Type *Type::getDecimal32Ty(LLVMContext &C) { return &C.pImpl->Decimal32Ty; }
+Type *Type::getDecimal64Ty(LLVMContext &C) { return &C.pImpl->Decimal64Ty; }
+Type *Type::getDecimal128Ty(LLVMContext &C) { return &C.pImpl->Decimal128Ty; }
+
IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; }
IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; }
IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; }
diff --git a/llvm/test/Assembler/dfp.ll b/llvm/test/Assembler/dfp.ll
new file mode 100644
index 00000000000000..8f93eef6836cbc
--- /dev/null
+++ b/llvm/test/Assembler/dfp.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s --check-prefix=ASSEM-DISASS
+
+define decimal32 @check_decimal32(decimal32 %A) {
+; ASSEM-DISASS: ret decimal32 %A
+ ret decimal32 %A
+}
+
+define decimal64 @check_decimal64(decimal64 %A) {
+; ASSEM-DISASS: ret decimal64 %A
+ ret decimal64 %A
+}
+
+define decimal128 @check_decimal128(decimal128 %A) {
+; ASSEM-DISASS: ret decimal128 %A
+ ret decimal128 %A
+}
>From 8bb4d14b5640f6800c2e4547afce6517a4ecf4e8 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Mon, 12 Aug 2024 12:13:20 -0700
Subject: [PATCH 6/7] Add support for -mdecimal-float-abi option.
---
clang/include/clang/Basic/CodeGenOptions.h | 3 ++
.../clang/Basic/DiagnosticDriverKinds.td | 4 ++
clang/include/clang/Basic/TargetInfo.h | 2 +
clang/include/clang/Driver/Options.td | 5 +++
clang/lib/Basic/Targets/X86.cpp | 3 +-
clang/lib/Basic/Targets/X86.h | 1 +
clang/lib/CodeGen/BackendUtil.cpp | 6 +++
clang/lib/Driver/ToolChain.cpp | 1 +
clang/lib/Driver/ToolChains/Arch/X86.cpp | 40 +++++++++++++++++++
clang/lib/Driver/ToolChains/Arch/X86.h | 16 ++++++++
clang/lib/Driver/ToolChains/Clang.cpp | 10 +++++
clang/test/Driver/decimal-float-abi.c | 28 +++++++++++++
llvm/include/llvm/CodeGen/CommandFlags.h | 2 +
llvm/include/llvm/Target/TargetOptions.h | 10 +++++
llvm/lib/Target/X86/X86.td | 3 ++
llvm/lib/Target/X86/X86InstrInfo.td | 1 +
llvm/lib/Target/X86/X86TargetMachine.cpp | 9 +++++
17 files changed, 143 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Driver/decimal-float-abi.c
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 08d4c103ce2453..c7de31071731b6 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -217,6 +217,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// The ABI to use for passing floating point arguments.
std::string FloatABI;
+ /// The encoding used for decimal floating point arguments.
+ std::string DecimalFloatABI;
+
/// The file to use for dumping bug report by `Debugify` for original
/// debug info.
std::string DIBugsReportFilePath;
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 9349ff85ca8a1d..9336593ccd3830 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -62,6 +62,8 @@ def err_drv_no_cuda_libdevice : Error<
"cannot find libdevice for %0; provide path to different CUDA installation "
"via '--cuda-path', or pass '-nocudalib' to build without linking with "
"libdevice">;
+def err_drv_unsupported_decimal_fp_encoding_for_target : Error<
+ "unsupported decimal floating-point encoding '%0' for target '%1'">;
def err_drv_no_rocm_device_lib : Error<
"cannot find ROCm device library%select{| for %1|for ABI version %1}0; provide its path via "
@@ -242,6 +244,8 @@ def err_drv_cannot_read_config_file : Error<
"cannot read configuration file '%0': %1">;
def err_drv_arg_requires_bitcode_input: Error<
"option '%0' requires input to be LLVM bitcode">;
+def err_drv_invalid_mdecimal_float_abi_EQ: Error<
+ "invalid argument '%0' to -mdecimal-float-abi=; each element must be one of: %1">;
def err_target_unsupported_arch
: Error<"the target architecture '%0' is not supported by the target '%1'">;
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index f7c7ffe9671296..276b26111175fe 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -114,6 +114,8 @@ struct TransferrableTargetInfo {
unsigned char DecimalFloat64Width, DecimalFloat64Align;
unsigned char DecimalFloat128Width, DecimalFloat128Align;
+ enum DecimalFloat { Libgcc_BID, Libgcc_DPD, Hard } DecimalFloatABI;
+
// Fixed point bit widths
unsigned char ShortAccumWidth, ShortAccumAlign;
unsigned char AccumWidth, AccumAlign;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 8a510295d34410..84d3cbf8ade3f7 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4284,6 +4284,11 @@ def malign_double : Flag<["-"], "malign-double">, Group<m_Group>,
MarshallingInfoFlag<LangOpts<"AlignDouble">>;
let Flags = [TargetSpecific] in {
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>, Values<"soft,softfp,hard">;
+def mdecimal_float_abi_EQ : Joined<["-"], "mdecimal-float-abi=">, Group<m_Group>,
+Visibility<[ClangOption, CC1Option]>,
+ Values<"libgcc:bid,libgcc:dpd,hard">,
+ HelpText<"The decimal float encoding to use">,
+ MarshallingInfoString<CodeGenOpts<"DecimalFloatABI">>;
def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index 022d5753135e16..60778f47eb629a 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -382,7 +382,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasX87 = true;
} else if (Feature == "+fullbf16") {
HasFullBFloat16 = true;
- }
+ } else if (Feature == "+bid-encoding")
+ HasBIDENCODING = true;
X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
.Case("+avx512f", AVX512F)
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index b759c76fc95ca0..fab5b19b7f3eaa 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -165,6 +165,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasUINTR = false;
bool HasCRC32 = false;
bool HasX87 = false;
+ bool HasBIDENCODING = false;
protected:
llvm::X86::CPUKind CPU = llvm::X86::CK_None;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index e2afc5d566281a..ad77d646b2dc7c 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -353,6 +353,12 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
.Case("softfp", llvm::FloatABI::Soft)
.Case("hard", llvm::FloatABI::Hard)
.Default(llvm::FloatABI::Default);
+ Options.DecimalFloatABIType =
+ llvm::StringSwitch<llvm::DecimalFloatABI>(CodeGenOpts.DecimalFloatABI)
+ .Case("libgcc:bid", llvm::DecimalFloatABI::Libgcc_BID)
+ .Case("libgcc:dpd", llvm::DecimalFloatABI::Libgcc_DPD)
+ .Case("hard", llvm::DecimalFloatABI::Hard)
+ .Default(llvm::DecimalFloatABI::Default);
// Set FP fusion mode.
switch (LangOpts.getDefaultFPContractMode()) {
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 410757d5f9e184..526c43878715d0 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -9,6 +9,7 @@
#include "clang/Driver/ToolChain.h"
#include "ToolChains/Arch/AArch64.h"
#include "ToolChains/Arch/ARM.h"
+#include "ToolChains/Arch/X86.h"
#include "ToolChains/Clang.h"
#include "ToolChains/CommonArgs.h"
#include "ToolChains/Flang.h"
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index cf2bc63d74ada9..59940e0c58d1d8 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -273,4 +273,44 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+prefer-no-gather");
if (Args.hasArg(options::OPT_mno_scatter))
Features.push_back("+prefer-no-scatter");
+
+ // -mdecimal-float-abi
+ x86::DecimalFloatABI ABI = x86::getX86DecimalFloatABI(D, Triple, Args);
+ if (ABI == DecimalFloatABI::Invalid)
+ ABI = x86::getDefaultX86DecimalFloatABI(Triple, Args);
+ if (ABI != x86::DecimalFloatABI::None && ABI != x86::DecimalFloatABI::Default)
+ Features.push_back("+bid-encoding");
+}
+
+x86::DecimalFloatABI
+x86::getDefaultX86DecimalFloatABI(const llvm::Triple &Triple,
+ const ArgList &Args) {
+ if (const Arg *A = Args.getLastArg(options::OPT_fdecimal_floating_point))
+ return DecimalFloatABI::Libgcc_BID;
+ else
+ return DecimalFloatABI::None;
}
+
+// Get the decimal float ABI type from the command line arguments
+// -mdecimal-float-abi=.
+x86::DecimalFloatABI x86::getX86DecimalFloatABI(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args) {
+ x86::DecimalFloatABI ABI = x86::DecimalFloatABI::Invalid;
+ if (const Arg *A = Args.getLastArg(options::OPT_mdecimal_float_abi_EQ)) {
+ StringRef Val = A->getValue();
+ ABI = llvm::StringSwitch<x86::DecimalFloatABI>(A->getValue())
+ .Case("libgcc:bid", DecimalFloatABI::Libgcc_BID)
+ .Case("libgcc:dpd", DecimalFloatABI::Libgcc_DPD)
+ .Case("hard", DecimalFloatABI::Hard)
+ .Default(DecimalFloatABI::None);
+ if (ABI != x86::DecimalFloatABI::None &&
+ ABI != x86::DecimalFloatABI::Default) {
+ // X86 targets only allow BID encoding.
+ if (ABI != x86::DecimalFloatABI::Libgcc_BID)
+ D.Diag(diag::err_drv_unsupported_decimal_fp_encoding_for_target)
+ << Val << "X86";
+ }
+ }
+ return ABI;
+}
\ No newline at end of file
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.h b/clang/lib/Driver/ToolChains/Arch/X86.h
index e07387f3ece3df..14ca9c07dbe17f 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.h
+++ b/clang/lib/Driver/ToolChains/Arch/X86.h
@@ -21,6 +21,15 @@ namespace driver {
namespace tools {
namespace x86 {
+enum class DecimalFloatABI {
+ Default, // Target-specific default.
+ None, // No decimal floating-point support.
+ Libgcc_BID, // libgcc with BID encoding.
+ Libgcc_DPD, // libgcc with DPD encoding.
+ Hard, // Target-specific hard ABI.
+ Invalid
+};
+
std::string getX86TargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
@@ -28,6 +37,13 @@ void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
+DecimalFloatABI getX86DecimalFloatABI(const Driver &D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+DecimalFloatABI getDefaultX86DecimalFloatABI(const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
} // end namespace x86
} // end namespace target
} // end namespace driver
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index d98574def75de7..c9da77a0108643 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2818,6 +2818,16 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
switch (optID) {
default:
break;
+ case options::OPT_mdecimal_float_abi_EQ: {
+ StringRef Val = A->getValue();
+ if (Val == "libgcc:bid" || Val == "libgcc:dpd" || Val == "hard") {
+ CmdArgs.push_back(Args.MakeArgString("-mdecimal-float-abi=" + Val));
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ }
+ break;
+ }
case options::OPT_ffp_model_EQ: {
// If -ffp-model= is seen, reset to fno-fast-math
HonorINFs = true;
diff --git a/clang/test/Driver/decimal-float-abi.c b/clang/test/Driver/decimal-float-abi.c
new file mode 100644
index 00000000000000..777498311cec17
--- /dev/null
+++ b/clang/test/Driver/decimal-float-abi.c
@@ -0,0 +1,28 @@
+// DEFINE: %{common_opts_x86} = -### \
+// DEFINE: -fexperimental-decimal-floating-point
+
+// X86
+// RUN: %clang %{common_opts_x86} --target=x86_64 \
+// RUN: -mdecimal-float-abi=libgcc:bid %s 2>&1 | FileCheck -check-prefix=BID %s
+
+// RUN: not %clang %{common_opts_x86} --target=x86_64 \
+// RUN: -mdecimal-float-abi=libgcc:dpd %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR_DPD %s
+
+// RUN: not %clang %{common_opts_x86} --target=x86_64 \
+// RUN: -mdecimal-float-abi=hard %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR_HARD %s
+
+// RUN: not %clang %{common_opts_x86} --target=mips64-unknown-linux \
+// RUN: -mdecimal-float-abi=hard %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR_MIPS_TRGT %s
+
+// BID: "-mdecimal-float-abi=libgcc:bid" {{.*}} "-target-feature" "+bid-encoding"
+
+// ERROR_DPD: unsupported decimal floating-point encoding 'libgcc:dpd' for target 'X86'
+// ERROR_HARD: unsupported decimal floating-point encoding 'hard' for target 'X86'
+// ERROR_MIPS_TRGT: unsupported option '-mdecimal-float-abi=' for target 'mips64-unknown-linux'
+
+// PPC
+// S390
+// ARM
diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h
index 732d6d0211c996..2f2bb670d11a23 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -75,6 +75,8 @@ bool getEnableHonorSignDependentRoundingFPMath();
llvm::FloatABI::ABIType getFloatABIForCalls();
+llvm::DecimalFloatABI getDecimalFloatABIForCalls();
+
llvm::FPOpFusion::FPOpFusionMode getFuseFPOps();
SwiftAsyncFramePointerMode getSwiftAsyncFramePointer();
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index d6d767f3d22c73..4baf14dd65baec 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -32,6 +32,14 @@ namespace llvm {
};
}
+ enum class DecimalFloatABI {
+ Default, // Target-specific.
+ None, // No decimal floating-point support.
+ Libgcc_BID, // libgcc with BID encoding.
+ Libgcc_DPD, // libgcc with DPD encoding.
+ Hard // Hardware with target-specific encoding.
+ };
+
namespace FPOpFusion {
enum FPOpFusionMode {
Fast, // Enable fusion of FP ops wherever it's profitable.
@@ -376,6 +384,8 @@ namespace llvm {
/// arm-apple-darwin). Hard presumes that the normal FP ABI is used.
FloatABI::ABIType FloatABIType = FloatABI::Default;
+ DecimalFloatABI DecimalFloatABIType = DecimalFloatABI::Default;
+
/// AllowFPOpFusion - This flag is set by the -fp-contract=xxx option.
/// This controls the creation of fused FP ops that store intermediate
/// results in higher precision than IEEE allows (E.g. FMAs).
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index 64f91ae90e2b0c..41e8981f38a276 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -66,6 +66,9 @@ def FeatureXSAVES : SubtargetFeature<"xsaves", "HasXSAVES", "true",
"Support xsaves instructions",
[FeatureXSAVE]>;
+def FeatureBIDENCODING : SubtargetFeature<"bid-encoding", "HasBIDENCODING", "true",
+ "Support BID encoding for decimal floatin-points">;
+
def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1",
"Enable SSE instructions">;
def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2",
diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td
index a20fa6a0c3b6c6..9a3e83af361a53 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.td
+++ b/llvm/lib/Target/X86/X86InstrInfo.td
@@ -929,6 +929,7 @@ def HasAVXVNNIINT16 : Predicate<"Subtarget->hasAVXVNNIINT16()">;
def HasAVXVNNIINT8 : Predicate<"Subtarget->hasAVXVNNIINT8()">;
def HasAVXVNNI : Predicate <"Subtarget->hasAVXVNNI()">;
def NoVLX_Or_NoVNNI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVNNI()">;
+def HasBIDENCODING : Predicate<"Subtarget->hasBIDENCODING()">;
def HasBITALG : Predicate<"Subtarget->hasBITALG()">;
def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">;
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index c0d3b8aa93e6ce..88bfc7836f0ae2 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -238,6 +238,15 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
this->Options.NoTrapAfterNoreturn = TT.isOSBinFormatMachO();
}
+ // Default to triple-appropriate decimal float ABI.
+ if (Options.DecimalFloatABIType == DecimalFloatABI::None) {
+ this->Options.DecimalFloatABIType = DecimalFloatABI::None;
+ } else {
+ if (Options.DecimalFloatABIType == DecimalFloatABI::Default) {
+ this->Options.DecimalFloatABIType = DecimalFloatABI::Libgcc_BID;
+ }
+ }
+
setMachineOutliner(true);
// x86 supports the debug entry values.
>From eb23c6d60228dcc9caac56eba1608fc23fe1c382 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 21 Aug 2024 05:04:14 -0700
Subject: [PATCH 7/7] Made the setting of the DFP ABI target agnostic and
addressed review comments.
---
.../clang/Basic/DiagnosticDriverKinds.td | 6 +--
clang/include/clang/Basic/TargetInfo.h | 16 --------
clang/include/clang/Basic/TargetOptions.h | 23 +++++++++++
clang/include/clang/Driver/Options.td | 2 +-
clang/include/clang/Driver/ToolChain.h | 3 ++
clang/lib/Basic/Targets/X86.cpp | 4 +-
clang/lib/Basic/Targets/X86.h | 5 ++-
clang/lib/CodeGen/BackendUtil.cpp | 7 ++++
clang/lib/Driver/ToolChain.cpp | 16 ++++++++
clang/lib/Driver/ToolChains/Arch/X86.cpp | 40 -------------------
clang/lib/Driver/ToolChains/Arch/X86.h | 18 ++++-----
clang/lib/Driver/ToolChains/Clang.cpp | 3 ++
clang/lib/Driver/ToolChains/CommonArgs.cpp | 37 +++++++++++++++++
clang/lib/Frontend/CompilerInvocation.cpp | 20 ++++++++++
clang/lib/Frontend/InitPreprocessor.cpp | 3 +-
clang/lib/Sema/SemaDeclAttr.cpp | 4 --
clang/lib/Sema/SemaType.cpp | 4 --
clang/test/Driver/decimal-float-abi.c | 11 ++---
llvm/include/llvm/ADT/FloatingPointMode.h | 10 +++++
llvm/include/llvm/Target/TargetOptions.h | 6 +--
llvm/lib/Target/X86/X86.td | 3 --
llvm/lib/Target/X86/X86InstrInfo.td | 1 -
22 files changed, 146 insertions(+), 96 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 9336593ccd3830..c7d625fce48e26 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -62,8 +62,8 @@ def err_drv_no_cuda_libdevice : Error<
"cannot find libdevice for %0; provide path to different CUDA installation "
"via '--cuda-path', or pass '-nocudalib' to build without linking with "
"libdevice">;
-def err_drv_unsupported_decimal_fp_encoding_for_target : Error<
- "unsupported decimal floating-point encoding '%0' for target '%1'">;
+def err_drv_unsupported_decimal_fp_option_for_target : Error<
+ "unsupported decimal floating-point option '%0' for this target">;
def err_drv_no_rocm_device_lib : Error<
"cannot find ROCm device library%select{| for %1|for ABI version %1}0; provide its path via "
@@ -245,7 +245,7 @@ def err_drv_cannot_read_config_file : Error<
def err_drv_arg_requires_bitcode_input: Error<
"option '%0' requires input to be LLVM bitcode">;
def err_drv_invalid_mdecimal_float_abi_EQ: Error<
- "invalid argument '%0' to -mdecimal-float-abi=; each element must be one of: %1">;
+ "invalid argument '%0' to -mdecimal-float-abi=; must be one of: %1">;
def err_target_unsupported_arch
: Error<"the target architecture '%0' is not supported by the target '%1'">;
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 276b26111175fe..9a5c232a5fef6a 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -114,8 +114,6 @@ struct TransferrableTargetInfo {
unsigned char DecimalFloat64Width, DecimalFloat64Align;
unsigned char DecimalFloat128Width, DecimalFloat128Align;
- enum DecimalFloat { Libgcc_BID, Libgcc_DPD, Hard } DecimalFloatABI;
-
// Fixed point bit widths
unsigned char ShortAccumWidth, ShortAccumAlign;
unsigned char AccumWidth, AccumAlign;
@@ -725,20 +723,6 @@ class TargetInfo : public TransferrableTargetInfo,
/// Determine whether constrained floating point is supported on this target.
virtual bool hasStrictFP() const { return HasStrictFP; }
- /// Determine whether decimal floating-point extensions are enabled on this
- /// target.
- bool hasDecimalFloatingPoint() const {
- return DecimalFloatEnablementAndMode.has_value();
- }
-
- /// Determine the encoding used for decimal floating-point values on this
- /// target if decimal floating-point extensions are enabled.
- DecimalFloatMode getDecimalFloatingPointMode() const {
- assert(hasDecimalFloatingPoint() &&
- "Decimal floating-point extensions are not enabled");
- return DecimalFloatEnablementAndMode.value();
- }
-
/// Return the alignment that is the largest alignment ever used for any
/// scalar/SIMD data type on the target machine you are compiling for
/// (including types with an extended alignment requirement).
diff --git a/clang/include/clang/Basic/TargetOptions.h b/clang/include/clang/Basic/TargetOptions.h
index b192c856384b9a..fc35fb2cf477ad 100644
--- a/clang/include/clang/Basic/TargetOptions.h
+++ b/clang/include/clang/Basic/TargetOptions.h
@@ -129,6 +129,29 @@ class TargetOptions {
/// The entry point name for HLSL shader being compiled as specified by -E.
std::string HLSLEntry;
+
+ // If disengaged, decimal floating-point extensions are not supported,
+ // otherwise, the decimal floating-point mode is enabled.
+ std::optional<llvm::DecimalFloatMode> DecimalFloatEnablementAndMode;
+
+ /// Determine whether decimal floating-point extensions are enabled on this
+ /// target.
+ bool hasDecimalFloatingPoint() const {
+ return DecimalFloatEnablementAndMode.has_value();
+ }
+
+ /// Determine the encoding used for decimal floating-point values on this
+ /// target if decimal floating-point extensions are enabled.
+ llvm::DecimalFloatMode getDecimalFloatingPointMode() const {
+ assert(hasDecimalFloatingPoint() &&
+ "Decimal floating-point extensions are not enabled");
+ return DecimalFloatEnablementAndMode.value();
+ }
+
+ /// Set the encoding used for decimal floating-point value on this target.
+ void setDecimalFloatingPointMode(llvm::DecimalFloatMode Mode) {
+ DecimalFloatEnablementAndMode = Mode;
+ }
};
} // end namespace clang
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 84d3cbf8ade3f7..89a9634b38c9d4 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4286,7 +4286,7 @@ let Flags = [TargetSpecific] in {
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>, Values<"soft,softfp,hard">;
def mdecimal_float_abi_EQ : Joined<["-"], "mdecimal-float-abi=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
- Values<"libgcc:bid,libgcc:dpd,hard">,
+ Values<"hard,default,libgcc:bid,libgcc:dpd">,
HelpText<"The decimal float encoding to use">,
MarshallingInfoString<CodeGenOpts<"DecimalFloatABI">>;
def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 0b38b939a188ae..bdbcf81d210b35 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -618,6 +618,9 @@ class ToolChain {
ComputeLLVMTriple(const llvm::opt::ArgList &Args,
types::ID InputType = types::TY_INVALID) const;
+ void setDecimalFloatABI(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple) const;
+
/// ComputeEffectiveClangTriple - Return the Clang triple to use for this
/// target, which may take into account the command line arguments. For
/// example, on Darwin the -mmacosx-version-min= command line argument (which
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index 60778f47eb629a..8912ab2789542a 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -382,9 +382,7 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasX87 = true;
} else if (Feature == "+fullbf16") {
HasFullBFloat16 = true;
- } else if (Feature == "+bid-encoding")
- HasBIDENCODING = true;
-
+ }
X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
.Case("+avx512f", AVX512F)
.Case("+avx2", AVX2)
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index fab5b19b7f3eaa..eba1cc9b7e7297 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -165,7 +165,6 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasUINTR = false;
bool HasCRC32 = false;
bool HasX87 = false;
- bool HasBIDENCODING = false;
protected:
llvm::X86::CPUKind CPU = llvm::X86::CK_None;
@@ -720,6 +719,10 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
Int64Type = IsX32 ? SignedLongLong : SignedLong;
RegParmMax = 6;
+ // TODO
+ // Here we would test for the value of Opts.DecimalFloatEnablementMode.
+ // If it is set we would make sure that it has the correct value for this
+ // target and set the datalayout accordingly.
// Pointers are 32-bit in x32.
resetDataLayout(IsX32 ? "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-"
"i64:64-f80:128-n8:16:32:64-S128"
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index ad77d646b2dc7c..6e6e40a75d4df5 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -353,6 +353,13 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
.Case("softfp", llvm::FloatABI::Soft)
.Case("hard", llvm::FloatABI::Hard)
.Default(llvm::FloatABI::Default);
+ // Set decimal float ABI type;
+ assert((CodeGenOpts.DecimalFloatABI == "hard" ||
+ CodeGenOpts.DecimalFloatABI == "default " ||
+ CodeGenOpts.DecimalFloatABI == "libgcc:bid" ||
+ CodeGenOpts.DecimalFloatABI == "libgcc:dpd" ||
+ CodeGenOpts.DecimalFloatABI.empty()) &&
+ "Invalid Decimal Floating Point ABI!");
Options.DecimalFloatABIType =
llvm::StringSwitch<llvm::DecimalFloatABI>(CodeGenOpts.DecimalFloatABI)
.Case("libgcc:bid", llvm::DecimalFloatABI::Libgcc_BID)
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 526c43878715d0..39a8d53c8286b1 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -923,6 +923,22 @@ bool ToolChain::isThreadModelSupported(const StringRef Model) const {
return false;
}
+void ToolChain::setDecimalFloatABI(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple) const {
+ tools::DecimalFloatABI ABI =
+ tools::getDecimalFloatABI(getDriver(), Triple, Args);
+ tools::DecimalFloatABI DefaultDecimalABI =
+ tools::getDefaultDecimalFloatABI(Triple);
+ if (DefaultDecimalABI != tools::DecimalFloatABI::None &&
+ ABI != DefaultDecimalABI) {
+ Arg *ABIArg =
+ Args.getLastArg(options::OPT_mdecimal_float_abi_EQ);
+ assert(ABIArg && "Non-default decimal float abi expected to be from arg");
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << ABIArg->getAsString(Args) << Triple.getTriple();
+ }
+}
+
std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
types::ID InputType) const {
switch (getTriple().getArch()) {
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index 59940e0c58d1d8..cf2bc63d74ada9 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -273,44 +273,4 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+prefer-no-gather");
if (Args.hasArg(options::OPT_mno_scatter))
Features.push_back("+prefer-no-scatter");
-
- // -mdecimal-float-abi
- x86::DecimalFloatABI ABI = x86::getX86DecimalFloatABI(D, Triple, Args);
- if (ABI == DecimalFloatABI::Invalid)
- ABI = x86::getDefaultX86DecimalFloatABI(Triple, Args);
- if (ABI != x86::DecimalFloatABI::None && ABI != x86::DecimalFloatABI::Default)
- Features.push_back("+bid-encoding");
-}
-
-x86::DecimalFloatABI
-x86::getDefaultX86DecimalFloatABI(const llvm::Triple &Triple,
- const ArgList &Args) {
- if (const Arg *A = Args.getLastArg(options::OPT_fdecimal_floating_point))
- return DecimalFloatABI::Libgcc_BID;
- else
- return DecimalFloatABI::None;
}
-
-// Get the decimal float ABI type from the command line arguments
-// -mdecimal-float-abi=.
-x86::DecimalFloatABI x86::getX86DecimalFloatABI(const Driver &D,
- const llvm::Triple &Triple,
- const ArgList &Args) {
- x86::DecimalFloatABI ABI = x86::DecimalFloatABI::Invalid;
- if (const Arg *A = Args.getLastArg(options::OPT_mdecimal_float_abi_EQ)) {
- StringRef Val = A->getValue();
- ABI = llvm::StringSwitch<x86::DecimalFloatABI>(A->getValue())
- .Case("libgcc:bid", DecimalFloatABI::Libgcc_BID)
- .Case("libgcc:dpd", DecimalFloatABI::Libgcc_DPD)
- .Case("hard", DecimalFloatABI::Hard)
- .Default(DecimalFloatABI::None);
- if (ABI != x86::DecimalFloatABI::None &&
- ABI != x86::DecimalFloatABI::Default) {
- // X86 targets only allow BID encoding.
- if (ABI != x86::DecimalFloatABI::Libgcc_BID)
- D.Diag(diag::err_drv_unsupported_decimal_fp_encoding_for_target)
- << Val << "X86";
- }
- }
- return ABI;
-}
\ No newline at end of file
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.h b/clang/lib/Driver/ToolChains/Arch/X86.h
index 14ca9c07dbe17f..bf0db863439eef 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.h
+++ b/clang/lib/Driver/ToolChains/Arch/X86.h
@@ -19,16 +19,21 @@
namespace clang {
namespace driver {
namespace tools {
-namespace x86 {
enum class DecimalFloatABI {
Default, // Target-specific default.
None, // No decimal floating-point support.
Libgcc_BID, // libgcc with BID encoding.
Libgcc_DPD, // libgcc with DPD encoding.
- Hard, // Target-specific hard ABI.
- Invalid
+ Hard // Target-specific hard ABI.
};
+DecimalFloatABI getDecimalFloatABI(const Driver &D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+DecimalFloatABI getDefaultDecimalFloatABI(const llvm::Triple &Triple);
+
+namespace x86 {
std::string getX86TargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
@@ -37,13 +42,6 @@ void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
-DecimalFloatABI getX86DecimalFloatABI(const Driver &D,
- const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
-
-DecimalFloatABI getDefaultX86DecimalFloatABI(const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
-
} // end namespace x86
} // end namespace target
} // end namespace driver
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index c9da77a0108643..c26e5b8bc4cc13 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1682,6 +1682,9 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
ArgStringList &CmdArgs) const {
const ToolChain &TC = getToolChain();
+ // Set the decimal floating-point ABI.
+ TC.setDecimalFloatABI(Args, EffectiveTriple);
+
// Add the target features
getTargetFeatures(TC.getDriver(), EffectiveTriple, Args, CmdArgs, false);
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 1db05b47e11ba6..42cc4e05d48c83 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -2466,3 +2466,40 @@ void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
}
}
}
+
+tools::DecimalFloatABI
+tools::getDefaultDecimalFloatABI(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ return DecimalFloatABI::Libgcc_BID;
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::amdgcn:
+ return DecimalFloatABI::Libgcc_BID;
+ default:
+ return DecimalFloatABI::None;
+ }
+}
+
+// Get the decimal float ABI type from the command line arguments
+// -mdecimal-float-abi=.
+tools::DecimalFloatABI tools::getDecimalFloatABI(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args) {
+ tools::DecimalFloatABI ABI = tools::DecimalFloatABI::None;
+ if (const Arg *A = Args.getLastArg(options::OPT_mdecimal_float_abi_EQ)) {
+ StringRef Val = A->getValue();
+ ABI = llvm::StringSwitch<tools::DecimalFloatABI>(Val)
+ .Case("libgcc:bid", DecimalFloatABI::Libgcc_BID)
+ .Case("libgcc:dpd", DecimalFloatABI::Libgcc_DPD)
+ .Case("hard", DecimalFloatABI::Hard)
+ .Default(DecimalFloatABI::None);
+ }
+ if (ABI == DecimalFloatABI::None)
+ ABI = getDefaultDecimalFloatABI(Triple);
+ return ABI;
+}
\ No newline at end of file
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index ffb4f30db0243e..d625c3399fc1dd 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4471,6 +4471,25 @@ static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
return Diags.getNumErrors() == NumErrorsBefore;
}
+static void SetDFPEnablementMode(TargetOptions & Opts, llvm::Triple T) {
+ // TODO: Add support for other architectures.
+ switch (T.getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::aarch64:
+ Opts.setDecimalFloatingPointMode(llvm::DecimalFloatMode::BID);
+ break;
+ case llvm::Triple::sparc:
+ Opts.setDecimalFloatingPointMode(llvm::DecimalFloatMode::DPD);
+ break;
+ default:
+ Opts.setDecimalFloatingPointMode(llvm::DecimalFloatMode::None);
+ break;
+ }
+}
+
bool CompilerInvocation::CreateFromArgsImpl(
CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
DiagnosticsEngine &Diags, const char *Argv0) {
@@ -4510,6 +4529,7 @@ bool CompilerInvocation::CreateFromArgsImpl(
InputKind DashX = Res.getFrontendOpts().DashX;
ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
llvm::Triple T(Res.getTargetOpts().Triple);
+ SetDFPEnablementMode(Res.getTargetOpts(), T);
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
Res.getFileSystemOpts().WorkingDir);
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index f0d0260625c175..ffa0eccce59b5e 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -501,8 +501,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// C23 decimal floating point extensions.
// FIXME: Define to 202311L when support for C23 decimal floating point
// FIXME: extensions is feature complete.
- if (!LangOpts.CPlusPlus && LangOpts.DecimalFloatingPoint &&
- TI.hasDecimalFloatingPoint())
+ if (!LangOpts.CPlusPlus && LangOpts.DecimalFloatingPoint)
Builder.defineMacro("__STDC_IEC_60559_DFP__", "197001L");
if (LangOpts.ObjC)
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 091b247f4794c2..cf9c51329577ef 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4865,10 +4865,6 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
Diag(AttrLoc, diag::err_dfp_disabled);
return;
}
- if (!Context.getTargetInfo().hasDecimalFloatingPoint()) {
- Diag(AttrLoc, diag::err_dfp_not_supported);
- return;
- }
}
if (ComplexMode) {
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 13c50b56972b7b..c3ab0d000f4d3c 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1592,10 +1592,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_dfp_disabled);
Result = Context.IntTy;
declarator.setInvalidType(true);
- } else if (!S.Context.getTargetInfo().hasDecimalFloatingPoint()) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_dfp_not_supported);
- Result = Context.IntTy;
- declarator.setInvalidType(true);
} else {
Result = TSTToDecimalFloatType(Context, DS.getTypeSpecType());
}
diff --git a/clang/test/Driver/decimal-float-abi.c b/clang/test/Driver/decimal-float-abi.c
index 777498311cec17..a95716240d47a7 100644
--- a/clang/test/Driver/decimal-float-abi.c
+++ b/clang/test/Driver/decimal-float-abi.c
@@ -13,14 +13,15 @@
// RUN: -mdecimal-float-abi=hard %s 2>&1 \
// RUN: | FileCheck -check-prefix=ERROR_HARD %s
-// RUN: not %clang %{common_opts_x86} --target=mips64-unknown-linux \
+// RUN: %clang %{common_opts_x86} --target=mips64-unknown-linux \
// RUN: -mdecimal-float-abi=hard %s 2>&1 \
-// RUN: | FileCheck -check-prefix=ERROR_MIPS_TRGT %s
+// RUN: | FileCheck -check-prefix=HARD %s
-// BID: "-mdecimal-float-abi=libgcc:bid" {{.*}} "-target-feature" "+bid-encoding"
+// BID: "-mdecimal-float-abi=libgcc:bid" {{.*}}
+// HARD: "-mdecimal-float-abi=hard" {{.*}}
-// ERROR_DPD: unsupported decimal floating-point encoding 'libgcc:dpd' for target 'X86'
-// ERROR_HARD: unsupported decimal floating-point encoding 'hard' for target 'X86'
+// ERROR_DPD: unsupported option '-mdecimal-float-abi=libgcc:dpd' for target 'x86_64'
+// ERROR_HARD: unsupported option '-mdecimal-float-abi=hard' for target 'x86_64'
// ERROR_MIPS_TRGT: unsupported option '-mdecimal-float-abi=' for target 'mips64-unknown-linux'
// PPC
diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h b/llvm/include/llvm/ADT/FloatingPointMode.h
index 468de085d1bede..31a732ea3868a4 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -279,6 +279,16 @@ FPClassTest unknown_sign(FPClassTest Mask);
/// Write a human readable form of \p Mask to \p OS
raw_ostream &operator<<(raw_ostream &OS, FPClassTest Mask);
+ // ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
+// Multiple encoding forms for the storage of decimal floating-point
+// values have been defined for use on various platforms. This
+// enumeration provides an enumerator for each known encoding.
+enum class DecimalFloatMode : uint8_t {
+ BID, // Binary Integer Decimal.
+ DPD, // Densely Packed Decimal.
+ None // No decimal floating-point in target.
+};
+
} // namespace llvm
#endif // LLVM_ADT_FLOATINGPOINTMODE_H
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 4baf14dd65baec..e3be2b61c68d79 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -32,12 +32,12 @@ namespace llvm {
};
}
- enum class DecimalFloatABI {
+ enum class DecimalFloatABI {
Default, // Target-specific.
None, // No decimal floating-point support.
+ Hard, // Hardware with target-specific encoding.
Libgcc_BID, // libgcc with BID encoding.
- Libgcc_DPD, // libgcc with DPD encoding.
- Hard // Hardware with target-specific encoding.
+ Libgcc_DPD // libgcc with DPD encoding.
};
namespace FPOpFusion {
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index 41e8981f38a276..64f91ae90e2b0c 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -66,9 +66,6 @@ def FeatureXSAVES : SubtargetFeature<"xsaves", "HasXSAVES", "true",
"Support xsaves instructions",
[FeatureXSAVE]>;
-def FeatureBIDENCODING : SubtargetFeature<"bid-encoding", "HasBIDENCODING", "true",
- "Support BID encoding for decimal floatin-points">;
-
def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1",
"Enable SSE instructions">;
def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2",
diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td
index 9a3e83af361a53..a20fa6a0c3b6c6 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.td
+++ b/llvm/lib/Target/X86/X86InstrInfo.td
@@ -929,7 +929,6 @@ def HasAVXVNNIINT16 : Predicate<"Subtarget->hasAVXVNNIINT16()">;
def HasAVXVNNIINT8 : Predicate<"Subtarget->hasAVXVNNIINT8()">;
def HasAVXVNNI : Predicate <"Subtarget->hasAVXVNNI()">;
def NoVLX_Or_NoVNNI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVNNI()">;
-def HasBIDENCODING : Predicate<"Subtarget->hasBIDENCODING()">;
def HasBITALG : Predicate<"Subtarget->hasBITALG()">;
def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">;
More information about the llvm-commits
mailing list