diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index f7c7ffe967129..f8734dcda10c7 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -220,15 +220,6 @@ 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, @@ -287,10 +278,6 @@ class TargetInfo : public TransferrableTargetInfo, std::optional MaxBitIntWidth; - // If disengaged, decimal floating-point extensions are not supported, - // otherwise, the decimal floating-point mode that is enabled. - std::optional DecimalFloatEnablementAndMode; - std::optional DarwinTargetVariantTriple; // TargetInfo Constructor. Default initializes all fields. @@ -723,20 +710,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 b192c856384b9..fc35fb2cf477a 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 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/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index e62b215240ad3..6b34c9e8d33eb 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -524,12 +524,6 @@ 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 41abb01c42707..f2bd846e670d1 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -352,12 +352,6 @@ class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo { 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/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index ef667b3d511f0..8f939abc57ff0 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -363,12 +363,23 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo { public: PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : PPCTargetInfo(Triple, Opts) { + std::string EncodedLayout; + if (Opts.hasDecimalFloatingPoint()) { + const llvm::DecimalFloatMode Encoding = + Opts.getDecimalFloatingPointMode(); + assert(Encoding == llvm::DecimalFloatMode::BID && + "wrong decimal floating-point encoding for powerpc target"); + EncodedLayout = "d:bid-m"; + } else { + EncodedLayout = "m"; + } + if (Triple.isOSAIX()) - resetDataLayout("E-m:a-p:32:32-Fi32-i64:64-n32"); + resetDataLayout("E-" + EncodedLayout + ":a-p:32:32-Fi32-i64:64-n32"); else if (Triple.getArch() == llvm::Triple::ppcle) - resetDataLayout("e-m:e-p:32:32-Fn32-i64:64-n32"); + resetDataLayout("e" + EncodedLayout + ":e-p:32:32-Fn32-i64:64-n32"); else - resetDataLayout("E-m:e-p:32:32-Fn32-i64:64-n32"); + resetDataLayout("E" + EncodedLayout + ":e-p:32:32-Fn32-i64:64-n32"); switch (getTriple().getOS()) { case llvm::Triple::Linux: diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index b759c76fc95ca..9fac386a4bc2e 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -719,13 +719,23 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo { Int64Type = IsX32 ? SignedLongLong : SignedLong; RegParmMax = 6; + std::string EncodedLayout; + if (Opts.hasDecimalFloatingPoint()) { + const llvm::DecimalFloatMode Encoding = + Opts.getDecimalFloatingPointMode(); + assert(Encoding == llvm::DecimalFloatMode::BID && + "wrong decimal floating-point encoding for x86_64 target"); + EncodedLayout = "e-d:bid"; + } else { + EncodedLayout = "e"; + } + std::string Layout = + "-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"; + // 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" - : IsWinCOFF ? "e-m:w-p270:32:32-p271:32:32-p272:64:" - "64-i64:64-f80:128-n8:16:32:64-S128" - : "e-m:e-p270:32:32-p271:32:32-p272:64:" - "64-i64:64-f80:128-n8:16:32:64-S128"); + resetDataLayout(IsX32 ? EncodedLayout + "-m:e-p:32:32" + Layout + : IsWinCOFF ? EncodedLayout + "-m:w" + Layout + : EncodedLayout + "-m:e" + Layout); // Use fpret only for long double. RealTypeUsesObjCFPRetMask = (unsigned)FloatModeKind::LongDouble; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index e2afc5d566281..7c578b9f7ad6b 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -369,7 +369,13 @@ static bool initTargetOptions(DiagnosticsEngine &Diags, Options.AllowFPOpFusion = llvm::FPOpFusion::Fast; break; } - + if (LangOpts.DecimalFloatingPoint) { + if (TargetOpts.getDecimalFloatingPointMode() == llvm::DecimalFloatMode::BID) + Options.DFPEncoding = llvm::DecimalFloatMode::BID; + else if (TargetOpts.getDecimalFloatingPointMode() == + llvm::DecimalFloatMode::DPD) + Options.DFPEncoding = llvm::DecimalFloatMode::DPD; + } Options.BinutilsVersion = llvm::TargetMachine::parseBinutilsVersion(CodeGenOpts.BinutilsVersion); Options.UseInitArray = CodeGenOpts.UseInitArray; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 49c1d8e553a1d..78237c711cdf1 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -105,6 +105,16 @@ void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; } void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; } bool CompilerInstance::createTarget() { + if (getLangOpts().DecimalFloatingPoint) { + if (getInvocation().getTargetOpts().CPU == "x86" || + getInvocation().getTargetOpts().CPU == "x86-64" || + getInvocation().getTargetOpts().CPU == "powerpc") + getInvocation().getTargetOpts().setDecimalFloatingPointMode( + llvm::DecimalFloatMode::BID); + else + getInvocation().getTargetOpts().setDecimalFloatingPointMode( + llvm::DecimalFloatMode::DPD); + } // Create the target instance. setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getInvocation().TargetOpts)); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index f0d0260625c17..ffa0eccce59b5 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 091b247f4794c..cf9c51329577e 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 13c50b56972b7..06183ab56e3bd 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1592,13 +1592,8 @@ 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 { + } else Result = TSTToDecimalFloatType(Context, DS.getTypeSpecType()); - } break; case DeclSpec::TST_class: case DeclSpec::TST_enum: diff --git a/clang/test/CodeGen/dfp-dl.c b/clang/test/CodeGen/dfp-dl.c new file mode 100644 index 0000000000000..2d54dfc9f9c31 --- /dev/null +++ b/clang/test/CodeGen/dfp-dl.c @@ -0,0 +1,25 @@ +// DEFINE: %{common_opts_x86} = -triple x86_64 -target-cpu x86-64 \ +// DEFINE: -emit-llvm -o - + +// RUN: %clang_cc1 %{common_opts_x86} %s | FileCheck %s --check-prefix=CHECK_x86 + +// RUN: %clang_cc1 %{common_opts_x86} -fexperimental-decimal-floating-point %s \ +// RUN: | FileCheck %s --check-prefix=DFP_x86 + +// DEFINE: %{common_opts_ppc} = -triple powerpc-unknown-aix \ +// DEFINE: -target-cpu powerpc -emit-llvm -o - + +// RUN: %clang_cc1 %{common_opts_ppc} %s | FileCheck %s \ +// RUN: --check-prefixes=CHECK_PPC + +// RUN: %clang_cc1 %{common_opts_ppc} -fexperimental-decimal-floating-point %s \ +// RUN: | FileCheck %s --check-prefixes=DFP_PPC + +// CHECK_x86: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +// DFP_x86: target datalayout = "e-d:bid-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +// CHECK_PPC: target datalayout = "E-m:a-p:32:32-Fi32-i64:64-n32" +// DFP_PPC: target datalayout = "E-d:bid-m:a-p:32:32-Fi32-i64:64-n32" + +void foo() { +} diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h b/llvm/include/llvm/ADT/FloatingPointMode.h index 468de085d1bed..7304ebbc1bb5a 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/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index c1fce09357ee3..8b474aaa1af41 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -24,6 +24,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/FloatingPointMode.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Type.h" #include "llvm/Support/Alignment.h" @@ -119,6 +120,8 @@ class DataLayout { /// Defaults to false. bool BigEndian; + llvm::DecimalFloatMode DFPEncoding; + unsigned AllocaAddrSpace; MaybeAlign StackNaturalAlign; unsigned ProgramAddrSpace; @@ -205,6 +208,7 @@ class DataLayout { clear(); StringRepresentation = DL.StringRepresentation; BigEndian = DL.isBigEndian(); + DFPEncoding = DL.DFPEncoding; AllocaAddrSpace = DL.AllocaAddrSpace; StackNaturalAlign = DL.StackNaturalAlign; FunctionPtrAlign = DL.FunctionPtrAlign; diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h index d6d767f3d22c7..4c3b98eebdf39 100644 --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -404,6 +404,8 @@ namespace llvm { /// Which debugger to tune for. DebuggerKind DebuggerTuning = DebuggerKind::Default; + llvm::DecimalFloatMode DFPEncoding = llvm::DecimalFloatMode::None; + private: /// Flushing mode to assume in default FP environment. DenormalMode FPDenormalMode; diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index 53842b184ed6b..8fbb46fecc6b3 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -197,6 +197,7 @@ void DataLayout::reset(StringRef Desc) { LayoutMap = nullptr; BigEndian = false; + DFPEncoding = llvm::DecimalFloatMode::None; AllocaAddrSpace = 0; StackNaturalAlign.reset(); ProgramAddrSpace = 0; @@ -318,6 +319,14 @@ Error DataLayout::parseSpecifier(StringRef Desc) { case 'e': BigEndian = false; break; + case 'd': + if (Split.second == "bid") + DFPEncoding = llvm::DecimalFloatMode::BID; + else if (Split.second == "dpd") + DFPEncoding = llvm::DecimalFloatMode::DPD; + else + DFPEncoding = llvm::DecimalFloatMode::None; + break; case 'p': { // Address space. unsigned AddrSpace = 0; diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index c0d3b8aa93e6c..634a5da0f6c37 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -117,10 +117,18 @@ static std::unique_ptr createTLOF(const Triple &TT) { return std::make_unique(); } -static std::string computeDataLayout(const Triple &TT) { +static std::string computeDataLayout(const Triple &TT, + const TargetOptions &Options) { // X86 is little endian std::string Ret = "e"; + // Decimal floating-point encoding. + if (Options.DFPEncoding != llvm::DecimalFloatMode::None) { + assert(Options.DFPEncoding == llvm::DecimalFloatMode::BID && + "Decimal floating-point on x86 is BID!"); + Ret += "-d:bid"; + } + Ret += DataLayout::getManglingComponent(TT); // X86 and x32 have 32 bit pointers. if (!TT.isArch64Bit() || TT.isX32() || TT.isOSNaCl()) @@ -226,7 +234,7 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT, std::optional CM, CodeGenOptLevel OL, bool JIT) : LLVMTargetMachine( - T, computeDataLayout(TT), TT, CPU, FS, Options, + T, computeDataLayout(TT, Options), TT, CPU, FS, Options, getEffectiveRelocModel(TT, JIT, RM), getEffectiveX86CodeModel(CM, JIT, TT.getArch() == Triple::x86_64), OL),