[llvm] [MC][Decoder] Cull decoder cases (PR #154775)
Rahul Joshi via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 21 07:51:49 PDT 2025
https://github.com/jurahul updated https://github.com/llvm/llvm-project/pull/154775
>From f98fe9a29c69a3188d3964159bec79834e8416d9 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Thu, 21 Aug 2025 04:49:06 -0700
Subject: [PATCH] [MC][Decoder] Cull decoder cases
---
llvm/include/llvm/MC/MCDecoder.h | 88 +++++++++++++++
llvm/include/llvm/MC/MCDecoderOps.h | 4 +-
llvm/include/llvm/Target/Target.td | 7 ++
.../Disassembler/AArch64Disassembler.cpp | 2 +
llvm/lib/Target/AMDGPU/AMDGPU.td | 1 +
.../Disassembler/AMDGPUDisassembler.cpp | 31 +++---
.../AMDGPU/Disassembler/AMDGPUDisassembler.h | 38 -------
.../ARC/Disassembler/ARCDisassembler.cpp | 2 +
.../ARM/Disassembler/ARMDisassembler.cpp | 2 +
.../AVR/Disassembler/AVRDisassembler.cpp | 2 +
.../BPF/Disassembler/BPFDisassembler.cpp | 1 +
.../CSKY/Disassembler/CSKYDisassembler.cpp | 1 +
.../Disassembler/HexagonDisassembler.cpp | 1 +
.../Lanai/Disassembler/LanaiDisassembler.cpp | 1 +
.../Disassembler/LoongArchDisassembler.cpp | 1 +
.../M68k/Disassembler/M68kDisassembler.cpp | 2 +
.../Disassembler/MSP430Disassembler.cpp | 2 +
.../Mips/Disassembler/MipsDisassembler.cpp | 2 +
.../PowerPC/Disassembler/PPCDisassembler.cpp | 1 +
.../RISCV/Disassembler/RISCVDisassembler.cpp | 47 ++++----
llvm/lib/Target/RISCV/RISCV.td | 1 +
.../Sparc/Disassembler/SparcDisassembler.cpp | 39 ++++---
.../Disassembler/SystemZDisassembler.cpp | 1 +
.../Target/VE/Disassembler/VEDisassembler.cpp | 2 +
.../XCore/Disassembler/XCoreDisassembler.cpp | 2 +
.../Disassembler/XtensaDisassembler.cpp | 1 +
llvm/utils/TableGen/DecoderEmitter.cpp | 102 +++++++++++++++---
27 files changed, 270 insertions(+), 114 deletions(-)
create mode 100644 llvm/include/llvm/MC/MCDecoder.h
diff --git a/llvm/include/llvm/MC/MCDecoder.h b/llvm/include/llvm/MC/MCDecoder.h
new file mode 100644
index 0000000000000..43a871499943a
--- /dev/null
+++ b/llvm/include/llvm/MC/MCDecoder.h
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Disassembler decoder state machine helper functions.
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_MC_MCDECODER_H
+#define LLVM_MC_MCDECODER_H
+
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/Support/MathExtras.h"
+#include <bitset>
+#include <cassert>
+
+namespace llvm {
+class APInt;
+}
+
+namespace llvm::MCD {
+
+inline bool Check(MCDisassembler::DecodeStatus &Out,
+ MCDisassembler::DecodeStatus In) {
+ Out = static_cast<MCDisassembler::DecodeStatus>(Out & In);
+ return Out != MCDisassembler::Fail;
+}
+
+// fieldFromInstruction - Extracts a given span of bits from the instruction
+// bits and return it as an integer.
+template <typename IntType>
+#if defined(_MSC_VER) && !defined(__clang__)
+__declspec(noinline)
+#endif
+inline std::enable_if_t<std::is_integral_v<IntType>, IntType>
+fieldFromInstruction(const IntType &Insn, unsigned StartBit, unsigned NumBits) {
+ assert(StartBit + NumBits <= 64 && "Cannot support >64-bit extractions!");
+ assert(StartBit + NumBits <= (sizeof(IntType) * 8) &&
+ "Instruction field out of bounds!");
+ const IntType Mask = maskTrailingOnes<IntType>(NumBits);
+ return (Insn >> StartBit) & Mask;
+}
+
+template <size_t N>
+inline uint64_t fieldFromInstruction(const std::bitset<N> &Insn,
+ unsigned StartBit, unsigned NumBits) {
+ assert(StartBit + NumBits <= N && "Instruction field out of bounds!");
+ assert(NumBits <= 64 && "Cannot support >64-bit extractions!");
+ const std::bitset<N> Mask(maskTrailingOnes<uint64_t>(NumBits));
+ return ((Insn >> StartBit) & Mask).to_ullong();
+}
+
+template <typename InsnType>
+inline std::enable_if_t<!std::is_integral_v<InsnType>, uint64_t>
+fieldFromInstruction(const InsnType &Insn, unsigned StartBit,
+ unsigned NumBits) {
+ return Insn.extractBitsAsZExtValue(NumBits, StartBit);
+}
+
+// InsnTypeTraits - Used by the decoder emitter to query whether a given type
+// is valid type for the template type parameter <InsnType> and if yes, the
+// instruction bitwidth its used to represent.
+struct InsnTypeTraits {
+ bool IsValid;
+ size_t BitWidth;
+};
+
+// By default, all types are invalid.
+template <typename T> constexpr InsnTypeTraits InsnTraits{false, 0};
+
+// Integer types are valid types for InsnType.
+template <> constexpr InsnTypeTraits InsnTraits<uint8_t>{true, 8};
+template <> constexpr InsnTypeTraits InsnTraits<uint16_t>{true, 16};
+template <> constexpr InsnTypeTraits InsnTraits<uint32_t>{true, 32};
+template <> constexpr InsnTypeTraits InsnTraits<uint64_t>{true, 64};
+
+// APInt type is valid, but is used for variable length instructions, so set the
+// size to be 0.
+template <> constexpr InsnTypeTraits InsnTraits<APInt>{true, 0};
+
+// std::bitset<> is valid.
+template <size_t N>
+constexpr InsnTypeTraits InsnTraits<std::bitset<N>>{true, N};
+
+} // namespace llvm::MCD
+
+#endif
diff --git a/llvm/include/llvm/MC/MCDecoderOps.h b/llvm/include/llvm/MC/MCDecoderOps.h
index 50fcf2a40e26d..dea5b6931250f 100644
--- a/llvm/include/llvm/MC/MCDecoderOps.h
+++ b/llvm/include/llvm/MC/MCDecoderOps.h
@@ -1,11 +1,11 @@
-//===------------ llvm/MC/MCDecoderOps.h - Decoder driver -------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-// Disassembler decoder state machine driver.
+// Disassembler decoder state machine ops.
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCDECODEROPS_H
#define LLVM_MC_MCDECODEROPS_H
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 495b59ee916cf..2c290edb7684e 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1158,6 +1158,13 @@ class InstrInfo {
//
// This option is a temporary migration help. It will go away.
bit guessInstructionProperties = true;
+
+ // When generating decoder/disassembler code, generate additional compile time
+ // checks to disable/cull decoders based on the instruction bitwidth. This
+ // requires use of different `InsnType` for different bitwidths and optionally
+ // providing `InsnTypeTraits` template specialization for `InsnType` unless
+ // its already provided in MCDecoder.h.
+ bit CullDecoders = false;
}
// Standard Pseudo Instructions.
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index ae984be670fc2..323db2a0728eb 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -15,6 +15,7 @@
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "TargetInfo/AArch64TargetInfo.h"
#include "Utils/AArch64BaseInfo.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
#include "llvm/MC/MCInst.h"
@@ -27,6 +28,7 @@
#include <memory>
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "aarch64-disassembler"
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index 8e4b6365dc06b..ffd261406a269 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -2091,6 +2091,7 @@ def FeatureISAVersion12_Generic: FeatureSet<
def AMDGPUInstrInfo : InstrInfo {
let guessInstructionProperties = 1;
+ let CullDecoders = true;
}
def AMDGPUAsmParser : AsmParser {
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index 070de008d4f59..0bde857af9334 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -27,6 +27,7 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrDesc.h"
@@ -497,26 +498,24 @@ template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
return Res;
}
-static inline DecoderUInt128 eat12Bytes(ArrayRef<uint8_t> &Bytes) {
+static inline std::bitset<96> eat12Bytes(ArrayRef<uint8_t> &Bytes) {
+ using namespace llvm::support::endian;
assert(Bytes.size() >= 12);
- uint64_t Lo =
- support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
+ std::bitset<96> Lo(read<uint64_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(8);
- uint64_t Hi =
- support::endian::read<uint32_t, llvm::endianness::little>(Bytes.data());
+ std::bitset<96> Hi(read<uint32_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(4);
- return DecoderUInt128(Lo, Hi);
+ return (Hi << 64) | Lo;
}
-static inline DecoderUInt128 eat16Bytes(ArrayRef<uint8_t> &Bytes) {
+static inline std::bitset<128> eat16Bytes(ArrayRef<uint8_t> &Bytes) {
+ using namespace llvm::support::endian;
assert(Bytes.size() >= 16);
- uint64_t Lo =
- support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
+ std::bitset<128> Lo(read<uint64_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(8);
- uint64_t Hi =
- support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
+ std::bitset<128> Hi(read<uint64_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(8);
- return DecoderUInt128(Lo, Hi);
+ return (Hi << 64) | Lo;
}
void AMDGPUDisassembler::decodeImmOperands(MCInst &MI,
@@ -599,14 +598,14 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
// Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
// encodings
if (isGFX1250() && Bytes.size() >= 16) {
- DecoderUInt128 DecW = eat16Bytes(Bytes);
+ std::bitset<128> DecW = eat16Bytes(Bytes);
if (tryDecodeInst(DecoderTableGFX1250128, MI, DecW, Address, CS))
break;
Bytes = Bytes_.slice(0, MaxInstBytesNum);
}
- if (isGFX11Plus() && Bytes.size() >= 12 ) {
- DecoderUInt128 DecW = eat12Bytes(Bytes);
+ if (isGFX11Plus() && Bytes.size() >= 12) {
+ std::bitset<96> DecW = eat12Bytes(Bytes);
if (isGFX11() &&
tryDecodeInst(DecoderTableGFX1196, DecoderTableGFX11_FAKE1696, MI,
@@ -641,7 +640,7 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
} else if (Bytes.size() >= 16 &&
STI.hasFeature(AMDGPU::FeatureGFX950Insts)) {
- DecoderUInt128 DecW = eat16Bytes(Bytes);
+ std::bitset<128> DecW = eat16Bytes(Bytes);
if (tryDecodeInst(DecoderTableGFX940128, MI, DecW, Address, CS))
break;
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
index f4d164bf10c3c..ded447b6f8d5a 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
@@ -32,44 +32,6 @@ class MCOperand;
class MCSubtargetInfo;
class Twine;
-// Exposes an interface expected by autogenerated code in
-// FixedLenDecoderEmitter
-class DecoderUInt128 {
-private:
- uint64_t Lo = 0;
- uint64_t Hi = 0;
-
-public:
- DecoderUInt128() = default;
- DecoderUInt128(uint64_t Lo, uint64_t Hi = 0) : Lo(Lo), Hi(Hi) {}
- operator bool() const { return Lo || Hi; }
- uint64_t extractBitsAsZExtValue(unsigned NumBits,
- unsigned BitPosition) const {
- assert(NumBits && NumBits <= 64);
- assert(BitPosition < 128);
- uint64_t Val;
- if (BitPosition < 64)
- Val = Lo >> BitPosition | Hi << 1 << (63 - BitPosition);
- else
- Val = Hi >> (BitPosition - 64);
- return Val & ((uint64_t(2) << (NumBits - 1)) - 1);
- }
- DecoderUInt128 operator&(const DecoderUInt128 &RHS) const {
- return DecoderUInt128(Lo & RHS.Lo, Hi & RHS.Hi);
- }
- DecoderUInt128 operator&(const uint64_t &RHS) const {
- return *this & DecoderUInt128(RHS);
- }
- DecoderUInt128 operator~() const { return DecoderUInt128(~Lo, ~Hi); }
- bool operator==(const DecoderUInt128 &RHS) {
- return Lo == RHS.Lo && Hi == RHS.Hi;
- }
- bool operator!=(const DecoderUInt128 &RHS) {
- return Lo != RHS.Lo || Hi != RHS.Hi;
- }
- bool operator!=(const int &RHS) { return *this != DecoderUInt128(RHS); }
-};
-
//===----------------------------------------------------------------------===//
// AMDGPUDisassembler
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
index 6181017559045..f28c7d8fe92a5 100644
--- a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
+++ b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
@@ -16,6 +16,7 @@
#include "MCTargetDesc/ARCMCTargetDesc.h"
#include "TargetInfo/ARCTargetInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -24,6 +25,7 @@
#include "llvm/MC/TargetRegistry.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "arc-disassembler"
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 2e47ceeca96b8..f24c68fec3cd4 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -13,6 +13,7 @@
#include "TargetInfo/ARMTargetInfo.h"
#include "Utils/ARMBaseInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -31,6 +32,7 @@
#include <vector>
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "arm-disassembler"
diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index c7a584868f4e6..948588cb9a754 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -18,6 +18,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -26,6 +27,7 @@
#include "llvm/Support/Compiler.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "avr-disassembler"
diff --git a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
index 4dfae81e90191..b5bb1c08c5644 100644
--- a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
+++ b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
diff --git a/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp b/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp
index d78d9acc2aa23..749127f4ddc8a 100644
--- a/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp
+++ b/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp
@@ -15,6 +15,7 @@
#include "TargetInfo/CSKYTargetInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
diff --git a/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp b/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp
index bcddb540d35dc..de10092cbe3c8 100644
--- a/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp
+++ b/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp
@@ -13,6 +13,7 @@
#include "TargetInfo/HexagonTargetInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCExpr.h"
diff --git a/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
index 5d87c3c4d72cf..c8cc855756c5e 100644
--- a/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
+++ b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
@@ -16,6 +16,7 @@
#include "LanaiCondCode.h"
#include "LanaiInstrInfo.h"
#include "TargetInfo/LanaiTargetInfo.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
diff --git a/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp b/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
index 8c4668ec70c7e..735f798afde24 100644
--- a/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
+++ b/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
@@ -13,6 +13,7 @@
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "TargetInfo/LoongArchTargetInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
diff --git a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
index 4ec18fe6bf544..6ca01e598d95d 100644
--- a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
+++ b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
@@ -19,6 +19,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -27,6 +28,7 @@
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "m68k-disassembler"
diff --git a/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp b/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
index 4c5b473982f77..c8094a8eeb361 100644
--- a/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
+++ b/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
@@ -14,6 +14,7 @@
#include "MSP430.h"
#include "TargetInfo/MSP430TargetInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -23,6 +24,7 @@
#include "llvm/Support/Endian.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "msp430-disassembler"
diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index b3f6cd1609fbb..0c98c4da2ede1 100644
--- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -14,6 +14,7 @@
#include "TargetInfo/MipsTargetInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -29,6 +30,7 @@
#include <cstdint>
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "mips-disassembler"
diff --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
index 71a76142bb389..5e27f06c94f06 100644
--- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
+++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
@@ -8,6 +8,7 @@
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "TargetInfo/PowerPCTargetInfo.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 78be55b3a51d3..450808cea3f45 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -14,6 +14,7 @@
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "TargetInfo/RISCVTargetInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -25,6 +26,7 @@
#include "llvm/Support/Endian.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "riscv-disassembler"
@@ -552,27 +554,8 @@ static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
return decodeZcmpRlist(Inst, Imm, Address, Decoder);
}
-static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
- uint64_t Address,
- const MCDisassembler *Decoder);
-
-static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn,
- uint64_t Address,
- const MCDisassembler *Decoder);
-
-#include "RISCVGenDisassemblerTables.inc"
-
-static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- uint32_t Rs1 = fieldFromInstruction(Insn, 7, 5);
- [[maybe_unused]] DecodeStatus Result =
- DecodeGPRX1X5RegisterClass(Inst, Rs1, Address, Decoder);
- assert(Result == MCDisassembler::Success && "Invalid register");
- return MCDisassembler::Success;
-}
-
-static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
+static DecodeStatus decodeXTHeadMemPair(MCInst &Inst,
+ const std::bitset<48> &Insn,
uint64_t Address,
const MCDisassembler *Decoder) {
DecodeStatus S = MCDisassembler::Success;
@@ -602,6 +585,19 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
return S;
}
+static DecodeStatus decodeCSSPushPopchk(MCInst &Inst,
+ const std::bitset<48> &Insn,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ uint32_t Rs1 = fieldFromInstruction(Insn, 7, 5);
+ [[maybe_unused]] DecodeStatus Result =
+ DecodeGPRX1X5RegisterClass(Inst, Rs1, Address, Decoder);
+ assert(Result == MCDisassembler::Success && "Invalid register");
+ return MCDisassembler::Success;
+}
+
+#include "RISCVGenDisassemblerTables.inc"
+
// Add implied SP operand for C.*SP compressed instructions. The SP operand
// isn't explicitly encoded in the instruction.
void RISCVDisassembler::addSPOperands(MCInst &MI) const {
@@ -714,7 +710,7 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
// Use uint64_t to match getInstruction48. decodeInstruction is templated
// on the Insn type.
- uint64_t Insn = support::endian::read32le(Bytes.data());
+ uint32_t Insn = support::endian::read32le(Bytes.data());
for (const DecoderListEntry &Entry : DecoderList32) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
@@ -762,7 +758,7 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
// Use uint64_t to match getInstruction48. decodeInstruction is templated
// on the Insn type.
- uint64_t Insn = support::endian::read16le(Bytes.data());
+ uint16_t Insn = support::endian::read16le(Bytes.data());
for (const DecoderListEntry &Entry : DecoderList16) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
@@ -796,10 +792,11 @@ DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
}
Size = 6;
- uint64_t Insn = 0;
+ uint64_t InsnBits = 0;
for (size_t i = Size; i-- != 0;)
- Insn += (static_cast<uint64_t>(Bytes[i]) << 8 * i);
+ InsnBits += (static_cast<uint64_t>(Bytes[i]) << 8 * i);
+ std::bitset<48> Insn(InsnBits);
for (const DecoderListEntry &Entry : DecoderList48) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
continue;
diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td
index b24d8637cb27f..573a962756020 100644
--- a/llvm/lib/Target/RISCV/RISCV.td
+++ b/llvm/lib/Target/RISCV/RISCV.td
@@ -85,6 +85,7 @@ include "RISCVPfmCounters.td"
def RISCVInstrInfo : InstrInfo {
let guessInstructionProperties = 0;
+ let CullDecoders = true;
}
def RISCVAsmParser : AsmParser {
diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
index fab94fb4d40ca..4d353a04d1234 100644
--- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -14,6 +14,7 @@
#include "TargetInfo/SparcTargetInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -21,6 +22,7 @@
#include "llvm/Support/Compiler.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "sparc-disassembler"
@@ -266,10 +268,26 @@ static DecodeStatus DecodeSIMM5(MCInst &Inst, unsigned insn, uint64_t Address,
const MCDisassembler *Decoder);
static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, uint64_t Address,
const MCDisassembler *Decoder);
+
+static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
+ uint64_t Address, uint64_t Offset,
+ uint64_t Width, MCInst &MI,
+ const MCDisassembler *Decoder) {
+ return Decoder->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset,
+ Width, /*InstSize=*/4);
+}
+
template <unsigned N>
constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal,
uint64_t Address,
- const MCDisassembler *Decoder);
+ const MCDisassembler *Decoder) {
+ int64_t BranchOffset = SignExtend64(ImmVal, N) * 4;
+ if (!tryAddingSymbolicOperand(Address + BranchOffset, true, Address, 0, N, MI,
+ Decoder))
+ MI.addOperand(MCOperand::createImm(BranchOffset));
+ return MCDisassembler::Success;
+}
+
#include "SparcGenDisassemblerTables.inc"
/// Read four bytes from the ArrayRef and return 32 bit word.
@@ -322,14 +340,6 @@ DecodeStatus SparcDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
return Result;
}
-static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
- uint64_t Address, uint64_t Offset,
- uint64_t Width, MCInst &MI,
- const MCDisassembler *Decoder) {
- return Decoder->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset,
- Width, /*InstSize=*/4);
-}
-
static DecodeStatus DecodeCall(MCInst &MI, unsigned insn, uint64_t Address,
const MCDisassembler *Decoder) {
int64_t CallOffset = SignExtend64(fieldFromInstruction(insn, 0, 30), 30) * 4;
@@ -352,14 +362,3 @@ static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, uint64_t Address,
MI.addOperand(MCOperand::createImm(SignExtend64<13>(insn)));
return MCDisassembler::Success;
}
-
-template <unsigned N>
-constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- int64_t BranchOffset = SignExtend64(ImmVal, N) * 4;
- if (!tryAddingSymbolicOperand(Address + BranchOffset, true, Address, 0, N, MI,
- Decoder))
- MI.addOperand(MCOperand::createImm(BranchOffset));
- return MCDisassembler::Success;
-}
diff --git a/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp b/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp
index 31b4f1196392c..0b91aba67694f 100644
--- a/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp
+++ b/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp
@@ -8,6 +8,7 @@
#include "MCTargetDesc/SystemZMCTargetDesc.h"
#include "TargetInfo/SystemZTargetInfo.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
diff --git a/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp
index 88200c5fc97eb..d7e1666a7417d 100644
--- a/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp
+++ b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp
@@ -15,6 +15,7 @@
#include "VE.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -22,6 +23,7 @@
#include "llvm/Support/Compiler.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "ve-disassembler"
diff --git a/llvm/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp b/llvm/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp
index d36f18238f7a3..6921f44b700c5 100644
--- a/llvm/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp
+++ b/llvm/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp
@@ -15,6 +15,7 @@
#include "XCore.h"
#include "XCoreRegisterInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -23,6 +24,7 @@
#include "llvm/Support/Compiler.h"
using namespace llvm;
+using namespace llvm::MCD;
#define DEBUG_TYPE "xcore-disassembler"
diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index 39bec4785c61c..396b00f7b8628 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -15,6 +15,7 @@
#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "TargetInfo/XtensaTargetInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDecoder.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 8fa44bcc7b964..2eee6cc7934c8 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -23,6 +23,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
@@ -258,12 +259,18 @@ class DecoderTable {
std::vector<uint8_t> Data;
};
+using BitWidthSet = SmallSet<unsigned, 4>;
+
struct DecoderTableInfo {
DecoderTable Table;
FixupScopeList FixupStack;
PredicateSet Predicates;
DecoderSet Decoders;
+ // Map from bitwidth to the decoders indices that are valid for that bitwidth.
+ // Indexed by the decoder index.
+ std::vector<BitWidthSet> DecoderBitWidths;
+
bool isOutermostScope() const { return FixupStack.size() == 1; }
void pushScope() { FixupStack.emplace_back(); }
@@ -306,7 +313,9 @@ class DecoderEmitter {
void emitPredicateFunction(formatted_raw_ostream &OS,
PredicateSet &Predicates) const;
void emitDecoderFunction(formatted_raw_ostream &OS,
- DecoderSet &Decoders) const;
+ const DecoderTableInfo &TableInfo,
+ const BitWidthSet &InstrBitWidths,
+ bool IsVarLenInsts, bool CullDecoders) const;
// run - Output the code emitter
void run(raw_ostream &o) const;
@@ -1100,7 +1109,12 @@ void DecoderEmitter::emitPredicateFunction(formatted_raw_ostream &OS,
}
void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS,
- DecoderSet &Decoders) const {
+ const DecoderTableInfo &TableInfo,
+ const BitWidthSet &InstrBitWidths,
+ bool IsVarLenInsts,
+ bool CullDecoders) const {
+ const DecoderSet &Decoders = TableInfo.Decoders;
+ const auto &DecoderBitWidths = TableInfo.DecoderBitWidths;
// The decoder function is just a big switch statement or a table of function
// pointers based on the input decoder index.
@@ -1114,11 +1128,30 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS,
"DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const "
"MCDisassembler *Decoder, bool &DecodeComplete";
+ // Generate a check that evaluates to true if `InsnBitWidth` is not valid.
+ auto GenerateIsInvalidBitwidth = [&OS](const BitWidthSet &ValidBitWidths) {
+ OS << '(';
+ ListSeparator LS(" && ");
+ for (unsigned ValidBW : ValidBitWidths)
+ OS << LS << "InsnBitWidth != " << ValidBW;
+ OS << ')';
+ };
+
if (UseFnTableInDecodeToMCInst) {
// Emit a function for each case first.
- for (const auto &[Index, Decoder] : enumerate(Decoders)) {
+ for (const auto &[Index, Decoder, DecoderBWs] :
+ enumerate(Decoders, DecoderBitWidths)) {
OS << "template <typename InsnType>\n";
- OS << "DecodeStatus decodeFn" << Index << "(" << DecodeParams << ") {\n";
+ OS << "static DecodeStatus decodeFn" << Index << "(" << DecodeParams
+ << ") {\n";
+ OS << " using namespace llvm::MCD;\n";
+ if (CullDecoders) {
+ OS << " constexpr size_t InsnBitWidth = "
+ "InsnTraits<InsnType>.BitWidth;\n";
+ OS << " if constexpr";
+ GenerateIsInvalidBitwidth(DecoderBWs);
+ OS << "\n llvm_unreachable(\"Invalid decoder index!\");\n";
+ }
OS << " " << TmpTypeDecl;
OS << " [[maybe_unused]] TmpType tmp;\n";
OS << Decoder;
@@ -1131,26 +1164,50 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS,
OS << "template <typename InsnType>\n";
OS << "static DecodeStatus decodeToMCInst(unsigned Idx, " << DecodeParams
<< ") {\n";
+ OS << " using namespace llvm::MCD;\n";
OS << " DecodeComplete = true;\n";
+ if (CullDecoders) {
+ // Generate a static assert to verify that InsnType is one of the types
+ // supported.
+ OS << " static_assert(InsnTraits<InsnType>.IsValid);\n";
+ OS << " constexpr size_t InsnBitWidth = InsnTraits<InsnType>.BitWidth;\n";
+ }
+
if (UseFnTableInDecodeToMCInst) {
- // Build a table of function pointers.
OS << " using DecodeFnTy = DecodeStatus (*)(" << DecodeParams << ");\n";
OS << " static constexpr DecodeFnTy decodeFnTable[] = {\n";
- for (size_t Index : llvm::seq(Decoders.size()))
- OS << " decodeFn" << Index << ",\n";
+ for (const auto &[Index, DecoderBWs] : enumerate(DecoderBitWidths)) {
+ if (!CullDecoders) {
+ OS << " decodeFn" << Index << ",\n";
+ continue;
+ }
+ OS << " ";
+ GenerateIsInvalidBitwidth(DecoderBWs);
+ OS << " ? nullptr : decodeFn" << Index << "<InsnType>,\n";
+ }
OS << " };\n";
- OS << " if (Idx >= " << Decoders.size() << ")\n";
- OS << " llvm_unreachable(\"Invalid index!\");\n";
+ OS << " if (Idx >= " << Decoders.size() << " || !decodeFnTable[Idx])\n";
+ OS << " llvm_unreachable(\"Invalid decoder index!\");\n";
+
OS << " return decodeFnTable[Idx](S, insn, MI, Address, Decoder, "
"DecodeComplete);\n";
} else {
OS << " " << TmpTypeDecl;
OS << " TmpType tmp;\n";
OS << " switch (Idx) {\n";
- OS << " default: llvm_unreachable(\"Invalid index!\");\n";
- for (const auto &[Index, Decoder] : enumerate(Decoders)) {
+ OS << " default: llvm_unreachable(\"Invalid decoder index!\");\n";
+ for (const auto &[Index, Decoder, DecoderBWs] :
+ enumerate(Decoders, DecoderBitWidths)) {
OS << " case " << Index << ":\n";
+ // If this decoder is not valid for all supported bitwidths, add checks
+ // that will cull this case for bitwidths for which this decoder is not
+ // valid.
+ if (CullDecoders && DecoderBWs != InstrBitWidths) {
+ OS << " if constexpr";
+ GenerateIsInvalidBitwidth(DecoderBWs);
+ OS << "\n llvm_unreachable(\"Invalid decoder index!\");\n";
+ }
OS << Decoder;
OS << " return S;\n";
}
@@ -1525,6 +1582,13 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
auto [DIdx, HasCompleteDecoder] =
getDecoderIndex(TableInfo.Decoders, EncodingID);
+ // Remember this decoder index as valid for instruction of the current bit
+ // width.
+ const InstructionEncoding &Enc = Encodings[EncodingID];
+ if (DIdx >= TableInfo.DecoderBitWidths.size())
+ TableInfo.DecoderBitWidths.resize(DIdx + 1);
+ TableInfo.DecoderBitWidths[DIdx].insert(Enc.getBitWidth());
+
// Produce OPC_Decode or OPC_TryDecode opcode based on the information
// whether the instruction decoder is complete or not. If it is complete
// then it handles all possible values of remaining variable/unfiltered bits
@@ -1539,7 +1603,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
? MCD::OPC_TryDecodeOrFail
: MCD::OPC_TryDecode);
TableInfo.Table.push_back(DecoderOp);
- const Record *InstDef = Encodings[EncodingID].getInstruction()->TheDef;
+ const Record *InstDef = Enc.getInstruction()->TheDef;
TableInfo.Table.insertULEB128(Emitter->getTarget().getInstrIntValue(InstDef));
TableInfo.Table.insertULEB128(DIdx);
@@ -2133,6 +2197,7 @@ void InstructionEncoding::populateEncoding() {
// using the VS compiler. It has a bug which causes the function
// to be optimized out in some circumstances. See llvm.org/pr38292
static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
+ return;
OS << R"(
// Helper functions for extracting fields from encoded instructions.
// InsnType must either be integral or an APInt-like object that must:
@@ -2219,6 +2284,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
OS << ") {\n";
if (HasCheckPredicate)
OS << " const FeatureBitset &Bits = STI.getFeatureBits();\n";
+ OS << " using namespace llvm::MCD;\n";
OS << R"(
const uint8_t *Ptr = DecodeTable;
@@ -2418,6 +2484,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
// is correct to propagate the values of this enum; see comment on 'enum
// DecodeStatus'.)
static void emitCheck(formatted_raw_ostream &OS) {
+ return;
OS << R"(
static bool Check(DecodeStatus &Out, DecodeStatus In) {
Out = static_cast<DecodeStatus>(Out & In);
@@ -2607,6 +2674,7 @@ void DecoderEmitter::run(raw_ostream &o) const {
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/SubtargetFeature.h"
#include <assert.h>
+#include <bitset>
namespace {
)";
@@ -2644,9 +2712,16 @@ namespace {
DecoderTableInfo TableInfo;
unsigned OpcodeMask = 0;
+
+ const bool CullDecoders =
+ Target.getInstructionSet()->getValueAsBit("CullDecoders");
+
+ // The set of valid instruction bitwidths for this target.
+ BitWidthSet InstrBitwidths;
for (const auto &[Key, EncodingIDs] : EncMap) {
auto [DecoderNamespace, HwModeID, Size] = Key;
const unsigned BitWidth = IsVarLenInst ? MaxInstLen : 8 * Size;
+ InstrBitwidths.insert(BitWidth);
// Emit the decoder for this (namespace, hwmode, width) combination.
FilterChooser FC(Encodings, EncodingIDs, BitWidth, this);
@@ -2683,7 +2758,8 @@ namespace {
emitPredicateFunction(OS, TableInfo.Predicates);
// Emit the decoder function.
- emitDecoderFunction(OS, TableInfo.Decoders);
+ emitDecoderFunction(OS, TableInfo, InstrBitwidths, IsVarLenInst,
+ CullDecoders);
// Emit the main entry point for the decoder, decodeInstruction().
emitDecodeInstruction(OS, IsVarLenInst, OpcodeMask);
More information about the llvm-commits
mailing list