brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.4 KiB · 914edd8 Raw
266 lines · c
1//===-- BitstreamRemarkParser.h - Parser for Bitstream remarks --*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides the impementation of the Bitstream remark parser.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_REMARKS_BITSTREAM_REMARK_PARSER_H14#define LLVM_LIB_REMARKS_BITSTREAM_REMARK_PARSER_H15 16#include "llvm/ADT/StringRef.h"17#include "llvm/Bitstream/BitstreamReader.h"18#include "llvm/Remarks/BitstreamRemarkContainer.h"19#include "llvm/Remarks/Remark.h"20#include "llvm/Remarks/RemarkFormat.h"21#include "llvm/Remarks/RemarkParser.h"22#include "llvm/Remarks/RemarkStringTable.h"23#include "llvm/Support/Error.h"24#include "llvm/Support/FormatVariadic.h"25#include <cstdint>26#include <memory>27#include <optional>28 29namespace llvm {30namespace remarks {31 32class BitstreamBlockParserHelperBase {33protected:34  BitstreamCursor &Stream;35 36  StringRef BlockName;37  unsigned BlockID;38 39public:40  BitstreamBlockParserHelperBase(BitstreamCursor &Stream, unsigned BlockID,41                                 StringRef BlockName)42      : Stream(Stream), BlockName(BlockName), BlockID(BlockID) {}43 44  template <typename... Ts> Error error(char const *Fmt, const Ts &...Vals) {45    std::string Buffer;46    raw_string_ostream OS(Buffer);47    OS << "Error while parsing " << BlockName << " block: ";48    OS << formatv(Fmt, Vals...);49    return make_error<StringError>(50        std::move(Buffer),51        std::make_error_code(std::errc::illegal_byte_sequence));52  }53 54  Error expectBlock();55 56protected:57  Error enterBlock();58 59  Error unknownRecord(unsigned AbbrevID);60  Error unexpectedRecord(StringRef RecordName);61  Error malformedRecord(StringRef RecordName);62  Error unexpectedBlock(unsigned Code);63};64 65template <typename Derived>66class BitstreamBlockParserHelper : public BitstreamBlockParserHelperBase {67protected:68  using BitstreamBlockParserHelperBase::BitstreamBlockParserHelperBase;69  Derived &derived() { return *static_cast<Derived *>(this); }70 71  /// Parse a record and fill in the fields in the parser.72  /// The subclass must statically override this method.73  Error parseRecord(unsigned Code) = delete;74 75  /// Parse a subblock and fill in the fields in the parser.76  /// The subclass can statically override this method.77  Error parseSubBlock(unsigned Code) { return unexpectedBlock(Code); }78 79public:80  /// Enter, parse, and leave this bitstream block. This expects the81  /// BitstreamCursor to be right after the SubBlock entry (i.e. after calling82  /// expectBlock).83  Error parseBlock() {84    if (Error E = enterBlock())85      return E;86 87    // Stop when there is nothing to read anymore or when we encounter an88    // END_BLOCK.89    while (true) {90      Expected<BitstreamEntry> Next = Stream.advance();91      if (!Next)92        return Next.takeError();93      switch (Next->Kind) {94      case BitstreamEntry::SubBlock:95        if (Error E = derived().parseSubBlock(Next->ID))96          return E;97        continue;98      case BitstreamEntry::EndBlock:99        return Error::success();100      case BitstreamEntry::Record:101        if (Error E = derived().parseRecord(Next->ID))102          return E;103        continue;104      case BitstreamEntry::Error:105        return error("Unexpected end of bitstream.");106      }107      llvm_unreachable("Unexpected BitstreamEntry");108    }109  }110};111 112/// Helper to parse a META_BLOCK for a bitstream remark container.113class BitstreamMetaParserHelper114    : public BitstreamBlockParserHelper<BitstreamMetaParserHelper> {115  friend class BitstreamBlockParserHelper<BitstreamMetaParserHelper>;116 117public:118  struct ContainerInfo {119    uint64_t Version;120    uint64_t Type;121  };122 123  /// The parsed content: depending on the container type, some fields might124  /// be empty.125  std::optional<ContainerInfo> Container;126  std::optional<uint64_t> RemarkVersion;127  std::optional<StringRef> ExternalFilePath;128  std::optional<StringRef> StrTabBuf;129 130  BitstreamMetaParserHelper(BitstreamCursor &Stream)131      : BitstreamBlockParserHelper(Stream, META_BLOCK_ID, MetaBlockName) {}132 133protected:134  Error parseRecord(unsigned Code);135};136 137/// Helper to parse a REMARK_BLOCK for a bitstream remark container.138class BitstreamRemarkParserHelper139    : public BitstreamBlockParserHelper<BitstreamRemarkParserHelper> {140  friend class BitstreamBlockParserHelper<BitstreamRemarkParserHelper>;141 142protected:143  SmallVector<uint64_t, 5> Record;144  StringRef RecordBlob;145  unsigned RecordID;146 147public:148  struct RemarkLoc {149    uint64_t SourceFileNameIdx;150    uint64_t SourceLine;151    uint64_t SourceColumn;152  };153 154  struct Argument {155    std::optional<uint64_t> KeyIdx;156    std::optional<uint64_t> ValueIdx;157    std::optional<RemarkLoc> Loc;158 159    Argument(std::optional<uint64_t> KeyIdx, std::optional<uint64_t> ValueIdx)160        : KeyIdx(KeyIdx), ValueIdx(ValueIdx) {}161  };162 163  /// The parsed content: depending on the remark, some fields might be empty.164  std::optional<uint8_t> Type;165  std::optional<uint64_t> RemarkNameIdx;166  std::optional<uint64_t> PassNameIdx;167  std::optional<uint64_t> FunctionNameIdx;168  std::optional<uint64_t> Hotness;169  std::optional<RemarkLoc> Loc;170 171  SmallVector<Argument, 8> Args;172 173  BitstreamRemarkParserHelper(BitstreamCursor &Stream)174      : BitstreamBlockParserHelper(Stream, REMARK_BLOCK_ID, RemarkBlockName) {}175 176  /// Clear helper state and parse next remark block.177  Error parseNext();178 179protected:180  Error parseRecord(unsigned Code);181  Error handleRecord();182};183 184/// Helper to parse any bitstream remark container.185struct BitstreamParserHelper {186  /// The Bitstream reader.187  BitstreamCursor Stream;188  /// The block info block.189  BitstreamBlockInfo BlockInfo;190 191  /// Helper to parse the metadata blocks in this bitstream.192  BitstreamMetaParserHelper MetaHelper;193  /// Helper to parse the remark blocks in this bitstream. Only needed194  /// for ContainerType RemarksFile.195  std::optional<BitstreamRemarkParserHelper> RemarksHelper;196  /// The position of the first remark block we encounter after197  /// the initial metadata block.198  std::optional<uint64_t> RemarkStartBitPos;199 200  /// Start parsing at \p Buffer.201  BitstreamParserHelper(StringRef Buffer)202      : Stream(Buffer), MetaHelper(Stream), RemarksHelper(Stream) {}203 204  /// Parse and validate the magic number.205  Error expectMagic();206  /// Parse the block info block containing all the abbrevs.207  /// This needs to be called before calling any other parsing function.208  Error parseBlockInfoBlock();209 210  /// Parse all metadata blocks in the file. This populates the meta helper.211  Error parseMeta();212  /// Parse the next remark. This populates the remark helper data.213  Error parseRemark();214};215 216/// Parses and holds the state of the latest parsed remark.217struct BitstreamRemarkParser : public RemarkParser {218  /// The buffer to parse.219  std::optional<BitstreamParserHelper> ParserHelper;220  /// The string table used for parsing strings.221  std::optional<ParsedStringTable> StrTab;222  /// Temporary remark buffer used when the remarks are stored separately.223  std::unique_ptr<MemoryBuffer> TmpRemarkBuffer;224  /// Whether the metadata has already been parsed, so we can continue parsing225  /// remarks.226  bool IsMetaReady = false;227  /// The common metadata used to decide how to parse the buffer.228  /// This is filled when parsing the metadata block.229  uint64_t ContainerVersion = 0;230  uint64_t RemarkVersion = 0;231  BitstreamRemarkContainerType ContainerType =232      BitstreamRemarkContainerType::RemarksFile;233 234  /// Create a parser that expects to find a string table embedded in the235  /// stream.236  explicit BitstreamRemarkParser(StringRef Buf);237 238  Expected<std::unique_ptr<Remark>> next() override;239 240  static bool classof(const RemarkParser *P) {241    return P->ParserFormat == Format::Bitstream;242  }243 244  /// Parse and process the metadata of the buffer.245  Error parseMeta();246 247private:248  Error processCommonMeta();249  Error processFileContainerMeta();250  Error processExternalFilePath();251 252  Expected<std::unique_ptr<Remark>> processRemark();253 254  Error processStrTab();255  Error processRemarkVersion();256};257 258Expected<std::unique_ptr<BitstreamRemarkParser>> createBitstreamParserFromMeta(259    StringRef Buf,260    std::optional<StringRef> ExternalFilePrependPath = std::nullopt);261 262} // end namespace remarks263} // end namespace llvm264 265#endif /* LLVM_LIB_REMARKS_BITSTREAM_REMARK_PARSER_H */266