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