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