xref: /freebsd-src/contrib/llvm-project/llvm/lib/Remarks/BitstreamRemarkParser.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
18bcb0991SDimitry Andric //===- BitstreamRemarkParser.cpp ------------------------------------------===//
28bcb0991SDimitry Andric //
38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bcb0991SDimitry Andric //
78bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
88bcb0991SDimitry Andric //
98bcb0991SDimitry Andric // This file provides utility methods used by clients that want to use the
108bcb0991SDimitry Andric // parser for remark diagnostics in LLVM.
118bcb0991SDimitry Andric //
128bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
138bcb0991SDimitry Andric 
148bcb0991SDimitry Andric #include "llvm/Remarks/BitstreamRemarkParser.h"
158bcb0991SDimitry Andric #include "BitstreamRemarkParser.h"
161fd87a68SDimitry Andric #include "llvm/Remarks/Remark.h"
178bcb0991SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
188bcb0991SDimitry Andric #include "llvm/Support/Path.h"
19*bdd1243dSDimitry Andric #include <optional>
208bcb0991SDimitry Andric 
218bcb0991SDimitry Andric using namespace llvm;
228bcb0991SDimitry Andric using namespace llvm::remarks;
238bcb0991SDimitry Andric 
unknownRecord(const char * BlockName,unsigned RecordID)248bcb0991SDimitry Andric static Error unknownRecord(const char *BlockName, unsigned RecordID) {
258bcb0991SDimitry Andric   return createStringError(
268bcb0991SDimitry Andric       std::make_error_code(std::errc::illegal_byte_sequence),
278bcb0991SDimitry Andric       "Error while parsing %s: unknown record entry (%lu).", BlockName,
288bcb0991SDimitry Andric       RecordID);
298bcb0991SDimitry Andric }
308bcb0991SDimitry Andric 
malformedRecord(const char * BlockName,const char * RecordName)318bcb0991SDimitry Andric static Error malformedRecord(const char *BlockName, const char *RecordName) {
328bcb0991SDimitry Andric   return createStringError(
338bcb0991SDimitry Andric       std::make_error_code(std::errc::illegal_byte_sequence),
348bcb0991SDimitry Andric       "Error while parsing %s: malformed record entry (%s).", BlockName,
358bcb0991SDimitry Andric       RecordName);
368bcb0991SDimitry Andric }
378bcb0991SDimitry Andric 
BitstreamMetaParserHelper(BitstreamCursor & Stream,BitstreamBlockInfo & BlockInfo)388bcb0991SDimitry Andric BitstreamMetaParserHelper::BitstreamMetaParserHelper(
398bcb0991SDimitry Andric     BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo)
408bcb0991SDimitry Andric     : Stream(Stream), BlockInfo(BlockInfo) {}
418bcb0991SDimitry Andric 
428bcb0991SDimitry Andric /// Parse a record and fill in the fields in the parser.
parseRecord(BitstreamMetaParserHelper & Parser,unsigned Code)438bcb0991SDimitry Andric static Error parseRecord(BitstreamMetaParserHelper &Parser, unsigned Code) {
448bcb0991SDimitry Andric   BitstreamCursor &Stream = Parser.Stream;
458bcb0991SDimitry Andric   // Note: 2 is used here because it's the max number of fields we have per
468bcb0991SDimitry Andric   // record.
478bcb0991SDimitry Andric   SmallVector<uint64_t, 2> Record;
488bcb0991SDimitry Andric   StringRef Blob;
498bcb0991SDimitry Andric   Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob);
508bcb0991SDimitry Andric   if (!RecordID)
518bcb0991SDimitry Andric     return RecordID.takeError();
528bcb0991SDimitry Andric 
538bcb0991SDimitry Andric   switch (*RecordID) {
548bcb0991SDimitry Andric   case RECORD_META_CONTAINER_INFO: {
558bcb0991SDimitry Andric     if (Record.size() != 2)
568bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_CONTAINER_INFO");
578bcb0991SDimitry Andric     Parser.ContainerVersion = Record[0];
588bcb0991SDimitry Andric     Parser.ContainerType = Record[1];
598bcb0991SDimitry Andric     break;
608bcb0991SDimitry Andric   }
618bcb0991SDimitry Andric   case RECORD_META_REMARK_VERSION: {
628bcb0991SDimitry Andric     if (Record.size() != 1)
638bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_REMARK_VERSION");
648bcb0991SDimitry Andric     Parser.RemarkVersion = Record[0];
658bcb0991SDimitry Andric     break;
668bcb0991SDimitry Andric   }
678bcb0991SDimitry Andric   case RECORD_META_STRTAB: {
688bcb0991SDimitry Andric     if (Record.size() != 0)
698bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_STRTAB");
708bcb0991SDimitry Andric     Parser.StrTabBuf = Blob;
718bcb0991SDimitry Andric     break;
728bcb0991SDimitry Andric   }
738bcb0991SDimitry Andric   case RECORD_META_EXTERNAL_FILE: {
748bcb0991SDimitry Andric     if (Record.size() != 0)
758bcb0991SDimitry Andric       return malformedRecord("BLOCK_META", "RECORD_META_EXTERNAL_FILE");
768bcb0991SDimitry Andric     Parser.ExternalFilePath = Blob;
778bcb0991SDimitry Andric     break;
788bcb0991SDimitry Andric   }
798bcb0991SDimitry Andric   default:
808bcb0991SDimitry Andric     return unknownRecord("BLOCK_META", *RecordID);
818bcb0991SDimitry Andric   }
828bcb0991SDimitry Andric   return Error::success();
838bcb0991SDimitry Andric }
848bcb0991SDimitry Andric 
BitstreamRemarkParserHelper(BitstreamCursor & Stream)858bcb0991SDimitry Andric BitstreamRemarkParserHelper::BitstreamRemarkParserHelper(
868bcb0991SDimitry Andric     BitstreamCursor &Stream)
878bcb0991SDimitry Andric     : Stream(Stream) {}
888bcb0991SDimitry Andric 
898bcb0991SDimitry Andric /// Parse a record and fill in the fields in the parser.
parseRecord(BitstreamRemarkParserHelper & Parser,unsigned Code)908bcb0991SDimitry Andric static Error parseRecord(BitstreamRemarkParserHelper &Parser, unsigned Code) {
918bcb0991SDimitry Andric   BitstreamCursor &Stream = Parser.Stream;
928bcb0991SDimitry Andric   // Note: 5 is used here because it's the max number of fields we have per
938bcb0991SDimitry Andric   // record.
948bcb0991SDimitry Andric   SmallVector<uint64_t, 5> Record;
958bcb0991SDimitry Andric   StringRef Blob;
968bcb0991SDimitry Andric   Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob);
978bcb0991SDimitry Andric   if (!RecordID)
988bcb0991SDimitry Andric     return RecordID.takeError();
998bcb0991SDimitry Andric 
1008bcb0991SDimitry Andric   switch (*RecordID) {
1018bcb0991SDimitry Andric   case RECORD_REMARK_HEADER: {
1028bcb0991SDimitry Andric     if (Record.size() != 4)
1038bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HEADER");
1048bcb0991SDimitry Andric     Parser.Type = Record[0];
1058bcb0991SDimitry Andric     Parser.RemarkNameIdx = Record[1];
1068bcb0991SDimitry Andric     Parser.PassNameIdx = Record[2];
1078bcb0991SDimitry Andric     Parser.FunctionNameIdx = Record[3];
1088bcb0991SDimitry Andric     break;
1098bcb0991SDimitry Andric   }
1108bcb0991SDimitry Andric   case RECORD_REMARK_DEBUG_LOC: {
1118bcb0991SDimitry Andric     if (Record.size() != 3)
1128bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_DEBUG_LOC");
1138bcb0991SDimitry Andric     Parser.SourceFileNameIdx = Record[0];
1148bcb0991SDimitry Andric     Parser.SourceLine = Record[1];
1158bcb0991SDimitry Andric     Parser.SourceColumn = Record[2];
1168bcb0991SDimitry Andric     break;
1178bcb0991SDimitry Andric   }
1188bcb0991SDimitry Andric   case RECORD_REMARK_HOTNESS: {
1198bcb0991SDimitry Andric     if (Record.size() != 1)
1208bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HOTNESS");
1218bcb0991SDimitry Andric     Parser.Hotness = Record[0];
1228bcb0991SDimitry Andric     break;
1238bcb0991SDimitry Andric   }
1248bcb0991SDimitry Andric   case RECORD_REMARK_ARG_WITH_DEBUGLOC: {
1258bcb0991SDimitry Andric     if (Record.size() != 5)
1268bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_ARG_WITH_DEBUGLOC");
1278bcb0991SDimitry Andric     // Create a temporary argument. Use that as a valid memory location for this
1288bcb0991SDimitry Andric     // argument entry.
1298bcb0991SDimitry Andric     Parser.TmpArgs.emplace_back();
1308bcb0991SDimitry Andric     Parser.TmpArgs.back().KeyIdx = Record[0];
1318bcb0991SDimitry Andric     Parser.TmpArgs.back().ValueIdx = Record[1];
1328bcb0991SDimitry Andric     Parser.TmpArgs.back().SourceFileNameIdx = Record[2];
1338bcb0991SDimitry Andric     Parser.TmpArgs.back().SourceLine = Record[3];
1348bcb0991SDimitry Andric     Parser.TmpArgs.back().SourceColumn = Record[4];
1358bcb0991SDimitry Andric     Parser.Args =
1368bcb0991SDimitry Andric         ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs);
1378bcb0991SDimitry Andric     break;
1388bcb0991SDimitry Andric   }
1398bcb0991SDimitry Andric   case RECORD_REMARK_ARG_WITHOUT_DEBUGLOC: {
1408bcb0991SDimitry Andric     if (Record.size() != 2)
1418bcb0991SDimitry Andric       return malformedRecord("BLOCK_REMARK",
1428bcb0991SDimitry Andric                              "RECORD_REMARK_ARG_WITHOUT_DEBUGLOC");
1438bcb0991SDimitry Andric     // Create a temporary argument. Use that as a valid memory location for this
1448bcb0991SDimitry Andric     // argument entry.
1458bcb0991SDimitry Andric     Parser.TmpArgs.emplace_back();
1468bcb0991SDimitry Andric     Parser.TmpArgs.back().KeyIdx = Record[0];
1478bcb0991SDimitry Andric     Parser.TmpArgs.back().ValueIdx = Record[1];
1488bcb0991SDimitry Andric     Parser.Args =
1498bcb0991SDimitry Andric         ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs);
1508bcb0991SDimitry Andric     break;
1518bcb0991SDimitry Andric   }
1528bcb0991SDimitry Andric   default:
1538bcb0991SDimitry Andric     return unknownRecord("BLOCK_REMARK", *RecordID);
1548bcb0991SDimitry Andric   }
1558bcb0991SDimitry Andric   return Error::success();
1568bcb0991SDimitry Andric }
1578bcb0991SDimitry Andric 
1588bcb0991SDimitry Andric template <typename T>
parseBlock(T & ParserHelper,unsigned BlockID,const char * BlockName)1598bcb0991SDimitry Andric static Error parseBlock(T &ParserHelper, unsigned BlockID,
1608bcb0991SDimitry Andric                         const char *BlockName) {
1618bcb0991SDimitry Andric   BitstreamCursor &Stream = ParserHelper.Stream;
1628bcb0991SDimitry Andric   Expected<BitstreamEntry> Next = Stream.advance();
1638bcb0991SDimitry Andric   if (!Next)
1648bcb0991SDimitry Andric     return Next.takeError();
1658bcb0991SDimitry Andric   if (Next->Kind != BitstreamEntry::SubBlock || Next->ID != BlockID)
1668bcb0991SDimitry Andric     return createStringError(
1678bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
1688bcb0991SDimitry Andric         "Error while parsing %s: expecting [ENTER_SUBBLOCK, %s, ...].",
1698bcb0991SDimitry Andric         BlockName, BlockName);
1708bcb0991SDimitry Andric   if (Stream.EnterSubBlock(BlockID))
1718bcb0991SDimitry Andric     return createStringError(
1728bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
1738bcb0991SDimitry Andric         "Error while entering %s.", BlockName);
1748bcb0991SDimitry Andric 
1758bcb0991SDimitry Andric   // Stop when there is nothing to read anymore or when we encounter an
1768bcb0991SDimitry Andric   // END_BLOCK.
1778bcb0991SDimitry Andric   while (!Stream.AtEndOfStream()) {
178480093f4SDimitry Andric     Next = Stream.advance();
1798bcb0991SDimitry Andric     if (!Next)
1808bcb0991SDimitry Andric       return Next.takeError();
1818bcb0991SDimitry Andric     switch (Next->Kind) {
1828bcb0991SDimitry Andric     case BitstreamEntry::EndBlock:
1838bcb0991SDimitry Andric       return Error::success();
1848bcb0991SDimitry Andric     case BitstreamEntry::Error:
1858bcb0991SDimitry Andric     case BitstreamEntry::SubBlock:
1868bcb0991SDimitry Andric       return createStringError(
1878bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
1888bcb0991SDimitry Andric           "Error while parsing %s: expecting records.", BlockName);
1898bcb0991SDimitry Andric     case BitstreamEntry::Record:
1908bcb0991SDimitry Andric       if (Error E = parseRecord(ParserHelper, Next->ID))
1918bcb0991SDimitry Andric         return E;
1928bcb0991SDimitry Andric       continue;
1938bcb0991SDimitry Andric     }
1948bcb0991SDimitry Andric   }
1958bcb0991SDimitry Andric   // If we're here, it means we didn't get an END_BLOCK yet, but we're at the
1968bcb0991SDimitry Andric   // end of the stream. In this case, error.
1978bcb0991SDimitry Andric   return createStringError(
1988bcb0991SDimitry Andric       std::make_error_code(std::errc::illegal_byte_sequence),
1998bcb0991SDimitry Andric       "Error while parsing %s: unterminated block.", BlockName);
2008bcb0991SDimitry Andric }
2018bcb0991SDimitry Andric 
parse()2028bcb0991SDimitry Andric Error BitstreamMetaParserHelper::parse() {
2038bcb0991SDimitry Andric   return parseBlock(*this, META_BLOCK_ID, "META_BLOCK");
2048bcb0991SDimitry Andric }
2058bcb0991SDimitry Andric 
parse()2068bcb0991SDimitry Andric Error BitstreamRemarkParserHelper::parse() {
2078bcb0991SDimitry Andric   return parseBlock(*this, REMARK_BLOCK_ID, "REMARK_BLOCK");
2088bcb0991SDimitry Andric }
2098bcb0991SDimitry Andric 
BitstreamParserHelper(StringRef Buffer)2108bcb0991SDimitry Andric BitstreamParserHelper::BitstreamParserHelper(StringRef Buffer)
2118bcb0991SDimitry Andric     : Stream(Buffer) {}
2128bcb0991SDimitry Andric 
parseMagic()2138bcb0991SDimitry Andric Expected<std::array<char, 4>> BitstreamParserHelper::parseMagic() {
2148bcb0991SDimitry Andric   std::array<char, 4> Result;
2158bcb0991SDimitry Andric   for (unsigned i = 0; i < 4; ++i)
2168bcb0991SDimitry Andric     if (Expected<unsigned> R = Stream.Read(8))
2178bcb0991SDimitry Andric       Result[i] = *R;
2188bcb0991SDimitry Andric     else
2198bcb0991SDimitry Andric       return R.takeError();
2208bcb0991SDimitry Andric   return Result;
2218bcb0991SDimitry Andric }
2228bcb0991SDimitry Andric 
parseBlockInfoBlock()2238bcb0991SDimitry Andric Error BitstreamParserHelper::parseBlockInfoBlock() {
2248bcb0991SDimitry Andric   Expected<BitstreamEntry> Next = Stream.advance();
2258bcb0991SDimitry Andric   if (!Next)
2268bcb0991SDimitry Andric     return Next.takeError();
2278bcb0991SDimitry Andric   if (Next->Kind != BitstreamEntry::SubBlock ||
2288bcb0991SDimitry Andric       Next->ID != llvm::bitc::BLOCKINFO_BLOCK_ID)
2298bcb0991SDimitry Andric     return createStringError(
2308bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
2318bcb0991SDimitry Andric         "Error while parsing BLOCKINFO_BLOCK: expecting [ENTER_SUBBLOCK, "
2328bcb0991SDimitry Andric         "BLOCKINFO_BLOCK, ...].");
2338bcb0991SDimitry Andric 
234*bdd1243dSDimitry Andric   Expected<std::optional<BitstreamBlockInfo>> MaybeBlockInfo =
2358bcb0991SDimitry Andric       Stream.ReadBlockInfoBlock();
2368bcb0991SDimitry Andric   if (!MaybeBlockInfo)
2378bcb0991SDimitry Andric     return MaybeBlockInfo.takeError();
2388bcb0991SDimitry Andric 
2398bcb0991SDimitry Andric   if (!*MaybeBlockInfo)
2408bcb0991SDimitry Andric     return createStringError(
2418bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
2428bcb0991SDimitry Andric         "Error while parsing BLOCKINFO_BLOCK.");
2438bcb0991SDimitry Andric 
2448bcb0991SDimitry Andric   BlockInfo = **MaybeBlockInfo;
2458bcb0991SDimitry Andric 
2468bcb0991SDimitry Andric   Stream.setBlockInfo(&BlockInfo);
2478bcb0991SDimitry Andric   return Error::success();
2488bcb0991SDimitry Andric }
2498bcb0991SDimitry Andric 
isBlock(BitstreamCursor & Stream,unsigned BlockID)2508bcb0991SDimitry Andric static Expected<bool> isBlock(BitstreamCursor &Stream, unsigned BlockID) {
2518bcb0991SDimitry Andric   bool Result = false;
2528bcb0991SDimitry Andric   uint64_t PreviousBitNo = Stream.GetCurrentBitNo();
2538bcb0991SDimitry Andric   Expected<BitstreamEntry> Next = Stream.advance();
2548bcb0991SDimitry Andric   if (!Next)
2558bcb0991SDimitry Andric     return Next.takeError();
2568bcb0991SDimitry Andric   switch (Next->Kind) {
2578bcb0991SDimitry Andric   case BitstreamEntry::SubBlock:
2588bcb0991SDimitry Andric     // Check for the block id.
2598bcb0991SDimitry Andric     Result = Next->ID == BlockID;
2608bcb0991SDimitry Andric     break;
2618bcb0991SDimitry Andric   case BitstreamEntry::Error:
2628bcb0991SDimitry Andric     return createStringError(
2638bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
2648bcb0991SDimitry Andric         "Unexpected error while parsing bitstream.");
2658bcb0991SDimitry Andric   default:
2668bcb0991SDimitry Andric     Result = false;
2678bcb0991SDimitry Andric     break;
2688bcb0991SDimitry Andric   }
2698bcb0991SDimitry Andric   if (Error E = Stream.JumpToBit(PreviousBitNo))
2708bcb0991SDimitry Andric     return std::move(E);
2718bcb0991SDimitry Andric   return Result;
2728bcb0991SDimitry Andric }
2738bcb0991SDimitry Andric 
isMetaBlock()2748bcb0991SDimitry Andric Expected<bool> BitstreamParserHelper::isMetaBlock() {
2758bcb0991SDimitry Andric   return isBlock(Stream, META_BLOCK_ID);
2768bcb0991SDimitry Andric }
2778bcb0991SDimitry Andric 
isRemarkBlock()2788bcb0991SDimitry Andric Expected<bool> BitstreamParserHelper::isRemarkBlock() {
2798bcb0991SDimitry Andric   return isBlock(Stream, META_BLOCK_ID);
2808bcb0991SDimitry Andric }
2818bcb0991SDimitry Andric 
validateMagicNumber(StringRef MagicNumber)282480093f4SDimitry Andric static Error validateMagicNumber(StringRef MagicNumber) {
283480093f4SDimitry Andric   if (MagicNumber != remarks::ContainerMagic)
2848bcb0991SDimitry Andric     return createStringError(std::make_error_code(std::errc::invalid_argument),
2858bcb0991SDimitry Andric                              "Unknown magic number: expecting %s, got %.4s.",
286480093f4SDimitry Andric                              remarks::ContainerMagic.data(), MagicNumber.data());
2878bcb0991SDimitry Andric   return Error::success();
2888bcb0991SDimitry Andric }
2898bcb0991SDimitry Andric 
advanceToMetaBlock(BitstreamParserHelper & Helper)2908bcb0991SDimitry Andric static Error advanceToMetaBlock(BitstreamParserHelper &Helper) {
291480093f4SDimitry Andric   Expected<std::array<char, 4>> MagicNumber = Helper.parseMagic();
292480093f4SDimitry Andric   if (!MagicNumber)
293480093f4SDimitry Andric     return MagicNumber.takeError();
294480093f4SDimitry Andric   if (Error E = validateMagicNumber(
295480093f4SDimitry Andric           StringRef(MagicNumber->data(), MagicNumber->size())))
2968bcb0991SDimitry Andric     return E;
2978bcb0991SDimitry Andric   if (Error E = Helper.parseBlockInfoBlock())
2988bcb0991SDimitry Andric     return E;
2998bcb0991SDimitry Andric   Expected<bool> isMetaBlock = Helper.isMetaBlock();
3008bcb0991SDimitry Andric   if (!isMetaBlock)
3018bcb0991SDimitry Andric     return isMetaBlock.takeError();
3028bcb0991SDimitry Andric   if (!*isMetaBlock)
3038bcb0991SDimitry Andric     return createStringError(
3048bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
3058bcb0991SDimitry Andric         "Expecting META_BLOCK after the BLOCKINFO_BLOCK.");
3068bcb0991SDimitry Andric   return Error::success();
3078bcb0991SDimitry Andric }
3088bcb0991SDimitry Andric 
3098bcb0991SDimitry Andric Expected<std::unique_ptr<BitstreamRemarkParser>>
createBitstreamParserFromMeta(StringRef Buf,std::optional<ParsedStringTable> StrTab,std::optional<StringRef> ExternalFilePrependPath)3108bcb0991SDimitry Andric remarks::createBitstreamParserFromMeta(
311*bdd1243dSDimitry Andric     StringRef Buf, std::optional<ParsedStringTable> StrTab,
312*bdd1243dSDimitry Andric     std::optional<StringRef> ExternalFilePrependPath) {
3138bcb0991SDimitry Andric   BitstreamParserHelper Helper(Buf);
314480093f4SDimitry Andric   Expected<std::array<char, 4>> MagicNumber = Helper.parseMagic();
315480093f4SDimitry Andric   if (!MagicNumber)
316480093f4SDimitry Andric     return MagicNumber.takeError();
3178bcb0991SDimitry Andric 
318480093f4SDimitry Andric   if (Error E = validateMagicNumber(
319480093f4SDimitry Andric           StringRef(MagicNumber->data(), MagicNumber->size())))
3208bcb0991SDimitry Andric     return std::move(E);
3218bcb0991SDimitry Andric 
3228bcb0991SDimitry Andric   auto Parser =
3238bcb0991SDimitry Andric       StrTab ? std::make_unique<BitstreamRemarkParser>(Buf, std::move(*StrTab))
3248bcb0991SDimitry Andric              : std::make_unique<BitstreamRemarkParser>(Buf);
3258bcb0991SDimitry Andric 
3268bcb0991SDimitry Andric   if (ExternalFilePrependPath)
3275ffd83dbSDimitry Andric     Parser->ExternalFilePrependPath = std::string(*ExternalFilePrependPath);
3288bcb0991SDimitry Andric 
3298bcb0991SDimitry Andric   return std::move(Parser);
3308bcb0991SDimitry Andric }
3318bcb0991SDimitry Andric 
next()3328bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::next() {
3338bcb0991SDimitry Andric   if (ParserHelper.atEndOfStream())
3348bcb0991SDimitry Andric     return make_error<EndOfFileError>();
3358bcb0991SDimitry Andric 
3368bcb0991SDimitry Andric   if (!ReadyToParseRemarks) {
3378bcb0991SDimitry Andric     if (Error E = parseMeta())
3388bcb0991SDimitry Andric       return std::move(E);
3398bcb0991SDimitry Andric     ReadyToParseRemarks = true;
3408bcb0991SDimitry Andric   }
3418bcb0991SDimitry Andric 
3428bcb0991SDimitry Andric   return parseRemark();
3438bcb0991SDimitry Andric }
3448bcb0991SDimitry Andric 
parseMeta()3458bcb0991SDimitry Andric Error BitstreamRemarkParser::parseMeta() {
3468bcb0991SDimitry Andric   // Advance and to the meta block.
3478bcb0991SDimitry Andric   if (Error E = advanceToMetaBlock(ParserHelper))
3488bcb0991SDimitry Andric     return E;
3498bcb0991SDimitry Andric 
3508bcb0991SDimitry Andric   BitstreamMetaParserHelper MetaHelper(ParserHelper.Stream,
3518bcb0991SDimitry Andric                                        ParserHelper.BlockInfo);
3528bcb0991SDimitry Andric   if (Error E = MetaHelper.parse())
3538bcb0991SDimitry Andric     return E;
3548bcb0991SDimitry Andric 
3558bcb0991SDimitry Andric   if (Error E = processCommonMeta(MetaHelper))
3568bcb0991SDimitry Andric     return E;
3578bcb0991SDimitry Andric 
3588bcb0991SDimitry Andric   switch (ContainerType) {
3598bcb0991SDimitry Andric   case BitstreamRemarkContainerType::Standalone:
3608bcb0991SDimitry Andric     return processStandaloneMeta(MetaHelper);
3618bcb0991SDimitry Andric   case BitstreamRemarkContainerType::SeparateRemarksFile:
3628bcb0991SDimitry Andric     return processSeparateRemarksFileMeta(MetaHelper);
3638bcb0991SDimitry Andric   case BitstreamRemarkContainerType::SeparateRemarksMeta:
3648bcb0991SDimitry Andric     return processSeparateRemarksMetaMeta(MetaHelper);
3658bcb0991SDimitry Andric   }
3668bcb0991SDimitry Andric   llvm_unreachable("Unknown BitstreamRemarkContainerType enum");
3678bcb0991SDimitry Andric }
3688bcb0991SDimitry Andric 
processCommonMeta(BitstreamMetaParserHelper & Helper)3698bcb0991SDimitry Andric Error BitstreamRemarkParser::processCommonMeta(
370480093f4SDimitry Andric     BitstreamMetaParserHelper &Helper) {
371*bdd1243dSDimitry Andric   if (std::optional<uint64_t> Version = Helper.ContainerVersion)
3728bcb0991SDimitry Andric     ContainerVersion = *Version;
3738bcb0991SDimitry Andric   else
3748bcb0991SDimitry Andric     return createStringError(
3758bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
3768bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing container version.");
3778bcb0991SDimitry Andric 
378*bdd1243dSDimitry Andric   if (std::optional<uint8_t> Type = Helper.ContainerType) {
3798bcb0991SDimitry Andric     // Always >= BitstreamRemarkContainerType::First since it's unsigned.
3808bcb0991SDimitry Andric     if (*Type > static_cast<uint8_t>(BitstreamRemarkContainerType::Last))
3818bcb0991SDimitry Andric       return createStringError(
3828bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
3838bcb0991SDimitry Andric           "Error while parsing BLOCK_META: invalid container type.");
3848bcb0991SDimitry Andric 
3858bcb0991SDimitry Andric     ContainerType = static_cast<BitstreamRemarkContainerType>(*Type);
3868bcb0991SDimitry Andric   } else
3878bcb0991SDimitry Andric     return createStringError(
3888bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
3898bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing container type.");
3908bcb0991SDimitry Andric 
3918bcb0991SDimitry Andric   return Error::success();
3928bcb0991SDimitry Andric }
3938bcb0991SDimitry Andric 
processStrTab(BitstreamRemarkParser & P,std::optional<StringRef> StrTabBuf)3948bcb0991SDimitry Andric static Error processStrTab(BitstreamRemarkParser &P,
395*bdd1243dSDimitry Andric                            std::optional<StringRef> StrTabBuf) {
3968bcb0991SDimitry Andric   if (!StrTabBuf)
3978bcb0991SDimitry Andric     return createStringError(
3988bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
3998bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing string table.");
4008bcb0991SDimitry Andric   // Parse and assign the string table.
4018bcb0991SDimitry Andric   P.StrTab.emplace(*StrTabBuf);
4028bcb0991SDimitry Andric   return Error::success();
4038bcb0991SDimitry Andric }
4048bcb0991SDimitry Andric 
processRemarkVersion(BitstreamRemarkParser & P,std::optional<uint64_t> RemarkVersion)4058bcb0991SDimitry Andric static Error processRemarkVersion(BitstreamRemarkParser &P,
406*bdd1243dSDimitry Andric                                   std::optional<uint64_t> RemarkVersion) {
4078bcb0991SDimitry Andric   if (!RemarkVersion)
4088bcb0991SDimitry Andric     return createStringError(
4098bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
4108bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing remark version.");
4118bcb0991SDimitry Andric   P.RemarkVersion = *RemarkVersion;
4128bcb0991SDimitry Andric   return Error::success();
4138bcb0991SDimitry Andric }
4148bcb0991SDimitry Andric 
processExternalFilePath(std::optional<StringRef> ExternalFilePath)4158bcb0991SDimitry Andric Error BitstreamRemarkParser::processExternalFilePath(
416*bdd1243dSDimitry Andric     std::optional<StringRef> ExternalFilePath) {
4178bcb0991SDimitry Andric   if (!ExternalFilePath)
4188bcb0991SDimitry Andric     return createStringError(
4198bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
4208bcb0991SDimitry Andric         "Error while parsing BLOCK_META: missing external file path.");
4218bcb0991SDimitry Andric 
4228bcb0991SDimitry Andric   SmallString<80> FullPath(ExternalFilePrependPath);
4238bcb0991SDimitry Andric   sys::path::append(FullPath, *ExternalFilePath);
4248bcb0991SDimitry Andric 
4258bcb0991SDimitry Andric   // External file: open the external file, parse it, check if its metadata
4268bcb0991SDimitry Andric   // matches the one from the separate metadata, then replace the current parser
4278bcb0991SDimitry Andric   // with the one parsing the remarks.
4288bcb0991SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
4298bcb0991SDimitry Andric       MemoryBuffer::getFile(FullPath);
4308bcb0991SDimitry Andric   if (std::error_code EC = BufferOrErr.getError())
4318bcb0991SDimitry Andric     return createFileError(FullPath, EC);
432480093f4SDimitry Andric 
4338bcb0991SDimitry Andric   TmpRemarkBuffer = std::move(*BufferOrErr);
4348bcb0991SDimitry Andric 
435480093f4SDimitry Andric   // Don't try to parse the file if it's empty.
436480093f4SDimitry Andric   if (TmpRemarkBuffer->getBufferSize() == 0)
437480093f4SDimitry Andric     return make_error<EndOfFileError>();
438480093f4SDimitry Andric 
4398bcb0991SDimitry Andric   // Create a separate parser used for parsing the separate file.
4408bcb0991SDimitry Andric   ParserHelper = BitstreamParserHelper(TmpRemarkBuffer->getBuffer());
4418bcb0991SDimitry Andric   // Advance and check until we can parse the meta block.
4428bcb0991SDimitry Andric   if (Error E = advanceToMetaBlock(ParserHelper))
4438bcb0991SDimitry Andric     return E;
4448bcb0991SDimitry Andric   // Parse the meta from the separate file.
4458bcb0991SDimitry Andric   // Note: here we overwrite the BlockInfo with the one from the file. This will
4468bcb0991SDimitry Andric   // be used to parse the rest of the file.
4478bcb0991SDimitry Andric   BitstreamMetaParserHelper SeparateMetaHelper(ParserHelper.Stream,
4488bcb0991SDimitry Andric                                                ParserHelper.BlockInfo);
4498bcb0991SDimitry Andric   if (Error E = SeparateMetaHelper.parse())
4508bcb0991SDimitry Andric     return E;
4518bcb0991SDimitry Andric 
4528bcb0991SDimitry Andric   uint64_t PreviousContainerVersion = ContainerVersion;
4538bcb0991SDimitry Andric   if (Error E = processCommonMeta(SeparateMetaHelper))
4548bcb0991SDimitry Andric     return E;
4558bcb0991SDimitry Andric 
4568bcb0991SDimitry Andric   if (ContainerType != BitstreamRemarkContainerType::SeparateRemarksFile)
4578bcb0991SDimitry Andric     return createStringError(
4588bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
4598bcb0991SDimitry Andric         "Error while parsing external file's BLOCK_META: wrong container "
4608bcb0991SDimitry Andric         "type.");
4618bcb0991SDimitry Andric 
4628bcb0991SDimitry Andric   if (PreviousContainerVersion != ContainerVersion)
4638bcb0991SDimitry Andric     return createStringError(
4648bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
4658bcb0991SDimitry Andric         "Error while parsing external file's BLOCK_META: mismatching versions: "
4668bcb0991SDimitry Andric         "original meta: %lu, external file meta: %lu.",
4678bcb0991SDimitry Andric         PreviousContainerVersion, ContainerVersion);
4688bcb0991SDimitry Andric 
4698bcb0991SDimitry Andric   // Process the meta from the separate file.
4708bcb0991SDimitry Andric   return processSeparateRemarksFileMeta(SeparateMetaHelper);
4718bcb0991SDimitry Andric }
4728bcb0991SDimitry Andric 
processStandaloneMeta(BitstreamMetaParserHelper & Helper)4738bcb0991SDimitry Andric Error BitstreamRemarkParser::processStandaloneMeta(
4748bcb0991SDimitry Andric     BitstreamMetaParserHelper &Helper) {
4758bcb0991SDimitry Andric   if (Error E = processStrTab(*this, Helper.StrTabBuf))
4768bcb0991SDimitry Andric     return E;
4778bcb0991SDimitry Andric   return processRemarkVersion(*this, Helper.RemarkVersion);
4788bcb0991SDimitry Andric }
4798bcb0991SDimitry Andric 
processSeparateRemarksFileMeta(BitstreamMetaParserHelper & Helper)4808bcb0991SDimitry Andric Error BitstreamRemarkParser::processSeparateRemarksFileMeta(
4818bcb0991SDimitry Andric     BitstreamMetaParserHelper &Helper) {
4828bcb0991SDimitry Andric   return processRemarkVersion(*this, Helper.RemarkVersion);
4838bcb0991SDimitry Andric }
4848bcb0991SDimitry Andric 
processSeparateRemarksMetaMeta(BitstreamMetaParserHelper & Helper)4858bcb0991SDimitry Andric Error BitstreamRemarkParser::processSeparateRemarksMetaMeta(
4868bcb0991SDimitry Andric     BitstreamMetaParserHelper &Helper) {
4878bcb0991SDimitry Andric   if (Error E = processStrTab(*this, Helper.StrTabBuf))
4888bcb0991SDimitry Andric     return E;
4898bcb0991SDimitry Andric   return processExternalFilePath(Helper.ExternalFilePath);
4908bcb0991SDimitry Andric }
4918bcb0991SDimitry Andric 
parseRemark()4928bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::parseRemark() {
4938bcb0991SDimitry Andric   BitstreamRemarkParserHelper RemarkHelper(ParserHelper.Stream);
4948bcb0991SDimitry Andric   if (Error E = RemarkHelper.parse())
4958bcb0991SDimitry Andric     return std::move(E);
4968bcb0991SDimitry Andric 
4978bcb0991SDimitry Andric   return processRemark(RemarkHelper);
4988bcb0991SDimitry Andric }
4998bcb0991SDimitry Andric 
5008bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>>
processRemark(BitstreamRemarkParserHelper & Helper)5018bcb0991SDimitry Andric BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) {
5028bcb0991SDimitry Andric   std::unique_ptr<Remark> Result = std::make_unique<Remark>();
5038bcb0991SDimitry Andric   Remark &R = *Result;
5048bcb0991SDimitry Andric 
505*bdd1243dSDimitry Andric   if (StrTab == std::nullopt)
5068bcb0991SDimitry Andric     return createStringError(
5078bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
5088bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing string table.");
5098bcb0991SDimitry Andric 
5108bcb0991SDimitry Andric   if (!Helper.Type)
5118bcb0991SDimitry Andric     return createStringError(
5128bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
5138bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark type.");
5148bcb0991SDimitry Andric 
5158bcb0991SDimitry Andric   // Always >= Type::First since it's unsigned.
5168bcb0991SDimitry Andric   if (*Helper.Type > static_cast<uint8_t>(Type::Last))
5178bcb0991SDimitry Andric     return createStringError(
5188bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
5198bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: unknown remark type.");
5208bcb0991SDimitry Andric 
5218bcb0991SDimitry Andric   R.RemarkType = static_cast<Type>(*Helper.Type);
5228bcb0991SDimitry Andric 
5238bcb0991SDimitry Andric   if (!Helper.RemarkNameIdx)
5248bcb0991SDimitry Andric     return createStringError(
5258bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
5268bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark name.");
5278bcb0991SDimitry Andric 
5288bcb0991SDimitry Andric   if (Expected<StringRef> RemarkName = (*StrTab)[*Helper.RemarkNameIdx])
5298bcb0991SDimitry Andric     R.RemarkName = *RemarkName;
5308bcb0991SDimitry Andric   else
5318bcb0991SDimitry Andric     return RemarkName.takeError();
5328bcb0991SDimitry Andric 
5338bcb0991SDimitry Andric   if (!Helper.PassNameIdx)
5348bcb0991SDimitry Andric     return createStringError(
5358bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
5368bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark pass.");
5378bcb0991SDimitry Andric 
5388bcb0991SDimitry Andric   if (Expected<StringRef> PassName = (*StrTab)[*Helper.PassNameIdx])
5398bcb0991SDimitry Andric     R.PassName = *PassName;
5408bcb0991SDimitry Andric   else
5418bcb0991SDimitry Andric     return PassName.takeError();
5428bcb0991SDimitry Andric 
5438bcb0991SDimitry Andric   if (!Helper.FunctionNameIdx)
5448bcb0991SDimitry Andric     return createStringError(
5458bcb0991SDimitry Andric         std::make_error_code(std::errc::illegal_byte_sequence),
5468bcb0991SDimitry Andric         "Error while parsing BLOCK_REMARK: missing remark function name.");
5478bcb0991SDimitry Andric   if (Expected<StringRef> FunctionName = (*StrTab)[*Helper.FunctionNameIdx])
5488bcb0991SDimitry Andric     R.FunctionName = *FunctionName;
5498bcb0991SDimitry Andric   else
5508bcb0991SDimitry Andric     return FunctionName.takeError();
5518bcb0991SDimitry Andric 
5528bcb0991SDimitry Andric   if (Helper.SourceFileNameIdx && Helper.SourceLine && Helper.SourceColumn) {
5538bcb0991SDimitry Andric     Expected<StringRef> SourceFileName = (*StrTab)[*Helper.SourceFileNameIdx];
5548bcb0991SDimitry Andric     if (!SourceFileName)
5558bcb0991SDimitry Andric       return SourceFileName.takeError();
5568bcb0991SDimitry Andric     R.Loc.emplace();
5578bcb0991SDimitry Andric     R.Loc->SourceFilePath = *SourceFileName;
5588bcb0991SDimitry Andric     R.Loc->SourceLine = *Helper.SourceLine;
5598bcb0991SDimitry Andric     R.Loc->SourceColumn = *Helper.SourceColumn;
5608bcb0991SDimitry Andric   }
5618bcb0991SDimitry Andric 
5628bcb0991SDimitry Andric   if (Helper.Hotness)
5638bcb0991SDimitry Andric     R.Hotness = *Helper.Hotness;
5648bcb0991SDimitry Andric 
5658bcb0991SDimitry Andric   if (!Helper.Args)
5668bcb0991SDimitry Andric     return std::move(Result);
5678bcb0991SDimitry Andric 
5688bcb0991SDimitry Andric   for (const BitstreamRemarkParserHelper::Argument &Arg : *Helper.Args) {
5698bcb0991SDimitry Andric     if (!Arg.KeyIdx)
5708bcb0991SDimitry Andric       return createStringError(
5718bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
5728bcb0991SDimitry Andric           "Error while parsing BLOCK_REMARK: missing key in remark argument.");
5738bcb0991SDimitry Andric     if (!Arg.ValueIdx)
5748bcb0991SDimitry Andric       return createStringError(
5758bcb0991SDimitry Andric           std::make_error_code(std::errc::illegal_byte_sequence),
5768bcb0991SDimitry Andric           "Error while parsing BLOCK_REMARK: missing value in remark "
5778bcb0991SDimitry Andric           "argument.");
5788bcb0991SDimitry Andric 
5798bcb0991SDimitry Andric     // We have at least a key and a value, create an entry.
5808bcb0991SDimitry Andric     R.Args.emplace_back();
5818bcb0991SDimitry Andric 
5828bcb0991SDimitry Andric     if (Expected<StringRef> Key = (*StrTab)[*Arg.KeyIdx])
5838bcb0991SDimitry Andric       R.Args.back().Key = *Key;
5848bcb0991SDimitry Andric     else
5858bcb0991SDimitry Andric       return Key.takeError();
5868bcb0991SDimitry Andric 
5878bcb0991SDimitry Andric     if (Expected<StringRef> Value = (*StrTab)[*Arg.ValueIdx])
5888bcb0991SDimitry Andric       R.Args.back().Val = *Value;
5898bcb0991SDimitry Andric     else
5908bcb0991SDimitry Andric       return Value.takeError();
5918bcb0991SDimitry Andric 
5928bcb0991SDimitry Andric     if (Arg.SourceFileNameIdx && Arg.SourceLine && Arg.SourceColumn) {
5938bcb0991SDimitry Andric       if (Expected<StringRef> SourceFileName =
5948bcb0991SDimitry Andric               (*StrTab)[*Arg.SourceFileNameIdx]) {
5958bcb0991SDimitry Andric         R.Args.back().Loc.emplace();
5968bcb0991SDimitry Andric         R.Args.back().Loc->SourceFilePath = *SourceFileName;
5978bcb0991SDimitry Andric         R.Args.back().Loc->SourceLine = *Arg.SourceLine;
5988bcb0991SDimitry Andric         R.Args.back().Loc->SourceColumn = *Arg.SourceColumn;
5998bcb0991SDimitry Andric       } else
6008bcb0991SDimitry Andric         return SourceFileName.takeError();
6018bcb0991SDimitry Andric     }
6028bcb0991SDimitry Andric   }
6038bcb0991SDimitry Andric 
6048bcb0991SDimitry Andric   return std::move(Result);
6058bcb0991SDimitry Andric }
606