123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- //===---------- CodeBeadsGen.cpp - Code Beads Generator -------------------===//
- //
- // 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
- //
- //===----------------------------------------------------------------------===//
- // CodeBeads are data fields carrying auxiliary information for instructions.
- //
- // Under the hood it's simply implemented by a `bits` field (with arbitrary
- // length) in each TG instruction description, where this TG backend will
- // generate a helper function to access it.
- //
- // This is especially useful for expressing variable length encoding
- // instructions and complex addressing modes. Since in those cases each
- // instruction is usually associated with large amount of information like
- // addressing mode details used on a specific operand. Instead of retreating to
- // ad-hoc methods to figure out these information when encoding an instruction,
- // CodeBeads provide a clean table for the instruction encoder to lookup.
- //===----------------------------------------------------------------------===//
- #include "CodeGenTarget.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/TableGen/Error.h"
- #include "llvm/TableGen/Record.h"
- #include "llvm/TableGen/TableGenBackend.h"
- #include <map>
- #include <string>
- #include <vector>
- using namespace llvm;
- namespace {
- class CodeBeadsGen {
- RecordKeeper &Records;
- public:
- CodeBeadsGen(RecordKeeper &R) : Records(R) {}
- void run(raw_ostream &OS);
- };
- void CodeBeadsGen::run(raw_ostream &OS) {
- CodeGenTarget Target(Records);
- std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
- // For little-endian instruction bit encodings, reverse the bit order
- Target.reverseBitsForLittleEndianEncoding();
- ArrayRef<const CodeGenInstruction *> NumberedInstructions =
- Target.getInstructionsByEnumValue();
- // Emit function declaration
- OS << "const uint8_t *llvm::" << Target.getInstNamespace();
- OS << "::getMCInstrBeads(unsigned Opcode) {\n";
- // First, get the maximum bit length among all beads. And do some
- // simple validation
- unsigned MaxBitLength = 0;
- for (const CodeGenInstruction *CGI : NumberedInstructions) {
- Record *R = CGI->TheDef;
- if (!R->getValue("Beads"))
- continue;
- BitsInit *BI = R->getValueAsBitsInit("Beads");
- if (!BI->isComplete()) {
- PrintFatalError(R->getLoc(), "Record `" + R->getName() +
- "', bit field 'Beads' is not complete");
- }
- MaxBitLength = std::max(MaxBitLength, BI->getNumBits());
- }
- // Number of bytes
- unsigned Parts = MaxBitLength / 8;
- // Emit instruction base values
- OS << " static const uint8_t InstBits[][" << Parts << "] = {\n";
- for (const CodeGenInstruction *CGI : NumberedInstructions) {
- Record *R = CGI->TheDef;
- if (R->getValueAsString("Namespace") == "TargetOpcode" ||
- !R->getValue("Beads")) {
- OS << "\t{ 0x0 },\t// ";
- if (R->getValueAsBit("isPseudo"))
- OS << "(Pseudo) ";
- OS << R->getName() << "\n";
- continue;
- }
- BitsInit *BI = R->getValueAsBitsInit("Beads");
- // Convert to byte array:
- // [dcba] -> [a][b][c][d]
- OS << "\t{";
- for (unsigned p = 0; p < Parts; ++p) {
- unsigned Right = 8 * p;
- unsigned Left = Right + 8;
- uint8_t Value = 0;
- for (unsigned i = Right; i != Left; ++i) {
- unsigned Shift = i % 8;
- if (auto *B = dyn_cast<BitInit>(BI->getBit(i))) {
- Value |= (static_cast<uint8_t>(B->getValue()) << Shift);
- } else {
- PrintFatalError(R->getLoc(), "Record `" + R->getName() +
- "', bit 'Beads[" + Twine(i) +
- "]' is not defined");
- }
- }
- if (p)
- OS << ',';
- OS << " 0x";
- OS.write_hex(Value);
- OS << "";
- }
- OS << " }," << '\t' << "// " << R->getName() << "\n";
- }
- OS << "\t{ 0x0 }\n };\n";
- // Emit initial function code
- OS << " return InstBits[Opcode];\n"
- << "}\n\n";
- }
- } // End anonymous namespace
- namespace llvm {
- void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) {
- emitSourceFileHeader("Machine Code Beads", OS);
- CodeBeadsGen(RK).run(OS);
- }
- } // namespace llvm
|