diff --git a/llvm/include/llvm/ADT/Sequence.h b/llvm/include/llvm/ADT/Sequence.h --- a/llvm/include/llvm/ADT/Sequence.h +++ b/llvm/include/llvm/ADT/Sequence.h @@ -18,12 +18,17 @@ #include // assert #include // std::random_access_iterator_tag #include // std::numeric_limits -#include // std::underlying_type, std::is_enum +#include // std::underlying_type, std::is_enum, std::false_type #include "llvm/Support/MathExtras.h" // AddOverflow / SubOverflow namespace llvm { +template struct is_iterable_enum : public std::false_type {}; + +#define DECLARE_ITERABLE_ENUM(ENUM) \ + template <> struct is_iterable_enum : public std::true_type {} + namespace detail { // Returns whether a value of type U can be represented with type T. @@ -56,6 +61,8 @@ template ::value, bool> = 0> static CheckedInt from(Enum FromValue) { + static_assert(llvm::is_iterable_enum::value, + "Enum type is not iterable, use DECLARE_ITERABLE_ENUM"); using type = typename std::underlying_type::type; return from(static_cast(FromValue)); } diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -19,6 +19,7 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Sequence.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -2357,6 +2358,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(FuncletPadInst, Value) +DECLARE_ITERABLE_ENUM(CmpInst::Predicate); + } // end namespace llvm #endif // LLVM_IR_INSTRTYPES_H diff --git a/llvm/include/llvm/Support/MachineValueType.h b/llvm/include/llvm/Support/MachineValueType.h --- a/llvm/include/llvm/Support/MachineValueType.h +++ b/llvm/include/llvm/Support/MachineValueType.h @@ -1454,6 +1454,8 @@ /// @} }; + DECLARE_ITERABLE_ENUM(MVT::SimpleValueType); + } // end namespace llvm #endif // LLVM_SUPPORT_MACHINEVALUETYPE_H diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -33,6 +33,9 @@ #endif namespace llvm { + +DECLARE_ITERABLE_ENUM(X86::CondCode); + namespace exegesis { static cl::OptionCategory @@ -619,13 +622,13 @@ public: X86SavedState() { #ifdef __x86_64__ -# if defined(_MSC_VER) +#if defined(_MSC_VER) _fxsave64(FPState); Eflags = __readeflags(); -# elif defined(__GNUC__) +#elif defined(__GNUC__) __builtin_ia32_fxsave64(FPState); Eflags = __builtin_ia32_readeflags_u64(); -# endif +#endif #else llvm_unreachable("X86 exegesis running on non-X86 target"); #endif @@ -635,15 +638,15 @@ // Restoring the X87 state does not flush pending exceptions, make sure // these exceptions are flushed now. #ifdef __x86_64__ -# if defined(_MSC_VER) +#if defined(_MSC_VER) _clearfp(); _fxrstor64(FPState); __writeeflags(Eflags); -# elif defined(__GNUC__) +#elif defined(__GNUC__) asm volatile("fwait"); __builtin_ia32_fxrstor64(FPState); __builtin_ia32_writeeflags_u64(Eflags); -# endif +#endif #else llvm_unreachable("X86 exegesis running on non-X86 target"); #endif diff --git a/llvm/unittests/ADT/SequenceTest.cpp b/llvm/unittests/ADT/SequenceTest.cpp --- a/llvm/unittests/ADT/SequenceTest.cpp +++ b/llvm/unittests/ADT/SequenceTest.cpp @@ -17,7 +17,7 @@ using testing::ElementsAre; -namespace { +namespace llvm { using detail::canTypeFitValue; using detail::CheckedInt; @@ -68,17 +68,6 @@ EXPECT_EQ(Actual - (Actual + 2), -2); } -TEST(StrongIntTest, Enums) { - enum UntypedEnum { A = 3 }; - EXPECT_EQ(CheckedInt::from(A).to(), A); - - enum TypedEnum : uint32_t { B = 3 }; - EXPECT_EQ(CheckedInt::from(B).to(), B); - - enum class ScopedEnum : uint16_t { C = 3 }; - EXPECT_EQ(CheckedInt::from(ScopedEnum::C).to(), ScopedEnum::C); -} - #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) TEST(StrongIntDeathTest, OutOfBounds) { // Values above 'INTMAX_MAX' are not representable. @@ -215,4 +204,17 @@ EXPECT_EQ(Backward[2], 7); } -} // anonymous namespace +enum UntypedEnum { A = 3 }; +enum TypedEnum : uint32_t { B = 3 }; +enum class ScopedEnum : uint16_t { C = 3 }; + +DECLARE_ITERABLE_ENUM(UntypedEnum); +DECLARE_ITERABLE_ENUM(TypedEnum); +DECLARE_ITERABLE_ENUM(ScopedEnum); + +TEST(StrongIntTest, Enums) { + EXPECT_EQ(CheckedInt::from(A).to(), A); + EXPECT_EQ(CheckedInt::from(B).to(), B); + EXPECT_EQ(CheckedInt::from(ScopedEnum::C).to(), ScopedEnum::C); +} +} // namespace llvm