BitstreamRemarkParser.cpp 21 KB

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