[llvm] [TableGen][DecoderEmitter] Add option to emit type-specialized code (PR #146593)

Rahul Joshi via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 20 13:32:13 PDT 2025


jurahul wrote:

Here's what the code looks like with a single impl function:

```
static DecodeStatus decodeInstructionImpl(const uint8_t DecodeTable[], MCInst &MI, const std::bitset<128> &Insn, uint64_t Address, const MCDisassembler *DisAsm, const MCSubtargetInfo &STI, function_ref<DecodeStatus(unsigned, DecodeStatus, MCInst &, uint64_t, const MCDisassembler *, bool &)> decodeToMCInstPtr) {
  const FeatureBitset &Bits = STI.getFeatureBits();

  const uint8_t *Ptr = DecodeTable;
  uint64_t CurFieldValue = 0;
  DecodeStatus S = MCDisassembler::Success;
  while (true) {
    ptrdiff_t Loc = Ptr - DecodeTable;
    const uint8_t DecoderOp = *Ptr++;
    switch (DecoderOp) {
    default:
      errs() << Loc << ": Unexpected decode table opcode: "
             << (int)DecoderOp << '\n';
      return MCDisassembler::Fail;
    case MCD::OPC_ExtractField: {

...
    case MCD::OPC_Decode: {
      // Decode the Opcode value.
      unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
      unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);

      MI.clear();
      MI.setOpcode(Opc);
      bool DecodeComplete;
      S = decodeToMCInstPtr(DecodeIdx, S, MI, Address, DisAsm, DecodeComplete);

...
}

static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
    uint32_t Insn, uint64_t Address, const MCDisassembler *DisAsm,
    const MCSubtargetInfo &STI) {
  std::bitset<128> InsnMaxWidth = Insn;
  auto DecodeToMCInst = [Insn](unsigned DecodeIdx, DecodeStatus S, MCInst &MI,
                                 uint64_t Address, const MCDisassembler *DisAsm,
                                 bool &DecodeComplete) {
    return decodeToMCInst32(DecodeIdx, S, Insn, MI, Address, DisAsm, DecodeComplete);
  };
  return decodeInstructionImpl(DecodeTable, MI, InsnMaxWidth, Address, DisAsm, STI, DecodeToMCInst);
}

static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
    uint64_t Insn, uint64_t Address, const MCDisassembler *DisAsm,
    const MCSubtargetInfo &STI) {
  std::bitset<128> InsnMaxWidth = Insn;
  auto DecodeToMCInst = [Insn](unsigned DecodeIdx, DecodeStatus S, MCInst &MI,
                                 uint64_t Address, const MCDisassembler *DisAsm,
                                 bool &DecodeComplete) {
    return decodeToMCInst64(DecodeIdx, S, Insn, MI, Address, DisAsm, DecodeComplete);
  };
  return decodeInstructionImpl(DecodeTable, MI, InsnMaxWidth, Address, DisAsm, STI, DecodeToMCInst);
}

static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
    const std::bitset<96> &Insn, uint64_t Address, const MCDisassembler *DisAsm,
    const MCSubtargetInfo &STI) {
  const std::bitset<96> Mask(maskTrailingOnes<uint64_t>(64));
  std::bitset<128> InsnMaxWidth((Insn & Mask).to_ullong());
  InsnMaxWidth |= std::bitset<128>(((Insn >> 64) & Mask).to_ullong()) << 64;

  auto DecodeToMCInst = [&Insn](unsigned DecodeIdx, DecodeStatus S, MCInst &MI,
                                 uint64_t Address, const MCDisassembler *DisAsm,
                                 bool &DecodeComplete) {
    return decodeToMCInst96(DecodeIdx, S, Insn, MI, Address, DisAsm, DecodeComplete);
  };
  return decodeInstructionImpl(DecodeTable, MI, InsnMaxWidth, Address, DisAsm, STI, DecodeToMCInst);
}

static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
    const std::bitset<128> &Insn, uint64_t Address, const MCDisassembler *DisAsm,
    const MCSubtargetInfo &STI) {
  std::bitset<128> InsnMaxWidth = Insn;
  auto DecodeToMCInst = [&Insn](unsigned DecodeIdx, DecodeStatus S, MCInst &MI,
                                 uint64_t Address, const MCDisassembler *DisAsm,
                                 bool &DecodeComplete) {
    return decodeToMCInst128(DecodeIdx, S, Insn, MI, Address, DisAsm, DecodeComplete);
  };
  return decodeInstructionImpl(DecodeTable, MI, InsnMaxWidth, Address, DisAsm, STI, DecodeToMCInst);
}
```

So each bit-width specific `decodeInstruction` up-converts the inst bits to max-width and then calls `decodeInstructionImpl`. In the final decode step (handling of OPC_Decode, we call the passed in lambda, so that code still operates on the native smaller instruction woidth).


https://github.com/llvm/llvm-project/pull/146593


More information about the llvm-commits mailing list