[NFC][MC][Decoder] Extract fixed pieces of decoder code into new header file (#154802)

Extract fixed functions generated by decoder emitter into a new
MCDecoder.h header.
This commit is contained in:
Rahul Joshi 2025-08-21 15:06:43 -07:00 committed by GitHub
parent 628280b597
commit 22f8693248
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 112 additions and 85 deletions

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// 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 helper functions.
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCDECODER_H
#define LLVM_MC_MCDECODER_H
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
namespace llvm::MCD {
// Helper to propagate SoftFail status. Returns false if the status is Fail;
// callers are expected to early-exit in that condition. (Note, the '&' operator
// is correct to propagate the values of this enum; see comment on 'enum
// DecodeStatus'.)
inline bool Check(MCDisassembler::DecodeStatus &Out,
MCDisassembler::DecodeStatus In) {
Out = static_cast<MCDisassembler::DecodeStatus>(Out & In);
return Out != MCDisassembler::Fail;
}
// 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 <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);
}
// Helper function for inserting bits extracted from an encoded instruction into
// an integer-typed field.
template <typename IntType>
static std::enable_if_t<std::is_integral_v<IntType>, void>
insertBits(IntType &field, IntType bits, unsigned startBit, unsigned numBits) {
// Check that no bit beyond numBits is set, so that a simple bitwise |
// is sufficient.
assert((~(((IntType)1 << numBits) - 1) & bits) == 0 &&
"bits has more than numBits bits set");
assert(startBit + numBits <= sizeof(IntType) * 8);
(void)numBits;
field |= bits << startBit;
}
} // namespace llvm::MCD
#endif // LLVM_MC_MCDECODER_H

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -1102,7 +1102,9 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS,
// Emit a function for each case first.
for (const auto &[Index, Decoder] : enumerate(Decoders)) {
OS << "template <typename InsnType>\n";
OS << "DecodeStatus decodeFn" << Index << "(" << DecodeParams << ") {\n";
OS << "static DecodeStatus decodeFn" << Index << "(" << DecodeParams
<< ") {\n";
OS << " using namespace llvm::MCD;\n";
OS << " " << TmpTypeDecl;
OS << " [[maybe_unused]] TmpType tmp;\n";
OS << Decoder;
@ -1115,24 +1117,26 @@ 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 (UseFnTableInDecodeToMCInst) {
// Build a table of function pointers.
// 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";
OS << " };\n";
OS << " if (Idx >= " << Decoders.size() << ")\n";
OS << " llvm_unreachable(\"Invalid index!\");\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";
OS << " default: llvm_unreachable(\"Invalid decoder index!\");\n";
for (const auto &[Index, Decoder] : enumerate(Decoders)) {
OS << " case " << Index << ":\n";
OS << Decoder;
@ -2126,65 +2130,6 @@ InstructionEncoding::InstructionEncoding(const Record *EncodingDef,
}
}
// emitFieldFromInstruction - Emit the templated helper function
// fieldFromInstruction().
// On Windows we make sure that this function is not inlined when
// 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) {
OS << R"(
// Helper functions for extracting fields from encoded instructions.
// InsnType must either be integral or an APInt-like object that must:
// * be default-constructible and copy-constructible
// * Support extractBitsAsZExtValue(numBits, startBit)
// * Support the ~, &, ==, and != operators with other objects of the same type
// * Support the != and bitwise & with uint64_t
template <typename InsnType>
#if defined(_MSC_VER) && !defined(__clang__)
__declspec(noinline)
#endif
static std::enable_if_t<std::is_integral<InsnType>::value, InsnType>
fieldFromInstruction(const InsnType &insn, unsigned startBit,
unsigned numBits) {
assert(startBit + numBits <= 64 && "Cannot support >64-bit extractions!");
assert(startBit + numBits <= (sizeof(InsnType) * 8) &&
"Instruction field out of bounds!");
InsnType fieldMask;
if (numBits == sizeof(InsnType) * 8)
fieldMask = (InsnType)(-1LL);
else
fieldMask = (((InsnType)1 << numBits) - 1) << startBit;
return (insn & fieldMask) >> startBit;
}
template <typename InsnType>
static std::enable_if_t<!std::is_integral<InsnType>::value, uint64_t>
fieldFromInstruction(const InsnType &insn, unsigned startBit,
unsigned numBits) {
return insn.extractBitsAsZExtValue(numBits, startBit);
}
)";
}
// emitInsertBits - Emit the templated helper function insertBits().
static void emitInsertBits(formatted_raw_ostream &OS) {
OS << R"(
// Helper function for inserting bits extracted from an encoded instruction into
// an integer-typed field.
template <typename IntType>
static std::enable_if_t<std::is_integral_v<IntType>, void>
insertBits(IntType &field, IntType bits, unsigned startBit, unsigned numBits) {
// Check that no bit beyond numBits is set, so that a simple bitwise |
// is sufficient.
assert((~(((IntType)1 << numBits) - 1) & bits) == 0 &&
"bits has more than numBits bits set");
assert(startBit + numBits <= sizeof(IntType) * 8);
(void)numBits;
field |= bits << startBit;
}
)";
}
// emitDecodeInstruction - Emit the templated helper function
// decodeInstruction().
static void emitDecodeInstruction(formatted_raw_ostream &OS, bool IsVarLenInst,
@ -2218,6 +2163,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;
@ -2412,20 +2358,6 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
)";
}
// Helper to propagate SoftFail status. Returns false if the status is Fail;
// callers are expected to early-exit in that condition. (Note, the '&' operator
// is correct to propagate the values of this enum; see comment on 'enum
// DecodeStatus'.)
static void emitCheck(formatted_raw_ostream &OS) {
OS << R"(
static bool Check(DecodeStatus &Out, DecodeStatus In) {
Out = static_cast<DecodeStatus>(Out & In);
return Out != MCDisassembler::Fail;
}
)";
}
/// Collects all HwModes referenced by the target for encoding purposes.
void DecoderEmitter::collectHwModesReferencedForEncodings(
std::vector<unsigned> &HwModeIDs,
@ -2610,10 +2542,6 @@ void DecoderEmitter::run(raw_ostream &o) const {
namespace {
)";
emitFieldFromInstruction(OS);
emitInsertBits(OS);
emitCheck(OS);
// Do extra bookkeeping for variable-length encodings.
std::vector<unsigned> InstrLen;
bool IsVarLenInst = Target.hasVariableLengthEncodings();
@ -2643,6 +2571,7 @@ namespace {
DecoderTableInfo TableInfo;
unsigned OpcodeMask = 0;
for (const auto &[Key, EncodingIDs] : EncMap) {
auto [DecoderNamespace, HwModeID, Size] = Key;
const unsigned BitWidth = IsVarLenInst ? MaxInstLen : 8 * Size;