Use std::bitset for SubtargetFeatures.

Previously, subtarget features were a bitfield with the underlying type being uint64_t. 
Since several targets (X86 and ARM, in particular) have hit or were very close to hitting this bound, switching the features to use a bitset.
No functional change.

The first several times this was committed (e.g. r229831, r233055), it caused several buildbot failures.
Apparently the reason for most failures was both clang and gcc's inability to deal with large numbers (> 10K) of bitset constructor calls in tablegen-generated initializers of instruction info tables. 
This should now be fixed.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238192 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Kuperstein 2015-05-26 10:47:10 +00:00
parent bda72d8098
commit d714fcf5c8
38 changed files with 1074 additions and 1022 deletions

View File

@ -22,6 +22,7 @@ namespace llvm {
class MCInst; class MCInst;
class MCRegisterInfo; class MCRegisterInfo;
class MCSubtargetInfo; class MCSubtargetInfo;
class FeatureBitset;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Machine Operand Flags and Description // Machine Operand Flags and Description
@ -145,8 +146,11 @@ public:
const uint16_t *ImplicitUses; // Registers implicitly read by this instr const uint16_t *ImplicitUses; // Registers implicitly read by this instr
const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr
const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands
uint64_t // Subtarget feature that this is deprecated on, if any
DeprecatedFeatureMask; // Feature bits that this is deprecated on, if any // -1 implies this is not deprecated by any single feature. It may still be
// deprecated due to a "complex" reason, below.
int64_t DeprecatedFeature;
// A complex method to determine is a certain is deprecated or not, and return // A complex method to determine is a certain is deprecated or not, and return
// the reason for deprecation. // the reason for deprecation.
bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &);

View File

@ -42,7 +42,7 @@ class MCSubtargetInfo {
const InstrStage *Stages; // Instruction itinerary stages const InstrStage *Stages; // Instruction itinerary stages
const unsigned *OperandCycles; // Itinerary operand cycles const unsigned *OperandCycles; // Itinerary operand cycles
const unsigned *ForwardingPaths; // Forwarding paths const unsigned *ForwardingPaths; // Forwarding paths
uint64_t FeatureBits; // Feature bits for current CPU + FS FeatureBitset FeatureBits; // Feature bits for current CPU + FS
public: public:
void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS,
@ -67,13 +67,13 @@ public:
/// getFeatureBits - Return the feature bits. /// getFeatureBits - Return the feature bits.
/// ///
uint64_t getFeatureBits() const { const FeatureBitset& getFeatureBits() const {
return FeatureBits; return FeatureBits;
} }
/// setFeatureBits - Set the feature bits. /// setFeatureBits - Set the feature bits.
/// ///
void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; } void setFeatureBits(FeatureBitset& FeatureBits_) { FeatureBits = FeatureBits_; }
/// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with
/// feature string). Recompute feature bits and scheduling model. /// feature string). Recompute feature bits and scheduling model.
@ -84,11 +84,15 @@ public:
/// ToggleFeature - Toggle a feature and returns the re-computed feature /// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version does not change the implied bits. /// bits. This version does not change the implied bits.
uint64_t ToggleFeature(uint64_t FB); FeatureBitset ToggleFeature(uint64_t FB);
/// ToggleFeature - Toggle a feature and returns the re-computed feature /// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version will also change all implied bits. /// bits. This version does not change the implied bits.
uint64_t ToggleFeature(StringRef FS); FeatureBitset ToggleFeature(const FeatureBitset& FB);
/// ToggleFeature - Toggle a set of features and returns the re-computed
/// feature bits. This version will also change all implied bits.
FeatureBitset ToggleFeature(StringRef FS);
/// getSchedModelForCPU - Get the machine model of a CPU. /// getSchedModelForCPU - Get the machine model of a CPU.
/// ///

View File

@ -21,11 +21,29 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include <bitset>
namespace llvm { namespace llvm {
class raw_ostream; class raw_ostream;
class StringRef; class StringRef;
// A container class for subtarget features.
// This is convenient because std::bitset does not have a constructor
// with an initializer list of set bits.
const unsigned MAX_SUBTARGET_FEATURES = 64;
class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> {
public:
// Cannot inherit constructors because it's not supported by VC++..
FeatureBitset() : bitset() {}
FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}
FeatureBitset(std::initializer_list<unsigned> Init) : bitset() {
for (auto I = Init.begin() , E = Init.end(); I != E; ++I)
set(*I);
}
};
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// ///
/// SubtargetFeatureKV - Used to provide key value pairs for feature and /// SubtargetFeatureKV - Used to provide key value pairs for feature and
@ -34,8 +52,8 @@ namespace llvm {
struct SubtargetFeatureKV { struct SubtargetFeatureKV {
const char *Key; // K-V key string const char *Key; // K-V key string
const char *Desc; // Help descriptor const char *Desc; // Help descriptor
uint64_t Value; // K-V integer value FeatureBitset Value; // K-V integer value
uint64_t Implies; // K-V bit mask FeatureBitset Implies; // K-V bit mask
// Compare routine for std::lower_bound // Compare routine for std::lower_bound
bool operator<(StringRef S) const { bool operator<(StringRef S) const {
@ -82,11 +100,11 @@ public:
/// ToggleFeature - Toggle a feature and returns the newly updated feature /// ToggleFeature - Toggle a feature and returns the newly updated feature
/// bits. /// bits.
uint64_t ToggleFeature(uint64_t Bits, StringRef String, FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String,
ArrayRef<SubtargetFeatureKV> FeatureTable); ArrayRef<SubtargetFeatureKV> FeatureTable);
/// Get feature bits of a CPU. /// Get feature bits of a CPU.
uint64_t getFeatureBits(StringRef CPU, FeatureBitset getFeatureBits(StringRef CPU,
ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> CPUTable,
ArrayRef<SubtargetFeatureKV> FeatureTable); ArrayRef<SubtargetFeatureKV> FeatureTable);

View File

@ -23,7 +23,7 @@ bool MCInstrDesc::getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) const { std::string &Info) const {
if (ComplexDeprecationInfo) if (ComplexDeprecationInfo)
return ComplexDeprecationInfo(MI, STI, Info); return ComplexDeprecationInfo(MI, STI, Info);
if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) { if (DeprecatedFeature != -1 && STI.getFeatureBits()[DeprecatedFeature]) {
// FIXME: it would be nice to include the subtarget feature here. // FIXME: it would be nice to include the subtarget feature here.
Info = "deprecated"; Info = "deprecated";
return true; return true;

View File

@ -63,14 +63,19 @@ MCSubtargetInfo::InitMCSubtargetInfo(StringRef TT, StringRef C, StringRef FS,
/// ToggleFeature - Toggle a feature and returns the re-computed feature /// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version does not change the implied bits. /// bits. This version does not change the implied bits.
uint64_t MCSubtargetInfo::ToggleFeature(uint64_t FB) { FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
FeatureBits.flip(FB);
return FeatureBits;
}
FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
FeatureBits ^= FB; FeatureBits ^= FB;
return FeatureBits; return FeatureBits;
} }
/// ToggleFeature - Toggle a feature and returns the re-computed feature /// ToggleFeature - Toggle a feature and returns the re-computed feature
/// bits. This version will also change all implied bits. /// bits. This version will also change all implied bits.
uint64_t MCSubtargetInfo::ToggleFeature(StringRef FS) { FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef FS) {
SubtargetFeatures Features; SubtargetFeatures Features;
FeatureBits = Features.ToggleFeature(FeatureBits, FS, ProcFeatures); FeatureBits = Features.ToggleFeature(FeatureBits, FS, ProcFeatures);
return FeatureBits; return FeatureBits;

View File

@ -151,12 +151,12 @@ std::string SubtargetFeatures::getString() const {
/// feature, set it. /// feature, set it.
/// ///
static static
void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV *FeatureEntry,
ArrayRef<SubtargetFeatureKV> FeatureTable) { ArrayRef<SubtargetFeatureKV> FeatureTable) {
for (auto &FE : FeatureTable) { for (auto &FE : FeatureTable) {
if (FeatureEntry->Value == FE.Value) continue; if (FeatureEntry->Value == FE.Value) continue;
if (FeatureEntry->Implies & FE.Value) { if ((FeatureEntry->Implies & FE.Value).any()) {
Bits |= FE.Value; Bits |= FE.Value;
SetImpliedBits(Bits, &FE, FeatureTable); SetImpliedBits(Bits, &FE, FeatureTable);
} }
@ -167,12 +167,13 @@ void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
/// feature, clear it. /// feature, clear it.
/// ///
static static
void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, void ClearImpliedBits(FeatureBitset &Bits,
const SubtargetFeatureKV *FeatureEntry,
ArrayRef<SubtargetFeatureKV> FeatureTable) { ArrayRef<SubtargetFeatureKV> FeatureTable) {
for (auto &FE : FeatureTable) { for (auto &FE : FeatureTable) {
if (FeatureEntry->Value == FE.Value) continue; if (FeatureEntry->Value == FE.Value) continue;
if (FE.Implies & FeatureEntry->Value) { if ((FE.Implies & FeatureEntry->Value).any()) {
Bits &= ~FE.Value; Bits &= ~FE.Value;
ClearImpliedBits(Bits, &FE, FeatureTable); ClearImpliedBits(Bits, &FE, FeatureTable);
} }
@ -181,8 +182,8 @@ void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
/// ToggleFeature - Toggle a feature and returns the newly updated feature /// ToggleFeature - Toggle a feature and returns the newly updated feature
/// bits. /// bits.
uint64_t FeatureBitset
SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature, SubtargetFeatures::ToggleFeature(FeatureBitset Bits, StringRef Feature,
ArrayRef<SubtargetFeatureKV> FeatureTable) { ArrayRef<SubtargetFeatureKV> FeatureTable) {
// Find feature in table. // Find feature in table.
@ -192,7 +193,6 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature,
if (FeatureEntry) { if (FeatureEntry) {
if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) { if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
Bits &= ~FeatureEntry->Value; Bits &= ~FeatureEntry->Value;
// For each feature that implies this, clear it. // For each feature that implies this, clear it.
ClearImpliedBits(Bits, FeatureEntry, FeatureTable); ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
} else { } else {
@ -213,13 +213,13 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature,
/// getFeatureBits - Get feature bits a CPU. /// getFeatureBits - Get feature bits a CPU.
/// ///
uint64_t FeatureBitset
SubtargetFeatures::getFeatureBits(StringRef CPU, SubtargetFeatures::getFeatureBits(StringRef CPU,
ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> CPUTable,
ArrayRef<SubtargetFeatureKV> FeatureTable) { ArrayRef<SubtargetFeatureKV> FeatureTable) {
if (CPUTable.empty() || FeatureTable.empty()) if (CPUTable.empty() || FeatureTable.empty())
return 0; return FeatureBitset();
#ifndef NDEBUG #ifndef NDEBUG
for (size_t i = 1, e = CPUTable.size(); i != e; ++i) { for (size_t i = 1, e = CPUTable.size(); i != e; ++i) {
@ -231,7 +231,8 @@ SubtargetFeatures::getFeatureBits(StringRef CPU,
"CPU features table is not sorted"); "CPU features table is not sorted");
} }
#endif #endif
uint64_t Bits = 0; // Resulting bits // Resulting bits
FeatureBitset Bits;
// Check if help is needed // Check if help is needed
if (CPU == "help") if (CPU == "help")
@ -248,7 +249,7 @@ SubtargetFeatures::getFeatureBits(StringRef CPU,
// Set the feature implied by this CPU feature, if any. // Set the feature implied by this CPU feature, if any.
for (auto &FE : FeatureTable) { for (auto &FE : FeatureTable) {
if (CPUEntry->Value & FE.Value) if ((CPUEntry->Value & FE.Value).any())
SetImpliedBits(Bits, &FE, FeatureTable); SetImpliedBits(Bits, &FE, FeatureTable);
} }
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,7 @@
#include "MCTargetDesc/AArch64MCTargetDesc.h" // For AArch64::X0 and friends. #include "MCTargetDesc/AArch64MCTargetDesc.h" // For AArch64::X0 and friends.
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
namespace llvm { namespace llvm {
@ -280,16 +281,22 @@ struct AArch64NamedImmMapper {
struct Mapping { struct Mapping {
const char *Name; const char *Name;
uint32_t Value; uint32_t Value;
uint64_t FeatureBitSet; // Set of features this mapping is available for // Set of features this mapping is available for
// Zero value of FeatureBitSet means the mapping is always available // Zero value of FeatureBitSet means the mapping is always available
FeatureBitset FeatureBitSet;
bool isNameEqual(std::string Other, uint64_t FeatureBits=~0ULL) const { bool isNameEqual(std::string Other,
if (FeatureBitSet && !(FeatureBitSet & FeatureBits)) const FeatureBitset& FeatureBits) const {
if (FeatureBitSet.any() &&
(FeatureBitSet & FeatureBits).none())
return false; return false;
return Name == Other; return Name == Other;
} }
bool isValueEqual(uint32_t Other, uint64_t FeatureBits=~0ULL) const {
if (FeatureBitSet && !(FeatureBitSet & FeatureBits)) bool isValueEqual(uint32_t Other,
const FeatureBitset& FeatureBits) const {
if (FeatureBitSet.any() &&
(FeatureBitSet & FeatureBits).none())
return false; return false;
return Value == Other; return Value == Other;
} }
@ -300,9 +307,11 @@ struct AArch64NamedImmMapper {
: Mappings(&Mappings[0]), NumMappings(N), TooBigImm(TooBigImm) {} : Mappings(&Mappings[0]), NumMappings(N), TooBigImm(TooBigImm) {}
// Maps value to string, depending on availability for FeatureBits given // Maps value to string, depending on availability for FeatureBits given
StringRef toString(uint32_t Value, uint64_t FeatureBits, bool &Valid) const; StringRef toString(uint32_t Value, const FeatureBitset& FeatureBits,
bool &Valid) const;
// Maps string to value, depending on availability for FeatureBits given // Maps string to value, depending on availability for FeatureBits given
uint32_t fromString(StringRef Name, uint64_t FeatureBits, bool &Valid) const; uint32_t fromString(StringRef Name, const FeatureBitset& FeatureBits,
bool &Valid) const;
/// Many of the instructions allow an alternative assembly form consisting of /// Many of the instructions allow an alternative assembly form consisting of
/// a simple immediate. Currently the only valid forms are ranges [0, N) where /// a simple immediate. Currently the only valid forms are ranges [0, N) where
@ -1195,8 +1204,9 @@ namespace AArch64SysReg {
size_t NumInstMappings; size_t NumInstMappings;
SysRegMapper() { } SysRegMapper() { }
uint32_t fromString(StringRef Name, uint64_t FeatureBits, bool &Valid) const; uint32_t fromString(StringRef Name, const FeatureBitset& FeatureBits,
std::string toString(uint32_t Bits, uint64_t FeatureBits) const; bool &Valid) const;
std::string toString(uint32_t Bits, const FeatureBitset& FeatureBits) const;
}; };
struct MSRMapper : SysRegMapper { struct MSRMapper : SysRegMapper {

View File

@ -415,7 +415,7 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
} }
static bool isThumb(const MCSubtargetInfo& STI) { static bool isThumb(const MCSubtargetInfo& STI) {
return (STI.getFeatureBits() & ARM::ModeThumb) != 0; return STI.getFeatureBits()[ARM::ModeThumb];
} }
void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,

View File

@ -4538,7 +4538,7 @@ breakPartialRegDependency(MachineBasicBlock::iterator MI,
} }
bool ARMBaseInstrInfo::hasNOP() const { bool ARMBaseInstrInfo::hasNOP() const {
return (Subtarget.getFeatureBits() & ARM::HasV6KOps) != 0; return Subtarget.getFeatureBits()[ARM::HasV6KOps];
} }
bool ARMBaseInstrInfo::isSwiftFastImmShift(const MachineInstr *MI) const { bool ARMBaseInstrInfo::isSwiftFastImmShift(const MachineInstr *MI) const {

View File

@ -265,8 +265,8 @@ void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
} }
// NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
uint64_t Bits = getFeatureBits(); const FeatureBitset &Bits = getFeatureBits();
if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters
(Options.UnsafeFPMath || isTargetDarwin())) (Options.UnsafeFPMath || isTargetDarwin()))
UseNEONForSinglePrecisionFP = true; UseNEONForSinglePrecisionFP = true;
} }

View File

@ -243,40 +243,40 @@ class ARMAsmParser : public MCTargetAsmParser {
bool isThumb() const { bool isThumb() const {
// FIXME: Can tablegen auto-generate this? // FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & ARM::ModeThumb) != 0; return STI.getFeatureBits()[ARM::ModeThumb];
} }
bool isThumbOne() const { bool isThumbOne() const {
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0; return isThumb() && !STI.getFeatureBits()[ARM::FeatureThumb2];
} }
bool isThumbTwo() const { bool isThumbTwo() const {
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2); return isThumb() && STI.getFeatureBits()[ARM::FeatureThumb2];
} }
bool hasThumb() const { bool hasThumb() const {
return STI.getFeatureBits() & ARM::HasV4TOps; return STI.getFeatureBits()[ARM::HasV4TOps];
} }
bool hasV6Ops() const { bool hasV6Ops() const {
return STI.getFeatureBits() & ARM::HasV6Ops; return STI.getFeatureBits()[ARM::HasV6Ops];
} }
bool hasV6MOps() const { bool hasV6MOps() const {
return STI.getFeatureBits() & ARM::HasV6MOps; return STI.getFeatureBits()[ARM::HasV6MOps];
} }
bool hasV7Ops() const { bool hasV7Ops() const {
return STI.getFeatureBits() & ARM::HasV7Ops; return STI.getFeatureBits()[ARM::HasV7Ops];
} }
bool hasV8Ops() const { bool hasV8Ops() const {
return STI.getFeatureBits() & ARM::HasV8Ops; return STI.getFeatureBits()[ARM::HasV8Ops];
} }
bool hasARM() const { bool hasARM() const {
return !(STI.getFeatureBits() & ARM::FeatureNoARM); return !STI.getFeatureBits()[ARM::FeatureNoARM];
} }
bool hasThumb2DSP() const { bool hasThumb2DSP() const {
return STI.getFeatureBits() & ARM::FeatureDSPThumb2; return STI.getFeatureBits()[ARM::FeatureDSPThumb2];
} }
bool hasD16() const { bool hasD16() const {
return STI.getFeatureBits() & ARM::FeatureD16; return STI.getFeatureBits()[ARM::FeatureD16];
} }
bool hasV8_1aOps() const { bool hasV8_1aOps() const {
return STI.getFeatureBits() & ARM::HasV8_1aOps; return STI.getFeatureBits()[ARM::HasV8_1aOps];
} }
void SwitchMode() { void SwitchMode() {
@ -284,7 +284,7 @@ class ARMAsmParser : public MCTargetAsmParser {
setAvailableFeatures(FB); setAvailableFeatures(FB);
} }
bool isMClass() const { bool isMClass() const {
return STI.getFeatureBits() & ARM::FeatureMClass; return STI.getFeatureBits()[ARM::FeatureMClass];
} }
/// @name Auto-generated Match Functions /// @name Auto-generated Match Functions
@ -9187,52 +9187,53 @@ bool ARMAsmParser::parseDirectiveCPU(SMLoc L) {
// tools/clang/lib/Driver/Tools.cpp // tools/clang/lib/Driver/Tools.cpp
static const struct { static const struct {
const unsigned ID; const unsigned ID;
const uint64_t Enabled; const FeatureBitset Enabled;
const uint64_t Disabled; const FeatureBitset Disabled;
} FPUs[] = { } FPUs[] = {
{/* ID */ ARM::FK_VFP, {/* ID */ ARM::FK_VFP,
/* Enabled */ ARM::FeatureVFP2, /* Enabled */ {ARM::FeatureVFP2},
/* Disabled */ ARM::FeatureNEON}, /* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_VFPV2, {/* ID */ ARM::FK_VFPV2,
/* Enabled */ ARM::FeatureVFP2, /* Enabled */ {ARM::FeatureVFP2},
/* Disabled */ ARM::FeatureNEON}, /* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_VFPV3, {/* ID */ ARM::FK_VFPV3,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3, /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3},
/* Disabled */ ARM::FeatureNEON | ARM::FeatureD16}, /* Disabled */ {ARM::FeatureNEON, ARM::FeatureD16}},
{/* ID */ ARM::FK_VFPV3_D16, {/* ID */ ARM::FK_VFPV3_D16,
/* Enable */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureD16, /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureD16},
/* Disabled */ ARM::FeatureNEON}, /* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_VFPV4, {/* ID */ ARM::FK_VFPV4,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4, /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4},
/* Disabled */ ARM::FeatureNEON | ARM::FeatureD16}, /* Disabled */ {ARM::FeatureNEON, ARM::FeatureD16}},
{/* ID */ ARM::FK_VFPV4_D16, {/* ID */ ARM::FK_VFPV4_D16,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureD16, ARM::FeatureD16},
/* Disabled */ ARM::FeatureNEON}, /* Disabled */ {ARM::FeatureNEON}},
{/* ID */ ARM::FK_FPV5_D16, {/* ID */ ARM::FK_FPV5_D16,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8 | ARM::FeatureD16, ARM::FeatureFPARMv8, ARM::FeatureD16},
/* Disabled */ ARM::FeatureNEON | ARM::FeatureCrypto}, /* Disabled */ {ARM::FeatureNEON, ARM::FeatureCrypto}},
{/* ID */ ARM::FK_FP_ARMV8, {/* ID */ ARM::FK_FP_ARMV8,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8, ARM::FeatureFPARMv8},
/* Disabled */ ARM::FeatureNEON | ARM::FeatureCrypto | ARM::FeatureD16}, /* Disabled */ {ARM::FeatureNEON, ARM::FeatureCrypto, ARM::FeatureD16}},
{/* ID */ ARM::FK_NEON, {/* ID */ ARM::FK_NEON,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureNEON, /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureNEON},
/* Disabled */ ARM::FeatureD16}, /* Disabled */ {ARM::FeatureD16}},
{/* ID */ ARM::FK_NEON_VFPV4, {/* ID */ ARM::FK_NEON_VFPV4,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureNEON, ARM::FeatureNEON},
/* Disabled */ ARM::FeatureD16}, /* Disabled */ {ARM::FeatureD16}},
{/* ID */ ARM::FK_NEON_FP_ARMV8, {/* ID */ ARM::FK_NEON_FP_ARMV8,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8 | ARM::FeatureNEON, ARM::FeatureFPARMv8, ARM::FeatureNEON},
/* Disabled */ ARM::FeatureCrypto | ARM::FeatureD16}, /* Disabled */ {ARM::FeatureCrypto, ARM::FeatureD16}},
{/* ID */ ARM::FK_CRYPTO_NEON_FP_ARMV8, {/* ID */ ARM::FK_CRYPTO_NEON_FP_ARMV8,
/* Enabled */ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4,
ARM::FeatureFPARMv8 | ARM::FeatureNEON | ARM::FeatureCrypto, ARM::FeatureFPARMv8, ARM::FeatureNEON,
/* Disabled */ ARM::FeatureD16}, ARM::FeatureCrypto},
{ARM::FK_SOFTVFP, 0, 0}, /* Disabled */ {ARM::FeatureD16}},
{ARM::FK_SOFTVFP, {}, {}},
}; };
/// parseDirectiveFPU /// parseDirectiveFPU
@ -9254,7 +9255,7 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {
// Need to toggle features that should be on but are off and that // Need to toggle features that should be on but are off and that
// should off but are on. // should off but are on.
uint64_t Toggle = (Entry.Enabled & ~STI.getFeatureBits()) | FeatureBitset Toggle = (Entry.Enabled & ~STI.getFeatureBits()) |
(Entry.Disabled & STI.getFeatureBits()); (Entry.Disabled & STI.getFeatureBits());
setAvailableFeatures(ComputeAvailableFeatures(STI.ToggleFeature(Toggle))); setAvailableFeatures(ComputeAvailableFeatures(STI.ToggleFeature(Toggle)));
break; break;
@ -9984,30 +9985,30 @@ extern "C" void LLVMInitializeARMAsmParser() {
static const struct { static const struct {
const char *Name; const char *Name;
const unsigned ArchCheck; const unsigned ArchCheck;
const uint64_t Features; const FeatureBitset Features;
} Extensions[] = { } Extensions[] = {
{ "crc", Feature_HasV8, ARM::FeatureCRC }, { "crc", Feature_HasV8, {ARM::FeatureCRC} },
{ "crypto", Feature_HasV8, { "crypto", Feature_HasV8,
ARM::FeatureCrypto | ARM::FeatureNEON | ARM::FeatureFPARMv8 }, {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} },
{ "fp", Feature_HasV8, ARM::FeatureFPARMv8 }, { "fp", Feature_HasV8, {ARM::FeatureFPARMv8} },
{ "idiv", Feature_HasV7 | Feature_IsNotMClass, { "idiv", Feature_HasV7 | Feature_IsNotMClass,
ARM::FeatureHWDiv | ARM::FeatureHWDivARM }, {ARM::FeatureHWDiv, ARM::FeatureHWDivARM} },
// FIXME: iWMMXT not supported // FIXME: iWMMXT not supported
{ "iwmmxt", Feature_None, 0 }, { "iwmmxt", Feature_None, {} },
// FIXME: iWMMXT2 not supported // FIXME: iWMMXT2 not supported
{ "iwmmxt2", Feature_None, 0 }, { "iwmmxt2", Feature_None, {} },
// FIXME: Maverick not supported // FIXME: Maverick not supported
{ "maverick", Feature_None, 0 }, { "maverick", Feature_None, {} },
{ "mp", Feature_HasV7 | Feature_IsNotMClass, ARM::FeatureMP }, { "mp", Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureMP} },
// FIXME: ARMv6-m OS Extensions feature not checked // FIXME: ARMv6-m OS Extensions feature not checked
{ "os", Feature_None, 0 }, { "os", Feature_None, {} },
// FIXME: Also available in ARMv6-K // FIXME: Also available in ARMv6-K
{ "sec", Feature_HasV7, ARM::FeatureTrustZone }, { "sec", Feature_HasV7, {ARM::FeatureTrustZone} },
{ "simd", Feature_HasV8, ARM::FeatureNEON | ARM::FeatureFPARMv8 }, { "simd", Feature_HasV8, {ARM::FeatureNEON, ARM::FeatureFPARMv8} },
// FIXME: Only available in A-class, isel not predicated // FIXME: Only available in A-class, isel not predicated
{ "virt", Feature_HasV7, ARM::FeatureVirtualization }, { "virt", Feature_HasV7, {ARM::FeatureVirtualization} },
// FIXME: xscale not supported // FIXME: xscale not supported
{ "xscale", Feature_None, 0 }, { "xscale", Feature_None, {} },
}; };
/// parseDirectiveArchExtension /// parseDirectiveArchExtension
@ -10035,7 +10036,7 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
if (Extension.Name != Name) if (Extension.Name != Name)
continue; continue;
if (!Extension.Features) if (Extension.Features.none())
report_fatal_error("unsupported architectural extension: " + Name); report_fatal_error("unsupported architectural extension: " + Name);
if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) { if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) {
@ -10044,9 +10045,10 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
return false; return false;
} }
uint64_t ToggleFeatures = EnableFeature FeatureBitset ToggleFeatures = EnableFeature
? (~STI.getFeatureBits() & Extension.Features) ? (~STI.getFeatureBits() & Extension.Features)
: ( STI.getFeatureBits() & Extension.Features); : ( STI.getFeatureBits() & Extension.Features);
uint64_t Features = uint64_t Features =
ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures)); ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
setAvailableFeatures(Features); setAvailableFeatures(Features);

View File

@ -435,7 +435,7 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
raw_ostream &CS) const { raw_ostream &CS) const {
CommentStream = &CS; CommentStream = &CS;
assert(!(STI.getFeatureBits() & ARM::ModeThumb) && assert(!STI.getFeatureBits()[ARM::ModeThumb] &&
"Asked to disassemble an ARM instruction but Subtarget is in Thumb " "Asked to disassemble an ARM instruction but Subtarget is in Thumb "
"mode!"); "mode!");
@ -700,7 +700,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
raw_ostream &CS) const { raw_ostream &CS) const {
CommentStream = &CS; CommentStream = &CS;
assert((STI.getFeatureBits() & ARM::ModeThumb) && assert(STI.getFeatureBits()[ARM::ModeThumb] &&
"Asked to disassemble in Thumb mode but Subtarget is in ARM mode!"); "Asked to disassemble in Thumb mode but Subtarget is in ARM mode!");
// We want to read exactly 2 bytes of data. // We want to read exactly 2 bytes of data.
@ -1026,9 +1026,10 @@ static const uint16_t DPRDecoderTable[] = {
static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo, static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) { uint64_t Address, const void *Decoder) {
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &featureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
bool hasD16 = featureBits & ARM::FeatureD16;
bool hasD16 = featureBits[ARM::FeatureD16];
if (RegNo > 31 || (hasD16 && RegNo > 15)) if (RegNo > 31 || (hasD16 && RegNo > 15))
return MCDisassembler::Fail; return MCDisassembler::Fail;
@ -1373,9 +1374,9 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
break; break;
} }
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &featureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
if ((featureBits & ARM::HasV8Ops) && (coproc != 14)) if (featureBits[ARM::HasV8Ops] && (coproc != 14))
return MCDisassembler::Fail; return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(coproc)); Inst.addOperand(MCOperand::createImm(coproc));
@ -2151,9 +2152,10 @@ static DecodeStatus DecodeSETPANInstruction(MCInst &Inst, unsigned Insn,
unsigned Imm = fieldFromInstruction(Insn, 9, 1); unsigned Imm = fieldFromInstruction(Insn, 9, 1);
const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder); const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
uint64_t FeatureBits = Dis->getSubtargetInfo().getFeatureBits(); const FeatureBitset &FeatureBits = Dis->getSubtargetInfo().getFeatureBits();
if ((FeatureBits & ARM::HasV8_1aOps) == 0 ||
(FeatureBits & ARM::HasV8Ops) == 0 ) if (!FeatureBits[ARM::HasV8_1aOps] ||
!FeatureBits[ARM::HasV8Ops])
return MCDisassembler::Fail; return MCDisassembler::Fail;
// Decoder can be called from DecodeTST, which does not check the full // Decoder can be called from DecodeTST, which does not check the full
@ -3319,10 +3321,11 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
unsigned Rt = fieldFromInstruction(Insn, 12, 4); unsigned Rt = fieldFromInstruction(Insn, 12, 4);
unsigned Rn = fieldFromInstruction(Insn, 16, 4); unsigned Rn = fieldFromInstruction(Insn, 16, 4);
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &featureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
bool hasMP = featureBits & ARM::FeatureMP;
bool hasV7Ops = featureBits & ARM::HasV7Ops; bool hasMP = featureBits[ARM::FeatureMP];
bool hasV7Ops = featureBits[ARM::HasV7Ops];
if (Rn == 15) { if (Rn == 15) {
switch (Inst.getOpcode()) { switch (Inst.getOpcode()) {
@ -3405,10 +3408,11 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
imm |= (Rn << 9); imm |= (Rn << 9);
unsigned add = fieldFromInstruction(Insn, 9, 1); unsigned add = fieldFromInstruction(Insn, 9, 1);
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &featureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
bool hasMP = featureBits & ARM::FeatureMP;
bool hasV7Ops = featureBits & ARM::HasV7Ops; bool hasMP = featureBits[ARM::FeatureMP];
bool hasV7Ops = featureBits[ARM::HasV7Ops];
if (Rn == 15) { if (Rn == 15) {
switch (Inst.getOpcode()) { switch (Inst.getOpcode()) {
@ -3485,10 +3489,11 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
unsigned imm = fieldFromInstruction(Insn, 0, 12); unsigned imm = fieldFromInstruction(Insn, 0, 12);
imm |= (Rn << 13); imm |= (Rn << 13);
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &featureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
bool hasMP = (featureBits & ARM::FeatureMP);
bool hasV7Ops = (featureBits & ARM::HasV7Ops); bool hasMP = featureBits[ARM::FeatureMP];
bool hasV7Ops = featureBits[ARM::HasV7Ops];
if (Rn == 15) { if (Rn == 15) {
switch (Inst.getOpcode()) { switch (Inst.getOpcode()) {
@ -3602,9 +3607,10 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
unsigned U = fieldFromInstruction(Insn, 23, 1); unsigned U = fieldFromInstruction(Insn, 23, 1);
int imm = fieldFromInstruction(Insn, 0, 12); int imm = fieldFromInstruction(Insn, 0, 12);
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &featureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
bool hasV7Ops = (featureBits & ARM::HasV7Ops);
bool hasV7Ops = featureBits[ARM::HasV7Ops];
if (Rt == 15) { if (Rt == 15) {
switch (Inst.getOpcode()) { switch (Inst.getOpcode()) {
@ -3925,9 +3931,10 @@ static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Val,
if (Val == 0xA || Val == 0xB) if (Val == 0xA || Val == 0xB)
return MCDisassembler::Fail; return MCDisassembler::Fail;
uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &featureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
if ((featureBits & ARM::HasV8Ops) && !(Val == 14 || Val == 15))
if (featureBits[ARM::HasV8Ops] && !(Val == 14 || Val == 15))
return MCDisassembler::Fail; return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(Val)); Inst.addOperand(MCOperand::createImm(Val));
@ -4077,9 +4084,10 @@ static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Val,
static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val, static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) { uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success; DecodeStatus S = MCDisassembler::Success;
uint64_t FeatureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() const FeatureBitset &FeatureBits =
.getFeatureBits(); ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
if (FeatureBits & ARM::FeatureMClass) {
if (FeatureBits[ARM::FeatureMClass]) {
unsigned ValLow = Val & 0xff; unsigned ValLow = Val & 0xff;
// Validate the SYSm value first. // Validate the SYSm value first.
@ -4099,7 +4107,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
case 17: // basepri case 17: // basepri
case 18: // basepri_max case 18: // basepri_max
case 19: // faultmask case 19: // faultmask
if (!(FeatureBits & ARM::HasV7Ops)) if (!(FeatureBits[ARM::HasV7Ops]))
// Values basepri, basepri_max and faultmask are only valid for v7m. // Values basepri, basepri_max and faultmask are only valid for v7m.
return MCDisassembler::Fail; return MCDisassembler::Fail;
break; break;
@ -4109,7 +4117,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
if (Inst.getOpcode() == ARM::t2MSR_M) { if (Inst.getOpcode() == ARM::t2MSR_M) {
unsigned Mask = fieldFromInstruction(Val, 10, 2); unsigned Mask = fieldFromInstruction(Val, 10, 2);
if (!(FeatureBits & ARM::HasV7Ops)) { if (!(FeatureBits[ARM::HasV7Ops])) {
// The ARMv6-M MSR bits {11-10} can be only 0b10, other values are // The ARMv6-M MSR bits {11-10} can be only 0b10, other values are
// unpredictable. // unpredictable.
if (Mask != 2) if (Mask != 2)
@ -4123,7 +4131,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
// indicates the move for the GE{3:0} bits, the mask{0} bit can be set // indicates the move for the GE{3:0} bits, the mask{0} bit can be set
// only if the processor includes the DSP extension. // only if the processor includes the DSP extension.
if (Mask == 0 || (Mask != 2 && ValLow > 3) || if (Mask == 0 || (Mask != 2 && ValLow > 3) ||
(!(FeatureBits & ARM::FeatureDSPThumb2) && (Mask & 1))) (!(FeatureBits[ARM::FeatureDSPThumb2]) && (Mask & 1)))
S = MCDisassembler::SoftFail; S = MCDisassembler::SoftFail;
} }
} }

View File

@ -93,7 +93,7 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
O << "\tsev"; O << "\tsev";
break; break;
case 5: case 5:
if ((STI.getFeatureBits() & ARM::HasV8Ops)) { if (STI.getFeatureBits()[ARM::HasV8Ops]) {
O << "\tsevl"; O << "\tsevl";
break; break;
} // Fallthrough for non-v8 } // Fallthrough for non-v8
@ -302,7 +302,7 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
case ARM::t2SUBS_PC_LR: { case ARM::t2SUBS_PC_LR: {
if (MI->getNumOperands() == 3 && MI->getOperand(0).isImm() && if (MI->getNumOperands() == 3 && MI->getOperand(0).isImm() &&
MI->getOperand(0).getImm() == 0 && MI->getOperand(0).getImm() == 0 &&
(STI.getFeatureBits() & ARM::FeatureVirtualization)) { STI.getFeatureBits()[ARM::FeatureVirtualization]) {
O << "\teret"; O << "\teret";
printPredicateOperand(MI, 1, STI, O); printPredicateOperand(MI, 1, STI, O);
printAnnotation(O, Annot); printAnnotation(O, Annot);
@ -695,7 +695,7 @@ void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, const MCSubtargetInfo &STI,
raw_ostream &O) { raw_ostream &O) {
unsigned val = MI->getOperand(OpNum).getImm(); unsigned val = MI->getOperand(OpNum).getImm();
O << ARM_MB::MemBOptToString(val, (STI.getFeatureBits() & ARM::HasV8Ops)); O << ARM_MB::MemBOptToString(val, STI.getFeatureBits()[ARM::HasV8Ops]);
} }
void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum, void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
@ -795,14 +795,14 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
const MCOperand &Op = MI->getOperand(OpNum); const MCOperand &Op = MI->getOperand(OpNum);
unsigned SpecRegRBit = Op.getImm() >> 4; unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf; unsigned Mask = Op.getImm() & 0xf;
uint64_t FeatureBits = STI.getFeatureBits(); const FeatureBitset &FeatureBits = STI.getFeatureBits();
if (FeatureBits & ARM::FeatureMClass) { if (FeatureBits[ARM::FeatureMClass]) {
unsigned SYSm = Op.getImm(); unsigned SYSm = Op.getImm();
unsigned Opcode = MI->getOpcode(); unsigned Opcode = MI->getOpcode();
// For writes, handle extended mask bits if the DSP extension is present. // For writes, handle extended mask bits if the DSP extension is present.
if (Opcode == ARM::t2MSR_M && (FeatureBits & ARM::FeatureDSPThumb2)) { if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSPThumb2]) {
switch (SYSm) { switch (SYSm) {
case 0x400: case 0x400:
O << "apsr_g"; O << "apsr_g";
@ -834,7 +834,7 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
// Handle the basic 8-bit mask. // Handle the basic 8-bit mask.
SYSm &= 0xff; SYSm &= 0xff;
if (Opcode == ARM::t2MSR_M && (FeatureBits & ARM::HasV7Ops)) { if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
// ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
// alias for MSR APSR_nzcvq. // alias for MSR APSR_nzcvq.
switch (SYSm) { switch (SYSm) {

View File

@ -154,7 +154,7 @@ void ARMAsmBackend::handleAssemblerFlag(MCAssemblerFlag Flag) {
} // end anonymous namespace } // end anonymous namespace
unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op) const { unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op) const {
bool HasThumb2 = STI->getFeatureBits() & ARM::FeatureThumb2; bool HasThumb2 = STI->getFeatureBits()[ARM::FeatureThumb2];
switch (Op) { switch (Op) {
default: default:

View File

@ -33,7 +33,7 @@ public:
return ARM::NumTargetFixupKinds; return ARM::NumTargetFixupKinds;
} }
bool hasNOP() const { return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; } bool hasNOP() const { return STI->getFeatureBits()[ARM::HasV6T2Ops]; }
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;

View File

@ -51,10 +51,10 @@ public:
~ARMMCCodeEmitter() override {} ~ARMMCCodeEmitter() override {}
bool isThumb(const MCSubtargetInfo &STI) const { bool isThumb(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & ARM::ModeThumb) != 0; return STI.getFeatureBits()[ARM::ModeThumb];
} }
bool isThumb2(const MCSubtargetInfo &STI) const { bool isThumb2(const MCSubtargetInfo &STI) const {
return isThumb(STI) && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0; return isThumb(STI) && STI.getFeatureBits()[ARM::FeatureThumb2];
} }
bool isTargetMachO(const MCSubtargetInfo &STI) const { bool isTargetMachO(const MCSubtargetInfo &STI) const {
Triple TT(STI.getTargetTriple()); Triple TT(STI.getTargetTriple());

View File

@ -33,7 +33,7 @@ using namespace llvm;
static bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, static bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) { std::string &Info) {
if (STI.getFeatureBits() & llvm::ARM::HasV7Ops && if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
(MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) && (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
(MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) && (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
// Checks for the deprecated CP15ISB encoding: // Checks for the deprecated CP15ISB encoding:
@ -65,7 +65,7 @@ static bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) { std::string &Info) {
if (STI.getFeatureBits() & llvm::ARM::HasV8Ops && MI.getOperand(1).isImm() && if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() != 8) { MI.getOperand(1).getImm() != 8) {
Info = "applying IT instruction to more than one subsequent instruction is " Info = "applying IT instruction to more than one subsequent instruction is "
"deprecated"; "deprecated";
@ -77,7 +77,7 @@ static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
static bool getARMStoreDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, static bool getARMStoreDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) { std::string &Info) {
assert((~STI.getFeatureBits() & llvm::ARM::ModeThumb) && assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
"cannot predicate thumb instructions"); "cannot predicate thumb instructions");
assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments"); assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
@ -94,7 +94,7 @@ static bool getARMStoreDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
static bool getARMLoadDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI, static bool getARMLoadDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
std::string &Info) { std::string &Info) {
assert((~STI.getFeatureBits() & llvm::ARM::ModeThumb) && assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
"cannot predicate thumb instructions"); "cannot predicate thumb instructions");
assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments"); assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");

View File

@ -78,15 +78,7 @@ public:
// The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]). // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
// The reason we need this mask is explained in the selectArch function. // The reason we need this mask is explained in the selectArch function.
// FIXME: Ideally we would like TableGen to generate this information. // FIXME: Ideally we would like TableGen to generate this information.
static const uint64_t AllArchRelatedMask = static const FeatureBitset AllArchRelatedMask;
Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
private: private:
unsigned ATReg; unsigned ATReg;
@ -96,6 +88,17 @@ private:
}; };
} }
const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
};
namespace { namespace {
class MipsAsmParser : public MCTargetAsmParser { class MipsAsmParser : public MCTargetAsmParser {
MipsTargetStreamer &getTargetStreamer() { MipsTargetStreamer &getTargetStreamer() {
@ -317,7 +320,7 @@ class MipsAsmParser : public MCTargetAsmParser {
// FeatureMipsGP64 | FeatureMips1) // FeatureMipsGP64 | FeatureMips1)
// Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4). // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
void selectArch(StringRef ArchFeature) { void selectArch(StringRef ArchFeature) {
uint64_t FeatureBits = STI.getFeatureBits(); FeatureBitset FeatureBits = STI.getFeatureBits();
FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask; FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
STI.setFeatureBits(FeatureBits); STI.setFeatureBits(FeatureBits);
setAvailableFeatures( setAvailableFeatures(
@ -326,7 +329,7 @@ class MipsAsmParser : public MCTargetAsmParser {
} }
void setFeatureBits(uint64_t Feature, StringRef FeatureString) { void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
if (!(STI.getFeatureBits() & Feature)) { if (!(STI.getFeatureBits()[Feature])) {
setAvailableFeatures( setAvailableFeatures(
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
} }
@ -334,7 +337,7 @@ class MipsAsmParser : public MCTargetAsmParser {
} }
void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
if (STI.getFeatureBits() & Feature) { if (STI.getFeatureBits()[Feature]) {
setAvailableFeatures( setAvailableFeatures(
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
} }
@ -381,69 +384,70 @@ public:
/// True if all of $fcc0 - $fcc7 exist for the current ISA. /// True if all of $fcc0 - $fcc7 exist for the current ISA.
bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); } bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; } bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; } bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
const MipsABIInfo &getABI() const { return ABI; } const MipsABIInfo &getABI() const { return ABI; }
bool isABI_N32() const { return ABI.IsN32(); } bool isABI_N32() const { return ABI.IsN32(); }
bool isABI_N64() const { return ABI.IsN64(); } bool isABI_N64() const { return ABI.IsN64(); }
bool isABI_O32() const { return ABI.IsO32(); } bool isABI_O32() const { return ABI.IsO32(); }
bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; } bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
bool useOddSPReg() const { bool useOddSPReg() const {
return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg); return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
} }
bool inMicroMipsMode() const { bool inMicroMipsMode() const {
return STI.getFeatureBits() & Mips::FeatureMicroMips; return STI.getFeatureBits()[Mips::FeatureMicroMips];
} }
bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; } bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; } bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; } bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; } bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; } bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
bool hasMips32() const { bool hasMips32() const {
return (STI.getFeatureBits() & Mips::FeatureMips32); return STI.getFeatureBits()[Mips::FeatureMips32];
} }
bool hasMips64() const { bool hasMips64() const {
return (STI.getFeatureBits() & Mips::FeatureMips64); return STI.getFeatureBits()[Mips::FeatureMips64];
} }
bool hasMips32r2() const { bool hasMips32r2() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r2); return STI.getFeatureBits()[Mips::FeatureMips32r2];
} }
bool hasMips64r2() const { bool hasMips64r2() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r2); return STI.getFeatureBits()[Mips::FeatureMips64r2];
} }
bool hasMips32r3() const { bool hasMips32r3() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r3); return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
} }
bool hasMips64r3() const { bool hasMips64r3() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r3); return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
} }
bool hasMips32r5() const { bool hasMips32r5() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r5); return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
} }
bool hasMips64r5() const { bool hasMips64r5() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r5); return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
} }
bool hasMips32r6() const { bool hasMips32r6() const {
return (STI.getFeatureBits() & Mips::FeatureMips32r6); return STI.getFeatureBits()[Mips::FeatureMips32r6];
} }
bool hasMips64r6() const { bool hasMips64r6() const {
return (STI.getFeatureBits() & Mips::FeatureMips64r6); return STI.getFeatureBits()[Mips::FeatureMips64r6];
} }
bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
bool hasCnMips() const { bool hasCnMips() const {
return (STI.getFeatureBits() & Mips::FeatureCnMips); return (STI.getFeatureBits()[Mips::FeatureCnMips]);
} }
bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
bool inMips16Mode() const { bool inMips16Mode() const {
return STI.getFeatureBits() & Mips::FeatureMips16; return STI.getFeatureBits()[Mips::FeatureMips16];
} }
bool useSoftFloat() const { bool useSoftFloat() const {
return (STI.getFeatureBits() & Mips::FeatureSoftFloat); return STI.getFeatureBits()[Mips::FeatureSoftFloat];
} }
/// Warn if RegIndex is the same as the current AT. /// Warn if RegIndex is the same as the current AT.

View File

@ -36,16 +36,16 @@ class MipsDisassembler : public MCDisassembler {
public: public:
MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian) MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian)
: MCDisassembler(STI, Ctx), : MCDisassembler(STI, Ctx),
IsMicroMips(STI.getFeatureBits() & Mips::FeatureMicroMips), IsMicroMips(STI.getFeatureBits()[Mips::FeatureMicroMips]),
IsBigEndian(IsBigEndian) {} IsBigEndian(IsBigEndian) {}
bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; } bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; } bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; }
bool hasMips32r6() const { bool hasMips32r6() const {
return STI.getFeatureBits() & Mips::FeatureMips32r6; return STI.getFeatureBits()[Mips::FeatureMips32r6];
} }
bool isGP64() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; } bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
bool hasCOP3() const { bool hasCOP3() const {
// Only present in MIPS-I and MIPS-II // Only present in MIPS-I and MIPS-II

View File

@ -113,11 +113,11 @@ static void LowerDextDins(MCInst& InstIn) {
} }
bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
return STI.getFeatureBits() & Mips::FeatureMicroMips; return STI.getFeatureBits()[Mips::FeatureMicroMips];
} }
bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const { bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {
return STI.getFeatureBits() & Mips::FeatureMips32r6; return STI.getFeatureBits()[Mips::FeatureMips32r6];
} }
void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {

View File

@ -386,7 +386,7 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
MCAssembler &MCA = getStreamer().getAssembler(); MCAssembler &MCA = getStreamer().getAssembler();
Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;
uint64_t Features = STI.getFeatureBits(); const FeatureBitset &Features = STI.getFeatureBits();
// Set the header flags that we can in the constructor. // Set the header flags that we can in the constructor.
// FIXME: This is a fairly terrible hack. We set the rest // FIXME: This is a fairly terrible hack. We set the rest
@ -402,35 +402,35 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
unsigned EFlags = MCA.getELFHeaderEFlags(); unsigned EFlags = MCA.getELFHeaderEFlags();
// Architecture // Architecture
if (Features & Mips::FeatureMips64r6) if (Features[Mips::FeatureMips64r6])
EFlags |= ELF::EF_MIPS_ARCH_64R6; EFlags |= ELF::EF_MIPS_ARCH_64R6;
else if (Features & Mips::FeatureMips64r2 || else if (Features[Mips::FeatureMips64r2] ||
Features & Mips::FeatureMips64r3 || Features[Mips::FeatureMips64r3] ||
Features & Mips::FeatureMips64r5) Features[Mips::FeatureMips64r5])
EFlags |= ELF::EF_MIPS_ARCH_64R2; EFlags |= ELF::EF_MIPS_ARCH_64R2;
else if (Features & Mips::FeatureMips64) else if (Features[Mips::FeatureMips64])
EFlags |= ELF::EF_MIPS_ARCH_64; EFlags |= ELF::EF_MIPS_ARCH_64;
else if (Features & Mips::FeatureMips5) else if (Features[Mips::FeatureMips5])
EFlags |= ELF::EF_MIPS_ARCH_5; EFlags |= ELF::EF_MIPS_ARCH_5;
else if (Features & Mips::FeatureMips4) else if (Features[Mips::FeatureMips4])
EFlags |= ELF::EF_MIPS_ARCH_4; EFlags |= ELF::EF_MIPS_ARCH_4;
else if (Features & Mips::FeatureMips3) else if (Features[Mips::FeatureMips3])
EFlags |= ELF::EF_MIPS_ARCH_3; EFlags |= ELF::EF_MIPS_ARCH_3;
else if (Features & Mips::FeatureMips32r6) else if (Features[Mips::FeatureMips32r6])
EFlags |= ELF::EF_MIPS_ARCH_32R6; EFlags |= ELF::EF_MIPS_ARCH_32R6;
else if (Features & Mips::FeatureMips32r2 || else if (Features[Mips::FeatureMips32r2] ||
Features & Mips::FeatureMips32r3 || Features[Mips::FeatureMips32r3] ||
Features & Mips::FeatureMips32r5) Features[Mips::FeatureMips32r5])
EFlags |= ELF::EF_MIPS_ARCH_32R2; EFlags |= ELF::EF_MIPS_ARCH_32R2;
else if (Features & Mips::FeatureMips32) else if (Features[Mips::FeatureMips32])
EFlags |= ELF::EF_MIPS_ARCH_32; EFlags |= ELF::EF_MIPS_ARCH_32;
else if (Features & Mips::FeatureMips2) else if (Features[Mips::FeatureMips2])
EFlags |= ELF::EF_MIPS_ARCH_2; EFlags |= ELF::EF_MIPS_ARCH_2;
else else
EFlags |= ELF::EF_MIPS_ARCH_1; EFlags |= ELF::EF_MIPS_ARCH_1;
// Other options. // Other options.
if (Features & Mips::FeatureNaN2008) if (Features[Mips::FeatureNaN2008])
EFlags |= ELF::EF_MIPS_NAN2008; EFlags |= ELF::EF_MIPS_NAN2008;
// -mabicalls and -mplt are not implemented but we should act as if they were // -mabicalls and -mplt are not implemented but we should act as if they were
@ -470,7 +470,7 @@ void MipsTargetELFStreamer::finish() {
DataSection.setAlignment(std::max(16u, DataSection.getAlignment())); DataSection.setAlignment(std::max(16u, DataSection.getAlignment()));
BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment())); BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment()));
uint64_t Features = STI.getFeatureBits(); const FeatureBitset &Features = STI.getFeatureBits();
// Update e_header flags. See the FIXME and comment above in // Update e_header flags. See the FIXME and comment above in
// the constructor for a full rundown on this. // the constructor for a full rundown on this.
@ -483,10 +483,10 @@ void MipsTargetELFStreamer::finish() {
else if (getABI().IsN32()) else if (getABI().IsN32())
EFlags |= ELF::EF_MIPS_ABI2; EFlags |= ELF::EF_MIPS_ABI2;
if (Features & Mips::FeatureGP64Bit) { if (Features[Mips::FeatureGP64Bit]) {
if (getABI().IsO32()) if (getABI().IsO32())
EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */
} else if (Features & Mips::FeatureMips64r2 || Features & Mips::FeatureMips64) } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])
EFlags |= ELF::EF_MIPS_32BITMODE; EFlags |= ELF::EF_MIPS_32BITMODE;
// If we've set the cpic eflag and we're n64, go ahead and set the pic // If we've set the cpic eflag and we're n64, go ahead and set the pic

View File

@ -1682,7 +1682,7 @@ bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
// where th can be omitted when it is 0. dcbtst is the same. We take the // where th can be omitted when it is 0. dcbtst is the same. We take the
// server form to be the default, so swap the operands if we're parsing for // server form to be the default, so swap the operands if we're parsing for
// an embedded core (they'll be swapped again upon printing). // an embedded core (they'll be swapped again upon printing).
if ((STI.getFeatureBits() & PPC::FeatureBookE) != 0 && if (STI.getFeatureBits()[PPC::FeatureBookE] &&
Operands.size() == 4 && Operands.size() == 4 &&
(Name == "dcbt" || Name == "dcbtst")) { (Name == "dcbt" || Name == "dcbtst")) {
std::swap(Operands[1], Operands[3]); std::swap(Operands[1], Operands[3]);

View File

@ -387,7 +387,7 @@ DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
uint32_t Inst = uint32_t Inst =
(Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0); (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
if ((STI.getFeatureBits() & PPC::FeatureQPX) != 0) { if (STI.getFeatureBits()[PPC::FeatureQPX]) {
DecodeStatus result = DecodeStatus result =
decodeInstruction(DecoderTableQPX32, MI, Inst, Address, this, STI); decodeInstruction(DecoderTableQPX32, MI, Inst, Address, this, STI);
if (result != MCDisassembler::Fail) if (result != MCDisassembler::Fail)

View File

@ -121,7 +121,7 @@ void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
O << "t"; O << "t";
O << " "; O << " ";
bool IsBookE = (STI.getFeatureBits() & PPC::FeatureBookE) != 0; bool IsBookE = STI.getFeatureBits()[PPC::FeatureBookE];
if (IsBookE && TH != 0 && TH != 16) if (IsBookE && TH != 0 && TH != 16)
O << (unsigned int) TH << ", "; O << (unsigned int) TH << ", ";

View File

@ -321,7 +321,7 @@ public:
: MCTargetAsmParser(), STI(STI), MII(MII), Parser(_Parser), : MCTargetAsmParser(), STI(STI), MII(MII), Parser(_Parser),
ForcedEncodingSize(0){ ForcedEncodingSize(0){
if (!STI.getFeatureBits()) { if (STI.getFeatureBits().none()) {
// Set default features. // Set default features.
STI.ToggleFeature("SOUTHERN_ISLANDS"); STI.ToggleFeature("SOUTHERN_ISLANDS");
} }

View File

@ -99,7 +99,7 @@ void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
} else if (IS_VTX(Desc)) { } else if (IS_VTX(Desc)) {
uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI); uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
if (!(STI.getFeatureBits() & AMDGPU::FeatureCaymanISA)) { if (!(STI.getFeatureBits()[AMDGPU::FeatureCaymanISA])) {
InstWord2 |= 1 << 19; // Mega-Fetch bit InstWord2 |= 1 << 19; // Mega-Fetch bit
} }
@ -132,7 +132,7 @@ void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
Emit((uint32_t) 0, OS); Emit((uint32_t) 0, OS);
} else { } else {
uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI); uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
if ((STI.getFeatureBits() & AMDGPU::FeatureR600ALUInst) && if ((STI.getFeatureBits()[AMDGPU::FeatureR600ALUInst]) &&
((Desc.TSFlags & R600_InstFlag::OP1) || ((Desc.TSFlags & R600_InstFlag::OP1) ||
Desc.TSFlags & R600_InstFlag::OP2)) { Desc.TSFlags & R600_InstFlag::OP2)) {
uint64_t ISAOpCode = Inst & (0x3FFULL << 39); uint64_t ISAOpCode = Inst & (0x3FFULL << 39);

View File

@ -35,7 +35,7 @@ namespace Sparc {
#include "SparcGenAsmWriter.inc" #include "SparcGenAsmWriter.inc"
bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const { bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & Sparc::FeatureV9) != 0; return (STI.getFeatureBits()[Sparc::FeatureV9]) != 0;
} }
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const

View File

@ -261,13 +261,13 @@ protected:
MCContext &Ctx, int64_t *Residue); MCContext &Ctx, int64_t *Residue);
bool is64BitMode() const { bool is64BitMode() const {
return (STI.getFeatureBits() & X86::Mode64Bit) != 0; return STI.getFeatureBits()[X86::Mode64Bit];
} }
bool is32BitMode() const { bool is32BitMode() const {
return (STI.getFeatureBits() & X86::Mode32Bit) != 0; return STI.getFeatureBits()[X86::Mode32Bit];
} }
bool is16BitMode() const { bool is16BitMode() const {
return (STI.getFeatureBits() & X86::Mode16Bit) != 0; return STI.getFeatureBits()[X86::Mode16Bit];
} }
unsigned getPointerWidth() { unsigned getPointerWidth() {
@ -1072,9 +1072,9 @@ CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
const bool hasCompilerRTSupport = T.isOSLinux(); const bool hasCompilerRTSupport = T.isOSLinux();
if (ClAsanInstrumentAssembly && hasCompilerRTSupport && if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
MCOptions.SanitizeAddress) { MCOptions.SanitizeAddress) {
if ((STI.getFeatureBits() & X86::Mode32Bit) != 0) if (STI.getFeatureBits()[X86::Mode32Bit] != 0)
return new X86AddressSanitizer32(STI); return new X86AddressSanitizer32(STI);
if ((STI.getFeatureBits() & X86::Mode64Bit) != 0) if (STI.getFeatureBits()[X86::Mode64Bit] != 0)
return new X86AddressSanitizer64(STI); return new X86AddressSanitizer64(STI);
} }
return new X86AsmInstrumentation(STI); return new X86AsmInstrumentation(STI);

View File

@ -729,23 +729,24 @@ private:
bool is64BitMode() const { bool is64BitMode() const {
// FIXME: Can tablegen auto-generate this? // FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode64Bit) != 0; return STI.getFeatureBits()[X86::Mode64Bit];
} }
bool is32BitMode() const { bool is32BitMode() const {
// FIXME: Can tablegen auto-generate this? // FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode32Bit) != 0; return STI.getFeatureBits()[X86::Mode32Bit];
} }
bool is16BitMode() const { bool is16BitMode() const {
// FIXME: Can tablegen auto-generate this? // FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode16Bit) != 0; return STI.getFeatureBits()[X86::Mode16Bit];
} }
void SwitchMode(uint64_t mode) { void SwitchMode(unsigned mode) {
uint64_t oldMode = STI.getFeatureBits() & FeatureBitset AllModes({X86::Mode64Bit, X86::Mode32Bit, X86::Mode16Bit});
(X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit); FeatureBitset OldMode = STI.getFeatureBits() & AllModes;
unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(oldMode | mode)); unsigned FB = ComputeAvailableFeatures(
STI.ToggleFeature(OldMode.flip(mode)));
setAvailableFeatures(FB); setAvailableFeatures(FB);
assert(mode == (STI.getFeatureBits() &
(X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit))); assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes));
} }
unsigned getPointerWidth() { unsigned getPointerWidth() {
@ -1696,7 +1697,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
} }
// rounding mode token // rounding mode token
if (STI.getFeatureBits() & X86::FeatureAVX512 && if (STI.getFeatureBits()[X86::FeatureAVX512] &&
getLexer().is(AsmToken::LCurly)) getLexer().is(AsmToken::LCurly))
return ParseRoundingModeOp(Start, End); return ParseRoundingModeOp(Start, End);
@ -1754,7 +1755,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
} }
case AsmToken::LCurly:{ case AsmToken::LCurly:{
SMLoc Start = Parser.getTok().getLoc(), End; SMLoc Start = Parser.getTok().getLoc(), End;
if (STI.getFeatureBits() & X86::FeatureAVX512) if (STI.getFeatureBits()[X86::FeatureAVX512])
return ParseRoundingModeOp(Start, End); return ParseRoundingModeOp(Start, End);
return ErrorOperand(Start, "unknown token in expression"); return ErrorOperand(Start, "unknown token in expression");
} }
@ -1764,7 +1765,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands, bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands,
const MCParsedAsmOperand &Op) { const MCParsedAsmOperand &Op) {
MCAsmParser &Parser = getParser(); MCAsmParser &Parser = getParser();
if(STI.getFeatureBits() & X86::FeatureAVX512) { if(STI.getFeatureBits()[X86::FeatureAVX512]) {
if (getLexer().is(AsmToken::LCurly)) { if (getLexer().is(AsmToken::LCurly)) {
// Eat "{" and mark the current place. // Eat "{" and mark the current place.
const SMLoc consumedToken = consumeToken(); const SMLoc consumedToken = consumeToken();

View File

@ -80,20 +80,19 @@ X86GenericDisassembler::X86GenericDisassembler(
MCContext &Ctx, MCContext &Ctx,
std::unique_ptr<const MCInstrInfo> MII) std::unique_ptr<const MCInstrInfo> MII)
: MCDisassembler(STI, Ctx), MII(std::move(MII)) { : MCDisassembler(STI, Ctx), MII(std::move(MII)) {
switch (STI.getFeatureBits() & const FeatureBitset &FB = STI.getFeatureBits();
(X86::Mode16Bit | X86::Mode32Bit | X86::Mode64Bit)) { if (FB[X86::Mode16Bit]) {
case X86::Mode16Bit:
fMode = MODE_16BIT; fMode = MODE_16BIT;
break; return;
case X86::Mode32Bit: } else if (FB[X86::Mode32Bit]) {
fMode = MODE_32BIT; fMode = MODE_32BIT;
break; return;
case X86::Mode64Bit: } else if (FB[X86::Mode64Bit]) {
fMode = MODE_64BIT; fMode = MODE_64BIT;
break; return;
default:
llvm_unreachable("Invalid CPU mode");
} }
llvm_unreachable("Invalid CPU mode");
} }
struct Region { struct Region {

View File

@ -57,7 +57,7 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
// InstrInfo.td as soon as Requires clause is supported properly // InstrInfo.td as soon as Requires clause is supported properly
// for InstAlias. // for InstAlias.
if (MI->getOpcode() == X86::CALLpcrel32 && if (MI->getOpcode() == X86::CALLpcrel32 &&
(STI.getFeatureBits() & X86::Mode64Bit) != 0) { (STI.getFeatureBits()[X86::Mode64Bit])) {
OS << "\tcallq\t"; OS << "\tcallq\t";
printPCRelImm(MI, 0, OS); printPCRelImm(MI, 0, OS);
} }

View File

@ -42,15 +42,15 @@ public:
~X86MCCodeEmitter() override {} ~X86MCCodeEmitter() override {}
bool is64BitMode(const MCSubtargetInfo &STI) const { bool is64BitMode(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & X86::Mode64Bit) != 0; return STI.getFeatureBits()[X86::Mode64Bit];
} }
bool is32BitMode(const MCSubtargetInfo &STI) const { bool is32BitMode(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & X86::Mode32Bit) != 0; return STI.getFeatureBits()[X86::Mode32Bit];
} }
bool is16BitMode(const MCSubtargetInfo &STI) const { bool is16BitMode(const MCSubtargetInfo &STI) const {
return (STI.getFeatureBits() & X86::Mode16Bit) != 0; return STI.getFeatureBits()[X86::Mode16Bit];
} }
/// Is16BitMemOperand - Return true if the specified instruction has /// Is16BitMemOperand - Return true if the specified instruction has

View File

@ -28,4 +28,4 @@ def foo : Instruction {
let Predicates = [Pred1, Pred2]; let Predicates = [Pred1, Pred2];
} }
// CHECK: return ((Bits & arch::AssemblerCondition2)); // CHECK: return (Bits[arch::AssemblerCondition2]);

View File

@ -2248,7 +2248,7 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
Info.AsmParser->getValueAsString("AsmParserClassName"); Info.AsmParser->getValueAsString("AsmParserClassName");
OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
<< "ComputeAvailableFeatures(uint64_t FB) const {\n"; << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n";
OS << " uint64_t Features = 0;\n"; OS << " uint64_t Features = 0;\n";
for (const auto &SF : Info.SubtargetFeatures) { for (const auto &SF : Info.SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second; const SubtargetFeatureInfo &SFI = SF.second;
@ -2270,12 +2270,10 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
Cond = Cond.substr(1); Cond = Cond.substr(1);
} }
OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")"; OS << "(";
if (Neg) if (Neg)
OS << " == 0"; OS << "!";
else OS << "FB[" << Info.Target.getName() << "::" << Cond << "])";
OS << " != 0";
OS << ")";
if (Comma.second.empty()) if (Comma.second.empty())
break; break;
@ -2645,7 +2643,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n"; OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of MCTargetAsmParser.\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n";
OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n" << "unsigned Opcode,\n"
<< " const OperandVector " << " const OperandVector "

View File

@ -848,7 +848,7 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
// The predicate function is just a big switch statement based on the // The predicate function is just a big switch statement based on the
// input predicate index. // input predicate index.
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, " OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
<< "uint64_t Bits) {\n"; << "const FeatureBitset& Bits) {\n";
Indentation += 2; Indentation += 2;
if (!Predicates.empty()) { if (!Predicates.empty()) {
OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "switch (Idx) {\n";
@ -1102,10 +1102,10 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
static void emitSinglePredicateMatch(raw_ostream &o, StringRef str, static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
const std::string &PredicateNamespace) { const std::string &PredicateNamespace) {
if (str[0] == '!') if (str[0] == '!')
o << "!(Bits & " << PredicateNamespace << "::" o << "!Bits[" << PredicateNamespace << "::"
<< str.slice(1,str.size()) << ")"; << str.slice(1,str.size()) << "]";
else else
o << "(Bits & " << PredicateNamespace << "::" << str << ")"; o << "Bits[" << PredicateNamespace << "::" << str << "]";
} }
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
@ -2012,7 +2012,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " InsnType insn, uint64_t Address,\n" << " InsnType insn, uint64_t Address,\n"
<< " const void *DisAsm,\n" << " const void *DisAsm,\n"
<< " const MCSubtargetInfo &STI) {\n" << " const MCSubtargetInfo &STI) {\n"
<< " uint64_t Bits = STI.getFeatureBits();\n" << " const FeatureBitset& Bits = STI.getFeatureBits();\n"
<< "\n" << "\n"
<< " const uint8_t *Ptr = DecodeTable;\n" << " const uint8_t *Ptr = DecodeTable;\n"
<< " uint32_t CurFieldValue = 0;\n" << " uint32_t CurFieldValue = 0;\n"

View File

@ -549,15 +549,15 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
CodeGenTarget &Target = CDP.getTargetInfo(); CodeGenTarget &Target = CDP.getTargetInfo();
if (Inst.HasComplexDeprecationPredicate) if (Inst.HasComplexDeprecationPredicate)
// Emit a function pointer to the complex predicate method. // Emit a function pointer to the complex predicate method.
OS << ",0" OS << ", -1 "
<< ",&get" << Inst.DeprecatedReason << "DeprecationInfo"; << ",&get" << Inst.DeprecatedReason << "DeprecationInfo";
else if (!Inst.DeprecatedReason.empty()) else if (!Inst.DeprecatedReason.empty())
// Emit the Subtarget feature. // Emit the Subtarget feature.
OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
<< ",nullptr"; << " ,nullptr";
else else
// Instruction isn't deprecated. // Instruction isn't deprecated.
OS << ",0,nullptr"; OS << ", -1 ,nullptr";
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
} }

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCInstrItineraries.h" #include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Error.h"
@ -62,7 +63,7 @@ class SubtargetEmitter {
CodeGenSchedModels &SchedModels; CodeGenSchedModels &SchedModels;
std::string Target; std::string Target;
void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits); void Enumeration(raw_ostream &OS, const char *ClassName);
unsigned FeatureKeyValues(raw_ostream &OS); unsigned FeatureKeyValues(raw_ostream &OS);
unsigned CPUKeyValues(raw_ostream &OS); unsigned CPUKeyValues(raw_ostream &OS);
void FormItineraryStageString(const std::string &Names, void FormItineraryStageString(const std::string &Names,
@ -112,8 +113,7 @@ public:
// Enumeration - Emit the specified class as an enumeration. // Enumeration - Emit the specified class as an enumeration.
// //
void SubtargetEmitter::Enumeration(raw_ostream &OS, void SubtargetEmitter::Enumeration(raw_ostream &OS,
const char *ClassName, const char *ClassName) {
bool isBits) {
// Get all records of class and sort // Get all records of class and sort
std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName); std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
std::sort(DefList.begin(), DefList.end(), LessRecord()); std::sort(DefList.begin(), DefList.end(), LessRecord());
@ -121,8 +121,8 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS,
unsigned N = DefList.size(); unsigned N = DefList.size();
if (N == 0) if (N == 0)
return; return;
if (N > 64) if (N > MAX_SUBTARGET_FEATURES)
PrintFatalError("Too many (> 64) subtarget features!"); PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
OS << "namespace " << Target << " {\n"; OS << "namespace " << Target << " {\n";
@ -135,21 +135,14 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS,
Record *Def = DefList[i]; Record *Def = DefList[i];
// Get and emit name // Get and emit name
OS << " " << Def->getName(); OS << " " << Def->getName() << " = " << i;
// If bit flags then emit expression (1 << i)
if (isBits) OS << " = " << " 1ULL << " << i;
// Depending on 'if more in the list' emit comma
if (++i < N) OS << ","; if (++i < N) OS << ",";
OS << "\n"; OS << "\n";
} }
// Close enumeration // Close enumeration and namespace
OS << "};\n"; OS << "};\n}\n";
OS << "}\n";
} }
// //
@ -183,22 +176,24 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
if (CommandLineName.empty()) continue; if (CommandLineName.empty()) continue;
// Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in } // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }
OS << " { " OS << " { "
<< "\"" << CommandLineName << "\", " << "\"" << CommandLineName << "\", "
<< "\"" << Desc << "\", " << "\"" << Desc << "\", "
<< Target << "::" << Name << ", "; << "{ " << Target << "::" << Name << " }, ";
const std::vector<Record*> &ImpliesList = const std::vector<Record*> &ImpliesList =
Feature->getValueAsListOfDefs("Implies"); Feature->getValueAsListOfDefs("Implies");
if (ImpliesList.empty()) { if (ImpliesList.empty()) {
OS << "0ULL"; OS << "{ }";
} else { } else {
OS << "{ ";
for (unsigned j = 0, M = ImpliesList.size(); j < M;) { for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
OS << Target << "::" << ImpliesList[j]->getName(); OS << Target << "::" << ImpliesList[j]->getName();
if (++j < M) OS << " | "; if (++j < M) OS << ", ";
} }
OS << " }";
} }
OS << " }"; OS << " }";
@ -240,22 +235,24 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
const std::vector<Record*> &FeatureList = const std::vector<Record*> &FeatureList =
Processor->getValueAsListOfDefs("Features"); Processor->getValueAsListOfDefs("Features");
// Emit as { "cpu", "description", f1 | f2 | ... fn }, // Emit as { "cpu", "description", { f1 , f2 , ... fn } },
OS << " { " OS << " { "
<< "\"" << Name << "\", " << "\"" << Name << "\", "
<< "\"Select the " << Name << " processor\", "; << "\"Select the " << Name << " processor\", ";
if (FeatureList.empty()) { if (FeatureList.empty()) {
OS << "0ULL"; OS << "{ }";
} else { } else {
OS << "{ ";
for (unsigned j = 0, M = FeatureList.size(); j < M;) { for (unsigned j = 0, M = FeatureList.size(); j < M;) {
OS << Target << "::" << FeatureList[j]->getName(); OS << Target << "::" << FeatureList[j]->getName();
if (++j < M) OS << " | "; if (++j < M) OS << ", ";
} }
OS << " }";
} }
// The "0" is for the "implies" section of this data structure. // The { } is for the "implies" section of this data structure.
OS << ", 0ULL }"; OS << ", { } }";
// Depending on 'if more in the list' emit comma // Depending on 'if more in the list' emit comma
if (++i < N) OS << ","; if (++i < N) OS << ",";
@ -1383,7 +1380,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
} }
OS << " InitMCProcessorInfo(CPU, FS);\n" OS << " InitMCProcessorInfo(CPU, FS);\n"
<< " uint64_t Bits = getFeatureBits();\n"; << " const FeatureBitset& Bits = getFeatureBits();\n";
for (unsigned i = 0; i < Features.size(); i++) { for (unsigned i = 0; i < Features.size(); i++) {
// Next record // Next record
@ -1393,12 +1390,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
const std::string &Attribute = R->getValueAsString("Attribute"); const std::string &Attribute = R->getValueAsString("Attribute");
if (Value=="true" || Value=="false") if (Value=="true" || Value=="false")
OS << " if ((Bits & " << Target << "::" OS << " if (Bits[" << Target << "::"
<< Instance << ") != 0) " << Instance << "]) "
<< Attribute << " = " << Value << ";\n"; << Attribute << " = " << Value << ";\n";
else else
OS << " if ((Bits & " << Target << "::" OS << " if (Bits[" << Target << "::"
<< Instance << ") != 0 && " << Instance << "] && "
<< Attribute << " < " << Value << ") " << Attribute << " < " << Value << ") "
<< Attribute << " = " << Value << ";\n"; << Attribute << " = " << Value << ";\n";
} }
@ -1416,7 +1413,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "#undef GET_SUBTARGETINFO_ENUM\n"; OS << "#undef GET_SUBTARGETINFO_ENUM\n";
OS << "namespace llvm {\n"; OS << "namespace llvm {\n";
Enumeration(OS, "SubtargetFeature", true); Enumeration(OS, "SubtargetFeature");
OS << "} // End llvm namespace \n"; OS << "} // End llvm namespace \n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";