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