[LLVM][TableGen][DecoderEmitter] Add wrapper struct for bit_value_t (#146248)
Add a convenience wrapper struct for the `bit_value_t` enum type to host various constructors, query, and printing support. Also refactor related code in several places. In `getBitsField`, use `llvm::append_range` and `SmallVector::append()` and eliminate manual loops. Eliminate `emitNameWithID` and instead use the `operator <<` that does the same thing as this function. Have `BitValue::getValue()` (replacement for `Value`) return std::optional<> instead of -1 for unset bits. Terminate with a fatal error when a decoding conflict is encountered.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s -o - 2>%t
|
// RUN: not llvm-tblgen -gen-disassembler -I %p/../../../include %s -o - 2>%t
|
||||||
// RUN: FileCheck %s < %t
|
// RUN: FileCheck %s < %t
|
||||||
|
|
||||||
include "llvm/Target/Target.td"
|
include "llvm/Target/Target.td"
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
#include "llvm/Support/FormatVariadic.h"
|
||||||
#include "llvm/Support/FormattedStream.h"
|
#include "llvm/Support/FormattedStream.h"
|
||||||
#include "llvm/Support/LEB128.h"
|
#include "llvm/Support/LEB128.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
@@ -215,13 +216,6 @@ struct EncodingIDAndOpcode {
|
|||||||
using EncodingIDsVec = std::vector<EncodingIDAndOpcode>;
|
using EncodingIDsVec = std::vector<EncodingIDAndOpcode>;
|
||||||
using NamespacesHwModesMap = std::map<std::string, std::set<StringRef>>;
|
using NamespacesHwModesMap = std::map<std::string, std::set<StringRef>>;
|
||||||
|
|
||||||
raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) {
|
|
||||||
if (Value.EncodingDef != Value.Inst->TheDef)
|
|
||||||
OS << Value.EncodingDef->getName() << ":";
|
|
||||||
OS << Value.Inst->TheDef->getName();
|
|
||||||
return OS;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DecoderEmitter {
|
class DecoderEmitter {
|
||||||
const RecordKeeper &RK;
|
const RecordKeeper &RK;
|
||||||
std::vector<EncodingAndInst> NumberedEncodings;
|
std::vector<EncodingAndInst> NumberedEncodings;
|
||||||
@@ -252,84 +246,96 @@ public:
|
|||||||
StringRef PredicateNamespace;
|
StringRef PredicateNamespace;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
|
// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
|
||||||
// for a bit value.
|
// for a bit value.
|
||||||
//
|
//
|
||||||
// BIT_UNFILTERED is used as the init value for a filter position. It is used
|
// BIT_UNFILTERED is used as the init value for a filter position. It is used
|
||||||
// only for filter processings.
|
// only for filter processings.
|
||||||
typedef enum : uint8_t {
|
struct BitValue {
|
||||||
BIT_FALSE, // '0'
|
enum bit_value_t : uint8_t {
|
||||||
BIT_TRUE, // '1'
|
BIT_FALSE, // '0'
|
||||||
BIT_UNSET, // '?'
|
BIT_TRUE, // '1'
|
||||||
BIT_UNFILTERED // unfiltered
|
BIT_UNSET, // '?', printed as '_'
|
||||||
} bit_value_t;
|
BIT_UNFILTERED // unfiltered, printed as '.'
|
||||||
|
};
|
||||||
|
|
||||||
static bool ValueSet(bit_value_t V) {
|
BitValue(bit_value_t V) : V(V) {}
|
||||||
return (V == BIT_TRUE || V == BIT_FALSE);
|
explicit BitValue(const Init *Init) {
|
||||||
}
|
if (const auto *Bit = dyn_cast<BitInit>(Init))
|
||||||
|
V = Bit->getValue() ? BIT_TRUE : BIT_FALSE;
|
||||||
|
else
|
||||||
|
V = BIT_UNSET;
|
||||||
|
}
|
||||||
|
BitValue(const BitsInit &Bits, unsigned Idx) : BitValue(Bits.getBit(Idx)) {}
|
||||||
|
|
||||||
static bool ValueNotSet(bit_value_t V) { return (V == BIT_UNSET); }
|
bool isSet() const { return V == BIT_TRUE || V == BIT_FALSE; }
|
||||||
|
bool isUnset() const { return V == BIT_UNSET; }
|
||||||
|
std::optional<uint64_t> getValue() const {
|
||||||
|
if (isSet())
|
||||||
|
return static_cast<uint64_t>(V);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
static int Value(bit_value_t V) {
|
// For printing a bit value.
|
||||||
return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1);
|
operator StringRef() const {
|
||||||
}
|
switch (V) {
|
||||||
|
case BIT_FALSE:
|
||||||
|
return "0";
|
||||||
|
case BIT_TRUE:
|
||||||
|
return "1";
|
||||||
|
case BIT_UNSET:
|
||||||
|
return "_";
|
||||||
|
case BIT_UNFILTERED:
|
||||||
|
return ".";
|
||||||
|
}
|
||||||
|
llvm_unreachable("Unknow bit value");
|
||||||
|
}
|
||||||
|
|
||||||
static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) {
|
bool operator==(bit_value_t Other) const { return Other == V; }
|
||||||
if (const BitInit *bit = dyn_cast<BitInit>(bits.getBit(index)))
|
bool operator!=(bit_value_t Other) const { return Other != V; }
|
||||||
return bit->getValue() ? BIT_TRUE : BIT_FALSE;
|
|
||||||
|
|
||||||
// The bit is uninitialized.
|
private:
|
||||||
return BIT_UNSET;
|
bit_value_t V;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
static raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) {
|
||||||
|
if (Value.EncodingDef != Value.Inst->TheDef)
|
||||||
|
OS << Value.EncodingDef->getName() << ":";
|
||||||
|
OS << Value.Inst->TheDef->getName();
|
||||||
|
return OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the bit value for each position.
|
// Prints the bit value for each position.
|
||||||
static void dumpBits(raw_ostream &OS, const BitsInit &bits) {
|
static void dumpBits(raw_ostream &OS, const BitsInit &Bits) {
|
||||||
for (unsigned index = bits.getNumBits(); index > 0; --index) {
|
for (const Init *Bit : reverse(Bits.getBits()))
|
||||||
switch (bitFromBits(bits, index - 1)) {
|
OS << BitValue(Bit);
|
||||||
case BIT_TRUE:
|
|
||||||
OS << "1";
|
|
||||||
break;
|
|
||||||
case BIT_FALSE:
|
|
||||||
OS << "0";
|
|
||||||
break;
|
|
||||||
case BIT_UNSET:
|
|
||||||
OS << "_";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
llvm_unreachable("unexpected return value from bitFromBits");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const BitsInit &getBitsField(const Record &def, StringRef str) {
|
static const BitsInit &getBitsField(const Record &Def, StringRef FieldName) {
|
||||||
const RecordVal *RV = def.getValue(str);
|
const RecordVal *RV = Def.getValue(FieldName);
|
||||||
if (const BitsInit *Bits = dyn_cast<BitsInit>(RV->getValue()))
|
if (const BitsInit *Bits = dyn_cast<BitsInit>(RV->getValue()))
|
||||||
return *Bits;
|
return *Bits;
|
||||||
|
|
||||||
// variable length instruction
|
// Handle variable length instructions.
|
||||||
VarLenInst VLI = VarLenInst(cast<DagInit>(RV->getValue()), RV);
|
VarLenInst VLI(cast<DagInit>(RV->getValue()), RV);
|
||||||
SmallVector<const Init *, 16> Bits;
|
SmallVector<const Init *, 16> Bits;
|
||||||
|
|
||||||
for (const auto &SI : VLI) {
|
for (const auto &SI : VLI) {
|
||||||
if (const BitsInit *BI = dyn_cast<BitsInit>(SI.Value)) {
|
if (const BitsInit *BI = dyn_cast<BitsInit>(SI.Value))
|
||||||
for (unsigned Idx = 0U; Idx < BI->getNumBits(); ++Idx) {
|
llvm::append_range(Bits, BI->getBits());
|
||||||
Bits.push_back(BI->getBit(Idx));
|
else if (const BitInit *BI = dyn_cast<BitInit>(SI.Value))
|
||||||
}
|
|
||||||
} else if (const BitInit *BI = dyn_cast<BitInit>(SI.Value)) {
|
|
||||||
Bits.push_back(BI);
|
Bits.push_back(BI);
|
||||||
} else {
|
else
|
||||||
for (unsigned Idx = 0U; Idx < SI.BitWidth; ++Idx)
|
Bits.append(SI.BitWidth, UnsetInit::get(Def.getRecords()));
|
||||||
Bits.push_back(UnsetInit::get(def.getRecords()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return *BitsInit::get(def.getRecords(), Bits);
|
return *BitsInit::get(Def.getRecords(), Bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of the instruction to work on.
|
// Representation of the instruction to work on.
|
||||||
typedef std::vector<bit_value_t> insn_t;
|
typedef std::vector<BitValue> insn_t;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -480,7 +486,7 @@ protected:
|
|||||||
|
|
||||||
// Array of bit values passed down from our parent.
|
// Array of bit values passed down from our parent.
|
||||||
// Set to all BIT_UNFILTERED's for Parent == NULL.
|
// Set to all BIT_UNFILTERED's for Parent == NULL.
|
||||||
std::vector<bit_value_t> FilterBitValues;
|
std::vector<BitValue> FilterBitValues;
|
||||||
|
|
||||||
// Links to the FilterChooser above us in the decoding tree.
|
// Links to the FilterChooser above us in the decoding tree.
|
||||||
const FilterChooser *Parent;
|
const FilterChooser *Parent;
|
||||||
@@ -506,15 +512,15 @@ public:
|
|||||||
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
|
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
|
||||||
unsigned BW, const DecoderEmitter *E)
|
unsigned BW, const DecoderEmitter *E)
|
||||||
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
|
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
|
||||||
FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1),
|
FilterBitValues(BW, BitValue::BIT_UNFILTERED), Parent(nullptr),
|
||||||
BitWidth(BW), Emitter(E) {
|
BestIndex(-1), BitWidth(BW), Emitter(E) {
|
||||||
doFilter();
|
doFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterChooser(ArrayRef<EncodingAndInst> Insts,
|
FilterChooser(ArrayRef<EncodingAndInst> Insts,
|
||||||
ArrayRef<EncodingIDAndOpcode> IDs,
|
ArrayRef<EncodingIDAndOpcode> IDs,
|
||||||
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
|
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
|
||||||
const std::vector<bit_value_t> &ParentFilterBitValues,
|
const std::vector<BitValue> &ParentFilterBitValues,
|
||||||
const FilterChooser &parent)
|
const FilterChooser &parent)
|
||||||
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
|
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
|
||||||
FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1),
|
FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1),
|
||||||
@@ -532,7 +538,7 @@ protected:
|
|||||||
void insnWithID(insn_t &Insn, unsigned Opcode) const {
|
void insnWithID(insn_t &Insn, unsigned Opcode) const {
|
||||||
const Record *EncodingDef = AllInstructions[Opcode].EncodingDef;
|
const Record *EncodingDef = AllInstructions[Opcode].EncodingDef;
|
||||||
const BitsInit &Bits = getBitsField(*EncodingDef, "Inst");
|
const BitsInit &Bits = getBitsField(*EncodingDef, "Inst");
|
||||||
Insn.resize(std::max(BitWidth, Bits.getNumBits()), BIT_UNSET);
|
Insn.resize(std::max(BitWidth, Bits.getNumBits()), BitValue::BIT_UNSET);
|
||||||
// We may have a SoftFail bitmask, which specifies a mask where an encoding
|
// We may have a SoftFail bitmask, which specifies a mask where an encoding
|
||||||
// may differ from the value in "Inst" and yet still be valid, but the
|
// may differ from the value in "Inst" and yet still be valid, but the
|
||||||
// disassembler should return SoftFail instead of Success.
|
// disassembler should return SoftFail instead of Success.
|
||||||
@@ -541,22 +547,13 @@ protected:
|
|||||||
const RecordVal *RV = EncodingDef->getValue("SoftFail");
|
const RecordVal *RV = EncodingDef->getValue("SoftFail");
|
||||||
const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
|
const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
|
||||||
for (unsigned i = 0; i < Bits.getNumBits(); ++i) {
|
for (unsigned i = 0; i < Bits.getNumBits(); ++i) {
|
||||||
if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE)
|
if (SFBits && BitValue(*SFBits, i) == BitValue::BIT_TRUE)
|
||||||
Insn[i] = BIT_UNSET;
|
Insn[i] = BitValue::BIT_UNSET;
|
||||||
else
|
else
|
||||||
Insn[i] = bitFromBits(Bits, i);
|
Insn[i] = BitValue(Bits, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the name of the encoding/instruction pair.
|
|
||||||
void emitNameWithID(raw_ostream &OS, unsigned Opcode) const {
|
|
||||||
const Record *EncodingDef = AllInstructions[Opcode].EncodingDef;
|
|
||||||
const Record *InstDef = AllInstructions[Opcode].Inst->TheDef;
|
|
||||||
if (EncodingDef != InstDef)
|
|
||||||
OS << EncodingDef->getName() << ":";
|
|
||||||
OS << InstDef->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populates the field of the insn given the start position and the number of
|
// Populates the field of the insn given the start position and the number of
|
||||||
// consecutive bits to scan for.
|
// consecutive bits to scan for.
|
||||||
//
|
//
|
||||||
@@ -568,7 +565,7 @@ protected:
|
|||||||
|
|
||||||
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
|
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
|
||||||
/// filter array as a series of chars.
|
/// filter array as a series of chars.
|
||||||
void dumpFilterArray(raw_ostream &OS, ArrayRef<bit_value_t> Filter) const;
|
void dumpFilterArray(raw_ostream &OS, ArrayRef<BitValue> Filter) const;
|
||||||
|
|
||||||
/// dumpStack - dumpStack traverses the filter chooser chain and calls
|
/// dumpStack - dumpStack traverses the filter chooser chain and calls
|
||||||
/// dumpFilterArray on each filter chooser up to the top level one.
|
/// dumpFilterArray on each filter chooser up to the top level one.
|
||||||
@@ -579,8 +576,8 @@ protected:
|
|||||||
return Filters[BestIndex];
|
return Filters[BestIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PositionFiltered(unsigned i) const {
|
bool PositionFiltered(unsigned Idx) const {
|
||||||
return ValueSet(FilterBitValues[i]);
|
return FilterBitValues[Idx].isSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the island(s) needed to decode the instruction.
|
// Calculates the island(s) needed to decode the instruction.
|
||||||
@@ -697,12 +694,12 @@ Filter::Filter(const FilterChooser &owner, unsigned startBit, unsigned numBits,
|
|||||||
// match the remaining undecoded encoding bits against the singleton.
|
// match the remaining undecoded encoding bits against the singleton.
|
||||||
void Filter::recurse() {
|
void Filter::recurse() {
|
||||||
// Starts by inheriting our parent filter chooser's filter bit values.
|
// Starts by inheriting our parent filter chooser's filter bit values.
|
||||||
std::vector<bit_value_t> BitValueArray(Owner.FilterBitValues);
|
std::vector<BitValue> BitValueArray(Owner.FilterBitValues);
|
||||||
|
|
||||||
if (!VariableInstructions.empty()) {
|
if (!VariableInstructions.empty()) {
|
||||||
// Conservatively marks each segment position as BIT_UNSET.
|
// Conservatively marks each segment position as BIT_UNSET.
|
||||||
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
|
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
|
||||||
BitValueArray[StartBit + bitIndex] = BIT_UNSET;
|
BitValueArray[StartBit + bitIndex] = BitValue::BIT_UNSET;
|
||||||
|
|
||||||
// Delegates to an inferior filter chooser for further processing on this
|
// Delegates to an inferior filter chooser for further processing on this
|
||||||
// group of instructions whose segment values are variable.
|
// group of instructions whose segment values are variable.
|
||||||
@@ -723,12 +720,10 @@ void Filter::recurse() {
|
|||||||
// Otherwise, create sub choosers.
|
// Otherwise, create sub choosers.
|
||||||
for (const auto &Inst : FilteredInstructions) {
|
for (const auto &Inst : FilteredInstructions) {
|
||||||
// Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
|
// Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
|
||||||
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) {
|
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
|
||||||
if (Inst.first & (1ULL << bitIndex))
|
BitValueArray[StartBit + bitIndex] = Inst.first & (1ULL << bitIndex)
|
||||||
BitValueArray[StartBit + bitIndex] = BIT_TRUE;
|
? BitValue::BIT_TRUE
|
||||||
else
|
: BitValue::BIT_FALSE;
|
||||||
BitValueArray[StartBit + bitIndex] = BIT_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delegates to an inferior filter chooser for further processing on this
|
// Delegates to an inferior filter chooser for further processing on this
|
||||||
// category of instructions.
|
// category of instructions.
|
||||||
@@ -1151,10 +1146,10 @@ std::pair<bool, uint64_t> FilterChooser::fieldFromInsn(const insn_t &Insn,
|
|||||||
uint64_t Field = 0;
|
uint64_t Field = 0;
|
||||||
|
|
||||||
for (unsigned i = 0; i < NumBits; ++i) {
|
for (unsigned i = 0; i < NumBits; ++i) {
|
||||||
if (Insn[StartBit + i] == BIT_UNSET)
|
if (Insn[StartBit + i] == BitValue::BIT_UNSET)
|
||||||
return {false, Field};
|
return {false, Field};
|
||||||
|
|
||||||
if (Insn[StartBit + i] == BIT_TRUE)
|
if (Insn[StartBit + i] == BitValue::BIT_TRUE)
|
||||||
Field = Field | (1ULL << i);
|
Field = Field | (1ULL << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1164,23 +1159,9 @@ std::pair<bool, uint64_t> FilterChooser::fieldFromInsn(const insn_t &Insn,
|
|||||||
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
|
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
|
||||||
/// filter array as a series of chars.
|
/// filter array as a series of chars.
|
||||||
void FilterChooser::dumpFilterArray(raw_ostream &OS,
|
void FilterChooser::dumpFilterArray(raw_ostream &OS,
|
||||||
ArrayRef<bit_value_t> Filter) const {
|
ArrayRef<BitValue> Filter) const {
|
||||||
for (unsigned bitIndex = BitWidth; bitIndex > 0; bitIndex--) {
|
for (unsigned bitIndex = BitWidth; bitIndex > 0; bitIndex--)
|
||||||
switch (Filter[bitIndex - 1]) {
|
OS << Filter[bitIndex - 1];
|
||||||
case BIT_UNFILTERED:
|
|
||||||
OS << ".";
|
|
||||||
break;
|
|
||||||
case BIT_UNSET:
|
|
||||||
OS << "_";
|
|
||||||
break;
|
|
||||||
case BIT_TRUE:
|
|
||||||
OS << "1";
|
|
||||||
break;
|
|
||||||
case BIT_FALSE:
|
|
||||||
OS << "0";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// dumpStack - dumpStack traverses the filter chooser chain and calls
|
/// dumpStack - dumpStack traverses the filter chooser chain and calls
|
||||||
@@ -1211,28 +1192,28 @@ unsigned FilterChooser::getIslands(std::vector<Island> &Islands,
|
|||||||
unsigned State = 0;
|
unsigned State = 0;
|
||||||
|
|
||||||
for (unsigned i = 0; i < BitWidth; ++i) {
|
for (unsigned i = 0; i < BitWidth; ++i) {
|
||||||
int64_t Val = Value(Insn[i]);
|
std::optional<uint64_t> Val = Insn[i].getValue();
|
||||||
bool Filtered = PositionFiltered(i);
|
bool Filtered = PositionFiltered(i);
|
||||||
switch (State) {
|
switch (State) {
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Unreachable code!");
|
llvm_unreachable("Unreachable code!");
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
if (Filtered || Val == -1) {
|
if (Filtered || !Val) {
|
||||||
State = 1; // Still in Water
|
State = 1; // Still in Water
|
||||||
} else {
|
} else {
|
||||||
State = 2; // Into the Island
|
State = 2; // Into the Island
|
||||||
StartBit = i;
|
StartBit = i;
|
||||||
FieldVal = Val;
|
FieldVal = *Val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (Filtered || Val == -1) {
|
if (Filtered || !Val) {
|
||||||
State = 1; // Into the Water
|
State = 1; // Into the Water
|
||||||
Islands.push_back({StartBit, i - StartBit, FieldVal});
|
Islands.push_back({StartBit, i - StartBit, FieldVal});
|
||||||
} else {
|
} else {
|
||||||
State = 2; // Still in Island
|
State = 2; // Still in Island
|
||||||
FieldVal |= Val << (i - StartBit);
|
FieldVal |= *Val << (i - StartBit);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1453,22 +1434,19 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
|
|||||||
APInt PositiveMask(BitWidth, 0ULL);
|
APInt PositiveMask(BitWidth, 0ULL);
|
||||||
APInt NegativeMask(BitWidth, 0ULL);
|
APInt NegativeMask(BitWidth, 0ULL);
|
||||||
for (unsigned i = 0; i < BitWidth; ++i) {
|
for (unsigned i = 0; i < BitWidth; ++i) {
|
||||||
bit_value_t B = bitFromBits(*SFBits, i);
|
BitValue B(*SFBits, i);
|
||||||
bit_value_t IB = bitFromBits(*InstBits, i);
|
BitValue IB(*InstBits, i);
|
||||||
|
|
||||||
if (B != BIT_TRUE)
|
if (B != BitValue::BIT_TRUE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (IB) {
|
if (IB == BitValue::BIT_FALSE) {
|
||||||
case BIT_FALSE:
|
|
||||||
// The bit is meant to be false, so emit a check to see if it is true.
|
// The bit is meant to be false, so emit a check to see if it is true.
|
||||||
PositiveMask.setBit(i);
|
PositiveMask.setBit(i);
|
||||||
break;
|
} else if (IB == BitValue::BIT_TRUE) {
|
||||||
case BIT_TRUE:
|
|
||||||
// The bit is meant to be true, so emit a check to see if it is false.
|
// The bit is meant to be true, so emit a check to see if it is false.
|
||||||
NegativeMask.setBit(i);
|
NegativeMask.setBit(i);
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
// The bit is not set; this must be an error!
|
// The bit is not set; this must be an error!
|
||||||
errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in "
|
errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in "
|
||||||
<< AllInstructions[Opc] << " is set but Inst{" << i
|
<< AllInstructions[Opc] << " is set but Inst{" << i
|
||||||
@@ -1651,8 +1629,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
|
|||||||
// FILTERED bit positions provide no entropy and are not worthy of pursuing.
|
// FILTERED bit positions provide no entropy and are not worthy of pursuing.
|
||||||
// Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
|
// Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
|
||||||
for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
|
for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
|
||||||
if (FilterBitValues[BitIndex] == BIT_TRUE ||
|
if (FilterBitValues[BitIndex].isSet())
|
||||||
FilterBitValues[BitIndex] == BIT_FALSE)
|
|
||||||
bitAttrs[BitIndex] = ATTR_FILTERED;
|
bitAttrs[BitIndex] = ATTR_FILTERED;
|
||||||
|
|
||||||
for (const auto &OpcPair : Opcodes) {
|
for (const auto &OpcPair : Opcodes) {
|
||||||
@@ -1663,17 +1640,17 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
|
|||||||
for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
|
for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
|
||||||
switch (bitAttrs[BitIndex]) {
|
switch (bitAttrs[BitIndex]) {
|
||||||
case ATTR_NONE:
|
case ATTR_NONE:
|
||||||
if (insn[BitIndex] == BIT_UNSET)
|
if (insn[BitIndex] == BitValue::BIT_UNSET)
|
||||||
bitAttrs[BitIndex] = ATTR_ALL_UNSET;
|
bitAttrs[BitIndex] = ATTR_ALL_UNSET;
|
||||||
else
|
else
|
||||||
bitAttrs[BitIndex] = ATTR_ALL_SET;
|
bitAttrs[BitIndex] = ATTR_ALL_SET;
|
||||||
break;
|
break;
|
||||||
case ATTR_ALL_SET:
|
case ATTR_ALL_SET:
|
||||||
if (insn[BitIndex] == BIT_UNSET)
|
if (insn[BitIndex] == BitValue::BIT_UNSET)
|
||||||
bitAttrs[BitIndex] = ATTR_MIXED;
|
bitAttrs[BitIndex] = ATTR_MIXED;
|
||||||
break;
|
break;
|
||||||
case ATTR_ALL_UNSET:
|
case ATTR_ALL_UNSET:
|
||||||
if (insn[BitIndex] != BIT_UNSET)
|
if (insn[BitIndex] != BitValue::BIT_UNSET)
|
||||||
bitAttrs[BitIndex] = ATTR_MIXED;
|
bitAttrs[BitIndex] = ATTR_MIXED;
|
||||||
break;
|
break;
|
||||||
case ATTR_MIXED:
|
case ATTR_MIXED:
|
||||||
@@ -1868,7 +1845,7 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't know how to decode these instructions! Dump the
|
// We don't know how to decode these instructions! Dump the
|
||||||
// conflict set and bail.
|
// conflict set and bail.
|
||||||
|
|
||||||
// Print out useful conflict information for postmortem analysis.
|
// Print out useful conflict information for postmortem analysis.
|
||||||
@@ -1877,14 +1854,12 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
|
|||||||
dumpStack(errs(), "\t\t");
|
dumpStack(errs(), "\t\t");
|
||||||
|
|
||||||
for (auto Opcode : Opcodes) {
|
for (auto Opcode : Opcodes) {
|
||||||
errs() << '\t';
|
const EncodingAndInst &Enc = AllInstructions[Opcode.EncodingID];
|
||||||
emitNameWithID(errs(), Opcode.EncodingID);
|
errs() << '\t' << Enc << ' ';
|
||||||
errs() << " ";
|
dumpBits(errs(), getBitsField(*Enc.EncodingDef, "Inst"));
|
||||||
dumpBits(
|
|
||||||
errs(),
|
|
||||||
getBitsField(*AllInstructions[Opcode.EncodingID].EncodingDef, "Inst"));
|
|
||||||
errs() << '\n';
|
errs() << '\n';
|
||||||
}
|
}
|
||||||
|
PrintFatalError("Decoding conflict encountered");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string findOperandDecoderMethod(const Record *Record) {
|
static std::string findOperandDecoderMethod(const Record *Record) {
|
||||||
|
|||||||
Reference in New Issue
Block a user