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