[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / utils / TableGen / CodeBeadsGen.cpp
blob18a6d6d19eb232ff71ac5eac951fb5e01ac2184e
1 //===---------- CodeBeadsGen.cpp - Code Beads Generator -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 // CodeBeads are data fields carrying auxiliary information for instructions.
9 //
10 // Under the hood it's simply implemented by a `bits` field (with arbitrary
11 // length) in each TG instruction description, where this TG backend will
12 // generate a helper function to access it.
14 // This is especially useful for expressing variable length encoding
15 // instructions and complex addressing modes. Since in those cases each
16 // instruction is usually associated with large amount of information like
17 // addressing mode details used on a specific operand. Instead of retreating to
18 // ad-hoc methods to figure out these information when encoding an instruction,
19 // CodeBeads provide a clean table for the instruction encoder to lookup.
20 //===----------------------------------------------------------------------===//
22 #include "CodeGenTarget.h"
23 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/TableGen/Error.h"
26 #include "llvm/TableGen/Record.h"
27 #include "llvm/TableGen/TableGenBackend.h"
28 #include <map>
29 #include <string>
30 #include <vector>
31 using namespace llvm;
33 namespace {
35 class CodeBeadsGen {
36 RecordKeeper &Records;
38 public:
39 CodeBeadsGen(RecordKeeper &R) : Records(R) {}
40 void run(raw_ostream &OS);
43 void CodeBeadsGen::run(raw_ostream &OS) {
44 CodeGenTarget Target(Records);
45 std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
47 // For little-endian instruction bit encodings, reverse the bit order
48 Target.reverseBitsForLittleEndianEncoding();
50 ArrayRef<const CodeGenInstruction *> NumberedInstructions =
51 Target.getInstructionsByEnumValue();
53 // Emit function declaration
54 OS << "const uint8_t *llvm::" << Target.getInstNamespace();
55 OS << "::getMCInstrBeads(unsigned Opcode) {\n";
57 // First, get the maximum bit length among all beads. And do some
58 // simple validation
59 unsigned MaxBitLength = 0;
61 for (const CodeGenInstruction *CGI : NumberedInstructions) {
62 Record *R = CGI->TheDef;
63 if (!R->getValue("Beads"))
64 continue;
66 BitsInit *BI = R->getValueAsBitsInit("Beads");
67 if (!BI->isComplete()) {
68 PrintFatalError(R->getLoc(), "Record `" + R->getName() +
69 "', bit field 'Beads' is not complete");
72 MaxBitLength = std::max(MaxBitLength, BI->getNumBits());
75 // Number of bytes
76 unsigned Parts = MaxBitLength / 8;
78 // Emit instruction base values
79 OS << " static const uint8_t InstBits[][" << Parts << "] = {\n";
80 for (const CodeGenInstruction *CGI : NumberedInstructions) {
81 Record *R = CGI->TheDef;
83 if (R->getValueAsString("Namespace") == "TargetOpcode" ||
84 !R->getValue("Beads")) {
85 OS << "\t{ 0x0 },\t// ";
86 if (R->getValueAsBit("isPseudo"))
87 OS << "(Pseudo) ";
88 OS << R->getName() << "\n";
89 continue;
92 BitsInit *BI = R->getValueAsBitsInit("Beads");
94 // Convert to byte array:
95 // [dcba] -> [a][b][c][d]
96 OS << "\t{";
97 for (unsigned p = 0; p < Parts; ++p) {
98 unsigned Right = 8 * p;
99 unsigned Left = Right + 8;
101 uint8_t Value = 0;
102 for (unsigned i = Right; i != Left; ++i) {
103 unsigned Shift = i % 8;
104 if (auto *B = dyn_cast<BitInit>(BI->getBit(i))) {
105 Value |= (static_cast<uint8_t>(B->getValue()) << Shift);
106 } else {
107 PrintFatalError(R->getLoc(), "Record `" + R->getName() +
108 "', bit 'Beads[" + Twine(i) +
109 "]' is not defined");
113 if (p)
114 OS << ',';
115 OS << " 0x";
116 OS.write_hex(Value);
117 OS << "";
119 OS << " }," << '\t' << "// " << R->getName() << "\n";
121 OS << "\t{ 0x0 }\n };\n";
123 // Emit initial function code
124 OS << " return InstBits[Opcode];\n"
125 << "}\n\n";
128 } // End anonymous namespace
130 namespace llvm {
132 void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) {
133 emitSourceFileHeader("Machine Code Beads", OS);
134 CodeBeadsGen(RK).run(OS);
137 } // namespace llvm