1 //===---------- CodeBeadsGen.cpp - Code Beads Generator -------------------===//
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
7 //===----------------------------------------------------------------------===//
8 // CodeBeads are data fields carrying auxiliary information for instructions.
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"
36 RecordKeeper
&Records
;
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
59 unsigned MaxBitLength
= 0;
61 for (const CodeGenInstruction
*CGI
: NumberedInstructions
) {
62 Record
*R
= CGI
->TheDef
;
63 if (!R
->getValue("Beads"))
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());
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"))
88 OS
<< R
->getName() << "\n";
92 BitsInit
*BI
= R
->getValueAsBitsInit("Beads");
94 // Convert to byte array:
95 // [dcba] -> [a][b][c][d]
97 for (unsigned p
= 0; p
< Parts
; ++p
) {
98 unsigned Right
= 8 * p
;
99 unsigned Left
= Right
+ 8;
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
);
107 PrintFatalError(R
->getLoc(), "Record `" + R
->getName() +
108 "', bit 'Beads[" + Twine(i
) +
109 "]' is not defined");
119 OS
<< " }," << '\t' << "// " << R
->getName() << "\n";
121 OS
<< "\t{ 0x0 }\n };\n";
123 // Emit initial function code
124 OS
<< " return InstBits[Opcode];\n"
128 } // End anonymous namespace
132 void EmitCodeBeads(RecordKeeper
&RK
, raw_ostream
&OS
) {
133 emitSourceFileHeader("Machine Code Beads", OS
);
134 CodeBeadsGen(RK
).run(OS
);