187866Ssheldonh//===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- C++ -*-===//
287866Ssheldonh//
387866Ssheldonh// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
487866Ssheldonh// See https://llvm.org/LICENSE.txt for license information.
587866Ssheldonh// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
687866Ssheldonh//
787866Ssheldonh//===----------------------------------------------------------------------===//
887866Ssheldonh//
987866Ssheldonh// This file contains a class that can take bytes that would normally be
1087866Ssheldonh// streamed via the AsmPrinter.
1187866Ssheldonh//
1287866Ssheldonh//===----------------------------------------------------------------------===//
1387866Ssheldonh
1487866Ssheldonh#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H
1587866Ssheldonh#define LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H
1687866Ssheldonh
1787866Ssheldonh#include "DIEHash.h"
1887866Ssheldonh#include "llvm/CodeGen/AsmPrinter.h"
1987866Ssheldonh#include "llvm/MC/MCStreamer.h"
2087866Ssheldonh#include "llvm/Support/LEB128.h"
2187866Ssheldonh#include <string>
2287866Ssheldonh
2387866Ssheldonhnamespace llvm {
2487866Ssheldonhclass ByteStreamer {
2587866Ssheldonh protected:
2687866Ssheldonh  ~ByteStreamer() = default;
2787866Ssheldonh  ByteStreamer(const ByteStreamer&) = default;
2887866Ssheldonh  ByteStreamer() = default;
2987866Ssheldonh
3087866Ssheldonh public:
3187866Ssheldonh  // For now we're just handling the calls we need for dwarf emission/hashing.
3287866Ssheldonh  virtual void EmitInt8(uint8_t Byte, const Twine &Comment = "") = 0;
33132752Skan  virtual void EmitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0;
3487866Ssheldonh  virtual void EmitULEB128(uint64_t DWord, const Twine &Comment = "", unsigned PadTo = 0) = 0;
3587866Ssheldonh};
3687866Ssheldonh
3787866Ssheldonhclass APByteStreamer final : public ByteStreamer {
3887866Ssheldonhprivate:
3987866Ssheldonh  AsmPrinter &AP;
4087866Ssheldonh
4187866Ssheldonhpublic:
4287866Ssheldonh  APByteStreamer(AsmPrinter &Asm) : AP(Asm) {}
4387866Ssheldonh  void EmitInt8(uint8_t Byte, const Twine &Comment) override {
4487866Ssheldonh    AP.OutStreamer->AddComment(Comment);
4587866Ssheldonh    AP.emitInt8(Byte);
4687866Ssheldonh  }
4787866Ssheldonh  void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
4887866Ssheldonh    AP.OutStreamer->AddComment(Comment);
4987866Ssheldonh    AP.EmitSLEB128(DWord);
5087866Ssheldonh  }
5187866Ssheldonh  void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override {
5287866Ssheldonh    AP.OutStreamer->AddComment(Comment);
5387866Ssheldonh    AP.EmitULEB128(DWord);
5487866Ssheldonh  }
5587866Ssheldonh};
5687866Ssheldonh
5787866Ssheldonhclass HashingByteStreamer final : public ByteStreamer {
5887866Ssheldonh private:
5987866Ssheldonh  DIEHash &Hash;
6087866Ssheldonh public:
6187866Ssheldonh HashingByteStreamer(DIEHash &H) : Hash(H) {}
6287866Ssheldonh  void EmitInt8(uint8_t Byte, const Twine &Comment) override {
6387866Ssheldonh    Hash.update(Byte);
6487866Ssheldonh  }
6587866Ssheldonh  void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
6687866Ssheldonh    Hash.addSLEB128(DWord);
6787866Ssheldonh  }
6887866Ssheldonh  void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override {
6987866Ssheldonh    Hash.addULEB128(DWord);
7087866Ssheldonh  }
7187866Ssheldonh};
7287866Ssheldonh
7387866Ssheldonhclass BufferByteStreamer final : public ByteStreamer {
7487866Ssheldonhprivate:
75132752Skan  SmallVectorImpl<char> &Buffer;
7687866Ssheldonh  std::vector<std::string> &Comments;
7787866Ssheldonh
7887866Ssheldonhpublic:
7987866Ssheldonh  /// Only verbose textual output needs comments.  This will be set to
8087866Ssheldonh  /// true for that case, and false otherwise.  If false, comments passed in to
8187866Ssheldonh  /// the emit methods will be ignored.
82  const bool GenerateComments;
83
84  BufferByteStreamer(SmallVectorImpl<char> &Buffer,
85                     std::vector<std::string> &Comments, bool GenerateComments)
86      : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {
87  }
88  void EmitInt8(uint8_t Byte, const Twine &Comment) override {
89    Buffer.push_back(Byte);
90    if (GenerateComments)
91      Comments.push_back(Comment.str());
92  }
93  void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
94    raw_svector_ostream OSE(Buffer);
95    unsigned Length = encodeSLEB128(DWord, OSE);
96    if (GenerateComments) {
97      Comments.push_back(Comment.str());
98      // Add some empty comments to keep the Buffer and Comments vectors aligned
99      // with each other.
100      for (size_t i = 1; i < Length; ++i)
101        Comments.push_back("");
102
103    }
104  }
105  void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override {
106    raw_svector_ostream OSE(Buffer);
107    unsigned Length = encodeULEB128(DWord, OSE, PadTo);
108    if (GenerateComments) {
109      Comments.push_back(Comment.str());
110      // Add some empty comments to keep the Buffer and Comments vectors aligned
111      // with each other.
112      for (size_t i = 1; i < Length; ++i)
113        Comments.push_back("");
114
115    }
116  }
117};
118
119}
120
121#endif
122