Index: clang/include/clang/Basic/FPOptions.def =================================================================== --- clang/include/clang/Basic/FPOptions.def +++ clang/include/clang/Basic/FPOptions.def @@ -12,19 +12,24 @@ # error Define the OPTION macro to handle floating point language options #endif +#define SIMPLE_OPTION(name, type, width, previousName) \ + OPTION(name, type, static_cast, static_cast, width, previousName) + // OPTION(name, type, width, previousName) -OPTION(FPContractMode, LangOptions::FPModeKind, 2, First) -OPTION(RoundingMath, bool, 1, FPContractMode) -OPTION(ConstRoundingMode, LangOptions::RoundingMode, 3, RoundingMath) -OPTION(SpecifiedExceptionMode, LangOptions::FPExceptionModeKind, 2, ConstRoundingMode) -OPTION(AllowFEnvAccess, bool, 1, SpecifiedExceptionMode) -OPTION(AllowFPReassociate, bool, 1, AllowFEnvAccess) -OPTION(NoHonorNaNs, bool, 1, AllowFPReassociate) -OPTION(NoHonorInfs, bool, 1, NoHonorNaNs) -OPTION(NoSignedZero, bool, 1, NoHonorInfs) -OPTION(AllowReciprocal, bool, 1, NoSignedZero) -OPTION(AllowApproxFunc, bool, 1, AllowReciprocal) -OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) -OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) -OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) +SIMPLE_OPTION(FPContractMode, LangOptions::FPModeKind, 2, First) +SIMPLE_OPTION(RoundingMath, bool, 1, FPContractMode) +OPTION(ConstRoundingMode, LangOptions::RoundingMode, llvm::encodeRoundingMode, llvm::decodeRoundingMode, 3, RoundingMath) +SIMPLE_OPTION(SpecifiedExceptionMode, LangOptions::FPExceptionModeKind, 2, ConstRoundingMode) +SIMPLE_OPTION(AllowFEnvAccess, bool, 1, SpecifiedExceptionMode) +SIMPLE_OPTION(AllowFPReassociate, bool, 1, AllowFEnvAccess) +SIMPLE_OPTION(NoHonorNaNs, bool, 1, AllowFPReassociate) +SIMPLE_OPTION(NoHonorInfs, bool, 1, NoHonorNaNs) +SIMPLE_OPTION(NoSignedZero, bool, 1, NoHonorInfs) +SIMPLE_OPTION(AllowReciprocal, bool, 1, NoSignedZero) +SIMPLE_OPTION(AllowApproxFunc, bool, 1, AllowReciprocal) +SIMPLE_OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) +SIMPLE_OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) +SIMPLE_OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) + +#undef SIMPLE_OPTION #undef OPTION Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -670,7 +670,7 @@ // Define a fake option named "First" so that we have a PREVIOUS even for the // real first option. static constexpr storage_type FirstShift = 0, FirstWidth = 0; -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, ENCODE, DECODE, TYPE, WIDTH, PREVIOUS) \ static constexpr storage_type NAME##Shift = \ PREVIOUS##Shift + PREVIOUS##Width; \ static constexpr storage_type NAME##Width = WIDTH; \ @@ -679,7 +679,7 @@ #include "clang/Basic/FPOptions.def" static constexpr storage_type TotalWidth = 0 -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) +WIDTH +#define OPTION(NAME, ENCODE, DECODE, TYPE, WIDTH, PREVIOUS) +WIDTH #include "clang/Basic/FPOptions.def" ; static_assert(TotalWidth <= StorageBitSize, "Too short type for FPOptions"); @@ -783,12 +783,13 @@ FPOptionsOverride getChangesFrom(const FPOptions &Base) const; // We can define most of the accessors automatically: -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, TYPE, ENCODE, DECODE, WIDTH, PREVIOUS) \ TYPE get##NAME() const { \ - return static_cast((Value & NAME##Mask) >> NAME##Shift); \ + return DECODE((Value & NAME##Mask) >> NAME##Shift); \ } \ void set##NAME(TYPE value) { \ - Value = (Value & ~NAME##Mask) | (storage_type(value) << NAME##Shift); \ + Value = \ + (Value & ~NAME##Mask) | (storage_type(ENCODE(value)) << NAME##Shift); \ } #include "clang/Basic/FPOptions.def" LLVM_DUMP_METHOD void dump(); @@ -890,7 +891,7 @@ } bool operator!=(FPOptionsOverride other) const { return !(*this == other); } -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, TYPE, ENCODE, DECODE, WIDTH, PREVIOUS) \ bool has##NAME##Override() const { \ return OverrideMask & FPOptions::NAME##Mask; \ } \ Index: clang/lib/AST/JSONNodeDumper.cpp =================================================================== --- clang/lib/AST/JSONNodeDumper.cpp +++ clang/lib/AST/JSONNodeDumper.cpp @@ -1740,7 +1740,7 @@ llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) { llvm::json::Object Ret; -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, TYPE, ENCODE, DECODE, WIDTH, PREVIOUS) \ if (FPO.has##NAME##Override()) \ Ret.try_emplace(#NAME, static_cast(FPO.get##NAME##Override())); #include "clang/Basic/FPOptions.def" Index: clang/lib/AST/TextNodeDumper.cpp =================================================================== --- clang/lib/AST/TextNodeDumper.cpp +++ clang/lib/AST/TextNodeDumper.cpp @@ -756,7 +756,7 @@ } void TextNodeDumper::printFPOptions(FPOptionsOverride FPO) { -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, TYPE, ENCODE, DECODE, WIDTH, PREVIOUS) \ if (FPO.has##NAME##Override()) \ OS << " " #NAME "=" << FPO.get##NAME##Override(); #include "clang/Basic/FPOptions.def" Index: clang/lib/Basic/LangOptions.cpp =================================================================== --- clang/lib/Basic/LangOptions.cpp +++ clang/lib/Basic/LangOptions.cpp @@ -215,7 +215,7 @@ FPOptionsOverride FPOptions::getChangesSlow(const FPOptions &Base) const { FPOptions::storage_type OverrideMask = 0; -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, TYPE, ENCODE, DECODE, WIDTH, PREVIOUS) \ if (get##NAME() != Base.get##NAME()) \ OverrideMask |= NAME##Mask; #include "clang/Basic/FPOptions.def" @@ -223,14 +223,14 @@ } LLVM_DUMP_METHOD void FPOptions::dump() { -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, TYPE, ENCODE, DECODE, WIDTH, PREVIOUS) \ llvm::errs() << "\n " #NAME " " << get##NAME(); #include "clang/Basic/FPOptions.def" llvm::errs() << "\n"; } LLVM_DUMP_METHOD void FPOptionsOverride::dump() { -#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ +#define OPTION(NAME, TYPE, ENCODE, DECODE, WIDTH, PREVIOUS) \ if (has##NAME##Override()) \ llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override(); #include "clang/Basic/FPOptions.def" Index: llvm/include/llvm/ADT/FloatingPointMode.h =================================================================== --- llvm/include/llvm/ADT/FloatingPointMode.h +++ llvm/include/llvm/ADT/FloatingPointMode.h @@ -35,18 +35,28 @@ /// rounding mode value, so it does not need to fit the bit fields. /// enum class RoundingMode : int8_t { + // Special values. + Invalid = -2, ///< Denotes invalid value. + Dynamic = -1, ///< Denotes mode unknown at compile time. + // Rounding mode defined in IEEE-754. TowardZero = 0, ///< roundTowardZero. NearestTiesToEven = 1, ///< roundTiesToEven. TowardPositive = 2, ///< roundTowardPositive. TowardNegative = 3, ///< roundTowardNegative. - NearestTiesToAway = 4, ///< roundTiesToAway. - - // Special values. - Dynamic = 7, ///< Denotes mode unknown at compile time. - Invalid = -1 ///< Denotes invalid value. + NearestTiesToAway = 4 ///< roundTiesToAway. }; +/// Encode a RoundingMode value into a form suitable for a bitfield. +constexpr int8_t encodeRoundingMode(RoundingMode RM) { + return static_cast(RM) + 1; +} + +/// Decode a RoundingMode value from a form suitable for a bitfield. +constexpr RoundingMode decodeRoundingMode(int8_t Val) { + return static_cast(Val - 1); +} + /// Returns text representation of the given rounding mode. inline StringRef spell(RoundingMode RM) { switch (RM) {