[llvm] [LLVM][MC] Introduce `OrFail` variants of MCD ops (PR #138614)
Rahul Joshi via llvm-commits
llvm-commits at lists.llvm.org
Wed May 7 09:55:54 PDT 2025
https://github.com/jurahul updated https://github.com/llvm/llvm-project/pull/138614
>From fb647574ea63060207de45c87865fd3f4f2b62f3 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Wed, 30 Apr 2025 06:46:29 -0700
Subject: [PATCH] [LLVM][MC] Introduce `OrFail` variants of MCD ops
---
llvm/include/llvm/MC/MCDecoderOps.h | 33 +--
llvm/lib/Target/AArch64/CMakeLists.txt | 2 +-
llvm/test/TableGen/VarLenDecoder.td | 21 +-
llvm/test/TableGen/trydecode-emission.td | 20 +-
llvm/test/TableGen/trydecode-emission2.td | 32 +--
llvm/test/TableGen/trydecode-emission3.td | 20 +-
llvm/test/TableGen/trydecode-emission4.td | 20 +-
llvm/utils/TableGen/DecoderEmitter.cpp | 253 +++++++++++++++-------
8 files changed, 249 insertions(+), 152 deletions(-)
diff --git a/llvm/include/llvm/MC/MCDecoderOps.h b/llvm/include/llvm/MC/MCDecoderOps.h
index 3c0b68101e346..29d62988e888e 100644
--- a/llvm/include/llvm/MC/MCDecoderOps.h
+++ b/llvm/include/llvm/MC/MCDecoderOps.h
@@ -10,24 +10,29 @@
#ifndef LLVM_MC_MCDECODEROPS_H
#define LLVM_MC_MCDECODEROPS_H
-namespace llvm {
+namespace llvm::MCD {
-namespace MCD {
// Disassembler state machine opcodes.
+// nts_t is either uint16_t or uint24_t based on whether large decoder table is
+// enabled.
enum DecoderOps {
- OPC_ExtractField = 1, // OPC_ExtractField(uleb128 Start, uint8_t Len)
- OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip)
- OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len,
- // uleb128 Val, uint16_t NumToSkip)
- OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip)
- OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
- OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx,
- // uint16_t NumToSkip)
- OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
- OPC_Fail // OPC_Fail()
+ OPC_ExtractField = 1, // OPC_ExtractField(uleb128 Start, uint8_t Len)
+ OPC_FilterValue, // OPC_FilterValue(uleb128 Val, nts_t NumToSkip)
+ OPC_FilterValueOrFail, // OPC_FilterValueOrFail(uleb128 Val)
+ OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len,
+ // uleb128 Val, nts_t NumToSkip)
+ OPC_CheckFieldOrFail, // OPC_ChecFieldOrFail(uleb128 Start, uint8_t Len,
+ // uleb128 Val)
+ OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, nts_t NumToSkip)
+ OPC_CheckPredicateOrFail, // OPC_CheckPredicateOrFail(uleb128 PIdx)
+ OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
+ OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx,
+ // nts_t NumToSkip)
+ OPC_TryDecodeOrFail, // OPC_TryDecodeOrFail(uleb128 Opcode, uleb128 DIdx)
+ OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
+ OPC_Fail // OPC_Fail()
};
-} // namespace MCD
-} // namespace llvm
+} // namespace llvm::MCD
#endif
diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt
index 583003f2f46e6..8c3e0f997fc31 100644
--- a/llvm/lib/Target/AArch64/CMakeLists.txt
+++ b/llvm/lib/Target/AArch64/CMakeLists.txt
@@ -8,7 +8,7 @@ tablegen(LLVM AArch64GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
tablegen(LLVM AArch64GenCallingConv.inc -gen-callingconv)
tablegen(LLVM AArch64GenDAGISel.inc -gen-dag-isel)
tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler
- --large-decoder-table)
+ )
tablegen(LLVM AArch64GenFastISel.inc -gen-fast-isel)
tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel)
tablegen(LLVM AArch64GenO0PreLegalizeGICombiner.inc -gen-global-isel-combiner
diff --git a/llvm/test/TableGen/VarLenDecoder.td b/llvm/test/TableGen/VarLenDecoder.td
index db7a520533e85..06ff62294a196 100644
--- a/llvm/test/TableGen/VarLenDecoder.td
+++ b/llvm/test/TableGen/VarLenDecoder.td
@@ -47,19 +47,19 @@ def FOO32 : MyVarInst<MemOp32> {
);
}
-// CHECK-SMALL: MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
-// CHECK-SMALL-NEXT: MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
-// CHECK-SMALL-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
-// CHECK-SMALL-NEXT: MCD::OPC_FilterValue, 9, 4, 0, // Skip to: 19
-// CHECK-SMALL-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
-// CHECK-SMALL-NEXT: MCD::OPC_Fail,
+// CHECK-SMALL: /* 0 */ MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
+// CHECK-SMALL-NEXT: /* 3 */ MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
+// CHECK-SMALL-NEXT: /* 7 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
+// CHECK-SMALL-NEXT: /* 11 */ MCD::OPC_FilterValueOrFail, 9,
+// CHECK-SMALL-NEXT: /* 13 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
+// CHECK-SMALL-NEXT: /* 17 */ MCD::OPC_Fail,
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 8, 4, 0, 0, // Skip to: 12
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
-// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_FilterValue, 9, 4, 0, 0, // Skip to: 21
-// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
-// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Fail,
+// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_FilterValueOrFail, 9,
+// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
+// CHECK-LARGE-NEXT: /* 18 */ MCD::OPC_Fail,
// Instruction length table
// CHECK: 27,
@@ -88,7 +88,8 @@ def FOO32 : MyVarInst<MemOp32> {
// CHECK-LABEL: case MCD::OPC_ExtractField: {
// CHECK: makeUp(insn, Start + Len);
-// CHECK-LABEL: case MCD::OPC_CheckField: {
+// CHECK-LABEL: case MCD::OPC_CheckField:
+// CHECK-NEXT: case MCD::OPC_CheckFieldOrFail: {
// CHECK: makeUp(insn, Start + Len);
// CHECK-LABEL: case MCD::OPC_Decode: {
diff --git a/llvm/test/TableGen/trydecode-emission.td b/llvm/test/TableGen/trydecode-emission.td
index db77d94b2aa52..47d47c9c96183 100644
--- a/llvm/test/TableGen/trydecode-emission.td
+++ b/llvm/test/TableGen/trydecode-emission.td
@@ -35,11 +35,11 @@ def InstB : TestInstruction {
}
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, // Skip to: 23
-// CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 19
-// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 19
-// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
+// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 17
+// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-NEXT: /* 21 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
@@ -48,11 +48,11 @@ def InstB : TestInstruction {
// CHECK-NEXT: return NumToSkip;
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
-// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
-// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
-// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_Fail,
+// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
+// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 19
+// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_Fail,
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission2.td b/llvm/test/TableGen/trydecode-emission2.td
index 914e17c6f820c..593da63cd7616 100644
--- a/llvm/test/TableGen/trydecode-emission2.td
+++ b/llvm/test/TableGen/trydecode-emission2.td
@@ -32,27 +32,27 @@ def InstB : TestInstruction {
}
// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 31, 0, // Skip to: 38
-// CHECK-NEXT: /* 7 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
-// CHECK-NEXT: /* 10 */ MCD::OPC_FilterValue, 0, 24, 0, // Skip to: 38
-// CHECK-NEXT: /* 14 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 26
-// CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 26
-// CHECK-NEXT: /* 26 */ MCD::OPC_CheckField, 3, 2, 0, 6, 0, // Skip to: 38
-// CHECK-NEXT: /* 32 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, // Opcode: InstA, skip to: 38
-// CHECK-NEXT: /* 38 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
+// CHECK-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0
+// CHECK-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 22
+// CHECK-NEXT: /* 16 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 22
+// CHECK-NEXT: /* 22 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
+// CHECK-NEXT: /* 26 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
+// CHECK-NEXT: /* 30 */ MCD::OPC_Fail,
// 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-LARGE: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
-// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 36, 0, 0, // Skip to: 44
-// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
-// CHECK-LARGE-NEXT: /* 11 */ MCD::OPC_FilterValue, 0, 28, 0, 0, // Skip to: 44
-// CHECK-LARGE-NEXT: /* 16 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 30
-// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 30
-// CHECK-LARGE-NEXT: /* 30 */ MCD::OPC_CheckField, 3, 2, 0, 7, 0, 0, // Skip to: 44
-// CHECK-LARGE-NEXT: /* 37 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, 0, // Opcode: InstA, skip to: 44
-// CHECK-LARGE-NEXT: /* 44 */ MCD::OPC_Fail,
+// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
+// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-LARGE-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 24
+// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 24
+// CHECK-LARGE-NEXT: /* 24 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
+// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
+// CHECK-LARGE-NEXT: /* 32 */ MCD::OPC_Fail,
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK-LARGE: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission3.td b/llvm/test/TableGen/trydecode-emission3.td
index 141dc5439ca13..e2b739d8338de 100644
--- a/llvm/test/TableGen/trydecode-emission3.td
+++ b/llvm/test/TableGen/trydecode-emission3.td
@@ -36,19 +36,19 @@ def InstB : TestInstruction {
}
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, // Skip to: 23
-// CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 19
-// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 19
-// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
+// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 17
+// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-NEXT: /* 21 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
-// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
-// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
-// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_Fail,
+// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
+// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 19
+// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_Fail,
// CHECK-LARGE: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission4.td b/llvm/test/TableGen/trydecode-emission4.td
index bb44876e77f02..39a3187c38bda 100644
--- a/llvm/test/TableGen/trydecode-emission4.td
+++ b/llvm/test/TableGen/trydecode-emission4.td
@@ -34,21 +34,21 @@ def InstB : TestInstruction {
}
// CHECK: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
-// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValue, 0, 17, 0, // Skip to: 25
-// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 21
-// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 21
-// CHECK-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-NEXT: /* 25 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 19
+// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 19
+// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
-// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_FilterValue, 0, 19, 0, 0, // Skip to: 28
-// CHECK-LARGE-NEXT: /* 9 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 24
-// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 24
-// CHECK-LARGE-NEXT: /* 24 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_Fail,
+// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
+// CHECK-LARGE-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 21
+// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 21
+// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-LARGE-NEXT: /* 25 */ MCD::OPC_Fail,
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index eb3b30018da8a..2d6048be52d9a 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -91,9 +91,9 @@ STATISTIC(NumInstructions, "Number of instructions considered");
STATISTIC(NumEncodingsSupported, "Number of encodings supported");
STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
-namespace {
+static unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; }
-unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; }
+namespace {
struct EncodingField {
unsigned Base, Width, Offset;
@@ -183,6 +183,8 @@ struct DecoderTableInfo {
FixupScopeList FixupStack;
PredicateSet Predicates;
DecoderSet Decoders;
+
+ bool isOutermostScope() const { return FixupStack.size() == 1; }
};
struct EncodingAndInst {
@@ -778,11 +780,21 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
PrevFilter = 0; // Don't re-process the filter's fallthrough.
} else {
- Table.push_back(MCD::OPC_FilterValue);
+ // The last filtervalue emitted can be OPC_FilterValue if we are at
+ // outermost scope.
+ const uint8_t DecoderOp =
+ FilterVal == LastFilter && TableInfo.isOutermostScope()
+ ? MCD::OPC_FilterValueOrFail
+ : MCD::OPC_FilterValue;
+ Table.push_back(DecoderOp);
Table.insertULEB128(FilterVal);
- // Reserve space for the NumToSkip entry. We'll backpatch the value
- // later.
- PrevFilter = Table.insertNumToSkip();
+ if (DecoderOp == MCD::OPC_FilterValue) {
+ // Reserve space for the NumToSkip entry. We'll backpatch the value
+ // later.
+ PrevFilter = Table.insertNumToSkip();
+ } else {
+ PrevFilter = 0;
+ }
}
// We arrive at a category of instructions with the same segment value.
@@ -797,9 +809,10 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
Table.patchNumToSkip(PrevFilter, Table.size());
}
- // If there is no fallthrough, then the final filter should get fixed
- // up according to the enclosing scope rather than the current position.
- if (!HasFallthrough)
+ // If there is no fallthrough and the final filter was not in the outermost
+ // scope, then it must be fixed up according to the enclosing scope rather
+ // than the current position.
+ if (PrevFilter)
TableInfo.FixupStack.back().push_back(PrevFilter);
}
@@ -864,6 +877,15 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
DecoderTable::const_iterator I = Table.begin();
DecoderTable::const_iterator E = Table.end();
const uint8_t *const EndPtr = Table.data() + Table.size();
+
+ auto emitNumToSkipComment = [&](uint32_t NumToSkip, bool InComment = false) {
+ uint32_t Index = ((I - Table.begin()) + NumToSkip);
+ OS << (InComment ? ", " : "// ");
+ OS << "Skip to: " << Index;
+ if (*(I + NumToSkip) == MCD::OPC_Fail)
+ OS << " (Fail)";
+ };
+
while (I != E) {
assert(I < E && "incomplete decode table entry!");
@@ -874,7 +896,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
const uint8_t DecoderOp = *I++;
switch (DecoderOp) {
default:
- PrintFatalError("Invalid decode table opcode: " + Twine(DecoderOp));
+ PrintFatalError("Invalid decode table opcode: " + Twine((int)DecoderOp) +
+ " at index " + Twine(Pos));
case MCD::OPC_ExtractField: {
OS << Indent << "MCD::OPC_ExtractField, ";
@@ -891,17 +914,24 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << Start << "} ...\n";
break;
}
- case MCD::OPC_FilterValue: {
- OS << Indent << "MCD::OPC_FilterValue, ";
+ case MCD::OPC_FilterValue:
+ case MCD::OPC_FilterValueOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail;
+ OS << Indent << "MCD::OPC_FilterValue" << (IsFail ? "OrFail, " : ", ");
// The filter value is ULEB128 encoded.
emitULEB128(I, OS);
- uint32_t NumToSkip = emitNumToSkip(I, OS);
- OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ if (!IsFail) {
+ uint32_t NumToSkip = emitNumToSkip(I, OS);
+ emitNumToSkipComment(NumToSkip);
+ }
+ OS << '\n';
break;
}
- case MCD::OPC_CheckField: {
- OS << Indent << "MCD::OPC_CheckField, ";
+ case MCD::OPC_CheckField:
+ case MCD::OPC_CheckFieldOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail;
+ OS << Indent << "MCD::OPC_CheckField" << (IsFail ? "OrFail, " : ", ");
// ULEB128 encoded start value.
emitULEB128(I, OS);
// 8-bit length.
@@ -910,27 +940,39 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// ULEB128 encoded field value.
emitULEB128(I, OS);
- uint32_t NumToSkip = emitNumToSkip(I, OS);
- OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ if (!IsFail) {
+ uint32_t NumToSkip = emitNumToSkip(I, OS);
+ emitNumToSkipComment(NumToSkip);
+ }
+ OS << '\n';
break;
}
- case MCD::OPC_CheckPredicate: {
- OS << Indent << "MCD::OPC_CheckPredicate, ";
+ case MCD::OPC_CheckPredicate:
+ case MCD::OPC_CheckPredicateOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
+
+ OS << Indent << "MCD::OPC_CheckPredicate" << (IsFail ? "OrFail, " : ", ");
emitULEB128(I, OS);
- uint32_t NumToSkip = emitNumToSkip(I, OS);
- OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ if (!IsFail) {
+ uint32_t NumToSkip = emitNumToSkip(I, OS);
+ emitNumToSkipComment(NumToSkip);
+ }
+ OS << '\n';
break;
}
case MCD::OPC_Decode:
- case MCD::OPC_TryDecode: {
- bool IsTry = DecoderOp == MCD::OPC_TryDecode;
+ case MCD::OPC_TryDecode:
+ case MCD::OPC_TryDecodeOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
+ bool IsTry = DecoderOp == MCD::OPC_TryDecode || IsFail;
// Decode the Opcode value.
const char *ErrMsg = nullptr;
unsigned Opc = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
assert(ErrMsg == nullptr && "ULEB128 value too large!");
- OS << Indent << "MCD::OPC_" << (IsTry ? "Try" : "") << "Decode, ";
+ OS << Indent << "MCD::OPC_" << (IsTry ? "Try" : "") << "Decode"
+ << (IsFail ? "OrFail, " : ", ");
emitULEB128(I, OS);
// Decoder index.
@@ -947,10 +989,14 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// Fallthrough for OPC_TryDecode.
- uint32_t NumToSkip = emitNumToSkip(I, OS);
-
- OS << "// Opcode: " << NumberedEncodings[EncodingID]
- << ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ if (!IsFail) {
+ uint32_t NumToSkip = emitNumToSkip(I, OS);
+ OS << "// Opcode: " << NumberedEncodings[EncodingID];
+ emitNumToSkipComment(NumToSkip, /*InComment=*/true);
+ } else {
+ OS << "// Opcode: " << NumberedEncodings[EncodingID];
+ }
+ OS << '\n';
break;
}
case MCD::OPC_SoftFail: {
@@ -972,11 +1018,10 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << '\n';
break;
}
- case MCD::OPC_Fail: {
+ case MCD::OPC_Fail:
OS << Indent << "MCD::OPC_Fail,\n";
break;
}
- }
}
OS << Indent << "0\n";
@@ -1338,11 +1383,16 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
// computed.
unsigned PIdx = getPredicateIndex(TableInfo, PS.str());
- TableInfo.Table.push_back(MCD::OPC_CheckPredicate);
+ const uint8_t DecoderOp = TableInfo.isOutermostScope()
+ ? MCD::OPC_CheckPredicateOrFail
+ : MCD::OPC_CheckPredicate;
+ TableInfo.Table.push_back(DecoderOp);
TableInfo.Table.insertULEB128(PIdx);
- // Push location for NumToSkip backpatching.
- TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
+ if (DecoderOp == MCD::OPC_CheckPredicate) {
+ // Push location for NumToSkip backpatching.
+ TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
+ }
}
void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
@@ -1412,17 +1462,22 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
for (const Island &Ilnd : reverse(Islands)) {
unsigned NumBits = Ilnd.NumBits;
assert(isUInt<8>(NumBits) && "NumBits overflowed uint8 table entry!");
- TableInfo.Table.push_back(MCD::OPC_CheckField);
+ const uint8_t DecoderOp = TableInfo.isOutermostScope()
+ ? MCD::OPC_CheckFieldOrFail
+ : MCD::OPC_CheckField;
+ TableInfo.Table.push_back(DecoderOp);
TableInfo.Table.insertULEB128(Ilnd.StartBit);
TableInfo.Table.push_back(NumBits);
TableInfo.Table.insertULEB128(Ilnd.FieldVal);
- // Allocate space in the table for fixup so all our relative position
- // calculations work OK even before we fully resolve the real value here.
+ if (DecoderOp == MCD::OPC_CheckField) {
+ // Allocate space in the table for fixup so all our relative position
+ // calculations work OK even before we fully resolve the real value here.
- // Push location for NumToSkip backpatching.
- TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
+ // Push location for NumToSkip backpatching.
+ TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
+ }
}
// Check for soft failure of the match.
@@ -1440,13 +1495,16 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
// decoder method indicates that additional processing should be done to see
// if there is any other instruction that also matches the bitpattern and
// can decode it.
- TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode
- : MCD::OPC_TryDecode);
+ const uint8_t DecoderOp = HasCompleteDecoder ? MCD::OPC_Decode
+ : (TableInfo.isOutermostScope()
+ ? MCD::OPC_TryDecodeOrFail
+ : MCD::OPC_TryDecode);
+ TableInfo.Table.push_back(DecoderOp);
NumEncodingsSupported++;
TableInfo.Table.insertULEB128(Opc.Opcode);
TableInfo.Table.insertULEB128(DIdx);
- if (!HasCompleteDecoder) {
+ if (DecoderOp == MCD::OPC_TryDecode) {
// Push location for NumToSkip backpatching.
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
}
@@ -2188,7 +2246,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
DecodeStatus S = MCDisassembler::Success;
while (true) {
ptrdiff_t Loc = Ptr - DecodeTable;
- switch (*Ptr++) {
+ const uint8_t DecoderOp = *Ptr++;
+ switch (DecoderOp) {
default:
errs() << Loc << ": Unexpected decode table opcode!\n";
return MCDisassembler::Fail;
@@ -2204,22 +2263,34 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
<< Len << "): " << CurFieldValue << "\n");
break;
}
- case MCD::OPC_FilterValue: {
+ case MCD::OPC_FilterValue:
+ case MCD::OPC_FilterValueOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail;
// Decode the field value.
uint64_t Val = decodeULEB128AndIncUnsafe(Ptr);
bool Failed = Val != CurFieldValue;
- unsigned NumToSkip = decodeNumToSkip(Ptr);
+ unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
+
+ // Note: Print NumToSkip even for OPC_FilterValueOrFail to simplify debug
+ // prints.
+ LLVM_DEBUG({
+ StringRef OpName = IsFail ? "OPC_FilterValueOrFail" : "OPC_FilterValue";
+ dbgs() << Loc << ": " << OpName << '(' << Val << ", " << NumToSkip
+ << ") " << (Failed ? "FAIL:" : "PASS:")
+ << " continuing at " << (Ptr - DecodeTable) << '\n';
+ });
// Perform the filter operation.
- if (Failed)
+ if (Failed) {
+ if (IsFail)
+ return MCDisassembler::Fail;
Ptr += NumToSkip;
- LLVM_DEBUG(dbgs() << Loc << ": OPC_FilterValue(" << Val << ", " << NumToSkip
- << "): " << (Failed ? "FAIL:" : "PASS:")
- << " continuing at " << (Ptr - DecodeTable) << "\n");
-
+ }
break;
}
- case MCD::OPC_CheckField: {
+ case MCD::OPC_CheckField:
+ case MCD::OPC_CheckFieldOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail;
// Decode the start value.
unsigned Start = decodeULEB128AndIncUnsafe(Ptr);
unsigned Len = *Ptr;)";
@@ -2232,29 +2303,44 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);
Ptr += PtrLen;
bool Failed = ExpectedValue != FieldValue;
- unsigned NumToSkip = decodeNumToSkip(Ptr);
-
- // If the actual and expected values don't match, skip.
- if (Failed)
+ unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
+
+ LLVM_DEBUG({
+ StringRef OpName = IsFail ? "OPC_CheckFieldOrFail" : "OPC_CheckField";
+ dbgs() << Loc << ": " << OpName << '(' << Start << ", " << Len << ", "
+ << ExpectedValue << ", " << NumToSkip << "): FieldValue = "
+ << FieldValue << ", ExpectedValue = " << ExpectedValue << ": "
+ << (Failed ? "FAIL\n" : "PASS\n");
+ });
+
+ // If the actual and expected values don't match, skip or fail.
+ if (Failed) {
+ if (IsFail)
+ return MCDisassembler::Fail;
Ptr += NumToSkip;
- LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckField(" << Start << ", "
- << Len << ", " << ExpectedValue << ", " << NumToSkip
- << "): FieldValue = " << FieldValue << ", ExpectedValue = "
- << ExpectedValue << ": "
- << (Failed ? "FAIL\n" : "PASS\n"));
+ }
break;
}
- case MCD::OPC_CheckPredicate: {
+ case MCD::OPC_CheckPredicate:
+ case MCD::OPC_CheckPredicateOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
// Decode the Predicate Index value.
unsigned PIdx = decodeULEB128AndIncUnsafe(Ptr);
- unsigned NumToSkip = decodeNumToSkip(Ptr);
+ unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
// Check the predicate.
bool Failed = !checkDecoderPredicate(PIdx, Bits);
- if (Failed)
- Ptr += NumToSkip;
- LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckPredicate(" << PIdx << "): "
- << (Failed ? "FAIL\n" : "PASS\n"));
+ LLVM_DEBUG({
+ StringRef OpName = IsFail ? "OPC_CheckPredicateOrFail" : "OPC_CheckPredicate";
+ dbgs() << Loc << ": " << OpName << '(' << PIdx << ", " << NumToSkip
+ << "): " << (Failed ? "FAIL\n" : "PASS\n");
+ });
+
+ if (Failed) {
+ if (IsFail)
+ return MCDisassembler::Fail;
+ Ptr += NumToSkip;
+ }
break;
}
case MCD::OPC_Decode: {
@@ -2275,14 +2361,16 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
<< ", using decoder " << DecodeIdx << ": "
- << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n");
+ << (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
return S;
}
- case MCD::OPC_TryDecode: {
+ case MCD::OPC_TryDecode:
+ case MCD::OPC_TryDecodeOrFail: {
+ bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
// Decode the Opcode value.
unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
- unsigned NumToSkip = decodeNumToSkip(Ptr);
+ unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
// Perform the decode operation.
MCInst TmpMI;
@@ -2294,28 +2382,31 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
if (DecodeComplete) {
// Decoding complete.
- LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n");
+ LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
MI = TmpMI;
return S;
- } else {
- assert(S == MCDisassembler::Fail);
- // If the decoding was incomplete, skip.
- Ptr += NumToSkip;
- LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n");
- // Reset decode status. This also drops a SoftFail status that could be
- // set before the decode attempt.
- S = MCDisassembler::Success;
}
+ assert(S == MCDisassembler::Fail);
+ if (IsFail) {
+ LLVM_DEBUG(dbgs() << "FAIL: returning FAIL\n");
+ return MCDisassembler::Fail;
+ }
+ // If the decoding was incomplete, skip.
+ Ptr += NumToSkip;
+ LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n");
+ // Reset decode status. This also drops a SoftFail status that could be
+ // set before the decode attempt.
+ S = MCDisassembler::Success;
break;
}
case MCD::OPC_SoftFail: {
// Decode the mask values.
uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
- bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
- if (Fail)
+ bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
+ if (Failed)
S = MCDisassembler::SoftFail;
- LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Fail ? "FAIL\n" : "PASS\n"));
+ LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n"));
break;
}
case MCD::OPC_Fail: {
More information about the llvm-commits
mailing list