Index: llvm/include/llvm/ADT/FloatingPointMode.h =================================================================== --- llvm/include/llvm/ADT/FloatingPointMode.h +++ llvm/include/llvm/ADT/FloatingPointMode.h @@ -288,6 +288,9 @@ return NewMask; } +/// Write a human readable form of \p Mask to \p OS +raw_ostream &operator<<(raw_ostream &OS, FPClassTest Mask); + } // namespace llvm #endif // LLVM_ADT_FLOATINGPOINTMODE_H Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -421,56 +421,6 @@ llvm_unreachable("Invalid ModRefInfo"); } -// Every bitfield has a unique name and one or more aliasing names that cover -// multiple bits. Names should be listed in order of preference, with higher -// popcounts listed first. -// -// Bits are consumed as printed. Each field should only be represented in one -// printed field. -static constexpr std::pair NoFPClassName[] = { - {fcAllFlags, "all"}, - {fcNan, "nan"}, - {fcSNan, "snan"}, - {fcQNan, "qnan"}, - {fcInf, "inf"}, - {fcNegInf, "ninf"}, - {fcPosInf, "pinf"}, - {fcZero, "zero"}, - {fcNegZero, "nzero"}, - {fcPosZero, "pzero"}, - {fcSubnormal, "sub"}, - {fcNegSubnormal, "nsub"}, - {fcPosSubnormal, "psub"}, - {fcNormal, "norm"}, - {fcNegNormal, "nnorm"}, - {fcPosNormal, "pnorm"} -}; - -static std::string getNoFPClassAttrAsString(unsigned Mask) { - std::string Result("nofpclass("); - raw_string_ostream OS(Result); - - if (Mask == 0) { - OS << "none)"; - return Result; - } - - ListSeparator LS(" "); - for (auto [BitTest, Name] : NoFPClassName) { - if ((Mask & BitTest) == BitTest) { - OS << LS << Name; - - // Clear the bits so we don't print any aliased names later. - Mask &= ~BitTest; - } - } - - assert(Mask == 0 && "didn't print some mask bits"); - - OS << ')'; - return Result; -} - std::string Attribute::getAsString(bool InAttrGrp) const { if (!pImpl) return {}; @@ -604,8 +554,12 @@ return Result; } - if (hasAttribute(Attribute::NoFPClass)) - return getNoFPClassAttrAsString(getValueAsInt()); + if (hasAttribute(Attribute::NoFPClass)) { + std::string Result = "nofpclass"; + raw_string_ostream OS(Result); + OS << getNoFPClass(); + return Result; + } // Convert target-dependent attributes to strings of the form: // Index: llvm/lib/Support/CMakeLists.txt =================================================================== --- llvm/lib/Support/CMakeLists.txt +++ llvm/lib/Support/CMakeLists.txt @@ -165,6 +165,7 @@ FileCollector.cpp FileUtilities.cpp FileOutputBuffer.cpp + FloatingPointMode.cpp FoldingSet.cpp FormattedStream.cpp FormatVariadic.cpp Index: llvm/lib/Support/FloatingPointMode.cpp =================================================================== --- /dev/null +++ llvm/lib/Support/FloatingPointMode.cpp @@ -0,0 +1,61 @@ +//===- FloatingPointMode.cpp ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/FloatingPointMode.h" +#include "llvm/ADT/StringExtras.h" + +using namespace llvm; + +// Every bitfield has a unique name and one or more aliasing names that cover +// multiple bits. Names should be listed in order of preference, with higher +// popcounts listed first. +// +// Bits are consumed as printed. Each field should only be represented in one +// printed field. +static constexpr std::pair NoFPClassName[] = { + {fcAllFlags, "all"}, + {fcNan, "nan"}, + {fcSNan, "snan"}, + {fcQNan, "qnan"}, + {fcInf, "inf"}, + {fcNegInf, "ninf"}, + {fcPosInf, "pinf"}, + {fcZero, "zero"}, + {fcNegZero, "nzero"}, + {fcPosZero, "pzero"}, + {fcSubnormal, "sub"}, + {fcNegSubnormal, "nsub"}, + {fcPosSubnormal, "psub"}, + {fcNormal, "norm"}, + {fcNegNormal, "nnorm"}, + {fcPosNormal, "pnorm"} +}; + +raw_ostream &operator<<(raw_ostream &OS, FPClassTest Mask) { + OS << '('; + + if (Mask == fcNone) { + OS << "none)"; + return OS; + } + + ListSeparator LS(" "); + for (auto [BitTest, Name] : NoFPClassName) { + if ((Mask & BitTest) == BitTest) { + OS << LS << Name; + + // Clear the bits so we don't print any aliased names later. + Mask &= ~BitTest; + } + } + + assert(Mask == 0 && "didn't print some mask bits"); + + OS << ')'; + return OS; +}