Skip to content

Commit 2ed0aac

Browse files
authored
[TableGen] Fixes for per-HwMode decoding problem (#82201)
Today, if any instruction uses EncodingInfos/EncodingByHwMode to override the default encoding, the opcode field of the decoder table is generated incorrectly. This causes failed disassemblies and other problems. Specifically, the main correctness issue is that the EncodingID is inadvertently stored in the table rather than the actual opcode. This is caused by having set up the IndexOfInstruction map incorrectly during the loop to populate NumberedEncodings-- which is then propagated around when OpcMap is set up with a bad EncodingIDAndOpcode. Instead, do away with IndexOfInstruction altogether and use opcode value queried from CodeGenTarget::getInstrIntValue to set up OpcMap. This itself exposed another problem where emitTable was using the decoded opcode to index into NumberedEncodings. Instead pass in the EncodingIDAndOpcode vector, and create the reverse mapping from Opcode to EncodingID, which is then used to index NumberedEncodings. This problem is not currently exposed upstream since no in-tree targets yet use the per-HwMode feature. It does show up in at least two downstream targets.
1 parent 9b76515 commit 2ed0aac

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

llvm/test/TableGen/HwModeEncodeDecode.td

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,8 @@ def baz : Instruction {
7474
// DECODER-DAG: Opcode: fooTypeEncA:foo
7575
// DECODER-DAG: Opcode: bar
7676
// DECODER-LABEL: DecoderTable_ModeB32[] =
77-
// Note that the comment says fooTypeEncA but this is actually fooTypeEncB; plumbing
78-
// the correct comment text through the decoder is nontrivial.
79-
// DECODER-DAG: Opcode: fooTypeEncA:foo
77+
// DECODER-DAG: Opcode: fooTypeEncB:foo
78+
// DECODER-DAG: Opcode: fooTypeEncA:baz
8079
// DECODER-DAG: Opcode: bar
8180

8281
// ENCODER-LABEL: static const uint64_t InstBits_ModeA[] = {

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ struct EncodingIDAndOpcode {
118118
: EncodingID(EncodingID), Opcode(Opcode) {}
119119
};
120120

121+
using EncodingIDsVec = std::vector<EncodingIDAndOpcode>;
122+
121123
raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) {
122124
if (Value.EncodingDef != Value.Inst->TheDef)
123125
OS << Value.EncodingDef->getName() << ":";
@@ -135,8 +137,8 @@ class DecoderEmitter {
135137

136138
// Emit the decoder state machine table.
137139
void emitTable(formatted_raw_ostream &o, DecoderTable &Table,
138-
unsigned Indentation, unsigned BitWidth,
139-
StringRef Namespace) const;
140+
unsigned Indentation, unsigned BitWidth, StringRef Namespace,
141+
const EncodingIDsVec &EncodingIDs) const;
140142
void emitInstrLenTable(formatted_raw_ostream &OS,
141143
std::vector<unsigned> &InstrLen) const;
142144
void emitPredicateFunction(formatted_raw_ostream &OS,
@@ -766,7 +768,16 @@ unsigned Filter::usefulness() const {
766768
// Emit the decoder state machine table.
767769
void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
768770
unsigned Indentation, unsigned BitWidth,
769-
StringRef Namespace) const {
771+
StringRef Namespace,
772+
const EncodingIDsVec &EncodingIDs) const {
773+
// We'll need to be able to map from a decoded opcode into the corresponding
774+
// EncodingID for this specific combination of BitWidth and Namespace. This
775+
// is used below to index into NumberedEncodings.
776+
DenseMap<unsigned, unsigned> OpcodeToEncodingID;
777+
OpcodeToEncodingID.reserve(EncodingIDs.size());
778+
for (auto &EI : EncodingIDs)
779+
OpcodeToEncodingID[EI.Opcode] = EI.EncodingID;
780+
770781
OS.indent(Indentation) << "static const uint8_t DecoderTable" << Namespace
771782
<< BitWidth << "[] = {\n";
772783

@@ -888,8 +899,12 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
888899
// Decoder index.
889900
I += emitULEB128(I, OS);
890901

902+
auto EncI = OpcodeToEncodingID.find(Opc);
903+
assert(EncI != OpcodeToEncodingID.end() && "no encoding entry");
904+
auto EncodingID = EncI->second;
905+
891906
if (!IsTry) {
892-
OS << "// Opcode: " << NumberedEncodings[Opc] << "\n";
907+
OS << "// Opcode: " << NumberedEncodings[EncodingID] << "\n";
893908
break;
894909
}
895910

@@ -899,7 +914,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
899914
uint32_t NumToSkip = emitNumToSkip(I, OS);
900915
I += 3;
901916

902-
OS << "// Opcode: " << NumberedEncodings[Opc]
917+
OS << "// Opcode: " << NumberedEncodings[EncodingID]
903918
<< ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
904919
break;
905920
}
@@ -2449,11 +2464,8 @@ void DecoderEmitter::run(raw_ostream &o) {
24492464
std::set<StringRef> HwModeNames;
24502465
const auto &NumberedInstructions = Target.getInstructionsByEnumValue();
24512466
NumberedEncodings.reserve(NumberedInstructions.size());
2452-
DenseMap<Record *, unsigned> IndexOfInstruction;
24532467
// First, collect all HwModes referenced by the target.
24542468
for (const auto &NumberedInstruction : NumberedInstructions) {
2455-
IndexOfInstruction[NumberedInstruction->TheDef] = NumberedEncodings.size();
2456-
24572469
if (const RecordVal *RV =
24582470
NumberedInstruction->TheDef->getValue("EncodingInfos")) {
24592471
if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
@@ -2470,8 +2482,6 @@ void DecoderEmitter::run(raw_ostream &o) {
24702482
HwModeNames.insert("");
24712483

24722484
for (const auto &NumberedInstruction : NumberedInstructions) {
2473-
IndexOfInstruction[NumberedInstruction->TheDef] = NumberedEncodings.size();
2474-
24752485
if (const RecordVal *RV =
24762486
NumberedInstruction->TheDef->getValue("EncodingInfos")) {
24772487
if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
@@ -2544,7 +2554,7 @@ void DecoderEmitter::run(raw_ostream &o) {
25442554
DecoderNamespace +=
25452555
std::string("_") + NumberedEncodings[i].HwModeName.str();
25462556
OpcMap[std::pair(DecoderNamespace, Size)].emplace_back(
2547-
i, IndexOfInstruction.find(Def)->second);
2557+
i, Target.getInstrIntValue(Def));
25482558
} else {
25492559
NumEncodingsOmitted++;
25502560
}
@@ -2577,7 +2587,8 @@ void DecoderEmitter::run(raw_ostream &o) {
25772587
TableInfo.Table.push_back(MCD::OPC_Fail);
25782588

25792589
// Print the table to the output stream.
2580-
emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), Opc.first.first);
2590+
emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), Opc.first.first,
2591+
Opc.second);
25812592
}
25822593

25832594
// For variable instruction, we emit a instruction length table

0 commit comments

Comments
 (0)