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 };
37 
38 class APByteStreamer final : public ByteStreamer {
39 private:
40   AsmPrinter &AP;
41 
42 public:
43   APByteStreamer(AsmPrinter &Asm) : AP(Asm) {}
44   void emitInt8(uint8_t Byte, const Twine &Comment) override {
45     AP.OutStreamer->AddComment(Comment);
46     AP.emitInt8(Byte);
47   }
48   void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
49     AP.OutStreamer->AddComment(Comment);
50     AP.emitSLEB128(DWord);
51   }
52   void emitULEB128(uint64_t DWord, const Twine &Comment,
53                    unsigned PadTo) override {
54     AP.OutStreamer->AddComment(Comment);
55     AP.emitULEB128(DWord, nullptr, PadTo);
56   }
57 };
58 
59 class HashingByteStreamer final : public ByteStreamer {
60  private:
61   DIEHash &Hash;
62  public:
63  HashingByteStreamer(DIEHash &H) : Hash(H) {}
64   void emitInt8(uint8_t Byte, const Twine &Comment) override {
65     Hash.update(Byte);
66   }
67   void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
68     Hash.addSLEB128(DWord);
69   }
70   void emitULEB128(uint64_t DWord, const Twine &Comment,
71                    unsigned PadTo) override {
72     Hash.addULEB128(DWord);
73   }
74 };
75 
76 class BufferByteStreamer final : public ByteStreamer {
77 private:
78   SmallVectorImpl<char> &Buffer;
79   std::vector<std::string> &Comments;
80 
81 public:
82   /// Only verbose textual output needs comments.  This will be set to
83   /// true for that case, and false otherwise.  If false, comments passed in to
84   /// the emit methods will be ignored.
85   const bool GenerateComments;
86 
87   BufferByteStreamer(SmallVectorImpl<char> &Buffer,
88                      std::vector<std::string> &Comments, bool GenerateComments)
89       : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {
90   }
91   void emitInt8(uint8_t Byte, const Twine &Comment) override {
92     Buffer.push_back(Byte);
93     if (GenerateComments)
94       Comments.push_back(Comment.str());
95   }
96   void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
97     raw_svector_ostream OSE(Buffer);
98     unsigned Length = encodeSLEB128(DWord, OSE);
99     if (GenerateComments) {
100       Comments.push_back(Comment.str());
101       // Add some empty comments to keep the Buffer and Comments vectors aligned
102       // with each other.
103       for (size_t i = 1; i < Length; ++i)
104         Comments.push_back("");
105 
106     }
107   }
108   void emitULEB128(uint64_t DWord, const Twine &Comment,
109                    unsigned PadTo) override {
110     raw_svector_ostream OSE(Buffer);
111     unsigned Length = encodeULEB128(DWord, OSE, PadTo);
112     if (GenerateComments) {
113       Comments.push_back(Comment.str());
114       // Add some empty comments to keep the Buffer and Comments vectors aligned
115       // with each other.
116       for (size_t i = 1; i < Length; ++i)
117         Comments.push_back("");
118 
119     }
120   }
121 };
122 
123 }
124 
125 #endif
126