aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/lib/CodeGen/AsmPrinter/ByteStreamer.h
blob: bd2c60eadd61291f91f8ae09f42530ea6d4e256c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains a class that can take bytes that would normally be
// streamed via the AsmPrinter.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H

#include "DIEHash.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/LEB128.h"
#include <string>

namespace llvm {
class ByteStreamer {
 protected:
  ~ByteStreamer() = default;
  ByteStreamer(const ByteStreamer&) = default;
  ByteStreamer() = default;

 public:
  // For now we're just handling the calls we need for dwarf emission/hashing.
  virtual void emitInt8(uint8_t Byte, const Twine &Comment = "") = 0;
  virtual void emitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0;
  virtual void emitULEB128(uint64_t DWord, const Twine &Comment = "",
                           unsigned PadTo = 0) = 0;
  virtual unsigned emitDIERef(const DIE &D) = 0;
};

class APByteStreamer final : public ByteStreamer {
private:
  AsmPrinter &AP;

public:
  APByteStreamer(AsmPrinter &Asm) : AP(Asm) {}
  void emitInt8(uint8_t Byte, const Twine &Comment) override {
    AP.OutStreamer->AddComment(Comment);
    AP.emitInt8(Byte);
  }
  void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
    AP.OutStreamer->AddComment(Comment);
    AP.emitSLEB128(DWord);
  }
  void emitULEB128(uint64_t DWord, const Twine &Comment,
                   unsigned PadTo) override {
    AP.OutStreamer->AddComment(Comment);
    AP.emitULEB128(DWord, nullptr, PadTo);
  }
  unsigned emitDIERef(const DIE &D) override {
    uint64_t Offset = D.getOffset();
    static constexpr unsigned ULEB128PadSize = 4;
    assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit");
    emitULEB128(Offset, "", ULEB128PadSize);
    // Return how many comments to skip in DwarfDebug::emitDebugLocEntry to keep
    // comments aligned with debug loc entries.
    return ULEB128PadSize;
  }
};

class HashingByteStreamer final : public ByteStreamer {
 private:
  DIEHash &Hash;
 public:
   HashingByteStreamer(DIEHash &H) : Hash(H) {}
   void emitInt8(uint8_t Byte, const Twine &Comment) override {
     Hash.update(Byte);
  }
  void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
    Hash.addSLEB128(DWord);
  }
  void emitULEB128(uint64_t DWord, const Twine &Comment,
                   unsigned PadTo) override {
    Hash.addULEB128(DWord);
  }
  unsigned emitDIERef(const DIE &D) override {
    Hash.hashRawTypeReference(D);
    return 0; // Only used together with the APByteStreamer.
  }
};

class BufferByteStreamer final : public ByteStreamer {
private:
  SmallVectorImpl<char> &Buffer;
  std::vector<std::string> &Comments;

public:
  /// Only verbose textual output needs comments.  This will be set to
  /// true for that case, and false otherwise.  If false, comments passed in to
  /// the emit methods will be ignored.
  const bool GenerateComments;

  BufferByteStreamer(SmallVectorImpl<char> &Buffer,
                     std::vector<std::string> &Comments, bool GenerateComments)
      : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {
  }
  void emitInt8(uint8_t Byte, const Twine &Comment) override {
    Buffer.push_back(Byte);
    if (GenerateComments)
      Comments.push_back(Comment.str());
  }
  void emitSLEB128(uint64_t DWord, const Twine &Comment) override {
    raw_svector_ostream OSE(Buffer);
    unsigned Length = encodeSLEB128(DWord, OSE);
    if (GenerateComments) {
      Comments.push_back(Comment.str());
      // Add some empty comments to keep the Buffer and Comments vectors aligned
      // with each other.
      for (size_t i = 1; i < Length; ++i)
        Comments.push_back("");

    }
  }
  void emitULEB128(uint64_t DWord, const Twine &Comment,
                   unsigned PadTo) override {
    raw_svector_ostream OSE(Buffer);
    unsigned Length = encodeULEB128(DWord, OSE, PadTo);
    if (GenerateComments) {
      Comments.push_back(Comment.str());
      // Add some empty comments to keep the Buffer and Comments vectors aligned
      // with each other.
      for (size_t i = 1; i < Length; ++i)
        Comments.push_back("");
    }
  }
  unsigned emitDIERef(const DIE &D) override {
    uint64_t Offset = D.getOffset();
    static constexpr unsigned ULEB128PadSize = 4;
    assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit");
    emitULEB128(Offset, "", ULEB128PadSize);
    return 0; // Only used together with the APByteStreamer.
  }
};

}

#endif