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 & = "" ) = 0; |
33 | virtual void emitSLEB128(uint64_t DWord, const Twine & = "" ) = 0; |
34 | virtual void emitULEB128(uint64_t DWord, const Twine & = "" , |
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 &) override { |
46 | AP.OutStreamer->AddComment(T: Comment); |
47 | AP.emitInt8(Value: Byte); |
48 | } |
49 | void emitSLEB128(uint64_t DWord, const Twine &) override { |
50 | AP.OutStreamer->AddComment(T: Comment); |
51 | AP.emitSLEB128(Value: DWord); |
52 | } |
53 | void emitULEB128(uint64_t DWord, const Twine &, |
54 | unsigned PadTo) override { |
55 | AP.OutStreamer->AddComment(T: Comment); |
56 | AP.emitULEB128(Value: DWord, Desc: 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(DWord: Offset, Comment: "" , PadTo: 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 &) override { |
75 | Hash.update(Value: Byte); |
76 | } |
77 | void emitSLEB128(uint64_t DWord, const Twine &) override { |
78 | Hash.addSLEB128(Value: DWord); |
79 | } |
80 | void emitULEB128(uint64_t DWord, const Twine &, |
81 | unsigned PadTo) override { |
82 | Hash.addULEB128(Value: DWord); |
83 | } |
84 | unsigned emitDIERef(const DIE &D) override { |
85 | Hash.hashRawTypeReference(Entry: 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> &; |
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 ; |
100 | |
101 | BufferByteStreamer(SmallVectorImpl<char> &Buffer, |
102 | std::vector<std::string> &, bool ) |
103 | : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) { |
104 | } |
105 | void emitInt8(uint8_t Byte, const Twine &) override { |
106 | Buffer.push_back(Elt: Byte); |
107 | if (GenerateComments) |
108 | Comments.push_back(x: Comment.str()); |
109 | } |
110 | void emitSLEB128(uint64_t DWord, const Twine &) override { |
111 | raw_svector_ostream OSE(Buffer); |
112 | unsigned Length = encodeSLEB128(Value: DWord, OS&: OSE); |
113 | if (GenerateComments) { |
114 | Comments.push_back(x: 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(x: "" ); |
119 | |
120 | } |
121 | } |
122 | void emitULEB128(uint64_t DWord, const Twine &, |
123 | unsigned PadTo) override { |
124 | raw_svector_ostream OSE(Buffer); |
125 | unsigned Length = encodeULEB128(Value: DWord, OS&: OSE, PadTo); |
126 | if (GenerateComments) { |
127 | Comments.push_back(x: 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(x: "" ); |
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(DWord: Offset, Comment: "" , PadTo: ULEB128PadSize); |
139 | return 0; // Only used together with the APByteStreamer. |
140 | } |
141 | }; |
142 | |
143 | } |
144 | |
145 | #endif |
146 | |