1*8bcb0991SDimitry Andric //===- BitstreamRemarkParser.cpp ------------------------------------------===// 2*8bcb0991SDimitry Andric // 3*8bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*8bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*8bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*8bcb0991SDimitry Andric // 7*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 8*8bcb0991SDimitry Andric // 9*8bcb0991SDimitry Andric // This file provides utility methods used by clients that want to use the 10*8bcb0991SDimitry Andric // parser for remark diagnostics in LLVM. 11*8bcb0991SDimitry Andric // 12*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 13*8bcb0991SDimitry Andric 14*8bcb0991SDimitry Andric #include "llvm/Remarks/BitstreamRemarkParser.h" 15*8bcb0991SDimitry Andric #include "BitstreamRemarkParser.h" 16*8bcb0991SDimitry Andric #include "llvm/Remarks/BitstreamRemarkContainer.h" 17*8bcb0991SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 18*8bcb0991SDimitry Andric #include "llvm/Support/Path.h" 19*8bcb0991SDimitry Andric 20*8bcb0991SDimitry Andric using namespace llvm; 21*8bcb0991SDimitry Andric using namespace llvm::remarks; 22*8bcb0991SDimitry Andric 23*8bcb0991SDimitry Andric static Error unknownRecord(const char *BlockName, unsigned RecordID) { 24*8bcb0991SDimitry Andric return createStringError( 25*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 26*8bcb0991SDimitry Andric "Error while parsing %s: unknown record entry (%lu).", BlockName, 27*8bcb0991SDimitry Andric RecordID); 28*8bcb0991SDimitry Andric } 29*8bcb0991SDimitry Andric 30*8bcb0991SDimitry Andric static Error malformedRecord(const char *BlockName, const char *RecordName) { 31*8bcb0991SDimitry Andric return createStringError( 32*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 33*8bcb0991SDimitry Andric "Error while parsing %s: malformed record entry (%s).", BlockName, 34*8bcb0991SDimitry Andric RecordName); 35*8bcb0991SDimitry Andric } 36*8bcb0991SDimitry Andric 37*8bcb0991SDimitry Andric BitstreamMetaParserHelper::BitstreamMetaParserHelper( 38*8bcb0991SDimitry Andric BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo) 39*8bcb0991SDimitry Andric : Stream(Stream), BlockInfo(BlockInfo) {} 40*8bcb0991SDimitry Andric 41*8bcb0991SDimitry Andric /// Parse a record and fill in the fields in the parser. 42*8bcb0991SDimitry Andric static Error parseRecord(BitstreamMetaParserHelper &Parser, unsigned Code) { 43*8bcb0991SDimitry Andric BitstreamCursor &Stream = Parser.Stream; 44*8bcb0991SDimitry Andric // Note: 2 is used here because it's the max number of fields we have per 45*8bcb0991SDimitry Andric // record. 46*8bcb0991SDimitry Andric SmallVector<uint64_t, 2> Record; 47*8bcb0991SDimitry Andric StringRef Blob; 48*8bcb0991SDimitry Andric Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob); 49*8bcb0991SDimitry Andric if (!RecordID) 50*8bcb0991SDimitry Andric return RecordID.takeError(); 51*8bcb0991SDimitry Andric 52*8bcb0991SDimitry Andric switch (*RecordID) { 53*8bcb0991SDimitry Andric case RECORD_META_CONTAINER_INFO: { 54*8bcb0991SDimitry Andric if (Record.size() != 2) 55*8bcb0991SDimitry Andric return malformedRecord("BLOCK_META", "RECORD_META_CONTAINER_INFO"); 56*8bcb0991SDimitry Andric Parser.ContainerVersion = Record[0]; 57*8bcb0991SDimitry Andric Parser.ContainerType = Record[1]; 58*8bcb0991SDimitry Andric break; 59*8bcb0991SDimitry Andric } 60*8bcb0991SDimitry Andric case RECORD_META_REMARK_VERSION: { 61*8bcb0991SDimitry Andric if (Record.size() != 1) 62*8bcb0991SDimitry Andric return malformedRecord("BLOCK_META", "RECORD_META_REMARK_VERSION"); 63*8bcb0991SDimitry Andric Parser.RemarkVersion = Record[0]; 64*8bcb0991SDimitry Andric break; 65*8bcb0991SDimitry Andric } 66*8bcb0991SDimitry Andric case RECORD_META_STRTAB: { 67*8bcb0991SDimitry Andric if (Record.size() != 0) 68*8bcb0991SDimitry Andric return malformedRecord("BLOCK_META", "RECORD_META_STRTAB"); 69*8bcb0991SDimitry Andric Parser.StrTabBuf = Blob; 70*8bcb0991SDimitry Andric break; 71*8bcb0991SDimitry Andric } 72*8bcb0991SDimitry Andric case RECORD_META_EXTERNAL_FILE: { 73*8bcb0991SDimitry Andric if (Record.size() != 0) 74*8bcb0991SDimitry Andric return malformedRecord("BLOCK_META", "RECORD_META_EXTERNAL_FILE"); 75*8bcb0991SDimitry Andric Parser.ExternalFilePath = Blob; 76*8bcb0991SDimitry Andric break; 77*8bcb0991SDimitry Andric } 78*8bcb0991SDimitry Andric default: 79*8bcb0991SDimitry Andric return unknownRecord("BLOCK_META", *RecordID); 80*8bcb0991SDimitry Andric } 81*8bcb0991SDimitry Andric return Error::success(); 82*8bcb0991SDimitry Andric } 83*8bcb0991SDimitry Andric 84*8bcb0991SDimitry Andric BitstreamRemarkParserHelper::BitstreamRemarkParserHelper( 85*8bcb0991SDimitry Andric BitstreamCursor &Stream) 86*8bcb0991SDimitry Andric : Stream(Stream) {} 87*8bcb0991SDimitry Andric 88*8bcb0991SDimitry Andric /// Parse a record and fill in the fields in the parser. 89*8bcb0991SDimitry Andric static Error parseRecord(BitstreamRemarkParserHelper &Parser, unsigned Code) { 90*8bcb0991SDimitry Andric BitstreamCursor &Stream = Parser.Stream; 91*8bcb0991SDimitry Andric // Note: 5 is used here because it's the max number of fields we have per 92*8bcb0991SDimitry Andric // record. 93*8bcb0991SDimitry Andric SmallVector<uint64_t, 5> Record; 94*8bcb0991SDimitry Andric StringRef Blob; 95*8bcb0991SDimitry Andric Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob); 96*8bcb0991SDimitry Andric if (!RecordID) 97*8bcb0991SDimitry Andric return RecordID.takeError(); 98*8bcb0991SDimitry Andric 99*8bcb0991SDimitry Andric switch (*RecordID) { 100*8bcb0991SDimitry Andric case RECORD_REMARK_HEADER: { 101*8bcb0991SDimitry Andric if (Record.size() != 4) 102*8bcb0991SDimitry Andric return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HEADER"); 103*8bcb0991SDimitry Andric Parser.Type = Record[0]; 104*8bcb0991SDimitry Andric Parser.RemarkNameIdx = Record[1]; 105*8bcb0991SDimitry Andric Parser.PassNameIdx = Record[2]; 106*8bcb0991SDimitry Andric Parser.FunctionNameIdx = Record[3]; 107*8bcb0991SDimitry Andric break; 108*8bcb0991SDimitry Andric } 109*8bcb0991SDimitry Andric case RECORD_REMARK_DEBUG_LOC: { 110*8bcb0991SDimitry Andric if (Record.size() != 3) 111*8bcb0991SDimitry Andric return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_DEBUG_LOC"); 112*8bcb0991SDimitry Andric Parser.SourceFileNameIdx = Record[0]; 113*8bcb0991SDimitry Andric Parser.SourceLine = Record[1]; 114*8bcb0991SDimitry Andric Parser.SourceColumn = Record[2]; 115*8bcb0991SDimitry Andric break; 116*8bcb0991SDimitry Andric } 117*8bcb0991SDimitry Andric case RECORD_REMARK_HOTNESS: { 118*8bcb0991SDimitry Andric if (Record.size() != 1) 119*8bcb0991SDimitry Andric return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HOTNESS"); 120*8bcb0991SDimitry Andric Parser.Hotness = Record[0]; 121*8bcb0991SDimitry Andric break; 122*8bcb0991SDimitry Andric } 123*8bcb0991SDimitry Andric case RECORD_REMARK_ARG_WITH_DEBUGLOC: { 124*8bcb0991SDimitry Andric if (Record.size() != 5) 125*8bcb0991SDimitry Andric return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_ARG_WITH_DEBUGLOC"); 126*8bcb0991SDimitry Andric // Create a temporary argument. Use that as a valid memory location for this 127*8bcb0991SDimitry Andric // argument entry. 128*8bcb0991SDimitry Andric Parser.TmpArgs.emplace_back(); 129*8bcb0991SDimitry Andric Parser.TmpArgs.back().KeyIdx = Record[0]; 130*8bcb0991SDimitry Andric Parser.TmpArgs.back().ValueIdx = Record[1]; 131*8bcb0991SDimitry Andric Parser.TmpArgs.back().SourceFileNameIdx = Record[2]; 132*8bcb0991SDimitry Andric Parser.TmpArgs.back().SourceLine = Record[3]; 133*8bcb0991SDimitry Andric Parser.TmpArgs.back().SourceColumn = Record[4]; 134*8bcb0991SDimitry Andric Parser.Args = 135*8bcb0991SDimitry Andric ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs); 136*8bcb0991SDimitry Andric break; 137*8bcb0991SDimitry Andric } 138*8bcb0991SDimitry Andric case RECORD_REMARK_ARG_WITHOUT_DEBUGLOC: { 139*8bcb0991SDimitry Andric if (Record.size() != 2) 140*8bcb0991SDimitry Andric return malformedRecord("BLOCK_REMARK", 141*8bcb0991SDimitry Andric "RECORD_REMARK_ARG_WITHOUT_DEBUGLOC"); 142*8bcb0991SDimitry Andric // Create a temporary argument. Use that as a valid memory location for this 143*8bcb0991SDimitry Andric // argument entry. 144*8bcb0991SDimitry Andric Parser.TmpArgs.emplace_back(); 145*8bcb0991SDimitry Andric Parser.TmpArgs.back().KeyIdx = Record[0]; 146*8bcb0991SDimitry Andric Parser.TmpArgs.back().ValueIdx = Record[1]; 147*8bcb0991SDimitry Andric Parser.Args = 148*8bcb0991SDimitry Andric ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs); 149*8bcb0991SDimitry Andric break; 150*8bcb0991SDimitry Andric } 151*8bcb0991SDimitry Andric default: 152*8bcb0991SDimitry Andric return unknownRecord("BLOCK_REMARK", *RecordID); 153*8bcb0991SDimitry Andric } 154*8bcb0991SDimitry Andric return Error::success(); 155*8bcb0991SDimitry Andric } 156*8bcb0991SDimitry Andric 157*8bcb0991SDimitry Andric template <typename T> 158*8bcb0991SDimitry Andric static Error parseBlock(T &ParserHelper, unsigned BlockID, 159*8bcb0991SDimitry Andric const char *BlockName) { 160*8bcb0991SDimitry Andric BitstreamCursor &Stream = ParserHelper.Stream; 161*8bcb0991SDimitry Andric Expected<BitstreamEntry> Next = Stream.advance(); 162*8bcb0991SDimitry Andric if (!Next) 163*8bcb0991SDimitry Andric return Next.takeError(); 164*8bcb0991SDimitry Andric if (Next->Kind != BitstreamEntry::SubBlock || Next->ID != BlockID) 165*8bcb0991SDimitry Andric return createStringError( 166*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 167*8bcb0991SDimitry Andric "Error while parsing %s: expecting [ENTER_SUBBLOCK, %s, ...].", 168*8bcb0991SDimitry Andric BlockName, BlockName); 169*8bcb0991SDimitry Andric if (Stream.EnterSubBlock(BlockID)) 170*8bcb0991SDimitry Andric return createStringError( 171*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 172*8bcb0991SDimitry Andric "Error while entering %s.", BlockName); 173*8bcb0991SDimitry Andric 174*8bcb0991SDimitry Andric // Stop when there is nothing to read anymore or when we encounter an 175*8bcb0991SDimitry Andric // END_BLOCK. 176*8bcb0991SDimitry Andric while (!Stream.AtEndOfStream()) { 177*8bcb0991SDimitry Andric Expected<BitstreamEntry> Next = Stream.advance(); 178*8bcb0991SDimitry Andric if (!Next) 179*8bcb0991SDimitry Andric return Next.takeError(); 180*8bcb0991SDimitry Andric switch (Next->Kind) { 181*8bcb0991SDimitry Andric case BitstreamEntry::EndBlock: 182*8bcb0991SDimitry Andric return Error::success(); 183*8bcb0991SDimitry Andric case BitstreamEntry::Error: 184*8bcb0991SDimitry Andric case BitstreamEntry::SubBlock: 185*8bcb0991SDimitry Andric return createStringError( 186*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 187*8bcb0991SDimitry Andric "Error while parsing %s: expecting records.", BlockName); 188*8bcb0991SDimitry Andric case BitstreamEntry::Record: 189*8bcb0991SDimitry Andric if (Error E = parseRecord(ParserHelper, Next->ID)) 190*8bcb0991SDimitry Andric return E; 191*8bcb0991SDimitry Andric continue; 192*8bcb0991SDimitry Andric } 193*8bcb0991SDimitry Andric } 194*8bcb0991SDimitry Andric // If we're here, it means we didn't get an END_BLOCK yet, but we're at the 195*8bcb0991SDimitry Andric // end of the stream. In this case, error. 196*8bcb0991SDimitry Andric return createStringError( 197*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 198*8bcb0991SDimitry Andric "Error while parsing %s: unterminated block.", BlockName); 199*8bcb0991SDimitry Andric } 200*8bcb0991SDimitry Andric 201*8bcb0991SDimitry Andric Error BitstreamMetaParserHelper::parse() { 202*8bcb0991SDimitry Andric return parseBlock(*this, META_BLOCK_ID, "META_BLOCK"); 203*8bcb0991SDimitry Andric } 204*8bcb0991SDimitry Andric 205*8bcb0991SDimitry Andric Error BitstreamRemarkParserHelper::parse() { 206*8bcb0991SDimitry Andric return parseBlock(*this, REMARK_BLOCK_ID, "REMARK_BLOCK"); 207*8bcb0991SDimitry Andric } 208*8bcb0991SDimitry Andric 209*8bcb0991SDimitry Andric BitstreamParserHelper::BitstreamParserHelper(StringRef Buffer) 210*8bcb0991SDimitry Andric : Stream(Buffer) {} 211*8bcb0991SDimitry Andric 212*8bcb0991SDimitry Andric Expected<std::array<char, 4>> BitstreamParserHelper::parseMagic() { 213*8bcb0991SDimitry Andric std::array<char, 4> Result; 214*8bcb0991SDimitry Andric for (unsigned i = 0; i < 4; ++i) 215*8bcb0991SDimitry Andric if (Expected<unsigned> R = Stream.Read(8)) 216*8bcb0991SDimitry Andric Result[i] = *R; 217*8bcb0991SDimitry Andric else 218*8bcb0991SDimitry Andric return R.takeError(); 219*8bcb0991SDimitry Andric return Result; 220*8bcb0991SDimitry Andric } 221*8bcb0991SDimitry Andric 222*8bcb0991SDimitry Andric Error BitstreamParserHelper::parseBlockInfoBlock() { 223*8bcb0991SDimitry Andric Expected<BitstreamEntry> Next = Stream.advance(); 224*8bcb0991SDimitry Andric if (!Next) 225*8bcb0991SDimitry Andric return Next.takeError(); 226*8bcb0991SDimitry Andric if (Next->Kind != BitstreamEntry::SubBlock || 227*8bcb0991SDimitry Andric Next->ID != llvm::bitc::BLOCKINFO_BLOCK_ID) 228*8bcb0991SDimitry Andric return createStringError( 229*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 230*8bcb0991SDimitry Andric "Error while parsing BLOCKINFO_BLOCK: expecting [ENTER_SUBBLOCK, " 231*8bcb0991SDimitry Andric "BLOCKINFO_BLOCK, ...]."); 232*8bcb0991SDimitry Andric 233*8bcb0991SDimitry Andric Expected<Optional<BitstreamBlockInfo>> MaybeBlockInfo = 234*8bcb0991SDimitry Andric Stream.ReadBlockInfoBlock(); 235*8bcb0991SDimitry Andric if (!MaybeBlockInfo) 236*8bcb0991SDimitry Andric return MaybeBlockInfo.takeError(); 237*8bcb0991SDimitry Andric 238*8bcb0991SDimitry Andric if (!*MaybeBlockInfo) 239*8bcb0991SDimitry Andric return createStringError( 240*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 241*8bcb0991SDimitry Andric "Error while parsing BLOCKINFO_BLOCK."); 242*8bcb0991SDimitry Andric 243*8bcb0991SDimitry Andric BlockInfo = **MaybeBlockInfo; 244*8bcb0991SDimitry Andric 245*8bcb0991SDimitry Andric Stream.setBlockInfo(&BlockInfo); 246*8bcb0991SDimitry Andric return Error::success(); 247*8bcb0991SDimitry Andric } 248*8bcb0991SDimitry Andric 249*8bcb0991SDimitry Andric static Expected<bool> isBlock(BitstreamCursor &Stream, unsigned BlockID) { 250*8bcb0991SDimitry Andric bool Result = false; 251*8bcb0991SDimitry Andric uint64_t PreviousBitNo = Stream.GetCurrentBitNo(); 252*8bcb0991SDimitry Andric Expected<BitstreamEntry> Next = Stream.advance(); 253*8bcb0991SDimitry Andric if (!Next) 254*8bcb0991SDimitry Andric return Next.takeError(); 255*8bcb0991SDimitry Andric switch (Next->Kind) { 256*8bcb0991SDimitry Andric case BitstreamEntry::SubBlock: 257*8bcb0991SDimitry Andric // Check for the block id. 258*8bcb0991SDimitry Andric Result = Next->ID == BlockID; 259*8bcb0991SDimitry Andric break; 260*8bcb0991SDimitry Andric case BitstreamEntry::Error: 261*8bcb0991SDimitry Andric return createStringError( 262*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 263*8bcb0991SDimitry Andric "Unexpected error while parsing bitstream."); 264*8bcb0991SDimitry Andric default: 265*8bcb0991SDimitry Andric Result = false; 266*8bcb0991SDimitry Andric break; 267*8bcb0991SDimitry Andric } 268*8bcb0991SDimitry Andric if (Error E = Stream.JumpToBit(PreviousBitNo)) 269*8bcb0991SDimitry Andric return std::move(E); 270*8bcb0991SDimitry Andric return Result; 271*8bcb0991SDimitry Andric } 272*8bcb0991SDimitry Andric 273*8bcb0991SDimitry Andric Expected<bool> BitstreamParserHelper::isMetaBlock() { 274*8bcb0991SDimitry Andric return isBlock(Stream, META_BLOCK_ID); 275*8bcb0991SDimitry Andric } 276*8bcb0991SDimitry Andric 277*8bcb0991SDimitry Andric Expected<bool> BitstreamParserHelper::isRemarkBlock() { 278*8bcb0991SDimitry Andric return isBlock(Stream, META_BLOCK_ID); 279*8bcb0991SDimitry Andric } 280*8bcb0991SDimitry Andric 281*8bcb0991SDimitry Andric static Error validateMagicNumber(StringRef Magic) { 282*8bcb0991SDimitry Andric if (Magic != remarks::ContainerMagic) 283*8bcb0991SDimitry Andric return createStringError(std::make_error_code(std::errc::invalid_argument), 284*8bcb0991SDimitry Andric "Unknown magic number: expecting %s, got %.4s.", 285*8bcb0991SDimitry Andric remarks::ContainerMagic.data(), Magic.data()); 286*8bcb0991SDimitry Andric return Error::success(); 287*8bcb0991SDimitry Andric } 288*8bcb0991SDimitry Andric 289*8bcb0991SDimitry Andric static Error advanceToMetaBlock(BitstreamParserHelper &Helper) { 290*8bcb0991SDimitry Andric Expected<std::array<char, 4>> Magic = Helper.parseMagic(); 291*8bcb0991SDimitry Andric if (!Magic) 292*8bcb0991SDimitry Andric return Magic.takeError(); 293*8bcb0991SDimitry Andric if (Error E = validateMagicNumber(StringRef(Magic->data(), Magic->size()))) 294*8bcb0991SDimitry Andric return E; 295*8bcb0991SDimitry Andric if (Error E = Helper.parseBlockInfoBlock()) 296*8bcb0991SDimitry Andric return E; 297*8bcb0991SDimitry Andric Expected<bool> isMetaBlock = Helper.isMetaBlock(); 298*8bcb0991SDimitry Andric if (!isMetaBlock) 299*8bcb0991SDimitry Andric return isMetaBlock.takeError(); 300*8bcb0991SDimitry Andric if (!*isMetaBlock) 301*8bcb0991SDimitry Andric return createStringError( 302*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 303*8bcb0991SDimitry Andric "Expecting META_BLOCK after the BLOCKINFO_BLOCK."); 304*8bcb0991SDimitry Andric return Error::success(); 305*8bcb0991SDimitry Andric } 306*8bcb0991SDimitry Andric 307*8bcb0991SDimitry Andric Expected<std::unique_ptr<BitstreamRemarkParser>> 308*8bcb0991SDimitry Andric remarks::createBitstreamParserFromMeta( 309*8bcb0991SDimitry Andric StringRef Buf, Optional<ParsedStringTable> StrTab, 310*8bcb0991SDimitry Andric Optional<StringRef> ExternalFilePrependPath) { 311*8bcb0991SDimitry Andric BitstreamParserHelper Helper(Buf); 312*8bcb0991SDimitry Andric Expected<std::array<char, 4>> Magic = Helper.parseMagic(); 313*8bcb0991SDimitry Andric if (!Magic) 314*8bcb0991SDimitry Andric return Magic.takeError(); 315*8bcb0991SDimitry Andric 316*8bcb0991SDimitry Andric if (Error E = validateMagicNumber(StringRef(Magic->data(), Magic->size()))) 317*8bcb0991SDimitry Andric return std::move(E); 318*8bcb0991SDimitry Andric 319*8bcb0991SDimitry Andric auto Parser = 320*8bcb0991SDimitry Andric StrTab ? std::make_unique<BitstreamRemarkParser>(Buf, std::move(*StrTab)) 321*8bcb0991SDimitry Andric : std::make_unique<BitstreamRemarkParser>(Buf); 322*8bcb0991SDimitry Andric 323*8bcb0991SDimitry Andric if (ExternalFilePrependPath) 324*8bcb0991SDimitry Andric Parser->ExternalFilePrependPath = *ExternalFilePrependPath; 325*8bcb0991SDimitry Andric 326*8bcb0991SDimitry Andric return std::move(Parser); 327*8bcb0991SDimitry Andric } 328*8bcb0991SDimitry Andric 329*8bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::next() { 330*8bcb0991SDimitry Andric if (ParserHelper.atEndOfStream()) 331*8bcb0991SDimitry Andric return make_error<EndOfFileError>(); 332*8bcb0991SDimitry Andric 333*8bcb0991SDimitry Andric if (!ReadyToParseRemarks) { 334*8bcb0991SDimitry Andric if (Error E = parseMeta()) 335*8bcb0991SDimitry Andric return std::move(E); 336*8bcb0991SDimitry Andric ReadyToParseRemarks = true; 337*8bcb0991SDimitry Andric } 338*8bcb0991SDimitry Andric 339*8bcb0991SDimitry Andric return parseRemark(); 340*8bcb0991SDimitry Andric } 341*8bcb0991SDimitry Andric 342*8bcb0991SDimitry Andric Error BitstreamRemarkParser::parseMeta() { 343*8bcb0991SDimitry Andric // Advance and to the meta block. 344*8bcb0991SDimitry Andric if (Error E = advanceToMetaBlock(ParserHelper)) 345*8bcb0991SDimitry Andric return E; 346*8bcb0991SDimitry Andric 347*8bcb0991SDimitry Andric BitstreamMetaParserHelper MetaHelper(ParserHelper.Stream, 348*8bcb0991SDimitry Andric ParserHelper.BlockInfo); 349*8bcb0991SDimitry Andric if (Error E = MetaHelper.parse()) 350*8bcb0991SDimitry Andric return E; 351*8bcb0991SDimitry Andric 352*8bcb0991SDimitry Andric if (Error E = processCommonMeta(MetaHelper)) 353*8bcb0991SDimitry Andric return E; 354*8bcb0991SDimitry Andric 355*8bcb0991SDimitry Andric switch (ContainerType) { 356*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::Standalone: 357*8bcb0991SDimitry Andric return processStandaloneMeta(MetaHelper); 358*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksFile: 359*8bcb0991SDimitry Andric return processSeparateRemarksFileMeta(MetaHelper); 360*8bcb0991SDimitry Andric case BitstreamRemarkContainerType::SeparateRemarksMeta: 361*8bcb0991SDimitry Andric return processSeparateRemarksMetaMeta(MetaHelper); 362*8bcb0991SDimitry Andric } 363*8bcb0991SDimitry Andric llvm_unreachable("Unknown BitstreamRemarkContainerType enum"); 364*8bcb0991SDimitry Andric } 365*8bcb0991SDimitry Andric 366*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processCommonMeta( 367*8bcb0991SDimitry Andric BitstreamMetaParserHelper &MetaHelper) { 368*8bcb0991SDimitry Andric if (Optional<uint64_t> Version = MetaHelper.ContainerVersion) 369*8bcb0991SDimitry Andric ContainerVersion = *Version; 370*8bcb0991SDimitry Andric else 371*8bcb0991SDimitry Andric return createStringError( 372*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 373*8bcb0991SDimitry Andric "Error while parsing BLOCK_META: missing container version."); 374*8bcb0991SDimitry Andric 375*8bcb0991SDimitry Andric if (Optional<uint8_t> Type = MetaHelper.ContainerType) { 376*8bcb0991SDimitry Andric // Always >= BitstreamRemarkContainerType::First since it's unsigned. 377*8bcb0991SDimitry Andric if (*Type > static_cast<uint8_t>(BitstreamRemarkContainerType::Last)) 378*8bcb0991SDimitry Andric return createStringError( 379*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 380*8bcb0991SDimitry Andric "Error while parsing BLOCK_META: invalid container type."); 381*8bcb0991SDimitry Andric 382*8bcb0991SDimitry Andric ContainerType = static_cast<BitstreamRemarkContainerType>(*Type); 383*8bcb0991SDimitry Andric } else 384*8bcb0991SDimitry Andric return createStringError( 385*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 386*8bcb0991SDimitry Andric "Error while parsing BLOCK_META: missing container type."); 387*8bcb0991SDimitry Andric 388*8bcb0991SDimitry Andric return Error::success(); 389*8bcb0991SDimitry Andric } 390*8bcb0991SDimitry Andric 391*8bcb0991SDimitry Andric static Error processStrTab(BitstreamRemarkParser &P, 392*8bcb0991SDimitry Andric Optional<StringRef> StrTabBuf) { 393*8bcb0991SDimitry Andric if (!StrTabBuf) 394*8bcb0991SDimitry Andric return createStringError( 395*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 396*8bcb0991SDimitry Andric "Error while parsing BLOCK_META: missing string table."); 397*8bcb0991SDimitry Andric // Parse and assign the string table. 398*8bcb0991SDimitry Andric P.StrTab.emplace(*StrTabBuf); 399*8bcb0991SDimitry Andric return Error::success(); 400*8bcb0991SDimitry Andric } 401*8bcb0991SDimitry Andric 402*8bcb0991SDimitry Andric static Error processRemarkVersion(BitstreamRemarkParser &P, 403*8bcb0991SDimitry Andric Optional<uint64_t> RemarkVersion) { 404*8bcb0991SDimitry Andric if (!RemarkVersion) 405*8bcb0991SDimitry Andric return createStringError( 406*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 407*8bcb0991SDimitry Andric "Error while parsing BLOCK_META: missing remark version."); 408*8bcb0991SDimitry Andric P.RemarkVersion = *RemarkVersion; 409*8bcb0991SDimitry Andric return Error::success(); 410*8bcb0991SDimitry Andric } 411*8bcb0991SDimitry Andric 412*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processExternalFilePath( 413*8bcb0991SDimitry Andric Optional<StringRef> ExternalFilePath) { 414*8bcb0991SDimitry Andric if (!ExternalFilePath) 415*8bcb0991SDimitry Andric return createStringError( 416*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 417*8bcb0991SDimitry Andric "Error while parsing BLOCK_META: missing external file path."); 418*8bcb0991SDimitry Andric 419*8bcb0991SDimitry Andric SmallString<80> FullPath(ExternalFilePrependPath); 420*8bcb0991SDimitry Andric sys::path::append(FullPath, *ExternalFilePath); 421*8bcb0991SDimitry Andric 422*8bcb0991SDimitry Andric // External file: open the external file, parse it, check if its metadata 423*8bcb0991SDimitry Andric // matches the one from the separate metadata, then replace the current parser 424*8bcb0991SDimitry Andric // with the one parsing the remarks. 425*8bcb0991SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 426*8bcb0991SDimitry Andric MemoryBuffer::getFile(FullPath); 427*8bcb0991SDimitry Andric if (std::error_code EC = BufferOrErr.getError()) 428*8bcb0991SDimitry Andric return createFileError(FullPath, EC); 429*8bcb0991SDimitry Andric TmpRemarkBuffer = std::move(*BufferOrErr); 430*8bcb0991SDimitry Andric 431*8bcb0991SDimitry Andric // Create a separate parser used for parsing the separate file. 432*8bcb0991SDimitry Andric ParserHelper = BitstreamParserHelper(TmpRemarkBuffer->getBuffer()); 433*8bcb0991SDimitry Andric // Advance and check until we can parse the meta block. 434*8bcb0991SDimitry Andric if (Error E = advanceToMetaBlock(ParserHelper)) 435*8bcb0991SDimitry Andric return E; 436*8bcb0991SDimitry Andric // Parse the meta from the separate file. 437*8bcb0991SDimitry Andric // Note: here we overwrite the BlockInfo with the one from the file. This will 438*8bcb0991SDimitry Andric // be used to parse the rest of the file. 439*8bcb0991SDimitry Andric BitstreamMetaParserHelper SeparateMetaHelper(ParserHelper.Stream, 440*8bcb0991SDimitry Andric ParserHelper.BlockInfo); 441*8bcb0991SDimitry Andric if (Error E = SeparateMetaHelper.parse()) 442*8bcb0991SDimitry Andric return E; 443*8bcb0991SDimitry Andric 444*8bcb0991SDimitry Andric uint64_t PreviousContainerVersion = ContainerVersion; 445*8bcb0991SDimitry Andric if (Error E = processCommonMeta(SeparateMetaHelper)) 446*8bcb0991SDimitry Andric return E; 447*8bcb0991SDimitry Andric 448*8bcb0991SDimitry Andric if (ContainerType != BitstreamRemarkContainerType::SeparateRemarksFile) 449*8bcb0991SDimitry Andric return createStringError( 450*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 451*8bcb0991SDimitry Andric "Error while parsing external file's BLOCK_META: wrong container " 452*8bcb0991SDimitry Andric "type."); 453*8bcb0991SDimitry Andric 454*8bcb0991SDimitry Andric if (PreviousContainerVersion != ContainerVersion) 455*8bcb0991SDimitry Andric return createStringError( 456*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 457*8bcb0991SDimitry Andric "Error while parsing external file's BLOCK_META: mismatching versions: " 458*8bcb0991SDimitry Andric "original meta: %lu, external file meta: %lu.", 459*8bcb0991SDimitry Andric PreviousContainerVersion, ContainerVersion); 460*8bcb0991SDimitry Andric 461*8bcb0991SDimitry Andric // Process the meta from the separate file. 462*8bcb0991SDimitry Andric return processSeparateRemarksFileMeta(SeparateMetaHelper); 463*8bcb0991SDimitry Andric } 464*8bcb0991SDimitry Andric 465*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processStandaloneMeta( 466*8bcb0991SDimitry Andric BitstreamMetaParserHelper &Helper) { 467*8bcb0991SDimitry Andric if (Error E = processStrTab(*this, Helper.StrTabBuf)) 468*8bcb0991SDimitry Andric return E; 469*8bcb0991SDimitry Andric return processRemarkVersion(*this, Helper.RemarkVersion); 470*8bcb0991SDimitry Andric } 471*8bcb0991SDimitry Andric 472*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processSeparateRemarksFileMeta( 473*8bcb0991SDimitry Andric BitstreamMetaParserHelper &Helper) { 474*8bcb0991SDimitry Andric return processRemarkVersion(*this, Helper.RemarkVersion); 475*8bcb0991SDimitry Andric } 476*8bcb0991SDimitry Andric 477*8bcb0991SDimitry Andric Error BitstreamRemarkParser::processSeparateRemarksMetaMeta( 478*8bcb0991SDimitry Andric BitstreamMetaParserHelper &Helper) { 479*8bcb0991SDimitry Andric if (Error E = processStrTab(*this, Helper.StrTabBuf)) 480*8bcb0991SDimitry Andric return E; 481*8bcb0991SDimitry Andric return processExternalFilePath(Helper.ExternalFilePath); 482*8bcb0991SDimitry Andric } 483*8bcb0991SDimitry Andric 484*8bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::parseRemark() { 485*8bcb0991SDimitry Andric BitstreamRemarkParserHelper RemarkHelper(ParserHelper.Stream); 486*8bcb0991SDimitry Andric if (Error E = RemarkHelper.parse()) 487*8bcb0991SDimitry Andric return std::move(E); 488*8bcb0991SDimitry Andric 489*8bcb0991SDimitry Andric return processRemark(RemarkHelper); 490*8bcb0991SDimitry Andric } 491*8bcb0991SDimitry Andric 492*8bcb0991SDimitry Andric Expected<std::unique_ptr<Remark>> 493*8bcb0991SDimitry Andric BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) { 494*8bcb0991SDimitry Andric std::unique_ptr<Remark> Result = std::make_unique<Remark>(); 495*8bcb0991SDimitry Andric Remark &R = *Result; 496*8bcb0991SDimitry Andric 497*8bcb0991SDimitry Andric if (StrTab == None) 498*8bcb0991SDimitry Andric return createStringError( 499*8bcb0991SDimitry Andric std::make_error_code(std::errc::invalid_argument), 500*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: missing string table."); 501*8bcb0991SDimitry Andric 502*8bcb0991SDimitry Andric if (!Helper.Type) 503*8bcb0991SDimitry Andric return createStringError( 504*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 505*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: missing remark type."); 506*8bcb0991SDimitry Andric 507*8bcb0991SDimitry Andric // Always >= Type::First since it's unsigned. 508*8bcb0991SDimitry Andric if (*Helper.Type > static_cast<uint8_t>(Type::Last)) 509*8bcb0991SDimitry Andric return createStringError( 510*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 511*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: unknown remark type."); 512*8bcb0991SDimitry Andric 513*8bcb0991SDimitry Andric R.RemarkType = static_cast<Type>(*Helper.Type); 514*8bcb0991SDimitry Andric 515*8bcb0991SDimitry Andric if (!Helper.RemarkNameIdx) 516*8bcb0991SDimitry Andric return createStringError( 517*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 518*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: missing remark name."); 519*8bcb0991SDimitry Andric 520*8bcb0991SDimitry Andric if (Expected<StringRef> RemarkName = (*StrTab)[*Helper.RemarkNameIdx]) 521*8bcb0991SDimitry Andric R.RemarkName = *RemarkName; 522*8bcb0991SDimitry Andric else 523*8bcb0991SDimitry Andric return RemarkName.takeError(); 524*8bcb0991SDimitry Andric 525*8bcb0991SDimitry Andric if (!Helper.PassNameIdx) 526*8bcb0991SDimitry Andric return createStringError( 527*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 528*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: missing remark pass."); 529*8bcb0991SDimitry Andric 530*8bcb0991SDimitry Andric if (Expected<StringRef> PassName = (*StrTab)[*Helper.PassNameIdx]) 531*8bcb0991SDimitry Andric R.PassName = *PassName; 532*8bcb0991SDimitry Andric else 533*8bcb0991SDimitry Andric return PassName.takeError(); 534*8bcb0991SDimitry Andric 535*8bcb0991SDimitry Andric if (!Helper.FunctionNameIdx) 536*8bcb0991SDimitry Andric return createStringError( 537*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 538*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: missing remark function name."); 539*8bcb0991SDimitry Andric if (Expected<StringRef> FunctionName = (*StrTab)[*Helper.FunctionNameIdx]) 540*8bcb0991SDimitry Andric R.FunctionName = *FunctionName; 541*8bcb0991SDimitry Andric else 542*8bcb0991SDimitry Andric return FunctionName.takeError(); 543*8bcb0991SDimitry Andric 544*8bcb0991SDimitry Andric if (Helper.SourceFileNameIdx && Helper.SourceLine && Helper.SourceColumn) { 545*8bcb0991SDimitry Andric Expected<StringRef> SourceFileName = (*StrTab)[*Helper.SourceFileNameIdx]; 546*8bcb0991SDimitry Andric if (!SourceFileName) 547*8bcb0991SDimitry Andric return SourceFileName.takeError(); 548*8bcb0991SDimitry Andric R.Loc.emplace(); 549*8bcb0991SDimitry Andric R.Loc->SourceFilePath = *SourceFileName; 550*8bcb0991SDimitry Andric R.Loc->SourceLine = *Helper.SourceLine; 551*8bcb0991SDimitry Andric R.Loc->SourceColumn = *Helper.SourceColumn; 552*8bcb0991SDimitry Andric } 553*8bcb0991SDimitry Andric 554*8bcb0991SDimitry Andric if (Helper.Hotness) 555*8bcb0991SDimitry Andric R.Hotness = *Helper.Hotness; 556*8bcb0991SDimitry Andric 557*8bcb0991SDimitry Andric if (!Helper.Args) 558*8bcb0991SDimitry Andric return std::move(Result); 559*8bcb0991SDimitry Andric 560*8bcb0991SDimitry Andric for (const BitstreamRemarkParserHelper::Argument &Arg : *Helper.Args) { 561*8bcb0991SDimitry Andric if (!Arg.KeyIdx) 562*8bcb0991SDimitry Andric return createStringError( 563*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 564*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: missing key in remark argument."); 565*8bcb0991SDimitry Andric if (!Arg.ValueIdx) 566*8bcb0991SDimitry Andric return createStringError( 567*8bcb0991SDimitry Andric std::make_error_code(std::errc::illegal_byte_sequence), 568*8bcb0991SDimitry Andric "Error while parsing BLOCK_REMARK: missing value in remark " 569*8bcb0991SDimitry Andric "argument."); 570*8bcb0991SDimitry Andric 571*8bcb0991SDimitry Andric // We have at least a key and a value, create an entry. 572*8bcb0991SDimitry Andric R.Args.emplace_back(); 573*8bcb0991SDimitry Andric 574*8bcb0991SDimitry Andric if (Expected<StringRef> Key = (*StrTab)[*Arg.KeyIdx]) 575*8bcb0991SDimitry Andric R.Args.back().Key = *Key; 576*8bcb0991SDimitry Andric else 577*8bcb0991SDimitry Andric return Key.takeError(); 578*8bcb0991SDimitry Andric 579*8bcb0991SDimitry Andric if (Expected<StringRef> Value = (*StrTab)[*Arg.ValueIdx]) 580*8bcb0991SDimitry Andric R.Args.back().Val = *Value; 581*8bcb0991SDimitry Andric else 582*8bcb0991SDimitry Andric return Value.takeError(); 583*8bcb0991SDimitry Andric 584*8bcb0991SDimitry Andric if (Arg.SourceFileNameIdx && Arg.SourceLine && Arg.SourceColumn) { 585*8bcb0991SDimitry Andric if (Expected<StringRef> SourceFileName = 586*8bcb0991SDimitry Andric (*StrTab)[*Arg.SourceFileNameIdx]) { 587*8bcb0991SDimitry Andric R.Args.back().Loc.emplace(); 588*8bcb0991SDimitry Andric R.Args.back().Loc->SourceFilePath = *SourceFileName; 589*8bcb0991SDimitry Andric R.Args.back().Loc->SourceLine = *Arg.SourceLine; 590*8bcb0991SDimitry Andric R.Args.back().Loc->SourceColumn = *Arg.SourceColumn; 591*8bcb0991SDimitry Andric } else 592*8bcb0991SDimitry Andric return SourceFileName.takeError(); 593*8bcb0991SDimitry Andric } 594*8bcb0991SDimitry Andric } 595*8bcb0991SDimitry Andric 596*8bcb0991SDimitry Andric return std::move(Result); 597*8bcb0991SDimitry Andric } 598