summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2018-12-13 14:55:57 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2018-12-13 14:55:57 +0000
commitf81ecd2ce2e8ffdee0990d009d5c4594d7385728 (patch)
tree322dbc51c666c8786221b366d350a4c65f84e6d4 /llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
parent7c84f7ae3aae3f61b0c284a505cfded3eed8cc12 (diff)
downloadbcm5719-llvm-f81ecd2ce2e8ffdee0990d009d5c4594d7385728.tar.gz
bcm5719-llvm-f81ecd2ce2e8ffdee0990d009d5c4594d7385728.zip
[tblgen][disasm] Separate encodings from instructions
Summary: Separate the concept of an encoding from an instruction. This will enable the definition of additional encodings for the same instruction which can be used to support variable length instruction sets in the disassembler (and potentially assembler but I'm not working towards that right now) without causing an explosion in the number of Instruction records that CodeGen then has to pick between. Reviewers: bogner, charukcs Reviewed By: bogner Subscribers: kparzysz, llvm-commits Differential Revision: https://reviews.llvm.org/D52366 llvm-svn: 349041
Diffstat (limited to 'llvm/utils/TableGen/FixedLenDecoderEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/FixedLenDecoderEmitter.cpp88
1 files changed, 51 insertions, 37 deletions
diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 44cf6eadcb0..70b91aa23e9 100644
--- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -87,8 +87,23 @@ struct DecoderTableInfo {
DecoderSet Decoders;
};
+struct EncodingAndInst {
+ const Record *EncodingDef;
+ const CodeGenInstruction *Inst;
+
+ EncodingAndInst(const Record *EncodingDef, const CodeGenInstruction *Inst)
+ : EncodingDef(EncodingDef), Inst(Inst) {}
+};
+
+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 FixedLenDecoderEmitter {
- ArrayRef<const CodeGenInstruction *> NumberedInstructions;
+ std::vector<EncodingAndInst> NumberedEncodings;
public:
// Defaults preserved here for documentation, even though they aren't
@@ -323,7 +338,7 @@ protected:
friend class Filter;
// Vector of codegen instructions to choose our filter.
- ArrayRef<const CodeGenInstruction *> AllInstructions;
+ ArrayRef<const EncodingAndInst> AllInstructions;
// Vector of uid's for this filter chooser to work on.
const std::vector<unsigned> &Opcodes;
@@ -351,25 +366,24 @@ protected:
const FixedLenDecoderEmitter *Emitter;
public:
- FilterChooser(ArrayRef<const CodeGenInstruction *> Insts,
+ FilterChooser(ArrayRef<const EncodingAndInst> Insts,
const std::vector<unsigned> &IDs,
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
- unsigned BW,
- const FixedLenDecoderEmitter *E)
- : AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
- FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1),
- BitWidth(BW), Emitter(E) {
+ unsigned BW, const FixedLenDecoderEmitter *E)
+ : AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
+ FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1),
+ BitWidth(BW), Emitter(E) {
doFilter();
}
- FilterChooser(ArrayRef<const CodeGenInstruction *> Insts,
+ FilterChooser(ArrayRef<const EncodingAndInst> Insts,
const std::vector<unsigned> &IDs,
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
const std::vector<bit_value_t> &ParentFilterBitValues,
const FilterChooser &parent)
- : AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
- FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1),
- BitWidth(parent.BitWidth), Emitter(parent.Emitter) {
+ : AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
+ FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1),
+ BitWidth(parent.BitWidth), Emitter(parent.Emitter) {
doFilter();
}
@@ -381,7 +395,7 @@ public:
protected:
// Populates the insn given the uid.
void insnWithID(insn_t &Insn, unsigned Opcode) const {
- BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
+ BitsInit &Bits = getBitsField(*AllInstructions[Opcode].EncodingDef, "Inst");
// 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
@@ -389,7 +403,7 @@ protected:
//
// This is used for marking UNPREDICTABLE instructions in the ARM world.
BitsInit *SFBits =
- AllInstructions[Opcode]->TheDef->getValueAsBitsInit("SoftFail");
+ AllInstructions[Opcode].EncodingDef->getValueAsBitsInit("SoftFail");
for (unsigned i = 0; i < BitWidth; ++i) {
if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE)
@@ -399,11 +413,6 @@ protected:
}
}
- // Returns the record name.
- const StringRef nameWithID(unsigned Opcode) const {
- return AllInstructions[Opcode]->TheDef->getName();
- }
-
// Populates the field of the insn given the start position and the number of
// consecutive bits to scan for.
//
@@ -827,8 +836,7 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
OS << (unsigned)*I++ << ", ";
if (!IsTry) {
- OS << "// Opcode: "
- << NumberedInstructions[Opc]->TheDef->getName() << "\n";
+ OS << "// Opcode: " << NumberedEncodings[Opc] << "\n";
break;
}
@@ -845,8 +853,7 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
OS << utostr(Byte) << ", ";
NumToSkip |= Byte << 16;
- OS << "// Opcode: "
- << NumberedInstructions[Opc]->TheDef->getName()
+ OS << "// Opcode: " << NumberedEncodings[Opc]
<< ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
}
@@ -1153,7 +1160,7 @@ static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
unsigned Opc) const {
ListInit *Predicates =
- AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ AllInstructions[Opc].EncodingDef->getValueAsListInit("Predicates");
bool IsFirstEmission = true;
for (unsigned i = 0; i < Predicates->size(); ++i) {
Record *Pred = Predicates->getElementAsRecord(i);
@@ -1182,7 +1189,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
bool FilterChooser::doesOpcodeNeedPredicate(unsigned Opc) const {
ListInit *Predicates =
- AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ AllInstructions[Opc].EncodingDef->getValueAsListInit("Predicates");
for (unsigned i = 0; i < Predicates->size(); ++i) {
Record *Pred = Predicates->getElementAsRecord(i);
if (!Pred->getValue("AssemblerMatcherPredicate"))
@@ -1247,9 +1254,10 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
unsigned Opc) const {
BitsInit *SFBits =
- AllInstructions[Opc]->TheDef->getValueAsBitsInit("SoftFail");
+ AllInstructions[Opc].EncodingDef->getValueAsBitsInit("SoftFail");
if (!SFBits) return;
- BitsInit *InstBits = AllInstructions[Opc]->TheDef->getValueAsBitsInit("Inst");
+ BitsInit *InstBits =
+ AllInstructions[Opc].EncodingDef->getValueAsBitsInit("Inst");
APInt PositiveMask(BitWidth, 0ULL);
APInt NegativeMask(BitWidth, 0ULL);
@@ -1270,9 +1278,9 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
break;
default:
// The bit is not set; this must be an error!
- StringRef Name = AllInstructions[Opc]->TheDef->getName();
- errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in " << Name
- << " is set but Inst{" << i << "} is unset!\n"
+ errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in "
+ << AllInstructions[Opc] << " is set but Inst{" << i
+ << "} is unset!\n"
<< " - You can only mark a bit as SoftFail if it is fully defined"
<< " (1/0 - not '?') in Inst\n";
return;
@@ -1709,9 +1717,9 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
dumpStack(errs(), "\t\t");
for (unsigned i = 0; i < Opcodes.size(); ++i) {
- errs() << '\t' << nameWithID(Opcodes[i]) << " ";
+ errs() << '\t' << Opcodes[i] << " ";
dumpBits(errs(),
- getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
+ getBitsField(*AllInstructions[Opcodes[i]].EncodingDef, "Inst"));
errs() << '\n';
}
}
@@ -2326,13 +2334,17 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
Target.reverseBitsForLittleEndianEncoding();
// Parameterize the decoders based on namespace and instruction width.
- NumberedInstructions = Target.getInstructionsByEnumValue();
+ const auto &NumberedInstructions = Target.getInstructionsByEnumValue();
+ NumberedEncodings.reserve(NumberedInstructions.size());
+ for (const auto &NumberedInstruction : NumberedInstructions)
+ NumberedEncodings.emplace_back(NumberedInstruction->TheDef, NumberedInstruction);
+
std::map<std::pair<std::string, unsigned>,
std::vector<unsigned>> OpcMap;
std::map<unsigned, std::vector<OperandInfo>> Operands;
- for (unsigned i = 0; i < NumberedInstructions.size(); ++i) {
- const CodeGenInstruction *Inst = NumberedInstructions[i];
+ for (unsigned i = 0; i < NumberedEncodings.size(); ++i) {
+ const CodeGenInstruction *Inst = NumberedEncodings[i].Inst;
const Record *Def = Inst->TheDef;
unsigned Size = Def->getValueAsInt("Size");
if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
@@ -2353,8 +2365,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
DecoderTableInfo TableInfo;
for (const auto &Opc : OpcMap) {
// Emit the decoder for this namespace+width combination.
- FilterChooser FC(NumberedInstructions, Opc.second, Operands,
- 8*Opc.first.second, this);
+ ArrayRef<const EncodingAndInst> NumberedEncodingsRef(
+ NumberedEncodings.data(), NumberedEncodings.size());
+ FilterChooser FC(NumberedEncodingsRef, Opc.second, Operands,
+ 8 * Opc.first.second, this);
// The decode table is cleared for each top level decoder function. The
// predicates and decoders themselves, however, are shared across all
OpenPOWER on IntegriCloud