CodeBeadsGen.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. #include "CodeGenTarget.h"
  22. #include "llvm/ADT/StringExtras.h"
  23. #include "llvm/Support/Debug.h"
  24. #include "llvm/TableGen/Error.h"
  25. #include "llvm/TableGen/Record.h"
  26. #include "llvm/TableGen/TableGenBackend.h"
  27. #include <map>
  28. #include <string>
  29. #include <vector>
  30. using namespace llvm;
  31. namespace {
  32. class CodeBeadsGen {
  33. RecordKeeper &Records;
  34. public:
  35. CodeBeadsGen(RecordKeeper &R) : Records(R) {}
  36. void run(raw_ostream &OS);
  37. };
  38. void CodeBeadsGen::run(raw_ostream &OS) {
  39. CodeGenTarget Target(Records);
  40. std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
  41. // For little-endian instruction bit encodings, reverse the bit order
  42. Target.reverseBitsForLittleEndianEncoding();
  43. ArrayRef<const CodeGenInstruction *> NumberedInstructions =
  44. Target.getInstructionsByEnumValue();
  45. // Emit function declaration
  46. OS << "const uint8_t *llvm::" << Target.getInstNamespace();
  47. OS << "::getMCInstrBeads(unsigned Opcode) {\n";
  48. // First, get the maximum bit length among all beads. And do some
  49. // simple validation
  50. unsigned MaxBitLength = 0;
  51. for (const CodeGenInstruction *CGI : NumberedInstructions) {
  52. Record *R = CGI->TheDef;
  53. if (!R->getValue("Beads"))
  54. continue;
  55. BitsInit *BI = R->getValueAsBitsInit("Beads");
  56. if (!BI->isComplete()) {
  57. PrintFatalError(R->getLoc(), "Record `" + R->getName() +
  58. "', bit field 'Beads' is not complete");
  59. }
  60. MaxBitLength = std::max(MaxBitLength, BI->getNumBits());
  61. }
  62. // Number of bytes
  63. unsigned Parts = MaxBitLength / 8;
  64. // Emit instruction base values
  65. OS << " static const uint8_t InstBits[][" << Parts << "] = {\n";
  66. for (const CodeGenInstruction *CGI : NumberedInstructions) {
  67. Record *R = CGI->TheDef;
  68. if (R->getValueAsString("Namespace") == "TargetOpcode" ||
  69. !R->getValue("Beads")) {
  70. OS << "\t{ 0x0 },\t// ";
  71. if (R->getValueAsBit("isPseudo"))
  72. OS << "(Pseudo) ";
  73. OS << R->getName() << "\n";
  74. continue;
  75. }
  76. BitsInit *BI = R->getValueAsBitsInit("Beads");
  77. // Convert to byte array:
  78. // [dcba] -> [a][b][c][d]
  79. OS << "\t{";
  80. for (unsigned p = 0; p < Parts; ++p) {
  81. unsigned Right = 8 * p;
  82. unsigned Left = Right + 8;
  83. uint8_t Value = 0;
  84. for (unsigned i = Right; i != Left; ++i) {
  85. unsigned Shift = i % 8;
  86. if (auto *B = dyn_cast<BitInit>(BI->getBit(i))) {
  87. Value |= (static_cast<uint8_t>(B->getValue()) << Shift);
  88. } else {
  89. PrintFatalError(R->getLoc(), "Record `" + R->getName() +
  90. "', bit 'Beads[" + Twine(i) +
  91. "]' is not defined");
  92. }
  93. }
  94. if (p)
  95. OS << ',';
  96. OS << " 0x";
  97. OS.write_hex(Value);
  98. OS << "";
  99. }
  100. OS << " }," << '\t' << "// " << R->getName() << "\n";
  101. }
  102. OS << "\t{ 0x0 }\n };\n";
  103. // Emit initial function code
  104. OS << " return InstBits[Opcode];\n"
  105. << "}\n\n";
  106. }
  107. } // End anonymous namespace
  108. namespace llvm {
  109. void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) {
  110. emitSourceFileHeader("Machine Code Beads", OS);
  111. CodeBeadsGen(RK).run(OS);
  112. }
  113. } // namespace llvm