BitstreamRemarkParser.cpp 21 KB

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