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