================ @@ -13,81 +13,171 @@ #ifndef LLVM_LIB_REMARKS_BITSTREAM_REMARK_PARSER_H #define LLVM_LIB_REMARKS_BITSTREAM_REMARK_PARSER_H -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Remarks/BitstreamRemarkContainer.h" +#include "llvm/Remarks/Remark.h" #include "llvm/Remarks/RemarkFormat.h" #include "llvm/Remarks/RemarkParser.h" +#include "llvm/Remarks/RemarkStringTable.h" #include "llvm/Support/Error.h" -#include <array> +#include "llvm/Support/FormatVariadic.h" #include <cstdint> #include <memory> #include <optional> namespace llvm { namespace remarks { -struct Remark; +class BitstreamBlockParserHelperBase { +protected: + BitstreamCursor &Stream; + + unsigned BlockID; + StringRef BlockName; + +public: + BitstreamBlockParserHelperBase(BitstreamCursor &Stream, unsigned BlockID, + StringRef BlockName) + : Stream(Stream), BlockID(BlockID), BlockName(BlockName) {} + + template <typename... Ts> Error error(char const *Fmt, const Ts &...Vals) { + std::string Buffer; + raw_string_ostream OS(Buffer); + OS << "Error while parsing " << BlockName << " block: "; + OS << formatv(Fmt, Vals...); + return make_error<StringError>( + std::move(Buffer), + std::make_error_code(std::errc::illegal_byte_sequence)); + } + + Error expectBlock(); + +protected: + Error enterBlock(); + + Error unknownRecord(unsigned AbbrevID); + Error unexpectedRecord(StringRef RecordName); + Error malformedRecord(StringRef RecordName); + Error unexpectedBlock(unsigned Code); +}; + +template <typename Derived> +class BitstreamBlockParserHelper : public BitstreamBlockParserHelperBase { +protected: + using BitstreamBlockParserHelperBase::BitstreamBlockParserHelperBase; + Derived &derived() { return *static_cast<Derived *>(this); } + + /// Parse a record and fill in the fields in the parser. + /// The subclass can statically override this method. + Error parseRecord(unsigned Code) { return unexpectedRecord(Code); } + + /// Parse a subblock and fill in the fields in the parser. + /// The subclass can statically override this method. + Error parseSubBlock(unsigned Code) { return unexpectedBlock(Code); } + +public: + /// Enter, parse, and leave this bitstream block. This expects the + /// BitstreamCursor to be right after the SubBlock entry (i.e. after calling + /// expectBlock). + Error parseBlock() { + if (Error E = enterBlock()) + return E; + + // Stop when there is nothing to read anymore or when we encounter an + // END_BLOCK. + while (true) { + Expected<BitstreamEntry> Next = Stream.advance(); + if (!Next) + return Next.takeError(); + switch (Next->Kind) { + case BitstreamEntry::SubBlock: + if (Error E = derived().parseSubBlock(Next->ID)) + return E; + continue; + case BitstreamEntry::EndBlock: + return Error::success(); + case BitstreamEntry::Record: + if (Error E = derived().parseRecord(Next->ID)) + return E; + continue; + case BitstreamEntry::Error: + return error("Unexpected end of bitstream."); + } + } + } +}; /// Helper to parse a META_BLOCK for a bitstream remark container. -struct BitstreamMetaParserHelper { - /// The Bitstream reader. - BitstreamCursor &Stream; - /// Reference to the storage for the block info. - BitstreamBlockInfo &BlockInfo; - /// The parsed content: depending on the container type, some fields might be - /// empty. - std::optional<uint64_t> ContainerVersion; - std::optional<uint8_t> ContainerType; - std::optional<StringRef> StrTabBuf; - std::optional<StringRef> ExternalFilePath; +class BitstreamMetaParserHelper + : public BitstreamBlockParserHelper<BitstreamMetaParserHelper> { + friend class BitstreamBlockParserHelper; + +public: + struct ContainerInfo { + uint64_t Version; + uint64_t Type; + }; + + /// The parsed content: depending on the container type, some fields might + /// be empty. + std::optional<ContainerInfo> Container; std::optional<uint64_t> RemarkVersion; + std::optional<StringRef> ExternalFilePath; + std::optional<StringRef> StrTabBuf; - /// Continue parsing with \p Stream. \p Stream is expected to contain a - /// ENTER_SUBBLOCK to the META_BLOCK at the current position. - /// \p Stream is expected to have a BLOCKINFO_BLOCK set. - BitstreamMetaParserHelper(BitstreamCursor &Stream, - BitstreamBlockInfo &BlockInfo); + BitstreamMetaParserHelper(BitstreamCursor &Stream) + : BitstreamBlockParserHelper(Stream, META_BLOCK_ID, MetaBlockName) {} - /// Parse the META_BLOCK and fill the available entries. - /// This helper does not check for the validity of the fields. - Error parse(); +protected: + Error parseRecord(unsigned Code); }; /// Helper to parse a REMARK_BLOCK for a bitstream remark container. -struct BitstreamRemarkParserHelper { - /// The Bitstream reader. - BitstreamCursor &Stream; +class BitstreamRemarkParserHelper + : public BitstreamBlockParserHelper<BitstreamRemarkParserHelper> { + friend class BitstreamBlockParserHelper; + +protected: + unsigned RecordID; + SmallVector<uint64_t, 5> Record; + StringRef RecordBlob; ---------------- jroelofs wrote:
```suggestion SmallVector<uint64_t, 5> Record; StringRef RecordBlob; unsigned RecordID; ``` https://github.com/llvm/llvm-project/pull/156511 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits