10b57cec5SDimitry Andric //===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains a class that can take bytes that would normally be 100b57cec5SDimitry Andric // streamed via the AsmPrinter. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H 150b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "DIEHash.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 200b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 210b57cec5SDimitry Andric #include <string> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace llvm { 240b57cec5SDimitry Andric class ByteStreamer { 250b57cec5SDimitry Andric protected: 260b57cec5SDimitry Andric ~ByteStreamer() = default; 270b57cec5SDimitry Andric ByteStreamer(const ByteStreamer&) = default; 280b57cec5SDimitry Andric ByteStreamer() = default; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric public: 310b57cec5SDimitry Andric // For now we're just handling the calls we need for dwarf emission/hashing. 32e8d8bef9SDimitry Andric virtual void emitInt8(uint8_t Byte, const Twine &Comment = "") = 0; 335ffd83dbSDimitry Andric virtual void emitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0; 345ffd83dbSDimitry Andric virtual void emitULEB128(uint64_t DWord, const Twine &Comment = "", 355ffd83dbSDimitry Andric unsigned PadTo = 0) = 0; 3604eeddc0SDimitry Andric virtual unsigned emitDIERef(const DIE &D) = 0; 370b57cec5SDimitry Andric }; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric class APByteStreamer final : public ByteStreamer { 400b57cec5SDimitry Andric private: 410b57cec5SDimitry Andric AsmPrinter &AP; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric public: APByteStreamer(AsmPrinter & Asm)440b57cec5SDimitry Andric APByteStreamer(AsmPrinter &Asm) : AP(Asm) {} emitInt8(uint8_t Byte,const Twine & Comment)45e8d8bef9SDimitry Andric void emitInt8(uint8_t Byte, const Twine &Comment) override { 460b57cec5SDimitry Andric AP.OutStreamer->AddComment(Comment); 470b57cec5SDimitry Andric AP.emitInt8(Byte); 480b57cec5SDimitry Andric } emitSLEB128(uint64_t DWord,const Twine & Comment)495ffd83dbSDimitry Andric void emitSLEB128(uint64_t DWord, const Twine &Comment) override { 500b57cec5SDimitry Andric AP.OutStreamer->AddComment(Comment); 515ffd83dbSDimitry Andric AP.emitSLEB128(DWord); 520b57cec5SDimitry Andric } emitULEB128(uint64_t DWord,const Twine & Comment,unsigned PadTo)535ffd83dbSDimitry Andric void emitULEB128(uint64_t DWord, const Twine &Comment, 545ffd83dbSDimitry Andric unsigned PadTo) override { 550b57cec5SDimitry Andric AP.OutStreamer->AddComment(Comment); 565ffd83dbSDimitry Andric AP.emitULEB128(DWord, nullptr, PadTo); 570b57cec5SDimitry Andric } emitDIERef(const DIE & D)5804eeddc0SDimitry Andric unsigned emitDIERef(const DIE &D) override { 5904eeddc0SDimitry Andric uint64_t Offset = D.getOffset(); 6004eeddc0SDimitry Andric static constexpr unsigned ULEB128PadSize = 4; 6104eeddc0SDimitry Andric assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit"); 6204eeddc0SDimitry Andric emitULEB128(Offset, "", ULEB128PadSize); 6304eeddc0SDimitry Andric // Return how many comments to skip in DwarfDebug::emitDebugLocEntry to keep 6404eeddc0SDimitry Andric // comments aligned with debug loc entries. 6504eeddc0SDimitry Andric return ULEB128PadSize; 6604eeddc0SDimitry Andric } 670b57cec5SDimitry Andric }; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric class HashingByteStreamer final : public ByteStreamer { 700b57cec5SDimitry Andric private: 710b57cec5SDimitry Andric DIEHash &Hash; 720b57cec5SDimitry Andric public: HashingByteStreamer(DIEHash & H)730b57cec5SDimitry Andric HashingByteStreamer(DIEHash &H) : Hash(H) {} emitInt8(uint8_t Byte,const Twine & Comment)74e8d8bef9SDimitry Andric void emitInt8(uint8_t Byte, const Twine &Comment) override { 750b57cec5SDimitry Andric Hash.update(Byte); 760b57cec5SDimitry Andric } emitSLEB128(uint64_t DWord,const Twine & Comment)775ffd83dbSDimitry Andric void emitSLEB128(uint64_t DWord, const Twine &Comment) override { 780b57cec5SDimitry Andric Hash.addSLEB128(DWord); 790b57cec5SDimitry Andric } emitULEB128(uint64_t DWord,const Twine & Comment,unsigned PadTo)805ffd83dbSDimitry Andric void emitULEB128(uint64_t DWord, const Twine &Comment, 815ffd83dbSDimitry Andric unsigned PadTo) override { 820b57cec5SDimitry Andric Hash.addULEB128(DWord); 830b57cec5SDimitry Andric } emitDIERef(const DIE & D)8404eeddc0SDimitry Andric unsigned emitDIERef(const DIE &D) override { 8504eeddc0SDimitry Andric Hash.hashRawTypeReference(D); 8604eeddc0SDimitry Andric return 0; // Only used together with the APByteStreamer. 8704eeddc0SDimitry Andric } 880b57cec5SDimitry Andric }; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric class BufferByteStreamer final : public ByteStreamer { 910b57cec5SDimitry Andric private: 920b57cec5SDimitry Andric SmallVectorImpl<char> &Buffer; 938bcb0991SDimitry Andric std::vector<std::string> &Comments; 940b57cec5SDimitry Andric 958bcb0991SDimitry Andric public: 960b57cec5SDimitry Andric /// Only verbose textual output needs comments. This will be set to 970b57cec5SDimitry Andric /// true for that case, and false otherwise. If false, comments passed in to 980b57cec5SDimitry Andric /// the emit methods will be ignored. 998bcb0991SDimitry Andric const bool GenerateComments; 1000b57cec5SDimitry Andric BufferByteStreamer(SmallVectorImpl<char> & Buffer,std::vector<std::string> & Comments,bool GenerateComments)1010b57cec5SDimitry Andric BufferByteStreamer(SmallVectorImpl<char> &Buffer, 1028bcb0991SDimitry Andric std::vector<std::string> &Comments, bool GenerateComments) 1038bcb0991SDimitry Andric : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) { 1048bcb0991SDimitry Andric } emitInt8(uint8_t Byte,const Twine & Comment)105e8d8bef9SDimitry Andric void emitInt8(uint8_t Byte, const Twine &Comment) override { 1060b57cec5SDimitry Andric Buffer.push_back(Byte); 1070b57cec5SDimitry Andric if (GenerateComments) 1080b57cec5SDimitry Andric Comments.push_back(Comment.str()); 1090b57cec5SDimitry Andric } emitSLEB128(uint64_t DWord,const Twine & Comment)1105ffd83dbSDimitry Andric void emitSLEB128(uint64_t DWord, const Twine &Comment) override { 1110b57cec5SDimitry Andric raw_svector_ostream OSE(Buffer); 1120b57cec5SDimitry Andric unsigned Length = encodeSLEB128(DWord, OSE); 1130b57cec5SDimitry Andric if (GenerateComments) { 1140b57cec5SDimitry Andric Comments.push_back(Comment.str()); 1150b57cec5SDimitry Andric // Add some empty comments to keep the Buffer and Comments vectors aligned 1160b57cec5SDimitry Andric // with each other. 1170b57cec5SDimitry Andric for (size_t i = 1; i < Length; ++i) 1180b57cec5SDimitry Andric Comments.push_back(""); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric } emitULEB128(uint64_t DWord,const Twine & Comment,unsigned PadTo)1225ffd83dbSDimitry Andric void emitULEB128(uint64_t DWord, const Twine &Comment, 1235ffd83dbSDimitry Andric unsigned PadTo) override { 1240b57cec5SDimitry Andric raw_svector_ostream OSE(Buffer); 1250b57cec5SDimitry Andric unsigned Length = encodeULEB128(DWord, OSE, PadTo); 1260b57cec5SDimitry Andric if (GenerateComments) { 1270b57cec5SDimitry Andric Comments.push_back(Comment.str()); 1280b57cec5SDimitry Andric // Add some empty comments to keep the Buffer and Comments vectors aligned 1290b57cec5SDimitry Andric // with each other. 1300b57cec5SDimitry Andric for (size_t i = 1; i < Length; ++i) 1310b57cec5SDimitry Andric Comments.push_back(""); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric } emitDIERef(const DIE & D)13404eeddc0SDimitry Andric unsigned emitDIERef(const DIE &D) override { 13504eeddc0SDimitry Andric uint64_t Offset = D.getOffset(); 13604eeddc0SDimitry Andric static constexpr unsigned ULEB128PadSize = 4; 13704eeddc0SDimitry Andric assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit"); 13804eeddc0SDimitry Andric emitULEB128(Offset, "", ULEB128PadSize); 13904eeddc0SDimitry Andric return 0; // Only used together with the APByteStreamer. 14004eeddc0SDimitry Andric } 1410b57cec5SDimitry Andric }; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric #endif 146