ByteStreamer.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. //===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- C++ -*-===//
  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. //
  9. // This file contains a class that can take bytes that would normally be
  10. // streamed via the AsmPrinter.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H
  14. #define LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H
  15. #include "DIEHash.h"
  16. #include "llvm/CodeGen/AsmPrinter.h"
  17. #include "llvm/MC/MCStreamer.h"
  18. #include "llvm/Support/LEB128.h"
  19. #include <string>
  20. namespace llvm {
  21. class ByteStreamer {
  22. protected:
  23. ~ByteStreamer() = default;
  24. ByteStreamer(const ByteStreamer&) = default;
  25. ByteStreamer() = default;
  26. public:
  27. // For now we're just handling the calls we need for dwarf emission/hashing.
  28. virtual void emitInt8(uint8_t Byte, const Twine &Comment = "") = 0;
  29. virtual void emitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0;
  30. virtual void emitULEB128(uint64_t DWord, const Twine &Comment = "",
  31. unsigned PadTo = 0) = 0;
  32. virtual unsigned emitDIERef(const DIE &D) = 0;
  33. };
  34. class APByteStreamer final : public ByteStreamer {
  35. private:
  36. AsmPrinter &AP;
  37. public:
  38. APByteStreamer(AsmPrinter &Asm) : AP(Asm) {}
  39. void emitInt8(uint8_t Byte, const Twine &Comment) override {
  40. AP.OutStreamer->AddComment(Comment);
  41. AP.emitInt8(Byte);
  42. }
  43. void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
  44. AP.OutStreamer->AddComment(Comment);
  45. AP.emitSLEB128(DWord);
  46. }
  47. void emitULEB128(uint64_t DWord, const Twine &Comment,
  48. unsigned PadTo) override {
  49. AP.OutStreamer->AddComment(Comment);
  50. AP.emitULEB128(DWord, nullptr, PadTo);
  51. }
  52. unsigned emitDIERef(const DIE &D) override {
  53. uint64_t Offset = D.getOffset();
  54. static constexpr unsigned ULEB128PadSize = 4;
  55. assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit");
  56. emitULEB128(Offset, "", ULEB128PadSize);
  57. // Return how many comments to skip in DwarfDebug::emitDebugLocEntry to keep
  58. // comments aligned with debug loc entries.
  59. return ULEB128PadSize;
  60. }
  61. };
  62. class HashingByteStreamer final : public ByteStreamer {
  63. private:
  64. DIEHash &Hash;
  65. public:
  66. HashingByteStreamer(DIEHash &H) : Hash(H) {}
  67. void emitInt8(uint8_t Byte, const Twine &Comment) override {
  68. Hash.update(Byte);
  69. }
  70. void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
  71. Hash.addSLEB128(DWord);
  72. }
  73. void emitULEB128(uint64_t DWord, const Twine &Comment,
  74. unsigned PadTo) override {
  75. Hash.addULEB128(DWord);
  76. }
  77. unsigned emitDIERef(const DIE &D) override {
  78. Hash.hashRawTypeReference(D);
  79. return 0; // Only used together with the APByteStreamer.
  80. }
  81. };
  82. class BufferByteStreamer final : public ByteStreamer {
  83. private:
  84. SmallVectorImpl<char> &Buffer;
  85. std::vector<std::string> &Comments;
  86. public:
  87. /// Only verbose textual output needs comments. This will be set to
  88. /// true for that case, and false otherwise. If false, comments passed in to
  89. /// the emit methods will be ignored.
  90. const bool GenerateComments;
  91. BufferByteStreamer(SmallVectorImpl<char> &Buffer,
  92. std::vector<std::string> &Comments, bool GenerateComments)
  93. : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {
  94. }
  95. void emitInt8(uint8_t Byte, const Twine &Comment) override {
  96. Buffer.push_back(Byte);
  97. if (GenerateComments)
  98. Comments.push_back(Comment.str());
  99. }
  100. void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
  101. raw_svector_ostream OSE(Buffer);
  102. unsigned Length = encodeSLEB128(DWord, OSE);
  103. if (GenerateComments) {
  104. Comments.push_back(Comment.str());
  105. // Add some empty comments to keep the Buffer and Comments vectors aligned
  106. // with each other.
  107. for (size_t i = 1; i < Length; ++i)
  108. Comments.push_back("");
  109. }
  110. }
  111. void emitULEB128(uint64_t DWord, const Twine &Comment,
  112. unsigned PadTo) override {
  113. raw_svector_ostream OSE(Buffer);
  114. unsigned Length = encodeULEB128(DWord, OSE, PadTo);
  115. if (GenerateComments) {
  116. Comments.push_back(Comment.str());
  117. // Add some empty comments to keep the Buffer and Comments vectors aligned
  118. // with each other.
  119. for (size_t i = 1; i < Length; ++i)
  120. Comments.push_back("");
  121. }
  122. }
  123. unsigned emitDIERef(const DIE &D) override {
  124. uint64_t Offset = D.getOffset();
  125. static constexpr unsigned ULEB128PadSize = 4;
  126. assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit");
  127. emitULEB128(Offset, "", ULEB128PadSize);
  128. return 0; // Only used together with the APByteStreamer.
  129. }
  130. };
  131. }
  132. #endif