[llvm] [TableGen] Emit Debug code for dynamic bits(eg: instruction operands) in DecoderEmitter (PR #194699)
Prerona Chaudhuri via llvm-commits
llvm-commits at lists.llvm.org
Wed May 6 13:48:00 PDT 2026
https://github.com/pchaudhuri-nv updated https://github.com/llvm/llvm-project/pull/194699
>From d112846c1afaea7a2588b20d5b9deffa07bc8560 Mon Sep 17 00:00:00 2001
From: pchaudhuri-nv <pchaudhuri at nvidia.com>
Date: Wed, 6 May 2026 16:47:57 +0000
Subject: [PATCH] [TableGen] Emit per-operand decode debug logging via dbgFail
helpers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Generated disassembler code now logs FAIL for each operand decode and
whole-instruction decode methods (emitCheckWithDbgMsg). Each emitted
check site is a single
`if (!Check(...)) return dbgFailOpd(...);` (or `dbgFailInsn(...)`) line.
Two specialized helpers, both in the decoder boilerplate:
- dbgFailOpd(Op, Desc, Decoder, ...) — for per-operand check sites.
- dbgFailInsn(Name, Decoder, ...) — for whole-instruction custom
decoder check sites.
Each helper owns the connector strings (": ", " using ", ": insn using ",
" : FAIL"), so they appear exactly once in .rodata. The call site only
carries the unique values as separate string-literal arguments, and the
linker can naturally dedup the operand names ("dst", "src", "imm", ...),
field descriptions ("field(0,3)", "bits<0>", ...), and decoder-method
names that recur thousands of times across emitted check sites.
Two debug prints that don't carry diagnostic value are dropped: the
PASS-side per-operand log (FAIL is the only message that helps when
chasing a decoder bug) and the per-attempt "attempting to decode
Opcode" log (redundant with the existing post-decode PASS/FAIL line).
Tests:
- DecoderEmitter and RegClassByHwMode TableGen tests updated.
- AArch64 MC lit test (aarch64-disassembler-debug.txt) feeds a
malformed `add (imm)` (with shift = 2; only 0 and 1 are legal) so
the generated decode table exercises the helpers end-to-end via
-debug-only=aarch64-disassembler.
Code-bloat measurements from the original single-helper landing
(tables in the prior commit message) predate this dedup refactor and
should be re-measured once we want a current snapshot.
Original work was authored partly via Cursor and partly via Claude;
this squashed commit consolidates both into a single change.
Assisted by Claude.
---
.../AArch64/aarch64-disassembler-debug.txt | 16 ++++
.../TableGen/DecoderEmitter/VarLenDecoder.td | 10 +-
.../DecoderEmitter/operand-decoder.td | 3 +-
.../DecoderEmitter/trydecode-emission.td | 3 +-
.../DecoderEmitter/trydecode-emission2.td | 6 +-
.../DecoderEmitter/trydecode-emission3.td | 4 +-
.../DecoderEmitter/trydecode-emission4.td | 3 +-
llvm/test/TableGen/RegClassByHwMode.td | 36 ++++++--
llvm/utils/TableGen/DecoderEmitter.cpp | 92 ++++++++++++++++---
9 files changed, 143 insertions(+), 30 deletions(-)
create mode 100644 llvm/test/MC/Disassembler/AArch64/aarch64-disassembler-debug.txt
diff --git a/llvm/test/MC/Disassembler/AArch64/aarch64-disassembler-debug.txt b/llvm/test/MC/Disassembler/AArch64/aarch64-disassembler-debug.txt
new file mode 100644
index 0000000000000..25aab52f0b945
--- /dev/null
+++ b/llvm/test/MC/Disassembler/AArch64/aarch64-disassembler-debug.txt
@@ -0,0 +1,16 @@
+# REQUIRES: asserts
+# RUN: llvm-mc -triple=aarch64 -mattr=+v8a -disassemble -debug-only=aarch64-disassembler < %s 2>&1 | FileCheck %s
+#
+# Exercises LLVM_DEBUG output from DecoderEmitter for dynamic bits like instruction operand.
+
+# blr x0 — valid; reaches per-operand checks and succeeds.
+# CHECK: OPC_Decode: opcode {{[0-9]+}} using decoder {{[0-9]+}}: PASS, decoding complete
+
+# Malformed `add (imm)` with `shift` field = 2 (only 0 and 1 are legal). The
+# whole-instruction decoder DecodeAddSubImmShift returns Fail, so the generated
+# table emits dbgFailInsn("ADDXri", "DecodeAddSubImmShift").
+# CHECK: OPC_Decode for ADDXri: insn using DecodeAddSubImmShift : FAIL
+# CHECK-NEXT: OPC_Decode: opcode {{[0-9]+}} using decoder {{[0-9]+}}: FAIL, decoding complete
+
+0x0 0x0 0x3f 0xd6
+0xe5 0x98 0x99 0x91
diff --git a/llvm/test/TableGen/DecoderEmitter/VarLenDecoder.td b/llvm/test/TableGen/DecoderEmitter/VarLenDecoder.td
index faac5cba4579f..0540bfc6e38eb 100644
--- a/llvm/test/TableGen/DecoderEmitter/VarLenDecoder.td
+++ b/llvm/test/TableGen/DecoderEmitter/VarLenDecoder.td
@@ -65,17 +65,17 @@ def FOO32 : MyVarInst<MemOp32> {
// CHECK: case 0:
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 8, 3);
-// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) return dbgFailOpd("opd", "field(8,3)", "DecodeRegClassRegisterClass");
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 0, 3);
-// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) return dbgFailOpd("opd", "field(0,3)", "DecodeRegClassRegisterClass");
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 11, 16);
-// CHECK-NEXT: if (!Check(S, myCustomDecoder(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, myCustomDecoder(MI, tmp, Address, Decoder))) return dbgFailOpd("opd", "field(11,16)", "myCustomDecoder");
// CHECK-NEXT: return S;
// CHECK-NEXT: case 1:
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 8, 3);
-// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) return dbgFailOpd("opd", "field(8,3)", "DecodeRegClassRegisterClass");
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 0, 3);
-// CHECK-NEXT: if (!Check(S, myCustomDecoder(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, myCustomDecoder(MI, tmp, Address, Decoder))) return dbgFailOpd("opd", "field(0,3)", "myCustomDecoder");
// CHECK-NEXT: tmp = 0x0;
// CHECK-NEXT: tmp |= fieldFromInstruction(insn, 11, 16) << 16;
// CHECK-NEXT: tmp |= fieldFromInstruction(insn, 27, 16);
diff --git a/llvm/test/TableGen/DecoderEmitter/operand-decoder.td b/llvm/test/TableGen/DecoderEmitter/operand-decoder.td
index c6ec2ee1a4db4..73f9c8e211768 100644
--- a/llvm/test/TableGen/DecoderEmitter/operand-decoder.td
+++ b/llvm/test/TableGen/DecoderEmitter/operand-decoder.td
@@ -12,8 +12,7 @@ def MyTarget : Target {
}
// CHECK-LABEL: case 0:
-// CHECK-NEXT: if (!Check(S, DecodeRCRegisterClass(MI, Decoder)))
-// CHECK-NEXT: return MCDisassembler::Fail;
+// CHECK-NEXT: if (!Check(S, DecodeRCRegisterClass(MI, Decoder))) return dbgFailOpd("op0", "bits<0>", "DecodeRCRegisterClass");
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 2, 4);
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
// CHECK-NEXT: tmp = 0x0;
diff --git a/llvm/test/TableGen/DecoderEmitter/trydecode-emission.td b/llvm/test/TableGen/DecoderEmitter/trydecode-emission.td
index a39f26a6e715a..75aaadce620f9 100644
--- a/llvm/test/TableGen/DecoderEmitter/trydecode-emission.td
+++ b/llvm/test/TableGen/DecoderEmitter/trydecode-emission.td
@@ -43,4 +43,5 @@ def InstB : TestInstruction {
// CHECK-NEXT: // 14: }
// CHECK-NEXT: };
-// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK-LABEL: case 0:
+// CHECK-NEXT: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) return dbgFailInsn("InstB", "DecodeInstB", &DecodeComplete);
diff --git a/llvm/test/TableGen/DecoderEmitter/trydecode-emission2.td b/llvm/test/TableGen/DecoderEmitter/trydecode-emission2.td
index 40d68061bfc0d..a676bb57104f4 100644
--- a/llvm/test/TableGen/DecoderEmitter/trydecode-emission2.td
+++ b/llvm/test/TableGen/DecoderEmitter/trydecode-emission2.td
@@ -42,5 +42,7 @@ def InstB : TestInstruction {
// CHECK-NEXT: // 22: }
// CHECK-NEXT: };
-// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
-// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK-LABEL: case 0:
+// CHECK-NEXT: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) return dbgFailInsn("InstB", "DecodeInstB", &DecodeComplete);
+// CHECK-LABEL: case 1:
+// CHECK-NEXT: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) return dbgFailInsn("InstA", "DecodeInstA", &DecodeComplete);
diff --git a/llvm/test/TableGen/DecoderEmitter/trydecode-emission3.td b/llvm/test/TableGen/DecoderEmitter/trydecode-emission3.td
index 2e2d1ddb8b8f6..f7ff58d307087 100644
--- a/llvm/test/TableGen/DecoderEmitter/trydecode-emission3.td
+++ b/llvm/test/TableGen/DecoderEmitter/trydecode-emission3.td
@@ -44,4 +44,6 @@ def InstB : TestInstruction {
// CHECK-NEXT: // 14: }
// CHECK-NEXT: };
-// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK-LABEL: case 0:
+// CHECK-NEXT: tmp = fieldFromInstruction(insn, 0, 2);
+// CHECK-NEXT: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) return dbgFailOpd("op", "field(0,2)", "DecodeInstBOp", &DecodeComplete);
diff --git a/llvm/test/TableGen/DecoderEmitter/trydecode-emission4.td b/llvm/test/TableGen/DecoderEmitter/trydecode-emission4.td
index bb0f658a037e8..5b54d70af70ba 100644
--- a/llvm/test/TableGen/DecoderEmitter/trydecode-emission4.td
+++ b/llvm/test/TableGen/DecoderEmitter/trydecode-emission4.td
@@ -42,4 +42,5 @@ def InstB : TestInstruction {
// CHECK-NEXT: // 16: }
// CHECK-NEXT: };
-// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK-LABEL: case 0:
+// CHECK-NEXT: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) return dbgFailInsn("InstB", "DecodeInstB", &DecodeComplete);
diff --git a/llvm/test/TableGen/RegClassByHwMode.td b/llvm/test/TableGen/RegClassByHwMode.td
index b7484d05e066c..a8a1135dba71f 100644
--- a/llvm/test/TableGen/RegClassByHwMode.td
+++ b/llvm/test/TableGen/RegClassByHwMode.td
@@ -144,6 +144,24 @@ include "Common/RegClassByHwModeCommon.td"
+// DISASM: DecodeStatus dbgFailOpd(const char *Op, const char *Desc, const char *Decoder,
+// DISASM-NEXT: bool *DecodeComplete = nullptr) {
+// DISASM-NEXT: LLVM_DEBUG(dbgs() << "OPC_Decode for " << Op << ": " << Desc << " using "
+// DISASM-NEXT: << Decoder << " : FAIL\n");
+// DISASM-NEXT: if (DecodeComplete)
+// DISASM-NEXT: *DecodeComplete = false;
+// DISASM-NEXT: return MCDisassembler::Fail;
+// DISASM-NEXT: }
+// DISASM-EMPTY:
+// DISASM-NEXT: DecodeStatus dbgFailInsn(const char *Name, const char *Decoder,
+// DISASM-NEXT: bool *DecodeComplete = nullptr) {
+// DISASM-NEXT: LLVM_DEBUG(dbgs() << "OPC_Decode for " << Name << ": insn using " << Decoder
+// DISASM-NEXT: << " : FAIL\n");
+// DISASM-NEXT: if (DecodeComplete)
+// DISASM-NEXT: *DecodeComplete = false;
+// DISASM-NEXT: return MCDisassembler::Fail;
+// DISASM-NEXT: }
+
// DISASM{LITERAL}: [[maybe_unused]]
// DISASM-NEXT: static DecodeStatus DecodeMyPtrRCRegClassByHwMode(MCInst &Inst, unsigned Imm, uint64_t Addr, const MCDisassembler *Decoder) {
// DISASM-NEXT: switch (Decoder->getSubtargetInfo().getHwMode(MCSubtargetInfo::HwMode_RegInfo)) {
@@ -185,19 +203,25 @@ include "Common/RegClassByHwModeCommon.td"
// DISASM: static DecodeStatus decodeToMCInst(
// DISASM: switch (Idx) {
// DISASM: case 0:
-// DISASM: if (!Check(S, DecodeYRegs_EvenIfRequiredRegClassByHwMode(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
-// DISASM: if (!Check(S, DecodeXRegs_EvenIfRequiredRegClassByHwMode(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// DISASM: tmp = fieldFromInstruction(insn, 0, 3);
+// DISASM: if (!Check(S, DecodeYRegs_EvenIfRequiredRegClassByHwMode(MI, tmp, Address, Decoder))) return dbgFailOpd("dst", "field(0,3)", "DecodeYRegs_EvenIfRequiredRegClassByHwMode");
+// DISASM: tmp = fieldFromInstruction(insn, 3, 2);
+// DISASM: if (!Check(S, DecodeXRegs_EvenIfRequiredRegClassByHwMode(MI, tmp, Address, Decoder))) return dbgFailOpd("src", "field(3,2)", "DecodeXRegs_EvenIfRequiredRegClassByHwMode");
// DISASM: case 1:
-// DISASM: if (!Check(S, DecodeXRegs_EvenIfRequiredRegClassByHwMode(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// DISASM: tmp = fieldFromInstruction(insn, 3, 2);
+// DISASM: if (!Check(S, DecodeXRegs_EvenIfRequiredRegClassByHwMode(MI, tmp, Address, Decoder))) return dbgFailOpd("src", "field(3,2)", "DecodeXRegs_EvenIfRequiredRegClassByHwMode");
// DISASM: case 2:
-// DISASM: if (!Check(S, DecodeXRegs_EvenRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// DISASM: tmp = fieldFromInstruction(insn, 3, 2);
+// DISASM: if (!Check(S, DecodeXRegs_EvenRegisterClass(MI, tmp, Address, Decoder))) return dbgFailOpd("src", "field(3,2)", "DecodeXRegs_EvenRegisterClass");
// DISASM: case 3:
-// DISASM: if (!Check(S, DecodeXRegsRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// DISASM: tmp = fieldFromInstruction(insn, 3, 2);
+// DISASM: if (!Check(S, DecodeXRegsRegisterClass(MI, tmp, Address, Decoder))) return dbgFailOpd("src", "field(3,2)", "DecodeXRegsRegisterClass");
// DISASM: case 4:
-// DISASM: if (!Check(S, YEvenIfRequiredCustomDecoder(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
+// DISASM: tmp = fieldFromInstruction(insn, 3, 2);
+// DISASM: if (!Check(S, YEvenIfRequiredCustomDecoder(MI, tmp, Address, Decoder))) return dbgFailOpd("src", "field(3,2)", "YEvenIfRequiredCustomDecoder");
// ISEL-SDAG: MatcherTable
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index f8ebdfccda46f..b0a2b03ee9cf9 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -683,6 +683,61 @@ static std::vector<EncodingIsland> getIslands(const KnownBits &EncodingBits,
return Islands;
}
+static std::string getOperandFieldDescForDebug(const OperandInfo &OpInfo) {
+ if (OpInfo.Fields.empty() && !OpInfo.InitValue)
+ return "bits<0>";
+ if (OpInfo.Fields.empty())
+ return "imm";
+ std::string S;
+ raw_string_ostream OS(S);
+ ListSeparator LS(" + ");
+ for (const auto &EF : OpInfo.Fields)
+ OS << LS << formatv("field({},{})", EF.Base, EF.Width);
+ return S;
+}
+
+/// Emit `if (!Check(...)) return <Helper>(<Args>[, &DecodeComplete]);`. The
+/// connector strings (": ", " using ", " : FAIL") live once inside the helper
+/// rather than being baked into every per-site string literal, so each call
+/// site only carries the unique parts (op name, field desc, decoder name) as
+/// separate string arguments — letting the linker dedup them.
+static void emitCheckWithDbgMsg(raw_ostream &OS, indent Indent,
+ const Twine &CheckCall, StringRef Helper,
+ const Twine &Args,
+ bool SetDecodeCompleteOnFail) {
+ OS << Indent << "if (!Check(S, " << CheckCall << ")) return " << Helper
+ << "(" << Args;
+ if (SetDecodeCompleteOnFail)
+ OS << ", &DecodeComplete";
+ OS << ");\n";
+}
+
+/// Operand-level decoder (emitBinaryParser).
+static void emitDecoderCheckWithOpcDebug(raw_ostream &OS, indent Indent,
+ const OperandInfo &OpInfo,
+ const Twine &CheckCall) {
+ StringRef OpName = OpInfo.Name.empty() ? "opd" : OpInfo.Name;
+ std::string FieldDesc = getOperandFieldDescForDebug(OpInfo);
+ StringRef DecoderName = OpInfo.Decoder;
+
+ emitCheckWithDbgMsg(
+ OS, Indent, CheckCall, "dbgFailOpd",
+ formatv("\"{}\", \"{}\", \"{}\"", OpName, FieldDesc, DecoderName),
+ !OpInfo.HasCompleteDecoder);
+}
+
+/// Whole-instruction \p DecoderMethod. Used when the encoding
+/// has a custom \p DecoderMethod (whole-instruction decoder).
+static void emitDecoderMethodOpcDebug(raw_ostream &OS, indent Indent,
+ const InstructionEncoding &Encoding,
+ StringRef DecoderMethod) {
+ StringRef EncName = Encoding.getName();
+ emitCheckWithDbgMsg(
+ OS, Indent, formatv("{}(MI, insn, Address, Decoder)", DecoderMethod),
+ "dbgFailInsn", formatv("\"{}\", \"{}\"", EncName, DecoderMethod),
+ !Encoding.hasCompleteDecoder());
+}
+
static void emitBinaryParser(raw_ostream &OS, indent Indent,
const InstructionEncoding &Encoding,
const OperandInfo &OpInfo) {
@@ -702,8 +757,8 @@ static void emitBinaryParser(raw_ostream &OS, indent Indent,
// The operand has no encoding, so the corresponding argument is omitted.
// This avoids confusion and allows the function to be overloaded if the
// operand does have an encoding in other instructions.
- OS << Indent << "if (!Check(S, " << OpInfo.Decoder << "(MI, Decoder)))\n"
- << Indent << " return MCDisassembler::Fail;\n";
+ emitDecoderCheckWithOpcDebug(OS, Indent, OpInfo,
+ formatv("{}(MI, Decoder)", OpInfo.Decoder));
return;
}
@@ -738,10 +793,8 @@ static void emitBinaryParser(raw_ostream &OS, indent Indent,
StringRef Decoder = OpInfo.Decoder;
if (!Decoder.empty()) {
- OS << Indent << "if (!Check(S, " << Decoder
- << "(MI, tmp, Address, Decoder))) { "
- << (OpInfo.HasCompleteDecoder ? "" : "DecodeComplete = false; ")
- << "return MCDisassembler::Fail; }\n";
+ emitDecoderCheckWithOpcDebug(
+ OS, Indent, OpInfo, formatv("{}(MI, tmp, Address, Decoder)", Decoder));
} else {
OS << Indent << "MI.addOperand(MCOperand::createImm(tmp));\n";
}
@@ -755,10 +808,7 @@ static std::string getDecoderString(const InstructionEncoding &Encoding) {
// If a custom instruction decoder was specified, use that.
StringRef DecoderMethod = Encoding.getDecoderMethod();
if (!DecoderMethod.empty()) {
- OS << Indent << "if (!Check(S, " << DecoderMethod
- << "(MI, insn, Address, Decoder))) { "
- << (Encoding.hasCompleteDecoder() ? "" : "DecodeComplete = false; ")
- << "return MCDisassembler::Fail; }\n";
+ emitDecoderMethodOpcDebug(OS, Indent, Encoding, DecoderMethod);
} else {
for (const OperandInfo &Op : Encoding.getOperands())
emitBinaryParser(OS, Indent, Encoding, Op);
@@ -1184,8 +1234,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
S = decodeToMCInst(DecodeIdx, S, insn, MI, Address, DisAsm,
DecodeComplete);
LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
- << ", using decoder " << DecodeIdx << ": "
- << (S ? "PASS, " : "FAIL, "));
+ << " using decoder " << DecodeIdx
+ << ": " << (S ? "PASS, " : "FAIL, "));
if (DecodeComplete) {
LLVM_DEBUG(dbgs() << "decoding complete\n");
@@ -1517,6 +1567,24 @@ namespace {
// on their usage.
template <typename T> constexpr uint32_t InsnBitWidth = 0;
+DecodeStatus dbgFailOpd(const char *Op, const char *Desc, const char *Decoder,
+ bool *DecodeComplete = nullptr) {
+ LLVM_DEBUG(dbgs() << "OPC_Decode for " << Op << ": " << Desc << " using "
+ << Decoder << " : FAIL\n");
+ if (DecodeComplete)
+ *DecodeComplete = false;
+ return MCDisassembler::Fail;
+}
+
+DecodeStatus dbgFailInsn(const char *Name, const char *Decoder,
+ bool *DecodeComplete = nullptr) {
+ LLVM_DEBUG(dbgs() << "OPC_Decode for " << Name << ": insn using " << Decoder
+ << " : FAIL\n");
+ if (DecodeComplete)
+ *DecodeComplete = false;
+ return MCDisassembler::Fail;
+}
+
)";
// Do extra bookkeeping for variable-length encodings.
More information about the llvm-commits
mailing list