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. 13 // 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 //===----------------------------------------------------------------------===// 21 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; 32 33 namespace { 34 35 class CodeBeadsGen { 36 RecordKeeper &Records; 37 38 public: 39 CodeBeadsGen(RecordKeeper &R) : Records(R) {} 40 void run(raw_ostream &OS); 41 }; 42 43 void CodeBeadsGen::run(raw_ostream &OS) { 44 CodeGenTarget Target(Records); 45 std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction"); 46 47 // For little-endian instruction bit encodings, reverse the bit order 48 Target.reverseBitsForLittleEndianEncoding(); 49 50 ArrayRef<const CodeGenInstruction *> NumberedInstructions = 51 Target.getInstructionsByEnumValue(); 52 53 // Emit function declaration 54 OS << "const uint8_t *llvm::" << Target.getInstNamespace(); 55 OS << "::getMCInstrBeads(unsigned Opcode) {\n"; 56 57 // First, get the maximum bit length among all beads. And do some 58 // simple validation 59 unsigned MaxBitLength = 0; 60 61 for (const CodeGenInstruction *CGI : NumberedInstructions) { 62 Record *R = CGI->TheDef; 63 if (!R->getValue("Beads")) 64 continue; 65 66 BitsInit *BI = R->getValueAsBitsInit("Beads"); 67 if (!BI->isComplete()) { 68 PrintFatalError(R->getLoc(), "Record `" + R->getName() + 69 "', bit field 'Beads' is not complete"); 70 } 71 72 MaxBitLength = std::max(MaxBitLength, BI->getNumBits()); 73 } 74 75 // Number of bytes 76 unsigned Parts = MaxBitLength / 8; 77 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; 82 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; 90 } 91 92 BitsInit *BI = R->getValueAsBitsInit("Beads"); 93 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; 100 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"); 110 } 111 } 112 113 if (p) 114 OS << ','; 115 OS << " 0x"; 116 OS.write_hex(Value); 117 OS << ""; 118 } 119 OS << " }," << '\t' << "// " << R->getName() << "\n"; 120 } 121 OS << "\t{ 0x0 }\n };\n"; 122 123 // Emit initial function code 124 OS << " return InstBits[Opcode];\n" 125 << "}\n\n"; 126 } 127 128 } // End anonymous namespace 129 130 namespace llvm { 131 132 void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) { 133 emitSourceFileHeader("Machine Code Beads", OS); 134 CodeBeadsGen(RK).run(OS); 135 } 136 137 } // namespace llvm 138