1//===- llvm/IR/DiagnosticInfo.cpp - Diagnostic Definitions ------*- C++ -*-===//
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 defines the different classes involved in low level diagnostics.
10//
11// Diagnostics reporting is still done as part of the LLVMContext.
12//===----------------------------------------------------------------------===//
13
14#include "llvm/IR/DiagnosticInfo.h"
15#include "llvm/ADT/StringExtras.h"
16#include "llvm/ADT/Twine.h"
17#include "llvm/ADT/iterator_range.h"
18#include "llvm/Demangle/Demangle.h"
19#include "llvm/IR/BasicBlock.h"
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/DebugInfoMetadata.h"
22#include "llvm/IR/DerivedTypes.h"
23#include "llvm/IR/DiagnosticPrinter.h"
24#include "llvm/IR/Function.h"
25#include "llvm/IR/GlobalValue.h"
26#include "llvm/IR/Instruction.h"
27#include "llvm/IR/Instructions.h"
28#include "llvm/IR/IntrinsicInst.h"
29#include "llvm/IR/Intrinsics.h"
30#include "llvm/IR/LLVMContext.h"
31#include "llvm/IR/Metadata.h"
32#include "llvm/IR/Module.h"
33#include "llvm/IR/Type.h"
34#include "llvm/IR/Value.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/InstructionCost.h"
38#include "llvm/Support/Path.h"
39#include "llvm/Support/ScopedPrinter.h"
40#include "llvm/Support/raw_ostream.h"
41#include <atomic>
42#include <string>
43
44using namespace llvm;
45
46int llvm::getNextAvailablePluginDiagnosticKind() {
47 static std::atomic<int> PluginKindID(DK_FirstPluginKind);
48 return ++PluginKindID;
49}
50
51const char *OptimizationRemarkAnalysis::AlwaysPrint = "";
52
53void DiagnosticInfoGeneric::print(DiagnosticPrinter &DP) const {
54 DP << getMsgStr();
55}
56
57void DiagnosticInfoGenericWithLoc::print(DiagnosticPrinter &DP) const {
58 DP << getLocationStr() << ": " << getMsgStr();
59}
60
61DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(uint64_t LocCookie,
62 const Twine &MsgStr,
63 DiagnosticSeverity Severity)
64 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
65 MsgStr(MsgStr) {}
66
67DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
68 const Twine &MsgStr,
69 DiagnosticSeverity Severity)
70 : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) {
71 if (const MDNode *SrcLoc = I.getMetadata(Kind: "srcloc")) {
72 if (SrcLoc->getNumOperands() != 0)
73 if (const auto *CI =
74 mdconst::dyn_extract<ConstantInt>(MD: SrcLoc->getOperand(I: 0)))
75 LocCookie = CI->getZExtValue();
76 }
77}
78
79void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
80 DP << getMsgStr();
81 if (getLocCookie())
82 DP << " at line " << getLocCookie();
83}
84
85void DiagnosticInfoLegalizationFailure::print(DiagnosticPrinter &DP) const {
86 DP << getLocationStr() << ": " << getMsgStr();
87}
88
89DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
90 const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL,
91 DiagnosticSeverity Severity)
92 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
93 DL.isValid() ? DL : Fn.getSubprogram()),
94 MsgStr(MsgStr) {}
95
96DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
97 const Twine &MsgStr, const Function &Fn, DiagnosticSeverity Severity)
98 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
99 Fn.getSubprogram()),
100 MsgStr(MsgStr) {}
101
102void DiagnosticInfoRegAllocFailure::print(DiagnosticPrinter &DP) const {
103 DP << getLocationStr() << ": " << MsgStr << " in function '" << getFunction()
104 << '\'';
105}
106
107DiagnosticInfoResourceLimit::DiagnosticInfoResourceLimit(
108 const Function &Fn, const Twine &ResourceName, uint64_t ResourceSize,
109 uint64_t ResourceLimit, DiagnosticSeverity Severity, DiagnosticKind Kind)
110 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Fn.getSubprogram()),
111 Fn(Fn), ResourceName(ResourceName), ResourceSize(ResourceSize),
112 ResourceLimit(ResourceLimit) {}
113
114void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {
115 DP << getLocationStr() << ": " << getResourceName() << " ("
116 << getResourceSize() << ") exceeds limit (" << getResourceLimit()
117 << ") in function '" << getFunction() << '\'';
118}
119
120void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
121 DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
122 << ") in " << getModule();
123}
124
125void DiagnosticInfoIgnoringInvalidDebugMetadata::print(
126 DiagnosticPrinter &DP) const {
127 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
128}
129
130void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
131 if (!FileName.empty()) {
132 DP << getFileName();
133 if (LineNum > 0)
134 DP << ":" << getLineNum();
135 DP << ": ";
136 }
137 DP << getMsg();
138}
139
140void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {
141 if (getFileName())
142 DP << getFileName() << ": ";
143 DP << getMsg();
144}
145
146void DiagnosticInfo::anchor() {}
147void DiagnosticInfoStackSize::anchor() {}
148void DiagnosticInfoWithLocationBase::anchor() {}
149void DiagnosticInfoIROptimization::anchor() {}
150
151DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {
152 if (!DL)
153 return;
154 File = DL->getFile();
155 Line = DL->getLine();
156 Column = DL->getColumn();
157}
158
159DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {
160 if (!SP)
161 return;
162
163 File = SP->getFile();
164 Line = SP->getScopeLine();
165 Column = 0;
166}
167
168StringRef DiagnosticLocation::getRelativePath() const {
169 return File->getFilename();
170}
171
172std::string DiagnosticLocation::getAbsolutePath() const {
173 StringRef Name = File->getFilename();
174 if (sys::path::is_absolute(path: Name))
175 return std::string(Name);
176
177 SmallString<128> Path;
178 sys::path::append(path&: Path, a: File->getDirectory(), b: Name);
179 return sys::path::remove_leading_dotslash(path: Path).str();
180}
181
182std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const {
183 return Loc.getAbsolutePath();
184}
185
186void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath,
187 unsigned &Line,
188 unsigned &Column) const {
189 RelativePath = Loc.getRelativePath();
190 Line = Loc.getLine();
191 Column = Loc.getColumn();
192}
193
194std::string DiagnosticInfoWithLocationBase::getLocationStr() const {
195 StringRef Filename("<unknown>");
196 unsigned Line = 0;
197 unsigned Column = 0;
198 if (isLocationAvailable())
199 getLocation(RelativePath&: Filename, Line, Column);
200 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
201}
202
203DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
204 const Value *V)
205 : Key(std::string(Key)) {
206 if (auto *F = dyn_cast<Function>(Val: V)) {
207 if (DISubprogram *SP = F->getSubprogram())
208 Loc = SP;
209 }
210 else if (auto *I = dyn_cast<Instruction>(Val: V))
211 Loc = I->getDebugLoc();
212
213 // Only include names that correspond to user variables. FIXME: We should use
214 // debug info if available to get the name of the user variable.
215 if (isa<llvm::Argument>(Val: V) || isa<GlobalValue>(Val: V))
216 Val = std::string(GlobalValue::dropLLVMManglingEscape(Name: V->getName()));
217 else if (isa<Constant>(Val: V)) {
218 raw_string_ostream OS(Val);
219 V->printAsOperand(O&: OS, /*PrintType=*/false);
220 } else if (auto *II = dyn_cast<IntrinsicInst>(Val: V)) {
221 raw_string_ostream(Val) << "call " << II->getCalledFunction()->getName();
222 } else if (auto *I = dyn_cast<Instruction>(Val: V)) {
223 Val = I->getOpcodeName();
224 } else if (auto *MD = dyn_cast<MetadataAsValue>(Val: V)) {
225 if (auto *S = dyn_cast<MDString>(Val: MD->getMetadata()))
226 Val = S->getString();
227 }
228}
229
230DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)
231 : Key(std::string(Key)) {
232 raw_string_ostream(Val) << *T;
233}
234
235DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S)
236 : Key(std::string(Key)), Val(S.str()) {}
237
238DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
239 : Key(std::string(Key)), Val(itostr(X: N)) {}
240
241DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N)
242 : Key(std::string(Key)), Val(llvm::to_string(Value: N)) {}
243
244DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N)
245 : Key(std::string(Key)), Val(itostr(X: N)) {}
246
247DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N)
248 : Key(std::string(Key)), Val(itostr(X: N)) {}
249
250DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)
251 : Key(std::string(Key)), Val(utostr(X: N)) {}
252
253DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
254 unsigned long N)
255 : Key(std::string(Key)), Val(utostr(X: N)) {}
256
257DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
258 unsigned long long N)
259 : Key(std::string(Key)), Val(utostr(X: N)) {}
260
261DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
262 ElementCount EC)
263 : Key(std::string(Key)) {
264 raw_string_ostream OS(Val);
265 EC.print(OS);
266}
267
268DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
269 InstructionCost C)
270 : Key(std::string(Key)) {
271 raw_string_ostream OS(Val);
272 C.print(OS);
273}
274
275DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
276 BranchProbability P)
277 : Key(std::string(Key)) {
278 raw_string_ostream OS(Val);
279 P.print(OS);
280}
281
282DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)
283 : Key(std::string(Key)), Loc(Loc) {
284 if (Loc) {
285 Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" +
286 Twine(Loc.getCol())).str();
287 } else {
288 Val = "<UNKNOWN LOCATION>";
289 }
290}
291
292void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
293 DP << getLocationStr() << ": " << getMsg();
294 if (Hotness)
295 DP << " (hotness: " << *Hotness << ")";
296}
297
298OptimizationRemark::OptimizationRemark(const char *PassName,
299 StringRef RemarkName,
300 const DiagnosticLocation &Loc,
301 const BasicBlock *CodeRegion)
302 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
303 RemarkName, *CodeRegion->getParent(), Loc,
304 CodeRegion) {}
305
306OptimizationRemark::OptimizationRemark(const char *PassName,
307 StringRef RemarkName,
308 const Instruction *Inst)
309 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
310 RemarkName, *Inst->getParent()->getParent(),
311 Inst->getDebugLoc(), Inst->getParent()) {}
312
313static const BasicBlock *getFirstFunctionBlock(const Function *Func) {
314 return Func->empty() ? nullptr : &Func->front();
315}
316
317OptimizationRemark::OptimizationRemark(const char *PassName,
318 StringRef RemarkName,
319 const Function *Func)
320 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
321 RemarkName, *Func, Func->getSubprogram(),
322 getFirstFunctionBlock(Func)) {}
323
324bool OptimizationRemark::isEnabled() const {
325 const Function &Fn = getFunction();
326 LLVMContext &Ctx = Fn.getContext();
327 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(PassName: getPassName());
328}
329
330OptimizationRemarkMissed::OptimizationRemarkMissed(
331 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
332 const BasicBlock *CodeRegion)
333 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
334 PassName, RemarkName,
335 *CodeRegion->getParent(), Loc, CodeRegion) {}
336
337OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
338 StringRef RemarkName,
339 const Instruction *Inst)
340 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
341 PassName, RemarkName,
342 *Inst->getParent()->getParent(),
343 Inst->getDebugLoc(), Inst->getParent()) {}
344
345OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
346 StringRef RemarkName,
347 const Function *Func)
348 : DiagnosticInfoIROptimization(
349 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func,
350 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
351
352bool OptimizationRemarkMissed::isEnabled() const {
353 const Function &Fn = getFunction();
354 LLVMContext &Ctx = Fn.getContext();
355 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(PassName: getPassName());
356}
357
358OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
359 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
360 const BasicBlock *CodeRegion)
361 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
362 PassName, RemarkName,
363 *CodeRegion->getParent(), Loc, CodeRegion) {}
364
365OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
366 StringRef RemarkName,
367 const Instruction *Inst)
368 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
369 PassName, RemarkName,
370 *Inst->getParent()->getParent(),
371 Inst->getDebugLoc(), Inst->getParent()) {}
372
373OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
374 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
375 const DiagnosticLocation &Loc, const BasicBlock *CodeRegion)
376 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName,
377 *CodeRegion->getParent(), Loc, CodeRegion) {}
378
379OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
380 StringRef RemarkName,
381 const Function *Func)
382 : DiagnosticInfoIROptimization(
383 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func,
384 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
385
386bool OptimizationRemarkAnalysis::isEnabled() const {
387 const Function &Fn = getFunction();
388 LLVMContext &Ctx = Fn.getContext();
389 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(PassName: getPassName()) ||
390 shouldAlwaysPrint();
391}
392
393void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
394 DP << Diagnostic;
395}
396
397void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const {
398 DP << Diagnostic;
399}
400
401DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(
402 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
403 const BasicBlock *CodeRegion)
404 : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning, PassName,
405 RemarkName, *CodeRegion->getParent(), Loc,
406 CodeRegion) {}
407
408bool DiagnosticInfoOptimizationFailure::isEnabled() const {
409 // Only print warnings.
410 return getSeverity() == DS_Warning;
411}
412
413void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
414 std::string Str;
415 raw_string_ostream(Str) << getLocationStr() << ": in function "
416 << getFunction().getName() << ' '
417 << *getFunction().getFunctionType() << ": " << Msg
418 << '\n';
419 DP << Str;
420}
421
422DiagnosticInfoUnsupportedTargetIntrinsic::
423 DiagnosticInfoUnsupportedTargetIntrinsic(const Function &Fn,
424 unsigned IntrinsicID,
425 const DiagnosticLocation &Loc)
426 : DiagnosticInfoWithLocationBase(DK_UnsupportedTargetIntrinsic, DS_Error,
427 Fn, Loc),
428 IntrinsicID(IntrinsicID),
429 RequiredFeatures(Intrinsic::getRequiredTargetFeatures(
430 id: static_cast<Intrinsic::ID>(IntrinsicID))) {
431 assert(!RequiredFeatures.empty() &&
432 "intrinsic without required features should be supported");
433}
434
435std::string DiagnosticInfoUnsupportedTargetIntrinsic::getMessage() const {
436 return (Twine(
437 Intrinsic::getBaseName(id: static_cast<Intrinsic::ID>(IntrinsicID))) +
438 " requires target feature '" + RequiredFeatures + "'")
439 .str();
440}
441
442void DiagnosticInfoUnsupportedTargetIntrinsic::print(
443 DiagnosticPrinter &DP) const {
444 std::string Str;
445 raw_string_ostream OS(Str);
446 OS << getLocationStr() << ": in function ";
447 getFunction().printAsOperand(O&: OS, /*PrintType=*/false);
448 OS << ' ' << *getFunction().getFunctionType() << ": " << getMessage() << '\n';
449 DP << Str;
450}
451
452void DiagnosticInfoInstrumentation::print(DiagnosticPrinter &DP) const {
453 DP << Msg;
454}
455
456void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
457 DP << "Instruction selection used fallback path for " << getFunction();
458}
459
460void DiagnosticInfoOptimizationBase::insert(StringRef S) {
461 Args.emplace_back(Args&: S);
462}
463
464void DiagnosticInfoOptimizationBase::insert(Argument A) {
465 Args.push_back(Elt: std::move(A));
466}
467
468void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) {
469 IsVerbose = true;
470}
471
472void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) {
473 FirstExtraArgIndex = Args.size();
474}
475
476std::string DiagnosticInfoOptimizationBase::getMsg() const {
477 std::string Str;
478 raw_string_ostream OS(Str);
479 for (const DiagnosticInfoOptimizationBase::Argument &Arg :
480 make_range(x: Args.begin(), y: FirstExtraArgIndex == -1
481 ? Args.end()
482 : Args.begin() + FirstExtraArgIndex))
483 OS << Arg.Val;
484 return Str;
485}
486
487DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst,
488 const Twine &Msg)
489 : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning,
490 *Inst->getParent()->getParent(),
491 Inst->getDebugLoc()),
492 Msg(Msg) {}
493
494void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const {
495 DP << getLocationStr() << ": " << getMsg();
496}
497
498void OptimizationRemarkAnalysisFPCommute::anchor() {}
499void OptimizationRemarkAnalysisAliasing::anchor() {}
500
501void llvm::diagnoseDontCall(const CallInst &CI) {
502 const auto *F =
503 dyn_cast<Function>(Val: CI.getCalledOperand()->stripPointerCasts());
504
505 if (!F)
506 return;
507
508 for (int i = 0; i != 2; ++i) {
509 auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn";
510 auto Sev = i == 0 ? DS_Error : DS_Warning;
511
512 if (F->hasFnAttribute(Kind: AttrName)) {
513 uint64_t LocCookie = 0;
514 auto A = F->getFnAttribute(Kind: AttrName);
515 if (MDNode *MD = CI.getMetadata(Kind: "srcloc"))
516 LocCookie =
517 mdconst::extract<ConstantInt>(MD: MD->getOperand(I: 0))->getZExtValue();
518 MDNode *InlinedFromMD = CI.getMetadata(Kind: "inlined.from");
519 DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev,
520 LocCookie, InlinedFromMD);
521
522 if (const DebugLoc &DL = CI.getDebugLoc()) {
523 SmallVector<DebugInlineInfo, 4> DebugChain;
524 auto AddLocation = [&](const DILocation *Loc) {
525 if (auto *Scope = Loc->getScope())
526 if (auto *SP = Scope->getSubprogram())
527 DebugChain.push_back(Elt: {.FuncName: SP->getName(), .Filename: Loc->getFilename(),
528 .Line: Loc->getLine(), .Column: Loc->getColumn()});
529 };
530 if (const DILocation *Loc = DL.get()) {
531 AddLocation(Loc);
532 for (const DILocation *InlinedAt = Loc->getInlinedAt(); InlinedAt;
533 InlinedAt = InlinedAt->getInlinedAt())
534 AddLocation(InlinedAt);
535 }
536 D.setDebugInlineChain(std::move(DebugChain));
537 }
538
539 F->getContext().diagnose(DI: D);
540 }
541 }
542}
543
544void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const {
545 DP << "call to " << demangle(MangledName: getFunctionName()) << " marked \"dontcall-";
546 if (getSeverity() == DiagnosticSeverity::DS_Error)
547 DP << "error\"";
548 else
549 DP << "warn\"";
550 if (!getNote().empty())
551 DP << ": " << getNote();
552}
553
554SmallVector<std::pair<StringRef, uint64_t>>
555DiagnosticInfoDontCall::getInliningDecisions() const {
556 SmallVector<std::pair<StringRef, uint64_t>> Chain;
557 if (!InlinedFromMD)
558 return Chain;
559
560 for (unsigned I = 0, E = InlinedFromMD->getNumOperands(); I + 1 < E; I += 2) {
561 auto *NameMD = dyn_cast<MDString>(Val: InlinedFromMD->getOperand(I));
562 auto *LocMD =
563 mdconst::dyn_extract<ConstantInt>(MD: InlinedFromMD->getOperand(I: I + 1));
564 if (NameMD && !NameMD->getString().empty())
565 Chain.emplace_back(Args: NameMD->getString(),
566 Args: LocMD ? LocMD->getZExtValue() : 0);
567 }
568 return Chain;
569}
570