aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/CodeBeadsGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/CodeBeadsGen.cpp')
-rw-r--r--llvm/utils/TableGen/CodeBeadsGen.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/llvm/utils/TableGen/CodeBeadsGen.cpp b/llvm/utils/TableGen/CodeBeadsGen.cpp
new file mode 100644
index 000000000000..18a6d6d19eb2
--- /dev/null
+++ b/llvm/utils/TableGen/CodeBeadsGen.cpp
@@ -0,0 +1,137 @@
+//===---------- 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