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 void 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   void 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   }
64 };
65 
66 class HashingByteStreamer final : public ByteStreamer {
67  private:
68   DIEHash &Hash;
69  public:
70    HashingByteStreamer(DIEHash &H) : Hash(H) {}
71    void emitInt8(uint8_t Byte, const Twine &Comment) override {
72      Hash.update(Byte);
73   }
74   void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
75     Hash.addSLEB128(DWord);
76   }
77   void emitULEB128(uint64_t DWord, const Twine &Comment,
78                    unsigned PadTo) override {
79     Hash.addULEB128(DWord);
80   }
81   void emitDIERef(const DIE &D) override { Hash.hashRawTypeReference(D); }
82 };
83 
84 class BufferByteStreamer final : public ByteStreamer {
85 private:
86   SmallVectorImpl<char> &Buffer;
87   std::vector<std::string> &Comments;
88 
89 public:
90   /// Only verbose textual output needs comments.  This will be set to
91   /// true for that case, and false otherwise.  If false, comments passed in to
92   /// the emit methods will be ignored.
93   const bool GenerateComments;
94 
95   BufferByteStreamer(SmallVectorImpl<char> &Buffer,
96                      std::vector<std::string> &Comments, bool GenerateComments)
97       : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {
98   }
99   void emitInt8(uint8_t Byte, const Twine &Comment) override {
100     Buffer.push_back(Byte);
101     if (GenerateComments)
102       Comments.push_back(Comment.str());
103   }
104   void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
105     raw_svector_ostream OSE(Buffer);
106     unsigned Length = encodeSLEB128(DWord, OSE);
107     if (GenerateComments) {
108       Comments.push_back(Comment.str());
109       // Add some empty comments to keep the Buffer and Comments vectors aligned
110       // with each other.
111       for (size_t i = 1; i < Length; ++i)
112         Comments.push_back("");
113 
114     }
115   }
116   void emitULEB128(uint64_t DWord, const Twine &Comment,
117                    unsigned PadTo) override {
118     raw_svector_ostream OSE(Buffer);
119     unsigned Length = encodeULEB128(DWord, OSE, PadTo);
120     if (GenerateComments) {
121       Comments.push_back(Comment.str());
122       // Add some empty comments to keep the Buffer and Comments vectors aligned
123       // with each other.
124       for (size_t i = 1; i < Length; ++i)
125         Comments.push_back("");
126     }
127   }
128   void emitDIERef(const DIE &D) override {
129     uint64_t Offset = D.getOffset();
130     static constexpr unsigned ULEB128PadSize = 4;
131     assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit");
132     emitULEB128(Offset, "", ULEB128PadSize);
133   }
134 };
135 
136 }
137 
138 #endif
139