File: | llvm/lib/IR/Verifier.cpp |
Warning: | line 2588, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- Verifier.cpp - Implement the Module Verifier -----------------------==// | ||||
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 function verifier interface, that can be used for some | ||||
10 | // sanity checking of input to the system. | ||||
11 | // | ||||
12 | // Note that this does not provide full `Java style' security and verifications, | ||||
13 | // instead it just tries to ensure that code is well-formed. | ||||
14 | // | ||||
15 | // * Both of a binary operator's parameters are of the same type | ||||
16 | // * Verify that the indices of mem access instructions match other operands | ||||
17 | // * Verify that arithmetic and other things are only performed on first-class | ||||
18 | // types. Verify that shifts & logicals only happen on integrals f.e. | ||||
19 | // * All of the constants in a switch statement are of the correct type | ||||
20 | // * The code is in valid SSA form | ||||
21 | // * It should be illegal to put a label into any other type (like a structure) | ||||
22 | // or to return one. [except constant arrays!] | ||||
23 | // * Only phi nodes can be self referential: 'add i32 %0, %0 ; <int>:0' is bad | ||||
24 | // * PHI nodes must have an entry for each predecessor, with no extras. | ||||
25 | // * PHI nodes must be the first thing in a basic block, all grouped together | ||||
26 | // * PHI nodes must have at least one entry | ||||
27 | // * All basic blocks should only end with terminator insts, not contain them | ||||
28 | // * The entry node to a function must not have predecessors | ||||
29 | // * All Instructions must be embedded into a basic block | ||||
30 | // * Functions cannot take a void-typed parameter | ||||
31 | // * Verify that a function's argument list agrees with it's declared type. | ||||
32 | // * It is illegal to specify a name for a void value. | ||||
33 | // * It is illegal to have a internal global value with no initializer | ||||
34 | // * It is illegal to have a ret instruction that returns a value that does not | ||||
35 | // agree with the function return value type. | ||||
36 | // * Function call argument types match the function prototype | ||||
37 | // * A landing pad is defined by a landingpad instruction, and can be jumped to | ||||
38 | // only by the unwind edge of an invoke instruction. | ||||
39 | // * A landingpad instruction must be the first non-PHI instruction in the | ||||
40 | // block. | ||||
41 | // * Landingpad instructions must be in a function with a personality function. | ||||
42 | // * All other things that are tested by asserts spread about the code... | ||||
43 | // | ||||
44 | //===----------------------------------------------------------------------===// | ||||
45 | |||||
46 | #include "llvm/IR/Verifier.h" | ||||
47 | #include "llvm/ADT/APFloat.h" | ||||
48 | #include "llvm/ADT/APInt.h" | ||||
49 | #include "llvm/ADT/ArrayRef.h" | ||||
50 | #include "llvm/ADT/DenseMap.h" | ||||
51 | #include "llvm/ADT/MapVector.h" | ||||
52 | #include "llvm/ADT/Optional.h" | ||||
53 | #include "llvm/ADT/STLExtras.h" | ||||
54 | #include "llvm/ADT/SmallPtrSet.h" | ||||
55 | #include "llvm/ADT/SmallSet.h" | ||||
56 | #include "llvm/ADT/SmallVector.h" | ||||
57 | #include "llvm/ADT/StringExtras.h" | ||||
58 | #include "llvm/ADT/StringMap.h" | ||||
59 | #include "llvm/ADT/StringRef.h" | ||||
60 | #include "llvm/ADT/Twine.h" | ||||
61 | #include "llvm/ADT/ilist.h" | ||||
62 | #include "llvm/BinaryFormat/Dwarf.h" | ||||
63 | #include "llvm/IR/Argument.h" | ||||
64 | #include "llvm/IR/Attributes.h" | ||||
65 | #include "llvm/IR/BasicBlock.h" | ||||
66 | #include "llvm/IR/CFG.h" | ||||
67 | #include "llvm/IR/CallingConv.h" | ||||
68 | #include "llvm/IR/Comdat.h" | ||||
69 | #include "llvm/IR/Constant.h" | ||||
70 | #include "llvm/IR/ConstantRange.h" | ||||
71 | #include "llvm/IR/Constants.h" | ||||
72 | #include "llvm/IR/DataLayout.h" | ||||
73 | #include "llvm/IR/DebugInfo.h" | ||||
74 | #include "llvm/IR/DebugInfoMetadata.h" | ||||
75 | #include "llvm/IR/DebugLoc.h" | ||||
76 | #include "llvm/IR/DerivedTypes.h" | ||||
77 | #include "llvm/IR/Dominators.h" | ||||
78 | #include "llvm/IR/Function.h" | ||||
79 | #include "llvm/IR/GlobalAlias.h" | ||||
80 | #include "llvm/IR/GlobalValue.h" | ||||
81 | #include "llvm/IR/GlobalVariable.h" | ||||
82 | #include "llvm/IR/InlineAsm.h" | ||||
83 | #include "llvm/IR/InstVisitor.h" | ||||
84 | #include "llvm/IR/InstrTypes.h" | ||||
85 | #include "llvm/IR/Instruction.h" | ||||
86 | #include "llvm/IR/Instructions.h" | ||||
87 | #include "llvm/IR/IntrinsicInst.h" | ||||
88 | #include "llvm/IR/Intrinsics.h" | ||||
89 | #include "llvm/IR/IntrinsicsWebAssembly.h" | ||||
90 | #include "llvm/IR/LLVMContext.h" | ||||
91 | #include "llvm/IR/Metadata.h" | ||||
92 | #include "llvm/IR/Module.h" | ||||
93 | #include "llvm/IR/ModuleSlotTracker.h" | ||||
94 | #include "llvm/IR/PassManager.h" | ||||
95 | #include "llvm/IR/Statepoint.h" | ||||
96 | #include "llvm/IR/Type.h" | ||||
97 | #include "llvm/IR/Use.h" | ||||
98 | #include "llvm/IR/User.h" | ||||
99 | #include "llvm/IR/Value.h" | ||||
100 | #include "llvm/InitializePasses.h" | ||||
101 | #include "llvm/Pass.h" | ||||
102 | #include "llvm/Support/AtomicOrdering.h" | ||||
103 | #include "llvm/Support/Casting.h" | ||||
104 | #include "llvm/Support/CommandLine.h" | ||||
105 | #include "llvm/Support/Debug.h" | ||||
106 | #include "llvm/Support/ErrorHandling.h" | ||||
107 | #include "llvm/Support/MathExtras.h" | ||||
108 | #include "llvm/Support/raw_ostream.h" | ||||
109 | #include <algorithm> | ||||
110 | #include <cassert> | ||||
111 | #include <cstdint> | ||||
112 | #include <memory> | ||||
113 | #include <string> | ||||
114 | #include <utility> | ||||
115 | |||||
116 | using namespace llvm; | ||||
117 | |||||
118 | static cl::opt<bool> VerifyNoAliasScopeDomination( | ||||
119 | "verify-noalias-scope-decl-dom", cl::Hidden, cl::init(false), | ||||
120 | cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical " | ||||
121 | "scopes are not dominating")); | ||||
122 | |||||
123 | namespace llvm { | ||||
124 | |||||
125 | struct VerifierSupport { | ||||
126 | raw_ostream *OS; | ||||
127 | const Module &M; | ||||
128 | ModuleSlotTracker MST; | ||||
129 | Triple TT; | ||||
130 | const DataLayout &DL; | ||||
131 | LLVMContext &Context; | ||||
132 | |||||
133 | /// Track the brokenness of the module while recursively visiting. | ||||
134 | bool Broken = false; | ||||
135 | /// Broken debug info can be "recovered" from by stripping the debug info. | ||||
136 | bool BrokenDebugInfo = false; | ||||
137 | /// Whether to treat broken debug info as an error. | ||||
138 | bool TreatBrokenDebugInfoAsError = true; | ||||
139 | |||||
140 | explicit VerifierSupport(raw_ostream *OS, const Module &M) | ||||
141 | : OS(OS), M(M), MST(&M), TT(M.getTargetTriple()), DL(M.getDataLayout()), | ||||
142 | Context(M.getContext()) {} | ||||
143 | |||||
144 | private: | ||||
145 | void Write(const Module *M) { | ||||
146 | *OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; | ||||
147 | } | ||||
148 | |||||
149 | void Write(const Value *V) { | ||||
150 | if (V) | ||||
151 | Write(*V); | ||||
152 | } | ||||
153 | |||||
154 | void Write(const Value &V) { | ||||
155 | if (isa<Instruction>(V)) { | ||||
156 | V.print(*OS, MST); | ||||
157 | *OS << '\n'; | ||||
158 | } else { | ||||
159 | V.printAsOperand(*OS, true, MST); | ||||
160 | *OS << '\n'; | ||||
161 | } | ||||
162 | } | ||||
163 | |||||
164 | void Write(const Metadata *MD) { | ||||
165 | if (!MD) | ||||
166 | return; | ||||
167 | MD->print(*OS, MST, &M); | ||||
168 | *OS << '\n'; | ||||
169 | } | ||||
170 | |||||
171 | template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) { | ||||
172 | Write(MD.get()); | ||||
173 | } | ||||
174 | |||||
175 | void Write(const NamedMDNode *NMD) { | ||||
176 | if (!NMD) | ||||
177 | return; | ||||
178 | NMD->print(*OS, MST); | ||||
179 | *OS << '\n'; | ||||
180 | } | ||||
181 | |||||
182 | void Write(Type *T) { | ||||
183 | if (!T) | ||||
184 | return; | ||||
185 | *OS << ' ' << *T; | ||||
186 | } | ||||
187 | |||||
188 | void Write(const Comdat *C) { | ||||
189 | if (!C) | ||||
190 | return; | ||||
191 | *OS << *C; | ||||
192 | } | ||||
193 | |||||
194 | void Write(const APInt *AI) { | ||||
195 | if (!AI) | ||||
196 | return; | ||||
197 | *OS << *AI << '\n'; | ||||
198 | } | ||||
199 | |||||
200 | void Write(const unsigned i) { *OS << i << '\n'; } | ||||
201 | |||||
202 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
203 | void Write(const Attribute *A) { | ||||
204 | if (!A) | ||||
205 | return; | ||||
206 | *OS << A->getAsString() << '\n'; | ||||
207 | } | ||||
208 | |||||
209 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
210 | void Write(const AttributeSet *AS) { | ||||
211 | if (!AS) | ||||
212 | return; | ||||
213 | *OS << AS->getAsString() << '\n'; | ||||
214 | } | ||||
215 | |||||
216 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
217 | void Write(const AttributeList *AL) { | ||||
218 | if (!AL) | ||||
219 | return; | ||||
220 | AL->print(*OS); | ||||
221 | } | ||||
222 | |||||
223 | template <typename T> void Write(ArrayRef<T> Vs) { | ||||
224 | for (const T &V : Vs) | ||||
225 | Write(V); | ||||
226 | } | ||||
227 | |||||
228 | template <typename T1, typename... Ts> | ||||
229 | void WriteTs(const T1 &V1, const Ts &... Vs) { | ||||
230 | Write(V1); | ||||
231 | WriteTs(Vs...); | ||||
232 | } | ||||
233 | |||||
234 | template <typename... Ts> void WriteTs() {} | ||||
235 | |||||
236 | public: | ||||
237 | /// A check failed, so printout out the condition and the message. | ||||
238 | /// | ||||
239 | /// This provides a nice place to put a breakpoint if you want to see why | ||||
240 | /// something is not correct. | ||||
241 | void CheckFailed(const Twine &Message) { | ||||
242 | if (OS) | ||||
243 | *OS << Message << '\n'; | ||||
244 | Broken = true; | ||||
245 | } | ||||
246 | |||||
247 | /// A check failed (with values to print). | ||||
248 | /// | ||||
249 | /// This calls the Message-only version so that the above is easier to set a | ||||
250 | /// breakpoint on. | ||||
251 | template <typename T1, typename... Ts> | ||||
252 | void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { | ||||
253 | CheckFailed(Message); | ||||
254 | if (OS) | ||||
255 | WriteTs(V1, Vs...); | ||||
256 | } | ||||
257 | |||||
258 | /// A debug info check failed. | ||||
259 | void DebugInfoCheckFailed(const Twine &Message) { | ||||
260 | if (OS) | ||||
261 | *OS << Message << '\n'; | ||||
262 | Broken |= TreatBrokenDebugInfoAsError; | ||||
263 | BrokenDebugInfo = true; | ||||
264 | } | ||||
265 | |||||
266 | /// A debug info check failed (with values to print). | ||||
267 | template <typename T1, typename... Ts> | ||||
268 | void DebugInfoCheckFailed(const Twine &Message, const T1 &V1, | ||||
269 | const Ts &... Vs) { | ||||
270 | DebugInfoCheckFailed(Message); | ||||
271 | if (OS) | ||||
272 | WriteTs(V1, Vs...); | ||||
273 | } | ||||
274 | }; | ||||
275 | |||||
276 | } // namespace llvm | ||||
277 | |||||
278 | namespace { | ||||
279 | |||||
280 | class Verifier : public InstVisitor<Verifier>, VerifierSupport { | ||||
281 | friend class InstVisitor<Verifier>; | ||||
282 | |||||
283 | DominatorTree DT; | ||||
284 | |||||
285 | /// When verifying a basic block, keep track of all of the | ||||
286 | /// instructions we have seen so far. | ||||
287 | /// | ||||
288 | /// This allows us to do efficient dominance checks for the case when an | ||||
289 | /// instruction has an operand that is an instruction in the same block. | ||||
290 | SmallPtrSet<Instruction *, 16> InstsInThisBlock; | ||||
291 | |||||
292 | /// Keep track of the metadata nodes that have been checked already. | ||||
293 | SmallPtrSet<const Metadata *, 32> MDNodes; | ||||
294 | |||||
295 | /// Keep track which DISubprogram is attached to which function. | ||||
296 | DenseMap<const DISubprogram *, const Function *> DISubprogramAttachments; | ||||
297 | |||||
298 | /// Track all DICompileUnits visited. | ||||
299 | SmallPtrSet<const Metadata *, 2> CUVisited; | ||||
300 | |||||
301 | /// The result type for a landingpad. | ||||
302 | Type *LandingPadResultTy; | ||||
303 | |||||
304 | /// Whether we've seen a call to @llvm.localescape in this function | ||||
305 | /// already. | ||||
306 | bool SawFrameEscape; | ||||
307 | |||||
308 | /// Whether the current function has a DISubprogram attached to it. | ||||
309 | bool HasDebugInfo = false; | ||||
310 | |||||
311 | /// The current source language. | ||||
312 | dwarf::SourceLanguage CurrentSourceLang = dwarf::DW_LANG_lo_user; | ||||
313 | |||||
314 | /// Whether source was present on the first DIFile encountered in each CU. | ||||
315 | DenseMap<const DICompileUnit *, bool> HasSourceDebugInfo; | ||||
316 | |||||
317 | /// Stores the count of how many objects were passed to llvm.localescape for a | ||||
318 | /// given function and the largest index passed to llvm.localrecover. | ||||
319 | DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo; | ||||
320 | |||||
321 | // Maps catchswitches and cleanuppads that unwind to siblings to the | ||||
322 | // terminators that indicate the unwind, used to detect cycles therein. | ||||
323 | MapVector<Instruction *, Instruction *> SiblingFuncletInfo; | ||||
324 | |||||
325 | /// Cache of constants visited in search of ConstantExprs. | ||||
326 | SmallPtrSet<const Constant *, 32> ConstantExprVisited; | ||||
327 | |||||
328 | /// Cache of declarations of the llvm.experimental.deoptimize.<ty> intrinsic. | ||||
329 | SmallVector<const Function *, 4> DeoptimizeDeclarations; | ||||
330 | |||||
331 | /// Cache of attribute lists verified. | ||||
332 | SmallPtrSet<const void *, 32> AttributeListsVisited; | ||||
333 | |||||
334 | // Verify that this GlobalValue is only used in this module. | ||||
335 | // This map is used to avoid visiting uses twice. We can arrive at a user | ||||
336 | // twice, if they have multiple operands. In particular for very large | ||||
337 | // constant expressions, we can arrive at a particular user many times. | ||||
338 | SmallPtrSet<const Value *, 32> GlobalValueVisited; | ||||
339 | |||||
340 | // Keeps track of duplicate function argument debug info. | ||||
341 | SmallVector<const DILocalVariable *, 16> DebugFnArgs; | ||||
342 | |||||
343 | TBAAVerifier TBAAVerifyHelper; | ||||
344 | |||||
345 | SmallVector<IntrinsicInst *, 4> NoAliasScopeDecls; | ||||
346 | |||||
347 | void checkAtomicMemAccessSize(Type *Ty, const Instruction *I); | ||||
348 | |||||
349 | public: | ||||
350 | explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError, | ||||
351 | const Module &M) | ||||
352 | : VerifierSupport(OS, M), LandingPadResultTy(nullptr), | ||||
353 | SawFrameEscape(false), TBAAVerifyHelper(this) { | ||||
354 | TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError; | ||||
355 | } | ||||
356 | |||||
357 | bool hasBrokenDebugInfo() const { return BrokenDebugInfo; } | ||||
358 | |||||
359 | bool verify(const Function &F) { | ||||
360 | assert(F.getParent() == &M &&(static_cast <bool> (F.getParent() == &M && "An instance of this class only works with a specific module!" ) ? void (0) : __assert_fail ("F.getParent() == &M && \"An instance of this class only works with a specific module!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 361, __extension__ __PRETTY_FUNCTION__)) | ||||
361 | "An instance of this class only works with a specific module!")(static_cast <bool> (F.getParent() == &M && "An instance of this class only works with a specific module!" ) ? void (0) : __assert_fail ("F.getParent() == &M && \"An instance of this class only works with a specific module!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 361, __extension__ __PRETTY_FUNCTION__)); | ||||
362 | |||||
363 | // First ensure the function is well-enough formed to compute dominance | ||||
364 | // information, and directly compute a dominance tree. We don't rely on the | ||||
365 | // pass manager to provide this as it isolates us from a potentially | ||||
366 | // out-of-date dominator tree and makes it significantly more complex to run | ||||
367 | // this code outside of a pass manager. | ||||
368 | // FIXME: It's really gross that we have to cast away constness here. | ||||
369 | if (!F.empty()) | ||||
370 | DT.recalculate(const_cast<Function &>(F)); | ||||
371 | |||||
372 | for (const BasicBlock &BB : F) { | ||||
373 | if (!BB.empty() && BB.back().isTerminator()) | ||||
374 | continue; | ||||
375 | |||||
376 | if (OS) { | ||||
377 | *OS << "Basic Block in function '" << F.getName() | ||||
378 | << "' does not have terminator!\n"; | ||||
379 | BB.printAsOperand(*OS, true, MST); | ||||
380 | *OS << "\n"; | ||||
381 | } | ||||
382 | return false; | ||||
383 | } | ||||
384 | |||||
385 | Broken = false; | ||||
386 | // FIXME: We strip const here because the inst visitor strips const. | ||||
387 | visit(const_cast<Function &>(F)); | ||||
388 | verifySiblingFuncletUnwinds(); | ||||
389 | InstsInThisBlock.clear(); | ||||
390 | DebugFnArgs.clear(); | ||||
391 | LandingPadResultTy = nullptr; | ||||
392 | SawFrameEscape = false; | ||||
393 | SiblingFuncletInfo.clear(); | ||||
394 | verifyNoAliasScopeDecl(); | ||||
395 | NoAliasScopeDecls.clear(); | ||||
396 | |||||
397 | return !Broken; | ||||
398 | } | ||||
399 | |||||
400 | /// Verify the module that this instance of \c Verifier was initialized with. | ||||
401 | bool verify() { | ||||
402 | Broken = false; | ||||
403 | |||||
404 | // Collect all declarations of the llvm.experimental.deoptimize intrinsic. | ||||
405 | for (const Function &F : M) | ||||
406 | if (F.getIntrinsicID() == Intrinsic::experimental_deoptimize) | ||||
407 | DeoptimizeDeclarations.push_back(&F); | ||||
408 | |||||
409 | // Now that we've visited every function, verify that we never asked to | ||||
410 | // recover a frame index that wasn't escaped. | ||||
411 | verifyFrameRecoverIndices(); | ||||
412 | for (const GlobalVariable &GV : M.globals()) | ||||
413 | visitGlobalVariable(GV); | ||||
414 | |||||
415 | for (const GlobalAlias &GA : M.aliases()) | ||||
416 | visitGlobalAlias(GA); | ||||
417 | |||||
418 | for (const NamedMDNode &NMD : M.named_metadata()) | ||||
419 | visitNamedMDNode(NMD); | ||||
420 | |||||
421 | for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) | ||||
422 | visitComdat(SMEC.getValue()); | ||||
423 | |||||
424 | visitModuleFlags(M); | ||||
425 | visitModuleIdents(M); | ||||
426 | visitModuleCommandLines(M); | ||||
427 | |||||
428 | verifyCompileUnits(); | ||||
429 | |||||
430 | verifyDeoptimizeCallingConvs(); | ||||
431 | DISubprogramAttachments.clear(); | ||||
432 | return !Broken; | ||||
433 | } | ||||
434 | |||||
435 | private: | ||||
436 | /// Whether a metadata node is allowed to be, or contain, a DILocation. | ||||
437 | enum class AreDebugLocsAllowed { No, Yes }; | ||||
438 | |||||
439 | // Verification methods... | ||||
440 | void visitGlobalValue(const GlobalValue &GV); | ||||
441 | void visitGlobalVariable(const GlobalVariable &GV); | ||||
442 | void visitGlobalAlias(const GlobalAlias &GA); | ||||
443 | void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); | ||||
444 | void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited, | ||||
445 | const GlobalAlias &A, const Constant &C); | ||||
446 | void visitNamedMDNode(const NamedMDNode &NMD); | ||||
447 | void visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs); | ||||
448 | void visitMetadataAsValue(const MetadataAsValue &MD, Function *F); | ||||
449 | void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); | ||||
450 | void visitComdat(const Comdat &C); | ||||
451 | void visitModuleIdents(const Module &M); | ||||
452 | void visitModuleCommandLines(const Module &M); | ||||
453 | void visitModuleFlags(const Module &M); | ||||
454 | void visitModuleFlag(const MDNode *Op, | ||||
455 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
456 | SmallVectorImpl<const MDNode *> &Requirements); | ||||
457 | void visitModuleFlagCGProfileEntry(const MDOperand &MDO); | ||||
458 | void visitFunction(const Function &F); | ||||
459 | void visitBasicBlock(BasicBlock &BB); | ||||
460 | void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); | ||||
461 | void visitDereferenceableMetadata(Instruction &I, MDNode *MD); | ||||
462 | void visitProfMetadata(Instruction &I, MDNode *MD); | ||||
463 | void visitAnnotationMetadata(MDNode *Annotation); | ||||
464 | |||||
465 | template <class Ty> bool isValidMetadataArray(const MDTuple &N); | ||||
466 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); | ||||
467 | #include "llvm/IR/Metadata.def" | ||||
468 | void visitDIScope(const DIScope &N); | ||||
469 | void visitDIVariable(const DIVariable &N); | ||||
470 | void visitDILexicalBlockBase(const DILexicalBlockBase &N); | ||||
471 | void visitDITemplateParameter(const DITemplateParameter &N); | ||||
472 | |||||
473 | void visitTemplateParams(const MDNode &N, const Metadata &RawParams); | ||||
474 | |||||
475 | // InstVisitor overrides... | ||||
476 | using InstVisitor<Verifier>::visit; | ||||
477 | void visit(Instruction &I); | ||||
478 | |||||
479 | void visitTruncInst(TruncInst &I); | ||||
480 | void visitZExtInst(ZExtInst &I); | ||||
481 | void visitSExtInst(SExtInst &I); | ||||
482 | void visitFPTruncInst(FPTruncInst &I); | ||||
483 | void visitFPExtInst(FPExtInst &I); | ||||
484 | void visitFPToUIInst(FPToUIInst &I); | ||||
485 | void visitFPToSIInst(FPToSIInst &I); | ||||
486 | void visitUIToFPInst(UIToFPInst &I); | ||||
487 | void visitSIToFPInst(SIToFPInst &I); | ||||
488 | void visitIntToPtrInst(IntToPtrInst &I); | ||||
489 | void visitPtrToIntInst(PtrToIntInst &I); | ||||
490 | void visitBitCastInst(BitCastInst &I); | ||||
491 | void visitAddrSpaceCastInst(AddrSpaceCastInst &I); | ||||
492 | void visitPHINode(PHINode &PN); | ||||
493 | void visitCallBase(CallBase &Call); | ||||
494 | void visitUnaryOperator(UnaryOperator &U); | ||||
495 | void visitBinaryOperator(BinaryOperator &B); | ||||
496 | void visitICmpInst(ICmpInst &IC); | ||||
497 | void visitFCmpInst(FCmpInst &FC); | ||||
498 | void visitExtractElementInst(ExtractElementInst &EI); | ||||
499 | void visitInsertElementInst(InsertElementInst &EI); | ||||
500 | void visitShuffleVectorInst(ShuffleVectorInst &EI); | ||||
501 | void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); } | ||||
502 | void visitCallInst(CallInst &CI); | ||||
503 | void visitInvokeInst(InvokeInst &II); | ||||
504 | void visitGetElementPtrInst(GetElementPtrInst &GEP); | ||||
505 | void visitLoadInst(LoadInst &LI); | ||||
506 | void visitStoreInst(StoreInst &SI); | ||||
507 | void verifyDominatesUse(Instruction &I, unsigned i); | ||||
508 | void visitInstruction(Instruction &I); | ||||
509 | void visitTerminator(Instruction &I); | ||||
510 | void visitBranchInst(BranchInst &BI); | ||||
511 | void visitReturnInst(ReturnInst &RI); | ||||
512 | void visitSwitchInst(SwitchInst &SI); | ||||
513 | void visitIndirectBrInst(IndirectBrInst &BI); | ||||
514 | void visitCallBrInst(CallBrInst &CBI); | ||||
515 | void visitSelectInst(SelectInst &SI); | ||||
516 | void visitUserOp1(Instruction &I); | ||||
517 | void visitUserOp2(Instruction &I) { visitUserOp1(I); } | ||||
518 | void visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call); | ||||
519 | void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); | ||||
520 | void visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII); | ||||
521 | void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI); | ||||
522 | void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); | ||||
523 | void visitAtomicRMWInst(AtomicRMWInst &RMWI); | ||||
524 | void visitFenceInst(FenceInst &FI); | ||||
525 | void visitAllocaInst(AllocaInst &AI); | ||||
526 | void visitExtractValueInst(ExtractValueInst &EVI); | ||||
527 | void visitInsertValueInst(InsertValueInst &IVI); | ||||
528 | void visitEHPadPredecessors(Instruction &I); | ||||
529 | void visitLandingPadInst(LandingPadInst &LPI); | ||||
530 | void visitResumeInst(ResumeInst &RI); | ||||
531 | void visitCatchPadInst(CatchPadInst &CPI); | ||||
532 | void visitCatchReturnInst(CatchReturnInst &CatchReturn); | ||||
533 | void visitCleanupPadInst(CleanupPadInst &CPI); | ||||
534 | void visitFuncletPadInst(FuncletPadInst &FPI); | ||||
535 | void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch); | ||||
536 | void visitCleanupReturnInst(CleanupReturnInst &CRI); | ||||
537 | |||||
538 | void verifySwiftErrorCall(CallBase &Call, const Value *SwiftErrorVal); | ||||
539 | void verifySwiftErrorValue(const Value *SwiftErrorVal); | ||||
540 | void verifyTailCCMustTailAttrs(AttrBuilder Attrs, StringRef Context); | ||||
541 | void verifyMustTailCall(CallInst &CI); | ||||
542 | bool verifyAttributeCount(AttributeList Attrs, unsigned Params); | ||||
543 | void verifyAttributeTypes(AttributeSet Attrs, const Value *V); | ||||
544 | void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V); | ||||
545 | void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
546 | const Value *V); | ||||
547 | void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
548 | const Value *V, bool IsIntrinsic); | ||||
549 | void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs); | ||||
550 | |||||
551 | void visitConstantExprsRecursively(const Constant *EntryC); | ||||
552 | void visitConstantExpr(const ConstantExpr *CE); | ||||
553 | void verifyStatepoint(const CallBase &Call); | ||||
554 | void verifyFrameRecoverIndices(); | ||||
555 | void verifySiblingFuncletUnwinds(); | ||||
556 | |||||
557 | void verifyFragmentExpression(const DbgVariableIntrinsic &I); | ||||
558 | template <typename ValueOrMetadata> | ||||
559 | void verifyFragmentExpression(const DIVariable &V, | ||||
560 | DIExpression::FragmentInfo Fragment, | ||||
561 | ValueOrMetadata *Desc); | ||||
562 | void verifyFnArgs(const DbgVariableIntrinsic &I); | ||||
563 | void verifyNotEntryValue(const DbgVariableIntrinsic &I); | ||||
564 | |||||
565 | /// Module-level debug info verification... | ||||
566 | void verifyCompileUnits(); | ||||
567 | |||||
568 | /// Module-level verification that all @llvm.experimental.deoptimize | ||||
569 | /// declarations share the same calling convention. | ||||
570 | void verifyDeoptimizeCallingConvs(); | ||||
571 | |||||
572 | /// Verify all-or-nothing property of DIFile source attribute within a CU. | ||||
573 | void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F); | ||||
574 | |||||
575 | /// Verify the llvm.experimental.noalias.scope.decl declarations | ||||
576 | void verifyNoAliasScopeDecl(); | ||||
577 | }; | ||||
578 | |||||
579 | } // end anonymous namespace | ||||
580 | |||||
581 | /// We know that cond should be true, if not print an error message. | ||||
582 | #define Assert(C, ...)do { if (!(C)) { CheckFailed(...); return; } } while (false) \ | ||||
583 | do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (false) | ||||
584 | |||||
585 | /// We know that a debug info condition should be true, if not print | ||||
586 | /// an error message. | ||||
587 | #define AssertDI(C, ...)do { if (!(C)) { DebugInfoCheckFailed(...); return; } } while (false) \ | ||||
588 | do { if (!(C)) { DebugInfoCheckFailed(__VA_ARGS__); return; } } while (false) | ||||
589 | |||||
590 | void Verifier::visit(Instruction &I) { | ||||
591 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) | ||||
592 | Assert(I.getOperand(i) != nullptr, "Operand is null", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Operand is null" , &I); return; } } while (false); | ||||
593 | InstVisitor<Verifier>::visit(I); | ||||
594 | } | ||||
595 | |||||
596 | // Helper to recursively iterate over indirect users. By | ||||
597 | // returning false, the callback can ask to stop recursing | ||||
598 | // further. | ||||
599 | static void forEachUser(const Value *User, | ||||
600 | SmallPtrSet<const Value *, 32> &Visited, | ||||
601 | llvm::function_ref<bool(const Value *)> Callback) { | ||||
602 | if (!Visited.insert(User).second) | ||||
603 | return; | ||||
604 | for (const Value *TheNextUser : User->materialized_users()) | ||||
605 | if (Callback(TheNextUser)) | ||||
606 | forEachUser(TheNextUser, Visited, Callback); | ||||
607 | } | ||||
608 | |||||
609 | void Verifier::visitGlobalValue(const GlobalValue &GV) { | ||||
610 | Assert(!GV.isDeclaration() || GV.hasValidDeclarationLinkage(),do { if (!(!GV.isDeclaration() || GV.hasValidDeclarationLinkage ())) { CheckFailed("Global is external, but doesn't have external or weak linkage!" , &GV); return; } } while (false) | ||||
611 | "Global is external, but doesn't have external or weak linkage!", &GV)do { if (!(!GV.isDeclaration() || GV.hasValidDeclarationLinkage ())) { CheckFailed("Global is external, but doesn't have external or weak linkage!" , &GV); return; } } while (false); | ||||
612 | |||||
613 | if (const GlobalObject *GO = dyn_cast<GlobalObject>(&GV)) | ||||
614 | Assert(GO->getAlignment() <= Value::MaximumAlignment,do { if (!(GO->getAlignment() <= Value::MaximumAlignment )) { CheckFailed("huge alignment values are unsupported", GO) ; return; } } while (false) | ||||
615 | "huge alignment values are unsupported", GO)do { if (!(GO->getAlignment() <= Value::MaximumAlignment )) { CheckFailed("huge alignment values are unsupported", GO) ; return; } } while (false); | ||||
616 | Assert(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),do { if (!(!GV.hasAppendingLinkage() || isa<GlobalVariable >(GV))) { CheckFailed("Only global variables can have appending linkage!" , &GV); return; } } while (false) | ||||
617 | "Only global variables can have appending linkage!", &GV)do { if (!(!GV.hasAppendingLinkage() || isa<GlobalVariable >(GV))) { CheckFailed("Only global variables can have appending linkage!" , &GV); return; } } while (false); | ||||
618 | |||||
619 | if (GV.hasAppendingLinkage()) { | ||||
620 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV); | ||||
621 | Assert(GVar && GVar->getValueType()->isArrayTy(),do { if (!(GVar && GVar->getValueType()->isArrayTy ())) { CheckFailed("Only global arrays can have appending linkage!" , GVar); return; } } while (false) | ||||
622 | "Only global arrays can have appending linkage!", GVar)do { if (!(GVar && GVar->getValueType()->isArrayTy ())) { CheckFailed("Only global arrays can have appending linkage!" , GVar); return; } } while (false); | ||||
623 | } | ||||
624 | |||||
625 | if (GV.isDeclarationForLinker()) | ||||
626 | Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV)do { if (!(!GV.hasComdat())) { CheckFailed("Declaration may not be in a Comdat!" , &GV); return; } } while (false); | ||||
627 | |||||
628 | if (GV.hasDLLImportStorageClass()) { | ||||
629 | Assert(!GV.isDSOLocal(),do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false) | ||||
630 | "GlobalValue with DLLImport Storage is dso_local!", &GV)do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false); | ||||
631 | |||||
632 | Assert((GV.isDeclaration() &&do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
633 | (GV.hasExternalLinkage() || GV.hasExternalWeakLinkage())) ||do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
634 | GV.hasAvailableExternallyLinkage(),do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
635 | "Global is marked as dllimport, but not external", &GV)do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false); | ||||
636 | } | ||||
637 | |||||
638 | if (GV.isImplicitDSOLocal()) | ||||
639 | Assert(GV.isDSOLocal(),do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
640 | "GlobalValue with local linkage or non-default "do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
641 | "visibility must be dso_local!",do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
642 | &GV)do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false); | ||||
643 | |||||
644 | forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool { | ||||
645 | if (const Instruction *I = dyn_cast<Instruction>(V)) { | ||||
646 | if (!I->getParent() || !I->getParent()->getParent()) | ||||
647 | CheckFailed("Global is referenced by parentless instruction!", &GV, &M, | ||||
648 | I); | ||||
649 | else if (I->getParent()->getParent()->getParent() != &M) | ||||
650 | CheckFailed("Global is referenced in a different module!", &GV, &M, I, | ||||
651 | I->getParent()->getParent(), | ||||
652 | I->getParent()->getParent()->getParent()); | ||||
653 | return false; | ||||
654 | } else if (const Function *F = dyn_cast<Function>(V)) { | ||||
655 | if (F->getParent() != &M) | ||||
656 | CheckFailed("Global is used by function in a different module", &GV, &M, | ||||
657 | F, F->getParent()); | ||||
658 | return false; | ||||
659 | } | ||||
660 | return true; | ||||
661 | }); | ||||
662 | } | ||||
663 | |||||
664 | void Verifier::visitGlobalVariable(const GlobalVariable &GV) { | ||||
665 | if (GV.hasInitializer()) { | ||||
666 | Assert(GV.getInitializer()->getType() == GV.getValueType(),do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
667 | "Global variable initializer type does not match global "do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
668 | "variable type!",do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
669 | &GV)do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false); | ||||
670 | // If the global has common linkage, it must have a zero initializer and | ||||
671 | // cannot be constant. | ||||
672 | if (GV.hasCommonLinkage()) { | ||||
673 | Assert(GV.getInitializer()->isNullValue(),do { if (!(GV.getInitializer()->isNullValue())) { CheckFailed ("'common' global must have a zero initializer!", &GV); return ; } } while (false) | ||||
674 | "'common' global must have a zero initializer!", &GV)do { if (!(GV.getInitializer()->isNullValue())) { CheckFailed ("'common' global must have a zero initializer!", &GV); return ; } } while (false); | ||||
675 | Assert(!GV.isConstant(), "'common' global may not be marked constant!",do { if (!(!GV.isConstant())) { CheckFailed("'common' global may not be marked constant!" , &GV); return; } } while (false) | ||||
676 | &GV)do { if (!(!GV.isConstant())) { CheckFailed("'common' global may not be marked constant!" , &GV); return; } } while (false); | ||||
677 | Assert(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV)do { if (!(!GV.hasComdat())) { CheckFailed("'common' global may not be in a Comdat!" , &GV); return; } } while (false); | ||||
678 | } | ||||
679 | } | ||||
680 | |||||
681 | if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || | ||||
682 | GV.getName() == "llvm.global_dtors")) { | ||||
683 | Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
684 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
685 | // Don't worry about emitting an error for it not being an array, | ||||
686 | // visitGlobalValue will complain on appending non-array. | ||||
687 | if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) { | ||||
688 | StructType *STy = dyn_cast<StructType>(ATy->getElementType()); | ||||
689 | PointerType *FuncPtrTy = | ||||
690 | FunctionType::get(Type::getVoidTy(Context), false)-> | ||||
691 | getPointerTo(DL.getProgramAddressSpace()); | ||||
692 | Assert(STy &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
693 | (STy->getNumElements() == 2 || STy->getNumElements() == 3) &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
694 | STy->getTypeAtIndex(0u)->isIntegerTy(32) &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
695 | STy->getTypeAtIndex(1) == FuncPtrTy,do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
696 | "wrong type for intrinsic global variable", &GV)do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false); | ||||
697 | Assert(STy->getNumElements() == 3,do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify i8* null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
698 | "the third field of the element type is mandatory, "do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify i8* null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
699 | "specify i8* null to migrate from the obsoleted 2-field form")do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify i8* null to migrate from the obsoleted 2-field form" ); return; } } while (false); | ||||
700 | Type *ETy = STy->getTypeAtIndex(2); | ||||
701 | Type *Int8Ty = Type::getInt8Ty(ETy->getContext()); | ||||
702 | Assert(ETy->isPointerTy() &&do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false) | ||||
703 | cast<PointerType>(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty),do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false) | ||||
704 | "wrong type for intrinsic global variable", &GV)do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false); | ||||
705 | } | ||||
706 | } | ||||
707 | |||||
708 | if (GV.hasName() && (GV.getName() == "llvm.used" || | ||||
709 | GV.getName() == "llvm.compiler.used")) { | ||||
710 | Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
711 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
712 | Type *GVType = GV.getValueType(); | ||||
713 | if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) { | ||||
714 | PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType()); | ||||
715 | Assert(PTy, "wrong type for intrinsic global variable", &GV)do { if (!(PTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false); | ||||
716 | if (GV.hasInitializer()) { | ||||
717 | const Constant *Init = GV.getInitializer(); | ||||
718 | const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); | ||||
719 | Assert(InitArray, "wrong initalizer for intrinsic global variable",do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false) | ||||
720 | Init)do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false); | ||||
721 | for (Value *Op : InitArray->operands()) { | ||||
722 | Value *V = Op->stripPointerCasts(); | ||||
723 | Assert(isa<GlobalVariable>(V) || isa<Function>(V) ||do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed("invalid llvm.used member" , V); return; } } while (false) | ||||
724 | isa<GlobalAlias>(V),do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed("invalid llvm.used member" , V); return; } } while (false) | ||||
725 | "invalid llvm.used member", V)do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed("invalid llvm.used member" , V); return; } } while (false); | ||||
726 | Assert(V->hasName(), "members of llvm.used must be named", V)do { if (!(V->hasName())) { CheckFailed("members of llvm.used must be named" , V); return; } } while (false); | ||||
727 | } | ||||
728 | } | ||||
729 | } | ||||
730 | } | ||||
731 | |||||
732 | // Visit any debug info attachments. | ||||
733 | SmallVector<MDNode *, 1> MDs; | ||||
734 | GV.getMetadata(LLVMContext::MD_dbg, MDs); | ||||
735 | for (auto *MD : MDs) { | ||||
736 | if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD)) | ||||
737 | visitDIGlobalVariableExpression(*GVE); | ||||
738 | else | ||||
739 | AssertDI(false, "!dbg attachment of global variable must be a "do { if (!(false)) { DebugInfoCheckFailed("!dbg attachment of global variable must be a " "DIGlobalVariableExpression"); return; } } while (false) | ||||
740 | "DIGlobalVariableExpression")do { if (!(false)) { DebugInfoCheckFailed("!dbg attachment of global variable must be a " "DIGlobalVariableExpression"); return; } } while (false); | ||||
741 | } | ||||
742 | |||||
743 | // Scalable vectors cannot be global variables, since we don't know | ||||
744 | // the runtime size. If the global is an array containing scalable vectors, | ||||
745 | // that will be caught by the isValidElementType methods in StructType or | ||||
746 | // ArrayType instead. | ||||
747 | Assert(!isa<ScalableVectorType>(GV.getValueType()),do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false) | ||||
748 | "Globals cannot contain scalable vectors", &GV)do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false); | ||||
749 | |||||
750 | if (auto *STy = dyn_cast<StructType>(GV.getValueType())) | ||||
751 | Assert(!STy->containsScalableVectorType(),do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false) | ||||
752 | "Globals cannot contain scalable vectors", &GV)do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false); | ||||
753 | |||||
754 | if (!GV.hasInitializer()) { | ||||
755 | visitGlobalValue(GV); | ||||
756 | return; | ||||
757 | } | ||||
758 | |||||
759 | // Walk any aggregate initializers looking for bitcasts between address spaces | ||||
760 | visitConstantExprsRecursively(GV.getInitializer()); | ||||
761 | |||||
762 | visitGlobalValue(GV); | ||||
763 | } | ||||
764 | |||||
765 | void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { | ||||
766 | SmallPtrSet<const GlobalAlias*, 4> Visited; | ||||
767 | Visited.insert(&GA); | ||||
768 | visitAliaseeSubExpr(Visited, GA, C); | ||||
769 | } | ||||
770 | |||||
771 | void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited, | ||||
772 | const GlobalAlias &GA, const Constant &C) { | ||||
773 | if (const auto *GV = dyn_cast<GlobalValue>(&C)) { | ||||
774 | Assert(!GV->isDeclarationForLinker(), "Alias must point to a definition",do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false) | ||||
775 | &GA)do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false); | ||||
776 | |||||
777 | if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { | ||||
778 | Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA)do { if (!(Visited.insert(GA2).second)) { CheckFailed("Aliases cannot form a cycle" , &GA); return; } } while (false); | ||||
779 | |||||
780 | Assert(!GA2->isInterposable(), "Alias cannot point to an interposable alias",do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false) | ||||
781 | &GA)do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false); | ||||
782 | } else { | ||||
783 | // Only continue verifying subexpressions of GlobalAliases. | ||||
784 | // Do not recurse into global initializers. | ||||
785 | return; | ||||
786 | } | ||||
787 | } | ||||
788 | |||||
789 | if (const auto *CE = dyn_cast<ConstantExpr>(&C)) | ||||
790 | visitConstantExprsRecursively(CE); | ||||
791 | |||||
792 | for (const Use &U : C.operands()) { | ||||
793 | Value *V = &*U; | ||||
794 | if (const auto *GA2 = dyn_cast<GlobalAlias>(V)) | ||||
795 | visitAliaseeSubExpr(Visited, GA, *GA2->getAliasee()); | ||||
796 | else if (const auto *C2 = dyn_cast<Constant>(V)) | ||||
797 | visitAliaseeSubExpr(Visited, GA, *C2); | ||||
798 | } | ||||
799 | } | ||||
800 | |||||
801 | void Verifier::visitGlobalAlias(const GlobalAlias &GA) { | ||||
802 | Assert(GlobalAlias::isValidLinkage(GA.getLinkage()),do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false) | ||||
803 | "Alias should have private, internal, linkonce, weak, linkonce_odr, "do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false) | ||||
804 | "weak_odr, or external linkage!",do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false) | ||||
805 | &GA)do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false); | ||||
806 | const Constant *Aliasee = GA.getAliasee(); | ||||
807 | Assert(Aliasee, "Aliasee cannot be NULL!", &GA)do { if (!(Aliasee)) { CheckFailed("Aliasee cannot be NULL!", &GA); return; } } while (false); | ||||
808 | Assert(GA.getType() == Aliasee->getType(),do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false) | ||||
809 | "Alias and aliasee types should match!", &GA)do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false); | ||||
810 | |||||
811 | Assert(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee),do { if (!(isa<GlobalValue>(Aliasee) || isa<ConstantExpr >(Aliasee))) { CheckFailed("Aliasee should be either GlobalValue or ConstantExpr" , &GA); return; } } while (false) | ||||
812 | "Aliasee should be either GlobalValue or ConstantExpr", &GA)do { if (!(isa<GlobalValue>(Aliasee) || isa<ConstantExpr >(Aliasee))) { CheckFailed("Aliasee should be either GlobalValue or ConstantExpr" , &GA); return; } } while (false); | ||||
813 | |||||
814 | visitAliaseeSubExpr(GA, *Aliasee); | ||||
815 | |||||
816 | visitGlobalValue(GA); | ||||
817 | } | ||||
818 | |||||
819 | void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { | ||||
820 | // There used to be various other llvm.dbg.* nodes, but we don't support | ||||
821 | // upgrading them and we want to reserve the namespace for future uses. | ||||
822 | if (NMD.getName().startswith("llvm.dbg.")) | ||||
823 | AssertDI(NMD.getName() == "llvm.dbg.cu",do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false) | ||||
824 | "unrecognized named metadata node in the llvm.dbg namespace",do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false) | ||||
825 | &NMD)do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false); | ||||
826 | for (const MDNode *MD : NMD.operands()) { | ||||
827 | if (NMD.getName() == "llvm.dbg.cu") | ||||
828 | AssertDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD)do { if (!(MD && isa<DICompileUnit>(MD))) { DebugInfoCheckFailed ("invalid compile unit", &NMD, MD); return; } } while (false ); | ||||
829 | |||||
830 | if (!MD) | ||||
831 | continue; | ||||
832 | |||||
833 | visitMDNode(*MD, AreDebugLocsAllowed::Yes); | ||||
834 | } | ||||
835 | } | ||||
836 | |||||
837 | void Verifier::visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs) { | ||||
838 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
839 | // avoids infinite recursion here, as well as being an optimization. | ||||
840 | if (!MDNodes.insert(&MD).second) | ||||
841 | return; | ||||
842 | |||||
843 | Assert(&MD.getContext() == &Context,do { if (!(&MD.getContext() == &Context)) { CheckFailed ("MDNode context does not match Module context!", &MD); return ; } } while (false) | ||||
844 | "MDNode context does not match Module context!", &MD)do { if (!(&MD.getContext() == &Context)) { CheckFailed ("MDNode context does not match Module context!", &MD); return ; } } while (false); | ||||
845 | |||||
846 | switch (MD.getMetadataID()) { | ||||
847 | default: | ||||
848 | llvm_unreachable("Invalid MDNode subclass")::llvm::llvm_unreachable_internal("Invalid MDNode subclass", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 848); | ||||
849 | case Metadata::MDTupleKind: | ||||
850 | break; | ||||
851 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ | ||||
852 | case Metadata::CLASS##Kind: \ | ||||
853 | visit##CLASS(cast<CLASS>(MD)); \ | ||||
854 | break; | ||||
855 | #include "llvm/IR/Metadata.def" | ||||
856 | } | ||||
857 | |||||
858 | for (const Metadata *Op : MD.operands()) { | ||||
859 | if (!Op) | ||||
860 | continue; | ||||
861 | Assert(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!",do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false) | ||||
862 | &MD, Op)do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false); | ||||
863 | AssertDI(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed::Yes,do { if (!(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed ::Yes)) { DebugInfoCheckFailed("DILocation not allowed within this metadata node" , &MD, Op); return; } } while (false) | ||||
864 | "DILocation not allowed within this metadata node", &MD, Op)do { if (!(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed ::Yes)) { DebugInfoCheckFailed("DILocation not allowed within this metadata node" , &MD, Op); return; } } while (false); | ||||
865 | if (auto *N = dyn_cast<MDNode>(Op)) { | ||||
866 | visitMDNode(*N, AllowLocs); | ||||
867 | continue; | ||||
868 | } | ||||
869 | if (auto *V = dyn_cast<ValueAsMetadata>(Op)) { | ||||
870 | visitValueAsMetadata(*V, nullptr); | ||||
871 | continue; | ||||
872 | } | ||||
873 | } | ||||
874 | |||||
875 | // Check these last, so we diagnose problems in operands first. | ||||
876 | Assert(!MD.isTemporary(), "Expected no forward declarations!", &MD)do { if (!(!MD.isTemporary())) { CheckFailed("Expected no forward declarations!" , &MD); return; } } while (false); | ||||
877 | Assert(MD.isResolved(), "All nodes should be resolved!", &MD)do { if (!(MD.isResolved())) { CheckFailed("All nodes should be resolved!" , &MD); return; } } while (false); | ||||
878 | } | ||||
879 | |||||
880 | void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) { | ||||
881 | Assert(MD.getValue(), "Expected valid value", &MD)do { if (!(MD.getValue())) { CheckFailed("Expected valid value" , &MD); return; } } while (false); | ||||
882 | Assert(!MD.getValue()->getType()->isMetadataTy(),do { if (!(!MD.getValue()->getType()->isMetadataTy())) { CheckFailed("Unexpected metadata round-trip through values", &MD, MD.getValue()); return; } } while (false) | ||||
883 | "Unexpected metadata round-trip through values", &MD, MD.getValue())do { if (!(!MD.getValue()->getType()->isMetadataTy())) { CheckFailed("Unexpected metadata round-trip through values", &MD, MD.getValue()); return; } } while (false); | ||||
884 | |||||
885 | auto *L = dyn_cast<LocalAsMetadata>(&MD); | ||||
886 | if (!L) | ||||
887 | return; | ||||
888 | |||||
889 | Assert(F, "function-local metadata used outside a function", L)do { if (!(F)) { CheckFailed("function-local metadata used outside a function" , L); return; } } while (false); | ||||
890 | |||||
891 | // If this was an instruction, bb, or argument, verify that it is in the | ||||
892 | // function that we expect. | ||||
893 | Function *ActualF = nullptr; | ||||
894 | if (Instruction *I = dyn_cast<Instruction>(L->getValue())) { | ||||
895 | Assert(I->getParent(), "function-local metadata not in basic block", L, I)do { if (!(I->getParent())) { CheckFailed("function-local metadata not in basic block" , L, I); return; } } while (false); | ||||
896 | ActualF = I->getParent()->getParent(); | ||||
897 | } else if (BasicBlock *BB = dyn_cast<BasicBlock>(L->getValue())) | ||||
898 | ActualF = BB->getParent(); | ||||
899 | else if (Argument *A = dyn_cast<Argument>(L->getValue())) | ||||
900 | ActualF = A->getParent(); | ||||
901 | assert(ActualF && "Unimplemented function local metadata case!")(static_cast <bool> (ActualF && "Unimplemented function local metadata case!" ) ? void (0) : __assert_fail ("ActualF && \"Unimplemented function local metadata case!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 901, __extension__ __PRETTY_FUNCTION__)); | ||||
902 | |||||
903 | Assert(ActualF == F, "function-local metadata used in wrong function", L)do { if (!(ActualF == F)) { CheckFailed("function-local metadata used in wrong function" , L); return; } } while (false); | ||||
904 | } | ||||
905 | |||||
906 | void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { | ||||
907 | Metadata *MD = MDV.getMetadata(); | ||||
908 | if (auto *N = dyn_cast<MDNode>(MD)) { | ||||
909 | visitMDNode(*N, AreDebugLocsAllowed::No); | ||||
910 | return; | ||||
911 | } | ||||
912 | |||||
913 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
914 | // avoids infinite recursion here, as well as being an optimization. | ||||
915 | if (!MDNodes.insert(MD).second) | ||||
916 | return; | ||||
917 | |||||
918 | if (auto *V = dyn_cast<ValueAsMetadata>(MD)) | ||||
919 | visitValueAsMetadata(*V, F); | ||||
920 | } | ||||
921 | |||||
922 | static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); } | ||||
923 | static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); } | ||||
924 | static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); } | ||||
925 | |||||
926 | void Verifier::visitDILocation(const DILocation &N) { | ||||
927 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("location requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
928 | "location requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("location requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
929 | if (auto *IA = N.getRawInlinedAt()) | ||||
930 | AssertDI(isa<DILocation>(IA), "inlined-at should be a location", &N, IA)do { if (!(isa<DILocation>(IA))) { DebugInfoCheckFailed ("inlined-at should be a location", &N, IA); return; } } while (false); | ||||
931 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
932 | AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
933 | } | ||||
934 | |||||
935 | void Verifier::visitGenericDINode(const GenericDINode &N) { | ||||
936 | AssertDI(N.getTag(), "invalid tag", &N)do { if (!(N.getTag())) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
937 | } | ||||
938 | |||||
939 | void Verifier::visitDIScope(const DIScope &N) { | ||||
940 | if (auto *F = N.getRawFile()) | ||||
941 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
942 | } | ||||
943 | |||||
944 | void Verifier::visitDISubrange(const DISubrange &N) { | ||||
945 | AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
946 | bool HasAssumedSizedArraySupport = dwarf::isFortran(CurrentSourceLang); | ||||
947 | AssertDI(HasAssumedSizedArraySupport || N.getRawCountNode() ||do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
948 | N.getRawUpperBound(),do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
949 | "Subrange must contain count or upperBound", &N)do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false); | ||||
950 | AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("Subrange can have any one of count or upperBound", &N); return; } } while (false) | ||||
951 | "Subrange can have any one of count or upperBound", &N)do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("Subrange can have any one of count or upperBound", &N); return; } } while (false); | ||||
952 | auto *CBound = N.getRawCountNode(); | ||||
953 | AssertDI(!CBound || isa<ConstantAsMetadata>(CBound) ||do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
954 | isa<DIVariable>(CBound) || isa<DIExpression>(CBound),do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
955 | "Count must be signed constant or DIVariable or DIExpression", &N)do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
956 | auto Count = N.getCount(); | ||||
957 | AssertDI(!Count || !Count.is<ConstantInt *>() ||do { if (!(!Count || !Count.is<ConstantInt *>() || Count .get<ConstantInt *>()->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
958 | Count.get<ConstantInt *>()->getSExtValue() >= -1,do { if (!(!Count || !Count.is<ConstantInt *>() || Count .get<ConstantInt *>()->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
959 | "invalid subrange count", &N)do { if (!(!Count || !Count.is<ConstantInt *>() || Count .get<ConstantInt *>()->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false); | ||||
960 | auto *LBound = N.getRawLowerBound(); | ||||
961 | AssertDI(!LBound || isa<ConstantAsMetadata>(LBound) ||do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
962 | isa<DIVariable>(LBound) || isa<DIExpression>(LBound),do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
963 | "LowerBound must be signed constant or DIVariable or DIExpression",do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
964 | &N)do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
965 | auto *UBound = N.getRawUpperBound(); | ||||
966 | AssertDI(!UBound || isa<ConstantAsMetadata>(UBound) ||do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
967 | isa<DIVariable>(UBound) || isa<DIExpression>(UBound),do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
968 | "UpperBound must be signed constant or DIVariable or DIExpression",do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
969 | &N)do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
970 | auto *Stride = N.getRawStride(); | ||||
971 | AssertDI(!Stride || isa<ConstantAsMetadata>(Stride) ||do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
972 | isa<DIVariable>(Stride) || isa<DIExpression>(Stride),do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
973 | "Stride must be signed constant or DIVariable or DIExpression", &N)do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
974 | } | ||||
975 | |||||
976 | void Verifier::visitDIGenericSubrange(const DIGenericSubrange &N) { | ||||
977 | AssertDI(N.getTag() == dwarf::DW_TAG_generic_subrange, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_generic_subrange)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
978 | AssertDI(N.getRawCountNode() || N.getRawUpperBound(),do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false) | ||||
979 | "GenericSubrange must contain count or upperBound", &N)do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false); | ||||
980 | AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange can have any one of count or upperBound", & N); return; } } while (false) | ||||
981 | "GenericSubrange can have any one of count or upperBound", &N)do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange can have any one of count or upperBound", & N); return; } } while (false); | ||||
982 | auto *CBound = N.getRawCountNode(); | ||||
983 | AssertDI(!CBound || isa<DIVariable>(CBound) || isa<DIExpression>(CBound),do { if (!(!CBound || isa<DIVariable>(CBound) || isa< DIExpression>(CBound))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
984 | "Count must be signed constant or DIVariable or DIExpression", &N)do { if (!(!CBound || isa<DIVariable>(CBound) || isa< DIExpression>(CBound))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
985 | auto *LBound = N.getRawLowerBound(); | ||||
986 | AssertDI(LBound, "GenericSubrange must contain lowerBound", &N)do { if (!(LBound)) { DebugInfoCheckFailed("GenericSubrange must contain lowerBound" , &N); return; } } while (false); | ||||
987 | AssertDI(isa<DIVariable>(LBound) || isa<DIExpression>(LBound),do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
988 | "LowerBound must be signed constant or DIVariable or DIExpression",do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
989 | &N)do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
990 | auto *UBound = N.getRawUpperBound(); | ||||
991 | AssertDI(!UBound || isa<DIVariable>(UBound) || isa<DIExpression>(UBound),do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
992 | "UpperBound must be signed constant or DIVariable or DIExpression",do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
993 | &N)do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
994 | auto *Stride = N.getRawStride(); | ||||
995 | AssertDI(Stride, "GenericSubrange must contain stride", &N)do { if (!(Stride)) { DebugInfoCheckFailed("GenericSubrange must contain stride" , &N); return; } } while (false); | ||||
996 | AssertDI(isa<DIVariable>(Stride) || isa<DIExpression>(Stride),do { if (!(isa<DIVariable>(Stride) || isa<DIExpression >(Stride))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
997 | "Stride must be signed constant or DIVariable or DIExpression", &N)do { if (!(isa<DIVariable>(Stride) || isa<DIExpression >(Stride))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
998 | } | ||||
999 | |||||
1000 | void Verifier::visitDIEnumerator(const DIEnumerator &N) { | ||||
1001 | AssertDI(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_enumerator)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1002 | } | ||||
1003 | |||||
1004 | void Verifier::visitDIBasicType(const DIBasicType &N) { | ||||
1005 | AssertDI(N.getTag() == dwarf::DW_TAG_base_type ||do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1006 | N.getTag() == dwarf::DW_TAG_unspecified_type ||do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1007 | N.getTag() == dwarf::DW_TAG_string_type,do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1008 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
1009 | } | ||||
1010 | |||||
1011 | void Verifier::visitDIStringType(const DIStringType &N) { | ||||
1012 | AssertDI(N.getTag() == dwarf::DW_TAG_string_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_string_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1013 | AssertDI(!(N.isBigEndian() && N.isLittleEndian()) ,do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false) | ||||
1014 | "has conflicting flags", &N)do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false); | ||||
1015 | } | ||||
1016 | |||||
1017 | void Verifier::visitDIDerivedType(const DIDerivedType &N) { | ||||
1018 | // Common scope checks. | ||||
1019 | visitDIScope(N); | ||||
1020 | |||||
1021 | AssertDI(N.getTag() == dwarf::DW_TAG_typedef ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1022 | N.getTag() == dwarf::DW_TAG_pointer_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1023 | N.getTag() == dwarf::DW_TAG_ptr_to_member_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1024 | N.getTag() == dwarf::DW_TAG_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1025 | N.getTag() == dwarf::DW_TAG_rvalue_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1026 | N.getTag() == dwarf::DW_TAG_const_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1027 | N.getTag() == dwarf::DW_TAG_volatile_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1028 | N.getTag() == dwarf::DW_TAG_restrict_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1029 | N.getTag() == dwarf::DW_TAG_atomic_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1030 | N.getTag() == dwarf::DW_TAG_member ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1031 | N.getTag() == dwarf::DW_TAG_inheritance ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1032 | N.getTag() == dwarf::DW_TAG_friend ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1033 | N.getTag() == dwarf::DW_TAG_set_type,do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1034 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1035 | if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) { | ||||
1036 | AssertDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,do { if (!(isType(N.getRawExtraData()))) { DebugInfoCheckFailed ("invalid pointer to member type", &N, N.getRawExtraData( )); return; } } while (false) | ||||
1037 | N.getRawExtraData())do { if (!(isType(N.getRawExtraData()))) { DebugInfoCheckFailed ("invalid pointer to member type", &N, N.getRawExtraData( )); return; } } while (false); | ||||
1038 | } | ||||
1039 | |||||
1040 | if (N.getTag() == dwarf::DW_TAG_set_type) { | ||||
1041 | if (auto *T = N.getRawBaseType()) { | ||||
1042 | auto *Enum = dyn_cast_or_null<DICompositeType>(T); | ||||
1043 | auto *Basic = dyn_cast_or_null<DIBasicType>(T); | ||||
1044 | AssertDI(do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
1045 | (Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type) ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
1046 | (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
1047 | Basic->getEncoding() == dwarf::DW_ATE_signed ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
1048 | Basic->getEncoding() == dwarf::DW_ATE_unsigned_char ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
1049 | Basic->getEncoding() == dwarf::DW_ATE_signed_char ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
1050 | Basic->getEncoding() == dwarf::DW_ATE_boolean)),do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
1051 | "invalid set base type", &N, T)do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false); | ||||
1052 | } | ||||
1053 | } | ||||
1054 | |||||
1055 | AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
1056 | AssertDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
1057 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
1058 | |||||
1059 | if (N.getDWARFAddressSpace()) { | ||||
1060 | AssertDI(N.getTag() == dwarf::DW_TAG_pointer_type ||do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
1061 | N.getTag() == dwarf::DW_TAG_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
1062 | N.getTag() == dwarf::DW_TAG_rvalue_reference_type,do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
1063 | "DWARF address space only applies to pointer or reference types",do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
1064 | &N)do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false); | ||||
1065 | } | ||||
1066 | } | ||||
1067 | |||||
1068 | /// Detect mutually exclusive flags. | ||||
1069 | static bool hasConflictingReferenceFlags(unsigned Flags) { | ||||
1070 | return ((Flags & DINode::FlagLValueReference) && | ||||
1071 | (Flags & DINode::FlagRValueReference)) || | ||||
1072 | ((Flags & DINode::FlagTypePassByValue) && | ||||
1073 | (Flags & DINode::FlagTypePassByReference)); | ||||
1074 | } | ||||
1075 | |||||
1076 | void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) { | ||||
1077 | auto *Params = dyn_cast<MDTuple>(&RawParams); | ||||
1078 | AssertDI(Params, "invalid template params", &N, &RawParams)do { if (!(Params)) { DebugInfoCheckFailed("invalid template params" , &N, &RawParams); return; } } while (false); | ||||
1079 | for (Metadata *Op : Params->operands()) { | ||||
1080 | AssertDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false) | ||||
1081 | &N, Params, Op)do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false); | ||||
1082 | } | ||||
1083 | } | ||||
1084 | |||||
1085 | void Verifier::visitDICompositeType(const DICompositeType &N) { | ||||
1086 | // Common scope checks. | ||||
1087 | visitDIScope(N); | ||||
1088 | |||||
1089 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1090 | N.getTag() == dwarf::DW_TAG_structure_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1091 | N.getTag() == dwarf::DW_TAG_union_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1092 | N.getTag() == dwarf::DW_TAG_enumeration_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1093 | N.getTag() == dwarf::DW_TAG_class_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1094 | N.getTag() == dwarf::DW_TAG_variant_part,do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1095 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
1096 | |||||
1097 | AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
1098 | AssertDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
1099 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
1100 | |||||
1101 | AssertDI(!N.getRawElements() || isa<MDTuple>(N.getRawElements()),do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false) | ||||
1102 | "invalid composite elements", &N, N.getRawElements())do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false); | ||||
1103 | AssertDI(isType(N.getRawVTableHolder()), "invalid vtable holder", &N,do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false) | ||||
1104 | N.getRawVTableHolder())do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false); | ||||
1105 | AssertDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
1106 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
1107 | unsigned DIBlockByRefStruct = 1 << 4; | ||||
1108 | AssertDI((N.getFlags() & DIBlockByRefStruct) == 0,do { if (!((N.getFlags() & DIBlockByRefStruct) == 0)) { DebugInfoCheckFailed ("DIBlockByRefStruct on DICompositeType is no longer supported" , &N); return; } } while (false) | ||||
1109 | "DIBlockByRefStruct on DICompositeType is no longer supported", &N)do { if (!((N.getFlags() & DIBlockByRefStruct) == 0)) { DebugInfoCheckFailed ("DIBlockByRefStruct on DICompositeType is no longer supported" , &N); return; } } while (false); | ||||
1110 | |||||
1111 | if (N.isVector()) { | ||||
1112 | const DINodeArray Elements = N.getElements(); | ||||
1113 | AssertDI(Elements.size() == 1 &&do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false) | ||||
1114 | Elements[0]->getTag() == dwarf::DW_TAG_subrange_type,do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false) | ||||
1115 | "invalid vector, expected one element of type subrange", &N)do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false); | ||||
1116 | } | ||||
1117 | |||||
1118 | if (auto *Params = N.getRawTemplateParams()) | ||||
1119 | visitTemplateParams(N, *Params); | ||||
1120 | |||||
1121 | if (auto *D = N.getRawDiscriminator()) { | ||||
1122 | AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,do { if (!(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part)) { DebugInfoCheckFailed("discriminator can only appear on variant part" ); return; } } while (false) | ||||
1123 | "discriminator can only appear on variant part")do { if (!(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part)) { DebugInfoCheckFailed("discriminator can only appear on variant part" ); return; } } while (false); | ||||
1124 | } | ||||
1125 | |||||
1126 | if (N.getRawDataLocation()) { | ||||
1127 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("dataLocation can only appear in array type"); return; } } while (false) | ||||
1128 | "dataLocation can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("dataLocation can only appear in array type"); return; } } while (false); | ||||
1129 | } | ||||
1130 | |||||
1131 | if (N.getRawAssociated()) { | ||||
1132 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("associated can only appear in array type"); return; } } while (false) | ||||
1133 | "associated can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("associated can only appear in array type"); return; } } while (false); | ||||
1134 | } | ||||
1135 | |||||
1136 | if (N.getRawAllocated()) { | ||||
1137 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("allocated can only appear in array type"); return; } } while (false) | ||||
1138 | "allocated can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("allocated can only appear in array type"); return; } } while (false); | ||||
1139 | } | ||||
1140 | |||||
1141 | if (N.getRawRank()) { | ||||
1142 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("rank can only appear in array type"); return; } } while (false ) | ||||
1143 | "rank can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("rank can only appear in array type"); return; } } while (false ); | ||||
1144 | } | ||||
1145 | } | ||||
1146 | |||||
1147 | void Verifier::visitDISubroutineType(const DISubroutineType &N) { | ||||
1148 | AssertDI(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subroutine_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1149 | if (auto *Types = N.getRawTypeArray()) { | ||||
1150 | AssertDI(isa<MDTuple>(Types), "invalid composite elements", &N, Types)do { if (!(isa<MDTuple>(Types))) { DebugInfoCheckFailed ("invalid composite elements", &N, Types); return; } } while (false); | ||||
1151 | for (Metadata *Ty : N.getTypeArray()->operands()) { | ||||
1152 | AssertDI(isType(Ty), "invalid subroutine type ref", &N, Types, Ty)do { if (!(isType(Ty))) { DebugInfoCheckFailed("invalid subroutine type ref" , &N, Types, Ty); return; } } while (false); | ||||
1153 | } | ||||
1154 | } | ||||
1155 | AssertDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
1156 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
1157 | } | ||||
1158 | |||||
1159 | void Verifier::visitDIFile(const DIFile &N) { | ||||
1160 | AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_file_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1161 | Optional<DIFile::ChecksumInfo<StringRef>> Checksum = N.getChecksum(); | ||||
1162 | if (Checksum) { | ||||
1163 | AssertDI(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last,do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false) | ||||
1164 | "invalid checksum kind", &N)do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false); | ||||
1165 | size_t Size; | ||||
1166 | switch (Checksum->Kind) { | ||||
1167 | case DIFile::CSK_MD5: | ||||
1168 | Size = 32; | ||||
1169 | break; | ||||
1170 | case DIFile::CSK_SHA1: | ||||
1171 | Size = 40; | ||||
1172 | break; | ||||
1173 | case DIFile::CSK_SHA256: | ||||
1174 | Size = 64; | ||||
1175 | break; | ||||
1176 | } | ||||
1177 | AssertDI(Checksum->Value.size() == Size, "invalid checksum length", &N)do { if (!(Checksum->Value.size() == Size)) { DebugInfoCheckFailed ("invalid checksum length", &N); return; } } while (false ); | ||||
1178 | AssertDI(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos,do { if (!(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos)) { DebugInfoCheckFailed("invalid checksum", &N); return; } } while (false) | ||||
1179 | "invalid checksum", &N)do { if (!(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos)) { DebugInfoCheckFailed("invalid checksum", &N); return; } } while (false); | ||||
1180 | } | ||||
1181 | } | ||||
1182 | |||||
1183 | void Verifier::visitDICompileUnit(const DICompileUnit &N) { | ||||
1184 | AssertDI(N.isDistinct(), "compile units must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("compile units must be distinct" , &N); return; } } while (false); | ||||
1185 | AssertDI(N.getTag() == dwarf::DW_TAG_compile_unit, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_compile_unit)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1186 | |||||
1187 | // Don't bother verifying the compilation directory or producer string | ||||
1188 | // as those could be empty. | ||||
1189 | AssertDI(N.getRawFile() && isa<DIFile>(N.getRawFile()), "invalid file", &N,do { if (!(N.getRawFile() && isa<DIFile>(N.getRawFile ()))) { DebugInfoCheckFailed("invalid file", &N, N.getRawFile ()); return; } } while (false) | ||||
1190 | N.getRawFile())do { if (!(N.getRawFile() && isa<DIFile>(N.getRawFile ()))) { DebugInfoCheckFailed("invalid file", &N, N.getRawFile ()); return; } } while (false); | ||||
1191 | AssertDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false) | ||||
1192 | N.getFile())do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false); | ||||
1193 | |||||
1194 | CurrentSourceLang = (dwarf::SourceLanguage)N.getSourceLanguage(); | ||||
1195 | |||||
1196 | verifySourceDebugInfo(N, *N.getFile()); | ||||
1197 | |||||
1198 | AssertDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false) | ||||
1199 | "invalid emission kind", &N)do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false); | ||||
1200 | |||||
1201 | if (auto *Array = N.getRawEnumTypes()) { | ||||
1202 | AssertDI(isa<MDTuple>(Array), "invalid enum list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid enum list", &N, Array); return; } } while (false ); | ||||
1203 | for (Metadata *Op : N.getEnumTypes()->operands()) { | ||||
1204 | auto *Enum = dyn_cast_or_null<DICompositeType>(Op); | ||||
1205 | AssertDI(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type,do { if (!(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type )) { DebugInfoCheckFailed("invalid enum type", &N, N.getEnumTypes (), Op); return; } } while (false) | ||||
1206 | "invalid enum type", &N, N.getEnumTypes(), Op)do { if (!(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type )) { DebugInfoCheckFailed("invalid enum type", &N, N.getEnumTypes (), Op); return; } } while (false); | ||||
1207 | } | ||||
1208 | } | ||||
1209 | if (auto *Array = N.getRawRetainedTypes()) { | ||||
1210 | AssertDI(isa<MDTuple>(Array), "invalid retained type list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid retained type list", &N, Array); return; } } while (false); | ||||
1211 | for (Metadata *Op : N.getRetainedTypes()->operands()) { | ||||
1212 | AssertDI(Op && (isa<DIType>(Op) ||do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
1213 | (isa<DISubprogram>(Op) &&do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
1214 | !cast<DISubprogram>(Op)->isDefinition())),do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
1215 | "invalid retained type", &N, Op)do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false); | ||||
1216 | } | ||||
1217 | } | ||||
1218 | if (auto *Array = N.getRawGlobalVariables()) { | ||||
1219 | AssertDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid global variable list", &N, Array); return; } } while (false); | ||||
1220 | for (Metadata *Op : N.getGlobalVariables()->operands()) { | ||||
1221 | AssertDI(Op && (isa<DIGlobalVariableExpression>(Op)),do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false) | ||||
1222 | "invalid global variable ref", &N, Op)do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false); | ||||
1223 | } | ||||
1224 | } | ||||
1225 | if (auto *Array = N.getRawImportedEntities()) { | ||||
1226 | AssertDI(isa<MDTuple>(Array), "invalid imported entity list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid imported entity list", &N, Array); return; } } while (false); | ||||
1227 | for (Metadata *Op : N.getImportedEntities()->operands()) { | ||||
1228 | AssertDI(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref",do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false) | ||||
1229 | &N, Op)do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false); | ||||
1230 | } | ||||
1231 | } | ||||
1232 | if (auto *Array = N.getRawMacros()) { | ||||
1233 | AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
1234 | for (Metadata *Op : N.getMacros()->operands()) { | ||||
1235 | AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
1236 | } | ||||
1237 | } | ||||
1238 | CUVisited.insert(&N); | ||||
1239 | } | ||||
1240 | |||||
1241 | void Verifier::visitDISubprogram(const DISubprogram &N) { | ||||
1242 | AssertDI(N.getTag() == dwarf::DW_TAG_subprogram, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subprogram)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1243 | AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
1244 | if (auto *F = N.getRawFile()) | ||||
1245 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1246 | else | ||||
1247 | AssertDI(N.getLine() == 0, "line specified with no file", &N, N.getLine())do { if (!(N.getLine() == 0)) { DebugInfoCheckFailed("line specified with no file" , &N, N.getLine()); return; } } while (false); | ||||
1248 | if (auto *T = N.getRawType()) | ||||
1249 | AssertDI(isa<DISubroutineType>(T), "invalid subroutine type", &N, T)do { if (!(isa<DISubroutineType>(T))) { DebugInfoCheckFailed ("invalid subroutine type", &N, T); return; } } while (false ); | ||||
1250 | AssertDI(isType(N.getRawContainingType()), "invalid containing type", &N,do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false) | ||||
1251 | N.getRawContainingType())do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false); | ||||
1252 | if (auto *Params = N.getRawTemplateParams()) | ||||
1253 | visitTemplateParams(N, *Params); | ||||
1254 | if (auto *S = N.getRawDeclaration()) | ||||
1255 | AssertDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(),do { if (!(isa<DISubprogram>(S) && !cast<DISubprogram >(S)->isDefinition())) { DebugInfoCheckFailed("invalid subprogram declaration" , &N, S); return; } } while (false) | ||||
1256 | "invalid subprogram declaration", &N, S)do { if (!(isa<DISubprogram>(S) && !cast<DISubprogram >(S)->isDefinition())) { DebugInfoCheckFailed("invalid subprogram declaration" , &N, S); return; } } while (false); | ||||
1257 | if (auto *RawNode = N.getRawRetainedNodes()) { | ||||
1258 | auto *Node = dyn_cast<MDTuple>(RawNode); | ||||
1259 | AssertDI(Node, "invalid retained nodes list", &N, RawNode)do { if (!(Node)) { DebugInfoCheckFailed("invalid retained nodes list" , &N, RawNode); return; } } while (false); | ||||
1260 | for (Metadata *Op : Node->operands()) { | ||||
1261 | AssertDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)),do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false) | ||||
1262 | "invalid retained nodes, expected DILocalVariable or DILabel",do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false) | ||||
1263 | &N, Node, Op)do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false); | ||||
1264 | } | ||||
1265 | } | ||||
1266 | AssertDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
1267 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
1268 | |||||
1269 | auto *Unit = N.getRawUnit(); | ||||
1270 | if (N.isDefinition()) { | ||||
1271 | // Subprogram definitions (not part of the type hierarchy). | ||||
1272 | AssertDI(N.isDistinct(), "subprogram definitions must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("subprogram definitions must be distinct" , &N); return; } } while (false); | ||||
1273 | AssertDI(Unit, "subprogram definitions must have a compile unit", &N)do { if (!(Unit)) { DebugInfoCheckFailed("subprogram definitions must have a compile unit" , &N); return; } } while (false); | ||||
1274 | AssertDI(isa<DICompileUnit>(Unit), "invalid unit type", &N, Unit)do { if (!(isa<DICompileUnit>(Unit))) { DebugInfoCheckFailed ("invalid unit type", &N, Unit); return; } } while (false ); | ||||
1275 | if (N.getFile()) | ||||
1276 | verifySourceDebugInfo(*N.getUnit(), *N.getFile()); | ||||
1277 | } else { | ||||
1278 | // Subprogram declarations (part of the type hierarchy). | ||||
1279 | AssertDI(!Unit, "subprogram declarations must not have a compile unit", &N)do { if (!(!Unit)) { DebugInfoCheckFailed("subprogram declarations must not have a compile unit" , &N); return; } } while (false); | ||||
1280 | } | ||||
1281 | |||||
1282 | if (auto *RawThrownTypes = N.getRawThrownTypes()) { | ||||
1283 | auto *ThrownTypes = dyn_cast<MDTuple>(RawThrownTypes); | ||||
1284 | AssertDI(ThrownTypes, "invalid thrown types list", &N, RawThrownTypes)do { if (!(ThrownTypes)) { DebugInfoCheckFailed("invalid thrown types list" , &N, RawThrownTypes); return; } } while (false); | ||||
1285 | for (Metadata *Op : ThrownTypes->operands()) | ||||
1286 | AssertDI(Op && isa<DIType>(Op), "invalid thrown type", &N, ThrownTypes,do { if (!(Op && isa<DIType>(Op))) { DebugInfoCheckFailed ("invalid thrown type", &N, ThrownTypes, Op); return; } } while (false) | ||||
1287 | Op)do { if (!(Op && isa<DIType>(Op))) { DebugInfoCheckFailed ("invalid thrown type", &N, ThrownTypes, Op); return; } } while (false); | ||||
1288 | } | ||||
1289 | |||||
1290 | if (N.areAllCallsDescribed()) | ||||
1291 | AssertDI(N.isDefinition(),do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false) | ||||
1292 | "DIFlagAllCallsDescribed must be attached to a definition")do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false); | ||||
1293 | } | ||||
1294 | |||||
1295 | void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { | ||||
1296 | AssertDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_lexical_block)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1297 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false) | ||||
1298 | "invalid local scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false); | ||||
1299 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
1300 | AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
1301 | } | ||||
1302 | |||||
1303 | void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { | ||||
1304 | visitDILexicalBlockBase(N); | ||||
1305 | |||||
1306 | AssertDI(N.getLine() || !N.getColumn(),do { if (!(N.getLine() || !N.getColumn())) { DebugInfoCheckFailed ("cannot have column info without line info", &N); return ; } } while (false) | ||||
1307 | "cannot have column info without line info", &N)do { if (!(N.getLine() || !N.getColumn())) { DebugInfoCheckFailed ("cannot have column info without line info", &N); return ; } } while (false); | ||||
1308 | } | ||||
1309 | |||||
1310 | void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { | ||||
1311 | visitDILexicalBlockBase(N); | ||||
1312 | } | ||||
1313 | |||||
1314 | void Verifier::visitDICommonBlock(const DICommonBlock &N) { | ||||
1315 | AssertDI(N.getTag() == dwarf::DW_TAG_common_block, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_common_block)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1316 | if (auto *S = N.getRawScope()) | ||||
1317 | AssertDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
1318 | if (auto *S = N.getRawDecl()) | ||||
1319 | AssertDI(isa<DIGlobalVariable>(S), "invalid declaration", &N, S)do { if (!(isa<DIGlobalVariable>(S))) { DebugInfoCheckFailed ("invalid declaration", &N, S); return; } } while (false); | ||||
1320 | } | ||||
1321 | |||||
1322 | void Verifier::visitDINamespace(const DINamespace &N) { | ||||
1323 | AssertDI(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_namespace)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1324 | if (auto *S = N.getRawScope()) | ||||
1325 | AssertDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
1326 | } | ||||
1327 | |||||
1328 | void Verifier::visitDIMacro(const DIMacro &N) { | ||||
1329 | AssertDI(N.getMacinfoType() == dwarf::DW_MACINFO_define ||do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false) | ||||
1330 | N.getMacinfoType() == dwarf::DW_MACINFO_undef,do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false) | ||||
1331 | "invalid macinfo type", &N)do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false); | ||||
1332 | AssertDI(!N.getName().empty(), "anonymous macro", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous macro" , &N); return; } } while (false); | ||||
1333 | if (!N.getValue().empty()) { | ||||
1334 | assert(N.getValue().data()[0] != ' ' && "Macro value has a space prefix")(static_cast <bool> (N.getValue().data()[0] != ' ' && "Macro value has a space prefix") ? void (0) : __assert_fail ("N.getValue().data()[0] != ' ' && \"Macro value has a space prefix\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 1334, __extension__ __PRETTY_FUNCTION__)); | ||||
1335 | } | ||||
1336 | } | ||||
1337 | |||||
1338 | void Verifier::visitDIMacroFile(const DIMacroFile &N) { | ||||
1339 | AssertDI(N.getMacinfoType() == dwarf::DW_MACINFO_start_file,do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false) | ||||
1340 | "invalid macinfo type", &N)do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false); | ||||
1341 | if (auto *F = N.getRawFile()) | ||||
1342 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1343 | |||||
1344 | if (auto *Array = N.getRawElements()) { | ||||
1345 | AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
1346 | for (Metadata *Op : N.getElements()->operands()) { | ||||
1347 | AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
1348 | } | ||||
1349 | } | ||||
1350 | } | ||||
1351 | |||||
1352 | void Verifier::visitDIArgList(const DIArgList &N) { | ||||
1353 | AssertDI(!N.getNumOperands(),do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
1354 | "DIArgList should have no operands other than a list of "do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
1355 | "ValueAsMetadata",do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
1356 | &N)do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false); | ||||
1357 | } | ||||
1358 | |||||
1359 | void Verifier::visitDIModule(const DIModule &N) { | ||||
1360 | AssertDI(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_module)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1361 | AssertDI(!N.getName().empty(), "anonymous module", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous module" , &N); return; } } while (false); | ||||
1362 | } | ||||
1363 | |||||
1364 | void Verifier::visitDITemplateParameter(const DITemplateParameter &N) { | ||||
1365 | AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
1366 | } | ||||
1367 | |||||
1368 | void Verifier::visitDITemplateTypeParameter(const DITemplateTypeParameter &N) { | ||||
1369 | visitDITemplateParameter(N); | ||||
1370 | |||||
1371 | AssertDI(N.getTag() == dwarf::DW_TAG_template_type_parameter, "invalid tag",do { if (!(N.getTag() == dwarf::DW_TAG_template_type_parameter )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
1372 | &N)do { if (!(N.getTag() == dwarf::DW_TAG_template_type_parameter )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
1373 | } | ||||
1374 | |||||
1375 | void Verifier::visitDITemplateValueParameter( | ||||
1376 | const DITemplateValueParameter &N) { | ||||
1377 | visitDITemplateParameter(N); | ||||
1378 | |||||
1379 | AssertDI(N.getTag() == dwarf::DW_TAG_template_value_parameter ||do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1380 | N.getTag() == dwarf::DW_TAG_GNU_template_template_param ||do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1381 | N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack,do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1382 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1383 | } | ||||
1384 | |||||
1385 | void Verifier::visitDIVariable(const DIVariable &N) { | ||||
1386 | if (auto *S = N.getRawScope()) | ||||
1387 | AssertDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
1388 | if (auto *F = N.getRawFile()) | ||||
1389 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1390 | } | ||||
1391 | |||||
1392 | void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { | ||||
1393 | // Checks common to all variables. | ||||
1394 | visitDIVariable(N); | ||||
1395 | |||||
1396 | AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1397 | AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
1398 | // Assert only if the global variable is not an extern | ||||
1399 | if (N.isDefinition()) | ||||
1400 | AssertDI(N.getType(), "missing global variable type", &N)do { if (!(N.getType())) { DebugInfoCheckFailed("missing global variable type" , &N); return; } } while (false); | ||||
1401 | if (auto *Member = N.getRawStaticDataMemberDeclaration()) { | ||||
1402 | AssertDI(isa<DIDerivedType>(Member),do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false) | ||||
1403 | "invalid static data member declaration", &N, Member)do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false); | ||||
1404 | } | ||||
1405 | } | ||||
1406 | |||||
1407 | void Verifier::visitDILocalVariable(const DILocalVariable &N) { | ||||
1408 | // Checks common to all variables. | ||||
1409 | visitDIVariable(N); | ||||
1410 | |||||
1411 | AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
1412 | AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1413 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("local variable requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
1414 | "local variable requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("local variable requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
1415 | if (auto Ty = N.getType()) | ||||
1416 | AssertDI(!isa<DISubroutineType>(Ty), "invalid type", &N, N.getType())do { if (!(!isa<DISubroutineType>(Ty))) { DebugInfoCheckFailed ("invalid type", &N, N.getType()); return; } } while (false ); | ||||
1417 | } | ||||
1418 | |||||
1419 | void Verifier::visitDILabel(const DILabel &N) { | ||||
1420 | if (auto *S = N.getRawScope()) | ||||
1421 | AssertDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
1422 | if (auto *F = N.getRawFile()) | ||||
1423 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1424 | |||||
1425 | AssertDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_label)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1426 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("label requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
1427 | "label requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("label requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
1428 | } | ||||
1429 | |||||
1430 | void Verifier::visitDIExpression(const DIExpression &N) { | ||||
1431 | AssertDI(N.isValid(), "invalid expression", &N)do { if (!(N.isValid())) { DebugInfoCheckFailed("invalid expression" , &N); return; } } while (false); | ||||
1432 | } | ||||
1433 | |||||
1434 | void Verifier::visitDIGlobalVariableExpression( | ||||
1435 | const DIGlobalVariableExpression &GVE) { | ||||
1436 | AssertDI(GVE.getVariable(), "missing variable")do { if (!(GVE.getVariable())) { DebugInfoCheckFailed("missing variable" ); return; } } while (false); | ||||
1437 | if (auto *Var = GVE.getVariable()) | ||||
1438 | visitDIGlobalVariable(*Var); | ||||
1439 | if (auto *Expr = GVE.getExpression()) { | ||||
1440 | visitDIExpression(*Expr); | ||||
1441 | if (auto Fragment = Expr->getFragmentInfo()) | ||||
1442 | verifyFragmentExpression(*GVE.getVariable(), *Fragment, &GVE); | ||||
1443 | } | ||||
1444 | } | ||||
1445 | |||||
1446 | void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { | ||||
1447 | AssertDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_APPLE_property)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1448 | if (auto *T = N.getRawType()) | ||||
1449 | AssertDI(isType(T), "invalid type ref", &N, T)do { if (!(isType(T))) { DebugInfoCheckFailed("invalid type ref" , &N, T); return; } } while (false); | ||||
1450 | if (auto *F = N.getRawFile()) | ||||
1451 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1452 | } | ||||
1453 | |||||
1454 | void Verifier::visitDIImportedEntity(const DIImportedEntity &N) { | ||||
1455 | AssertDI(N.getTag() == dwarf::DW_TAG_imported_module ||do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1456 | N.getTag() == dwarf::DW_TAG_imported_declaration,do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1457 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1458 | if (auto *S = N.getRawScope()) | ||||
1459 | AssertDI(isa<DIScope>(S), "invalid scope for imported entity", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope for imported entity" , &N, S); return; } } while (false); | ||||
1460 | AssertDI(isDINode(N.getRawEntity()), "invalid imported entity", &N,do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false) | ||||
1461 | N.getRawEntity())do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false); | ||||
1462 | } | ||||
1463 | |||||
1464 | void Verifier::visitComdat(const Comdat &C) { | ||||
1465 | // In COFF the Module is invalid if the GlobalValue has private linkage. | ||||
1466 | // Entities with private linkage don't have entries in the symbol table. | ||||
1467 | if (TT.isOSBinFormatCOFF()) | ||||
1468 | if (const GlobalValue *GV = M.getNamedValue(C.getName())) | ||||
1469 | Assert(!GV->hasPrivateLinkage(),do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false) | ||||
1470 | "comdat global value has private linkage", GV)do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false); | ||||
1471 | } | ||||
1472 | |||||
1473 | void Verifier::visitModuleIdents(const Module &M) { | ||||
1474 | const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); | ||||
1475 | if (!Idents) | ||||
1476 | return; | ||||
1477 | |||||
1478 | // llvm.ident takes a list of metadata entry. Each entry has only one string. | ||||
1479 | // Scan each llvm.ident entry and make sure that this requirement is met. | ||||
1480 | for (const MDNode *N : Idents->operands()) { | ||||
1481 | Assert(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.ident metadata" , N); return; } } while (false) | ||||
1482 | "incorrect number of operands in llvm.ident metadata", N)do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.ident metadata" , N); return; } } while (false); | ||||
1483 | Assert(dyn_cast_or_null<MDString>(N->getOperand(0)),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
1484 | ("invalid value for llvm.ident metadata entry operand"do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
1485 | "(the operand should be a string)"),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
1486 | N->getOperand(0))do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false); | ||||
1487 | } | ||||
1488 | } | ||||
1489 | |||||
1490 | void Verifier::visitModuleCommandLines(const Module &M) { | ||||
1491 | const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline"); | ||||
1492 | if (!CommandLines) | ||||
1493 | return; | ||||
1494 | |||||
1495 | // llvm.commandline takes a list of metadata entry. Each entry has only one | ||||
1496 | // string. Scan each llvm.commandline entry and make sure that this | ||||
1497 | // requirement is met. | ||||
1498 | for (const MDNode *N : CommandLines->operands()) { | ||||
1499 | Assert(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.commandline metadata" , N); return; } } while (false) | ||||
1500 | "incorrect number of operands in llvm.commandline metadata", N)do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.commandline metadata" , N); return; } } while (false); | ||||
1501 | Assert(dyn_cast_or_null<MDString>(N->getOperand(0)),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
1502 | ("invalid value for llvm.commandline metadata entry operand"do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
1503 | "(the operand should be a string)"),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
1504 | N->getOperand(0))do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false); | ||||
1505 | } | ||||
1506 | } | ||||
1507 | |||||
1508 | void Verifier::visitModuleFlags(const Module &M) { | ||||
1509 | const NamedMDNode *Flags = M.getModuleFlagsMetadata(); | ||||
1510 | if (!Flags) return; | ||||
1511 | |||||
1512 | // Scan each flag, and track the flags and requirements. | ||||
1513 | DenseMap<const MDString*, const MDNode*> SeenIDs; | ||||
1514 | SmallVector<const MDNode*, 16> Requirements; | ||||
1515 | for (const MDNode *MDN : Flags->operands()) | ||||
1516 | visitModuleFlag(MDN, SeenIDs, Requirements); | ||||
1517 | |||||
1518 | // Validate that the requirements in the module are valid. | ||||
1519 | for (const MDNode *Requirement : Requirements) { | ||||
1520 | const MDString *Flag = cast<MDString>(Requirement->getOperand(0)); | ||||
1521 | const Metadata *ReqValue = Requirement->getOperand(1); | ||||
1522 | |||||
1523 | const MDNode *Op = SeenIDs.lookup(Flag); | ||||
1524 | if (!Op) { | ||||
1525 | CheckFailed("invalid requirement on flag, flag is not present in module", | ||||
1526 | Flag); | ||||
1527 | continue; | ||||
1528 | } | ||||
1529 | |||||
1530 | if (Op->getOperand(2) != ReqValue) { | ||||
1531 | CheckFailed(("invalid requirement on flag, " | ||||
1532 | "flag does not have the required value"), | ||||
1533 | Flag); | ||||
1534 | continue; | ||||
1535 | } | ||||
1536 | } | ||||
1537 | } | ||||
1538 | |||||
1539 | void | ||||
1540 | Verifier::visitModuleFlag(const MDNode *Op, | ||||
1541 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
1542 | SmallVectorImpl<const MDNode *> &Requirements) { | ||||
1543 | // Each module flag should have three arguments, the merge behavior (a | ||||
1544 | // constant int), the flag ID (an MDString), and the value. | ||||
1545 | Assert(Op->getNumOperands() == 3,do { if (!(Op->getNumOperands() == 3)) { CheckFailed("incorrect number of operands in module flag" , Op); return; } } while (false) | ||||
1546 | "incorrect number of operands in module flag", Op)do { if (!(Op->getNumOperands() == 3)) { CheckFailed("incorrect number of operands in module flag" , Op); return; } } while (false); | ||||
1547 | Module::ModFlagBehavior MFB; | ||||
1548 | if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { | ||||
1549 | Assert(do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
1550 | mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0)),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
1551 | "invalid behavior operand in module flag (expected constant integer)",do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
1552 | Op->getOperand(0))do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false); | ||||
1553 | Assert(false,do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false) | ||||
1554 | "invalid behavior operand in module flag (unexpected constant)",do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false) | ||||
1555 | Op->getOperand(0))do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false); | ||||
1556 | } | ||||
1557 | MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1)); | ||||
1558 | Assert(ID, "invalid ID operand in module flag (expected metadata string)",do { if (!(ID)) { CheckFailed("invalid ID operand in module flag (expected metadata string)" , Op->getOperand(1)); return; } } while (false) | ||||
1559 | Op->getOperand(1))do { if (!(ID)) { CheckFailed("invalid ID operand in module flag (expected metadata string)" , Op->getOperand(1)); return; } } while (false); | ||||
1560 | |||||
1561 | // Sanity check the values for behaviors with additional requirements. | ||||
1562 | switch (MFB) { | ||||
1563 | case Module::Error: | ||||
1564 | case Module::Warning: | ||||
1565 | case Module::Override: | ||||
1566 | // These behavior types accept any value. | ||||
1567 | break; | ||||
1568 | |||||
1569 | case Module::Max: { | ||||
1570 | Assert(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false) | ||||
1571 | "invalid value for 'max' module flag (expected constant integer)",do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false) | ||||
1572 | Op->getOperand(2))do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false); | ||||
1573 | break; | ||||
1574 | } | ||||
1575 | |||||
1576 | case Module::Require: { | ||||
1577 | // The value should itself be an MDNode with two operands, a flag ID (an | ||||
1578 | // MDString), and a value. | ||||
1579 | MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2)); | ||||
1580 | Assert(Value && Value->getNumOperands() == 2,do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false) | ||||
1581 | "invalid value for 'require' module flag (expected metadata pair)",do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false) | ||||
1582 | Op->getOperand(2))do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false); | ||||
1583 | Assert(isa<MDString>(Value->getOperand(0)),do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
1584 | ("invalid value for 'require' module flag "do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
1585 | "(first value operand should be a string)"),do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
1586 | Value->getOperand(0))do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false); | ||||
1587 | |||||
1588 | // Append it to the list of requirements, to check once all module flags are | ||||
1589 | // scanned. | ||||
1590 | Requirements.push_back(Value); | ||||
1591 | break; | ||||
1592 | } | ||||
1593 | |||||
1594 | case Module::Append: | ||||
1595 | case Module::AppendUnique: { | ||||
1596 | // These behavior types require the operand be an MDNode. | ||||
1597 | Assert(isa<MDNode>(Op->getOperand(2)),do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
1598 | "invalid value for 'append'-type module flag "do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
1599 | "(expected a metadata node)",do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
1600 | Op->getOperand(2))do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false); | ||||
1601 | break; | ||||
1602 | } | ||||
1603 | } | ||||
1604 | |||||
1605 | // Unless this is a "requires" flag, check the ID is unique. | ||||
1606 | if (MFB != Module::Require) { | ||||
1607 | bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; | ||||
1608 | Assert(Inserted,do { if (!(Inserted)) { CheckFailed("module flag identifiers must be unique (or of 'require' type)" , ID); return; } } while (false) | ||||
1609 | "module flag identifiers must be unique (or of 'require' type)", ID)do { if (!(Inserted)) { CheckFailed("module flag identifiers must be unique (or of 'require' type)" , ID); return; } } while (false); | ||||
1610 | } | ||||
1611 | |||||
1612 | if (ID->getString() == "wchar_size") { | ||||
1613 | ConstantInt *Value | ||||
1614 | = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
1615 | Assert(Value, "wchar_size metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("wchar_size metadata requires constant integer argument" ); return; } } while (false); | ||||
1616 | } | ||||
1617 | |||||
1618 | if (ID->getString() == "Linker Options") { | ||||
1619 | // If the llvm.linker.options named metadata exists, we assume that the | ||||
1620 | // bitcode reader has upgraded the module flag. Otherwise the flag might | ||||
1621 | // have been created by a client directly. | ||||
1622 | Assert(M.getNamedMetadata("llvm.linker.options"),do { if (!(M.getNamedMetadata("llvm.linker.options"))) { CheckFailed ("'Linker Options' named metadata no longer supported"); return ; } } while (false) | ||||
1623 | "'Linker Options' named metadata no longer supported")do { if (!(M.getNamedMetadata("llvm.linker.options"))) { CheckFailed ("'Linker Options' named metadata no longer supported"); return ; } } while (false); | ||||
1624 | } | ||||
1625 | |||||
1626 | if (ID->getString() == "SemanticInterposition") { | ||||
1627 | ConstantInt *Value = | ||||
1628 | mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
1629 | Assert(Value,do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false) | ||||
1630 | "SemanticInterposition metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false); | ||||
1631 | } | ||||
1632 | |||||
1633 | if (ID->getString() == "CG Profile") { | ||||
1634 | for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands()) | ||||
1635 | visitModuleFlagCGProfileEntry(MDO); | ||||
1636 | } | ||||
1637 | } | ||||
1638 | |||||
1639 | void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) { | ||||
1640 | auto CheckFunction = [&](const MDOperand &FuncMDO) { | ||||
1641 | if (!FuncMDO) | ||||
1642 | return; | ||||
1643 | auto F = dyn_cast<ValueAsMetadata>(FuncMDO); | ||||
1644 | Assert(F && isa<Function>(F->getValue()->stripPointerCasts()),do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false) | ||||
1645 | "expected a Function or null", FuncMDO)do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false); | ||||
1646 | }; | ||||
1647 | auto Node = dyn_cast_or_null<MDNode>(MDO); | ||||
1648 | Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO)do { if (!(Node && Node->getNumOperands() == 3)) { CheckFailed("expected a MDNode triple", MDO); return; } } while (false); | ||||
1649 | CheckFunction(Node->getOperand(0)); | ||||
1650 | CheckFunction(Node->getOperand(1)); | ||||
1651 | auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2)); | ||||
1652 | Assert(Count && Count->getType()->isIntegerTy(),do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false) | ||||
1653 | "expected an integer constant", Node->getOperand(2))do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false); | ||||
1654 | } | ||||
1655 | |||||
1656 | void Verifier::verifyAttributeTypes(AttributeSet Attrs, const Value *V) { | ||||
1657 | for (Attribute A : Attrs) { | ||||
1658 | |||||
1659 | if (A.isStringAttribute()) { | ||||
1660 | #define GET_ATTR_NAMES | ||||
1661 | #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) | ||||
1662 | #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \ | ||||
1663 | if (A.getKindAsString() == #DISPLAY_NAME) { \ | ||||
1664 | auto V = A.getValueAsString(); \ | ||||
1665 | if (!(V.empty() || V == "true" || V == "false")) \ | ||||
1666 | CheckFailed("invalid value for '" #DISPLAY_NAME "' attribute: " + V + \ | ||||
1667 | ""); \ | ||||
1668 | } | ||||
1669 | |||||
1670 | #include "llvm/IR/Attributes.inc" | ||||
1671 | continue; | ||||
1672 | } | ||||
1673 | |||||
1674 | if (A.isIntAttribute() != Attribute::isIntAttrKind(A.getKindAsEnum())) { | ||||
1675 | CheckFailed("Attribute '" + A.getAsString() + "' should have an Argument", | ||||
1676 | V); | ||||
1677 | return; | ||||
1678 | } | ||||
1679 | } | ||||
1680 | } | ||||
1681 | |||||
1682 | // VerifyParameterAttrs - Check the given attributes for an argument or return | ||||
1683 | // value of the specified type. The value V is printed in error messages. | ||||
1684 | void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, | ||||
1685 | const Value *V) { | ||||
1686 | if (!Attrs.hasAttributes()) | ||||
1687 | return; | ||||
1688 | |||||
1689 | verifyAttributeTypes(Attrs, V); | ||||
1690 | |||||
1691 | for (Attribute Attr : Attrs) | ||||
1692 | Assert(Attr.isStringAttribute() ||do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
1693 | Attribute::canUseAsParamAttr(Attr.getKindAsEnum()),do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
1694 | "Attribute '" + Attr.getAsString() +do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
1695 | "' does not apply to parameters",do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
1696 | V)do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false); | ||||
1697 | |||||
1698 | if (Attrs.hasAttribute(Attribute::ImmArg)) { | ||||
1699 | Assert(Attrs.getNumAttributes() == 1,do { if (!(Attrs.getNumAttributes() == 1)) { CheckFailed("Attribute 'immarg' is incompatible with other attributes" , V); return; } } while (false) | ||||
1700 | "Attribute 'immarg' is incompatible with other attributes", V)do { if (!(Attrs.getNumAttributes() == 1)) { CheckFailed("Attribute 'immarg' is incompatible with other attributes" , V); return; } } while (false); | ||||
1701 | } | ||||
1702 | |||||
1703 | // Check for mutually incompatible attributes. Only inreg is compatible with | ||||
1704 | // sret. | ||||
1705 | unsigned AttrCount = 0; | ||||
1706 | AttrCount += Attrs.hasAttribute(Attribute::ByVal); | ||||
1707 | AttrCount += Attrs.hasAttribute(Attribute::InAlloca); | ||||
1708 | AttrCount += Attrs.hasAttribute(Attribute::Preallocated); | ||||
1709 | AttrCount += Attrs.hasAttribute(Attribute::StructRet) || | ||||
1710 | Attrs.hasAttribute(Attribute::InReg); | ||||
1711 | AttrCount += Attrs.hasAttribute(Attribute::Nest); | ||||
1712 | AttrCount += Attrs.hasAttribute(Attribute::ByRef); | ||||
1713 | Assert(AttrCount <= 1,do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
1714 | "Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', "do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
1715 | "'byref', and 'sret' are incompatible!",do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
1716 | V)do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false); | ||||
1717 | |||||
1718 | Assert(!(Attrs.hasAttribute(Attribute::InAlloca) &&do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
1719 | Attrs.hasAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
1720 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
1721 | "'inalloca and readonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
1722 | V)do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false); | ||||
1723 | |||||
1724 | Assert(!(Attrs.hasAttribute(Attribute::StructRet) &&do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
1725 | Attrs.hasAttribute(Attribute::Returned)),do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
1726 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
1727 | "'sret and returned' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
1728 | V)do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false); | ||||
1729 | |||||
1730 | Assert(!(Attrs.hasAttribute(Attribute::ZExt) &&do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
1731 | Attrs.hasAttribute(Attribute::SExt)),do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
1732 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
1733 | "'zeroext and signext' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
1734 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false); | ||||
1735 | |||||
1736 | Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
1737 | Attrs.hasAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
1738 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
1739 | "'readnone and readonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
1740 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false); | ||||
1741 | |||||
1742 | Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
1743 | Attrs.hasAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
1744 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
1745 | "'readnone and writeonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
1746 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false); | ||||
1747 | |||||
1748 | Assert(!(Attrs.hasAttribute(Attribute::ReadOnly) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
1749 | Attrs.hasAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
1750 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
1751 | "'readonly and writeonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
1752 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false); | ||||
1753 | |||||
1754 | Assert(!(Attrs.hasAttribute(Attribute::NoInline) &&do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
1755 | Attrs.hasAttribute(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
1756 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
1757 | "'noinline and alwaysinline' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
1758 | V)do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false); | ||||
1759 | |||||
1760 | AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty); | ||||
1761 | for (Attribute Attr : Attrs) { | ||||
1762 | if (!Attr.isStringAttribute() && | ||||
1763 | IncompatibleAttrs.contains(Attr.getKindAsEnum())) { | ||||
1764 | CheckFailed("Attribute '" + Attr.getAsString() + | ||||
1765 | "' applied to incompatible type!", V); | ||||
1766 | return; | ||||
1767 | } | ||||
1768 | } | ||||
1769 | |||||
1770 | if (PointerType *PTy = dyn_cast<PointerType>(Ty)) { | ||||
1771 | if (Attrs.hasAttribute(Attribute::ByVal)) { | ||||
1772 | SmallPtrSet<Type *, 4> Visited; | ||||
1773 | Assert(Attrs.getByValType()->isSized(&Visited),do { if (!(Attrs.getByValType()->isSized(&Visited))) { CheckFailed("Attribute 'byval' does not support unsized types!" , V); return; } } while (false) | ||||
1774 | "Attribute 'byval' does not support unsized types!", V)do { if (!(Attrs.getByValType()->isSized(&Visited))) { CheckFailed("Attribute 'byval' does not support unsized types!" , V); return; } } while (false); | ||||
1775 | } | ||||
1776 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
1777 | SmallPtrSet<Type *, 4> Visited; | ||||
1778 | Assert(Attrs.getByRefType()->isSized(&Visited),do { if (!(Attrs.getByRefType()->isSized(&Visited))) { CheckFailed("Attribute 'byref' does not support unsized types!" , V); return; } } while (false) | ||||
1779 | "Attribute 'byref' does not support unsized types!", V)do { if (!(Attrs.getByRefType()->isSized(&Visited))) { CheckFailed("Attribute 'byref' does not support unsized types!" , V); return; } } while (false); | ||||
1780 | } | ||||
1781 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
1782 | SmallPtrSet<Type *, 4> Visited; | ||||
1783 | Assert(Attrs.getInAllocaType()->isSized(&Visited),do { if (!(Attrs.getInAllocaType()->isSized(&Visited)) ) { CheckFailed("Attribute 'inalloca' does not support unsized types!" , V); return; } } while (false) | ||||
1784 | "Attribute 'inalloca' does not support unsized types!", V)do { if (!(Attrs.getInAllocaType()->isSized(&Visited)) ) { CheckFailed("Attribute 'inalloca' does not support unsized types!" , V); return; } } while (false); | ||||
1785 | } | ||||
1786 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
1787 | SmallPtrSet<Type *, 4> Visited; | ||||
1788 | Assert(Attrs.getPreallocatedType()->isSized(&Visited),do { if (!(Attrs.getPreallocatedType()->isSized(&Visited ))) { CheckFailed("Attribute 'preallocated' does not support unsized types!" , V); return; } } while (false) | ||||
1789 | "Attribute 'preallocated' does not support unsized types!", V)do { if (!(Attrs.getPreallocatedType()->isSized(&Visited ))) { CheckFailed("Attribute 'preallocated' does not support unsized types!" , V); return; } } while (false); | ||||
1790 | } | ||||
1791 | if (!PTy->isOpaque()) { | ||||
1792 | if (!isa<PointerType>(PTy->getElementType())) | ||||
1793 | Assert(!Attrs.hasAttribute(Attribute::SwiftError),do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
1794 | "Attribute 'swifterror' only applies to parameters "do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
1795 | "with pointer to pointer type!",do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
1796 | V)do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false); | ||||
1797 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
1798 | Assert(Attrs.getByRefType() == PTy->getElementType(),do { if (!(Attrs.getByRefType() == PTy->getElementType())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false) | ||||
1799 | "Attribute 'byref' type does not match parameter!", V)do { if (!(Attrs.getByRefType() == PTy->getElementType())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false); | ||||
1800 | } | ||||
1801 | |||||
1802 | if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) { | ||||
1803 | Assert(Attrs.getByValType() == PTy->getElementType(),do { if (!(Attrs.getByValType() == PTy->getElementType())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false) | ||||
1804 | "Attribute 'byval' type does not match parameter!", V)do { if (!(Attrs.getByValType() == PTy->getElementType())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false); | ||||
1805 | } | ||||
1806 | |||||
1807 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
1808 | Assert(Attrs.getPreallocatedType() == PTy->getElementType(),do { if (!(Attrs.getPreallocatedType() == PTy->getElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false) | ||||
1809 | "Attribute 'preallocated' type does not match parameter!", V)do { if (!(Attrs.getPreallocatedType() == PTy->getElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false); | ||||
1810 | } | ||||
1811 | |||||
1812 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
1813 | Assert(Attrs.getInAllocaType() == PTy->getElementType(),do { if (!(Attrs.getInAllocaType() == PTy->getElementType( ))) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false) | ||||
1814 | "Attribute 'inalloca' type does not match parameter!", V)do { if (!(Attrs.getInAllocaType() == PTy->getElementType( ))) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false); | ||||
1815 | } | ||||
1816 | |||||
1817 | if (Attrs.hasAttribute(Attribute::ElementType)) { | ||||
1818 | Assert(Attrs.getElementType() == PTy->getElementType(),do { if (!(Attrs.getElementType() == PTy->getElementType() )) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false) | ||||
1819 | "Attribute 'elementtype' type does not match parameter!", V)do { if (!(Attrs.getElementType() == PTy->getElementType() )) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false); | ||||
1820 | } | ||||
1821 | } | ||||
1822 | } | ||||
1823 | } | ||||
1824 | |||||
1825 | void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
1826 | const Value *V) { | ||||
1827 | if (Attrs.hasFnAttr(Attr)) { | ||||
1828 | StringRef S = Attrs.getFnAttr(Attr).getValueAsString(); | ||||
1829 | unsigned N; | ||||
1830 | if (S.getAsInteger(10, N)) | ||||
1831 | CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, V); | ||||
1832 | } | ||||
1833 | } | ||||
1834 | |||||
1835 | // Check parameter attributes against a function type. | ||||
1836 | // The value V is printed in error messages. | ||||
1837 | void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
1838 | const Value *V, bool IsIntrinsic) { | ||||
1839 | if (Attrs.isEmpty()) | ||||
1840 | return; | ||||
1841 | |||||
1842 | if (AttributeListsVisited.insert(Attrs.getRawPointer()).second) { | ||||
1843 | Assert(Attrs.hasParentContext(Context),do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false) | ||||
1844 | "Attribute list does not match Module context!", &Attrs, V)do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false); | ||||
1845 | for (const auto &AttrSet : Attrs) { | ||||
1846 | Assert(!AttrSet.hasAttributes() || AttrSet.hasParentContext(Context),do { if (!(!AttrSet.hasAttributes() || AttrSet.hasParentContext (Context))) { CheckFailed("Attribute set does not match Module context!" , &AttrSet, V); return; } } while (false) | ||||
1847 | "Attribute set does not match Module context!", &AttrSet, V)do { if (!(!AttrSet.hasAttributes() || AttrSet.hasParentContext (Context))) { CheckFailed("Attribute set does not match Module context!" , &AttrSet, V); return; } } while (false); | ||||
1848 | for (const auto &A : AttrSet) { | ||||
1849 | Assert(A.hasParentContext(Context),do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false) | ||||
1850 | "Attribute does not match Module context!", &A, V)do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false); | ||||
1851 | } | ||||
1852 | } | ||||
1853 | } | ||||
1854 | |||||
1855 | bool SawNest = false; | ||||
1856 | bool SawReturned = false; | ||||
1857 | bool SawSRet = false; | ||||
1858 | bool SawSwiftSelf = false; | ||||
1859 | bool SawSwiftAsync = false; | ||||
1860 | bool SawSwiftError = false; | ||||
1861 | |||||
1862 | // Verify return value attributes. | ||||
1863 | AttributeSet RetAttrs = Attrs.getRetAttrs(); | ||||
1864 | for (Attribute RetAttr : RetAttrs) | ||||
1865 | Assert(RetAttr.isStringAttribute() ||do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
1866 | Attribute::canUseAsRetAttr(RetAttr.getKindAsEnum()),do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
1867 | "Attribute '" + RetAttr.getAsString() +do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
1868 | "' does not apply to function return values",do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
1869 | V)do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false); | ||||
1870 | |||||
1871 | verifyParameterAttrs(RetAttrs, FT->getReturnType(), V); | ||||
1872 | |||||
1873 | // Verify parameter attributes. | ||||
1874 | for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { | ||||
1875 | Type *Ty = FT->getParamType(i); | ||||
1876 | AttributeSet ArgAttrs = Attrs.getParamAttrs(i); | ||||
1877 | |||||
1878 | if (!IsIntrinsic) { | ||||
1879 | Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg),do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics",V); return; } } while (false) | ||||
1880 | "immarg attribute only applies to intrinsics",V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics",V); return; } } while (false); | ||||
1881 | Assert(!ArgAttrs.hasAttribute(Attribute::ElementType),do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics." , V); return; } } while (false) | ||||
1882 | "Attribute 'elementtype' can only be applied to intrinsics.", V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics." , V); return; } } while (false); | ||||
1883 | } | ||||
1884 | |||||
1885 | verifyParameterAttrs(ArgAttrs, Ty, V); | ||||
1886 | |||||
1887 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
1888 | Assert(!SawNest, "More than one parameter has attribute nest!", V)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , V); return; } } while (false); | ||||
1889 | SawNest = true; | ||||
1890 | } | ||||
1891 | |||||
1892 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
1893 | Assert(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false) | ||||
1894 | V)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false); | ||||
1895 | Assert(Ty->canLosslesslyBitCastTo(FT->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
1896 | "Incompatible argument and return types for 'returned' attribute",do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
1897 | V)do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false); | ||||
1898 | SawReturned = true; | ||||
1899 | } | ||||
1900 | |||||
1901 | if (ArgAttrs.hasAttribute(Attribute::StructRet)) { | ||||
1902 | Assert(!SawSRet, "Cannot have multiple 'sret' parameters!", V)do { if (!(!SawSRet)) { CheckFailed("Cannot have multiple 'sret' parameters!" , V); return; } } while (false); | ||||
1903 | Assert(i == 0 || i == 1,do { if (!(i == 0 || i == 1)) { CheckFailed("Attribute 'sret' is not on first or second parameter!" , V); return; } } while (false) | ||||
1904 | "Attribute 'sret' is not on first or second parameter!", V)do { if (!(i == 0 || i == 1)) { CheckFailed("Attribute 'sret' is not on first or second parameter!" , V); return; } } while (false); | ||||
1905 | SawSRet = true; | ||||
1906 | } | ||||
1907 | |||||
1908 | if (ArgAttrs.hasAttribute(Attribute::SwiftSelf)) { | ||||
1909 | Assert(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V)do { if (!(!SawSwiftSelf)) { CheckFailed("Cannot have multiple 'swiftself' parameters!" , V); return; } } while (false); | ||||
1910 | SawSwiftSelf = true; | ||||
1911 | } | ||||
1912 | |||||
1913 | if (ArgAttrs.hasAttribute(Attribute::SwiftAsync)) { | ||||
1914 | Assert(!SawSwiftAsync, "Cannot have multiple 'swiftasync' parameters!", V)do { if (!(!SawSwiftAsync)) { CheckFailed("Cannot have multiple 'swiftasync' parameters!" , V); return; } } while (false); | ||||
1915 | SawSwiftAsync = true; | ||||
1916 | } | ||||
1917 | |||||
1918 | if (ArgAttrs.hasAttribute(Attribute::SwiftError)) { | ||||
1919 | Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!",do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false) | ||||
1920 | V)do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false); | ||||
1921 | SawSwiftError = true; | ||||
1922 | } | ||||
1923 | |||||
1924 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) { | ||||
1925 | Assert(i == FT->getNumParams() - 1,do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false) | ||||
1926 | "inalloca isn't on the last parameter!", V)do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false); | ||||
1927 | } | ||||
1928 | } | ||||
1929 | |||||
1930 | if (!Attrs.hasFnAttrs()) | ||||
1931 | return; | ||||
1932 | |||||
1933 | verifyAttributeTypes(Attrs.getFnAttrs(), V); | ||||
1934 | for (Attribute FnAttr : Attrs.getFnAttrs()) | ||||
1935 | Assert(FnAttr.isStringAttribute() ||do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
1936 | Attribute::canUseAsFnAttr(FnAttr.getKindAsEnum()),do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
1937 | "Attribute '" + FnAttr.getAsString() +do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
1938 | "' does not apply to functions!",do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
1939 | V)do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false); | ||||
1940 | |||||
1941 | Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false) | ||||
1942 | Attrs.hasFnAttr(Attribute::ReadOnly)),do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false) | ||||
1943 | "Attributes 'readnone and readonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false); | ||||
1944 | |||||
1945 | Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::WriteOnly)))) { CheckFailed("Attributes 'readnone and writeonly' are incompatible!" , V); return; } } while (false) | ||||
1946 | Attrs.hasFnAttr(Attribute::WriteOnly)),do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::WriteOnly)))) { CheckFailed("Attributes 'readnone and writeonly' are incompatible!" , V); return; } } while (false) | ||||
1947 | "Attributes 'readnone and writeonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::WriteOnly)))) { CheckFailed("Attributes 'readnone and writeonly' are incompatible!" , V); return; } } while (false); | ||||
1948 | |||||
1949 | Assert(!(Attrs.hasFnAttr(Attribute::ReadOnly) &&do { if (!(!(Attrs.hasFnAttr(Attribute::ReadOnly) && Attrs .hasFnAttr(Attribute::WriteOnly)))) { CheckFailed("Attributes 'readonly and writeonly' are incompatible!" , V); return; } } while (false) | ||||
1950 | Attrs.hasFnAttr(Attribute::WriteOnly)),do { if (!(!(Attrs.hasFnAttr(Attribute::ReadOnly) && Attrs .hasFnAttr(Attribute::WriteOnly)))) { CheckFailed("Attributes 'readonly and writeonly' are incompatible!" , V); return; } } while (false) | ||||
1951 | "Attributes 'readonly and writeonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttr(Attribute::ReadOnly) && Attrs .hasFnAttr(Attribute::WriteOnly)))) { CheckFailed("Attributes 'readonly and writeonly' are incompatible!" , V); return; } } while (false); | ||||
1952 | |||||
1953 | Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1954 | Attrs.hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)),do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1955 | "Attributes 'readnone and inaccessiblemem_or_argmemonly' are "do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1956 | "incompatible!",do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1957 | V)do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false); | ||||
1958 | |||||
1959 | Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOnly)))) { CheckFailed("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false) | ||||
1960 | Attrs.hasFnAttr(Attribute::InaccessibleMemOnly)),do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOnly)))) { CheckFailed("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false) | ||||
1961 | "Attributes 'readnone and inaccessiblememonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttr(Attribute::ReadNone) && Attrs .hasFnAttr(Attribute::InaccessibleMemOnly)))) { CheckFailed("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false); | ||||
1962 | |||||
1963 | Assert(!(Attrs.hasFnAttr(Attribute::NoInline) &&do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
1964 | Attrs.hasFnAttr(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
1965 | "Attributes 'noinline and alwaysinline' are incompatible!", V)do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false); | ||||
1966 | |||||
1967 | if (Attrs.hasFnAttr(Attribute::OptimizeNone)) { | ||||
1968 | Assert(Attrs.hasFnAttr(Attribute::NoInline),do { if (!(Attrs.hasFnAttr(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false) | ||||
1969 | "Attribute 'optnone' requires 'noinline'!", V)do { if (!(Attrs.hasFnAttr(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false); | ||||
1970 | |||||
1971 | Assert(!Attrs.hasFnAttr(Attribute::OptimizeForSize),do { if (!(!Attrs.hasFnAttr(Attribute::OptimizeForSize))) { CheckFailed ("Attributes 'optsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
1972 | "Attributes 'optsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttr(Attribute::OptimizeForSize))) { CheckFailed ("Attributes 'optsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
1973 | |||||
1974 | Assert(!Attrs.hasFnAttr(Attribute::MinSize),do { if (!(!Attrs.hasFnAttr(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
1975 | "Attributes 'minsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttr(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
1976 | } | ||||
1977 | |||||
1978 | if (Attrs.hasFnAttr(Attribute::JumpTable)) { | ||||
1979 | const GlobalValue *GV = cast<GlobalValue>(V); | ||||
1980 | Assert(GV->hasGlobalUnnamedAddr(),do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false) | ||||
1981 | "Attribute 'jumptable' requires 'unnamed_addr'", V)do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false); | ||||
1982 | } | ||||
1983 | |||||
1984 | if (Attrs.hasFnAttr(Attribute::AllocSize)) { | ||||
1985 | std::pair<unsigned, Optional<unsigned>> Args = | ||||
1986 | Attrs.getFnAttrs().getAllocSizeArgs(); | ||||
1987 | |||||
1988 | auto CheckParam = [&](StringRef Name, unsigned ParamNo) { | ||||
1989 | if (ParamNo >= FT->getNumParams()) { | ||||
1990 | CheckFailed("'allocsize' " + Name + " argument is out of bounds", V); | ||||
1991 | return false; | ||||
1992 | } | ||||
1993 | |||||
1994 | if (!FT->getParamType(ParamNo)->isIntegerTy()) { | ||||
1995 | CheckFailed("'allocsize' " + Name + | ||||
1996 | " argument must refer to an integer parameter", | ||||
1997 | V); | ||||
1998 | return false; | ||||
1999 | } | ||||
2000 | |||||
2001 | return true; | ||||
2002 | }; | ||||
2003 | |||||
2004 | if (!CheckParam("element size", Args.first)) | ||||
2005 | return; | ||||
2006 | |||||
2007 | if (Args.second && !CheckParam("number of elements", *Args.second)) | ||||
2008 | return; | ||||
2009 | } | ||||
2010 | |||||
2011 | if (Attrs.hasFnAttr(Attribute::VScaleRange)) { | ||||
2012 | std::pair<unsigned, unsigned> Args = | ||||
2013 | Attrs.getFnAttrs().getVScaleRangeArgs(); | ||||
2014 | |||||
2015 | if (Args.first > Args.second && Args.second != 0) | ||||
2016 | CheckFailed("'vscale_range' minimum cannot be greater than maximum", V); | ||||
2017 | } | ||||
2018 | |||||
2019 | if (Attrs.hasFnAttr("frame-pointer")) { | ||||
2020 | StringRef FP = Attrs.getFnAttr("frame-pointer").getValueAsString(); | ||||
2021 | if (FP != "all" && FP != "non-leaf" && FP != "none") | ||||
2022 | CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V); | ||||
2023 | } | ||||
2024 | |||||
2025 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V); | ||||
2026 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V); | ||||
2027 | checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", V); | ||||
2028 | } | ||||
2029 | |||||
2030 | void Verifier::verifyFunctionMetadata( | ||||
2031 | ArrayRef<std::pair<unsigned, MDNode *>> MDs) { | ||||
2032 | for (const auto &Pair : MDs) { | ||||
2033 | if (Pair.first == LLVMContext::MD_prof) { | ||||
2034 | MDNode *MD = Pair.second; | ||||
2035 | Assert(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
2036 | "!prof annotations should have no less than 2 operands", MD)do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false); | ||||
2037 | |||||
2038 | // Check first operand. | ||||
2039 | Assert(MD->getOperand(0) != nullptr, "first operand should not be null",do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false) | ||||
2040 | MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
2041 | Assert(isa<MDString>(MD->getOperand(0)),do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false) | ||||
2042 | "expected string with name of the !prof annotation", MD)do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false); | ||||
2043 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
2044 | StringRef ProfName = MDS->getString(); | ||||
2045 | Assert(ProfName.equals("function_entry_count") ||do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
2046 | ProfName.equals("synthetic_function_entry_count"),do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
2047 | "first operand should be 'function_entry_count'"do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
2048 | " or 'synthetic_function_entry_count'",do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
2049 | MD)do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false); | ||||
2050 | |||||
2051 | // Check second operand. | ||||
2052 | Assert(MD->getOperand(1) != nullptr, "second operand should not be null",do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false) | ||||
2053 | MD)do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
2054 | Assert(isa<ConstantAsMetadata>(MD->getOperand(1)),do { if (!(isa<ConstantAsMetadata>(MD->getOperand(1) ))) { CheckFailed("expected integer argument to function_entry_count" , MD); return; } } while (false) | ||||
2055 | "expected integer argument to function_entry_count", MD)do { if (!(isa<ConstantAsMetadata>(MD->getOperand(1) ))) { CheckFailed("expected integer argument to function_entry_count" , MD); return; } } while (false); | ||||
2056 | } | ||||
2057 | } | ||||
2058 | } | ||||
2059 | |||||
2060 | void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { | ||||
2061 | if (!ConstantExprVisited.insert(EntryC).second) | ||||
2062 | return; | ||||
2063 | |||||
2064 | SmallVector<const Constant *, 16> Stack; | ||||
2065 | Stack.push_back(EntryC); | ||||
2066 | |||||
2067 | while (!Stack.empty()) { | ||||
2068 | const Constant *C = Stack.pop_back_val(); | ||||
2069 | |||||
2070 | // Check this constant expression. | ||||
2071 | if (const auto *CE = dyn_cast<ConstantExpr>(C)) | ||||
2072 | visitConstantExpr(CE); | ||||
2073 | |||||
2074 | if (const auto *GV = dyn_cast<GlobalValue>(C)) { | ||||
2075 | // Global Values get visited separately, but we do need to make sure | ||||
2076 | // that the global value is in the correct module | ||||
2077 | Assert(GV->getParent() == &M, "Referencing global in another module!",do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false) | ||||
2078 | EntryC, &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false); | ||||
2079 | continue; | ||||
2080 | } | ||||
2081 | |||||
2082 | // Visit all sub-expressions. | ||||
2083 | for (const Use &U : C->operands()) { | ||||
2084 | const auto *OpC = dyn_cast<Constant>(U); | ||||
2085 | if (!OpC) | ||||
2086 | continue; | ||||
2087 | if (!ConstantExprVisited.insert(OpC).second) | ||||
2088 | continue; | ||||
2089 | Stack.push_back(OpC); | ||||
2090 | } | ||||
2091 | } | ||||
2092 | } | ||||
2093 | |||||
2094 | void Verifier::visitConstantExpr(const ConstantExpr *CE) { | ||||
2095 | if (CE->getOpcode() == Instruction::BitCast) | ||||
2096 | Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
2097 | CE->getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
2098 | "Invalid bitcast", CE)do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false); | ||||
2099 | } | ||||
2100 | |||||
2101 | bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) { | ||||
2102 | // There shouldn't be more attribute sets than there are parameters plus the | ||||
2103 | // function and return value. | ||||
2104 | return Attrs.getNumAttrSets() <= Params + 2; | ||||
2105 | } | ||||
2106 | |||||
2107 | /// Verify that statepoint intrinsic is well formed. | ||||
2108 | void Verifier::verifyStatepoint(const CallBase &Call) { | ||||
2109 | assert(Call.getCalledFunction() &&(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 2111, __extension__ __PRETTY_FUNCTION__)) | ||||
2110 | Call.getCalledFunction()->getIntrinsicID() ==(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 2111, __extension__ __PRETTY_FUNCTION__)) | ||||
2111 | Intrinsic::experimental_gc_statepoint)(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 2111, __extension__ __PRETTY_FUNCTION__)); | ||||
2112 | |||||
2113 | Assert(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory() &&do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
2114 | !Call.onlyAccessesArgMemory(),do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
2115 | "gc.statepoint must read and write all memory to preserve "do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
2116 | "reordering restrictions required by safepoint semantics",do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
2117 | Call)do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false); | ||||
2118 | |||||
2119 | const int64_t NumPatchBytes = | ||||
2120 | cast<ConstantInt>(Call.getArgOperand(1))->getSExtValue(); | ||||
2121 | assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!")(static_cast <bool> (isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!") ? void (0) : __assert_fail ("isInt<32>(NumPatchBytes) && \"NumPatchBytesV is an i32!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 2121, __extension__ __PRETTY_FUNCTION__)); | ||||
2122 | Assert(NumPatchBytes >= 0,do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
2123 | "gc.statepoint number of patchable bytes must be "do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
2124 | "positive",do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
2125 | Call)do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false); | ||||
2126 | |||||
2127 | const Value *Target = Call.getArgOperand(2); | ||||
2128 | auto *PT = dyn_cast<PointerType>(Target->getType()); | ||||
2129 | Assert(PT && PT->getElementType()->isFunctionTy(),do { if (!(PT && PT->getElementType()->isFunctionTy ())) { CheckFailed("gc.statepoint callee must be of function pointer type" , Call, Target); return; } } while (false) | ||||
2130 | "gc.statepoint callee must be of function pointer type", Call, Target)do { if (!(PT && PT->getElementType()->isFunctionTy ())) { CheckFailed("gc.statepoint callee must be of function pointer type" , Call, Target); return; } } while (false); | ||||
2131 | FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType()); | ||||
2132 | |||||
2133 | const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue(); | ||||
2134 | Assert(NumCallArgs >= 0,do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
2135 | "gc.statepoint number of arguments to underlying call "do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
2136 | "must be positive",do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
2137 | Call)do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false); | ||||
2138 | const int NumParams = (int)TargetFuncType->getNumParams(); | ||||
2139 | if (TargetFuncType->isVarArg()) { | ||||
2140 | Assert(NumCallArgs >= NumParams,do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false) | ||||
2141 | "gc.statepoint mismatch in number of vararg call args", Call)do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false); | ||||
2142 | |||||
2143 | // TODO: Remove this limitation | ||||
2144 | Assert(TargetFuncType->getReturnType()->isVoidTy(),do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
2145 | "gc.statepoint doesn't support wrapping non-void "do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
2146 | "vararg functions yet",do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
2147 | Call)do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false); | ||||
2148 | } else | ||||
2149 | Assert(NumCallArgs == NumParams,do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false) | ||||
2150 | "gc.statepoint mismatch in number of call args", Call)do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false); | ||||
2151 | |||||
2152 | const uint64_t Flags | ||||
2153 | = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue(); | ||||
2154 | Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0,do { if (!((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)) { CheckFailed("unknown flag used in gc.statepoint flags argument" , Call); return; } } while (false) | ||||
2155 | "unknown flag used in gc.statepoint flags argument", Call)do { if (!((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)) { CheckFailed("unknown flag used in gc.statepoint flags argument" , Call); return; } } while (false); | ||||
2156 | |||||
2157 | // Verify that the types of the call parameter arguments match | ||||
2158 | // the type of the wrapped callee. | ||||
2159 | AttributeList Attrs = Call.getAttributes(); | ||||
2160 | for (int i = 0; i < NumParams; i++) { | ||||
2161 | Type *ParamType = TargetFuncType->getParamType(i); | ||||
2162 | Type *ArgType = Call.getArgOperand(5 + i)->getType(); | ||||
2163 | Assert(ArgType == ParamType,do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
2164 | "gc.statepoint call argument does not match wrapped "do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
2165 | "function type",do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
2166 | Call)do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false); | ||||
2167 | |||||
2168 | if (TargetFuncType->isVarArg()) { | ||||
2169 | AttributeSet ArgAttrs = Attrs.getParamAttrs(5 + i); | ||||
2170 | Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
2171 | "Attribute 'sret' cannot be used for vararg call arguments!",do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
2172 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
2173 | } | ||||
2174 | } | ||||
2175 | |||||
2176 | const int EndCallArgsInx = 4 + NumCallArgs; | ||||
2177 | |||||
2178 | const Value *NumTransitionArgsV = Call.getArgOperand(EndCallArgsInx + 1); | ||||
2179 | Assert(isa<ConstantInt>(NumTransitionArgsV),do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2180 | "gc.statepoint number of transition arguments "do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2181 | "must be constant integer",do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2182 | Call)do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false); | ||||
2183 | const int NumTransitionArgs = | ||||
2184 | cast<ConstantInt>(NumTransitionArgsV)->getZExtValue(); | ||||
2185 | Assert(NumTransitionArgs == 0,do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false) | ||||
2186 | "gc.statepoint w/inline transition bundle is deprecated", Call)do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false); | ||||
2187 | const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; | ||||
2188 | |||||
2189 | const Value *NumDeoptArgsV = Call.getArgOperand(EndTransitionArgsInx + 1); | ||||
2190 | Assert(isa<ConstantInt>(NumDeoptArgsV),do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2191 | "gc.statepoint number of deoptimization arguments "do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2192 | "must be constant integer",do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2193 | Call)do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false); | ||||
2194 | const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue(); | ||||
2195 | Assert(NumDeoptArgs == 0,do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false) | ||||
2196 | "gc.statepoint w/inline deopt operands is deprecated", Call)do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false); | ||||
2197 | |||||
2198 | const int ExpectedNumArgs = 7 + NumCallArgs; | ||||
2199 | Assert(ExpectedNumArgs == (int)Call.arg_size(),do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false) | ||||
2200 | "gc.statepoint too many arguments", Call)do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false); | ||||
2201 | |||||
2202 | // Check that the only uses of this gc.statepoint are gc.result or | ||||
2203 | // gc.relocate calls which are tied to this statepoint and thus part | ||||
2204 | // of the same statepoint sequence | ||||
2205 | for (const User *U : Call.users()) { | ||||
2206 | const CallInst *UserCall = dyn_cast<const CallInst>(U); | ||||
2207 | Assert(UserCall, "illegal use of statepoint token", Call, U)do { if (!(UserCall)) { CheckFailed("illegal use of statepoint token" , Call, U); return; } } while (false); | ||||
2208 | if (!UserCall) | ||||
2209 | continue; | ||||
2210 | Assert(isa<GCRelocateInst>(UserCall) || isa<GCResultInst>(UserCall),do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
2211 | "gc.result or gc.relocate are the only value uses "do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
2212 | "of a gc.statepoint",do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
2213 | Call, U)do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false); | ||||
2214 | if (isa<GCResultInst>(UserCall)) { | ||||
2215 | Assert(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
2216 | "gc.result connected to wrong gc.statepoint", Call, UserCall)do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false); | ||||
2217 | } else if (isa<GCRelocateInst>(Call)) { | ||||
2218 | Assert(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
2219 | "gc.relocate connected to wrong gc.statepoint", Call, UserCall)do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false); | ||||
2220 | } | ||||
2221 | } | ||||
2222 | |||||
2223 | // Note: It is legal for a single derived pointer to be listed multiple | ||||
2224 | // times. It's non-optimal, but it is legal. It can also happen after | ||||
2225 | // insertion if we strip a bitcast away. | ||||
2226 | // Note: It is really tempting to check that each base is relocated and | ||||
2227 | // that a derived pointer is never reused as a base pointer. This turns | ||||
2228 | // out to be problematic since optimizations run after safepoint insertion | ||||
2229 | // can recognize equality properties that the insertion logic doesn't know | ||||
2230 | // about. See example statepoint.ll in the verifier subdirectory | ||||
2231 | } | ||||
2232 | |||||
2233 | void Verifier::verifyFrameRecoverIndices() { | ||||
2234 | for (auto &Counts : FrameEscapeInfo) { | ||||
2235 | Function *F = Counts.first; | ||||
2236 | unsigned EscapedObjectCount = Counts.second.first; | ||||
2237 | unsigned MaxRecoveredIndex = Counts.second.second; | ||||
2238 | Assert(MaxRecoveredIndex <= EscapedObjectCount,do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
2239 | "all indices passed to llvm.localrecover must be less than the "do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
2240 | "number of arguments passed to llvm.localescape in the parent "do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
2241 | "function",do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
2242 | F)do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false); | ||||
2243 | } | ||||
2244 | } | ||||
2245 | |||||
2246 | static Instruction *getSuccPad(Instruction *Terminator) { | ||||
2247 | BasicBlock *UnwindDest; | ||||
2248 | if (auto *II = dyn_cast<InvokeInst>(Terminator)) | ||||
2249 | UnwindDest = II->getUnwindDest(); | ||||
2250 | else if (auto *CSI = dyn_cast<CatchSwitchInst>(Terminator)) | ||||
2251 | UnwindDest = CSI->getUnwindDest(); | ||||
2252 | else | ||||
2253 | UnwindDest = cast<CleanupReturnInst>(Terminator)->getUnwindDest(); | ||||
2254 | return UnwindDest->getFirstNonPHI(); | ||||
2255 | } | ||||
2256 | |||||
2257 | void Verifier::verifySiblingFuncletUnwinds() { | ||||
2258 | SmallPtrSet<Instruction *, 8> Visited; | ||||
2259 | SmallPtrSet<Instruction *, 8> Active; | ||||
2260 | for (const auto &Pair : SiblingFuncletInfo) { | ||||
2261 | Instruction *PredPad = Pair.first; | ||||
2262 | if (Visited.count(PredPad)) | ||||
2263 | continue; | ||||
2264 | Active.insert(PredPad); | ||||
2265 | Instruction *Terminator = Pair.second; | ||||
2266 | do { | ||||
2267 | Instruction *SuccPad = getSuccPad(Terminator); | ||||
2268 | if (Active.count(SuccPad)) { | ||||
2269 | // Found a cycle; report error | ||||
2270 | Instruction *CyclePad = SuccPad; | ||||
2271 | SmallVector<Instruction *, 8> CycleNodes; | ||||
2272 | do { | ||||
2273 | CycleNodes.push_back(CyclePad); | ||||
2274 | Instruction *CycleTerminator = SiblingFuncletInfo[CyclePad]; | ||||
2275 | if (CycleTerminator != CyclePad) | ||||
2276 | CycleNodes.push_back(CycleTerminator); | ||||
2277 | CyclePad = getSuccPad(CycleTerminator); | ||||
2278 | } while (CyclePad != SuccPad); | ||||
2279 | Assert(false, "EH pads can't handle each other's exceptions",do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false) | ||||
2280 | ArrayRef<Instruction *>(CycleNodes))do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false); | ||||
2281 | } | ||||
2282 | // Don't re-walk a node we've already checked | ||||
2283 | if (!Visited.insert(SuccPad).second) | ||||
2284 | break; | ||||
2285 | // Walk to this successor if it has a map entry. | ||||
2286 | PredPad = SuccPad; | ||||
2287 | auto TermI = SiblingFuncletInfo.find(PredPad); | ||||
2288 | if (TermI == SiblingFuncletInfo.end()) | ||||
2289 | break; | ||||
2290 | Terminator = TermI->second; | ||||
2291 | Active.insert(PredPad); | ||||
2292 | } while (true); | ||||
2293 | // Each node only has one successor, so we've walked all the active | ||||
2294 | // nodes' successors. | ||||
2295 | Active.clear(); | ||||
2296 | } | ||||
2297 | } | ||||
2298 | |||||
2299 | // visitFunction - Verify that a function is ok. | ||||
2300 | // | ||||
2301 | void Verifier::visitFunction(const Function &F) { | ||||
2302 | visitGlobalValue(F); | ||||
2303 | |||||
2304 | // Check function arguments. | ||||
2305 | FunctionType *FT = F.getFunctionType(); | ||||
2306 | unsigned NumArgs = F.arg_size(); | ||||
2307 | |||||
2308 | Assert(&Context == &F.getContext(),do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false) | ||||
| |||||
2309 | "Function context does not match Module context!", &F)do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false); | ||||
2310 | |||||
2311 | Assert(!F.hasCommonLinkage(), "Functions may not have common linkage", &F)do { if (!(!F.hasCommonLinkage())) { CheckFailed("Functions may not have common linkage" , &F); return; } } while (false); | ||||
2312 | Assert(FT->getNumParams() == NumArgs,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
2313 | "# formal arguments must match # of arguments for function type!", &F,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
2314 | FT)do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false); | ||||
2315 | Assert(F.getReturnType()->isFirstClassType() ||do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false) | ||||
2316 | F.getReturnType()->isVoidTy() || F.getReturnType()->isStructTy(),do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false) | ||||
2317 | "Functions cannot return aggregate values!", &F)do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false); | ||||
2318 | |||||
2319 | Assert(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false) | ||||
2320 | "Invalid struct return type!", &F)do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false); | ||||
2321 | |||||
2322 | AttributeList Attrs = F.getAttributes(); | ||||
2323 | |||||
2324 | Assert(verifyAttributeCount(Attrs, FT->getNumParams()),do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false) | ||||
2325 | "Attribute after last parameter!", &F)do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false); | ||||
2326 | |||||
2327 | bool IsIntrinsic = F.isIntrinsic(); | ||||
2328 | |||||
2329 | // Check function attributes. | ||||
2330 | verifyFunctionAttrs(FT, Attrs, &F, IsIntrinsic); | ||||
2331 | |||||
2332 | // On function declarations/definitions, we do not support the builtin | ||||
2333 | // attribute. We do not check this in VerifyFunctionAttrs since that is | ||||
2334 | // checking for Attributes that can/can not ever be on functions. | ||||
2335 | Assert(!Attrs.hasFnAttr(Attribute::Builtin),do { if (!(!Attrs.hasFnAttr(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false) | ||||
2336 | "Attribute 'builtin' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasFnAttr(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false); | ||||
2337 | |||||
2338 | Assert(!Attrs.hasAttrSomewhere(Attribute::ElementType),do { if (!(!Attrs.hasAttrSomewhere(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to a callsite." , &F); return; } } while (false) | ||||
2339 | "Attribute 'elementtype' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasAttrSomewhere(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to a callsite." , &F); return; } } while (false); | ||||
2340 | |||||
2341 | // Check that this function meets the restrictions on this calling convention. | ||||
2342 | // Sometimes varargs is used for perfectly forwarding thunks, so some of these | ||||
2343 | // restrictions can be lifted. | ||||
2344 | switch (F.getCallingConv()) { | ||||
2345 | default: | ||||
2346 | case CallingConv::C: | ||||
2347 | break; | ||||
2348 | case CallingConv::X86_INTR: { | ||||
2349 | Assert(F.arg_empty() || Attrs.hasParamAttr(0, Attribute::ByVal),do { if (!(F.arg_empty() || Attrs.hasParamAttr(0, Attribute:: ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false) | ||||
2350 | "Calling convention parameter requires byval", &F)do { if (!(F.arg_empty() || Attrs.hasParamAttr(0, Attribute:: ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false); | ||||
2351 | break; | ||||
2352 | } | ||||
2353 | case CallingConv::AMDGPU_KERNEL: | ||||
2354 | case CallingConv::SPIR_KERNEL: | ||||
2355 | Assert(F.getReturnType()->isVoidTy(),do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false) | ||||
2356 | "Calling convention requires void return type", &F)do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false); | ||||
2357 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2358 | case CallingConv::AMDGPU_VS: | ||||
2359 | case CallingConv::AMDGPU_HS: | ||||
2360 | case CallingConv::AMDGPU_GS: | ||||
2361 | case CallingConv::AMDGPU_PS: | ||||
2362 | case CallingConv::AMDGPU_CS: | ||||
2363 | Assert(!F.hasStructRetAttr(),do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false) | ||||
2364 | "Calling convention does not allow sret", &F)do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false); | ||||
2365 | if (F.getCallingConv() != CallingConv::SPIR_KERNEL) { | ||||
2366 | const unsigned StackAS = DL.getAllocaAddrSpace(); | ||||
2367 | unsigned i = 0; | ||||
2368 | for (const Argument &Arg : F.args()) { | ||||
2369 | Assert(!Attrs.hasParamAttr(i, Attribute::ByVal),do { if (!(!Attrs.hasParamAttr(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false) | ||||
2370 | "Calling convention disallows byval", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false); | ||||
2371 | Assert(!Attrs.hasParamAttr(i, Attribute::Preallocated),do { if (!(!Attrs.hasParamAttr(i, Attribute::Preallocated))) { CheckFailed("Calling convention disallows preallocated", & F); return; } } while (false) | ||||
2372 | "Calling convention disallows preallocated", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::Preallocated))) { CheckFailed("Calling convention disallows preallocated", & F); return; } } while (false); | ||||
2373 | Assert(!Attrs.hasParamAttr(i, Attribute::InAlloca),do { if (!(!Attrs.hasParamAttr(i, Attribute::InAlloca))) { CheckFailed ("Calling convention disallows inalloca", &F); return; } } while (false) | ||||
2374 | "Calling convention disallows inalloca", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::InAlloca))) { CheckFailed ("Calling convention disallows inalloca", &F); return; } } while (false); | ||||
2375 | |||||
2376 | if (Attrs.hasParamAttr(i, Attribute::ByRef)) { | ||||
2377 | // FIXME: Should also disallow LDS and GDS, but we don't have the enum | ||||
2378 | // value here. | ||||
2379 | Assert(Arg.getType()->getPointerAddressSpace() != StackAS,do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false) | ||||
2380 | "Calling convention disallows stack byref", &F)do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false); | ||||
2381 | } | ||||
2382 | |||||
2383 | ++i; | ||||
2384 | } | ||||
2385 | } | ||||
2386 | |||||
2387 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2388 | case CallingConv::Fast: | ||||
2389 | case CallingConv::Cold: | ||||
2390 | case CallingConv::Intel_OCL_BI: | ||||
2391 | case CallingConv::PTX_Kernel: | ||||
2392 | case CallingConv::PTX_Device: | ||||
2393 | Assert(!F.isVarArg(), "Calling convention does not support varargs or "do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
2394 | "perfect forwarding!",do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
2395 | &F)do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false); | ||||
2396 | break; | ||||
2397 | } | ||||
2398 | |||||
2399 | // Check that the argument values match the function type for this function... | ||||
2400 | unsigned i = 0; | ||||
2401 | for (const Argument &Arg : F.args()) { | ||||
2402 | Assert(Arg.getType() == FT->getParamType(i),do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false) | ||||
2403 | "Argument value does not match function argument type!", &Arg,do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false) | ||||
2404 | FT->getParamType(i))do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false); | ||||
2405 | Assert(Arg.getType()->isFirstClassType(),do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false) | ||||
2406 | "Function arguments must have first-class types!", &Arg)do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false); | ||||
2407 | if (!IsIntrinsic) { | ||||
2408 | Assert(!Arg.getType()->isMetadataTy(),do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false) | ||||
2409 | "Function takes metadata but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false); | ||||
2410 | Assert(!Arg.getType()->isTokenTy(),do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
2411 | "Function takes token but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false); | ||||
2412 | Assert(!Arg.getType()->isX86_AMXTy(),do { if (!(!Arg.getType()->isX86_AMXTy())) { CheckFailed("Function takes x86_amx but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
2413 | "Function takes x86_amx but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isX86_AMXTy())) { CheckFailed("Function takes x86_amx but isn't an intrinsic" , &Arg, &F); return; } } while (false); | ||||
2414 | } | ||||
2415 | |||||
2416 | // Check that swifterror argument is only used by loads and stores. | ||||
2417 | if (Attrs.hasParamAttr(i, Attribute::SwiftError)) { | ||||
2418 | verifySwiftErrorValue(&Arg); | ||||
2419 | } | ||||
2420 | ++i; | ||||
2421 | } | ||||
2422 | |||||
2423 | if (!IsIntrinsic) { | ||||
2424 | Assert(!F.getReturnType()->isTokenTy(),do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false) | ||||
2425 | "Function returns a token but isn't an intrinsic", &F)do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false); | ||||
2426 | Assert(!F.getReturnType()->isX86_AMXTy(),do { if (!(!F.getReturnType()->isX86_AMXTy())) { CheckFailed ("Function returns a x86_amx but isn't an intrinsic", &F) ; return; } } while (false) | ||||
2427 | "Function returns a x86_amx but isn't an intrinsic", &F)do { if (!(!F.getReturnType()->isX86_AMXTy())) { CheckFailed ("Function returns a x86_amx but isn't an intrinsic", &F) ; return; } } while (false); | ||||
2428 | } | ||||
2429 | |||||
2430 | // Get the function metadata attachments. | ||||
2431 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
2432 | F.getAllMetadata(MDs); | ||||
2433 | assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync")(static_cast <bool> (F.hasMetadata() != MDs.empty() && "Bit out-of-sync") ? void (0) : __assert_fail ("F.hasMetadata() != MDs.empty() && \"Bit out-of-sync\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 2433, __extension__ __PRETTY_FUNCTION__)); | ||||
2434 | verifyFunctionMetadata(MDs); | ||||
2435 | |||||
2436 | // Check validity of the personality function | ||||
2437 | if (F.hasPersonalityFn()) { | ||||
2438 | auto *Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); | ||||
2439 | if (Per) | ||||
2440 | Assert(Per->getParent() == F.getParent(),do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false) | ||||
2441 | "Referencing personality function in another module!",do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false) | ||||
2442 | &F, F.getParent(), Per, Per->getParent())do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false); | ||||
2443 | } | ||||
2444 | |||||
2445 | if (F.isMaterializable()) { | ||||
2446 | // Function has a body somewhere we can't see. | ||||
2447 | Assert(MDs.empty(), "unmaterialized function cannot have metadata", &F,do { if (!(MDs.empty())) { CheckFailed("unmaterialized function cannot have metadata" , &F, MDs.empty() ? nullptr : MDs.front().second); return ; } } while (false) | ||||
2448 | MDs.empty() ? nullptr : MDs.front().second)do { if (!(MDs.empty())) { CheckFailed("unmaterialized function cannot have metadata" , &F, MDs.empty() ? nullptr : MDs.front().second); return ; } } while (false); | ||||
2449 | } else if (F.isDeclaration()) { | ||||
2450 | for (const auto &I : MDs) { | ||||
2451 | // This is used for call site debug information. | ||||
2452 | AssertDI(I.first != LLVMContext::MD_dbg ||do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
2453 | !cast<DISubprogram>(I.second)->isDistinct(),do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
2454 | "function declaration may only have a unique !dbg attachment",do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
2455 | &F)do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false); | ||||
2456 | Assert(I.first != LLVMContext::MD_prof,do { if (!(I.first != LLVMContext::MD_prof)) { CheckFailed("function declaration may not have a !prof attachment" , &F); return; } } while (false) | ||||
2457 | "function declaration may not have a !prof attachment", &F)do { if (!(I.first != LLVMContext::MD_prof)) { CheckFailed("function declaration may not have a !prof attachment" , &F); return; } } while (false); | ||||
2458 | |||||
2459 | // Verify the metadata itself. | ||||
2460 | visitMDNode(*I.second, AreDebugLocsAllowed::Yes); | ||||
2461 | } | ||||
2462 | Assert(!F.hasPersonalityFn(),do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false) | ||||
2463 | "Function declaration shouldn't have a personality routine", &F)do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false); | ||||
2464 | } else { | ||||
2465 | // Verify that this function (which has a body) is not named "llvm.*". It | ||||
2466 | // is not legal to define intrinsics. | ||||
2467 | Assert(!IsIntrinsic, "llvm intrinsics cannot be defined!", &F)do { if (!(!IsIntrinsic)) { CheckFailed("llvm intrinsics cannot be defined!" , &F); return; } } while (false); | ||||
2468 | |||||
2469 | // Check the entry node | ||||
2470 | const BasicBlock *Entry = &F.getEntryBlock(); | ||||
2471 | Assert(pred_empty(Entry),do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false) | ||||
2472 | "Entry block to function must not have predecessors!", Entry)do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false); | ||||
2473 | |||||
2474 | // The address of the entry block cannot be taken, unless it is dead. | ||||
2475 | if (Entry->hasAddressTaken()) { | ||||
2476 | Assert(!BlockAddress::lookup(Entry)->isConstantUsed(),do { if (!(!BlockAddress::lookup(Entry)->isConstantUsed()) ) { CheckFailed("blockaddress may not be used with the entry block!" , Entry); return; } } while (false) | ||||
2477 | "blockaddress may not be used with the entry block!", Entry)do { if (!(!BlockAddress::lookup(Entry)->isConstantUsed()) ) { CheckFailed("blockaddress may not be used with the entry block!" , Entry); return; } } while (false); | ||||
2478 | } | ||||
2479 | |||||
2480 | unsigned NumDebugAttachments = 0, NumProfAttachments = 0; | ||||
2481 | // Visit metadata attachments. | ||||
2482 | for (const auto &I : MDs) { | ||||
2483 | // Verify that the attachment is legal. | ||||
2484 | auto AllowLocs = AreDebugLocsAllowed::No; | ||||
2485 | switch (I.first) { | ||||
2486 | default: | ||||
2487 | break; | ||||
2488 | case LLVMContext::MD_dbg: { | ||||
2489 | ++NumDebugAttachments; | ||||
2490 | AssertDI(NumDebugAttachments == 1,do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false) | ||||
2491 | "function must have a single !dbg attachment", &F, I.second)do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false); | ||||
2492 | AssertDI(isa<DISubprogram>(I.second),do { if (!(isa<DISubprogram>(I.second))) { DebugInfoCheckFailed ("function !dbg attachment must be a subprogram", &F, I.second ); return; } } while (false) | ||||
2493 | "function !dbg attachment must be a subprogram", &F, I.second)do { if (!(isa<DISubprogram>(I.second))) { DebugInfoCheckFailed ("function !dbg attachment must be a subprogram", &F, I.second ); return; } } while (false); | ||||
2494 | AssertDI(cast<DISubprogram>(I.second)->isDistinct(),do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false) | ||||
2495 | "function definition may only have a distinct !dbg attachment",do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false) | ||||
2496 | &F)do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false); | ||||
2497 | |||||
2498 | auto *SP = cast<DISubprogram>(I.second); | ||||
2499 | const Function *&AttachedTo = DISubprogramAttachments[SP]; | ||||
2500 | AssertDI(!AttachedTo || AttachedTo == &F,do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false) | ||||
2501 | "DISubprogram attached to more than one function", SP, &F)do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false); | ||||
2502 | AttachedTo = &F; | ||||
2503 | AllowLocs = AreDebugLocsAllowed::Yes; | ||||
2504 | break; | ||||
2505 | } | ||||
2506 | case LLVMContext::MD_prof: | ||||
2507 | ++NumProfAttachments; | ||||
2508 | Assert(NumProfAttachments == 1,do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false) | ||||
2509 | "function must have a single !prof attachment", &F, I.second)do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false); | ||||
2510 | break; | ||||
2511 | } | ||||
2512 | |||||
2513 | // Verify the metadata itself. | ||||
2514 | visitMDNode(*I.second, AllowLocs); | ||||
2515 | } | ||||
2516 | } | ||||
2517 | |||||
2518 | // If this function is actually an intrinsic, verify that it is only used in | ||||
2519 | // direct call/invokes, never having its "address taken". | ||||
2520 | // Only do this if the module is materialized, otherwise we don't have all the | ||||
2521 | // uses. | ||||
2522 | if (F.isIntrinsic() && F.getParent()->isMaterialized()) { | ||||
2523 | const User *U; | ||||
2524 | if (F.hasAddressTaken(&U)) | ||||
2525 | Assert(false, "Invalid user of intrinsic instruction!", U)do { if (!(false)) { CheckFailed("Invalid user of intrinsic instruction!" , U); return; } } while (false); | ||||
2526 | } | ||||
2527 | |||||
2528 | // Check intrinsics' signatures. | ||||
2529 | switch (F.getIntrinsicID()) { | ||||
2530 | case Intrinsic::experimental_gc_get_pointer_base: { | ||||
2531 | FunctionType *FT = F.getFunctionType(); | ||||
2532 | Assert(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
2533 | Assert(isa<PointerType>(F.getReturnType()),do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false) | ||||
2534 | "gc.get.pointer.base must return a pointer", F)do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false); | ||||
2535 | Assert(FT->getParamType(0) == F.getReturnType(),do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false) | ||||
2536 | "gc.get.pointer.base operand and result must be of the same type",do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false) | ||||
2537 | F)do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false); | ||||
2538 | break; | ||||
2539 | } | ||||
2540 | case Intrinsic::experimental_gc_get_pointer_offset: { | ||||
2541 | FunctionType *FT = F.getFunctionType(); | ||||
2542 | Assert(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
2543 | Assert(isa<PointerType>(FT->getParamType(0)),do { if (!(isa<PointerType>(FT->getParamType(0)))) { CheckFailed("gc.get.pointer.offset operand must be a pointer" , F); return; } } while (false) | ||||
2544 | "gc.get.pointer.offset operand must be a pointer", F)do { if (!(isa<PointerType>(FT->getParamType(0)))) { CheckFailed("gc.get.pointer.offset operand must be a pointer" , F); return; } } while (false); | ||||
2545 | Assert(F.getReturnType()->isIntegerTy(),do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false) | ||||
2546 | "gc.get.pointer.offset must return integer", F)do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false); | ||||
2547 | break; | ||||
2548 | } | ||||
2549 | } | ||||
2550 | |||||
2551 | auto *N = F.getSubprogram(); | ||||
2552 | HasDebugInfo = (N != nullptr); | ||||
2553 | if (!HasDebugInfo
| ||||
2554 | return; | ||||
2555 | |||||
2556 | // Check that all !dbg attachments lead to back to N. | ||||
2557 | // | ||||
2558 | // FIXME: Check this incrementally while visiting !dbg attachments. | ||||
2559 | // FIXME: Only check when N is the canonical subprogram for F. | ||||
2560 | SmallPtrSet<const MDNode *, 32> Seen; | ||||
2561 | auto VisitDebugLoc = [&](const Instruction &I, const MDNode *Node) { | ||||
2562 | // Be careful about using DILocation here since we might be dealing with | ||||
2563 | // broken code (this is the Verifier after all). | ||||
2564 | const DILocation *DL = dyn_cast_or_null<DILocation>(Node); | ||||
2565 | if (!DL
| ||||
2566 | return; | ||||
2567 | if (!Seen.insert(DL).second) | ||||
2568 | return; | ||||
2569 | |||||
2570 | Metadata *Parent = DL->getRawScope(); | ||||
2571 | AssertDI(Parent && isa<DILocalScope>(Parent),do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false) | ||||
2572 | "DILocation's scope must be a DILocalScope", N, &F, &I, DL,do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false) | ||||
2573 | Parent)do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false); | ||||
2574 | |||||
2575 | DILocalScope *Scope = DL->getInlinedAtScope(); | ||||
2576 | Assert(Scope, "Failed to find DILocalScope", DL)do { if (!(Scope)) { CheckFailed("Failed to find DILocalScope" , DL); return; } } while (false); | ||||
2577 | |||||
2578 | if (!Seen.insert(Scope).second) | ||||
2579 | return; | ||||
2580 | |||||
2581 | DISubprogram *SP = Scope->getSubprogram(); | ||||
2582 | |||||
2583 | // Scope and SP could be the same MDNode and we don't want to skip | ||||
2584 | // validation in that case | ||||
2585 | if (SP && ((Scope != SP) && !Seen.insert(SP).second)) | ||||
2586 | return; | ||||
2587 | |||||
2588 | AssertDI(SP->describes(&F),do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false) | ||||
| |||||
2589 | "!dbg attachment points at wrong subprogram for function", N, &F,do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false) | ||||
2590 | &I, DL, Scope, SP)do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false); | ||||
2591 | }; | ||||
2592 | for (auto &BB : F) | ||||
2593 | for (auto &I : BB) { | ||||
2594 | VisitDebugLoc(I, I.getDebugLoc().getAsMDNode()); | ||||
2595 | // The llvm.loop annotations also contain two DILocations. | ||||
2596 | if (auto MD = I.getMetadata(LLVMContext::MD_loop)) | ||||
2597 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) | ||||
2598 | VisitDebugLoc(I, dyn_cast_or_null<MDNode>(MD->getOperand(i))); | ||||
2599 | if (BrokenDebugInfo) | ||||
2600 | return; | ||||
2601 | } | ||||
2602 | } | ||||
2603 | |||||
2604 | // verifyBasicBlock - Verify that a basic block is well formed... | ||||
2605 | // | ||||
2606 | void Verifier::visitBasicBlock(BasicBlock &BB) { | ||||
2607 | InstsInThisBlock.clear(); | ||||
2608 | |||||
2609 | // Ensure that basic blocks have terminators! | ||||
2610 | Assert(BB.getTerminator(), "Basic Block does not have terminator!", &BB)do { if (!(BB.getTerminator())) { CheckFailed("Basic Block does not have terminator!" , &BB); return; } } while (false); | ||||
2611 | |||||
2612 | // Check constraints that this basic block imposes on all of the PHI nodes in | ||||
2613 | // it. | ||||
2614 | if (isa<PHINode>(BB.front())) { | ||||
2615 | SmallVector<BasicBlock *, 8> Preds(predecessors(&BB)); | ||||
2616 | SmallVector<std::pair<BasicBlock*, Value*>, 8> Values; | ||||
2617 | llvm::sort(Preds); | ||||
2618 | for (const PHINode &PN : BB.phis()) { | ||||
2619 | Assert(PN.getNumIncomingValues() == Preds.size(),do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
2620 | "PHINode should have one entry for each predecessor of its "do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
2621 | "parent basic block!",do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
2622 | &PN)do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false); | ||||
2623 | |||||
2624 | // Get and sort all incoming values in the PHI node... | ||||
2625 | Values.clear(); | ||||
2626 | Values.reserve(PN.getNumIncomingValues()); | ||||
2627 | for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) | ||||
2628 | Values.push_back( | ||||
2629 | std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i))); | ||||
2630 | llvm::sort(Values); | ||||
2631 | |||||
2632 | for (unsigned i = 0, e = Values.size(); i != e; ++i) { | ||||
2633 | // Check to make sure that if there is more than one entry for a | ||||
2634 | // particular basic block in this PHI node, that the incoming values are | ||||
2635 | // all identical. | ||||
2636 | // | ||||
2637 | Assert(i == 0 || Values[i].first != Values[i - 1].first ||do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
2638 | Values[i].second == Values[i - 1].second,do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
2639 | "PHI node has multiple entries for the same basic block with "do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
2640 | "different incoming values!",do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
2641 | &PN, Values[i].first, Values[i].second, Values[i - 1].second)do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false); | ||||
2642 | |||||
2643 | // Check to make sure that the predecessors and PHI node entries are | ||||
2644 | // matched up. | ||||
2645 | Assert(Values[i].first == Preds[i],do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ) | ||||
2646 | "PHI node entries do not match predecessors!", &PN,do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ) | ||||
2647 | Values[i].first, Preds[i])do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ); | ||||
2648 | } | ||||
2649 | } | ||||
2650 | } | ||||
2651 | |||||
2652 | // Check that all instructions have their parent pointers set up correctly. | ||||
2653 | for (auto &I : BB) | ||||
2654 | { | ||||
2655 | Assert(I.getParent() == &BB, "Instruction has bogus parent pointer!")do { if (!(I.getParent() == &BB)) { CheckFailed("Instruction has bogus parent pointer!" ); return; } } while (false); | ||||
2656 | } | ||||
2657 | } | ||||
2658 | |||||
2659 | void Verifier::visitTerminator(Instruction &I) { | ||||
2660 | // Ensure that terminators only exist at the end of the basic block. | ||||
2661 | Assert(&I == I.getParent()->getTerminator(),do { if (!(&I == I.getParent()->getTerminator())) { CheckFailed ("Terminator found in the middle of a basic block!", I.getParent ()); return; } } while (false) | ||||
2662 | "Terminator found in the middle of a basic block!", I.getParent())do { if (!(&I == I.getParent()->getTerminator())) { CheckFailed ("Terminator found in the middle of a basic block!", I.getParent ()); return; } } while (false); | ||||
2663 | visitInstruction(I); | ||||
2664 | } | ||||
2665 | |||||
2666 | void Verifier::visitBranchInst(BranchInst &BI) { | ||||
2667 | if (BI.isConditional()) { | ||||
2668 | Assert(BI.getCondition()->getType()->isIntegerTy(1),do { if (!(BI.getCondition()->getType()->isIntegerTy(1) )) { CheckFailed("Branch condition is not 'i1' type!", &BI , BI.getCondition()); return; } } while (false) | ||||
2669 | "Branch condition is not 'i1' type!", &BI, BI.getCondition())do { if (!(BI.getCondition()->getType()->isIntegerTy(1) )) { CheckFailed("Branch condition is not 'i1' type!", &BI , BI.getCondition()); return; } } while (false); | ||||
2670 | } | ||||
2671 | visitTerminator(BI); | ||||
2672 | } | ||||
2673 | |||||
2674 | void Verifier::visitReturnInst(ReturnInst &RI) { | ||||
2675 | Function *F = RI.getParent()->getParent(); | ||||
2676 | unsigned N = RI.getNumOperands(); | ||||
2677 | if (F->getReturnType()->isVoidTy()) | ||||
2678 | Assert(N == 0,do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
2679 | "Found return instr that returns non-void in Function of void "do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
2680 | "return type!",do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
2681 | &RI, F->getReturnType())do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false); | ||||
2682 | else | ||||
2683 | Assert(N == 1 && F->getReturnType() == RI.getOperand(0)->getType(),do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
2684 | "Function return type does not match operand "do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
2685 | "type of return inst!",do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
2686 | &RI, F->getReturnType())do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false); | ||||
2687 | |||||
2688 | // Check to make sure that the return value has necessary properties for | ||||
2689 | // terminators... | ||||
2690 | visitTerminator(RI); | ||||
2691 | } | ||||
2692 | |||||
2693 | void Verifier::visitSwitchInst(SwitchInst &SI) { | ||||
2694 | Assert(SI.getType()->isVoidTy(), "Switch must have void result type!", &SI)do { if (!(SI.getType()->isVoidTy())) { CheckFailed("Switch must have void result type!" , &SI); return; } } while (false); | ||||
2695 | // Check to make sure that all of the constants in the switch instruction | ||||
2696 | // have the same type as the switched-on value. | ||||
2697 | Type *SwitchTy = SI.getCondition()->getType(); | ||||
2698 | SmallPtrSet<ConstantInt*, 32> Constants; | ||||
2699 | for (auto &Case : SI.cases()) { | ||||
2700 | Assert(Case.getCaseValue()->getType() == SwitchTy,do { if (!(Case.getCaseValue()->getType() == SwitchTy)) { CheckFailed ("Switch constants must all be same type as switch value!", & SI); return; } } while (false) | ||||
2701 | "Switch constants must all be same type as switch value!", &SI)do { if (!(Case.getCaseValue()->getType() == SwitchTy)) { CheckFailed ("Switch constants must all be same type as switch value!", & SI); return; } } while (false); | ||||
2702 | Assert(Constants.insert(Case.getCaseValue()).second,do { if (!(Constants.insert(Case.getCaseValue()).second)) { CheckFailed ("Duplicate integer as switch case", &SI, Case.getCaseValue ()); return; } } while (false) | ||||
2703 | "Duplicate integer as switch case", &SI, Case.getCaseValue())do { if (!(Constants.insert(Case.getCaseValue()).second)) { CheckFailed ("Duplicate integer as switch case", &SI, Case.getCaseValue ()); return; } } while (false); | ||||
2704 | } | ||||
2705 | |||||
2706 | visitTerminator(SI); | ||||
2707 | } | ||||
2708 | |||||
2709 | void Verifier::visitIndirectBrInst(IndirectBrInst &BI) { | ||||
2710 | Assert(BI.getAddress()->getType()->isPointerTy(),do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false) | ||||
2711 | "Indirectbr operand must have pointer type!", &BI)do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false); | ||||
2712 | for (unsigned i = 0, e = BI.getNumDestinations(); i != e; ++i) | ||||
2713 | Assert(BI.getDestination(i)->getType()->isLabelTy(),do { if (!(BI.getDestination(i)->getType()->isLabelTy() )) { CheckFailed("Indirectbr destinations must all have pointer type!" , &BI); return; } } while (false) | ||||
2714 | "Indirectbr destinations must all have pointer type!", &BI)do { if (!(BI.getDestination(i)->getType()->isLabelTy() )) { CheckFailed("Indirectbr destinations must all have pointer type!" , &BI); return; } } while (false); | ||||
2715 | |||||
2716 | visitTerminator(BI); | ||||
2717 | } | ||||
2718 | |||||
2719 | void Verifier::visitCallBrInst(CallBrInst &CBI) { | ||||
2720 | Assert(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!",do { if (!(CBI.isInlineAsm())) { CheckFailed("Callbr is currently only used for asm-goto!" , &CBI); return; } } while (false) | ||||
2721 | &CBI)do { if (!(CBI.isInlineAsm())) { CheckFailed("Callbr is currently only used for asm-goto!" , &CBI); return; } } while (false); | ||||
2722 | const InlineAsm *IA = cast<InlineAsm>(CBI.getCalledOperand()); | ||||
2723 | Assert(!IA->canThrow(), "Unwinding from Callbr is not allowed")do { if (!(!IA->canThrow())) { CheckFailed("Unwinding from Callbr is not allowed" ); return; } } while (false); | ||||
2724 | for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i) | ||||
2725 | Assert(CBI.getSuccessor(i)->getType()->isLabelTy(),do { if (!(CBI.getSuccessor(i)->getType()->isLabelTy()) ) { CheckFailed("Callbr successors must all have pointer type!" , &CBI); return; } } while (false) | ||||
2726 | "Callbr successors must all have pointer type!", &CBI)do { if (!(CBI.getSuccessor(i)->getType()->isLabelTy()) ) { CheckFailed("Callbr successors must all have pointer type!" , &CBI); return; } } while (false); | ||||
2727 | for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) { | ||||
2728 | Assert(i >= CBI.getNumArgOperands() || !isa<BasicBlock>(CBI.getOperand(i)),do { if (!(i >= CBI.getNumArgOperands() || !isa<BasicBlock >(CBI.getOperand(i)))) { CheckFailed("Using an unescaped label as a callbr argument!" , &CBI); return; } } while (false) | ||||
2729 | "Using an unescaped label as a callbr argument!", &CBI)do { if (!(i >= CBI.getNumArgOperands() || !isa<BasicBlock >(CBI.getOperand(i)))) { CheckFailed("Using an unescaped label as a callbr argument!" , &CBI); return; } } while (false); | ||||
2730 | if (isa<BasicBlock>(CBI.getOperand(i))) | ||||
2731 | for (unsigned j = i + 1; j != e; ++j) | ||||
2732 | Assert(CBI.getOperand(i) != CBI.getOperand(j),do { if (!(CBI.getOperand(i) != CBI.getOperand(j))) { CheckFailed ("Duplicate callbr destination!", &CBI); return; } } while (false) | ||||
2733 | "Duplicate callbr destination!", &CBI)do { if (!(CBI.getOperand(i) != CBI.getOperand(j))) { CheckFailed ("Duplicate callbr destination!", &CBI); return; } } while (false); | ||||
2734 | } | ||||
2735 | { | ||||
2736 | SmallPtrSet<BasicBlock *, 4> ArgBBs; | ||||
2737 | for (Value *V : CBI.args()) | ||||
2738 | if (auto *BA = dyn_cast<BlockAddress>(V)) | ||||
2739 | ArgBBs.insert(BA->getBasicBlock()); | ||||
2740 | for (BasicBlock *BB : CBI.getIndirectDests()) | ||||
2741 | Assert(ArgBBs.count(BB), "Indirect label missing from arglist.", &CBI)do { if (!(ArgBBs.count(BB))) { CheckFailed("Indirect label missing from arglist." , &CBI); return; } } while (false); | ||||
2742 | } | ||||
2743 | |||||
2744 | visitTerminator(CBI); | ||||
2745 | } | ||||
2746 | |||||
2747 | void Verifier::visitSelectInst(SelectInst &SI) { | ||||
2748 | Assert(!SelectInst::areInvalidOperands(SI.getOperand(0), SI.getOperand(1),do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false) | ||||
2749 | SI.getOperand(2)),do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false) | ||||
2750 | "Invalid operands for select instruction!", &SI)do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false); | ||||
2751 | |||||
2752 | Assert(SI.getTrueValue()->getType() == SI.getType(),do { if (!(SI.getTrueValue()->getType() == SI.getType())) { CheckFailed("Select values must have same type as select instruction!" , &SI); return; } } while (false) | ||||
2753 | "Select values must have same type as select instruction!", &SI)do { if (!(SI.getTrueValue()->getType() == SI.getType())) { CheckFailed("Select values must have same type as select instruction!" , &SI); return; } } while (false); | ||||
2754 | visitInstruction(SI); | ||||
2755 | } | ||||
2756 | |||||
2757 | /// visitUserOp1 - User defined operators shouldn't live beyond the lifetime of | ||||
2758 | /// a pass, if any exist, it's an error. | ||||
2759 | /// | ||||
2760 | void Verifier::visitUserOp1(Instruction &I) { | ||||
2761 | Assert(false, "User-defined operators should not live outside of a pass!", &I)do { if (!(false)) { CheckFailed("User-defined operators should not live outside of a pass!" , &I); return; } } while (false); | ||||
2762 | } | ||||
2763 | |||||
2764 | void Verifier::visitTruncInst(TruncInst &I) { | ||||
2765 | // Get the source and destination types | ||||
2766 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2767 | Type *DestTy = I.getType(); | ||||
2768 | |||||
2769 | // Get the size of the types in bits, we'll need this later | ||||
2770 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2771 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2772 | |||||
2773 | Assert(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only operates on integer" , &I); return; } } while (false); | ||||
2774 | Assert(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only produces integer" , &I); return; } } while (false); | ||||
2775 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("trunc source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
2776 | "trunc source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("trunc source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
2777 | Assert(SrcBitSize > DestBitSize, "DestTy too big for Trunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for Trunc" , &I); return; } } while (false); | ||||
2778 | |||||
2779 | visitInstruction(I); | ||||
2780 | } | ||||
2781 | |||||
2782 | void Verifier::visitZExtInst(ZExtInst &I) { | ||||
2783 | // Get the source and destination types | ||||
2784 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2785 | Type *DestTy = I.getType(); | ||||
2786 | |||||
2787 | // Get the size of the types in bits, we'll need this later | ||||
2788 | Assert(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only operates on integer" , &I); return; } } while (false); | ||||
2789 | Assert(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only produces an integer" , &I); return; } } while (false); | ||||
2790 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("zext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
2791 | "zext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("zext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
2792 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2793 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2794 | |||||
2795 | Assert(SrcBitSize < DestBitSize, "Type too small for ZExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for ZExt" , &I); return; } } while (false); | ||||
2796 | |||||
2797 | visitInstruction(I); | ||||
2798 | } | ||||
2799 | |||||
2800 | void Verifier::visitSExtInst(SExtInst &I) { | ||||
2801 | // Get the source and destination types | ||||
2802 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2803 | Type *DestTy = I.getType(); | ||||
2804 | |||||
2805 | // Get the size of the types in bits, we'll need this later | ||||
2806 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2807 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2808 | |||||
2809 | Assert(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SExt only operates on integer" , &I); return; } } while (false); | ||||
2810 | Assert(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("SExt only produces an integer" , &I); return; } } while (false); | ||||
2811 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("sext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
2812 | "sext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("sext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
2813 | Assert(SrcBitSize < DestBitSize, "Type too small for SExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for SExt" , &I); return; } } while (false); | ||||
2814 | |||||
2815 | visitInstruction(I); | ||||
2816 | } | ||||
2817 | |||||
2818 | void Verifier::visitFPTruncInst(FPTruncInst &I) { | ||||
2819 | // Get the source and destination types | ||||
2820 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2821 | Type *DestTy = I.getType(); | ||||
2822 | // Get the size of the types in bits, we'll need this later | ||||
2823 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2824 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2825 | |||||
2826 | Assert(SrcTy->isFPOrFPVectorTy(), "FPTrunc only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only operates on FP" , &I); return; } } while (false); | ||||
2827 | Assert(DestTy->isFPOrFPVectorTy(), "FPTrunc only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only produces an FP" , &I); return; } } while (false); | ||||
2828 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fptrunc source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
2829 | "fptrunc source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fptrunc source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
2830 | Assert(SrcBitSize > DestBitSize, "DestTy too big for FPTrunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for FPTrunc" , &I); return; } } while (false); | ||||
2831 | |||||
2832 | visitInstruction(I); | ||||
2833 | } | ||||
2834 | |||||
2835 | void Verifier::visitFPExtInst(FPExtInst &I) { | ||||
2836 | // Get the source and destination types | ||||
2837 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2838 | Type *DestTy = I.getType(); | ||||
2839 | |||||
2840 | // Get the size of the types in bits, we'll need this later | ||||
2841 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2842 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2843 | |||||
2844 | Assert(SrcTy->isFPOrFPVectorTy(), "FPExt only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only operates on FP" , &I); return; } } while (false); | ||||
2845 | Assert(DestTy->isFPOrFPVectorTy(), "FPExt only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only produces an FP" , &I); return; } } while (false); | ||||
2846 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fpext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
2847 | "fpext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fpext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
2848 | Assert(SrcBitSize < DestBitSize, "DestTy too small for FPExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("DestTy too small for FPExt" , &I); return; } } while (false); | ||||
2849 | |||||
2850 | visitInstruction(I); | ||||
2851 | } | ||||
2852 | |||||
2853 | void Verifier::visitUIToFPInst(UIToFPInst &I) { | ||||
2854 | // Get the source and destination types | ||||
2855 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2856 | Type *DestTy = I.getType(); | ||||
2857 | |||||
2858 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2859 | bool DstVec = DestTy->isVectorTy(); | ||||
2860 | |||||
2861 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2862 | "UIToFP source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
2863 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
2864 | "UIToFP source must be integer or integer vector", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false); | ||||
2865 | Assert(DestTy->isFPOrFPVectorTy(), "UIToFP result must be FP or FP vector",do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false) | ||||
2866 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
2867 | |||||
2868 | if (SrcVec && DstVec) | ||||
2869 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
2870 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
2871 | "UIToFP source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false); | ||||
2872 | |||||
2873 | visitInstruction(I); | ||||
2874 | } | ||||
2875 | |||||
2876 | void Verifier::visitSIToFPInst(SIToFPInst &I) { | ||||
2877 | // Get the source and destination types | ||||
2878 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2879 | Type *DestTy = I.getType(); | ||||
2880 | |||||
2881 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2882 | bool DstVec = DestTy->isVectorTy(); | ||||
2883 | |||||
2884 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2885 | "SIToFP source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
2886 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
2887 | "SIToFP source must be integer or integer vector", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false); | ||||
2888 | Assert(DestTy->isFPOrFPVectorTy(), "SIToFP result must be FP or FP vector",do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false) | ||||
2889 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
2890 | |||||
2891 | if (SrcVec && DstVec) | ||||
2892 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
2893 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
2894 | "SIToFP source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false); | ||||
2895 | |||||
2896 | visitInstruction(I); | ||||
2897 | } | ||||
2898 | |||||
2899 | void Verifier::visitFPToUIInst(FPToUIInst &I) { | ||||
2900 | // Get the source and destination types | ||||
2901 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2902 | Type *DestTy = I.getType(); | ||||
2903 | |||||
2904 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2905 | bool DstVec = DestTy->isVectorTy(); | ||||
2906 | |||||
2907 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2908 | "FPToUI source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
2909 | Assert(SrcTy->isFPOrFPVectorTy(), "FPToUI source must be FP or FP vector",do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToUI source must be FP or FP vector" , &I); return; } } while (false) | ||||
2910 | &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToUI source must be FP or FP vector" , &I); return; } } while (false); | ||||
2911 | Assert(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false) | ||||
2912 | "FPToUI result must be integer or integer vector", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false); | ||||
2913 | |||||
2914 | if (SrcVec && DstVec) | ||||
2915 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false) | ||||
2916 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false) | ||||
2917 | "FPToUI source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false); | ||||
2918 | |||||
2919 | visitInstruction(I); | ||||
2920 | } | ||||
2921 | |||||
2922 | void Verifier::visitFPToSIInst(FPToSIInst &I) { | ||||
2923 | // Get the source and destination types | ||||
2924 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2925 | Type *DestTy = I.getType(); | ||||
2926 | |||||
2927 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2928 | bool DstVec = DestTy->isVectorTy(); | ||||
2929 | |||||
2930 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2931 | "FPToSI source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
2932 | Assert(SrcTy->isFPOrFPVectorTy(), "FPToSI source must be FP or FP vector",do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToSI source must be FP or FP vector" , &I); return; } } while (false) | ||||
2933 | &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToSI source must be FP or FP vector" , &I); return; } } while (false); | ||||
2934 | Assert(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false) | ||||
2935 | "FPToSI result must be integer or integer vector", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false); | ||||
2936 | |||||
2937 | if (SrcVec && DstVec) | ||||
2938 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false) | ||||
2939 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false) | ||||
2940 | "FPToSI source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false); | ||||
2941 | |||||
2942 | visitInstruction(I); | ||||
2943 | } | ||||
2944 | |||||
2945 | void Verifier::visitPtrToIntInst(PtrToIntInst &I) { | ||||
2946 | // Get the source and destination types | ||||
2947 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2948 | Type *DestTy = I.getType(); | ||||
2949 | |||||
2950 | Assert(SrcTy->isPtrOrPtrVectorTy(), "PtrToInt source must be pointer", &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("PtrToInt source must be pointer" , &I); return; } } while (false); | ||||
2951 | |||||
2952 | Assert(DestTy->isIntOrIntVectorTy(), "PtrToInt result must be integral", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("PtrToInt result must be integral" , &I); return; } } while (false); | ||||
2953 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false) | ||||
2954 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false); | ||||
2955 | |||||
2956 | if (SrcTy->isVectorTy()) { | ||||
2957 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
2958 | auto *VDest = cast<VectorType>(DestTy); | ||||
2959 | Assert(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false) | ||||
2960 | "PtrToInt Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false); | ||||
2961 | } | ||||
2962 | |||||
2963 | visitInstruction(I); | ||||
2964 | } | ||||
2965 | |||||
2966 | void Verifier::visitIntToPtrInst(IntToPtrInst &I) { | ||||
2967 | // Get the source and destination types | ||||
2968 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2969 | Type *DestTy = I.getType(); | ||||
2970 | |||||
2971 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false) | ||||
2972 | "IntToPtr source must be an integral", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false); | ||||
2973 | Assert(DestTy->isPtrOrPtrVectorTy(), "IntToPtr result must be a pointer", &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("IntToPtr result must be a pointer" , &I); return; } } while (false); | ||||
2974 | |||||
2975 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false) | ||||
2976 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false); | ||||
2977 | if (SrcTy->isVectorTy()) { | ||||
2978 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
2979 | auto *VDest = cast<VectorType>(DestTy); | ||||
2980 | Assert(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false) | ||||
2981 | "IntToPtr Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false); | ||||
2982 | } | ||||
2983 | visitInstruction(I); | ||||
2984 | } | ||||
2985 | |||||
2986 | void Verifier::visitBitCastInst(BitCastInst &I) { | ||||
2987 | Assert(do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
2988 | CastInst::castIsValid(Instruction::BitCast, I.getOperand(0), I.getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
2989 | "Invalid bitcast", &I)do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false); | ||||
2990 | visitInstruction(I); | ||||
2991 | } | ||||
2992 | |||||
2993 | void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { | ||||
2994 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2995 | Type *DestTy = I.getType(); | ||||
2996 | |||||
2997 | Assert(SrcTy->isPtrOrPtrVectorTy(), "AddrSpaceCast source must be a pointer",do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false) | ||||
2998 | &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false); | ||||
2999 | Assert(DestTy->isPtrOrPtrVectorTy(), "AddrSpaceCast result must be a pointer",do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false) | ||||
3000 | &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false); | ||||
3001 | Assert(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(),do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false) | ||||
3002 | "AddrSpaceCast must be between different address spaces", &I)do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false); | ||||
3003 | if (auto *SrcVTy = dyn_cast<VectorType>(SrcTy)) | ||||
3004 | Assert(SrcVTy->getElementCount() ==do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
3005 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
3006 | "AddrSpaceCast vector pointer number of elements mismatch", &I)do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false); | ||||
3007 | visitInstruction(I); | ||||
3008 | } | ||||
3009 | |||||
3010 | /// visitPHINode - Ensure that a PHI node is well formed. | ||||
3011 | /// | ||||
3012 | void Verifier::visitPHINode(PHINode &PN) { | ||||
3013 | // Ensure that the PHI nodes are all grouped together at the top of the block. | ||||
3014 | // This can be tested by checking whether the instruction before this is | ||||
3015 | // either nonexistent (because this is begin()) or is a PHI node. If not, | ||||
3016 | // then there is some other instruction before a PHI. | ||||
3017 | Assert(&PN == &PN.getParent()->front() ||do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false) | ||||
3018 | isa<PHINode>(--BasicBlock::iterator(&PN)),do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false) | ||||
3019 | "PHI nodes not grouped at top of basic block!", &PN, PN.getParent())do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false); | ||||
3020 | |||||
3021 | // Check that a PHI doesn't yield a Token. | ||||
3022 | Assert(!PN.getType()->isTokenTy(), "PHI nodes cannot have token type!")do { if (!(!PN.getType()->isTokenTy())) { CheckFailed("PHI nodes cannot have token type!" ); return; } } while (false); | ||||
3023 | |||||
3024 | // Check that all of the values of the PHI node have the same type as the | ||||
3025 | // result, and that the incoming blocks are really basic blocks. | ||||
3026 | for (Value *IncValue : PN.incoming_values()) { | ||||
3027 | Assert(PN.getType() == IncValue->getType(),do { if (!(PN.getType() == IncValue->getType())) { CheckFailed ("PHI node operands are not the same type as the result!", & PN); return; } } while (false) | ||||
3028 | "PHI node operands are not the same type as the result!", &PN)do { if (!(PN.getType() == IncValue->getType())) { CheckFailed ("PHI node operands are not the same type as the result!", & PN); return; } } while (false); | ||||
3029 | } | ||||
3030 | |||||
3031 | // All other PHI node constraints are checked in the visitBasicBlock method. | ||||
3032 | |||||
3033 | visitInstruction(PN); | ||||
3034 | } | ||||
3035 | |||||
3036 | void Verifier::visitCallBase(CallBase &Call) { | ||||
3037 | Assert(Call.getCalledOperand()->getType()->isPointerTy(),do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false) | ||||
3038 | "Called function must be a pointer!", Call)do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false); | ||||
3039 | PointerType *FPTy = cast<PointerType>(Call.getCalledOperand()->getType()); | ||||
3040 | |||||
3041 | Assert(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType()),do { if (!(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType ()))) { CheckFailed("Called function is not the same type as the call!" , Call); return; } } while (false) | ||||
3042 | "Called function is not the same type as the call!", Call)do { if (!(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType ()))) { CheckFailed("Called function is not the same type as the call!" , Call); return; } } while (false); | ||||
3043 | |||||
3044 | FunctionType *FTy = Call.getFunctionType(); | ||||
3045 | |||||
3046 | // Verify that the correct number of arguments are being passed | ||||
3047 | if (FTy->isVarArg()) | ||||
3048 | Assert(Call.arg_size() >= FTy->getNumParams(),do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false) | ||||
3049 | "Called function requires more parameters than were provided!",do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false) | ||||
3050 | Call)do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false); | ||||
3051 | else | ||||
3052 | Assert(Call.arg_size() == FTy->getNumParams(),do { if (!(Call.arg_size() == FTy->getNumParams())) { CheckFailed ("Incorrect number of arguments passed to called function!", Call ); return; } } while (false) | ||||
3053 | "Incorrect number of arguments passed to called function!", Call)do { if (!(Call.arg_size() == FTy->getNumParams())) { CheckFailed ("Incorrect number of arguments passed to called function!", Call ); return; } } while (false); | ||||
3054 | |||||
3055 | // Verify that all arguments to the call match the function type. | ||||
3056 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) | ||||
3057 | Assert(Call.getArgOperand(i)->getType() == FTy->getParamType(i),do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false) | ||||
3058 | "Call parameter type does not match function signature!",do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false) | ||||
3059 | Call.getArgOperand(i), FTy->getParamType(i), Call)do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false); | ||||
3060 | |||||
3061 | AttributeList Attrs = Call.getAttributes(); | ||||
3062 | |||||
3063 | Assert(verifyAttributeCount(Attrs, Call.arg_size()),do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false) | ||||
3064 | "Attribute after last parameter!", Call)do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false); | ||||
3065 | |||||
3066 | Function *Callee = | ||||
3067 | dyn_cast<Function>(Call.getCalledOperand()->stripPointerCasts()); | ||||
3068 | bool IsIntrinsic = Callee && Callee->isIntrinsic(); | ||||
3069 | if (IsIntrinsic) | ||||
3070 | Assert(Callee->getValueType() == FTy,do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false) | ||||
3071 | "Intrinsic called with incompatible signature", Call)do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false); | ||||
3072 | |||||
3073 | if (Attrs.hasFnAttr(Attribute::Speculatable)) { | ||||
3074 | // Don't allow speculatable on call sites, unless the underlying function | ||||
3075 | // declaration is also speculatable. | ||||
3076 | Assert(Callee && Callee->isSpeculatable(),do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false) | ||||
3077 | "speculatable attribute may not apply to call sites", Call)do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false); | ||||
3078 | } | ||||
3079 | |||||
3080 | if (Attrs.hasFnAttr(Attribute::Preallocated)) { | ||||
3081 | Assert(Call.getCalledFunction()->getIntrinsicID() ==do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
3082 | Intrinsic::call_preallocated_arg,do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
3083 | "preallocated as a call site attribute can only be on "do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
3084 | "llvm.call.preallocated.arg")do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false); | ||||
3085 | } | ||||
3086 | |||||
3087 | // Verify call attributes. | ||||
3088 | verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic); | ||||
3089 | |||||
3090 | // Conservatively check the inalloca argument. | ||||
3091 | // We have a bug if we can find that there is an underlying alloca without | ||||
3092 | // inalloca. | ||||
3093 | if (Call.hasInAllocaArgument()) { | ||||
3094 | Value *InAllocaArg = Call.getArgOperand(FTy->getNumParams() - 1); | ||||
3095 | if (auto AI = dyn_cast<AllocaInst>(InAllocaArg->stripInBoundsOffsets())) | ||||
3096 | Assert(AI->isUsedWithInAlloca(),do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
3097 | "inalloca argument for call has mismatched alloca", AI, Call)do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false); | ||||
3098 | } | ||||
3099 | |||||
3100 | // For each argument of the callsite, if it has the swifterror argument, | ||||
3101 | // make sure the underlying alloca/parameter it comes from has a swifterror as | ||||
3102 | // well. | ||||
3103 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { | ||||
3104 | if (Call.paramHasAttr(i, Attribute::SwiftError)) { | ||||
3105 | Value *SwiftErrorArg = Call.getArgOperand(i); | ||||
3106 | if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) { | ||||
3107 | Assert(AI->isSwiftError(),do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
3108 | "swifterror argument for call has mismatched alloca", AI, Call)do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false); | ||||
3109 | continue; | ||||
3110 | } | ||||
3111 | auto ArgI = dyn_cast<Argument>(SwiftErrorArg); | ||||
3112 | Assert(ArgI,do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false) | ||||
3113 | "swifterror argument should come from an alloca or parameter",do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false) | ||||
3114 | SwiftErrorArg, Call)do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false); | ||||
3115 | Assert(ArgI->hasSwiftErrorAttr(),do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
3116 | "swifterror argument for call has mismatched parameter", ArgI,do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
3117 | Call)do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false); | ||||
3118 | } | ||||
3119 | |||||
3120 | if (Attrs.hasParamAttr(i, Attribute::ImmArg)) { | ||||
3121 | // Don't allow immarg on call sites, unless the underlying declaration | ||||
3122 | // also has the matching immarg. | ||||
3123 | Assert(Callee && Callee->hasParamAttribute(i, Attribute::ImmArg),do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false) | ||||
3124 | "immarg may not apply only to call sites",do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false) | ||||
3125 | Call.getArgOperand(i), Call)do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false); | ||||
3126 | } | ||||
3127 | |||||
3128 | if (Call.paramHasAttr(i, Attribute::ImmArg)) { | ||||
3129 | Value *ArgVal = Call.getArgOperand(i); | ||||
3130 | Assert(isa<ConstantInt>(ArgVal) || isa<ConstantFP>(ArgVal),do { if (!(isa<ConstantInt>(ArgVal) || isa<ConstantFP >(ArgVal))) { CheckFailed("immarg operand has non-immediate parameter" , ArgVal, Call); return; } } while (false) | ||||
3131 | "immarg operand has non-immediate parameter", ArgVal, Call)do { if (!(isa<ConstantInt>(ArgVal) || isa<ConstantFP >(ArgVal))) { CheckFailed("immarg operand has non-immediate parameter" , ArgVal, Call); return; } } while (false); | ||||
3132 | } | ||||
3133 | |||||
3134 | if (Call.paramHasAttr(i, Attribute::Preallocated)) { | ||||
3135 | Value *ArgVal = Call.getArgOperand(i); | ||||
3136 | bool hasOB = | ||||
3137 | Call.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0; | ||||
3138 | bool isMustTail = Call.isMustTailCall(); | ||||
3139 | Assert(hasOB != isMustTail,do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
3140 | "preallocated operand either requires a preallocated bundle or "do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
3141 | "the call to be musttail (but not both)",do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
3142 | ArgVal, Call)do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false); | ||||
3143 | } | ||||
3144 | } | ||||
3145 | |||||
3146 | if (FTy->isVarArg()) { | ||||
3147 | // FIXME? is 'nest' even legal here? | ||||
3148 | bool SawNest = false; | ||||
3149 | bool SawReturned = false; | ||||
3150 | |||||
3151 | for (unsigned Idx = 0; Idx < FTy->getNumParams(); ++Idx) { | ||||
3152 | if (Attrs.hasParamAttr(Idx, Attribute::Nest)) | ||||
3153 | SawNest = true; | ||||
3154 | if (Attrs.hasParamAttr(Idx, Attribute::Returned)) | ||||
3155 | SawReturned = true; | ||||
3156 | } | ||||
3157 | |||||
3158 | // Check attributes on the varargs part. | ||||
3159 | for (unsigned Idx = FTy->getNumParams(); Idx < Call.arg_size(); ++Idx) { | ||||
3160 | Type *Ty = Call.getArgOperand(Idx)->getType(); | ||||
3161 | AttributeSet ArgAttrs = Attrs.getParamAttrs(Idx); | ||||
3162 | verifyParameterAttrs(ArgAttrs, Ty, &Call); | ||||
3163 | |||||
3164 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
3165 | Assert(!SawNest, "More than one parameter has attribute nest!", Call)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , Call); return; } } while (false); | ||||
3166 | SawNest = true; | ||||
3167 | } | ||||
3168 | |||||
3169 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
3170 | Assert(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false) | ||||
3171 | Call)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false); | ||||
3172 | Assert(Ty->canLosslesslyBitCastTo(FTy->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
3173 | "Incompatible argument and return types for 'returned' "do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
3174 | "attribute",do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
3175 | Call)do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false); | ||||
3176 | SawReturned = true; | ||||
3177 | } | ||||
3178 | |||||
3179 | // Statepoint intrinsic is vararg but the wrapped function may be not. | ||||
3180 | // Allow sret here and check the wrapped function in verifyStatepoint. | ||||
3181 | if (!Call.getCalledFunction() || | ||||
3182 | Call.getCalledFunction()->getIntrinsicID() != | ||||
3183 | Intrinsic::experimental_gc_statepoint) | ||||
3184 | Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
3185 | "Attribute 'sret' cannot be used for vararg call arguments!",do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
3186 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
3187 | |||||
3188 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) | ||||
3189 | Assert(Idx == Call.arg_size() - 1,do { if (!(Idx == Call.arg_size() - 1)) { CheckFailed("inalloca isn't on the last argument!" , Call); return; } } while (false) | ||||
3190 | "inalloca isn't on the last argument!", Call)do { if (!(Idx == Call.arg_size() - 1)) { CheckFailed("inalloca isn't on the last argument!" , Call); return; } } while (false); | ||||
3191 | } | ||||
3192 | } | ||||
3193 | |||||
3194 | // Verify that there's no metadata unless it's a direct call to an intrinsic. | ||||
3195 | if (!IsIntrinsic) { | ||||
3196 | for (Type *ParamTy : FTy->params()) { | ||||
3197 | Assert(!ParamTy->isMetadataTy(),do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
3198 | "Function has metadata parameter but isn't an intrinsic", Call)do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false); | ||||
3199 | Assert(!ParamTy->isTokenTy(),do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
3200 | "Function has token parameter but isn't an intrinsic", Call)do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false); | ||||
3201 | } | ||||
3202 | } | ||||
3203 | |||||
3204 | // Verify that indirect calls don't return tokens. | ||||
3205 | if (!Call.getCalledFunction()) { | ||||
3206 | Assert(!FTy->getReturnType()->isTokenTy(),do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false) | ||||
3207 | "Return type cannot be token for indirect call!")do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false); | ||||
3208 | Assert(!FTy->getReturnType()->isX86_AMXTy(),do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false) | ||||
3209 | "Return type cannot be x86_amx for indirect call!")do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false); | ||||
3210 | } | ||||
3211 | |||||
3212 | if (Function *F = Call.getCalledFunction()) | ||||
3213 | if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) | ||||
3214 | visitIntrinsicCall(ID, Call); | ||||
3215 | |||||
3216 | // Verify that a callsite has at most one "deopt", at most one "funclet", at | ||||
3217 | // most one "gc-transition", at most one "cfguardtarget", | ||||
3218 | // and at most one "preallocated" operand bundle. | ||||
3219 | bool FoundDeoptBundle = false, FoundFuncletBundle = false, | ||||
3220 | FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false, | ||||
3221 | FoundPreallocatedBundle = false, FoundGCLiveBundle = false, | ||||
3222 | FoundAttachedCallBundle = false; | ||||
3223 | for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) { | ||||
3224 | OperandBundleUse BU = Call.getOperandBundleAt(i); | ||||
3225 | uint32_t Tag = BU.getTagID(); | ||||
3226 | if (Tag == LLVMContext::OB_deopt) { | ||||
3227 | Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", Call)do { if (!(!FoundDeoptBundle)) { CheckFailed("Multiple deopt operand bundles" , Call); return; } } while (false); | ||||
3228 | FoundDeoptBundle = true; | ||||
3229 | } else if (Tag == LLVMContext::OB_gc_transition) { | ||||
3230 | Assert(!FoundGCTransitionBundle, "Multiple gc-transition operand bundles",do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false) | ||||
3231 | Call)do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false); | ||||
3232 | FoundGCTransitionBundle = true; | ||||
3233 | } else if (Tag == LLVMContext::OB_funclet) { | ||||
3234 | Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", Call)do { if (!(!FoundFuncletBundle)) { CheckFailed("Multiple funclet operand bundles" , Call); return; } } while (false); | ||||
3235 | FoundFuncletBundle = true; | ||||
3236 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false) | ||||
3237 | "Expected exactly one funclet bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false); | ||||
3238 | Assert(isa<FuncletPadInst>(BU.Inputs.front()),do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false) | ||||
3239 | "Funclet bundle operands should correspond to a FuncletPadInst",do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false) | ||||
3240 | Call)do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false); | ||||
3241 | } else if (Tag == LLVMContext::OB_cfguardtarget) { | ||||
3242 | Assert(!FoundCFGuardTargetBundle,do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false) | ||||
3243 | "Multiple CFGuardTarget operand bundles", Call)do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false); | ||||
3244 | FoundCFGuardTargetBundle = true; | ||||
3245 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false) | ||||
3246 | "Expected exactly one cfguardtarget bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false); | ||||
3247 | } else if (Tag == LLVMContext::OB_preallocated) { | ||||
3248 | Assert(!FoundPreallocatedBundle, "Multiple preallocated operand bundles",do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false) | ||||
3249 | Call)do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false); | ||||
3250 | FoundPreallocatedBundle = true; | ||||
3251 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false) | ||||
3252 | "Expected exactly one preallocated bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false); | ||||
3253 | auto Input = dyn_cast<IntrinsicInst>(BU.Inputs.front()); | ||||
3254 | Assert(Input &&do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
3255 | Input->getIntrinsicID() == Intrinsic::call_preallocated_setup,do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
3256 | "\"preallocated\" argument must be a token from "do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
3257 | "llvm.call.preallocated.setup",do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
3258 | Call)do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ); | ||||
3259 | } else if (Tag == LLVMContext::OB_gc_live) { | ||||
3260 | Assert(!FoundGCLiveBundle, "Multiple gc-live operand bundles",do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false) | ||||
3261 | Call)do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false); | ||||
3262 | FoundGCLiveBundle = true; | ||||
3263 | } else if (Tag == LLVMContext::OB_clang_arc_attachedcall) { | ||||
3264 | Assert(!FoundAttachedCallBundle,do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false) | ||||
3265 | "Multiple \"clang.arc.attachedcall\" operand bundles", Call)do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false); | ||||
3266 | FoundAttachedCallBundle = true; | ||||
3267 | } | ||||
3268 | } | ||||
3269 | |||||
3270 | if (FoundAttachedCallBundle) | ||||
3271 | Assert((FTy->getReturnType()->isPointerTy() ||do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
3272 | (Call.doesNotReturn() && FTy->getReturnType()->isVoidTy())),do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
3273 | "a call with operand bundle \"clang.arc.attachedcall\" must call a "do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
3274 | "function returning a pointer or a non-returning function that has "do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
3275 | "a void return type",do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
3276 | Call)do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false); | ||||
3277 | |||||
3278 | // Verify that each inlinable callsite of a debug-info-bearing function in a | ||||
3279 | // debug-info-bearing function has a debug location attached to it. Failure to | ||||
3280 | // do so causes assertion failures when the inliner sets up inline scope info. | ||||
3281 | if (Call.getFunction()->getSubprogram() && Call.getCalledFunction() && | ||||
3282 | Call.getCalledFunction()->getSubprogram()) | ||||
3283 | AssertDI(Call.getDebugLoc(),do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
3284 | "inlinable function call in a function with "do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
3285 | "debug info must have a !dbg location",do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
3286 | Call)do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false); | ||||
3287 | |||||
3288 | visitInstruction(Call); | ||||
3289 | } | ||||
3290 | |||||
3291 | void Verifier::verifyTailCCMustTailAttrs(AttrBuilder Attrs, | ||||
3292 | StringRef Context) { | ||||
3293 | Assert(!Attrs.contains(Attribute::InAlloca),do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false) | ||||
3294 | Twine("inalloca attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false); | ||||
3295 | Assert(!Attrs.contains(Attribute::InReg),do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false) | ||||
3296 | Twine("inreg attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false); | ||||
3297 | Assert(!Attrs.contains(Attribute::SwiftError),do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false) | ||||
3298 | Twine("swifterror attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false); | ||||
3299 | Assert(!Attrs.contains(Attribute::Preallocated),do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false) | ||||
3300 | Twine("preallocated attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false); | ||||
3301 | Assert(!Attrs.contains(Attribute::ByRef),do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false) | ||||
3302 | Twine("byref attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false); | ||||
3303 | } | ||||
3304 | |||||
3305 | /// Two types are "congruent" if they are identical, or if they are both pointer | ||||
3306 | /// types with different pointee types and the same address space. | ||||
3307 | static bool isTypeCongruent(Type *L, Type *R) { | ||||
3308 | if (L == R) | ||||
3309 | return true; | ||||
3310 | PointerType *PL = dyn_cast<PointerType>(L); | ||||
3311 | PointerType *PR = dyn_cast<PointerType>(R); | ||||
3312 | if (!PL || !PR) | ||||
3313 | return false; | ||||
3314 | return PL->getAddressSpace() == PR->getAddressSpace(); | ||||
3315 | } | ||||
3316 | |||||
3317 | static AttrBuilder getParameterABIAttributes(int I, AttributeList Attrs) { | ||||
3318 | static const Attribute::AttrKind ABIAttrs[] = { | ||||
3319 | Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, | ||||
3320 | Attribute::InReg, Attribute::StackAlignment, Attribute::SwiftSelf, | ||||
3321 | Attribute::SwiftAsync, Attribute::SwiftError, Attribute::Preallocated, | ||||
3322 | Attribute::ByRef}; | ||||
3323 | AttrBuilder Copy; | ||||
3324 | for (auto AK : ABIAttrs) { | ||||
3325 | Attribute Attr = Attrs.getParamAttrs(I).getAttribute(AK); | ||||
3326 | if (Attr.isValid()) | ||||
3327 | Copy.addAttribute(Attr); | ||||
3328 | } | ||||
3329 | |||||
3330 | // `align` is ABI-affecting only in combination with `byval` or `byref`. | ||||
3331 | if (Attrs.hasParamAttr(I, Attribute::Alignment) && | ||||
3332 | (Attrs.hasParamAttr(I, Attribute::ByVal) || | ||||
3333 | Attrs.hasParamAttr(I, Attribute::ByRef))) | ||||
3334 | Copy.addAlignmentAttr(Attrs.getParamAlignment(I)); | ||||
3335 | return Copy; | ||||
3336 | } | ||||
3337 | |||||
3338 | void Verifier::verifyMustTailCall(CallInst &CI) { | ||||
3339 | Assert(!CI.isInlineAsm(), "cannot use musttail call with inline asm", &CI)do { if (!(!CI.isInlineAsm())) { CheckFailed("cannot use musttail call with inline asm" , &CI); return; } } while (false); | ||||
3340 | |||||
3341 | Function *F = CI.getParent()->getParent(); | ||||
3342 | FunctionType *CallerTy = F->getFunctionType(); | ||||
3343 | FunctionType *CalleeTy = CI.getFunctionType(); | ||||
3344 | Assert(CallerTy->isVarArg() == CalleeTy->isVarArg(),do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false) | ||||
3345 | "cannot guarantee tail call due to mismatched varargs", &CI)do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false); | ||||
3346 | Assert(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()),do { if (!(isTypeCongruent(CallerTy->getReturnType(), CalleeTy ->getReturnType()))) { CheckFailed("cannot guarantee tail call due to mismatched return types" , &CI); return; } } while (false) | ||||
3347 | "cannot guarantee tail call due to mismatched return types", &CI)do { if (!(isTypeCongruent(CallerTy->getReturnType(), CalleeTy ->getReturnType()))) { CheckFailed("cannot guarantee tail call due to mismatched return types" , &CI); return; } } while (false); | ||||
3348 | |||||
3349 | // - The calling conventions of the caller and callee must match. | ||||
3350 | Assert(F->getCallingConv() == CI.getCallingConv(),do { if (!(F->getCallingConv() == CI.getCallingConv())) { CheckFailed ("cannot guarantee tail call due to mismatched calling conv", &CI); return; } } while (false) | ||||
3351 | "cannot guarantee tail call due to mismatched calling conv", &CI)do { if (!(F->getCallingConv() == CI.getCallingConv())) { CheckFailed ("cannot guarantee tail call due to mismatched calling conv", &CI); return; } } while (false); | ||||
3352 | |||||
3353 | // - The call must immediately precede a :ref:`ret <i_ret>` instruction, | ||||
3354 | // or a pointer bitcast followed by a ret instruction. | ||||
3355 | // - The ret instruction must return the (possibly bitcasted) value | ||||
3356 | // produced by the call or void. | ||||
3357 | Value *RetVal = &CI; | ||||
3358 | Instruction *Next = CI.getNextNode(); | ||||
3359 | |||||
3360 | // Handle the optional bitcast. | ||||
3361 | if (BitCastInst *BI = dyn_cast_or_null<BitCastInst>(Next)) { | ||||
3362 | Assert(BI->getOperand(0) == RetVal,do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false) | ||||
3363 | "bitcast following musttail call must use the call", BI)do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false); | ||||
3364 | RetVal = BI; | ||||
3365 | Next = BI->getNextNode(); | ||||
3366 | } | ||||
3367 | |||||
3368 | // Check the return. | ||||
3369 | ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next); | ||||
3370 | Assert(Ret, "musttail call must precede a ret with an optional bitcast",do { if (!(Ret)) { CheckFailed("musttail call must precede a ret with an optional bitcast" , &CI); return; } } while (false) | ||||
3371 | &CI)do { if (!(Ret)) { CheckFailed("musttail call must precede a ret with an optional bitcast" , &CI); return; } } while (false); | ||||
3372 | Assert(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal ||do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false) | ||||
3373 | isa<UndefValue>(Ret->getReturnValue()),do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false) | ||||
3374 | "musttail call result must be returned", Ret)do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false); | ||||
3375 | |||||
3376 | AttributeList CallerAttrs = F->getAttributes(); | ||||
3377 | AttributeList CalleeAttrs = CI.getAttributes(); | ||||
3378 | if (CI.getCallingConv() == CallingConv::SwiftTail || | ||||
3379 | CI.getCallingConv() == CallingConv::Tail) { | ||||
3380 | StringRef CCName = | ||||
3381 | CI.getCallingConv() == CallingConv::Tail ? "tailcc" : "swifttailcc"; | ||||
3382 | |||||
3383 | // - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes | ||||
3384 | // are allowed in swifttailcc call | ||||
3385 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3386 | AttrBuilder ABIAttrs = getParameterABIAttributes(I, CallerAttrs); | ||||
3387 | SmallString<32> Context{CCName, StringRef(" musttail caller")}; | ||||
3388 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
3389 | } | ||||
3390 | for (int I = 0, E = CalleeTy->getNumParams(); I != E; ++I) { | ||||
3391 | AttrBuilder ABIAttrs = getParameterABIAttributes(I, CalleeAttrs); | ||||
3392 | SmallString<32> Context{CCName, StringRef(" musttail callee")}; | ||||
3393 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
3394 | } | ||||
3395 | // - Varargs functions are not allowed | ||||
3396 | Assert(!CallerTy->isVarArg(), Twine("cannot guarantee ") + CCName +do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false) | ||||
3397 | " tail call for varargs function")do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false); | ||||
3398 | return; | ||||
3399 | } | ||||
3400 | |||||
3401 | // - The caller and callee prototypes must match. Pointer types of | ||||
3402 | // parameters or return types may differ in pointee type, but not | ||||
3403 | // address space. | ||||
3404 | if (!CI.getCalledFunction() || !CI.getCalledFunction()->isIntrinsic()) { | ||||
3405 | Assert(CallerTy->getNumParams() == CalleeTy->getNumParams(),do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false) | ||||
3406 | "cannot guarantee tail call due to mismatched parameter counts",do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false) | ||||
3407 | &CI)do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false); | ||||
3408 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3409 | Assert(do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
3410 | isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)),do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
3411 | "cannot guarantee tail call due to mismatched parameter types", &CI)do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false); | ||||
3412 | } | ||||
3413 | } | ||||
3414 | |||||
3415 | // - All ABI-impacting function attributes, such as sret, byval, inreg, | ||||
3416 | // returned, preallocated, and inalloca, must match. | ||||
3417 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3418 | AttrBuilder CallerABIAttrs = getParameterABIAttributes(I, CallerAttrs); | ||||
3419 | AttrBuilder CalleeABIAttrs = getParameterABIAttributes(I, CalleeAttrs); | ||||
3420 | Assert(CallerABIAttrs == CalleeABIAttrs,do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
3421 | "cannot guarantee tail call due to mismatched ABI impacting "do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
3422 | "function attributes",do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
3423 | &CI, CI.getOperand(I))do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false); | ||||
3424 | } | ||||
3425 | } | ||||
3426 | |||||
3427 | void Verifier::visitCallInst(CallInst &CI) { | ||||
3428 | visitCallBase(CI); | ||||
3429 | |||||
3430 | if (CI.isMustTailCall()) | ||||
3431 | verifyMustTailCall(CI); | ||||
3432 | } | ||||
3433 | |||||
3434 | void Verifier::visitInvokeInst(InvokeInst &II) { | ||||
3435 | visitCallBase(II); | ||||
3436 | |||||
3437 | // Verify that the first non-PHI instruction of the unwind destination is an | ||||
3438 | // exception handling instruction. | ||||
3439 | Assert(do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
3440 | II.getUnwindDest()->isEHPad(),do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
3441 | "The unwind destination does not have an exception handling instruction!",do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
3442 | &II)do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false); | ||||
3443 | |||||
3444 | visitTerminator(II); | ||||
3445 | } | ||||
3446 | |||||
3447 | /// visitUnaryOperator - Check the argument to the unary operator. | ||||
3448 | /// | ||||
3449 | void Verifier::visitUnaryOperator(UnaryOperator &U) { | ||||
3450 | Assert(U.getType() == U.getOperand(0)->getType(),do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
3451 | "Unary operators must have same type for"do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
3452 | "operands and result!",do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
3453 | &U)do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false); | ||||
3454 | |||||
3455 | switch (U.getOpcode()) { | ||||
3456 | // Check that floating-point arithmetic operators are only used with | ||||
3457 | // floating-point operands. | ||||
3458 | case Instruction::FNeg: | ||||
3459 | Assert(U.getType()->isFPOrFPVectorTy(),do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false) | ||||
3460 | "FNeg operator only works with float types!", &U)do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false); | ||||
3461 | break; | ||||
3462 | default: | ||||
3463 | llvm_unreachable("Unknown UnaryOperator opcode!")::llvm::llvm_unreachable_internal("Unknown UnaryOperator opcode!" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 3463); | ||||
3464 | } | ||||
3465 | |||||
3466 | visitInstruction(U); | ||||
3467 | } | ||||
3468 | |||||
3469 | /// visitBinaryOperator - Check that both arguments to the binary operator are | ||||
3470 | /// of the same type! | ||||
3471 | /// | ||||
3472 | void Verifier::visitBinaryOperator(BinaryOperator &B) { | ||||
3473 | Assert(B.getOperand(0)->getType() == B.getOperand(1)->getType(),do { if (!(B.getOperand(0)->getType() == B.getOperand(1)-> getType())) { CheckFailed("Both operands to a binary operator are not of the same type!" , &B); return; } } while (false) | ||||
3474 | "Both operands to a binary operator are not of the same type!", &B)do { if (!(B.getOperand(0)->getType() == B.getOperand(1)-> getType())) { CheckFailed("Both operands to a binary operator are not of the same type!" , &B); return; } } while (false); | ||||
3475 | |||||
3476 | switch (B.getOpcode()) { | ||||
3477 | // Check that integer arithmetic operators are only used with | ||||
3478 | // integral operands. | ||||
3479 | case Instruction::Add: | ||||
3480 | case Instruction::Sub: | ||||
3481 | case Instruction::Mul: | ||||
3482 | case Instruction::SDiv: | ||||
3483 | case Instruction::UDiv: | ||||
3484 | case Instruction::SRem: | ||||
3485 | case Instruction::URem: | ||||
3486 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false) | ||||
3487 | "Integer arithmetic operators only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false); | ||||
3488 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
3489 | "Integer arithmetic operators must have same type "do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
3490 | "for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
3491 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false); | ||||
3492 | break; | ||||
3493 | // Check that floating-point arithmetic operators are only used with | ||||
3494 | // floating-point operands. | ||||
3495 | case Instruction::FAdd: | ||||
3496 | case Instruction::FSub: | ||||
3497 | case Instruction::FMul: | ||||
3498 | case Instruction::FDiv: | ||||
3499 | case Instruction::FRem: | ||||
3500 | Assert(B.getType()->isFPOrFPVectorTy(),do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
3501 | "Floating-point arithmetic operators only work with "do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
3502 | "floating-point types!",do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
3503 | &B)do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false); | ||||
3504 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
3505 | "Floating-point arithmetic operators must have same type "do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
3506 | "for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
3507 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false); | ||||
3508 | break; | ||||
3509 | // Check that logical operators are only used with integral operands. | ||||
3510 | case Instruction::And: | ||||
3511 | case Instruction::Or: | ||||
3512 | case Instruction::Xor: | ||||
3513 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false) | ||||
3514 | "Logical operators only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false); | ||||
3515 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false) | ||||
3516 | "Logical operators must have same type for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false) | ||||
3517 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false); | ||||
3518 | break; | ||||
3519 | case Instruction::Shl: | ||||
3520 | case Instruction::LShr: | ||||
3521 | case Instruction::AShr: | ||||
3522 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false) | ||||
3523 | "Shifts only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false); | ||||
3524 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Shift return type must be same as operands!", &B); return ; } } while (false) | ||||
3525 | "Shift return type must be same as operands!", &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Shift return type must be same as operands!", &B); return ; } } while (false); | ||||
3526 | break; | ||||
3527 | default: | ||||
3528 | llvm_unreachable("Unknown BinaryOperator opcode!")::llvm::llvm_unreachable_internal("Unknown BinaryOperator opcode!" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 3528); | ||||
3529 | } | ||||
3530 | |||||
3531 | visitInstruction(B); | ||||
3532 | } | ||||
3533 | |||||
3534 | void Verifier::visitICmpInst(ICmpInst &IC) { | ||||
3535 | // Check that the operands are the same type | ||||
3536 | Type *Op0Ty = IC.getOperand(0)->getType(); | ||||
3537 | Type *Op1Ty = IC.getOperand(1)->getType(); | ||||
3538 | Assert(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false) | ||||
3539 | "Both operands to ICmp instruction are not of the same type!", &IC)do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false); | ||||
3540 | // Check that the operands are the right type | ||||
3541 | Assert(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy(),do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false) | ||||
3542 | "Invalid operand types for ICmp instruction", &IC)do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false); | ||||
3543 | // Check that the predicate is valid. | ||||
3544 | Assert(IC.isIntPredicate(),do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false) | ||||
3545 | "Invalid predicate in ICmp instruction!", &IC)do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false); | ||||
3546 | |||||
3547 | visitInstruction(IC); | ||||
3548 | } | ||||
3549 | |||||
3550 | void Verifier::visitFCmpInst(FCmpInst &FC) { | ||||
3551 | // Check that the operands are the same type | ||||
3552 | Type *Op0Ty = FC.getOperand(0)->getType(); | ||||
3553 | Type *Op1Ty = FC.getOperand(1)->getType(); | ||||
3554 | Assert(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false) | ||||
3555 | "Both operands to FCmp instruction are not of the same type!", &FC)do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false); | ||||
3556 | // Check that the operands are the right type | ||||
3557 | Assert(Op0Ty->isFPOrFPVectorTy(),do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false) | ||||
3558 | "Invalid operand types for FCmp instruction", &FC)do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false); | ||||
3559 | // Check that the predicate is valid. | ||||
3560 | Assert(FC.isFPPredicate(),do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false) | ||||
3561 | "Invalid predicate in FCmp instruction!", &FC)do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false); | ||||
3562 | |||||
3563 | visitInstruction(FC); | ||||
3564 | } | ||||
3565 | |||||
3566 | void Verifier::visitExtractElementInst(ExtractElementInst &EI) { | ||||
3567 | Assert(do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false) | ||||
3568 | ExtractElementInst::isValidOperands(EI.getOperand(0), EI.getOperand(1)),do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false) | ||||
3569 | "Invalid extractelement operands!", &EI)do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false); | ||||
3570 | visitInstruction(EI); | ||||
3571 | } | ||||
3572 | |||||
3573 | void Verifier::visitInsertElementInst(InsertElementInst &IE) { | ||||
3574 | Assert(InsertElementInst::isValidOperands(IE.getOperand(0), IE.getOperand(1),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
3575 | IE.getOperand(2)),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
3576 | "Invalid insertelement operands!", &IE)do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false); | ||||
3577 | visitInstruction(IE); | ||||
3578 | } | ||||
3579 | |||||
3580 | void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) { | ||||
3581 | Assert(ShuffleVectorInst::isValidOperands(SV.getOperand(0), SV.getOperand(1),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
3582 | SV.getShuffleMask()),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
3583 | "Invalid shufflevector operands!", &SV)do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false); | ||||
3584 | visitInstruction(SV); | ||||
3585 | } | ||||
3586 | |||||
3587 | void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { | ||||
3588 | Type *TargetTy = GEP.getPointerOperandType()->getScalarType(); | ||||
3589 | |||||
3590 | Assert(isa<PointerType>(TargetTy),do { if (!(isa<PointerType>(TargetTy))) { CheckFailed("GEP base pointer is not a vector or a vector of pointers" , &GEP); return; } } while (false) | ||||
3591 | "GEP base pointer is not a vector or a vector of pointers", &GEP)do { if (!(isa<PointerType>(TargetTy))) { CheckFailed("GEP base pointer is not a vector or a vector of pointers" , &GEP); return; } } while (false); | ||||
3592 | Assert(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP)do { if (!(GEP.getSourceElementType()->isSized())) { CheckFailed ("GEP into unsized type!", &GEP); return; } } while (false ); | ||||
3593 | |||||
3594 | SmallVector<Value *, 16> Idxs(GEP.indices()); | ||||
3595 | Assert(all_of(do { if (!(all_of( Idxs, [](Value* V) { return V->getType( )->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
3596 | Idxs, [](Value* V) { return V->getType()->isIntOrIntVectorTy(); }),do { if (!(all_of( Idxs, [](Value* V) { return V->getType( )->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
3597 | "GEP indexes must be integers", &GEP)do { if (!(all_of( Idxs, [](Value* V) { return V->getType( )->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false); | ||||
3598 | Type *ElTy = | ||||
3599 | GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs); | ||||
3600 | Assert(ElTy, "Invalid indices for GEP pointer type!", &GEP)do { if (!(ElTy)) { CheckFailed("Invalid indices for GEP pointer type!" , &GEP); return; } } while (false); | ||||
3601 | |||||
3602 | Assert(GEP.getType()->isPtrOrPtrVectorTy() &&do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false) | ||||
3603 | GEP.getResultElementType() == ElTy,do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false) | ||||
3604 | "GEP is not of right type for indices!", &GEP, ElTy)do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false); | ||||
3605 | |||||
3606 | if (auto *GEPVTy = dyn_cast<VectorType>(GEP.getType())) { | ||||
3607 | // Additional checks for vector GEPs. | ||||
3608 | ElementCount GEPWidth = GEPVTy->getElementCount(); | ||||
3609 | if (GEP.getPointerOperandType()->isVectorTy()) | ||||
3610 | Assert(do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
3611 | GEPWidth ==do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
3612 | cast<VectorType>(GEP.getPointerOperandType())->getElementCount(),do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
3613 | "Vector GEP result width doesn't match operand's", &GEP)do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false); | ||||
3614 | for (Value *Idx : Idxs) { | ||||
3615 | Type *IndexTy = Idx->getType(); | ||||
3616 | if (auto *IndexVTy = dyn_cast<VectorType>(IndexTy)) { | ||||
3617 | ElementCount IndexWidth = IndexVTy->getElementCount(); | ||||
3618 | Assert(IndexWidth == GEPWidth, "Invalid GEP index vector width", &GEP)do { if (!(IndexWidth == GEPWidth)) { CheckFailed("Invalid GEP index vector width" , &GEP); return; } } while (false); | ||||
3619 | } | ||||
3620 | Assert(IndexTy->isIntOrIntVectorTy(),do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false) | ||||
3621 | "All GEP indices should be of integer type")do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false); | ||||
3622 | } | ||||
3623 | } | ||||
3624 | |||||
3625 | if (auto *PTy = dyn_cast<PointerType>(GEP.getType())) { | ||||
3626 | Assert(GEP.getAddressSpace() == PTy->getAddressSpace(),do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false) | ||||
3627 | "GEP address space doesn't match type", &GEP)do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false); | ||||
3628 | } | ||||
3629 | |||||
3630 | visitInstruction(GEP); | ||||
3631 | } | ||||
3632 | |||||
3633 | static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { | ||||
3634 | return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); | ||||
3635 | } | ||||
3636 | |||||
3637 | void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { | ||||
3638 | assert(Range && Range == I.getMetadata(LLVMContext::MD_range) &&(static_cast <bool> (Range && Range == I.getMetadata (LLVMContext::MD_range) && "precondition violation") ? void (0) : __assert_fail ("Range && Range == I.getMetadata(LLVMContext::MD_range) && \"precondition violation\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 3639, __extension__ __PRETTY_FUNCTION__)) | ||||
3639 | "precondition violation")(static_cast <bool> (Range && Range == I.getMetadata (LLVMContext::MD_range) && "precondition violation") ? void (0) : __assert_fail ("Range && Range == I.getMetadata(LLVMContext::MD_range) && \"precondition violation\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 3639, __extension__ __PRETTY_FUNCTION__)); | ||||
3640 | |||||
3641 | unsigned NumOperands = Range->getNumOperands(); | ||||
3642 | Assert(NumOperands % 2 == 0, "Unfinished range!", Range)do { if (!(NumOperands % 2 == 0)) { CheckFailed("Unfinished range!" , Range); return; } } while (false); | ||||
3643 | unsigned NumRanges = NumOperands / 2; | ||||
3644 | Assert(NumRanges >= 1, "It should have at least one range!", Range)do { if (!(NumRanges >= 1)) { CheckFailed("It should have at least one range!" , Range); return; } } while (false); | ||||
3645 | |||||
3646 | ConstantRange LastRange(1, true); // Dummy initial value | ||||
3647 | for (unsigned i = 0; i < NumRanges; ++i) { | ||||
3648 | ConstantInt *Low = | ||||
3649 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i)); | ||||
3650 | Assert(Low, "The lower limit must be an integer!", Low)do { if (!(Low)) { CheckFailed("The lower limit must be an integer!" , Low); return; } } while (false); | ||||
3651 | ConstantInt *High = | ||||
3652 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i + 1)); | ||||
3653 | Assert(High, "The upper limit must be an integer!", High)do { if (!(High)) { CheckFailed("The upper limit must be an integer!" , High); return; } } while (false); | ||||
3654 | Assert(High->getType() == Low->getType() && High->getType() == Ty,do { if (!(High->getType() == Low->getType() && High->getType() == Ty)) { CheckFailed("Range types must match instruction type!" , &I); return; } } while (false) | ||||
3655 | "Range types must match instruction type!", &I)do { if (!(High->getType() == Low->getType() && High->getType() == Ty)) { CheckFailed("Range types must match instruction type!" , &I); return; } } while (false); | ||||
3656 | |||||
3657 | APInt HighV = High->getValue(); | ||||
3658 | APInt LowV = Low->getValue(); | ||||
3659 | ConstantRange CurRange(LowV, HighV); | ||||
3660 | Assert(!CurRange.isEmptySet() && !CurRange.isFullSet(),do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false) | ||||
3661 | "Range must not be empty!", Range)do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false); | ||||
3662 | if (i != 0) { | ||||
3663 | Assert(CurRange.intersectWith(LastRange).isEmptySet(),do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
3664 | "Intervals are overlapping", Range)do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
3665 | Assert(LowV.sgt(LastRange.getLower()), "Intervals are not in order",do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false) | ||||
3666 | Range)do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false); | ||||
3667 | Assert(!isContiguous(CurRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
3668 | Range)do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
3669 | } | ||||
3670 | LastRange = ConstantRange(LowV, HighV); | ||||
3671 | } | ||||
3672 | if (NumRanges > 2) { | ||||
3673 | APInt FirstLow = | ||||
3674 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(0))->getValue(); | ||||
3675 | APInt FirstHigh = | ||||
3676 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(1))->getValue(); | ||||
3677 | ConstantRange FirstRange(FirstLow, FirstHigh); | ||||
3678 | Assert(FirstRange.intersectWith(LastRange).isEmptySet(),do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
3679 | "Intervals are overlapping", Range)do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
3680 | Assert(!isContiguous(FirstRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
3681 | Range)do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
3682 | } | ||||
3683 | } | ||||
3684 | |||||
3685 | void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) { | ||||
3686 | unsigned Size = DL.getTypeSizeInBits(Ty); | ||||
3687 | Assert(Size >= 8, "atomic memory access' size must be byte-sized", Ty, I)do { if (!(Size >= 8)) { CheckFailed("atomic memory access' size must be byte-sized" , Ty, I); return; } } while (false); | ||||
3688 | Assert(!(Size & (Size - 1)),do { if (!(!(Size & (Size - 1)))) { CheckFailed("atomic memory access' operand must have a power-of-two size" , Ty, I); return; } } while (false) | ||||
3689 | "atomic memory access' operand must have a power-of-two size", Ty, I)do { if (!(!(Size & (Size - 1)))) { CheckFailed("atomic memory access' operand must have a power-of-two size" , Ty, I); return; } } while (false); | ||||
3690 | } | ||||
3691 | |||||
3692 | void Verifier::visitLoadInst(LoadInst &LI) { | ||||
3693 | PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType()); | ||||
3694 | Assert(PTy, "Load operand must be a pointer.", &LI)do { if (!(PTy)) { CheckFailed("Load operand must be a pointer." , &LI); return; } } while (false); | ||||
3695 | Type *ElTy = LI.getType(); | ||||
3696 | Assert(LI.getAlignment() <= Value::MaximumAlignment,do { if (!(LI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &LI ); return; } } while (false) | ||||
3697 | "huge alignment values are unsupported", &LI)do { if (!(LI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &LI ); return; } } while (false); | ||||
3698 | Assert(ElTy->isSized(), "loading unsized types is not allowed", &LI)do { if (!(ElTy->isSized())) { CheckFailed("loading unsized types is not allowed" , &LI); return; } } while (false); | ||||
3699 | if (LI.isAtomic()) { | ||||
3700 | Assert(LI.getOrdering() != AtomicOrdering::Release &&do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
3701 | LI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
3702 | "Load cannot have Release ordering", &LI)do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false); | ||||
3703 | Assert(LI.getAlignment() != 0,do { if (!(LI.getAlignment() != 0)) { CheckFailed("Atomic load must specify explicit alignment" , &LI); return; } } while (false) | ||||
3704 | "Atomic load must specify explicit alignment", &LI)do { if (!(LI.getAlignment() != 0)) { CheckFailed("Atomic load must specify explicit alignment" , &LI); return; } } while (false); | ||||
3705 | Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
3706 | "atomic load operand must have integer, pointer, or floating point "do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
3707 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
3708 | ElTy, &LI)do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false); | ||||
3709 | checkAtomicMemAccessSize(ElTy, &LI); | ||||
3710 | } else { | ||||
3711 | Assert(LI.getSyncScopeID() == SyncScope::System,do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false) | ||||
3712 | "Non-atomic load cannot have SynchronizationScope specified", &LI)do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false); | ||||
3713 | } | ||||
3714 | |||||
3715 | visitInstruction(LI); | ||||
3716 | } | ||||
3717 | |||||
3718 | void Verifier::visitStoreInst(StoreInst &SI) { | ||||
3719 | PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType()); | ||||
3720 | Assert(PTy, "Store operand must be a pointer.", &SI)do { if (!(PTy)) { CheckFailed("Store operand must be a pointer." , &SI); return; } } while (false); | ||||
3721 | Type *ElTy = SI.getOperand(0)->getType(); | ||||
3722 | Assert(PTy->isOpaqueOrPointeeTypeMatches(ElTy),do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false) | ||||
3723 | "Stored value type does not match pointer operand type!", &SI, ElTy)do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false); | ||||
3724 | Assert(SI.getAlignment() <= Value::MaximumAlignment,do { if (!(SI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &SI ); return; } } while (false) | ||||
3725 | "huge alignment values are unsupported", &SI)do { if (!(SI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &SI ); return; } } while (false); | ||||
3726 | Assert(ElTy->isSized(), "storing unsized types is not allowed", &SI)do { if (!(ElTy->isSized())) { CheckFailed("storing unsized types is not allowed" , &SI); return; } } while (false); | ||||
3727 | if (SI.isAtomic()) { | ||||
3728 | Assert(SI.getOrdering() != AtomicOrdering::Acquire &&do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
3729 | SI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
3730 | "Store cannot have Acquire ordering", &SI)do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false); | ||||
3731 | Assert(SI.getAlignment() != 0,do { if (!(SI.getAlignment() != 0)) { CheckFailed("Atomic store must specify explicit alignment" , &SI); return; } } while (false) | ||||
3732 | "Atomic store must specify explicit alignment", &SI)do { if (!(SI.getAlignment() != 0)) { CheckFailed("Atomic store must specify explicit alignment" , &SI); return; } } while (false); | ||||
3733 | Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
3734 | "atomic store operand must have integer, pointer, or floating point "do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
3735 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
3736 | ElTy, &SI)do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false); | ||||
3737 | checkAtomicMemAccessSize(ElTy, &SI); | ||||
3738 | } else { | ||||
3739 | Assert(SI.getSyncScopeID() == SyncScope::System,do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false) | ||||
3740 | "Non-atomic store cannot have SynchronizationScope specified", &SI)do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false); | ||||
3741 | } | ||||
3742 | visitInstruction(SI); | ||||
3743 | } | ||||
3744 | |||||
3745 | /// Check that SwiftErrorVal is used as a swifterror argument in CS. | ||||
3746 | void Verifier::verifySwiftErrorCall(CallBase &Call, | ||||
3747 | const Value *SwiftErrorVal) { | ||||
3748 | for (const auto &I : llvm::enumerate(Call.args())) { | ||||
3749 | if (I.value() == SwiftErrorVal) { | ||||
3750 | Assert(Call.paramHasAttr(I.index(), Attribute::SwiftError),do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
3751 | "swifterror value when used in a callsite should be marked "do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
3752 | "with swifterror attribute",do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
3753 | SwiftErrorVal, Call)do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false); | ||||
3754 | } | ||||
3755 | } | ||||
3756 | } | ||||
3757 | |||||
3758 | void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) { | ||||
3759 | // Check that swifterror value is only used by loads, stores, or as | ||||
3760 | // a swifterror argument. | ||||
3761 | for (const User *U : SwiftErrorVal->users()) { | ||||
3762 | Assert(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) ||do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
3763 | isa<InvokeInst>(U),do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
3764 | "swifterror value can only be loaded and stored from, or "do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
3765 | "as a swifterror argument!",do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
3766 | SwiftErrorVal, U)do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false); | ||||
3767 | // If it is used by a store, check it is the second operand. | ||||
3768 | if (auto StoreI = dyn_cast<StoreInst>(U)) | ||||
3769 | Assert(StoreI->getOperand(1) == SwiftErrorVal,do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
3770 | "swifterror value should be the second operand when used "do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
3771 | "by stores", SwiftErrorVal, U)do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false); | ||||
3772 | if (auto *Call = dyn_cast<CallBase>(U)) | ||||
3773 | verifySwiftErrorCall(*const_cast<CallBase *>(Call), SwiftErrorVal); | ||||
3774 | } | ||||
3775 | } | ||||
3776 | |||||
3777 | void Verifier::visitAllocaInst(AllocaInst &AI) { | ||||
3778 | SmallPtrSet<Type*, 4> Visited; | ||||
3779 | Assert(AI.getAllocatedType()->isSized(&Visited),do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false) | ||||
3780 | "Cannot allocate unsized type", &AI)do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false); | ||||
3781 | Assert(AI.getArraySize()->getType()->isIntegerTy(),do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false) | ||||
3782 | "Alloca array size must have integer type", &AI)do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false); | ||||
3783 | Assert(AI.getAlignment() <= Value::MaximumAlignment,do { if (!(AI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &AI ); return; } } while (false) | ||||
3784 | "huge alignment values are unsupported", &AI)do { if (!(AI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &AI ); return; } } while (false); | ||||
3785 | |||||
3786 | if (AI.isSwiftError()) { | ||||
3787 | verifySwiftErrorValue(&AI); | ||||
3788 | } | ||||
3789 | |||||
3790 | visitInstruction(AI); | ||||
3791 | } | ||||
3792 | |||||
3793 | void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { | ||||
3794 | Type *ElTy = CXI.getOperand(1)->getType(); | ||||
3795 | Assert(ElTy->isIntOrPtrTy(),do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false) | ||||
3796 | "cmpxchg operand must have integer or pointer type", ElTy, &CXI)do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false); | ||||
3797 | checkAtomicMemAccessSize(ElTy, &CXI); | ||||
3798 | visitInstruction(CXI); | ||||
3799 | } | ||||
3800 | |||||
3801 | void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { | ||||
3802 | Assert(RMWI.getOrdering() != AtomicOrdering::Unordered,do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false) | ||||
3803 | "atomicrmw instructions cannot be unordered.", &RMWI)do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false); | ||||
3804 | auto Op = RMWI.getOperation(); | ||||
3805 | Type *ElTy = RMWI.getOperand(1)->getType(); | ||||
3806 | if (Op == AtomicRMWInst::Xchg) { | ||||
3807 | Assert(ElTy->isIntegerTy() || ElTy->isFloatingPointTy(), "atomicrmw " +do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false) | ||||
3808 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false) | ||||
3809 | " operand must have integer or floating point type!",do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false) | ||||
3810 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false); | ||||
3811 | } else if (AtomicRMWInst::isFPOperation(Op)) { | ||||
3812 | Assert(ElTy->isFloatingPointTy(), "atomicrmw " +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
3813 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
3814 | " operand must have floating point type!",do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
3815 | &RMWI, ElTy)do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false); | ||||
3816 | } else { | ||||
3817 | Assert(ElTy->isIntegerTy(), "atomicrmw " +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
3818 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
3819 | " operand must have integer type!",do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
3820 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false); | ||||
3821 | } | ||||
3822 | checkAtomicMemAccessSize(ElTy, &RMWI); | ||||
3823 | Assert(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP,do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false) | ||||
3824 | "Invalid binary operation!", &RMWI)do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false); | ||||
3825 | visitInstruction(RMWI); | ||||
3826 | } | ||||
3827 | |||||
3828 | void Verifier::visitFenceInst(FenceInst &FI) { | ||||
3829 | const AtomicOrdering Ordering = FI.getOrdering(); | ||||
3830 | Assert(Ordering == AtomicOrdering::Acquire ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
3831 | Ordering == AtomicOrdering::Release ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
3832 | Ordering == AtomicOrdering::AcquireRelease ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
3833 | Ordering == AtomicOrdering::SequentiallyConsistent,do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
3834 | "fence instructions may only have acquire, release, acq_rel, or "do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
3835 | "seq_cst ordering.",do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
3836 | &FI)do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false); | ||||
3837 | visitInstruction(FI); | ||||
3838 | } | ||||
3839 | |||||
3840 | void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { | ||||
3841 | Assert(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
3842 | EVI.getIndices()) == EVI.getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
3843 | "Invalid ExtractValueInst operands!", &EVI)do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false); | ||||
3844 | |||||
3845 | visitInstruction(EVI); | ||||
3846 | } | ||||
3847 | |||||
3848 | void Verifier::visitInsertValueInst(InsertValueInst &IVI) { | ||||
3849 | Assert(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(),do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
3850 | IVI.getIndices()) ==do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
3851 | IVI.getOperand(1)->getType(),do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
3852 | "Invalid InsertValueInst operands!", &IVI)do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false); | ||||
3853 | |||||
3854 | visitInstruction(IVI); | ||||
3855 | } | ||||
3856 | |||||
3857 | static Value *getParentPad(Value *EHPad) { | ||||
3858 | if (auto *FPI = dyn_cast<FuncletPadInst>(EHPad)) | ||||
3859 | return FPI->getParentPad(); | ||||
3860 | |||||
3861 | return cast<CatchSwitchInst>(EHPad)->getParentPad(); | ||||
3862 | } | ||||
3863 | |||||
3864 | void Verifier::visitEHPadPredecessors(Instruction &I) { | ||||
3865 | assert(I.isEHPad())(static_cast <bool> (I.isEHPad()) ? void (0) : __assert_fail ("I.isEHPad()", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 3865, __extension__ __PRETTY_FUNCTION__)); | ||||
3866 | |||||
3867 | BasicBlock *BB = I.getParent(); | ||||
3868 | Function *F = BB->getParent(); | ||||
3869 | |||||
3870 | Assert(BB != &F->getEntryBlock(), "EH pad cannot be in entry block.", &I)do { if (!(BB != &F->getEntryBlock())) { CheckFailed("EH pad cannot be in entry block." , &I); return; } } while (false); | ||||
3871 | |||||
3872 | if (auto *LPI = dyn_cast<LandingPadInst>(&I)) { | ||||
3873 | // The landingpad instruction defines its parent as a landing pad block. The | ||||
3874 | // landing pad block may be branched to only by the unwind edge of an | ||||
3875 | // invoke. | ||||
3876 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
3877 | const auto *II = dyn_cast<InvokeInst>(PredBB->getTerminator()); | ||||
3878 | Assert(II && II->getUnwindDest() == BB && II->getNormalDest() != BB,do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
3879 | "Block containing LandingPadInst must be jumped to "do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
3880 | "only by the unwind edge of an invoke.",do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
3881 | LPI)do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false); | ||||
3882 | } | ||||
3883 | return; | ||||
3884 | } | ||||
3885 | if (auto *CPI = dyn_cast<CatchPadInst>(&I)) { | ||||
3886 | if (!pred_empty(BB)) | ||||
3887 | Assert(BB->getUniquePredecessor() == CPI->getCatchSwitch()->getParent(),do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
3888 | "Block containg CatchPadInst must be jumped to "do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
3889 | "only by its catchswitch.",do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
3890 | CPI)do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false); | ||||
3891 | Assert(BB != CPI->getCatchSwitch()->getUnwindDest(),do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false) | ||||
3892 | "Catchswitch cannot unwind to one of its catchpads",do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false) | ||||
3893 | CPI->getCatchSwitch(), CPI)do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false); | ||||
3894 | return; | ||||
3895 | } | ||||
3896 | |||||
3897 | // Verify that each pred has a legal terminator with a legal to/from EH | ||||
3898 | // pad relationship. | ||||
3899 | Instruction *ToPad = &I; | ||||
3900 | Value *ToPadParent = getParentPad(ToPad); | ||||
3901 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
3902 | Instruction *TI = PredBB->getTerminator(); | ||||
3903 | Value *FromPad; | ||||
3904 | if (auto *II = dyn_cast<InvokeInst>(TI)) { | ||||
3905 | Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB,do { if (!(II->getUnwindDest() == BB && II->getNormalDest () != BB)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, II); return; } } while (false) | ||||
3906 | "EH pad must be jumped to via an unwind edge", ToPad, II)do { if (!(II->getUnwindDest() == BB && II->getNormalDest () != BB)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, II); return; } } while (false); | ||||
3907 | if (auto Bundle = II->getOperandBundle(LLVMContext::OB_funclet)) | ||||
3908 | FromPad = Bundle->Inputs[0]; | ||||
3909 | else | ||||
3910 | FromPad = ConstantTokenNone::get(II->getContext()); | ||||
3911 | } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) { | ||||
3912 | FromPad = CRI->getOperand(0); | ||||
3913 | Assert(FromPad != ToPadParent, "A cleanupret must exit its cleanup", CRI)do { if (!(FromPad != ToPadParent)) { CheckFailed("A cleanupret must exit its cleanup" , CRI); return; } } while (false); | ||||
3914 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) { | ||||
3915 | FromPad = CSI; | ||||
3916 | } else { | ||||
3917 | Assert(false, "EH pad must be jumped to via an unwind edge", ToPad, TI)do { if (!(false)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, TI); return; } } while (false); | ||||
3918 | } | ||||
3919 | |||||
3920 | // The edge may exit from zero or more nested pads. | ||||
3921 | SmallSet<Value *, 8> Seen; | ||||
3922 | for (;; FromPad = getParentPad(FromPad)) { | ||||
3923 | Assert(FromPad != ToPad,do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false) | ||||
3924 | "EH pad cannot handle exceptions raised within it", FromPad, TI)do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false); | ||||
3925 | if (FromPad == ToPadParent) { | ||||
3926 | // This is a legal unwind edge. | ||||
3927 | break; | ||||
3928 | } | ||||
3929 | Assert(!isa<ConstantTokenNone>(FromPad),do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false) | ||||
3930 | "A single unwind edge may only enter one EH pad", TI)do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false); | ||||
3931 | Assert(Seen.insert(FromPad).second,do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false) | ||||
3932 | "EH pad jumps through a cycle of pads", FromPad)do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false); | ||||
3933 | } | ||||
3934 | } | ||||
3935 | } | ||||
3936 | |||||
3937 | void Verifier::visitLandingPadInst(LandingPadInst &LPI) { | ||||
3938 | // The landingpad instruction is ill-formed if it doesn't have any clauses and | ||||
3939 | // isn't a cleanup. | ||||
3940 | Assert(LPI.getNumClauses() > 0 || LPI.isCleanup(),do { if (!(LPI.getNumClauses() > 0 || LPI.isCleanup())) { CheckFailed ("LandingPadInst needs at least one clause or to be a cleanup." , &LPI); return; } } while (false) | ||||
3941 | "LandingPadInst needs at least one clause or to be a cleanup.", &LPI)do { if (!(LPI.getNumClauses() > 0 || LPI.isCleanup())) { CheckFailed ("LandingPadInst needs at least one clause or to be a cleanup." , &LPI); return; } } while (false); | ||||
3942 | |||||
3943 | visitEHPadPredecessors(LPI); | ||||
3944 | |||||
3945 | if (!LandingPadResultTy) | ||||
3946 | LandingPadResultTy = LPI.getType(); | ||||
3947 | else | ||||
3948 | Assert(LandingPadResultTy == LPI.getType(),do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
3949 | "The landingpad instruction should have a consistent result type "do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
3950 | "inside a function.",do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
3951 | &LPI)do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false); | ||||
3952 | |||||
3953 | Function *F = LPI.getParent()->getParent(); | ||||
3954 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false) | ||||
3955 | "LandingPadInst needs to be in a function with a personality.", &LPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false); | ||||
3956 | |||||
3957 | // The landingpad instruction must be the first non-PHI instruction in the | ||||
3958 | // block. | ||||
3959 | Assert(LPI.getParent()->getLandingPadInst() == &LPI,do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false) | ||||
3960 | "LandingPadInst not the first non-PHI instruction in the block.",do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false) | ||||
3961 | &LPI)do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false); | ||||
3962 | |||||
3963 | for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) { | ||||
3964 | Constant *Clause = LPI.getClause(i); | ||||
3965 | if (LPI.isCatch(i)) { | ||||
3966 | Assert(isa<PointerType>(Clause->getType()),do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false) | ||||
3967 | "Catch operand does not have pointer type!", &LPI)do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false); | ||||
3968 | } else { | ||||
3969 | Assert(LPI.isFilter(i), "Clause is neither catch nor filter!", &LPI)do { if (!(LPI.isFilter(i))) { CheckFailed("Clause is neither catch nor filter!" , &LPI); return; } } while (false); | ||||
3970 | Assert(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero>(Clause),do { if (!(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero >(Clause))) { CheckFailed("Filter operand is not an array of constants!" , &LPI); return; } } while (false) | ||||
3971 | "Filter operand is not an array of constants!", &LPI)do { if (!(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero >(Clause))) { CheckFailed("Filter operand is not an array of constants!" , &LPI); return; } } while (false); | ||||
3972 | } | ||||
3973 | } | ||||
3974 | |||||
3975 | visitInstruction(LPI); | ||||
3976 | } | ||||
3977 | |||||
3978 | void Verifier::visitResumeInst(ResumeInst &RI) { | ||||
3979 | Assert(RI.getFunction()->hasPersonalityFn(),do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false) | ||||
3980 | "ResumeInst needs to be in a function with a personality.", &RI)do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false); | ||||
3981 | |||||
3982 | if (!LandingPadResultTy) | ||||
3983 | LandingPadResultTy = RI.getValue()->getType(); | ||||
3984 | else | ||||
3985 | Assert(LandingPadResultTy == RI.getValue()->getType(),do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
3986 | "The resume instruction should have a consistent result type "do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
3987 | "inside a function.",do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
3988 | &RI)do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false); | ||||
3989 | |||||
3990 | visitTerminator(RI); | ||||
3991 | } | ||||
3992 | |||||
3993 | void Verifier::visitCatchPadInst(CatchPadInst &CPI) { | ||||
3994 | BasicBlock *BB = CPI.getParent(); | ||||
3995 | |||||
3996 | Function *F = BB->getParent(); | ||||
3997 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
3998 | "CatchPadInst needs to be in a function with a personality.", &CPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false); | ||||
3999 | |||||
4000 | Assert(isa<CatchSwitchInst>(CPI.getParentPad()),do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false) | ||||
4001 | "CatchPadInst needs to be directly nested in a CatchSwitchInst.",do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false) | ||||
4002 | CPI.getParentPad())do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false); | ||||
4003 | |||||
4004 | // The catchpad instruction must be the first non-PHI instruction in the | ||||
4005 | // block. | ||||
4006 | Assert(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
4007 | "CatchPadInst not the first non-PHI instruction in the block.", &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
4008 | |||||
4009 | visitEHPadPredecessors(CPI); | ||||
4010 | visitFuncletPadInst(CPI); | ||||
4011 | } | ||||
4012 | |||||
4013 | void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) { | ||||
4014 | Assert(isa<CatchPadInst>(CatchReturn.getOperand(0)),do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false) | ||||
4015 | "CatchReturnInst needs to be provided a CatchPad", &CatchReturn,do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false) | ||||
4016 | CatchReturn.getOperand(0))do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false); | ||||
4017 | |||||
4018 | visitTerminator(CatchReturn); | ||||
4019 | } | ||||
4020 | |||||
4021 | void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { | ||||
4022 | BasicBlock *BB = CPI.getParent(); | ||||
4023 | |||||
4024 | Function *F = BB->getParent(); | ||||
4025 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
4026 | "CleanupPadInst needs to be in a function with a personality.", &CPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false); | ||||
4027 | |||||
4028 | // The cleanuppad instruction must be the first non-PHI instruction in the | ||||
4029 | // block. | ||||
4030 | Assert(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
4031 | "CleanupPadInst not the first non-PHI instruction in the block.",do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
4032 | &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
4033 | |||||
4034 | auto *ParentPad = CPI.getParentPad(); | ||||
4035 | Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false) | ||||
4036 | "CleanupPadInst has an invalid parent.", &CPI)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false); | ||||
4037 | |||||
4038 | visitEHPadPredecessors(CPI); | ||||
4039 | visitFuncletPadInst(CPI); | ||||
4040 | } | ||||
4041 | |||||
4042 | void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { | ||||
4043 | User *FirstUser = nullptr; | ||||
4044 | Value *FirstUnwindPad = nullptr; | ||||
4045 | SmallVector<FuncletPadInst *, 8> Worklist({&FPI}); | ||||
4046 | SmallSet<FuncletPadInst *, 8> Seen; | ||||
4047 | |||||
4048 | while (!Worklist.empty()) { | ||||
4049 | FuncletPadInst *CurrentPad = Worklist.pop_back_val(); | ||||
4050 | Assert(Seen.insert(CurrentPad).second,do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false) | ||||
4051 | "FuncletPadInst must not be nested within itself", CurrentPad)do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false); | ||||
4052 | Value *UnresolvedAncestorPad = nullptr; | ||||
4053 | for (User *U : CurrentPad->users()) { | ||||
4054 | BasicBlock *UnwindDest; | ||||
4055 | if (auto *CRI = dyn_cast<CleanupReturnInst>(U)) { | ||||
4056 | UnwindDest = CRI->getUnwindDest(); | ||||
4057 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(U)) { | ||||
4058 | // We allow catchswitch unwind to caller to nest | ||||
4059 | // within an outer pad that unwinds somewhere else, | ||||
4060 | // because catchswitch doesn't have a nounwind variant. | ||||
4061 | // See e.g. SimplifyCFGOpt::SimplifyUnreachable. | ||||
4062 | if (CSI->unwindsToCaller()) | ||||
4063 | continue; | ||||
4064 | UnwindDest = CSI->getUnwindDest(); | ||||
4065 | } else if (auto *II = dyn_cast<InvokeInst>(U)) { | ||||
4066 | UnwindDest = II->getUnwindDest(); | ||||
4067 | } else if (isa<CallInst>(U)) { | ||||
4068 | // Calls which don't unwind may be found inside funclet | ||||
4069 | // pads that unwind somewhere else. We don't *require* | ||||
4070 | // such calls to be annotated nounwind. | ||||
4071 | continue; | ||||
4072 | } else if (auto *CPI = dyn_cast<CleanupPadInst>(U)) { | ||||
4073 | // The unwind dest for a cleanup can only be found by | ||||
4074 | // recursive search. Add it to the worklist, and we'll | ||||
4075 | // search for its first use that determines where it unwinds. | ||||
4076 | Worklist.push_back(CPI); | ||||
4077 | continue; | ||||
4078 | } else { | ||||
4079 | Assert(isa<CatchReturnInst>(U), "Bogus funclet pad use", U)do { if (!(isa<CatchReturnInst>(U))) { CheckFailed("Bogus funclet pad use" , U); return; } } while (false); | ||||
4080 | continue; | ||||
4081 | } | ||||
4082 | |||||
4083 | Value *UnwindPad; | ||||
4084 | bool ExitsFPI; | ||||
4085 | if (UnwindDest) { | ||||
4086 | UnwindPad = UnwindDest->getFirstNonPHI(); | ||||
4087 | if (!cast<Instruction>(UnwindPad)->isEHPad()) | ||||
4088 | continue; | ||||
4089 | Value *UnwindParent = getParentPad(UnwindPad); | ||||
4090 | // Ignore unwind edges that don't exit CurrentPad. | ||||
4091 | if (UnwindParent == CurrentPad) | ||||
4092 | continue; | ||||
4093 | // Determine whether the original funclet pad is exited, | ||||
4094 | // and if we are scanning nested pads determine how many | ||||
4095 | // of them are exited so we can stop searching their | ||||
4096 | // children. | ||||
4097 | Value *ExitedPad = CurrentPad; | ||||
4098 | ExitsFPI = false; | ||||
4099 | do { | ||||
4100 | if (ExitedPad == &FPI) { | ||||
4101 | ExitsFPI = true; | ||||
4102 | // Now we can resolve any ancestors of CurrentPad up to | ||||
4103 | // FPI, but not including FPI since we need to make sure | ||||
4104 | // to check all direct users of FPI for consistency. | ||||
4105 | UnresolvedAncestorPad = &FPI; | ||||
4106 | break; | ||||
4107 | } | ||||
4108 | Value *ExitedParent = getParentPad(ExitedPad); | ||||
4109 | if (ExitedParent == UnwindParent) { | ||||
4110 | // ExitedPad is the ancestor-most pad which this unwind | ||||
4111 | // edge exits, so we can resolve up to it, meaning that | ||||
4112 | // ExitedParent is the first ancestor still unresolved. | ||||
4113 | UnresolvedAncestorPad = ExitedParent; | ||||
4114 | break; | ||||
4115 | } | ||||
4116 | ExitedPad = ExitedParent; | ||||
4117 | } while (!isa<ConstantTokenNone>(ExitedPad)); | ||||
4118 | } else { | ||||
4119 | // Unwinding to caller exits all pads. | ||||
4120 | UnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
4121 | ExitsFPI = true; | ||||
4122 | UnresolvedAncestorPad = &FPI; | ||||
4123 | } | ||||
4124 | |||||
4125 | if (ExitsFPI) { | ||||
4126 | // This unwind edge exits FPI. Make sure it agrees with other | ||||
4127 | // such edges. | ||||
4128 | if (FirstUser) { | ||||
4129 | Assert(UnwindPad == FirstUnwindPad, "Unwind edges out of a funclet "do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
4130 | "pad must have the same unwind "do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
4131 | "dest",do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
4132 | &FPI, U, FirstUser)do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false); | ||||
4133 | } else { | ||||
4134 | FirstUser = U; | ||||
4135 | FirstUnwindPad = UnwindPad; | ||||
4136 | // Record cleanup sibling unwinds for verifySiblingFuncletUnwinds | ||||
4137 | if (isa<CleanupPadInst>(&FPI) && !isa<ConstantTokenNone>(UnwindPad) && | ||||
4138 | getParentPad(UnwindPad) == getParentPad(&FPI)) | ||||
4139 | SiblingFuncletInfo[&FPI] = cast<Instruction>(U); | ||||
4140 | } | ||||
4141 | } | ||||
4142 | // Make sure we visit all uses of FPI, but for nested pads stop as | ||||
4143 | // soon as we know where they unwind to. | ||||
4144 | if (CurrentPad != &FPI) | ||||
4145 | break; | ||||
4146 | } | ||||
4147 | if (UnresolvedAncestorPad) { | ||||
4148 | if (CurrentPad == UnresolvedAncestorPad) { | ||||
4149 | // When CurrentPad is FPI itself, we don't mark it as resolved even if | ||||
4150 | // we've found an unwind edge that exits it, because we need to verify | ||||
4151 | // all direct uses of FPI. | ||||
4152 | assert(CurrentPad == &FPI)(static_cast <bool> (CurrentPad == &FPI) ? void (0) : __assert_fail ("CurrentPad == &FPI", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 4152, __extension__ __PRETTY_FUNCTION__)); | ||||
4153 | continue; | ||||
4154 | } | ||||
4155 | // Pop off the worklist any nested pads that we've found an unwind | ||||
4156 | // destination for. The pads on the worklist are the uncles, | ||||
4157 | // great-uncles, etc. of CurrentPad. We've found an unwind destination | ||||
4158 | // for all ancestors of CurrentPad up to but not including | ||||
4159 | // UnresolvedAncestorPad. | ||||
4160 | Value *ResolvedPad = CurrentPad; | ||||
4161 | while (!Worklist.empty()) { | ||||
4162 | Value *UnclePad = Worklist.back(); | ||||
4163 | Value *AncestorPad = getParentPad(UnclePad); | ||||
4164 | // Walk ResolvedPad up the ancestor list until we either find the | ||||
4165 | // uncle's parent or the last resolved ancestor. | ||||
4166 | while (ResolvedPad != AncestorPad) { | ||||
4167 | Value *ResolvedParent = getParentPad(ResolvedPad); | ||||
4168 | if (ResolvedParent == UnresolvedAncestorPad) { | ||||
4169 | break; | ||||
4170 | } | ||||
4171 | ResolvedPad = ResolvedParent; | ||||
4172 | } | ||||
4173 | // If the resolved ancestor search didn't find the uncle's parent, | ||||
4174 | // then the uncle is not yet resolved. | ||||
4175 | if (ResolvedPad != AncestorPad) | ||||
4176 | break; | ||||
4177 | // This uncle is resolved, so pop it from the worklist. | ||||
4178 | Worklist.pop_back(); | ||||
4179 | } | ||||
4180 | } | ||||
4181 | } | ||||
4182 | |||||
4183 | if (FirstUnwindPad) { | ||||
4184 | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FPI.getParentPad())) { | ||||
4185 | BasicBlock *SwitchUnwindDest = CatchSwitch->getUnwindDest(); | ||||
4186 | Value *SwitchUnwindPad; | ||||
4187 | if (SwitchUnwindDest) | ||||
4188 | SwitchUnwindPad = SwitchUnwindDest->getFirstNonPHI(); | ||||
4189 | else | ||||
4190 | SwitchUnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
4191 | Assert(SwitchUnwindPad == FirstUnwindPad,do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
4192 | "Unwind edges out of a catch must have the same unwind dest as "do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
4193 | "the parent catchswitch",do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
4194 | &FPI, FirstUser, CatchSwitch)do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false); | ||||
4195 | } | ||||
4196 | } | ||||
4197 | |||||
4198 | visitInstruction(FPI); | ||||
4199 | } | ||||
4200 | |||||
4201 | void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) { | ||||
4202 | BasicBlock *BB = CatchSwitch.getParent(); | ||||
4203 | |||||
4204 | Function *F = BB->getParent(); | ||||
4205 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
4206 | "CatchSwitchInst needs to be in a function with a personality.",do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
4207 | &CatchSwitch)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false); | ||||
4208 | |||||
4209 | // The catchswitch instruction must be the first non-PHI instruction in the | ||||
4210 | // block. | ||||
4211 | Assert(BB->getFirstNonPHI() == &CatchSwitch,do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
4212 | "CatchSwitchInst not the first non-PHI instruction in the block.",do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
4213 | &CatchSwitch)do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false); | ||||
4214 | |||||
4215 | auto *ParentPad = CatchSwitch.getParentPad(); | ||||
4216 | Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false) | ||||
4217 | "CatchSwitchInst has an invalid parent.", ParentPad)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false); | ||||
4218 | |||||
4219 | if (BasicBlock *UnwindDest = CatchSwitch.getUnwindDest()) { | ||||
4220 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
4221 | Assert(I->isEHPad() && !isa<LandingPadInst>(I),do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
4222 | "CatchSwitchInst must unwind to an EH block which is not a "do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
4223 | "landingpad.",do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
4224 | &CatchSwitch)do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false); | ||||
4225 | |||||
4226 | // Record catchswitch sibling unwinds for verifySiblingFuncletUnwinds | ||||
4227 | if (getParentPad(I) == ParentPad) | ||||
4228 | SiblingFuncletInfo[&CatchSwitch] = &CatchSwitch; | ||||
4229 | } | ||||
4230 | |||||
4231 | Assert(CatchSwitch.getNumHandlers() != 0,do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false) | ||||
4232 | "CatchSwitchInst cannot have empty handler list", &CatchSwitch)do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false); | ||||
4233 | |||||
4234 | for (BasicBlock *Handler : CatchSwitch.handlers()) { | ||||
4235 | Assert(isa<CatchPadInst>(Handler->getFirstNonPHI()),do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false) | ||||
4236 | "CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler)do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false); | ||||
4237 | } | ||||
4238 | |||||
4239 | visitEHPadPredecessors(CatchSwitch); | ||||
4240 | visitTerminator(CatchSwitch); | ||||
4241 | } | ||||
4242 | |||||
4243 | void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) { | ||||
4244 | Assert(isa<CleanupPadInst>(CRI.getOperand(0)),do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false) | ||||
4245 | "CleanupReturnInst needs to be provided a CleanupPad", &CRI,do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false) | ||||
4246 | CRI.getOperand(0))do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false); | ||||
4247 | |||||
4248 | if (BasicBlock *UnwindDest = CRI.getUnwindDest()) { | ||||
4249 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
4250 | Assert(I->isEHPad() && !isa<LandingPadInst>(I),do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
4251 | "CleanupReturnInst must unwind to an EH block which is not a "do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
4252 | "landingpad.",do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
4253 | &CRI)do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false); | ||||
4254 | } | ||||
4255 | |||||
4256 | visitTerminator(CRI); | ||||
4257 | } | ||||
4258 | |||||
4259 | void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { | ||||
4260 | Instruction *Op = cast<Instruction>(I.getOperand(i)); | ||||
4261 | // If the we have an invalid invoke, don't try to compute the dominance. | ||||
4262 | // We already reject it in the invoke specific checks and the dominance | ||||
4263 | // computation doesn't handle multiple edges. | ||||
4264 | if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) { | ||||
4265 | if (II->getNormalDest() == II->getUnwindDest()) | ||||
4266 | return; | ||||
4267 | } | ||||
4268 | |||||
4269 | // Quick check whether the def has already been encountered in the same block. | ||||
4270 | // PHI nodes are not checked to prevent accepting preceding PHIs, because PHI | ||||
4271 | // uses are defined to happen on the incoming edge, not at the instruction. | ||||
4272 | // | ||||
4273 | // FIXME: If this operand is a MetadataAsValue (wrapping a LocalAsMetadata) | ||||
4274 | // wrapping an SSA value, assert that we've already encountered it. See | ||||
4275 | // related FIXME in Mapper::mapLocalAsMetadata in ValueMapper.cpp. | ||||
4276 | if (!isa<PHINode>(I) && InstsInThisBlock.count(Op)) | ||||
4277 | return; | ||||
4278 | |||||
4279 | const Use &U = I.getOperandUse(i); | ||||
4280 | Assert(DT.dominates(Op, U),do { if (!(DT.dominates(Op, U))) { CheckFailed("Instruction does not dominate all uses!" , Op, &I); return; } } while (false) | ||||
4281 | "Instruction does not dominate all uses!", Op, &I)do { if (!(DT.dominates(Op, U))) { CheckFailed("Instruction does not dominate all uses!" , Op, &I); return; } } while (false); | ||||
4282 | } | ||||
4283 | |||||
4284 | void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) { | ||||
4285 | Assert(I.getType()->isPointerTy(), "dereferenceable, dereferenceable_or_null "do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
4286 | "apply only to pointer types", &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ); | ||||
4287 | Assert((isa<LoadInst>(I) || isa<IntToPtrInst>(I)),do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false) | ||||
4288 | "dereferenceable, dereferenceable_or_null apply only to load"do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false) | ||||
4289 | " and inttoptr instructions, use attributes for calls or invokes", &I)do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false); | ||||
4290 | Assert(MD->getNumOperands() == 1, "dereferenceable, dereferenceable_or_null "do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
4291 | "take one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false); | ||||
4292 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0)); | ||||
4293 | Assert(CI && CI->getType()->isIntegerTy(64), "dereferenceable, "do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
4294 | "dereferenceable_or_null metadata value must be an i64!", &I)do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false); | ||||
4295 | } | ||||
4296 | |||||
4297 | void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) { | ||||
4298 | Assert(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
4299 | "!prof annotations should have no less than 2 operands", MD)do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false); | ||||
4300 | |||||
4301 | // Check first operand. | ||||
4302 | Assert(MD->getOperand(0) != nullptr, "first operand should not be null", MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
4303 | Assert(isa<MDString>(MD->getOperand(0)),do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false) | ||||
4304 | "expected string with name of the !prof annotation", MD)do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false); | ||||
4305 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
4306 | StringRef ProfName = MDS->getString(); | ||||
4307 | |||||
4308 | // Check consistency of !prof branch_weights metadata. | ||||
4309 | if (ProfName.equals("branch_weights")) { | ||||
4310 | if (isa<InvokeInst>(&I)) { | ||||
4311 | Assert(MD->getNumOperands() == 2 || MD->getNumOperands() == 3,do { if (!(MD->getNumOperands() == 2 || MD->getNumOperands () == 3)) { CheckFailed("Wrong number of InvokeInst branch_weights operands" , MD); return; } } while (false) | ||||
4312 | "Wrong number of InvokeInst branch_weights operands", MD)do { if (!(MD->getNumOperands() == 2 || MD->getNumOperands () == 3)) { CheckFailed("Wrong number of InvokeInst branch_weights operands" , MD); return; } } while (false); | ||||
4313 | } else { | ||||
4314 | unsigned ExpectedNumOperands = 0; | ||||
4315 | if (BranchInst *BI = dyn_cast<BranchInst>(&I)) | ||||
4316 | ExpectedNumOperands = BI->getNumSuccessors(); | ||||
4317 | else if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) | ||||
4318 | ExpectedNumOperands = SI->getNumSuccessors(); | ||||
4319 | else if (isa<CallInst>(&I)) | ||||
4320 | ExpectedNumOperands = 1; | ||||
4321 | else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(&I)) | ||||
4322 | ExpectedNumOperands = IBI->getNumDestinations(); | ||||
4323 | else if (isa<SelectInst>(&I)) | ||||
4324 | ExpectedNumOperands = 2; | ||||
4325 | else | ||||
4326 | CheckFailed("!prof branch_weights are not allowed for this instruction", | ||||
4327 | MD); | ||||
4328 | |||||
4329 | Assert(MD->getNumOperands() == 1 + ExpectedNumOperands,do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false) | ||||
4330 | "Wrong number of operands", MD)do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false); | ||||
4331 | } | ||||
4332 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) { | ||||
4333 | auto &MDO = MD->getOperand(i); | ||||
4334 | Assert(MDO, "second operand should not be null", MD)do { if (!(MDO)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
4335 | Assert(mdconst::dyn_extract<ConstantInt>(MDO),do { if (!(mdconst::dyn_extract<ConstantInt>(MDO))) { CheckFailed ("!prof brunch_weights operand is not a const int"); return; } } while (false) | ||||
4336 | "!prof brunch_weights operand is not a const int")do { if (!(mdconst::dyn_extract<ConstantInt>(MDO))) { CheckFailed ("!prof brunch_weights operand is not a const int"); return; } } while (false); | ||||
4337 | } | ||||
4338 | } | ||||
4339 | } | ||||
4340 | |||||
4341 | void Verifier::visitAnnotationMetadata(MDNode *Annotation) { | ||||
4342 | Assert(isa<MDTuple>(Annotation), "annotation must be a tuple")do { if (!(isa<MDTuple>(Annotation))) { CheckFailed("annotation must be a tuple" ); return; } } while (false); | ||||
4343 | Assert(Annotation->getNumOperands() >= 1,do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false) | ||||
4344 | "annotation must have at least one operand")do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false); | ||||
4345 | for (const MDOperand &Op : Annotation->operands()) | ||||
4346 | Assert(isa<MDString>(Op.get()), "operands must be strings")do { if (!(isa<MDString>(Op.get()))) { CheckFailed("operands must be strings" ); return; } } while (false); | ||||
4347 | } | ||||
4348 | |||||
4349 | /// verifyInstruction - Verify that an instruction is well formed. | ||||
4350 | /// | ||||
4351 | void Verifier::visitInstruction(Instruction &I) { | ||||
4352 | BasicBlock *BB = I.getParent(); | ||||
4353 | Assert(BB, "Instruction not embedded in basic block!", &I)do { if (!(BB)) { CheckFailed("Instruction not embedded in basic block!" , &I); return; } } while (false); | ||||
4354 | |||||
4355 | if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential | ||||
4356 | for (User *U : I.users()) { | ||||
4357 | Assert(U != (User *)&I || !DT.isReachableFromEntry(BB),do { if (!(U != (User *)&I || !DT.isReachableFromEntry(BB ))) { CheckFailed("Only PHI nodes may reference their own value!" , &I); return; } } while (false) | ||||
4358 | "Only PHI nodes may reference their own value!", &I)do { if (!(U != (User *)&I || !DT.isReachableFromEntry(BB ))) { CheckFailed("Only PHI nodes may reference their own value!" , &I); return; } } while (false); | ||||
4359 | } | ||||
4360 | } | ||||
4361 | |||||
4362 | // Check that void typed values don't have names | ||||
4363 | Assert(!I.getType()->isVoidTy() || !I.hasName(),do { if (!(!I.getType()->isVoidTy() || !I.hasName())) { CheckFailed ("Instruction has a name, but provides a void value!", &I ); return; } } while (false) | ||||
4364 | "Instruction has a name, but provides a void value!", &I)do { if (!(!I.getType()->isVoidTy() || !I.hasName())) { CheckFailed ("Instruction has a name, but provides a void value!", &I ); return; } } while (false); | ||||
4365 | |||||
4366 | // Check that the return value of the instruction is either void or a legal | ||||
4367 | // value type. | ||||
4368 | Assert(I.getType()->isVoidTy() || I.getType()->isFirstClassType(),do { if (!(I.getType()->isVoidTy() || I.getType()->isFirstClassType ())) { CheckFailed("Instruction returns a non-scalar type!", & I); return; } } while (false) | ||||
4369 | "Instruction returns a non-scalar type!", &I)do { if (!(I.getType()->isVoidTy() || I.getType()->isFirstClassType ())) { CheckFailed("Instruction returns a non-scalar type!", & I); return; } } while (false); | ||||
4370 | |||||
4371 | // Check that the instruction doesn't produce metadata. Calls are already | ||||
4372 | // checked against the callee type. | ||||
4373 | Assert(!I.getType()->isMetadataTy() || isa<CallInst>(I) || isa<InvokeInst>(I),do { if (!(!I.getType()->isMetadataTy() || isa<CallInst >(I) || isa<InvokeInst>(I))) { CheckFailed("Invalid use of metadata!" , &I); return; } } while (false) | ||||
4374 | "Invalid use of metadata!", &I)do { if (!(!I.getType()->isMetadataTy() || isa<CallInst >(I) || isa<InvokeInst>(I))) { CheckFailed("Invalid use of metadata!" , &I); return; } } while (false); | ||||
4375 | |||||
4376 | // Check that all uses of the instruction, if they are instructions | ||||
4377 | // themselves, actually have parent basic blocks. If the use is not an | ||||
4378 | // instruction, it is an error! | ||||
4379 | for (Use &U : I.uses()) { | ||||
4380 | if (Instruction *Used = dyn_cast<Instruction>(U.getUser())) | ||||
4381 | Assert(Used->getParent() != nullptr,do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
4382 | "Instruction referencing"do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
4383 | " instruction not embedded in a basic block!",do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
4384 | &I, Used)do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false); | ||||
4385 | else { | ||||
4386 | CheckFailed("Use of instruction is not an instruction!", U); | ||||
4387 | return; | ||||
4388 | } | ||||
4389 | } | ||||
4390 | |||||
4391 | // Get a pointer to the call base of the instruction if it is some form of | ||||
4392 | // call. | ||||
4393 | const CallBase *CBI = dyn_cast<CallBase>(&I); | ||||
4394 | |||||
4395 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { | ||||
4396 | Assert(I.getOperand(i) != nullptr, "Instruction has null operand!", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Instruction has null operand!" , &I); return; } } while (false); | ||||
4397 | |||||
4398 | // Check to make sure that only first-class-values are operands to | ||||
4399 | // instructions. | ||||
4400 | if (!I.getOperand(i)->getType()->isFirstClassType()) { | ||||
4401 | Assert(false, "Instruction operands must be first-class values!", &I)do { if (!(false)) { CheckFailed("Instruction operands must be first-class values!" , &I); return; } } while (false); | ||||
4402 | } | ||||
4403 | |||||
4404 | if (Function *F = dyn_cast<Function>(I.getOperand(i))) { | ||||
4405 | // Check to make sure that the "address of" an intrinsic function is never | ||||
4406 | // taken. | ||||
4407 | Assert(!F->isIntrinsic() ||do { if (!(!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)))) { CheckFailed ("Cannot take the address of an intrinsic!", &I); return; } } while (false) | ||||
4408 | (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)),do { if (!(!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)))) { CheckFailed ("Cannot take the address of an intrinsic!", &I); return; } } while (false) | ||||
4409 | "Cannot take the address of an intrinsic!", &I)do { if (!(!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)))) { CheckFailed ("Cannot take the address of an intrinsic!", &I); return; } } while (false); | ||||
4410 | Assert(do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4411 | !F->isIntrinsic() || isa<CallInst>(I) ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4412 | F->getIntrinsicID() == Intrinsic::donothing ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4413 | F->getIntrinsicID() == Intrinsic::seh_try_begin ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4414 | F->getIntrinsicID() == Intrinsic::seh_try_end ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4415 | F->getIntrinsicID() == Intrinsic::seh_scope_begin ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4416 | F->getIntrinsicID() == Intrinsic::seh_scope_end ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4417 | F->getIntrinsicID() == Intrinsic::coro_resume ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4418 | F->getIntrinsicID() == Intrinsic::coro_destroy ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4419 | F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4420 | F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4421 | F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4422 | F->getIntrinsicID() == Intrinsic::wasm_rethrow,do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4423 | "Cannot invoke an intrinsic other than donothing, patchpoint, "do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4424 | "statepoint, coro_resume or coro_destroy",do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
4425 | &I)do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false); | ||||
4426 | Assert(F->getParent() == &M, "Referencing function in another module!",do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ) | ||||
4427 | &I, &M, F, F->getParent())do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ); | ||||
4428 | } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { | ||||
4429 | Assert(OpBB->getParent() == BB->getParent(),do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false) | ||||
4430 | "Referring to a basic block in another function!", &I)do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false); | ||||
4431 | } else if (Argument *OpArg = dyn_cast<Argument>(I.getOperand(i))) { | ||||
4432 | Assert(OpArg->getParent() == BB->getParent(),do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false) | ||||
4433 | "Referring to an argument in another function!", &I)do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false); | ||||
4434 | } else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) { | ||||
4435 | Assert(GV->getParent() == &M, "Referencing global in another module!", &I,do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false) | ||||
4436 | &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false); | ||||
4437 | } else if (isa<Instruction>(I.getOperand(i))) { | ||||
4438 | verifyDominatesUse(I, i); | ||||
4439 | } else if (isa<InlineAsm>(I.getOperand(i))) { | ||||
4440 | Assert(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i),do { if (!(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i))) { CheckFailed("Cannot take the address of an inline asm!" , &I); return; } } while (false) | ||||
4441 | "Cannot take the address of an inline asm!", &I)do { if (!(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i))) { CheckFailed("Cannot take the address of an inline asm!" , &I); return; } } while (false); | ||||
4442 | } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { | ||||
4443 | if (CE->getType()->isPtrOrPtrVectorTy()) { | ||||
4444 | // If we have a ConstantExpr pointer, we need to see if it came from an | ||||
4445 | // illegal bitcast. | ||||
4446 | visitConstantExprsRecursively(CE); | ||||
4447 | } | ||||
4448 | } | ||||
4449 | } | ||||
4450 | |||||
4451 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_fpmath)) { | ||||
4452 | Assert(I.getType()->isFPOrFPVectorTy(),do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false) | ||||
4453 | "fpmath requires a floating point result!", &I)do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false); | ||||
4454 | Assert(MD->getNumOperands() == 1, "fpmath takes one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("fpmath takes one operand!" , &I); return; } } while (false); | ||||
4455 | if (ConstantFP *CFP0 = | ||||
4456 | mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { | ||||
4457 | const APFloat &Accuracy = CFP0->getValueAPF(); | ||||
4458 | Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle(),do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false) | ||||
4459 | "fpmath accuracy must have float type", &I)do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false); | ||||
4460 | Assert(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(),do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false) | ||||
4461 | "fpmath accuracy not a positive number!", &I)do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false); | ||||
4462 | } else { | ||||
4463 | Assert(false, "invalid fpmath accuracy!", &I)do { if (!(false)) { CheckFailed("invalid fpmath accuracy!", & I); return; } } while (false); | ||||
4464 | } | ||||
4465 | } | ||||
4466 | |||||
4467 | if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) { | ||||
4468 | Assert(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I),do { if (!(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I))) { CheckFailed("Ranges are only for loads, calls and invokes!" , &I); return; } } while (false) | ||||
4469 | "Ranges are only for loads, calls and invokes!", &I)do { if (!(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I))) { CheckFailed("Ranges are only for loads, calls and invokes!" , &I); return; } } while (false); | ||||
4470 | visitRangeMetadata(I, Range, I.getType()); | ||||
4471 | } | ||||
4472 | |||||
4473 | if (I.getMetadata(LLVMContext::MD_nonnull)) { | ||||
4474 | Assert(I.getType()->isPointerTy(), "nonnull applies only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false) | ||||
4475 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false); | ||||
4476 | Assert(isa<LoadInst>(I),do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
4477 | "nonnull applies only to load instructions, use attributes"do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
4478 | " for calls or invokes",do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
4479 | &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false); | ||||
4480 | } | ||||
4481 | |||||
4482 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable)) | ||||
4483 | visitDereferenceableMetadata(I, MD); | ||||
4484 | |||||
4485 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) | ||||
4486 | visitDereferenceableMetadata(I, MD); | ||||
4487 | |||||
4488 | if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) | ||||
4489 | TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); | ||||
4490 | |||||
4491 | if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { | ||||
4492 | Assert(I.getType()->isPointerTy(), "align applies only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false) | ||||
4493 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false); | ||||
4494 | Assert(isa<LoadInst>(I), "align applies only to load instructions, "do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false) | ||||
4495 | "use attributes for calls or invokes", &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false); | ||||
4496 | Assert(AlignMD->getNumOperands() == 1, "align takes one operand!", &I)do { if (!(AlignMD->getNumOperands() == 1)) { CheckFailed( "align takes one operand!", &I); return; } } while (false ); | ||||
4497 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(AlignMD->getOperand(0)); | ||||
4498 | Assert(CI && CI->getType()->isIntegerTy(64),do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("align metadata value must be an i64!", & I); return; } } while (false) | ||||
4499 | "align metadata value must be an i64!", &I)do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("align metadata value must be an i64!", & I); return; } } while (false); | ||||
4500 | uint64_t Align = CI->getZExtValue(); | ||||
4501 | Assert(isPowerOf2_64(Align),do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false) | ||||
4502 | "align metadata value must be a power of 2!", &I)do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false); | ||||
4503 | Assert(Align <= Value::MaximumAlignment,do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false) | ||||
4504 | "alignment is larger that implementation defined limit", &I)do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false); | ||||
4505 | } | ||||
4506 | |||||
4507 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_prof)) | ||||
4508 | visitProfMetadata(I, MD); | ||||
4509 | |||||
4510 | if (MDNode *Annotation = I.getMetadata(LLVMContext::MD_annotation)) | ||||
4511 | visitAnnotationMetadata(Annotation); | ||||
4512 | |||||
4513 | if (MDNode *N = I.getDebugLoc().getAsMDNode()) { | ||||
4514 | AssertDI(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N)do { if (!(isa<DILocation>(N))) { DebugInfoCheckFailed( "invalid !dbg metadata attachment", &I, N); return; } } while (false); | ||||
4515 | visitMDNode(*N, AreDebugLocsAllowed::Yes); | ||||
4516 | } | ||||
4517 | |||||
4518 | if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { | ||||
4519 | verifyFragmentExpression(*DII); | ||||
4520 | verifyNotEntryValue(*DII); | ||||
4521 | } | ||||
4522 | |||||
4523 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
4524 | I.getAllMetadata(MDs); | ||||
4525 | for (auto Attachment : MDs) { | ||||
4526 | unsigned Kind = Attachment.first; | ||||
4527 | auto AllowLocs = | ||||
4528 | (Kind == LLVMContext::MD_dbg || Kind == LLVMContext::MD_loop) | ||||
4529 | ? AreDebugLocsAllowed::Yes | ||||
4530 | : AreDebugLocsAllowed::No; | ||||
4531 | visitMDNode(*Attachment.second, AllowLocs); | ||||
4532 | } | ||||
4533 | |||||
4534 | InstsInThisBlock.insert(&I); | ||||
4535 | } | ||||
4536 | |||||
4537 | /// Allow intrinsics to be verified in different ways. | ||||
4538 | void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { | ||||
4539 | Function *IF = Call.getCalledFunction(); | ||||
4540 | Assert(IF->isDeclaration(), "Intrinsic functions should never be defined!",do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false) | ||||
4541 | IF)do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false); | ||||
4542 | |||||
4543 | // Verify that the intrinsic prototype lines up with what the .td files | ||||
4544 | // describe. | ||||
4545 | FunctionType *IFTy = IF->getFunctionType(); | ||||
4546 | bool IsVarArg = IFTy->isVarArg(); | ||||
4547 | |||||
4548 | SmallVector<Intrinsic::IITDescriptor, 8> Table; | ||||
4549 | getIntrinsicInfoTableEntries(ID, Table); | ||||
4550 | ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; | ||||
4551 | |||||
4552 | // Walk the descriptors to extract overloaded types. | ||||
4553 | SmallVector<Type *, 4> ArgTys; | ||||
4554 | Intrinsic::MatchIntrinsicTypesResult Res = | ||||
4555 | Intrinsic::matchIntrinsicSignature(IFTy, TableRef, ArgTys); | ||||
4556 | Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false) | ||||
4557 | "Intrinsic has incorrect return type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false); | ||||
4558 | Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false) | ||||
4559 | "Intrinsic has incorrect argument type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false); | ||||
4560 | |||||
4561 | // Verify if the intrinsic call matches the vararg property. | ||||
4562 | if (IsVarArg) | ||||
4563 | Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false) | ||||
4564 | "Intrinsic was not defined with variable arguments!", IF)do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false); | ||||
4565 | else | ||||
4566 | Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false) | ||||
4567 | "Callsite was not defined with variable arguments!", IF)do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false); | ||||
4568 | |||||
4569 | // All descriptors should be absorbed by now. | ||||
4570 | Assert(TableRef.empty(), "Intrinsic has too few arguments!", IF)do { if (!(TableRef.empty())) { CheckFailed("Intrinsic has too few arguments!" , IF); return; } } while (false); | ||||
4571 | |||||
4572 | // Now that we have the intrinsic ID and the actual argument types (and we | ||||
4573 | // know they are legal for the intrinsic!) get the intrinsic name through the | ||||
4574 | // usual means. This allows us to verify the mangling of argument types into | ||||
4575 | // the name. | ||||
4576 | const std::string ExpectedName = | ||||
4577 | Intrinsic::getName(ID, ArgTys, IF->getParent(), IFTy); | ||||
4578 | Assert(ExpectedName == IF->getName(),do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
4579 | "Intrinsic name not mangled correctly for type arguments! "do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
4580 | "Should be: " +do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
4581 | ExpectedName,do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
4582 | IF)do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false); | ||||
4583 | |||||
4584 | // If the intrinsic takes MDNode arguments, verify that they are either global | ||||
4585 | // or are local to *this* function. | ||||
4586 | for (Value *V : Call.args()) { | ||||
4587 | if (auto *MD = dyn_cast<MetadataAsValue>(V)) | ||||
4588 | visitMetadataAsValue(*MD, Call.getCaller()); | ||||
4589 | if (auto *Const = dyn_cast<Constant>(V)) | ||||
4590 | Assert(!Const->getType()->isX86_AMXTy(),do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false) | ||||
4591 | "const x86_amx is not allowed in argument!")do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false); | ||||
4592 | } | ||||
4593 | |||||
4594 | switch (ID) { | ||||
4595 | default: | ||||
4596 | break; | ||||
4597 | case Intrinsic::assume: { | ||||
4598 | for (auto &Elem : Call.bundle_op_infos()) { | ||||
4599 | Assert(Elem.Tag->getKey() == "ignore" ||do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" ); return; } } while (false) | ||||
4600 | Attribute::isExistingAttribute(Elem.Tag->getKey()),do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" ); return; } } while (false) | ||||
4601 | "tags must be valid attribute names")do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" ); return; } } while (false); | ||||
4602 | Attribute::AttrKind Kind = | ||||
4603 | Attribute::getAttrKindFromName(Elem.Tag->getKey()); | ||||
4604 | unsigned ArgCount = Elem.End - Elem.Begin; | ||||
4605 | if (Kind == Attribute::Alignment) { | ||||
4606 | Assert(ArgCount <= 3 && ArgCount >= 2,do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments"); return ; } } while (false) | ||||
4607 | "alignment assumptions should have 2 or 3 arguments")do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments"); return ; } } while (false); | ||||
4608 | Assert(Call.getOperand(Elem.Begin)->getType()->isPointerTy(),do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer"); return ; } } while (false) | ||||
4609 | "first argument should be a pointer")do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer"); return ; } } while (false); | ||||
4610 | Assert(Call.getOperand(Elem.Begin + 1)->getType()->isIntegerTy(),do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" ); return; } } while (false) | ||||
4611 | "second argument should be an integer")do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" ); return; } } while (false); | ||||
4612 | if (ArgCount == 3) | ||||
4613 | Assert(Call.getOperand(Elem.Begin + 2)->getType()->isIntegerTy(),do { if (!(Call.getOperand(Elem.Begin + 2)->getType()-> isIntegerTy())) { CheckFailed("third argument should be an integer if present" ); return; } } while (false) | ||||
4614 | "third argument should be an integer if present")do { if (!(Call.getOperand(Elem.Begin + 2)->getType()-> isIntegerTy())) { CheckFailed("third argument should be an integer if present" ); return; } } while (false); | ||||
4615 | return; | ||||
4616 | } | ||||
4617 | Assert(ArgCount <= 2, "to many arguments")do { if (!(ArgCount <= 2)) { CheckFailed("to many arguments" ); return; } } while (false); | ||||
4618 | if (Kind == Attribute::None) | ||||
4619 | break; | ||||
4620 | if (Attribute::isIntAttrKind(Kind)) { | ||||
4621 | Assert(ArgCount == 2, "this attribute should have 2 arguments")do { if (!(ArgCount == 2)) { CheckFailed("this attribute should have 2 arguments" ); return; } } while (false); | ||||
4622 | Assert(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)),do { if (!(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)))) { CheckFailed("the second argument should be a constant integral value" ); return; } } while (false) | ||||
4623 | "the second argument should be a constant integral value")do { if (!(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)))) { CheckFailed("the second argument should be a constant integral value" ); return; } } while (false); | ||||
4624 | } else if (Attribute::canUseAsParamAttr(Kind)) { | ||||
4625 | Assert((ArgCount) == 1, "this attribute should have one argument")do { if (!((ArgCount) == 1)) { CheckFailed("this attribute should have one argument" ); return; } } while (false); | ||||
4626 | } else if (Attribute::canUseAsFnAttr(Kind)) { | ||||
4627 | Assert((ArgCount) == 0, "this attribute has no argument")do { if (!((ArgCount) == 0)) { CheckFailed("this attribute has no argument" ); return; } } while (false); | ||||
4628 | } | ||||
4629 | } | ||||
4630 | break; | ||||
4631 | } | ||||
4632 | case Intrinsic::coro_id: { | ||||
4633 | auto *InfoArg = Call.getArgOperand(3)->stripPointerCasts(); | ||||
4634 | if (isa<ConstantPointerNull>(InfoArg)) | ||||
4635 | break; | ||||
4636 | auto *GV = dyn_cast<GlobalVariable>(InfoArg); | ||||
4637 | Assert(GV && GV->isConstant() && GV->hasDefinitiveInitializer(),do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false) | ||||
4638 | "info argument of llvm.coro.id must refer to an initialized "do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false) | ||||
4639 | "constant")do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false); | ||||
4640 | Constant *Init = GV->getInitializer(); | ||||
4641 | Assert(isa<ConstantStruct>(Init) || isa<ConstantArray>(Init),do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false) | ||||
4642 | "info argument of llvm.coro.id must refer to either a struct or "do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false) | ||||
4643 | "an array")do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false); | ||||
4644 | break; | ||||
4645 | } | ||||
4646 | #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ | ||||
4647 | case Intrinsic::INTRINSIC: | ||||
4648 | #include "llvm/IR/ConstrainedOps.def" | ||||
4649 | visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(Call)); | ||||
4650 | break; | ||||
4651 | case Intrinsic::dbg_declare: // llvm.dbg.declare | ||||
4652 | Assert(isa<MetadataAsValue>(Call.getArgOperand(0)),do { if (!(isa<MetadataAsValue>(Call.getArgOperand(0))) ) { CheckFailed("invalid llvm.dbg.declare intrinsic call 1", Call ); return; } } while (false) | ||||
4653 | "invalid llvm.dbg.declare intrinsic call 1", Call)do { if (!(isa<MetadataAsValue>(Call.getArgOperand(0))) ) { CheckFailed("invalid llvm.dbg.declare intrinsic call 1", Call ); return; } } while (false); | ||||
4654 | visitDbgIntrinsic("declare", cast<DbgVariableIntrinsic>(Call)); | ||||
4655 | break; | ||||
4656 | case Intrinsic::dbg_addr: // llvm.dbg.addr | ||||
4657 | visitDbgIntrinsic("addr", cast<DbgVariableIntrinsic>(Call)); | ||||
4658 | break; | ||||
4659 | case Intrinsic::dbg_value: // llvm.dbg.value | ||||
4660 | visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call)); | ||||
4661 | break; | ||||
4662 | case Intrinsic::dbg_label: // llvm.dbg.label | ||||
4663 | visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call)); | ||||
4664 | break; | ||||
4665 | case Intrinsic::memcpy: | ||||
4666 | case Intrinsic::memcpy_inline: | ||||
4667 | case Intrinsic::memmove: | ||||
4668 | case Intrinsic::memset: { | ||||
4669 | const auto *MI = cast<MemIntrinsic>(&Call); | ||||
4670 | auto IsValidAlignment = [&](unsigned Alignment) -> bool { | ||||
4671 | return Alignment == 0 || isPowerOf2_32(Alignment); | ||||
4672 | }; | ||||
4673 | Assert(IsValidAlignment(MI->getDestAlignment()),do { if (!(IsValidAlignment(MI->getDestAlignment()))) { CheckFailed ("alignment of arg 0 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
4674 | "alignment of arg 0 of memory intrinsic must be 0 or a power of 2",do { if (!(IsValidAlignment(MI->getDestAlignment()))) { CheckFailed ("alignment of arg 0 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
4675 | Call)do { if (!(IsValidAlignment(MI->getDestAlignment()))) { CheckFailed ("alignment of arg 0 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false); | ||||
4676 | if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) { | ||||
4677 | Assert(IsValidAlignment(MTI->getSourceAlignment()),do { if (!(IsValidAlignment(MTI->getSourceAlignment()))) { CheckFailed("alignment of arg 1 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
4678 | "alignment of arg 1 of memory intrinsic must be 0 or a power of 2",do { if (!(IsValidAlignment(MTI->getSourceAlignment()))) { CheckFailed("alignment of arg 1 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
4679 | Call)do { if (!(IsValidAlignment(MTI->getSourceAlignment()))) { CheckFailed("alignment of arg 1 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false); | ||||
4680 | } | ||||
4681 | |||||
4682 | break; | ||||
4683 | } | ||||
4684 | case Intrinsic::memcpy_element_unordered_atomic: | ||||
4685 | case Intrinsic::memmove_element_unordered_atomic: | ||||
4686 | case Intrinsic::memset_element_unordered_atomic: { | ||||
4687 | const auto *AMI = cast<AtomicMemIntrinsic>(&Call); | ||||
4688 | |||||
4689 | ConstantInt *ElementSizeCI = | ||||
4690 | cast<ConstantInt>(AMI->getRawElementSizeInBytes()); | ||||
4691 | const APInt &ElementSizeVal = ElementSizeCI->getValue(); | ||||
4692 | Assert(ElementSizeVal.isPowerOf2(),do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
4693 | "element size of the element-wise atomic memory intrinsic "do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
4694 | "must be a power of 2",do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
4695 | Call)do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false); | ||||
4696 | |||||
4697 | auto IsValidAlignment = [&](uint64_t Alignment) { | ||||
4698 | return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment); | ||||
4699 | }; | ||||
4700 | uint64_t DstAlignment = AMI->getDestAlignment(); | ||||
4701 | Assert(IsValidAlignment(DstAlignment),do { if (!(IsValidAlignment(DstAlignment))) { CheckFailed("incorrect alignment of the destination argument" , Call); return; } } while (false) | ||||
4702 | "incorrect alignment of the destination argument", Call)do { if (!(IsValidAlignment(DstAlignment))) { CheckFailed("incorrect alignment of the destination argument" , Call); return; } } while (false); | ||||
4703 | if (const auto *AMT = dyn_cast<AtomicMemTransferInst>(AMI)) { | ||||
4704 | uint64_t SrcAlignment = AMT->getSourceAlignment(); | ||||
4705 | Assert(IsValidAlignment(SrcAlignment),do { if (!(IsValidAlignment(SrcAlignment))) { CheckFailed("incorrect alignment of the source argument" , Call); return; } } while (false) | ||||
4706 | "incorrect alignment of the source argument", Call)do { if (!(IsValidAlignment(SrcAlignment))) { CheckFailed("incorrect alignment of the source argument" , Call); return; } } while (false); | ||||
4707 | } | ||||
4708 | break; | ||||
4709 | } | ||||
4710 | case Intrinsic::call_preallocated_setup: { | ||||
4711 | auto *NumArgs = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
4712 | Assert(NumArgs != nullptr,do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false) | ||||
4713 | "llvm.call.preallocated.setup argument must be a constant")do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false); | ||||
4714 | bool FoundCall = false; | ||||
4715 | for (User *U : Call.users()) { | ||||
4716 | auto *UseCall = dyn_cast<CallBase>(U); | ||||
4717 | Assert(UseCall != nullptr,do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false) | ||||
4718 | "Uses of llvm.call.preallocated.setup must be calls")do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false); | ||||
4719 | const Function *Fn = UseCall->getCalledFunction(); | ||||
4720 | if (Fn && Fn->getIntrinsicID() == Intrinsic::call_preallocated_arg) { | ||||
4721 | auto *AllocArgIndex = dyn_cast<ConstantInt>(UseCall->getArgOperand(1)); | ||||
4722 | Assert(AllocArgIndex != nullptr,do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false) | ||||
4723 | "llvm.call.preallocated.alloc arg index must be a constant")do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false); | ||||
4724 | auto AllocArgIndexInt = AllocArgIndex->getValue(); | ||||
4725 | Assert(AllocArgIndexInt.sge(0) &&do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
4726 | AllocArgIndexInt.slt(NumArgs->getValue()),do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
4727 | "llvm.call.preallocated.alloc arg index must be between 0 and "do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
4728 | "corresponding "do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
4729 | "llvm.call.preallocated.setup's argument count")do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false); | ||||
4730 | } else if (Fn && Fn->getIntrinsicID() == | ||||
4731 | Intrinsic::call_preallocated_teardown) { | ||||
4732 | // nothing to do | ||||
4733 | } else { | ||||
4734 | Assert(!FoundCall, "Can have at most one call corresponding to a "do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
4735 | "llvm.call.preallocated.setup")do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
4736 | FoundCall = true; | ||||
4737 | size_t NumPreallocatedArgs = 0; | ||||
4738 | for (unsigned i = 0; i < UseCall->getNumArgOperands(); i++) { | ||||
4739 | if (UseCall->paramHasAttr(i, Attribute::Preallocated)) { | ||||
4740 | ++NumPreallocatedArgs; | ||||
4741 | } | ||||
4742 | } | ||||
4743 | Assert(NumPreallocatedArgs != 0,do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
4744 | "cannot use preallocated intrinsics on a call without "do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
4745 | "preallocated arguments")do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false); | ||||
4746 | Assert(NumArgs->equalsInt(NumPreallocatedArgs),do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
4747 | "llvm.call.preallocated.setup arg size must be equal to number "do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
4748 | "of preallocated arguments "do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
4749 | "at call site",do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
4750 | Call, *UseCall)do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false); | ||||
4751 | // getOperandBundle() cannot be called if more than one of the operand | ||||
4752 | // bundle exists. There is already a check elsewhere for this, so skip | ||||
4753 | // here if we see more than one. | ||||
4754 | if (UseCall->countOperandBundlesOfType(LLVMContext::OB_preallocated) > | ||||
4755 | 1) { | ||||
4756 | return; | ||||
4757 | } | ||||
4758 | auto PreallocatedBundle = | ||||
4759 | UseCall->getOperandBundle(LLVMContext::OB_preallocated); | ||||
4760 | Assert(PreallocatedBundle,do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
4761 | "Use of llvm.call.preallocated.setup outside intrinsics "do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
4762 | "must be in \"preallocated\" operand bundle")do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false); | ||||
4763 | Assert(PreallocatedBundle->Inputs.front().get() == &Call,do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
4764 | "preallocated bundle must have token from corresponding "do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
4765 | "llvm.call.preallocated.setup")do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
4766 | } | ||||
4767 | } | ||||
4768 | break; | ||||
4769 | } | ||||
4770 | case Intrinsic::call_preallocated_arg: { | ||||
4771 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
4772 | Assert(Token && Token->getCalledFunction()->getIntrinsicID() ==do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
4773 | Intrinsic::call_preallocated_setup,do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
4774 | "llvm.call.preallocated.arg token argument must be a "do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
4775 | "llvm.call.preallocated.setup")do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false); | ||||
4776 | Assert(Call.hasFnAttr(Attribute::Preallocated),do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false) | ||||
4777 | "llvm.call.preallocated.arg must be called with a \"preallocated\" "do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false) | ||||
4778 | "call site attribute")do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false); | ||||
4779 | break; | ||||
4780 | } | ||||
4781 | case Intrinsic::call_preallocated_teardown: { | ||||
4782 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
4783 | Assert(Token && Token->getCalledFunction()->getIntrinsicID() ==do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
4784 | Intrinsic::call_preallocated_setup,do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
4785 | "llvm.call.preallocated.teardown token argument must be a "do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
4786 | "llvm.call.preallocated.setup")do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false); | ||||
4787 | break; | ||||
4788 | } | ||||
4789 | case Intrinsic::gcroot: | ||||
4790 | case Intrinsic::gcwrite: | ||||
4791 | case Intrinsic::gcread: | ||||
4792 | if (ID == Intrinsic::gcroot) { | ||||
4793 | AllocaInst *AI = | ||||
4794 | dyn_cast<AllocaInst>(Call.getArgOperand(0)->stripPointerCasts()); | ||||
4795 | Assert(AI, "llvm.gcroot parameter #1 must be an alloca.", Call)do { if (!(AI)) { CheckFailed("llvm.gcroot parameter #1 must be an alloca." , Call); return; } } while (false); | ||||
4796 | Assert(isa<Constant>(Call.getArgOperand(1)),do { if (!(isa<Constant>(Call.getArgOperand(1)))) { CheckFailed ("llvm.gcroot parameter #2 must be a constant.", Call); return ; } } while (false) | ||||
4797 | "llvm.gcroot parameter #2 must be a constant.", Call)do { if (!(isa<Constant>(Call.getArgOperand(1)))) { CheckFailed ("llvm.gcroot parameter #2 must be a constant.", Call); return ; } } while (false); | ||||
4798 | if (!AI->getAllocatedType()->isPointerTy()) { | ||||
4799 | Assert(!isa<ConstantPointerNull>(Call.getArgOperand(1)),do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
4800 | "llvm.gcroot parameter #1 must either be a pointer alloca, "do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
4801 | "or argument #2 must be a non-null constant.",do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
4802 | Call)do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false); | ||||
4803 | } | ||||
4804 | } | ||||
4805 | |||||
4806 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
4807 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
4808 | break; | ||||
4809 | case Intrinsic::init_trampoline: | ||||
4810 | Assert(isa<Function>(Call.getArgOperand(1)->stripPointerCasts()),do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false) | ||||
4811 | "llvm.init_trampoline parameter #2 must resolve to a function.",do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false) | ||||
4812 | Call)do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false); | ||||
4813 | break; | ||||
4814 | case Intrinsic::prefetch: | ||||
4815 | Assert(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2 &&do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2 && cast<ConstantInt>(Call .getArgOperand(2))->getZExtValue() < 4)) { CheckFailed( "invalid arguments to llvm.prefetch", Call); return; } } while (false) | ||||
4816 | cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4,do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2 && cast<ConstantInt>(Call .getArgOperand(2))->getZExtValue() < 4)) { CheckFailed( "invalid arguments to llvm.prefetch", Call); return; } } while (false) | ||||
4817 | "invalid arguments to llvm.prefetch", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2 && cast<ConstantInt>(Call .getArgOperand(2))->getZExtValue() < 4)) { CheckFailed( "invalid arguments to llvm.prefetch", Call); return; } } while (false); | ||||
4818 | break; | ||||
4819 | case Intrinsic::stackprotector: | ||||
4820 | Assert(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts()),do { if (!(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.stackprotector parameter #2 must resolve to an alloca." , Call); return; } } while (false) | ||||
4821 | "llvm.stackprotector parameter #2 must resolve to an alloca.", Call)do { if (!(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.stackprotector parameter #2 must resolve to an alloca." , Call); return; } } while (false); | ||||
4822 | break; | ||||
4823 | case Intrinsic::localescape: { | ||||
4824 | BasicBlock *BB = Call.getParent(); | ||||
4825 | Assert(BB == &BB->getParent()->front(),do { if (!(BB == &BB->getParent()->front())) { CheckFailed ("llvm.localescape used outside of entry block", Call); return ; } } while (false) | ||||
4826 | "llvm.localescape used outside of entry block", Call)do { if (!(BB == &BB->getParent()->front())) { CheckFailed ("llvm.localescape used outside of entry block", Call); return ; } } while (false); | ||||
4827 | Assert(!SawFrameEscape,do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false) | ||||
4828 | "multiple calls to llvm.localescape in one function", Call)do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false); | ||||
4829 | for (Value *Arg : Call.args()) { | ||||
4830 | if (isa<ConstantPointerNull>(Arg)) | ||||
4831 | continue; // Null values are allowed as placeholders. | ||||
4832 | auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts()); | ||||
4833 | Assert(AI && AI->isStaticAlloca(),do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false) | ||||
4834 | "llvm.localescape only accepts static allocas", Call)do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false); | ||||
4835 | } | ||||
4836 | FrameEscapeInfo[BB->getParent()].first = Call.getNumArgOperands(); | ||||
4837 | SawFrameEscape = true; | ||||
4838 | break; | ||||
4839 | } | ||||
4840 | case Intrinsic::localrecover: { | ||||
4841 | Value *FnArg = Call.getArgOperand(0)->stripPointerCasts(); | ||||
4842 | Function *Fn = dyn_cast<Function>(FnArg); | ||||
4843 | Assert(Fn && !Fn->isDeclaration(),do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
4844 | "llvm.localrecover first "do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
4845 | "argument must be function defined in this module",do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
4846 | Call)do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false); | ||||
4847 | auto *IdxArg = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
4848 | auto &Entry = FrameEscapeInfo[Fn]; | ||||
4849 | Entry.second = unsigned( | ||||
4850 | std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1)); | ||||
4851 | break; | ||||
4852 | } | ||||
4853 | |||||
4854 | case Intrinsic::experimental_gc_statepoint: | ||||
4855 | if (auto *CI = dyn_cast<CallInst>(&Call)) | ||||
4856 | Assert(!CI->isInlineAsm(),do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false) | ||||
4857 | "gc.statepoint support for inline assembly unimplemented", CI)do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false); | ||||
4858 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
4859 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
4860 | |||||
4861 | verifyStatepoint(Call); | ||||
4862 | break; | ||||
4863 | case Intrinsic::experimental_gc_result: { | ||||
4864 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
4865 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
4866 | // Are we tied to a statepoint properly? | ||||
4867 | const auto *StatepointCall = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
4868 | const Function *StatepointFn = | ||||
4869 | StatepointCall ? StatepointCall->getCalledFunction() : nullptr; | ||||
4870 | Assert(StatepointFn && StatepointFn->isDeclaration() &&do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
4871 | StatepointFn->getIntrinsicID() ==do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
4872 | Intrinsic::experimental_gc_statepoint,do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
4873 | "gc.result operand #1 must be from a statepoint", Call,do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
4874 | Call.getArgOperand(0))do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false); | ||||
4875 | |||||
4876 | // Assert that result type matches wrapped callee. | ||||
4877 | const Value *Target = StatepointCall->getArgOperand(2); | ||||
4878 | auto *PT = cast<PointerType>(Target->getType()); | ||||
4879 | auto *TargetFuncType = cast<FunctionType>(PT->getElementType()); | ||||
4880 | Assert(Call.getType() == TargetFuncType->getReturnType(),do { if (!(Call.getType() == TargetFuncType->getReturnType ())) { CheckFailed("gc.result result type does not match wrapped callee" , Call); return; } } while (false) | ||||
4881 | "gc.result result type does not match wrapped callee", Call)do { if (!(Call.getType() == TargetFuncType->getReturnType ())) { CheckFailed("gc.result result type does not match wrapped callee" , Call); return; } } while (false); | ||||
4882 | break; | ||||
4883 | } | ||||
4884 | case Intrinsic::experimental_gc_relocate: { | ||||
4885 | Assert(Call.getNumArgOperands() == 3, "wrong number of arguments", Call)do { if (!(Call.getNumArgOperands() == 3)) { CheckFailed("wrong number of arguments" , Call); return; } } while (false); | ||||
4886 | |||||
4887 | Assert(isa<PointerType>(Call.getType()->getScalarType()),do { if (!(isa<PointerType>(Call.getType()->getScalarType ()))) { CheckFailed("gc.relocate must return a pointer or a vector of pointers" , Call); return; } } while (false) | ||||
4888 | "gc.relocate must return a pointer or a vector of pointers", Call)do { if (!(isa<PointerType>(Call.getType()->getScalarType ()))) { CheckFailed("gc.relocate must return a pointer or a vector of pointers" , Call); return; } } while (false); | ||||
4889 | |||||
4890 | // Check that this relocate is correctly tied to the statepoint | ||||
4891 | |||||
4892 | // This is case for relocate on the unwinding path of an invoke statepoint | ||||
4893 | if (LandingPadInst *LandingPad = | ||||
4894 | dyn_cast<LandingPadInst>(Call.getArgOperand(0))) { | ||||
4895 | |||||
4896 | const BasicBlock *InvokeBB = | ||||
4897 | LandingPad->getParent()->getUniquePredecessor(); | ||||
4898 | |||||
4899 | // Landingpad relocates should have only one predecessor with invoke | ||||
4900 | // statepoint terminator | ||||
4901 | Assert(InvokeBB, "safepoints should have unique landingpads",do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false) | ||||
4902 | LandingPad->getParent())do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false); | ||||
4903 | Assert(InvokeBB->getTerminator(), "safepoint block should be well formed",do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false) | ||||
4904 | InvokeBB)do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false); | ||||
4905 | Assert(isa<GCStatepointInst>(InvokeBB->getTerminator()),do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false) | ||||
4906 | "gc relocate should be linked to a statepoint", InvokeBB)do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false); | ||||
4907 | } else { | ||||
4908 | // In all other cases relocate should be tied to the statepoint directly. | ||||
4909 | // This covers relocates on a normal return path of invoke statepoint and | ||||
4910 | // relocates of a call statepoint. | ||||
4911 | auto Token = Call.getArgOperand(0); | ||||
4912 | Assert(isa<GCStatepointInst>(Token),do { if (!(isa<GCStatepointInst>(Token))) { CheckFailed ("gc relocate is incorrectly tied to the statepoint", Call, Token ); return; } } while (false) | ||||
4913 | "gc relocate is incorrectly tied to the statepoint", Call, Token)do { if (!(isa<GCStatepointInst>(Token))) { CheckFailed ("gc relocate is incorrectly tied to the statepoint", Call, Token ); return; } } while (false); | ||||
4914 | } | ||||
4915 | |||||
4916 | // Verify rest of the relocate arguments. | ||||
4917 | const CallBase &StatepointCall = | ||||
4918 | *cast<GCRelocateInst>(Call).getStatepoint(); | ||||
4919 | |||||
4920 | // Both the base and derived must be piped through the safepoint. | ||||
4921 | Value *Base = Call.getArgOperand(1); | ||||
4922 | Assert(isa<ConstantInt>(Base),do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false) | ||||
4923 | "gc.relocate operand #2 must be integer offset", Call)do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false); | ||||
4924 | |||||
4925 | Value *Derived = Call.getArgOperand(2); | ||||
4926 | Assert(isa<ConstantInt>(Derived),do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false) | ||||
4927 | "gc.relocate operand #3 must be integer offset", Call)do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false); | ||||
4928 | |||||
4929 | const uint64_t BaseIndex = cast<ConstantInt>(Base)->getZExtValue(); | ||||
4930 | const uint64_t DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue(); | ||||
4931 | |||||
4932 | // Check the bounds | ||||
4933 | if (auto Opt = StatepointCall.getOperandBundle(LLVMContext::OB_gc_live)) { | ||||
4934 | Assert(BaseIndex < Opt->Inputs.size(),do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false) | ||||
4935 | "gc.relocate: statepoint base index out of bounds", Call)do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false); | ||||
4936 | Assert(DerivedIndex < Opt->Inputs.size(),do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false) | ||||
4937 | "gc.relocate: statepoint derived index out of bounds", Call)do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false); | ||||
4938 | } | ||||
4939 | |||||
4940 | // Relocated value must be either a pointer type or vector-of-pointer type, | ||||
4941 | // but gc_relocate does not need to return the same pointer type as the | ||||
4942 | // relocated pointer. It can be casted to the correct type later if it's | ||||
4943 | // desired. However, they must have the same address space and 'vectorness' | ||||
4944 | GCRelocateInst &Relocate = cast<GCRelocateInst>(Call); | ||||
4945 | Assert(Relocate.getDerivedPtr()->getType()->isPtrOrPtrVectorTy(),do { if (!(Relocate.getDerivedPtr()->getType()->isPtrOrPtrVectorTy ())) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false) | ||||
4946 | "gc.relocate: relocated value must be a gc pointer", Call)do { if (!(Relocate.getDerivedPtr()->getType()->isPtrOrPtrVectorTy ())) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false); | ||||
4947 | |||||
4948 | auto ResultType = Call.getType(); | ||||
4949 | auto DerivedType = Relocate.getDerivedPtr()->getType(); | ||||
4950 | Assert(ResultType->isVectorTy() == DerivedType->isVectorTy(),do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false) | ||||
4951 | "gc.relocate: vector relocates to vector and pointer to pointer",do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false) | ||||
4952 | Call)do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false); | ||||
4953 | Assert(do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
4954 | ResultType->getPointerAddressSpace() ==do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
4955 | DerivedType->getPointerAddressSpace(),do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
4956 | "gc.relocate: relocating a pointer shouldn't change its address space",do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
4957 | Call)do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false); | ||||
4958 | break; | ||||
4959 | } | ||||
4960 | case Intrinsic::eh_exceptioncode: | ||||
4961 | case Intrinsic::eh_exceptionpointer: { | ||||
4962 | Assert(isa<CatchPadInst>(Call.getArgOperand(0)),do { if (!(isa<CatchPadInst>(Call.getArgOperand(0)))) { CheckFailed("eh.exceptionpointer argument must be a catchpad" , Call); return; } } while (false) | ||||
4963 | "eh.exceptionpointer argument must be a catchpad", Call)do { if (!(isa<CatchPadInst>(Call.getArgOperand(0)))) { CheckFailed("eh.exceptionpointer argument must be a catchpad" , Call); return; } } while (false); | ||||
4964 | break; | ||||
4965 | } | ||||
4966 | case Intrinsic::get_active_lane_mask: { | ||||
4967 | Assert(Call.getType()->isVectorTy(), "get_active_lane_mask: must return a "do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false) | ||||
4968 | "vector", Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false); | ||||
4969 | auto *ElemTy = Call.getType()->getScalarType(); | ||||
4970 | Assert(ElemTy->isIntegerTy(1), "get_active_lane_mask: element type is not "do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false) | ||||
4971 | "i1", Call)do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false); | ||||
4972 | break; | ||||
4973 | } | ||||
4974 | case Intrinsic::masked_load: { | ||||
4975 | Assert(Call.getType()->isVectorTy(), "masked_load: must return a vector",do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false) | ||||
4976 | Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false); | ||||
4977 | |||||
4978 | Value *Ptr = Call.getArgOperand(0); | ||||
4979 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
4980 | Value *Mask = Call.getArgOperand(2); | ||||
4981 | Value *PassThru = Call.getArgOperand(3); | ||||
4982 | Assert(Mask->getType()->isVectorTy(), "masked_load: mask must be vector",do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false) | ||||
4983 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false); | ||||
4984 | Assert(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false) | ||||
4985 | "masked_load: alignment must be a power of 2", Call)do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false); | ||||
4986 | |||||
4987 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
4988 | Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false) | ||||
4989 | "masked_load: return must match pointer type", Call)do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false); | ||||
4990 | Assert(PassThru->getType() == Call.getType(),do { if (!(PassThru->getType() == Call.getType())) { CheckFailed ("masked_load: pass through and return type must match", Call ); return; } } while (false) | ||||
4991 | "masked_load: pass through and return type must match", Call)do { if (!(PassThru->getType() == Call.getType())) { CheckFailed ("masked_load: pass through and return type must match", Call ); return; } } while (false); | ||||
4992 | Assert(cast<VectorType>(Mask->getType())->getElementCount() ==do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false) | ||||
4993 | cast<VectorType>(Call.getType())->getElementCount(),do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false) | ||||
4994 | "masked_load: vector mask must be same length as return", Call)do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false); | ||||
4995 | break; | ||||
4996 | } | ||||
4997 | case Intrinsic::masked_store: { | ||||
4998 | Value *Val = Call.getArgOperand(0); | ||||
4999 | Value *Ptr = Call.getArgOperand(1); | ||||
5000 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5001 | Value *Mask = Call.getArgOperand(3); | ||||
5002 | Assert(Mask->getType()->isVectorTy(), "masked_store: mask must be vector",do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false) | ||||
5003 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false); | ||||
5004 | Assert(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false) | ||||
5005 | "masked_store: alignment must be a power of 2", Call)do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false); | ||||
5006 | |||||
5007 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
5008 | Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false) | ||||
5009 | "masked_store: storee must match pointer type", Call)do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false); | ||||
5010 | Assert(cast<VectorType>(Mask->getType())->getElementCount() ==do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false) | ||||
5011 | cast<VectorType>(Val->getType())->getElementCount(),do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false) | ||||
5012 | "masked_store: vector mask must be same length as value", Call)do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false); | ||||
5013 | break; | ||||
5014 | } | ||||
5015 | |||||
5016 | case Intrinsic::masked_gather: { | ||||
5017 | const APInt &Alignment = | ||||
5018 | cast<ConstantInt>(Call.getArgOperand(1))->getValue(); | ||||
5019 | Assert(Alignment.isNullValue() || Alignment.isPowerOf2(),do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_gather: alignment must be 0 or a power of 2" , Call); return; } } while (false) | ||||
5020 | "masked_gather: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_gather: alignment must be 0 or a power of 2" , Call); return; } } while (false); | ||||
5021 | break; | ||||
5022 | } | ||||
5023 | case Intrinsic::masked_scatter: { | ||||
5024 | const APInt &Alignment = | ||||
5025 | cast<ConstantInt>(Call.getArgOperand(2))->getValue(); | ||||
5026 | Assert(Alignment.isNullValue() || Alignment.isPowerOf2(),do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_scatter: alignment must be 0 or a power of 2" , Call); return; } } while (false) | ||||
5027 | "masked_scatter: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_scatter: alignment must be 0 or a power of 2" , Call); return; } } while (false); | ||||
5028 | break; | ||||
5029 | } | ||||
5030 | |||||
5031 | case Intrinsic::experimental_guard: { | ||||
5032 | Assert(isa<CallInst>(Call), "experimental_guard cannot be invoked", Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_guard cannot be invoked" , Call); return; } } while (false); | ||||
5033 | Assert(Call.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1,do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
5034 | "experimental_guard must have exactly one "do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
5035 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
5036 | break; | ||||
5037 | } | ||||
5038 | |||||
5039 | case Intrinsic::experimental_deoptimize: { | ||||
5040 | Assert(isa<CallInst>(Call), "experimental_deoptimize cannot be invoked",do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false) | ||||
5041 | Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false); | ||||
5042 | Assert(Call.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1,do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
5043 | "experimental_deoptimize must have exactly one "do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
5044 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
5045 | Assert(Call.getType() == Call.getFunction()->getReturnType(),do { if (!(Call.getType() == Call.getFunction()->getReturnType ())) { CheckFailed("experimental_deoptimize return type must match caller return type" ); return; } } while (false) | ||||
5046 | "experimental_deoptimize return type must match caller return type")do { if (!(Call.getType() == Call.getFunction()->getReturnType ())) { CheckFailed("experimental_deoptimize return type must match caller return type" ); return; } } while (false); | ||||
5047 | |||||
5048 | if (isa<CallInst>(Call)) { | ||||
5049 | auto *RI = dyn_cast<ReturnInst>(Call.getNextNode()); | ||||
5050 | Assert(RI,do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false) | ||||
5051 | "calls to experimental_deoptimize must be followed by a return")do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false); | ||||
5052 | |||||
5053 | if (!Call.getType()->isVoidTy() && RI) | ||||
5054 | Assert(RI->getReturnValue() == &Call,do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false) | ||||
5055 | "calls to experimental_deoptimize must be followed by a return "do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false) | ||||
5056 | "of the value computed by experimental_deoptimize")do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false); | ||||
5057 | } | ||||
5058 | |||||
5059 | break; | ||||
5060 | } | ||||
5061 | case Intrinsic::vector_reduce_and: | ||||
5062 | case Intrinsic::vector_reduce_or: | ||||
5063 | case Intrinsic::vector_reduce_xor: | ||||
5064 | case Intrinsic::vector_reduce_add: | ||||
5065 | case Intrinsic::vector_reduce_mul: | ||||
5066 | case Intrinsic::vector_reduce_smax: | ||||
5067 | case Intrinsic::vector_reduce_smin: | ||||
5068 | case Intrinsic::vector_reduce_umax: | ||||
5069 | case Intrinsic::vector_reduce_umin: { | ||||
5070 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
5071 | Assert(ArgTy->isIntOrIntVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5072 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5073 | break; | ||||
5074 | } | ||||
5075 | case Intrinsic::vector_reduce_fmax: | ||||
5076 | case Intrinsic::vector_reduce_fmin: { | ||||
5077 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
5078 | Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5079 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5080 | break; | ||||
5081 | } | ||||
5082 | case Intrinsic::vector_reduce_fadd: | ||||
5083 | case Intrinsic::vector_reduce_fmul: { | ||||
5084 | // Unlike the other reductions, the first argument is a start value. The | ||||
5085 | // second argument is the vector to be reduced. | ||||
5086 | Type *ArgTy = Call.getArgOperand(1)->getType(); | ||||
5087 | Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5088 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5089 | break; | ||||
5090 | } | ||||
5091 | case Intrinsic::smul_fix: | ||||
5092 | case Intrinsic::smul_fix_sat: | ||||
5093 | case Intrinsic::umul_fix: | ||||
5094 | case Intrinsic::umul_fix_sat: | ||||
5095 | case Intrinsic::sdiv_fix: | ||||
5096 | case Intrinsic::sdiv_fix_sat: | ||||
5097 | case Intrinsic::udiv_fix: | ||||
5098 | case Intrinsic::udiv_fix_sat: { | ||||
5099 | Value *Op1 = Call.getArgOperand(0); | ||||
5100 | Value *Op2 = Call.getArgOperand(1); | ||||
5101 | Assert(Op1->getType()->isIntOrIntVectorTy(),do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
5102 | "first operand of [us][mul|div]_fix[_sat] must be an int type or "do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
5103 | "vector of ints")do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false); | ||||
5104 | Assert(Op2->getType()->isIntOrIntVectorTy(),do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
5105 | "second operand of [us][mul|div]_fix[_sat] must be an int type or "do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
5106 | "vector of ints")do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false); | ||||
5107 | |||||
5108 | auto *Op3 = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5109 | Assert(Op3->getType()->getBitWidth() <= 32,do { if (!(Op3->getType()->getBitWidth() <= 32)) { CheckFailed ("third argument of [us][mul|div]_fix[_sat] must fit within 32 bits" ); return; } } while (false) | ||||
5110 | "third argument of [us][mul|div]_fix[_sat] must fit within 32 bits")do { if (!(Op3->getType()->getBitWidth() <= 32)) { CheckFailed ("third argument of [us][mul|div]_fix[_sat] must fit within 32 bits" ); return; } } while (false); | ||||
5111 | |||||
5112 | if (ID == Intrinsic::smul_fix || ID == Intrinsic::smul_fix_sat || | ||||
5113 | ID == Intrinsic::sdiv_fix || ID == Intrinsic::sdiv_fix_sat) { | ||||
5114 | Assert(do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
5115 | Op3->getZExtValue() < Op1->getType()->getScalarSizeInBits(),do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
5116 | "the scale of s[mul|div]_fix[_sat] must be less than the width of "do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
5117 | "the operands")do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false); | ||||
5118 | } else { | ||||
5119 | Assert(Op3->getZExtValue() <= Op1->getType()->getScalarSizeInBits(),do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false) | ||||
5120 | "the scale of u[mul|div]_fix[_sat] must be less than or equal "do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false) | ||||
5121 | "to the width of the operands")do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false); | ||||
5122 | } | ||||
5123 | break; | ||||
5124 | } | ||||
5125 | case Intrinsic::lround: | ||||
5126 | case Intrinsic::llround: | ||||
5127 | case Intrinsic::lrint: | ||||
5128 | case Intrinsic::llrint: { | ||||
5129 | Type *ValTy = Call.getArgOperand(0)->getType(); | ||||
5130 | Type *ResultTy = Call.getType(); | ||||
5131 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false) | ||||
5132 | "Intrinsic does not support vectors", &Call)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false); | ||||
5133 | break; | ||||
5134 | } | ||||
5135 | case Intrinsic::bswap: { | ||||
5136 | Type *Ty = Call.getType(); | ||||
5137 | unsigned Size = Ty->getScalarSizeInBits(); | ||||
5138 | Assert(Size % 16 == 0, "bswap must be an even number of bytes", &Call)do { if (!(Size % 16 == 0)) { CheckFailed("bswap must be an even number of bytes" , &Call); return; } } while (false); | ||||
5139 | break; | ||||
5140 | } | ||||
5141 | case Intrinsic::invariant_start: { | ||||
5142 | ConstantInt *InvariantSize = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
5143 | Assert(InvariantSize &&do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
5144 | (!InvariantSize->isNegative() || InvariantSize->isMinusOne()),do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
5145 | "invariant_start parameter must be -1, 0 or a positive number",do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
5146 | &Call)do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false); | ||||
5147 | break; | ||||
5148 | } | ||||
5149 | case Intrinsic::matrix_multiply: | ||||
5150 | case Intrinsic::matrix_transpose: | ||||
5151 | case Intrinsic::matrix_column_major_load: | ||||
5152 | case Intrinsic::matrix_column_major_store: { | ||||
5153 | Function *IF = Call.getCalledFunction(); | ||||
5154 | ConstantInt *Stride = nullptr; | ||||
5155 | ConstantInt *NumRows; | ||||
5156 | ConstantInt *NumColumns; | ||||
5157 | VectorType *ResultTy; | ||||
5158 | Type *Op0ElemTy = nullptr; | ||||
5159 | Type *Op1ElemTy = nullptr; | ||||
5160 | switch (ID) { | ||||
5161 | case Intrinsic::matrix_multiply: | ||||
5162 | NumRows = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5163 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5164 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5165 | Op0ElemTy = | ||||
5166 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5167 | Op1ElemTy = | ||||
5168 | cast<VectorType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
5169 | break; | ||||
5170 | case Intrinsic::matrix_transpose: | ||||
5171 | NumRows = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
5172 | NumColumns = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5173 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5174 | Op0ElemTy = | ||||
5175 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5176 | break; | ||||
5177 | case Intrinsic::matrix_column_major_load: | ||||
5178 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(1)); | ||||
5179 | NumRows = cast<ConstantInt>(Call.getArgOperand(3)); | ||||
5180 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5181 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5182 | Op0ElemTy = | ||||
5183 | cast<PointerType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5184 | break; | ||||
5185 | case Intrinsic::matrix_column_major_store: | ||||
5186 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5187 | NumRows = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5188 | NumColumns = cast<ConstantInt>(Call.getArgOperand(5)); | ||||
5189 | ResultTy = cast<VectorType>(Call.getArgOperand(0)->getType()); | ||||
5190 | Op0ElemTy = | ||||
5191 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5192 | Op1ElemTy = | ||||
5193 | cast<PointerType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
5194 | break; | ||||
5195 | default: | ||||
5196 | llvm_unreachable("unexpected intrinsic")::llvm::llvm_unreachable_internal("unexpected intrinsic", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5196); | ||||
5197 | } | ||||
5198 | |||||
5199 | Assert(ResultTy->getElementType()->isIntegerTy() ||do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false) | ||||
5200 | ResultTy->getElementType()->isFloatingPointTy(),do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false) | ||||
5201 | "Result type must be an integer or floating-point type!", IF)do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false); | ||||
5202 | |||||
5203 | Assert(ResultTy->getElementType() == Op0ElemTy,do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
5204 | "Vector element type mismatch of the result and first operand "do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
5205 | "vector!", IF)do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false); | ||||
5206 | |||||
5207 | if (Op1ElemTy) | ||||
5208 | Assert(ResultTy->getElementType() == Op1ElemTy,do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
5209 | "Vector element type mismatch of the result and second operand "do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
5210 | "vector!", IF)do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false); | ||||
5211 | |||||
5212 | Assert(cast<FixedVectorType>(ResultTy)->getNumElements() ==do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false) | ||||
5213 | NumRows->getZExtValue() * NumColumns->getZExtValue(),do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false) | ||||
5214 | "Result of a matrix operation does not fit in the returned vector!")do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false); | ||||
5215 | |||||
5216 | if (Stride) | ||||
5217 | Assert(Stride->getZExtValue() >= NumRows->getZExtValue(),do { if (!(Stride->getZExtValue() >= NumRows->getZExtValue ())) { CheckFailed("Stride must be greater or equal than the number of rows!" , IF); return; } } while (false) | ||||
5218 | "Stride must be greater or equal than the number of rows!", IF)do { if (!(Stride->getZExtValue() >= NumRows->getZExtValue ())) { CheckFailed("Stride must be greater or equal than the number of rows!" , IF); return; } } while (false); | ||||
5219 | |||||
5220 | break; | ||||
5221 | } | ||||
5222 | case Intrinsic::experimental_stepvector: { | ||||
5223 | VectorType *VecTy = dyn_cast<VectorType>(Call.getType()); | ||||
5224 | Assert(VecTy && VecTy->getScalarType()->isIntegerTy() &&do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
5225 | VecTy->getScalarSizeInBits() >= 8,do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
5226 | "experimental_stepvector only supported for vectors of integers "do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
5227 | "with a bitwidth of at least 8.",do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
5228 | &Call)do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false); | ||||
5229 | break; | ||||
5230 | } | ||||
5231 | case Intrinsic::experimental_vector_insert: { | ||||
5232 | Value *Vec = Call.getArgOperand(0); | ||||
5233 | Value *SubVec = Call.getArgOperand(1); | ||||
5234 | Value *Idx = Call.getArgOperand(2); | ||||
5235 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
5236 | |||||
5237 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
5238 | VectorType *SubVecTy = cast<VectorType>(SubVec->getType()); | ||||
5239 | |||||
5240 | ElementCount VecEC = VecTy->getElementCount(); | ||||
5241 | ElementCount SubVecEC = SubVecTy->getElementCount(); | ||||
5242 | Assert(VecTy->getElementType() == SubVecTy->getElementType(),do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
5243 | "experimental_vector_insert parameters must have the same element "do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
5244 | "type.",do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
5245 | &Call)do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false); | ||||
5246 | Assert(IdxN % SubVecEC.getKnownMinValue() == 0,do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_insert index must be a constant multiple of " "the subvector's known minimum vector length."); return; } } while (false) | ||||
5247 | "experimental_vector_insert index must be a constant multiple of "do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_insert index must be a constant multiple of " "the subvector's known minimum vector length."); return; } } while (false) | ||||
5248 | "the subvector's known minimum vector length.")do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_insert index must be a constant multiple of " "the subvector's known minimum vector length."); return; } } while (false); | ||||
5249 | |||||
5250 | // If this insertion is not the 'mixed' case where a fixed vector is | ||||
5251 | // inserted into a scalable vector, ensure that the insertion of the | ||||
5252 | // subvector does not overrun the parent vector. | ||||
5253 | if (VecEC.isScalable() == SubVecEC.isScalable()) { | ||||
5254 | Assert(do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
5255 | IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
5256 | IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
5257 | "subvector operand of experimental_vector_insert would overrun the "do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
5258 | "vector being inserted into.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false); | ||||
5259 | } | ||||
5260 | break; | ||||
5261 | } | ||||
5262 | case Intrinsic::experimental_vector_extract: { | ||||
5263 | Value *Vec = Call.getArgOperand(0); | ||||
5264 | Value *Idx = Call.getArgOperand(1); | ||||
5265 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
5266 | |||||
5267 | VectorType *ResultTy = cast<VectorType>(Call.getType()); | ||||
5268 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
5269 | |||||
5270 | ElementCount VecEC = VecTy->getElementCount(); | ||||
5271 | ElementCount ResultEC = ResultTy->getElementCount(); | ||||
5272 | |||||
5273 | Assert(ResultTy->getElementType() == VecTy->getElementType(),do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
5274 | "experimental_vector_extract result must have the same element "do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
5275 | "type as the input vector.",do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
5276 | &Call)do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false); | ||||
5277 | Assert(IdxN % ResultEC.getKnownMinValue() == 0,do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_extract index must be a constant multiple of " "the result type's known minimum vector length."); return; } } while (false) | ||||
5278 | "experimental_vector_extract index must be a constant multiple of "do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_extract index must be a constant multiple of " "the result type's known minimum vector length."); return; } } while (false) | ||||
5279 | "the result type's known minimum vector length.")do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_extract index must be a constant multiple of " "the result type's known minimum vector length."); return; } } while (false); | ||||
5280 | |||||
5281 | // If this extraction is not the 'mixed' case where a fixed vector is is | ||||
5282 | // extracted from a scalable vector, ensure that the extraction does not | ||||
5283 | // overrun the parent vector. | ||||
5284 | if (VecEC.isScalable() == ResultEC.isScalable()) { | ||||
5285 | Assert(IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false) | ||||
5286 | IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false) | ||||
5287 | "experimental_vector_extract would overrun.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false); | ||||
5288 | } | ||||
5289 | break; | ||||
5290 | } | ||||
5291 | case Intrinsic::experimental_noalias_scope_decl: { | ||||
5292 | NoAliasScopeDecls.push_back(cast<IntrinsicInst>(&Call)); | ||||
5293 | break; | ||||
5294 | } | ||||
5295 | case Intrinsic::preserve_array_access_index: | ||||
5296 | case Intrinsic::preserve_struct_access_index: { | ||||
5297 | Type *ElemTy = Call.getAttributes().getParamElementType(0); | ||||
5298 | Assert(ElemTy,do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
5299 | "Intrinsic requires elementtype attribute on first argument.",do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
5300 | &Call)do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false); | ||||
5301 | break; | ||||
5302 | } | ||||
5303 | }; | ||||
5304 | } | ||||
5305 | |||||
5306 | /// Carefully grab the subprogram from a local scope. | ||||
5307 | /// | ||||
5308 | /// This carefully grabs the subprogram from a local scope, avoiding the | ||||
5309 | /// built-in assertions that would typically fire. | ||||
5310 | static DISubprogram *getSubprogram(Metadata *LocalScope) { | ||||
5311 | if (!LocalScope) | ||||
5312 | return nullptr; | ||||
5313 | |||||
5314 | if (auto *SP = dyn_cast<DISubprogram>(LocalScope)) | ||||
5315 | return SP; | ||||
5316 | |||||
5317 | if (auto *LB = dyn_cast<DILexicalBlockBase>(LocalScope)) | ||||
5318 | return getSubprogram(LB->getRawScope()); | ||||
5319 | |||||
5320 | // Just return null; broken scope chains are checked elsewhere. | ||||
5321 | assert(!isa<DILocalScope>(LocalScope) && "Unknown type of local scope")(static_cast <bool> (!isa<DILocalScope>(LocalScope ) && "Unknown type of local scope") ? void (0) : __assert_fail ("!isa<DILocalScope>(LocalScope) && \"Unknown type of local scope\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5321, __extension__ __PRETTY_FUNCTION__)); | ||||
5322 | return nullptr; | ||||
5323 | } | ||||
5324 | |||||
5325 | void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { | ||||
5326 | unsigned NumOperands; | ||||
5327 | bool HasRoundingMD; | ||||
5328 | switch (FPI.getIntrinsicID()) { | ||||
5329 | #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ | ||||
5330 | case Intrinsic::INTRINSIC: \ | ||||
5331 | NumOperands = NARG; \ | ||||
5332 | HasRoundingMD = ROUND_MODE; \ | ||||
5333 | break; | ||||
5334 | #include "llvm/IR/ConstrainedOps.def" | ||||
5335 | default: | ||||
5336 | llvm_unreachable("Invalid constrained FP intrinsic!")::llvm::llvm_unreachable_internal("Invalid constrained FP intrinsic!" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5336); | ||||
5337 | } | ||||
5338 | NumOperands += (1 + HasRoundingMD); | ||||
5339 | // Compare intrinsics carry an extra predicate metadata operand. | ||||
5340 | if (isa<ConstrainedFPCmpIntrinsic>(FPI)) | ||||
5341 | NumOperands += 1; | ||||
5342 | Assert((FPI.getNumArgOperands() == NumOperands),do { if (!((FPI.getNumArgOperands() == NumOperands))) { CheckFailed ("invalid arguments for constrained FP intrinsic", &FPI); return; } } while (false) | ||||
5343 | "invalid arguments for constrained FP intrinsic", &FPI)do { if (!((FPI.getNumArgOperands() == NumOperands))) { CheckFailed ("invalid arguments for constrained FP intrinsic", &FPI); return; } } while (false); | ||||
5344 | |||||
5345 | switch (FPI.getIntrinsicID()) { | ||||
5346 | case Intrinsic::experimental_constrained_lrint: | ||||
5347 | case Intrinsic::experimental_constrained_llrint: { | ||||
5348 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
5349 | Type *ResultTy = FPI.getType(); | ||||
5350 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
5351 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
5352 | } | ||||
5353 | break; | ||||
5354 | |||||
5355 | case Intrinsic::experimental_constrained_lround: | ||||
5356 | case Intrinsic::experimental_constrained_llround: { | ||||
5357 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
5358 | Type *ResultTy = FPI.getType(); | ||||
5359 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
5360 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
5361 | break; | ||||
5362 | } | ||||
5363 | |||||
5364 | case Intrinsic::experimental_constrained_fcmp: | ||||
5365 | case Intrinsic::experimental_constrained_fcmps: { | ||||
5366 | auto Pred = cast<ConstrainedFPCmpIntrinsic>(&FPI)->getPredicate(); | ||||
5367 | Assert(CmpInst::isFPPredicate(Pred),do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false) | ||||
5368 | "invalid predicate for constrained FP comparison intrinsic", &FPI)do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false); | ||||
5369 | break; | ||||
5370 | } | ||||
5371 | |||||
5372 | case Intrinsic::experimental_constrained_fptosi: | ||||
5373 | case Intrinsic::experimental_constrained_fptoui: { | ||||
5374 | Value *Operand = FPI.getArgOperand(0); | ||||
5375 | uint64_t NumSrcElem = 0; | ||||
5376 | Assert(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false) | ||||
5377 | "Intrinsic first argument must be floating point", &FPI)do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false); | ||||
5378 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5379 | NumSrcElem = cast<FixedVectorType>(OperandT)->getNumElements(); | ||||
5380 | } | ||||
5381 | |||||
5382 | Operand = &FPI; | ||||
5383 | Assert((NumSrcElem > 0) == Operand->getType()->isVectorTy(),do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
5384 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
5385 | Assert(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false) | ||||
5386 | "Intrinsic result must be an integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false); | ||||
5387 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5388 | Assert(NumSrcElem == cast<FixedVectorType>(OperandT)->getNumElements(),do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
5389 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
5390 | &FPI)do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
5391 | } | ||||
5392 | } | ||||
5393 | break; | ||||
5394 | |||||
5395 | case Intrinsic::experimental_constrained_sitofp: | ||||
5396 | case Intrinsic::experimental_constrained_uitofp: { | ||||
5397 | Value *Operand = FPI.getArgOperand(0); | ||||
5398 | uint64_t NumSrcElem = 0; | ||||
5399 | Assert(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false) | ||||
5400 | "Intrinsic first argument must be integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false); | ||||
5401 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5402 | NumSrcElem = cast<FixedVectorType>(OperandT)->getNumElements(); | ||||
5403 | } | ||||
5404 | |||||
5405 | Operand = &FPI; | ||||
5406 | Assert((NumSrcElem > 0) == Operand->getType()->isVectorTy(),do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
5407 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
5408 | Assert(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false) | ||||
5409 | "Intrinsic result must be a floating point", &FPI)do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false); | ||||
5410 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5411 | Assert(NumSrcElem == cast<FixedVectorType>(OperandT)->getNumElements(),do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
5412 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
5413 | &FPI)do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
5414 | } | ||||
5415 | } break; | ||||
5416 | |||||
5417 | case Intrinsic::experimental_constrained_fptrunc: | ||||
5418 | case Intrinsic::experimental_constrained_fpext: { | ||||
5419 | Value *Operand = FPI.getArgOperand(0); | ||||
5420 | Type *OperandTy = Operand->getType(); | ||||
5421 | Value *Result = &FPI; | ||||
5422 | Type *ResultTy = Result->getType(); | ||||
5423 | Assert(OperandTy->isFPOrFPVectorTy(),do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false) | ||||
5424 | "Intrinsic first argument must be FP or FP vector", &FPI)do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false); | ||||
5425 | Assert(ResultTy->isFPOrFPVectorTy(),do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false) | ||||
5426 | "Intrinsic result must be FP or FP vector", &FPI)do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false); | ||||
5427 | Assert(OperandTy->isVectorTy() == ResultTy->isVectorTy(),do { if (!(OperandTy->isVectorTy() == ResultTy->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
5428 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!(OperandTy->isVectorTy() == ResultTy->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
5429 | if (OperandTy->isVectorTy()) { | ||||
5430 | Assert(cast<FixedVectorType>(OperandTy)->getNumElements() ==do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
5431 | cast<FixedVectorType>(ResultTy)->getNumElements(),do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
5432 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
5433 | &FPI)do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
5434 | } | ||||
5435 | if (FPI.getIntrinsicID() == Intrinsic::experimental_constrained_fptrunc) { | ||||
5436 | Assert(OperandTy->getScalarSizeInBits() > ResultTy->getScalarSizeInBits(),do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false) | ||||
5437 | "Intrinsic first argument's type must be larger than result type",do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false) | ||||
5438 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false); | ||||
5439 | } else { | ||||
5440 | Assert(OperandTy->getScalarSizeInBits() < ResultTy->getScalarSizeInBits(),do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false) | ||||
5441 | "Intrinsic first argument's type must be smaller than result type",do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false) | ||||
5442 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false); | ||||
5443 | } | ||||
5444 | } | ||||
5445 | break; | ||||
5446 | |||||
5447 | default: | ||||
5448 | break; | ||||
5449 | } | ||||
5450 | |||||
5451 | // If a non-metadata argument is passed in a metadata slot then the | ||||
5452 | // error will be caught earlier when the incorrect argument doesn't | ||||
5453 | // match the specification in the intrinsic call table. Thus, no | ||||
5454 | // argument type check is needed here. | ||||
5455 | |||||
5456 | Assert(FPI.getExceptionBehavior().hasValue(),do { if (!(FPI.getExceptionBehavior().hasValue())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false) | ||||
5457 | "invalid exception behavior argument", &FPI)do { if (!(FPI.getExceptionBehavior().hasValue())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false); | ||||
5458 | if (HasRoundingMD) { | ||||
5459 | Assert(FPI.getRoundingMode().hasValue(),do { if (!(FPI.getRoundingMode().hasValue())) { CheckFailed("invalid rounding mode argument" , &FPI); return; } } while (false) | ||||
5460 | "invalid rounding mode argument", &FPI)do { if (!(FPI.getRoundingMode().hasValue())) { CheckFailed("invalid rounding mode argument" , &FPI); return; } } while (false); | ||||
5461 | } | ||||
5462 | } | ||||
5463 | |||||
5464 | void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { | ||||
5465 | auto *MD = DII.getRawLocation(); | ||||
5466 | AssertDI(isa<ValueAsMetadata>(MD) || isa<DIArgList>(MD) ||do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false) | ||||
5467 | (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()),do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false) | ||||
5468 | "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD)do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false); | ||||
5469 | AssertDI(isa<DILocalVariable>(DII.getRawVariable()),do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
5470 | "invalid llvm.dbg." + Kind + " intrinsic variable", &DII,do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
5471 | DII.getRawVariable())do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false); | ||||
5472 | AssertDI(isa<DIExpression>(DII.getRawExpression()),do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
5473 | "invalid llvm.dbg." + Kind + " intrinsic expression", &DII,do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
5474 | DII.getRawExpression())do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ); | ||||
5475 | |||||
5476 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
5477 | if (MDNode *N = DII.getDebugLoc().getAsMDNode()) | ||||
5478 | if (!isa<DILocation>(N)) | ||||
5479 | return; | ||||
5480 | |||||
5481 | BasicBlock *BB = DII.getParent(); | ||||
5482 | Function *F = BB ? BB->getParent() : nullptr; | ||||
5483 | |||||
5484 | // The scopes for variables and !dbg attachments must agree. | ||||
5485 | DILocalVariable *Var = DII.getVariable(); | ||||
5486 | DILocation *Loc = DII.getDebugLoc(); | ||||
5487 | AssertDI(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false) | ||||
5488 | &DII, BB, F)do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false); | ||||
5489 | |||||
5490 | DISubprogram *VarSP = getSubprogram(Var->getRawScope()); | ||||
5491 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
5492 | if (!VarSP || !LocSP) | ||||
5493 | return; // Broken scope chains are checked elsewhere. | ||||
5494 | |||||
5495 | AssertDI(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
5496 | " variable and !dbg attachment",do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
5497 | &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
5498 | Loc->getScope()->getSubprogram())do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false); | ||||
5499 | |||||
5500 | // This check is redundant with one in visitLocalVariable(). | ||||
5501 | AssertDI(isType(Var->getRawType()), "invalid type ref", Var,do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false) | ||||
5502 | Var->getRawType())do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false); | ||||
5503 | verifyFnArgs(DII); | ||||
5504 | } | ||||
5505 | |||||
5506 | void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) { | ||||
5507 | AssertDI(isa<DILabel>(DLI.getRawLabel()),do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
5508 | "invalid llvm.dbg." + Kind + " intrinsic variable", &DLI,do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
5509 | DLI.getRawLabel())do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false); | ||||
5510 | |||||
5511 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
5512 | if (MDNode *N = DLI.getDebugLoc().getAsMDNode()) | ||||
5513 | if (!isa<DILocation>(N)) | ||||
5514 | return; | ||||
5515 | |||||
5516 | BasicBlock *BB = DLI.getParent(); | ||||
5517 | Function *F = BB ? BB->getParent() : nullptr; | ||||
5518 | |||||
5519 | // The scopes for variables and !dbg attachments must agree. | ||||
5520 | DILabel *Label = DLI.getLabel(); | ||||
5521 | DILocation *Loc = DLI.getDebugLoc(); | ||||
5522 | Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false) | ||||
5523 | &DLI, BB, F)do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false); | ||||
5524 | |||||
5525 | DISubprogram *LabelSP = getSubprogram(Label->getRawScope()); | ||||
5526 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
5527 | if (!LabelSP || !LocSP) | ||||
5528 | return; | ||||
5529 | |||||
5530 | AssertDI(LabelSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
5531 | " label and !dbg attachment",do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
5532 | &DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc,do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
5533 | Loc->getScope()->getSubprogram())do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false); | ||||
5534 | } | ||||
5535 | |||||
5536 | void Verifier::verifyFragmentExpression(const DbgVariableIntrinsic &I) { | ||||
5537 | DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); | ||||
5538 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
5539 | |||||
5540 | // We don't know whether this intrinsic verified correctly. | ||||
5541 | if (!V || !E || !E->isValid()) | ||||
5542 | return; | ||||
5543 | |||||
5544 | // Nothing to do if this isn't a DW_OP_LLVM_fragment expression. | ||||
5545 | auto Fragment = E->getFragmentInfo(); | ||||
5546 | if (!Fragment) | ||||
5547 | return; | ||||
5548 | |||||
5549 | // The frontend helps out GDB by emitting the members of local anonymous | ||||
5550 | // unions as artificial local variables with shared storage. When SROA splits | ||||
5551 | // the storage for artificial local variables that are smaller than the entire | ||||
5552 | // union, the overhang piece will be outside of the allotted space for the | ||||
5553 | // variable and this check fails. | ||||
5554 | // FIXME: Remove this check as soon as clang stops doing this; it hides bugs. | ||||
5555 | if (V->isArtificial()) | ||||
5556 | return; | ||||
5557 | |||||
5558 | verifyFragmentExpression(*V, *Fragment, &I); | ||||
5559 | } | ||||
5560 | |||||
5561 | template <typename ValueOrMetadata> | ||||
5562 | void Verifier::verifyFragmentExpression(const DIVariable &V, | ||||
5563 | DIExpression::FragmentInfo Fragment, | ||||
5564 | ValueOrMetadata *Desc) { | ||||
5565 | // If there's no size, the type is broken, but that should be checked | ||||
5566 | // elsewhere. | ||||
5567 | auto VarSize = V.getSizeInBits(); | ||||
5568 | if (!VarSize) | ||||
5569 | return; | ||||
5570 | |||||
5571 | unsigned FragSize = Fragment.SizeInBits; | ||||
5572 | unsigned FragOffset = Fragment.OffsetInBits; | ||||
5573 | AssertDI(FragSize + FragOffset <= *VarSize,do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false) | ||||
5574 | "fragment is larger than or outside of variable", Desc, &V)do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false); | ||||
5575 | AssertDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V)do { if (!(FragSize != *VarSize)) { DebugInfoCheckFailed("fragment covers entire variable" , Desc, &V); return; } } while (false); | ||||
5576 | } | ||||
5577 | |||||
5578 | void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) { | ||||
5579 | // This function does not take the scope of noninlined function arguments into | ||||
5580 | // account. Don't run it if current function is nodebug, because it may | ||||
5581 | // contain inlined debug intrinsics. | ||||
5582 | if (!HasDebugInfo) | ||||
5583 | return; | ||||
5584 | |||||
5585 | // For performance reasons only check non-inlined ones. | ||||
5586 | if (I.getDebugLoc()->getInlinedAt()) | ||||
5587 | return; | ||||
5588 | |||||
5589 | DILocalVariable *Var = I.getVariable(); | ||||
5590 | AssertDI(Var, "dbg intrinsic without variable")do { if (!(Var)) { DebugInfoCheckFailed("dbg intrinsic without variable" ); return; } } while (false); | ||||
5591 | |||||
5592 | unsigned ArgNo = Var->getArg(); | ||||
5593 | if (!ArgNo) | ||||
5594 | return; | ||||
5595 | |||||
5596 | // Verify there are no duplicate function argument debug info entries. | ||||
5597 | // These will cause hard-to-debug assertions in the DWARF backend. | ||||
5598 | if (DebugFnArgs.size() < ArgNo) | ||||
5599 | DebugFnArgs.resize(ArgNo, nullptr); | ||||
5600 | |||||
5601 | auto *Prev = DebugFnArgs[ArgNo - 1]; | ||||
5602 | DebugFnArgs[ArgNo - 1] = Var; | ||||
5603 | AssertDI(!Prev || (Prev == Var), "conflicting debug info for argument", &I,do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false) | ||||
5604 | Prev, Var)do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false); | ||||
5605 | } | ||||
5606 | |||||
5607 | void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) { | ||||
5608 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
5609 | |||||
5610 | // We don't know whether this intrinsic verified correctly. | ||||
5611 | if (!E || !E->isValid()) | ||||
5612 | return; | ||||
5613 | |||||
5614 | AssertDI(!E->isEntryValue(), "Entry values are only allowed in MIR", &I)do { if (!(!E->isEntryValue())) { DebugInfoCheckFailed("Entry values are only allowed in MIR" , &I); return; } } while (false); | ||||
5615 | } | ||||
5616 | |||||
5617 | void Verifier::verifyCompileUnits() { | ||||
5618 | // When more than one Module is imported into the same context, such as during | ||||
5619 | // an LTO build before linking the modules, ODR type uniquing may cause types | ||||
5620 | // to point to a different CU. This check does not make sense in this case. | ||||
5621 | if (M.getContext().isODRUniquingDebugTypes()) | ||||
5622 | return; | ||||
5623 | auto *CUs = M.getNamedMetadata("llvm.dbg.cu"); | ||||
5624 | SmallPtrSet<const Metadata *, 2> Listed; | ||||
5625 | if (CUs) | ||||
5626 | Listed.insert(CUs->op_begin(), CUs->op_end()); | ||||
5627 | for (auto *CU : CUVisited) | ||||
5628 | AssertDI(Listed.count(CU), "DICompileUnit not listed in llvm.dbg.cu", CU)do { if (!(Listed.count(CU))) { DebugInfoCheckFailed("DICompileUnit not listed in llvm.dbg.cu" , CU); return; } } while (false); | ||||
5629 | CUVisited.clear(); | ||||
5630 | } | ||||
5631 | |||||
5632 | void Verifier::verifyDeoptimizeCallingConvs() { | ||||
5633 | if (DeoptimizeDeclarations.empty()) | ||||
5634 | return; | ||||
5635 | |||||
5636 | const Function *First = DeoptimizeDeclarations[0]; | ||||
5637 | for (auto *F : makeArrayRef(DeoptimizeDeclarations).slice(1)) { | ||||
5638 | Assert(First->getCallingConv() == F->getCallingConv(),do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
5639 | "All llvm.experimental.deoptimize declarations must have the same "do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
5640 | "calling convention",do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
5641 | First, F)do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false); | ||||
5642 | } | ||||
5643 | } | ||||
5644 | |||||
5645 | void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) { | ||||
5646 | bool HasSource = F.getSource().hasValue(); | ||||
5647 | if (!HasSourceDebugInfo.count(&U)) | ||||
5648 | HasSourceDebugInfo[&U] = HasSource; | ||||
5649 | AssertDI(HasSource == HasSourceDebugInfo[&U],do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ) | ||||
5650 | "inconsistent use of embedded source")do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ); | ||||
5651 | } | ||||
5652 | |||||
5653 | void Verifier::verifyNoAliasScopeDecl() { | ||||
5654 | if (NoAliasScopeDecls.empty()) | ||||
5655 | return; | ||||
5656 | |||||
5657 | // only a single scope must be declared at a time. | ||||
5658 | for (auto *II : NoAliasScopeDecls) { | ||||
5659 | assert(II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl &&(static_cast <bool> (II->getIntrinsicID() == Intrinsic ::experimental_noalias_scope_decl && "Not a llvm.experimental.noalias.scope.decl ?" ) ? void (0) : __assert_fail ("II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl && \"Not a llvm.experimental.noalias.scope.decl ?\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5660, __extension__ __PRETTY_FUNCTION__)) | ||||
5660 | "Not a llvm.experimental.noalias.scope.decl ?")(static_cast <bool> (II->getIntrinsicID() == Intrinsic ::experimental_noalias_scope_decl && "Not a llvm.experimental.noalias.scope.decl ?" ) ? void (0) : __assert_fail ("II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl && \"Not a llvm.experimental.noalias.scope.decl ?\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5660, __extension__ __PRETTY_FUNCTION__)); | ||||
5661 | const auto *ScopeListMV = dyn_cast<MetadataAsValue>( | ||||
5662 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
5663 | Assert(ScopeListMV != nullptr,do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
5664 | "llvm.experimental.noalias.scope.decl must have a MetadataAsValue "do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
5665 | "argument",do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
5666 | II)do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false); | ||||
5667 | |||||
5668 | const auto *ScopeListMD = dyn_cast<MDNode>(ScopeListMV->getMetadata()); | ||||
5669 | Assert(ScopeListMD != nullptr, "!id.scope.list must point to an MDNode",do { if (!(ScopeListMD != nullptr)) { CheckFailed("!id.scope.list must point to an MDNode" , II); return; } } while (false) | ||||
5670 | II)do { if (!(ScopeListMD != nullptr)) { CheckFailed("!id.scope.list must point to an MDNode" , II); return; } } while (false); | ||||
5671 | Assert(ScopeListMD->getNumOperands() == 1,do { if (!(ScopeListMD->getNumOperands() == 1)) { CheckFailed ("!id.scope.list must point to a list with a single scope", II ); return; } } while (false) | ||||
5672 | "!id.scope.list must point to a list with a single scope", II)do { if (!(ScopeListMD->getNumOperands() == 1)) { CheckFailed ("!id.scope.list must point to a list with a single scope", II ); return; } } while (false); | ||||
5673 | } | ||||
5674 | |||||
5675 | // Only check the domination rule when requested. Once all passes have been | ||||
5676 | // adapted this option can go away. | ||||
5677 | if (!VerifyNoAliasScopeDomination) | ||||
5678 | return; | ||||
5679 | |||||
5680 | // Now sort the intrinsics based on the scope MDNode so that declarations of | ||||
5681 | // the same scopes are next to each other. | ||||
5682 | auto GetScope = [](IntrinsicInst *II) { | ||||
5683 | const auto *ScopeListMV = cast<MetadataAsValue>( | ||||
5684 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
5685 | return &cast<MDNode>(ScopeListMV->getMetadata())->getOperand(0); | ||||
5686 | }; | ||||
5687 | |||||
5688 | // We are sorting on MDNode pointers here. For valid input IR this is ok. | ||||
5689 | // TODO: Sort on Metadata ID to avoid non-deterministic error messages. | ||||
5690 | auto Compare = [GetScope](IntrinsicInst *Lhs, IntrinsicInst *Rhs) { | ||||
5691 | return GetScope(Lhs) < GetScope(Rhs); | ||||
5692 | }; | ||||
5693 | |||||
5694 | llvm::sort(NoAliasScopeDecls, Compare); | ||||
5695 | |||||
5696 | // Go over the intrinsics and check that for the same scope, they are not | ||||
5697 | // dominating each other. | ||||
5698 | auto ItCurrent = NoAliasScopeDecls.begin(); | ||||
5699 | while (ItCurrent != NoAliasScopeDecls.end()) { | ||||
5700 | auto CurScope = GetScope(*ItCurrent); | ||||
5701 | auto ItNext = ItCurrent; | ||||
5702 | do { | ||||
5703 | ++ItNext; | ||||
5704 | } while (ItNext != NoAliasScopeDecls.end() && | ||||
5705 | GetScope(*ItNext) == CurScope); | ||||
5706 | |||||
5707 | // [ItCurrent, ItNext) represents the declarations for the same scope. | ||||
5708 | // Ensure they are not dominating each other.. but only if it is not too | ||||
5709 | // expensive. | ||||
5710 | if (ItNext - ItCurrent < 32) | ||||
5711 | for (auto *I : llvm::make_range(ItCurrent, ItNext)) | ||||
5712 | for (auto *J : llvm::make_range(ItCurrent, ItNext)) | ||||
5713 | if (I != J) | ||||
5714 | Assert(!DT.dominates(I, J),do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
5715 | "llvm.experimental.noalias.scope.decl dominates another one "do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
5716 | "with the same scope",do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
5717 | I)do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false); | ||||
5718 | ItCurrent = ItNext; | ||||
5719 | } | ||||
5720 | } | ||||
5721 | |||||
5722 | //===----------------------------------------------------------------------===// | ||||
5723 | // Implement the public interfaces to this file... | ||||
5724 | //===----------------------------------------------------------------------===// | ||||
5725 | |||||
5726 | bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { | ||||
5727 | Function &F = const_cast<Function &>(f); | ||||
5728 | |||||
5729 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
5730 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true, *f.getParent()); | ||||
5731 | |||||
5732 | // Note that this function's return value is inverted from what you would | ||||
5733 | // expect of a function called "verify". | ||||
5734 | return !V.verify(F); | ||||
5735 | } | ||||
5736 | |||||
5737 | bool llvm::verifyModule(const Module &M, raw_ostream *OS, | ||||
5738 | bool *BrokenDebugInfo) { | ||||
5739 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
5740 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo, M); | ||||
5741 | |||||
5742 | bool Broken = false; | ||||
5743 | for (const Function &F : M) | ||||
5744 | Broken |= !V.verify(F); | ||||
5745 | |||||
5746 | Broken |= !V.verify(); | ||||
5747 | if (BrokenDebugInfo) | ||||
5748 | *BrokenDebugInfo = V.hasBrokenDebugInfo(); | ||||
5749 | // Note that this function's return value is inverted from what you would | ||||
5750 | // expect of a function called "verify". | ||||
5751 | return Broken; | ||||
5752 | } | ||||
5753 | |||||
5754 | namespace { | ||||
5755 | |||||
5756 | struct VerifierLegacyPass : public FunctionPass { | ||||
5757 | static char ID; | ||||
5758 | |||||
5759 | std::unique_ptr<Verifier> V; | ||||
5760 | bool FatalErrors = true; | ||||
5761 | |||||
5762 | VerifierLegacyPass() : FunctionPass(ID) { | ||||
5763 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
5764 | } | ||||
5765 | explicit VerifierLegacyPass(bool FatalErrors) | ||||
5766 | : FunctionPass(ID), | ||||
5767 | FatalErrors(FatalErrors) { | ||||
5768 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
5769 | } | ||||
5770 | |||||
5771 | bool doInitialization(Module &M) override { | ||||
5772 | V = std::make_unique<Verifier>( | ||||
5773 | &dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false, M); | ||||
5774 | return false; | ||||
5775 | } | ||||
5776 | |||||
5777 | bool runOnFunction(Function &F) override { | ||||
5778 | if (!V->verify(F) && FatalErrors) { | ||||
5779 | errs() << "in function " << F.getName() << '\n'; | ||||
5780 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
5781 | } | ||||
5782 | return false; | ||||
5783 | } | ||||
5784 | |||||
5785 | bool doFinalization(Module &M) override { | ||||
5786 | bool HasErrors = false; | ||||
5787 | for (Function &F : M) | ||||
5788 | if (F.isDeclaration()) | ||||
5789 | HasErrors |= !V->verify(F); | ||||
5790 | |||||
5791 | HasErrors |= !V->verify(); | ||||
5792 | if (FatalErrors && (HasErrors || V->hasBrokenDebugInfo())) | ||||
5793 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
5794 | return false; | ||||
5795 | } | ||||
5796 | |||||
5797 | void getAnalysisUsage(AnalysisUsage &AU) const override { | ||||
5798 | AU.setPreservesAll(); | ||||
5799 | } | ||||
5800 | }; | ||||
5801 | |||||
5802 | } // end anonymous namespace | ||||
5803 | |||||
5804 | /// Helper to issue failure from the TBAA verification | ||||
5805 | template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) { | ||||
5806 | if (Diagnostic) | ||||
5807 | return Diagnostic->CheckFailed(Args...); | ||||
5808 | } | ||||
5809 | |||||
5810 | #define AssertTBAA(C, ...)do { if (!(C)) { CheckFailed(...); return false; } } while (false ) \ | ||||
5811 | do { \ | ||||
5812 | if (!(C)) { \ | ||||
5813 | CheckFailed(__VA_ARGS__); \ | ||||
5814 | return false; \ | ||||
5815 | } \ | ||||
5816 | } while (false) | ||||
5817 | |||||
5818 | /// Verify that \p BaseNode can be used as the "base type" in the struct-path | ||||
5819 | /// TBAA scheme. This means \p BaseNode is either a scalar node, or a | ||||
5820 | /// struct-type node describing an aggregate data structure (like a struct). | ||||
5821 | TBAAVerifier::TBAABaseNodeSummary | ||||
5822 | TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode, | ||||
5823 | bool IsNewFormat) { | ||||
5824 | if (BaseNode->getNumOperands() < 2) { | ||||
5825 | CheckFailed("Base nodes must have at least two operands", &I, BaseNode); | ||||
5826 | return {true, ~0u}; | ||||
5827 | } | ||||
5828 | |||||
5829 | auto Itr = TBAABaseNodes.find(BaseNode); | ||||
5830 | if (Itr != TBAABaseNodes.end()) | ||||
5831 | return Itr->second; | ||||
5832 | |||||
5833 | auto Result = verifyTBAABaseNodeImpl(I, BaseNode, IsNewFormat); | ||||
5834 | auto InsertResult = TBAABaseNodes.insert({BaseNode, Result}); | ||||
5835 | (void)InsertResult; | ||||
5836 | assert(InsertResult.second && "We just checked!")(static_cast <bool> (InsertResult.second && "We just checked!" ) ? void (0) : __assert_fail ("InsertResult.second && \"We just checked!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5836, __extension__ __PRETTY_FUNCTION__)); | ||||
5837 | return Result; | ||||
5838 | } | ||||
5839 | |||||
5840 | TBAAVerifier::TBAABaseNodeSummary | ||||
5841 | TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode, | ||||
5842 | bool IsNewFormat) { | ||||
5843 | const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u}; | ||||
5844 | |||||
5845 | if (BaseNode->getNumOperands() == 2) { | ||||
5846 | // Scalar nodes can only be accessed at offset 0. | ||||
5847 | return isValidScalarTBAANode(BaseNode) | ||||
5848 | ? TBAAVerifier::TBAABaseNodeSummary({false, 0}) | ||||
5849 | : InvalidNode; | ||||
5850 | } | ||||
5851 | |||||
5852 | if (IsNewFormat) { | ||||
5853 | if (BaseNode->getNumOperands() % 3 != 0) { | ||||
5854 | CheckFailed("Access tag nodes must have the number of operands that is a " | ||||
5855 | "multiple of 3!", BaseNode); | ||||
5856 | return InvalidNode; | ||||
5857 | } | ||||
5858 | } else { | ||||
5859 | if (BaseNode->getNumOperands() % 2 != 1) { | ||||
5860 | CheckFailed("Struct tag nodes must have an odd number of operands!", | ||||
5861 | BaseNode); | ||||
5862 | return InvalidNode; | ||||
5863 | } | ||||
5864 | } | ||||
5865 | |||||
5866 | // Check the type size field. | ||||
5867 | if (IsNewFormat) { | ||||
5868 | auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
5869 | BaseNode->getOperand(1)); | ||||
5870 | if (!TypeSizeNode) { | ||||
5871 | CheckFailed("Type size nodes must be constants!", &I, BaseNode); | ||||
5872 | return InvalidNode; | ||||
5873 | } | ||||
5874 | } | ||||
5875 | |||||
5876 | // Check the type name field. In the new format it can be anything. | ||||
5877 | if (!IsNewFormat && !isa<MDString>(BaseNode->getOperand(0))) { | ||||
5878 | CheckFailed("Struct tag nodes have a string as their first operand", | ||||
5879 | BaseNode); | ||||
5880 | return InvalidNode; | ||||
5881 | } | ||||
5882 | |||||
5883 | bool Failed = false; | ||||
5884 | |||||
5885 | Optional<APInt> PrevOffset; | ||||
5886 | unsigned BitWidth = ~0u; | ||||
5887 | |||||
5888 | // We've already checked that BaseNode is not a degenerate root node with one | ||||
5889 | // operand in \c verifyTBAABaseNode, so this loop should run at least once. | ||||
5890 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
5891 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
5892 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
5893 | Idx += NumOpsPerField) { | ||||
5894 | const MDOperand &FieldTy = BaseNode->getOperand(Idx); | ||||
5895 | const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1); | ||||
5896 | if (!isa<MDNode>(FieldTy)) { | ||||
5897 | CheckFailed("Incorrect field entry in struct type node!", &I, BaseNode); | ||||
5898 | Failed = true; | ||||
5899 | continue; | ||||
5900 | } | ||||
5901 | |||||
5902 | auto *OffsetEntryCI = | ||||
5903 | mdconst::dyn_extract_or_null<ConstantInt>(FieldOffset); | ||||
5904 | if (!OffsetEntryCI) { | ||||
5905 | CheckFailed("Offset entries must be constants!", &I, BaseNode); | ||||
5906 | Failed = true; | ||||
5907 | continue; | ||||
5908 | } | ||||
5909 | |||||
5910 | if (BitWidth == ~0u) | ||||
5911 | BitWidth = OffsetEntryCI->getBitWidth(); | ||||
5912 | |||||
5913 | if (OffsetEntryCI->getBitWidth() != BitWidth) { | ||||
5914 | CheckFailed( | ||||
5915 | "Bitwidth between the offsets and struct type entries must match", &I, | ||||
5916 | BaseNode); | ||||
5917 | Failed = true; | ||||
5918 | continue; | ||||
5919 | } | ||||
5920 | |||||
5921 | // NB! As far as I can tell, we generate a non-strictly increasing offset | ||||
5922 | // sequence only from structs that have zero size bit fields. When | ||||
5923 | // recursing into a contained struct in \c getFieldNodeFromTBAABaseNode we | ||||
5924 | // pick the field lexically the latest in struct type metadata node. This | ||||
5925 | // mirrors the actual behavior of the alias analysis implementation. | ||||
5926 | bool IsAscending = | ||||
5927 | !PrevOffset || PrevOffset->ule(OffsetEntryCI->getValue()); | ||||
5928 | |||||
5929 | if (!IsAscending) { | ||||
5930 | CheckFailed("Offsets must be increasing!", &I, BaseNode); | ||||
5931 | Failed = true; | ||||
5932 | } | ||||
5933 | |||||
5934 | PrevOffset = OffsetEntryCI->getValue(); | ||||
5935 | |||||
5936 | if (IsNewFormat) { | ||||
5937 | auto *MemberSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
5938 | BaseNode->getOperand(Idx + 2)); | ||||
5939 | if (!MemberSizeNode) { | ||||
5940 | CheckFailed("Member size entries must be constants!", &I, BaseNode); | ||||
5941 | Failed = true; | ||||
5942 | continue; | ||||
5943 | } | ||||
5944 | } | ||||
5945 | } | ||||
5946 | |||||
5947 | return Failed ? InvalidNode | ||||
5948 | : TBAAVerifier::TBAABaseNodeSummary(false, BitWidth); | ||||
5949 | } | ||||
5950 | |||||
5951 | static bool IsRootTBAANode(const MDNode *MD) { | ||||
5952 | return MD->getNumOperands() < 2; | ||||
5953 | } | ||||
5954 | |||||
5955 | static bool IsScalarTBAANodeImpl(const MDNode *MD, | ||||
5956 | SmallPtrSetImpl<const MDNode *> &Visited) { | ||||
5957 | if (MD->getNumOperands() != 2 && MD->getNumOperands() != 3) | ||||
5958 | return false; | ||||
5959 | |||||
5960 | if (!isa<MDString>(MD->getOperand(0))) | ||||
5961 | return false; | ||||
5962 | |||||
5963 | if (MD->getNumOperands() == 3) { | ||||
5964 | auto *Offset = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2)); | ||||
5965 | if (!(Offset && Offset->isZero() && isa<MDString>(MD->getOperand(0)))) | ||||
5966 | return false; | ||||
5967 | } | ||||
5968 | |||||
5969 | auto *Parent = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
5970 | return Parent && Visited.insert(Parent).second && | ||||
5971 | (IsRootTBAANode(Parent) || IsScalarTBAANodeImpl(Parent, Visited)); | ||||
5972 | } | ||||
5973 | |||||
5974 | bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) { | ||||
5975 | auto ResultIt = TBAAScalarNodes.find(MD); | ||||
5976 | if (ResultIt != TBAAScalarNodes.end()) | ||||
5977 | return ResultIt->second; | ||||
5978 | |||||
5979 | SmallPtrSet<const MDNode *, 4> Visited; | ||||
5980 | bool Result = IsScalarTBAANodeImpl(MD, Visited); | ||||
5981 | auto InsertResult = TBAAScalarNodes.insert({MD, Result}); | ||||
5982 | (void)InsertResult; | ||||
5983 | assert(InsertResult.second && "Just checked!")(static_cast <bool> (InsertResult.second && "Just checked!" ) ? void (0) : __assert_fail ("InsertResult.second && \"Just checked!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5983, __extension__ __PRETTY_FUNCTION__)); | ||||
5984 | |||||
5985 | return Result; | ||||
5986 | } | ||||
5987 | |||||
5988 | /// Returns the field node at the offset \p Offset in \p BaseNode. Update \p | ||||
5989 | /// Offset in place to be the offset within the field node returned. | ||||
5990 | /// | ||||
5991 | /// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode. | ||||
5992 | MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, | ||||
5993 | const MDNode *BaseNode, | ||||
5994 | APInt &Offset, | ||||
5995 | bool IsNewFormat) { | ||||
5996 | assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!")(static_cast <bool> (BaseNode->getNumOperands() >= 2 && "Invalid base node!") ? void (0) : __assert_fail ("BaseNode->getNumOperands() >= 2 && \"Invalid base node!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/IR/Verifier.cpp" , 5996, __extension__ __PRETTY_FUNCTION__)); | ||||
5997 | |||||
5998 | // Scalar nodes have only one possible "field" -- their parent in the access | ||||
5999 | // hierarchy. Offset must be zero at this point, but our caller is supposed | ||||
6000 | // to Assert that. | ||||
6001 | if (BaseNode->getNumOperands() == 2) | ||||
6002 | return cast<MDNode>(BaseNode->getOperand(1)); | ||||
6003 | |||||
6004 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
6005 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
6006 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
6007 | Idx += NumOpsPerField) { | ||||
6008 | auto *OffsetEntryCI = | ||||
6009 | mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1)); | ||||
6010 | if (OffsetEntryCI->getValue().ugt(Offset)) { | ||||
6011 | if (Idx == FirstFieldOpNo) { | ||||
6012 | CheckFailed("Could not find TBAA parent in struct type node", &I, | ||||
6013 | BaseNode, &Offset); | ||||
6014 | return nullptr; | ||||
6015 | } | ||||
6016 | |||||
6017 | unsigned PrevIdx = Idx - NumOpsPerField; | ||||
6018 | auto *PrevOffsetEntryCI = | ||||
6019 | mdconst::extract<ConstantInt>(BaseNode->getOperand(PrevIdx + 1)); | ||||
6020 | Offset -= PrevOffsetEntryCI->getValue(); | ||||
6021 | return cast<MDNode>(BaseNode->getOperand(PrevIdx)); | ||||
6022 | } | ||||
6023 | } | ||||
6024 | |||||
6025 | unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField; | ||||
6026 | auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( | ||||
6027 | BaseNode->getOperand(LastIdx + 1)); | ||||
6028 | Offset -= LastOffsetEntryCI->getValue(); | ||||
6029 | return cast<MDNode>(BaseNode->getOperand(LastIdx)); | ||||
6030 | } | ||||
6031 | |||||
6032 | static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { | ||||
6033 | if (!Type || Type->getNumOperands() < 3) | ||||
6034 | return false; | ||||
6035 | |||||
6036 | // In the new format type nodes shall have a reference to the parent type as | ||||
6037 | // its first operand. | ||||
6038 | MDNode *Parent = dyn_cast_or_null<MDNode>(Type->getOperand(0)); | ||||
6039 | if (!Parent) | ||||
6040 | return false; | ||||
6041 | |||||
6042 | return true; | ||||
6043 | } | ||||
6044 | |||||
6045 | bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { | ||||
6046 | AssertTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
6047 | isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
6048 | isa<AtomicCmpXchgInst>(I),do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
6049 | "This instruction shall not have a TBAA access tag!", &I)do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false); | ||||
6050 | |||||
6051 | bool IsStructPathTBAA = | ||||
6052 | isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; | ||||
6053 | |||||
6054 | AssertTBAA(do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
6055 | IsStructPathTBAA,do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
6056 | "Old-style TBAA is no longer allowed, use struct-path TBAA instead", &I)do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false); | ||||
6057 | |||||
6058 | MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0)); | ||||
6059 | MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
6060 | |||||
6061 | bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); | ||||
6062 | |||||
6063 | if (IsNewFormat) { | ||||
6064 | AssertTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5,do { if (!(MD->getNumOperands() == 4 || MD->getNumOperands () == 5)) { CheckFailed("Access tag metadata must have either 4 or 5 operands" , &I, MD); return false; } } while (false) | ||||
6065 | "Access tag metadata must have either 4 or 5 operands", &I, MD)do { if (!(MD->getNumOperands() == 4 || MD->getNumOperands () == 5)) { CheckFailed("Access tag metadata must have either 4 or 5 operands" , &I, MD); return false; } } while (false); | ||||
6066 | } else { | ||||
6067 | AssertTBAA(MD->getNumOperands() < 5,do { if (!(MD->getNumOperands() < 5)) { CheckFailed("Struct tag metadata must have either 3 or 4 operands" , &I, MD); return false; } } while (false) | ||||
6068 | "Struct tag metadata must have either 3 or 4 operands", &I, MD)do { if (!(MD->getNumOperands() < 5)) { CheckFailed("Struct tag metadata must have either 3 or 4 operands" , &I, MD); return false; } } while (false); | ||||
6069 | } | ||||
6070 | |||||
6071 | // Check the access size field. | ||||
6072 | if (IsNewFormat) { | ||||
6073 | auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6074 | MD->getOperand(3)); | ||||
6075 | AssertTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD)do { if (!(AccessSizeNode)) { CheckFailed("Access size field must be a constant" , &I, MD); return false; } } while (false); | ||||
6076 | } | ||||
6077 | |||||
6078 | // Check the immutability flag. | ||||
6079 | unsigned ImmutabilityFlagOpNo = IsNewFormat ? 4 : 3; | ||||
6080 | if (MD->getNumOperands() == ImmutabilityFlagOpNo + 1) { | ||||
6081 | auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6082 | MD->getOperand(ImmutabilityFlagOpNo)); | ||||
6083 | AssertTBAA(IsImmutableCI,do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
6084 | "Immutability tag on struct tag metadata must be a constant",do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
6085 | &I, MD)do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false); | ||||
6086 | AssertTBAA(do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
6087 | IsImmutableCI->isZero() || IsImmutableCI->isOne(),do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
6088 | "Immutability part of the struct tag metadata must be either 0 or 1",do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
6089 | &I, MD)do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false); | ||||
6090 | } | ||||
6091 | |||||
6092 | AssertTBAA(BaseNode && AccessType,do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
6093 | "Malformed struct tag metadata: base and access-type "do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
6094 | "should be non-null and point to Metadata nodes",do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
6095 | &I, MD, BaseNode, AccessType)do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false); | ||||
6096 | |||||
6097 | if (!IsNewFormat) { | ||||
6098 | AssertTBAA(isValidScalarTBAANode(AccessType),do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
6099 | "Access type node must be a valid scalar type", &I, MD,do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
6100 | AccessType)do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false); | ||||
6101 | } | ||||
6102 | |||||
6103 | auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2)); | ||||
6104 | AssertTBAA(OffsetCI, "Offset must be constant integer", &I, MD)do { if (!(OffsetCI)) { CheckFailed("Offset must be constant integer" , &I, MD); return false; } } while (false); | ||||
6105 | |||||
6106 | APInt Offset = OffsetCI->getValue(); | ||||
6107 | bool SeenAccessTypeInPath = false; | ||||
6108 | |||||
6109 | SmallPtrSet<MDNode *, 4> StructPath; | ||||
6110 | |||||
6111 | for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); | ||||
6112 | BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, | ||||
6113 | IsNewFormat)) { | ||||
6114 | if (!StructPath.insert(BaseNode).second) { | ||||
6115 | CheckFailed("Cycle detected in struct path", &I, MD); | ||||
6116 | return false; | ||||
6117 | } | ||||
6118 | |||||
6119 | bool Invalid; | ||||
6120 | unsigned BaseNodeBitWidth; | ||||
6121 | std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode, | ||||
6122 | IsNewFormat); | ||||
6123 | |||||
6124 | // If the base node is invalid in itself, then we've already printed all the | ||||
6125 | // errors we wanted to print. | ||||
6126 | if (Invalid) | ||||
6127 | return false; | ||||
6128 | |||||
6129 | SeenAccessTypeInPath |= BaseNode == AccessType; | ||||
6130 | |||||
6131 | if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType) | ||||
6132 | AssertTBAA(Offset == 0, "Offset not zero at the point of scalar access",do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false) | ||||
6133 | &I, MD, &Offset)do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false); | ||||
6134 | |||||
6135 | AssertTBAA(BaseNodeBitWidth == Offset.getBitWidth() ||do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
6136 | (BaseNodeBitWidth == 0 && Offset == 0) ||do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
6137 | (IsNewFormat && BaseNodeBitWidth == ~0u),do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
6138 | "Access bit-width not the same as description bit-width", &I, MD,do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
6139 | BaseNodeBitWidth, Offset.getBitWidth())do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false); | ||||
6140 | |||||
6141 | if (IsNewFormat && SeenAccessTypeInPath) | ||||
6142 | break; | ||||
6143 | } | ||||
6144 | |||||
6145 | AssertTBAA(SeenAccessTypeInPath, "Did not see access type in access path!",do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false) | ||||
6146 | &I, MD)do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false); | ||||
6147 | return true; | ||||
6148 | } | ||||
6149 | |||||
6150 | char VerifierLegacyPass::ID = 0; | ||||
6151 | INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false)static void *initializeVerifierLegacyPassPassOnce(PassRegistry &Registry) { PassInfo *PI = new PassInfo( "Module Verifier" , "verify", &VerifierLegacyPass::ID, PassInfo::NormalCtor_t (callDefaultCtor<VerifierLegacyPass>), false, false); Registry .registerPass(*PI, true); return PI; } static llvm::once_flag InitializeVerifierLegacyPassPassFlag; void llvm::initializeVerifierLegacyPassPass (PassRegistry &Registry) { llvm::call_once(InitializeVerifierLegacyPassPassFlag , initializeVerifierLegacyPassPassOnce, std::ref(Registry)); } | ||||
6152 | |||||
6153 | FunctionPass *llvm::createVerifierPass(bool FatalErrors) { | ||||
6154 | return new VerifierLegacyPass(FatalErrors); | ||||
6155 | } | ||||
6156 | |||||
6157 | AnalysisKey VerifierAnalysis::Key; | ||||
6158 | VerifierAnalysis::Result VerifierAnalysis::run(Module &M, | ||||
6159 | ModuleAnalysisManager &) { | ||||
6160 | Result Res; | ||||
6161 | Res.IRBroken = llvm::verifyModule(M, &dbgs(), &Res.DebugInfoBroken); | ||||
6162 | return Res; | ||||
6163 | } | ||||
6164 | |||||
6165 | VerifierAnalysis::Result VerifierAnalysis::run(Function &F, | ||||
6166 | FunctionAnalysisManager &) { | ||||
6167 | return { llvm::verifyFunction(F, &dbgs()), false }; | ||||
6168 | } | ||||
6169 | |||||
6170 | PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { | ||||
6171 | auto Res = AM.getResult<VerifierAnalysis>(M); | ||||
6172 | if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) | ||||
6173 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
6174 | |||||
6175 | return PreservedAnalyses::all(); | ||||
6176 | } | ||||
6177 | |||||
6178 | PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { | ||||
6179 | auto res = AM.getResult<VerifierAnalysis>(F); | ||||
6180 | if (res.IRBroken && FatalErrors) | ||||
6181 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
6182 | |||||
6183 | return PreservedAnalyses::all(); | ||||
6184 | } |
1 | //===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- 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 | // Declarations for metadata specific to debug info. | ||||
10 | // | ||||
11 | //===----------------------------------------------------------------------===// | ||||
12 | |||||
13 | #ifndef LLVM_IR_DEBUGINFOMETADATA_H | ||||
14 | #define LLVM_IR_DEBUGINFOMETADATA_H | ||||
15 | |||||
16 | #include "llvm/ADT/ArrayRef.h" | ||||
17 | #include "llvm/ADT/BitmaskEnum.h" | ||||
18 | #include "llvm/ADT/None.h" | ||||
19 | #include "llvm/ADT/Optional.h" | ||||
20 | #include "llvm/ADT/PointerUnion.h" | ||||
21 | #include "llvm/ADT/STLExtras.h" | ||||
22 | #include "llvm/ADT/SmallVector.h" | ||||
23 | #include "llvm/ADT/StringRef.h" | ||||
24 | #include "llvm/ADT/iterator_range.h" | ||||
25 | #include "llvm/BinaryFormat/Dwarf.h" | ||||
26 | #include "llvm/IR/Constants.h" | ||||
27 | #include "llvm/IR/Metadata.h" | ||||
28 | #include "llvm/Support/Casting.h" | ||||
29 | #include "llvm/Support/CommandLine.h" | ||||
30 | #include "llvm/Support/Discriminator.h" | ||||
31 | #include <cassert> | ||||
32 | #include <climits> | ||||
33 | #include <cstddef> | ||||
34 | #include <cstdint> | ||||
35 | #include <iterator> | ||||
36 | #include <type_traits> | ||||
37 | #include <vector> | ||||
38 | |||||
39 | // Helper macros for defining get() overrides. | ||||
40 | #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ | ||||
41 | #define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS | ||||
42 | #define DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)static CLASS *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK (FORMAL)) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK( ARGS), Distinct); } static TempCLASS getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { return TempCLASS ( getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary) ); } \ | ||||
43 | static CLASS *getDistinct(LLVMContext &Context, \ | ||||
44 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
45 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ | ||||
46 | } \ | ||||
47 | static Temp##CLASS getTemporary(LLVMContext &Context, \ | ||||
48 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
49 | return Temp##CLASS( \ | ||||
50 | getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ | ||||
51 | } | ||||
52 | #define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ | ||||
53 | static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
54 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ | ||||
55 | } \ | ||||
56 | static CLASS *getIfExists(LLVMContext &Context, \ | ||||
57 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
58 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ | ||||
59 | /* ShouldCreate */ false); \ | ||||
60 | } \ | ||||
61 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)static CLASS *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK (FORMAL)) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK( ARGS), Distinct); } static TempCLASS getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { return TempCLASS ( getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary) ); } | ||||
62 | |||||
63 | namespace llvm { | ||||
64 | |||||
65 | extern cl::opt<bool> EnableFSDiscriminator; | ||||
66 | |||||
67 | class DITypeRefArray { | ||||
68 | const MDTuple *N = nullptr; | ||||
69 | |||||
70 | public: | ||||
71 | DITypeRefArray() = default; | ||||
72 | DITypeRefArray(const MDTuple *N) : N(N) {} | ||||
73 | |||||
74 | explicit operator bool() const { return get(); } | ||||
75 | explicit operator MDTuple *() const { return get(); } | ||||
76 | |||||
77 | MDTuple *get() const { return const_cast<MDTuple *>(N); } | ||||
78 | MDTuple *operator->() const { return get(); } | ||||
79 | MDTuple &operator*() const { return *get(); } | ||||
80 | |||||
81 | // FIXME: Fix callers and remove condition on N. | ||||
82 | unsigned size() const { return N ? N->getNumOperands() : 0u; } | ||||
83 | DIType *operator[](unsigned I) const { | ||||
84 | return cast_or_null<DIType>(N->getOperand(I)); | ||||
85 | } | ||||
86 | |||||
87 | class iterator { | ||||
88 | MDNode::op_iterator I = nullptr; | ||||
89 | |||||
90 | public: | ||||
91 | using iterator_category = std::input_iterator_tag; | ||||
92 | using value_type = DIType *; | ||||
93 | using difference_type = std::ptrdiff_t; | ||||
94 | using pointer = void; | ||||
95 | using reference = DIType *; | ||||
96 | |||||
97 | iterator() = default; | ||||
98 | explicit iterator(MDNode::op_iterator I) : I(I) {} | ||||
99 | |||||
100 | DIType *operator*() const { return cast_or_null<DIType>(*I); } | ||||
101 | |||||
102 | iterator &operator++() { | ||||
103 | ++I; | ||||
104 | return *this; | ||||
105 | } | ||||
106 | |||||
107 | iterator operator++(int) { | ||||
108 | iterator Temp(*this); | ||||
109 | ++I; | ||||
110 | return Temp; | ||||
111 | } | ||||
112 | |||||
113 | bool operator==(const iterator &X) const { return I == X.I; } | ||||
114 | bool operator!=(const iterator &X) const { return I != X.I; } | ||||
115 | }; | ||||
116 | |||||
117 | // FIXME: Fix callers and remove condition on N. | ||||
118 | iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } | ||||
119 | iterator end() const { return N ? iterator(N->op_end()) : iterator(); } | ||||
120 | }; | ||||
121 | |||||
122 | /// Tagged DWARF-like metadata node. | ||||
123 | /// | ||||
124 | /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, | ||||
125 | /// defined in llvm/BinaryFormat/Dwarf.h). Called \a DINode because it's | ||||
126 | /// potentially used for non-DWARF output. | ||||
127 | class DINode : public MDNode { | ||||
128 | friend class LLVMContextImpl; | ||||
129 | friend class MDNode; | ||||
130 | |||||
131 | protected: | ||||
132 | DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
133 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) | ||||
134 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||
135 | assert(Tag < 1u << 16)(static_cast <bool> (Tag < 1u << 16) ? void (0 ) : __assert_fail ("Tag < 1u << 16", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 135, __extension__ __PRETTY_FUNCTION__)); | ||||
136 | SubclassData16 = Tag; | ||||
137 | } | ||||
138 | ~DINode() = default; | ||||
139 | |||||
140 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||
141 | return cast_or_null<Ty>(getOperand(I)); | ||||
142 | } | ||||
143 | |||||
144 | StringRef getStringOperand(unsigned I) const { | ||||
145 | if (auto *S = getOperandAs<MDString>(I)) | ||||
146 | return S->getString(); | ||||
147 | return StringRef(); | ||||
148 | } | ||||
149 | |||||
150 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||
151 | if (S.empty()) | ||||
152 | return nullptr; | ||||
153 | return MDString::get(Context, S); | ||||
154 | } | ||||
155 | |||||
156 | /// Allow subclasses to mutate the tag. | ||||
157 | void setTag(unsigned Tag) { SubclassData16 = Tag; } | ||||
158 | |||||
159 | public: | ||||
160 | dwarf::Tag getTag() const { return (dwarf::Tag)SubclassData16; } | ||||
161 | |||||
162 | /// Debug info flags. | ||||
163 | /// | ||||
164 | /// The three accessibility flags are mutually exclusive and rolled together | ||||
165 | /// in the first two bits. | ||||
166 | enum DIFlags : uint32_t { | ||||
167 | #define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, | ||||
168 | #define DI_FLAG_LARGEST_NEEDED | ||||
169 | #include "llvm/IR/DebugInfoFlags.def" | ||||
170 | FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic, | ||||
171 | FlagPtrToMemberRep = FlagSingleInheritance | FlagMultipleInheritance | | ||||
172 | FlagVirtualInheritance, | ||||
173 | LLVM_MARK_AS_BITMASK_ENUM(FlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = FlagLargest | ||||
174 | }; | ||||
175 | |||||
176 | static DIFlags getFlag(StringRef Flag); | ||||
177 | static StringRef getFlagString(DIFlags Flag); | ||||
178 | |||||
179 | /// Split up a flags bitfield. | ||||
180 | /// | ||||
181 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||
182 | /// any remaining (unrecognized) bits. | ||||
183 | static DIFlags splitFlags(DIFlags Flags, | ||||
184 | SmallVectorImpl<DIFlags> &SplitFlags); | ||||
185 | |||||
186 | static bool classof(const Metadata *MD) { | ||||
187 | switch (MD->getMetadataID()) { | ||||
188 | default: | ||||
189 | return false; | ||||
190 | case GenericDINodeKind: | ||||
191 | case DISubrangeKind: | ||||
192 | case DIEnumeratorKind: | ||||
193 | case DIBasicTypeKind: | ||||
194 | case DIStringTypeKind: | ||||
195 | case DIDerivedTypeKind: | ||||
196 | case DICompositeTypeKind: | ||||
197 | case DISubroutineTypeKind: | ||||
198 | case DIFileKind: | ||||
199 | case DICompileUnitKind: | ||||
200 | case DISubprogramKind: | ||||
201 | case DILexicalBlockKind: | ||||
202 | case DILexicalBlockFileKind: | ||||
203 | case DINamespaceKind: | ||||
204 | case DICommonBlockKind: | ||||
205 | case DITemplateTypeParameterKind: | ||||
206 | case DITemplateValueParameterKind: | ||||
207 | case DIGlobalVariableKind: | ||||
208 | case DILocalVariableKind: | ||||
209 | case DILabelKind: | ||||
210 | case DIObjCPropertyKind: | ||||
211 | case DIImportedEntityKind: | ||||
212 | case DIModuleKind: | ||||
213 | case DIGenericSubrangeKind: | ||||
214 | return true; | ||||
215 | } | ||||
216 | } | ||||
217 | }; | ||||
218 | |||||
219 | /// Generic tagged DWARF-like metadata node. | ||||
220 | /// | ||||
221 | /// An un-specialized DWARF-like metadata node. The first operand is a | ||||
222 | /// (possibly empty) null-separated \a MDString header that contains arbitrary | ||||
223 | /// fields. The remaining operands are \a dwarf_operands(), and are pointers | ||||
224 | /// to other metadata. | ||||
225 | class GenericDINode : public DINode { | ||||
226 | friend class LLVMContextImpl; | ||||
227 | friend class MDNode; | ||||
228 | |||||
229 | GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, | ||||
230 | unsigned Tag, ArrayRef<Metadata *> Ops1, | ||||
231 | ArrayRef<Metadata *> Ops2) | ||||
232 | : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { | ||||
233 | setHash(Hash); | ||||
234 | } | ||||
235 | ~GenericDINode() { dropAllReferences(); } | ||||
236 | |||||
237 | void setHash(unsigned Hash) { SubclassData32 = Hash; } | ||||
238 | void recalculateHash(); | ||||
239 | |||||
240 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||
241 | StringRef Header, ArrayRef<Metadata *> DwarfOps, | ||||
242 | StorageType Storage, bool ShouldCreate = true) { | ||||
243 | return getImpl(Context, Tag, getCanonicalMDString(Context, Header), | ||||
244 | DwarfOps, Storage, ShouldCreate); | ||||
245 | } | ||||
246 | |||||
247 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||
248 | MDString *Header, ArrayRef<Metadata *> DwarfOps, | ||||
249 | StorageType Storage, bool ShouldCreate = true); | ||||
250 | |||||
251 | TempGenericDINode cloneImpl() const { | ||||
252 | return getTemporary(getContext(), getTag(), getHeader(), | ||||
253 | SmallVector<Metadata *, 4>(dwarf_operands())); | ||||
254 | } | ||||
255 | |||||
256 | public: | ||||
257 | unsigned getHash() const { return SubclassData32; } | ||||
258 | |||||
259 | DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef Header, | ||||
260 | ArrayRef<Metadata *> DwarfOps), | ||||
261 | (Tag, Header, DwarfOps)) | ||||
262 | DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *Header, | ||||
263 | ArrayRef<Metadata *> DwarfOps), | ||||
264 | (Tag, Header, DwarfOps)) | ||||
265 | |||||
266 | /// Return a (temporary) clone of this. | ||||
267 | TempGenericDINode clone() const { return cloneImpl(); } | ||||
268 | |||||
269 | dwarf::Tag getTag() const { return (dwarf::Tag)SubclassData16; } | ||||
270 | StringRef getHeader() const { return getStringOperand(0); } | ||||
271 | MDString *getRawHeader() const { return getOperandAs<MDString>(0); } | ||||
272 | |||||
273 | op_iterator dwarf_op_begin() const { return op_begin() + 1; } | ||||
274 | op_iterator dwarf_op_end() const { return op_end(); } | ||||
275 | op_range dwarf_operands() const { | ||||
276 | return op_range(dwarf_op_begin(), dwarf_op_end()); | ||||
277 | } | ||||
278 | |||||
279 | unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } | ||||
280 | const MDOperand &getDwarfOperand(unsigned I) const { | ||||
281 | return getOperand(I + 1); | ||||
282 | } | ||||
283 | void replaceDwarfOperandWith(unsigned I, Metadata *New) { | ||||
284 | replaceOperandWith(I + 1, New); | ||||
285 | } | ||||
286 | |||||
287 | static bool classof(const Metadata *MD) { | ||||
288 | return MD->getMetadataID() == GenericDINodeKind; | ||||
289 | } | ||||
290 | }; | ||||
291 | |||||
292 | /// Array subrange. | ||||
293 | /// | ||||
294 | /// TODO: Merge into node for DW_TAG_array_type, which should have a custom | ||||
295 | /// type. | ||||
296 | class DISubrange : public DINode { | ||||
297 | friend class LLVMContextImpl; | ||||
298 | friend class MDNode; | ||||
299 | |||||
300 | DISubrange(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) | ||||
301 | : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {} | ||||
302 | |||||
303 | ~DISubrange() = default; | ||||
304 | |||||
305 | static DISubrange *getImpl(LLVMContext &Context, int64_t Count, | ||||
306 | int64_t LowerBound, StorageType Storage, | ||||
307 | bool ShouldCreate = true); | ||||
308 | |||||
309 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||
310 | int64_t LowerBound, StorageType Storage, | ||||
311 | bool ShouldCreate = true); | ||||
312 | |||||
313 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||
314 | Metadata *LowerBound, Metadata *UpperBound, | ||||
315 | Metadata *Stride, StorageType Storage, | ||||
316 | bool ShouldCreate = true); | ||||
317 | |||||
318 | TempDISubrange cloneImpl() const { | ||||
319 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||
320 | getRawUpperBound(), getRawStride()); | ||||
321 | } | ||||
322 | |||||
323 | public: | ||||
324 | DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), | ||||
325 | (Count, LowerBound)) | ||||
326 | |||||
327 | DEFINE_MDNODE_GET(DISubrange, (Metadata *CountNode, int64_t LowerBound = 0), | ||||
328 | (CountNode, LowerBound)) | ||||
329 | |||||
330 | DEFINE_MDNODE_GET(DISubrange, | ||||
331 | (Metadata * CountNode, Metadata *LowerBound, | ||||
332 | Metadata *UpperBound, Metadata *Stride), | ||||
333 | (CountNode, LowerBound, UpperBound, Stride)) | ||||
334 | |||||
335 | TempDISubrange clone() const { return cloneImpl(); } | ||||
336 | |||||
337 | Metadata *getRawCountNode() const { | ||||
338 | return getOperand(0).get(); | ||||
339 | } | ||||
340 | |||||
341 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||
342 | |||||
343 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||
344 | |||||
345 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||
346 | |||||
347 | typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType; | ||||
348 | |||||
349 | BoundType getCount() const; | ||||
350 | |||||
351 | BoundType getLowerBound() const; | ||||
352 | |||||
353 | BoundType getUpperBound() const; | ||||
354 | |||||
355 | BoundType getStride() const; | ||||
356 | |||||
357 | static bool classof(const Metadata *MD) { | ||||
358 | return MD->getMetadataID() == DISubrangeKind; | ||||
359 | } | ||||
360 | }; | ||||
361 | |||||
362 | class DIGenericSubrange : public DINode { | ||||
363 | friend class LLVMContextImpl; | ||||
364 | friend class MDNode; | ||||
365 | |||||
366 | DIGenericSubrange(LLVMContext &C, StorageType Storage, | ||||
367 | ArrayRef<Metadata *> Ops) | ||||
368 | : DINode(C, DIGenericSubrangeKind, Storage, | ||||
369 | dwarf::DW_TAG_generic_subrange, Ops) {} | ||||
370 | |||||
371 | ~DIGenericSubrange() = default; | ||||
372 | |||||
373 | static DIGenericSubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||
374 | Metadata *LowerBound, Metadata *UpperBound, | ||||
375 | Metadata *Stride, StorageType Storage, | ||||
376 | bool ShouldCreate = true); | ||||
377 | |||||
378 | TempDIGenericSubrange cloneImpl() const { | ||||
379 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||
380 | getRawUpperBound(), getRawStride()); | ||||
381 | } | ||||
382 | |||||
383 | public: | ||||
384 | DEFINE_MDNODE_GET(DIGenericSubrange, | ||||
385 | (Metadata * CountNode, Metadata *LowerBound, | ||||
386 | Metadata *UpperBound, Metadata *Stride), | ||||
387 | (CountNode, LowerBound, UpperBound, Stride)) | ||||
388 | |||||
389 | TempDIGenericSubrange clone() const { return cloneImpl(); } | ||||
390 | |||||
391 | Metadata *getRawCountNode() const { return getOperand(0).get(); } | ||||
392 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||
393 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||
394 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||
395 | |||||
396 | using BoundType = PointerUnion<DIVariable *, DIExpression *>; | ||||
397 | |||||
398 | BoundType getCount() const; | ||||
399 | BoundType getLowerBound() const; | ||||
400 | BoundType getUpperBound() const; | ||||
401 | BoundType getStride() const; | ||||
402 | |||||
403 | static bool classof(const Metadata *MD) { | ||||
404 | return MD->getMetadataID() == DIGenericSubrangeKind; | ||||
405 | } | ||||
406 | }; | ||||
407 | |||||
408 | /// Enumeration value. | ||||
409 | /// | ||||
410 | /// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no | ||||
411 | /// longer creates a type cycle. | ||||
412 | class DIEnumerator : public DINode { | ||||
413 | friend class LLVMContextImpl; | ||||
414 | friend class MDNode; | ||||
415 | |||||
416 | APInt Value; | ||||
417 | DIEnumerator(LLVMContext &C, StorageType Storage, const APInt &Value, | ||||
418 | bool IsUnsigned, ArrayRef<Metadata *> Ops) | ||||
419 | : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), | ||||
420 | Value(Value) { | ||||
421 | SubclassData32 = IsUnsigned; | ||||
422 | } | ||||
423 | DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, | ||||
424 | bool IsUnsigned, ArrayRef<Metadata *> Ops) | ||||
425 | : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, | ||||
426 | Ops) {} | ||||
427 | ~DIEnumerator() = default; | ||||
428 | |||||
429 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||
430 | bool IsUnsigned, StringRef Name, | ||||
431 | StorageType Storage, bool ShouldCreate = true) { | ||||
432 | return getImpl(Context, Value, IsUnsigned, | ||||
433 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); | ||||
434 | } | ||||
435 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||
436 | bool IsUnsigned, MDString *Name, | ||||
437 | StorageType Storage, bool ShouldCreate = true); | ||||
438 | |||||
439 | TempDIEnumerator cloneImpl() const { | ||||
440 | return getTemporary(getContext(), getValue(), isUnsigned(), getName()); | ||||
441 | } | ||||
442 | |||||
443 | public: | ||||
444 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
445 | (int64_t Value, bool IsUnsigned, StringRef Name), | ||||
446 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||
447 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
448 | (int64_t Value, bool IsUnsigned, MDString *Name), | ||||
449 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||
450 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
451 | (APInt Value, bool IsUnsigned, StringRef Name), | ||||
452 | (Value, IsUnsigned, Name)) | ||||
453 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
454 | (APInt Value, bool IsUnsigned, MDString *Name), | ||||
455 | (Value, IsUnsigned, Name)) | ||||
456 | |||||
457 | TempDIEnumerator clone() const { return cloneImpl(); } | ||||
458 | |||||
459 | const APInt &getValue() const { return Value; } | ||||
460 | bool isUnsigned() const { return SubclassData32; } | ||||
461 | StringRef getName() const { return getStringOperand(0); } | ||||
462 | |||||
463 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
464 | |||||
465 | static bool classof(const Metadata *MD) { | ||||
466 | return MD->getMetadataID() == DIEnumeratorKind; | ||||
467 | } | ||||
468 | }; | ||||
469 | |||||
470 | /// Base class for scope-like contexts. | ||||
471 | /// | ||||
472 | /// Base class for lexical scopes and types (which are also declaration | ||||
473 | /// contexts). | ||||
474 | /// | ||||
475 | /// TODO: Separate the concepts of declaration contexts and lexical scopes. | ||||
476 | class DIScope : public DINode { | ||||
477 | protected: | ||||
478 | DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
479 | ArrayRef<Metadata *> Ops) | ||||
480 | : DINode(C, ID, Storage, Tag, Ops) {} | ||||
481 | ~DIScope() = default; | ||||
482 | |||||
483 | public: | ||||
484 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
485 | |||||
486 | inline StringRef getFilename() const; | ||||
487 | inline StringRef getDirectory() const; | ||||
488 | inline Optional<StringRef> getSource() const; | ||||
489 | |||||
490 | StringRef getName() const; | ||||
491 | DIScope *getScope() const; | ||||
492 | |||||
493 | /// Return the raw underlying file. | ||||
494 | /// | ||||
495 | /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file (it | ||||
496 | /// \em is the file). If \c this is an \a DIFile, we need to return \c this. | ||||
497 | /// Otherwise, return the first operand, which is where all other subclasses | ||||
498 | /// store their file pointer. | ||||
499 | Metadata *getRawFile() const { | ||||
500 | return isa<DIFile>(this) ? const_cast<DIScope *>(this) | ||||
501 | : static_cast<Metadata *>(getOperand(0)); | ||||
502 | } | ||||
503 | |||||
504 | static bool classof(const Metadata *MD) { | ||||
505 | switch (MD->getMetadataID()) { | ||||
506 | default: | ||||
507 | return false; | ||||
508 | case DIBasicTypeKind: | ||||
509 | case DIStringTypeKind: | ||||
510 | case DIDerivedTypeKind: | ||||
511 | case DICompositeTypeKind: | ||||
512 | case DISubroutineTypeKind: | ||||
513 | case DIFileKind: | ||||
514 | case DICompileUnitKind: | ||||
515 | case DISubprogramKind: | ||||
516 | case DILexicalBlockKind: | ||||
517 | case DILexicalBlockFileKind: | ||||
518 | case DINamespaceKind: | ||||
519 | case DICommonBlockKind: | ||||
520 | case DIModuleKind: | ||||
521 | return true; | ||||
522 | } | ||||
523 | } | ||||
524 | }; | ||||
525 | |||||
526 | /// File. | ||||
527 | /// | ||||
528 | /// TODO: Merge with directory/file node (including users). | ||||
529 | /// TODO: Canonicalize paths on creation. | ||||
530 | class DIFile : public DIScope { | ||||
531 | friend class LLVMContextImpl; | ||||
532 | friend class MDNode; | ||||
533 | |||||
534 | public: | ||||
535 | /// Which algorithm (e.g. MD5) a checksum was generated with. | ||||
536 | /// | ||||
537 | /// The encoding is explicit because it is used directly in Bitcode. The | ||||
538 | /// value 0 is reserved to indicate the absence of a checksum in Bitcode. | ||||
539 | enum ChecksumKind { | ||||
540 | // The first variant was originally CSK_None, encoded as 0. The new | ||||
541 | // internal representation removes the need for this by wrapping the | ||||
542 | // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0 | ||||
543 | // encoding is reserved. | ||||
544 | CSK_MD5 = 1, | ||||
545 | CSK_SHA1 = 2, | ||||
546 | CSK_SHA256 = 3, | ||||
547 | CSK_Last = CSK_SHA256 // Should be last enumeration. | ||||
548 | }; | ||||
549 | |||||
550 | /// A single checksum, represented by a \a Kind and a \a Value (a string). | ||||
551 | template <typename T> | ||||
552 | struct ChecksumInfo { | ||||
553 | /// The kind of checksum which \a Value encodes. | ||||
554 | ChecksumKind Kind; | ||||
555 | /// The string value of the checksum. | ||||
556 | T Value; | ||||
557 | |||||
558 | ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) { } | ||||
559 | ~ChecksumInfo() = default; | ||||
560 | bool operator==(const ChecksumInfo<T> &X) const { | ||||
561 | return Kind == X.Kind && Value == X.Value; | ||||
562 | } | ||||
563 | bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } | ||||
564 | StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } | ||||
565 | }; | ||||
566 | |||||
567 | private: | ||||
568 | Optional<ChecksumInfo<MDString *>> Checksum; | ||||
569 | Optional<MDString *> Source; | ||||
570 | |||||
571 | DIFile(LLVMContext &C, StorageType Storage, | ||||
572 | Optional<ChecksumInfo<MDString *>> CS, Optional<MDString *> Src, | ||||
573 | ArrayRef<Metadata *> Ops) | ||||
574 | : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), | ||||
575 | Checksum(CS), Source(Src) {} | ||||
576 | ~DIFile() = default; | ||||
577 | |||||
578 | static DIFile *getImpl(LLVMContext &Context, StringRef Filename, | ||||
579 | StringRef Directory, | ||||
580 | Optional<ChecksumInfo<StringRef>> CS, | ||||
581 | Optional<StringRef> Source, | ||||
582 | StorageType Storage, bool ShouldCreate = true) { | ||||
583 | Optional<ChecksumInfo<MDString *>> MDChecksum; | ||||
584 | if (CS) | ||||
585 | MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); | ||||
586 | return getImpl(Context, getCanonicalMDString(Context, Filename), | ||||
587 | getCanonicalMDString(Context, Directory), MDChecksum, | ||||
588 | Source ? Optional<MDString *>(getCanonicalMDString(Context, *Source)) : None, | ||||
589 | Storage, ShouldCreate); | ||||
590 | } | ||||
591 | static DIFile *getImpl(LLVMContext &Context, MDString *Filename, | ||||
592 | MDString *Directory, | ||||
593 | Optional<ChecksumInfo<MDString *>> CS, | ||||
594 | Optional<MDString *> Source, StorageType Storage, | ||||
595 | bool ShouldCreate = true); | ||||
596 | |||||
597 | TempDIFile cloneImpl() const { | ||||
598 | return getTemporary(getContext(), getFilename(), getDirectory(), | ||||
599 | getChecksum(), getSource()); | ||||
600 | } | ||||
601 | |||||
602 | public: | ||||
603 | DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory, | ||||
604 | Optional<ChecksumInfo<StringRef>> CS = None, | ||||
605 | Optional<StringRef> Source = None), | ||||
606 | (Filename, Directory, CS, Source)) | ||||
607 | DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory, | ||||
608 | Optional<ChecksumInfo<MDString *>> CS = None, | ||||
609 | Optional<MDString *> Source = None), | ||||
610 | (Filename, Directory, CS, Source)) | ||||
611 | |||||
612 | TempDIFile clone() const { return cloneImpl(); } | ||||
613 | |||||
614 | StringRef getFilename() const { return getStringOperand(0); } | ||||
615 | StringRef getDirectory() const { return getStringOperand(1); } | ||||
616 | Optional<ChecksumInfo<StringRef>> getChecksum() const { | ||||
617 | Optional<ChecksumInfo<StringRef>> StringRefChecksum; | ||||
618 | if (Checksum) | ||||
619 | StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); | ||||
620 | return StringRefChecksum; | ||||
621 | } | ||||
622 | Optional<StringRef> getSource() const { | ||||
623 | return Source ? Optional<StringRef>((*Source)->getString()) : None; | ||||
624 | } | ||||
625 | |||||
626 | MDString *getRawFilename() const { return getOperandAs<MDString>(0); } | ||||
627 | MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } | ||||
628 | Optional<ChecksumInfo<MDString *>> getRawChecksum() const { return Checksum; } | ||||
629 | Optional<MDString *> getRawSource() const { return Source; } | ||||
630 | |||||
631 | static StringRef getChecksumKindAsString(ChecksumKind CSKind); | ||||
632 | static Optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); | ||||
633 | |||||
634 | static bool classof(const Metadata *MD) { | ||||
635 | return MD->getMetadataID() == DIFileKind; | ||||
636 | } | ||||
637 | }; | ||||
638 | |||||
639 | StringRef DIScope::getFilename() const { | ||||
640 | if (auto *F = getFile()) | ||||
641 | return F->getFilename(); | ||||
642 | return ""; | ||||
643 | } | ||||
644 | |||||
645 | StringRef DIScope::getDirectory() const { | ||||
646 | if (auto *F = getFile()) | ||||
647 | return F->getDirectory(); | ||||
648 | return ""; | ||||
649 | } | ||||
650 | |||||
651 | Optional<StringRef> DIScope::getSource() const { | ||||
652 | if (auto *F = getFile()) | ||||
653 | return F->getSource(); | ||||
654 | return None; | ||||
655 | } | ||||
656 | |||||
657 | /// Base class for types. | ||||
658 | /// | ||||
659 | /// TODO: Remove the hardcoded name and context, since many types don't use | ||||
660 | /// them. | ||||
661 | /// TODO: Split up flags. | ||||
662 | class DIType : public DIScope { | ||||
663 | unsigned Line; | ||||
664 | DIFlags Flags; | ||||
665 | uint64_t SizeInBits; | ||||
666 | uint64_t OffsetInBits; | ||||
667 | uint32_t AlignInBits; | ||||
668 | |||||
669 | protected: | ||||
670 | DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
671 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
672 | uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||
673 | : DIScope(C, ID, Storage, Tag, Ops) { | ||||
674 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||
675 | } | ||||
676 | ~DIType() = default; | ||||
677 | |||||
678 | void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
679 | uint64_t OffsetInBits, DIFlags Flags) { | ||||
680 | this->Line = Line; | ||||
681 | this->Flags = Flags; | ||||
682 | this->SizeInBits = SizeInBits; | ||||
683 | this->AlignInBits = AlignInBits; | ||||
684 | this->OffsetInBits = OffsetInBits; | ||||
685 | } | ||||
686 | |||||
687 | /// Change fields in place. | ||||
688 | void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits, | ||||
689 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) { | ||||
690 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 690, __extension__ __PRETTY_FUNCTION__)); | ||||
691 | setTag(Tag); | ||||
692 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||
693 | } | ||||
694 | |||||
695 | public: | ||||
696 | TempDIType clone() const { | ||||
697 | return TempDIType(cast<DIType>(MDNode::clone().release())); | ||||
698 | } | ||||
699 | |||||
700 | unsigned getLine() const { return Line; } | ||||
701 | uint64_t getSizeInBits() const { return SizeInBits; } | ||||
702 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||
703 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||
704 | uint64_t getOffsetInBits() const { return OffsetInBits; } | ||||
705 | DIFlags getFlags() const { return Flags; } | ||||
706 | |||||
707 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
708 | StringRef getName() const { return getStringOperand(2); } | ||||
709 | |||||
710 | |||||
711 | Metadata *getRawScope() const { return getOperand(1); } | ||||
712 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
713 | |||||
714 | /// Returns a new temporary DIType with updated Flags | ||||
715 | TempDIType cloneWithFlags(DIFlags NewFlags) const { | ||||
716 | auto NewTy = clone(); | ||||
717 | NewTy->Flags = NewFlags; | ||||
718 | return NewTy; | ||||
719 | } | ||||
720 | |||||
721 | bool isPrivate() const { | ||||
722 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||
723 | } | ||||
724 | bool isProtected() const { | ||||
725 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||
726 | } | ||||
727 | bool isPublic() const { | ||||
728 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||
729 | } | ||||
730 | bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } | ||||
731 | bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } | ||||
732 | bool isVirtual() const { return getFlags() & FlagVirtual; } | ||||
733 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
734 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||
735 | bool isObjcClassComplete() const { | ||||
736 | return getFlags() & FlagObjcClassComplete; | ||||
737 | } | ||||
738 | bool isVector() const { return getFlags() & FlagVector; } | ||||
739 | bool isBitField() const { return getFlags() & FlagBitField; } | ||||
740 | bool isStaticMember() const { return getFlags() & FlagStaticMember; } | ||||
741 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||
742 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||
743 | bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; } | ||||
744 | bool isTypePassByReference() const { | ||||
745 | return getFlags() & FlagTypePassByReference; | ||||
746 | } | ||||
747 | bool isBigEndian() const { return getFlags() & FlagBigEndian; } | ||||
748 | bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } | ||||
749 | bool getExportSymbols() const { return getFlags() & FlagExportSymbols; } | ||||
750 | |||||
751 | static bool classof(const Metadata *MD) { | ||||
752 | switch (MD->getMetadataID()) { | ||||
753 | default: | ||||
754 | return false; | ||||
755 | case DIBasicTypeKind: | ||||
756 | case DIStringTypeKind: | ||||
757 | case DIDerivedTypeKind: | ||||
758 | case DICompositeTypeKind: | ||||
759 | case DISubroutineTypeKind: | ||||
760 | return true; | ||||
761 | } | ||||
762 | } | ||||
763 | }; | ||||
764 | |||||
765 | /// Basic type, like 'int' or 'float'. | ||||
766 | /// | ||||
767 | /// TODO: Split out DW_TAG_unspecified_type. | ||||
768 | /// TODO: Drop unused accessors. | ||||
769 | class DIBasicType : public DIType { | ||||
770 | friend class LLVMContextImpl; | ||||
771 | friend class MDNode; | ||||
772 | |||||
773 | unsigned Encoding; | ||||
774 | |||||
775 | DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
776 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||
777 | DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||
778 | : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||
779 | Flags, Ops), | ||||
780 | Encoding(Encoding) {} | ||||
781 | ~DIBasicType() = default; | ||||
782 | |||||
783 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
784 | StringRef Name, uint64_t SizeInBits, | ||||
785 | uint32_t AlignInBits, unsigned Encoding, | ||||
786 | DIFlags Flags, StorageType Storage, | ||||
787 | bool ShouldCreate = true) { | ||||
788 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||
789 | SizeInBits, AlignInBits, Encoding, Flags, Storage, | ||||
790 | ShouldCreate); | ||||
791 | } | ||||
792 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
793 | MDString *Name, uint64_t SizeInBits, | ||||
794 | uint32_t AlignInBits, unsigned Encoding, | ||||
795 | DIFlags Flags, StorageType Storage, | ||||
796 | bool ShouldCreate = true); | ||||
797 | |||||
798 | TempDIBasicType cloneImpl() const { | ||||
799 | return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), | ||||
800 | getAlignInBits(), getEncoding(), getFlags()); | ||||
801 | } | ||||
802 | |||||
803 | public: | ||||
804 | DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), | ||||
805 | (Tag, Name, 0, 0, 0, FlagZero)) | ||||
806 | DEFINE_MDNODE_GET(DIBasicType, | ||||
807 | (unsigned Tag, StringRef Name, uint64_t SizeInBits), | ||||
808 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||
809 | DEFINE_MDNODE_GET(DIBasicType, | ||||
810 | (unsigned Tag, MDString *Name, uint64_t SizeInBits), | ||||
811 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||
812 | DEFINE_MDNODE_GET(DIBasicType, | ||||
813 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||
814 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||
815 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||
816 | DEFINE_MDNODE_GET(DIBasicType, | ||||
817 | (unsigned Tag, MDString *Name, uint64_t SizeInBits, | ||||
818 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||
819 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||
820 | |||||
821 | TempDIBasicType clone() const { return cloneImpl(); } | ||||
822 | |||||
823 | unsigned getEncoding() const { return Encoding; } | ||||
824 | |||||
825 | enum class Signedness { Signed, Unsigned }; | ||||
826 | |||||
827 | /// Return the signedness of this type, or None if this type is neither | ||||
828 | /// signed nor unsigned. | ||||
829 | Optional<Signedness> getSignedness() const; | ||||
830 | |||||
831 | static bool classof(const Metadata *MD) { | ||||
832 | return MD->getMetadataID() == DIBasicTypeKind; | ||||
833 | } | ||||
834 | }; | ||||
835 | |||||
836 | /// String type, Fortran CHARACTER(n) | ||||
837 | class DIStringType : public DIType { | ||||
838 | friend class LLVMContextImpl; | ||||
839 | friend class MDNode; | ||||
840 | |||||
841 | unsigned Encoding; | ||||
842 | |||||
843 | DIStringType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
844 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||
845 | ArrayRef<Metadata *> Ops) | ||||
846 | : DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||
847 | FlagZero, Ops), | ||||
848 | Encoding(Encoding) {} | ||||
849 | ~DIStringType() = default; | ||||
850 | |||||
851 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
852 | StringRef Name, Metadata *StringLength, | ||||
853 | Metadata *StrLenExp, uint64_t SizeInBits, | ||||
854 | uint32_t AlignInBits, unsigned Encoding, | ||||
855 | StorageType Storage, bool ShouldCreate = true) { | ||||
856 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||
857 | StringLength, StrLenExp, SizeInBits, AlignInBits, Encoding, | ||||
858 | Storage, ShouldCreate); | ||||
859 | } | ||||
860 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
861 | MDString *Name, Metadata *StringLength, | ||||
862 | Metadata *StrLenExp, uint64_t SizeInBits, | ||||
863 | uint32_t AlignInBits, unsigned Encoding, | ||||
864 | StorageType Storage, bool ShouldCreate = true); | ||||
865 | |||||
866 | TempDIStringType cloneImpl() const { | ||||
867 | return getTemporary(getContext(), getTag(), getRawName(), | ||||
868 | getRawStringLength(), getRawStringLengthExp(), | ||||
869 | getSizeInBits(), getAlignInBits(), getEncoding()); | ||||
870 | } | ||||
871 | |||||
872 | public: | ||||
873 | DEFINE_MDNODE_GET(DIStringType, | ||||
874 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||
875 | uint32_t AlignInBits), | ||||
876 | (Tag, Name, nullptr, nullptr, SizeInBits, AlignInBits, 0)) | ||||
877 | DEFINE_MDNODE_GET(DIStringType, | ||||
878 | (unsigned Tag, MDString *Name, Metadata *StringLength, | ||||
879 | Metadata *StringLengthExp, uint64_t SizeInBits, | ||||
880 | uint32_t AlignInBits, unsigned Encoding), | ||||
881 | (Tag, Name, StringLength, StringLengthExp, SizeInBits, | ||||
882 | AlignInBits, Encoding)) | ||||
883 | DEFINE_MDNODE_GET(DIStringType, | ||||
884 | (unsigned Tag, StringRef Name, Metadata *StringLength, | ||||
885 | Metadata *StringLengthExp, uint64_t SizeInBits, | ||||
886 | uint32_t AlignInBits, unsigned Encoding), | ||||
887 | (Tag, Name, StringLength, StringLengthExp, SizeInBits, | ||||
888 | AlignInBits, Encoding)) | ||||
889 | |||||
890 | TempDIStringType clone() const { return cloneImpl(); } | ||||
891 | |||||
892 | static bool classof(const Metadata *MD) { | ||||
893 | return MD->getMetadataID() == DIStringTypeKind; | ||||
894 | } | ||||
895 | |||||
896 | DIVariable *getStringLength() const { | ||||
897 | return cast_or_null<DIVariable>(getRawStringLength()); | ||||
898 | } | ||||
899 | |||||
900 | DIExpression *getStringLengthExp() const { | ||||
901 | return cast_or_null<DIExpression>(getRawStringLengthExp()); | ||||
902 | } | ||||
903 | |||||
904 | unsigned getEncoding() const { return Encoding; } | ||||
905 | |||||
906 | Metadata *getRawStringLength() const { return getOperand(3); } | ||||
907 | |||||
908 | Metadata *getRawStringLengthExp() const { return getOperand(4); } | ||||
909 | }; | ||||
910 | |||||
911 | /// Derived types. | ||||
912 | /// | ||||
913 | /// This includes qualified types, pointers, references, friends, typedefs, and | ||||
914 | /// class members. | ||||
915 | /// | ||||
916 | /// TODO: Split out members (inheritance, fields, methods, etc.). | ||||
917 | class DIDerivedType : public DIType { | ||||
918 | friend class LLVMContextImpl; | ||||
919 | friend class MDNode; | ||||
920 | |||||
921 | /// The DWARF address space of the memory pointed to or referenced by a | ||||
922 | /// pointer or reference type respectively. | ||||
923 | Optional<unsigned> DWARFAddressSpace; | ||||
924 | |||||
925 | DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
926 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
927 | uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace, | ||||
928 | DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||
929 | : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, | ||||
930 | AlignInBits, OffsetInBits, Flags, Ops), | ||||
931 | DWARFAddressSpace(DWARFAddressSpace) {} | ||||
932 | ~DIDerivedType() = default; | ||||
933 | |||||
934 | static DIDerivedType * | ||||
935 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, | ||||
936 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
937 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
938 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
939 | Metadata *ExtraData, DINodeArray Annotations, StorageType Storage, | ||||
940 | bool ShouldCreate = true) { | ||||
941 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, | ||||
942 | Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, | ||||
943 | DWARFAddressSpace, Flags, ExtraData, Annotations.get(), | ||||
944 | Storage, ShouldCreate); | ||||
945 | } | ||||
946 | static DIDerivedType * | ||||
947 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||
948 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||
949 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
950 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
951 | Metadata *ExtraData, Metadata *Annotations, StorageType Storage, | ||||
952 | bool ShouldCreate = true); | ||||
953 | |||||
954 | TempDIDerivedType cloneImpl() const { | ||||
955 | return getTemporary( | ||||
956 | getContext(), getTag(), getName(), getFile(), getLine(), getScope(), | ||||
957 | getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), | ||||
958 | getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations()); | ||||
959 | } | ||||
960 | |||||
961 | public: | ||||
962 | DEFINE_MDNODE_GET(DIDerivedType, | ||||
963 | (unsigned Tag, MDString *Name, Metadata *File, | ||||
964 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||
965 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
966 | uint64_t OffsetInBits, | ||||
967 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
968 | Metadata *ExtraData = nullptr, | ||||
969 | Metadata *Annotations = nullptr), | ||||
970 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||
971 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||
972 | ExtraData, Annotations)) | ||||
973 | DEFINE_MDNODE_GET(DIDerivedType, | ||||
974 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||
975 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
976 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
977 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
978 | Metadata *ExtraData = nullptr, | ||||
979 | DINodeArray Annotations = nullptr), | ||||
980 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||
981 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||
982 | ExtraData, Annotations)) | ||||
983 | |||||
984 | TempDIDerivedType clone() const { return cloneImpl(); } | ||||
985 | |||||
986 | /// Get the base type this is derived from. | ||||
987 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||
988 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||
989 | |||||
990 | /// \returns The DWARF address space of the memory pointed to or referenced by | ||||
991 | /// a pointer or reference type respectively. | ||||
992 | Optional<unsigned> getDWARFAddressSpace() const { return DWARFAddressSpace; } | ||||
993 | |||||
994 | /// Get extra data associated with this derived type. | ||||
995 | /// | ||||
996 | /// Class type for pointer-to-members, objective-c property node for ivars, | ||||
997 | /// global constant wrapper for static members, or virtual base pointer offset | ||||
998 | /// for inheritance. | ||||
999 | /// | ||||
1000 | /// TODO: Separate out types that need this extra operand: pointer-to-member | ||||
1001 | /// types and member fields (static members and ivars). | ||||
1002 | Metadata *getExtraData() const { return getRawExtraData(); } | ||||
1003 | Metadata *getRawExtraData() const { return getOperand(4); } | ||||
1004 | |||||
1005 | /// Get annotations associated with this derived type. | ||||
1006 | DINodeArray getAnnotations() const { | ||||
1007 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||
1008 | } | ||||
1009 | Metadata *getRawAnnotations() const { return getOperand(5); } | ||||
1010 | |||||
1011 | /// Get casted version of extra data. | ||||
1012 | /// @{ | ||||
1013 | DIType *getClassType() const { | ||||
1014 | assert(getTag() == dwarf::DW_TAG_ptr_to_member_type)(static_cast <bool> (getTag() == dwarf::DW_TAG_ptr_to_member_type ) ? void (0) : __assert_fail ("getTag() == dwarf::DW_TAG_ptr_to_member_type" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1014, __extension__ __PRETTY_FUNCTION__)); | ||||
1015 | return cast_or_null<DIType>(getExtraData()); | ||||
1016 | } | ||||
1017 | |||||
1018 | DIObjCProperty *getObjCProperty() const { | ||||
1019 | return dyn_cast_or_null<DIObjCProperty>(getExtraData()); | ||||
1020 | } | ||||
1021 | |||||
1022 | uint32_t getVBPtrOffset() const { | ||||
1023 | assert(getTag() == dwarf::DW_TAG_inheritance)(static_cast <bool> (getTag() == dwarf::DW_TAG_inheritance ) ? void (0) : __assert_fail ("getTag() == dwarf::DW_TAG_inheritance" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1023, __extension__ __PRETTY_FUNCTION__)); | ||||
1024 | if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1025 | if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue())) | ||||
1026 | return static_cast<uint32_t>(CI->getZExtValue()); | ||||
1027 | return 0; | ||||
1028 | } | ||||
1029 | |||||
1030 | Constant *getStorageOffsetInBits() const { | ||||
1031 | assert(getTag() == dwarf::DW_TAG_member && isBitField())(static_cast <bool> (getTag() == dwarf::DW_TAG_member && isBitField()) ? void (0) : __assert_fail ("getTag() == dwarf::DW_TAG_member && isBitField()" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1031, __extension__ __PRETTY_FUNCTION__)); | ||||
1032 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1033 | return C->getValue(); | ||||
1034 | return nullptr; | ||||
1035 | } | ||||
1036 | |||||
1037 | Constant *getConstant() const { | ||||
1038 | assert(getTag() == dwarf::DW_TAG_member && isStaticMember())(static_cast <bool> (getTag() == dwarf::DW_TAG_member && isStaticMember()) ? void (0) : __assert_fail ("getTag() == dwarf::DW_TAG_member && isStaticMember()" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1038, __extension__ __PRETTY_FUNCTION__)); | ||||
1039 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1040 | return C->getValue(); | ||||
1041 | return nullptr; | ||||
1042 | } | ||||
1043 | Constant *getDiscriminantValue() const { | ||||
1044 | assert(getTag() == dwarf::DW_TAG_member && !isStaticMember())(static_cast <bool> (getTag() == dwarf::DW_TAG_member && !isStaticMember()) ? void (0) : __assert_fail ("getTag() == dwarf::DW_TAG_member && !isStaticMember()" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1044, __extension__ __PRETTY_FUNCTION__)); | ||||
1045 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1046 | return C->getValue(); | ||||
1047 | return nullptr; | ||||
1048 | } | ||||
1049 | /// @} | ||||
1050 | |||||
1051 | static bool classof(const Metadata *MD) { | ||||
1052 | return MD->getMetadataID() == DIDerivedTypeKind; | ||||
1053 | } | ||||
1054 | }; | ||||
1055 | |||||
1056 | /// Composite types. | ||||
1057 | /// | ||||
1058 | /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). | ||||
1059 | /// TODO: Create a custom, unrelated node for DW_TAG_array_type. | ||||
1060 | class DICompositeType : public DIType { | ||||
1061 | friend class LLVMContextImpl; | ||||
1062 | friend class MDNode; | ||||
1063 | |||||
1064 | unsigned RuntimeLang; | ||||
1065 | |||||
1066 | DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
1067 | unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, | ||||
1068 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1069 | ArrayRef<Metadata *> Ops) | ||||
1070 | : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, | ||||
1071 | AlignInBits, OffsetInBits, Flags, Ops), | ||||
1072 | RuntimeLang(RuntimeLang) {} | ||||
1073 | ~DICompositeType() = default; | ||||
1074 | |||||
1075 | /// Change fields in place. | ||||
1076 | void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, | ||||
1077 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
1078 | uint64_t OffsetInBits, DIFlags Flags) { | ||||
1079 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1079, __extension__ __PRETTY_FUNCTION__)); | ||||
1080 | assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate")(static_cast <bool> (getRawIdentifier() && "Only ODR-uniqued nodes should mutate" ) ? void (0) : __assert_fail ("getRawIdentifier() && \"Only ODR-uniqued nodes should mutate\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1080, __extension__ __PRETTY_FUNCTION__)); | ||||
1081 | this->RuntimeLang = RuntimeLang; | ||||
1082 | DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||
1083 | } | ||||
1084 | |||||
1085 | static DICompositeType * | ||||
1086 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, | ||||
1087 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
1088 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1089 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||
1090 | DITemplateParameterArray TemplateParams, StringRef Identifier, | ||||
1091 | DIDerivedType *Discriminator, Metadata *DataLocation, | ||||
1092 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||
1093 | DINodeArray Annotations, StorageType Storage, | ||||
1094 | bool ShouldCreate = true) { | ||||
1095 | return getImpl( | ||||
1096 | Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, | ||||
1097 | BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), | ||||
1098 | RuntimeLang, VTableHolder, TemplateParams.get(), | ||||
1099 | getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, | ||||
1100 | Associated, Allocated, Rank, Annotations.get(), Storage, ShouldCreate); | ||||
1101 | } | ||||
1102 | static DICompositeType * | ||||
1103 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||
1104 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||
1105 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
1106 | DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, | ||||
1107 | Metadata *VTableHolder, Metadata *TemplateParams, | ||||
1108 | MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, | ||||
1109 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||
1110 | Metadata *Annotations, StorageType Storage, bool ShouldCreate = true); | ||||
1111 | |||||
1112 | TempDICompositeType cloneImpl() const { | ||||
1113 | return getTemporary( | ||||
1114 | getContext(), getTag(), getName(), getFile(), getLine(), getScope(), | ||||
1115 | getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), | ||||
1116 | getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), | ||||
1117 | getTemplateParams(), getIdentifier(), getDiscriminator(), | ||||
1118 | getRawDataLocation(), getRawAssociated(), getRawAllocated(), | ||||
1119 | getRawRank(), getAnnotations()); | ||||
1120 | } | ||||
1121 | |||||
1122 | public: | ||||
1123 | DEFINE_MDNODE_GET( | ||||
1124 | DICompositeType, | ||||
1125 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||
1126 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
1127 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1128 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||
1129 | DITemplateParameterArray TemplateParams = nullptr, | ||||
1130 | StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, | ||||
1131 | Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, | ||||
1132 | Metadata *Allocated = nullptr, Metadata *Rank = nullptr, | ||||
1133 | DINodeArray Annotations = nullptr), | ||||
1134 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||
1135 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||
1136 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, | ||||
1137 | Annotations)) | ||||
1138 | DEFINE_MDNODE_GET( | ||||
1139 | DICompositeType, | ||||
1140 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, | ||||
1141 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, | ||||
1142 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1143 | Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, | ||||
1144 | Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, | ||||
1145 | Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, | ||||
1146 | Metadata *Associated = nullptr, Metadata *Allocated = nullptr, | ||||
1147 | Metadata *Rank = nullptr, Metadata *Annotations = nullptr), | ||||
1148 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||
1149 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||
1150 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, | ||||
1151 | Annotations)) | ||||
1152 | |||||
1153 | TempDICompositeType clone() const { return cloneImpl(); } | ||||
1154 | |||||
1155 | /// Get a DICompositeType with the given ODR identifier. | ||||
1156 | /// | ||||
1157 | /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped | ||||
1158 | /// DICompositeType for the given ODR \c Identifier. If none exists, creates | ||||
1159 | /// a new node. | ||||
1160 | /// | ||||
1161 | /// Else, returns \c nullptr. | ||||
1162 | static DICompositeType * | ||||
1163 | getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||
1164 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||
1165 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
1166 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||
1167 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||
1168 | Metadata *TemplateParams, Metadata *Discriminator, | ||||
1169 | Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, | ||||
1170 | Metadata *Rank, Metadata *Annotations); | ||||
1171 | static DICompositeType *getODRTypeIfExists(LLVMContext &Context, | ||||
1172 | MDString &Identifier); | ||||
1173 | |||||
1174 | /// Build a DICompositeType with the given ODR identifier. | ||||
1175 | /// | ||||
1176 | /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If | ||||
1177 | /// it doesn't exist, creates a new one. If it does exist and \a | ||||
1178 | /// isForwardDecl(), and the new arguments would be a definition, mutates the | ||||
1179 | /// the type in place. In either case, returns the type. | ||||
1180 | /// | ||||
1181 | /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns | ||||
1182 | /// nullptr. | ||||
1183 | static DICompositeType * | ||||
1184 | buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||
1185 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||
1186 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
1187 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||
1188 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||
1189 | Metadata *TemplateParams, Metadata *Discriminator, | ||||
1190 | Metadata *DataLocation, Metadata *Associated, | ||||
1191 | Metadata *Allocated, Metadata *Rank, Metadata *Annotations); | ||||
1192 | |||||
1193 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||
1194 | DINodeArray getElements() const { | ||||
1195 | return cast_or_null<MDTuple>(getRawElements()); | ||||
1196 | } | ||||
1197 | DIType *getVTableHolder() const { | ||||
1198 | return cast_or_null<DIType>(getRawVTableHolder()); | ||||
1199 | } | ||||
1200 | DITemplateParameterArray getTemplateParams() const { | ||||
1201 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||
1202 | } | ||||
1203 | StringRef getIdentifier() const { return getStringOperand(7); } | ||||
1204 | unsigned getRuntimeLang() const { return RuntimeLang; } | ||||
1205 | |||||
1206 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||
1207 | Metadata *getRawElements() const { return getOperand(4); } | ||||
1208 | Metadata *getRawVTableHolder() const { return getOperand(5); } | ||||
1209 | Metadata *getRawTemplateParams() const { return getOperand(6); } | ||||
1210 | MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } | ||||
1211 | Metadata *getRawDiscriminator() const { return getOperand(8); } | ||||
1212 | DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); } | ||||
1213 | Metadata *getRawDataLocation() const { return getOperand(9); } | ||||
1214 | DIVariable *getDataLocation() const { | ||||
1215 | return dyn_cast_or_null<DIVariable>(getRawDataLocation()); | ||||
1216 | } | ||||
1217 | DIExpression *getDataLocationExp() const { | ||||
1218 | return dyn_cast_or_null<DIExpression>(getRawDataLocation()); | ||||
1219 | } | ||||
1220 | Metadata *getRawAssociated() const { return getOperand(10); } | ||||
1221 | DIVariable *getAssociated() const { | ||||
1222 | return dyn_cast_or_null<DIVariable>(getRawAssociated()); | ||||
1223 | } | ||||
1224 | DIExpression *getAssociatedExp() const { | ||||
1225 | return dyn_cast_or_null<DIExpression>(getRawAssociated()); | ||||
1226 | } | ||||
1227 | Metadata *getRawAllocated() const { return getOperand(11); } | ||||
1228 | DIVariable *getAllocated() const { | ||||
1229 | return dyn_cast_or_null<DIVariable>(getRawAllocated()); | ||||
1230 | } | ||||
1231 | DIExpression *getAllocatedExp() const { | ||||
1232 | return dyn_cast_or_null<DIExpression>(getRawAllocated()); | ||||
1233 | } | ||||
1234 | Metadata *getRawRank() const { return getOperand(12); } | ||||
1235 | ConstantInt *getRankConst() const { | ||||
1236 | if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawRank())) | ||||
1237 | return dyn_cast_or_null<ConstantInt>(MD->getValue()); | ||||
1238 | return nullptr; | ||||
1239 | } | ||||
1240 | DIExpression *getRankExp() const { | ||||
1241 | return dyn_cast_or_null<DIExpression>(getRawRank()); | ||||
1242 | } | ||||
1243 | |||||
1244 | Metadata *getRawAnnotations() const { return getOperand(13); } | ||||
1245 | DINodeArray getAnnotations() const { | ||||
1246 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||
1247 | } | ||||
1248 | |||||
1249 | /// Replace operands. | ||||
1250 | /// | ||||
1251 | /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision | ||||
1252 | /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track | ||||
1253 | /// of its movement if necessary. | ||||
1254 | /// @{ | ||||
1255 | void replaceElements(DINodeArray Elements) { | ||||
1256 | #ifndef NDEBUG | ||||
1257 | for (DINode *Op : getElements()) | ||||
1258 | assert(is_contained(Elements->operands(), Op) &&(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a member during member list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a member during member list replacement\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1259, __extension__ __PRETTY_FUNCTION__)) | ||||
1259 | "Lost a member during member list replacement")(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a member during member list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a member during member list replacement\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1259, __extension__ __PRETTY_FUNCTION__)); | ||||
1260 | #endif | ||||
1261 | replaceOperandWith(4, Elements.get()); | ||||
1262 | } | ||||
1263 | |||||
1264 | void replaceVTableHolder(DIType *VTableHolder) { | ||||
1265 | replaceOperandWith(5, VTableHolder); | ||||
1266 | } | ||||
1267 | |||||
1268 | void replaceTemplateParams(DITemplateParameterArray TemplateParams) { | ||||
1269 | replaceOperandWith(6, TemplateParams.get()); | ||||
1270 | } | ||||
1271 | /// @} | ||||
1272 | |||||
1273 | static bool classof(const Metadata *MD) { | ||||
1274 | return MD->getMetadataID() == DICompositeTypeKind; | ||||
1275 | } | ||||
1276 | }; | ||||
1277 | |||||
1278 | /// Type array for a subprogram. | ||||
1279 | /// | ||||
1280 | /// TODO: Fold the array of types in directly as operands. | ||||
1281 | class DISubroutineType : public DIType { | ||||
1282 | friend class LLVMContextImpl; | ||||
1283 | friend class MDNode; | ||||
1284 | |||||
1285 | /// The calling convention used with DW_AT_calling_convention. Actually of | ||||
1286 | /// type dwarf::CallingConvention. | ||||
1287 | uint8_t CC; | ||||
1288 | |||||
1289 | DISubroutineType(LLVMContext &C, StorageType Storage, DIFlags Flags, | ||||
1290 | uint8_t CC, ArrayRef<Metadata *> Ops) | ||||
1291 | : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, | ||||
1292 | 0, 0, 0, 0, Flags, Ops), | ||||
1293 | CC(CC) {} | ||||
1294 | ~DISubroutineType() = default; | ||||
1295 | |||||
1296 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||
1297 | uint8_t CC, DITypeRefArray TypeArray, | ||||
1298 | StorageType Storage, | ||||
1299 | bool ShouldCreate = true) { | ||||
1300 | return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); | ||||
1301 | } | ||||
1302 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||
1303 | uint8_t CC, Metadata *TypeArray, | ||||
1304 | StorageType Storage, | ||||
1305 | bool ShouldCreate = true); | ||||
1306 | |||||
1307 | TempDISubroutineType cloneImpl() const { | ||||
1308 | return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); | ||||
1309 | } | ||||
1310 | |||||
1311 | public: | ||||
1312 | DEFINE_MDNODE_GET(DISubroutineType, | ||||
1313 | (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), | ||||
1314 | (Flags, CC, TypeArray)) | ||||
1315 | DEFINE_MDNODE_GET(DISubroutineType, | ||||
1316 | (DIFlags Flags, uint8_t CC, Metadata *TypeArray), | ||||
1317 | (Flags, CC, TypeArray)) | ||||
1318 | |||||
1319 | TempDISubroutineType clone() const { return cloneImpl(); } | ||||
1320 | |||||
1321 | uint8_t getCC() const { return CC; } | ||||
1322 | |||||
1323 | DITypeRefArray getTypeArray() const { | ||||
1324 | return cast_or_null<MDTuple>(getRawTypeArray()); | ||||
1325 | } | ||||
1326 | |||||
1327 | Metadata *getRawTypeArray() const { return getOperand(3); } | ||||
1328 | |||||
1329 | static bool classof(const Metadata *MD) { | ||||
1330 | return MD->getMetadataID() == DISubroutineTypeKind; | ||||
1331 | } | ||||
1332 | }; | ||||
1333 | |||||
1334 | /// Compile unit. | ||||
1335 | class DICompileUnit : public DIScope { | ||||
1336 | friend class LLVMContextImpl; | ||||
1337 | friend class MDNode; | ||||
1338 | |||||
1339 | public: | ||||
1340 | enum DebugEmissionKind : unsigned { | ||||
1341 | NoDebug = 0, | ||||
1342 | FullDebug, | ||||
1343 | LineTablesOnly, | ||||
1344 | DebugDirectivesOnly, | ||||
1345 | LastEmissionKind = DebugDirectivesOnly | ||||
1346 | }; | ||||
1347 | |||||
1348 | enum class DebugNameTableKind : unsigned { | ||||
1349 | Default = 0, | ||||
1350 | GNU = 1, | ||||
1351 | None = 2, | ||||
1352 | LastDebugNameTableKind = None | ||||
1353 | }; | ||||
1354 | |||||
1355 | static Optional<DebugEmissionKind> getEmissionKind(StringRef Str); | ||||
1356 | static const char *emissionKindString(DebugEmissionKind EK); | ||||
1357 | static Optional<DebugNameTableKind> getNameTableKind(StringRef Str); | ||||
1358 | static const char *nameTableKindString(DebugNameTableKind PK); | ||||
1359 | |||||
1360 | private: | ||||
1361 | unsigned SourceLanguage; | ||||
1362 | bool IsOptimized; | ||||
1363 | unsigned RuntimeVersion; | ||||
1364 | unsigned EmissionKind; | ||||
1365 | uint64_t DWOId; | ||||
1366 | bool SplitDebugInlining; | ||||
1367 | bool DebugInfoForProfiling; | ||||
1368 | unsigned NameTableKind; | ||||
1369 | bool RangesBaseAddress; | ||||
1370 | |||||
1371 | DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, | ||||
1372 | bool IsOptimized, unsigned RuntimeVersion, | ||||
1373 | unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, | ||||
1374 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||
1375 | bool RangesBaseAddress, ArrayRef<Metadata *> Ops) | ||||
1376 | : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), | ||||
1377 | SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), | ||||
1378 | RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), | ||||
1379 | DWOId(DWOId), SplitDebugInlining(SplitDebugInlining), | ||||
1380 | DebugInfoForProfiling(DebugInfoForProfiling), | ||||
1381 | NameTableKind(NameTableKind), RangesBaseAddress(RangesBaseAddress) { | ||||
1382 | assert(Storage != Uniqued)(static_cast <bool> (Storage != Uniqued) ? void (0) : __assert_fail ("Storage != Uniqued", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1382, __extension__ __PRETTY_FUNCTION__)); | ||||
1383 | } | ||||
1384 | ~DICompileUnit() = default; | ||||
1385 | |||||
1386 | static DICompileUnit * | ||||
1387 | getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, | ||||
1388 | StringRef Producer, bool IsOptimized, StringRef Flags, | ||||
1389 | unsigned RuntimeVersion, StringRef SplitDebugFilename, | ||||
1390 | unsigned EmissionKind, DICompositeTypeArray EnumTypes, | ||||
1391 | DIScopeArray RetainedTypes, | ||||
1392 | DIGlobalVariableExpressionArray GlobalVariables, | ||||
1393 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, | ||||
1394 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, | ||||
1395 | unsigned NameTableKind, bool RangesBaseAddress, StringRef SysRoot, | ||||
1396 | StringRef SDK, StorageType Storage, bool ShouldCreate = true) { | ||||
1397 | return getImpl( | ||||
1398 | Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), | ||||
1399 | IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, | ||||
1400 | getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, | ||||
1401 | EnumTypes.get(), RetainedTypes.get(), GlobalVariables.get(), | ||||
1402 | ImportedEntities.get(), Macros.get(), DWOId, SplitDebugInlining, | ||||
1403 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, | ||||
1404 | getCanonicalMDString(Context, SysRoot), | ||||
1405 | getCanonicalMDString(Context, SDK), Storage, ShouldCreate); | ||||
1406 | } | ||||
1407 | static DICompileUnit * | ||||
1408 | getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, | ||||
1409 | MDString *Producer, bool IsOptimized, MDString *Flags, | ||||
1410 | unsigned RuntimeVersion, MDString *SplitDebugFilename, | ||||
1411 | unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, | ||||
1412 | Metadata *GlobalVariables, Metadata *ImportedEntities, | ||||
1413 | Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, | ||||
1414 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||
1415 | bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, | ||||
1416 | StorageType Storage, bool ShouldCreate = true); | ||||
1417 | |||||
1418 | TempDICompileUnit cloneImpl() const { | ||||
1419 | return getTemporary( | ||||
1420 | getContext(), getSourceLanguage(), getFile(), getProducer(), | ||||
1421 | isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), | ||||
1422 | getEmissionKind(), getEnumTypes(), getRetainedTypes(), | ||||
1423 | getGlobalVariables(), getImportedEntities(), getMacros(), DWOId, | ||||
1424 | getSplitDebugInlining(), getDebugInfoForProfiling(), getNameTableKind(), | ||||
1425 | getRangesBaseAddress(), getSysRoot(), getSDK()); | ||||
1426 | } | ||||
1427 | |||||
1428 | public: | ||||
1429 | static void get() = delete; | ||||
1430 | static void getIfExists() = delete; | ||||
1431 | |||||
1432 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1433 | DICompileUnit,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1434 | (unsigned SourceLanguage, DIFile *File, StringRef Producer,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1435 | bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1436 | StringRef SplitDebugFilename, DebugEmissionKind EmissionKind,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1437 | DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1438 | DIGlobalVariableExpressionArray GlobalVariables,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1439 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1440 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1441 | DebugNameTableKind NameTableKind, bool RangesBaseAddress,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1442 | StringRef SysRoot, StringRef SDK),static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1443 | (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1444 | SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1445 | GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1446 | DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1447 | SysRoot, SDK))static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
1448 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1449 | DICompileUnit,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1450 | (unsigned SourceLanguage, Metadata *File, MDString *Producer,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1451 | bool IsOptimized, MDString *Flags, unsigned RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1452 | MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1453 | Metadata *RetainedTypes, Metadata *GlobalVariables,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1454 | Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1455 | bool SplitDebugInlining, bool DebugInfoForProfiling,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1456 | unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1457 | MDString *SDK),static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1458 | (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1459 | SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1460 | GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1461 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot, SDK))static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
1462 | |||||
1463 | TempDICompileUnit clone() const { return cloneImpl(); } | ||||
1464 | |||||
1465 | unsigned getSourceLanguage() const { return SourceLanguage; } | ||||
1466 | bool isOptimized() const { return IsOptimized; } | ||||
1467 | unsigned getRuntimeVersion() const { return RuntimeVersion; } | ||||
1468 | DebugEmissionKind getEmissionKind() const { | ||||
1469 | return (DebugEmissionKind)EmissionKind; | ||||
1470 | } | ||||
1471 | bool isDebugDirectivesOnly() const { | ||||
1472 | return EmissionKind == DebugDirectivesOnly; | ||||
1473 | } | ||||
1474 | bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; } | ||||
1475 | DebugNameTableKind getNameTableKind() const { | ||||
1476 | return (DebugNameTableKind)NameTableKind; | ||||
1477 | } | ||||
1478 | bool getRangesBaseAddress() const { return RangesBaseAddress; } | ||||
1479 | StringRef getProducer() const { return getStringOperand(1); } | ||||
1480 | StringRef getFlags() const { return getStringOperand(2); } | ||||
1481 | StringRef getSplitDebugFilename() const { return getStringOperand(3); } | ||||
1482 | DICompositeTypeArray getEnumTypes() const { | ||||
1483 | return cast_or_null<MDTuple>(getRawEnumTypes()); | ||||
1484 | } | ||||
1485 | DIScopeArray getRetainedTypes() const { | ||||
1486 | return cast_or_null<MDTuple>(getRawRetainedTypes()); | ||||
1487 | } | ||||
1488 | DIGlobalVariableExpressionArray getGlobalVariables() const { | ||||
1489 | return cast_or_null<MDTuple>(getRawGlobalVariables()); | ||||
1490 | } | ||||
1491 | DIImportedEntityArray getImportedEntities() const { | ||||
1492 | return cast_or_null<MDTuple>(getRawImportedEntities()); | ||||
1493 | } | ||||
1494 | DIMacroNodeArray getMacros() const { | ||||
1495 | return cast_or_null<MDTuple>(getRawMacros()); | ||||
1496 | } | ||||
1497 | uint64_t getDWOId() const { return DWOId; } | ||||
1498 | void setDWOId(uint64_t DwoId) { DWOId = DwoId; } | ||||
1499 | bool getSplitDebugInlining() const { return SplitDebugInlining; } | ||||
1500 | void setSplitDebugInlining(bool SplitDebugInlining) { | ||||
1501 | this->SplitDebugInlining = SplitDebugInlining; | ||||
1502 | } | ||||
1503 | StringRef getSysRoot() const { return getStringOperand(9); } | ||||
1504 | StringRef getSDK() const { return getStringOperand(10); } | ||||
1505 | |||||
1506 | MDString *getRawProducer() const { return getOperandAs<MDString>(1); } | ||||
1507 | MDString *getRawFlags() const { return getOperandAs<MDString>(2); } | ||||
1508 | MDString *getRawSplitDebugFilename() const { | ||||
1509 | return getOperandAs<MDString>(3); | ||||
1510 | } | ||||
1511 | Metadata *getRawEnumTypes() const { return getOperand(4); } | ||||
1512 | Metadata *getRawRetainedTypes() const { return getOperand(5); } | ||||
1513 | Metadata *getRawGlobalVariables() const { return getOperand(6); } | ||||
1514 | Metadata *getRawImportedEntities() const { return getOperand(7); } | ||||
1515 | Metadata *getRawMacros() const { return getOperand(8); } | ||||
1516 | MDString *getRawSysRoot() const { return getOperandAs<MDString>(9); } | ||||
1517 | MDString *getRawSDK() const { return getOperandAs<MDString>(10); } | ||||
1518 | |||||
1519 | /// Replace arrays. | ||||
1520 | /// | ||||
1521 | /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and | ||||
1522 | /// deleted on a uniquing collision. In practice, uniquing collisions on \a | ||||
1523 | /// DICompileUnit should be fairly rare. | ||||
1524 | /// @{ | ||||
1525 | void replaceEnumTypes(DICompositeTypeArray N) { | ||||
1526 | replaceOperandWith(4, N.get()); | ||||
1527 | } | ||||
1528 | void replaceRetainedTypes(DITypeArray N) { | ||||
1529 | replaceOperandWith(5, N.get()); | ||||
1530 | } | ||||
1531 | void replaceGlobalVariables(DIGlobalVariableExpressionArray N) { | ||||
1532 | replaceOperandWith(6, N.get()); | ||||
1533 | } | ||||
1534 | void replaceImportedEntities(DIImportedEntityArray N) { | ||||
1535 | replaceOperandWith(7, N.get()); | ||||
1536 | } | ||||
1537 | void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); } | ||||
1538 | /// @} | ||||
1539 | |||||
1540 | static bool classof(const Metadata *MD) { | ||||
1541 | return MD->getMetadataID() == DICompileUnitKind; | ||||
1542 | } | ||||
1543 | }; | ||||
1544 | |||||
1545 | /// A scope for locals. | ||||
1546 | /// | ||||
1547 | /// A legal scope for lexical blocks, local variables, and debug info | ||||
1548 | /// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a | ||||
1549 | /// DILexicalBlockFile. | ||||
1550 | class DILocalScope : public DIScope { | ||||
1551 | protected: | ||||
1552 | DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
1553 | ArrayRef<Metadata *> Ops) | ||||
1554 | : DIScope(C, ID, Storage, Tag, Ops) {} | ||||
1555 | ~DILocalScope() = default; | ||||
1556 | |||||
1557 | public: | ||||
1558 | /// Get the subprogram for this scope. | ||||
1559 | /// | ||||
1560 | /// Return this if it's an \a DISubprogram; otherwise, look up the scope | ||||
1561 | /// chain. | ||||
1562 | DISubprogram *getSubprogram() const; | ||||
1563 | |||||
1564 | /// Get the first non DILexicalBlockFile scope of this scope. | ||||
1565 | /// | ||||
1566 | /// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the | ||||
1567 | /// scope chain. | ||||
1568 | DILocalScope *getNonLexicalBlockFileScope() const; | ||||
1569 | |||||
1570 | static bool classof(const Metadata *MD) { | ||||
1571 | return MD->getMetadataID() == DISubprogramKind || | ||||
1572 | MD->getMetadataID() == DILexicalBlockKind || | ||||
1573 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||
1574 | } | ||||
1575 | }; | ||||
1576 | |||||
1577 | /// Debug location. | ||||
1578 | /// | ||||
1579 | /// A debug location in source code, used for debug info and otherwise. | ||||
1580 | class DILocation : public MDNode { | ||||
1581 | friend class LLVMContextImpl; | ||||
1582 | friend class MDNode; | ||||
1583 | |||||
1584 | DILocation(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
1585 | unsigned Column, ArrayRef<Metadata *> MDs, bool ImplicitCode); | ||||
1586 | ~DILocation() { dropAllReferences(); } | ||||
1587 | |||||
1588 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||
1589 | unsigned Column, Metadata *Scope, | ||||
1590 | Metadata *InlinedAt, bool ImplicitCode, | ||||
1591 | StorageType Storage, bool ShouldCreate = true); | ||||
1592 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||
1593 | unsigned Column, DILocalScope *Scope, | ||||
1594 | DILocation *InlinedAt, bool ImplicitCode, | ||||
1595 | StorageType Storage, bool ShouldCreate = true) { | ||||
1596 | return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), | ||||
1597 | static_cast<Metadata *>(InlinedAt), ImplicitCode, Storage, | ||||
1598 | ShouldCreate); | ||||
1599 | } | ||||
1600 | |||||
1601 | TempDILocation cloneImpl() const { | ||||
1602 | // Get the raw scope/inlinedAt since it is possible to invoke this on | ||||
1603 | // a DILocation containing temporary metadata. | ||||
1604 | return getTemporary(getContext(), getLine(), getColumn(), getRawScope(), | ||||
1605 | getRawInlinedAt(), isImplicitCode()); | ||||
1606 | } | ||||
1607 | |||||
1608 | public: | ||||
1609 | // Disallow replacing operands. | ||||
1610 | void replaceOperandWith(unsigned I, Metadata *New) = delete; | ||||
1611 | |||||
1612 | DEFINE_MDNODE_GET(DILocation, | ||||
1613 | (unsigned Line, unsigned Column, Metadata *Scope, | ||||
1614 | Metadata *InlinedAt = nullptr, bool ImplicitCode = false), | ||||
1615 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||
1616 | DEFINE_MDNODE_GET(DILocation, | ||||
1617 | (unsigned Line, unsigned Column, DILocalScope *Scope, | ||||
1618 | DILocation *InlinedAt = nullptr, | ||||
1619 | bool ImplicitCode = false), | ||||
1620 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||
1621 | |||||
1622 | /// Return a (temporary) clone of this. | ||||
1623 | TempDILocation clone() const { return cloneImpl(); } | ||||
1624 | |||||
1625 | unsigned getLine() const { return SubclassData32; } | ||||
1626 | unsigned getColumn() const { return SubclassData16; } | ||||
1627 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||
1628 | |||||
1629 | DILocation *getInlinedAt() const { | ||||
1630 | return cast_or_null<DILocation>(getRawInlinedAt()); | ||||
1631 | } | ||||
1632 | |||||
1633 | /// Check if the location corresponds to an implicit code. | ||||
1634 | /// When the ImplicitCode flag is true, it means that the Instruction | ||||
1635 | /// with this DILocation has been added by the front-end but it hasn't been | ||||
1636 | /// written explicitly by the user (e.g. cleanup stuff in C++ put on a closing | ||||
1637 | /// bracket). It's useful for code coverage to not show a counter on "empty" | ||||
1638 | /// lines. | ||||
1639 | bool isImplicitCode() const { return SubclassData1; } | ||||
1640 | void setImplicitCode(bool ImplicitCode) { SubclassData1 = ImplicitCode; } | ||||
1641 | |||||
1642 | DIFile *getFile() const { return getScope()->getFile(); } | ||||
1643 | StringRef getFilename() const { return getScope()->getFilename(); } | ||||
1644 | StringRef getDirectory() const { return getScope()->getDirectory(); } | ||||
1645 | Optional<StringRef> getSource() const { return getScope()->getSource(); } | ||||
1646 | |||||
1647 | /// Get the scope where this is inlined. | ||||
1648 | /// | ||||
1649 | /// Walk through \a getInlinedAt() and return \a getScope() from the deepest | ||||
1650 | /// location. | ||||
1651 | DILocalScope *getInlinedAtScope() const { | ||||
1652 | if (auto *IA
| ||||
1653 | return IA->getInlinedAtScope(); | ||||
1654 | return getScope(); | ||||
1655 | } | ||||
1656 | |||||
1657 | /// Get the DWARF discriminator. | ||||
1658 | /// | ||||
1659 | /// DWARF discriminators distinguish identical file locations between | ||||
1660 | /// instructions that are on different basic blocks. | ||||
1661 | /// | ||||
1662 | /// There are 3 components stored in discriminator, from lower bits: | ||||
1663 | /// | ||||
1664 | /// Base discriminator: assigned by AddDiscriminators pass to identify IRs | ||||
1665 | /// that are defined by the same source line, but | ||||
1666 | /// different basic blocks. | ||||
1667 | /// Duplication factor: assigned by optimizations that will scale down | ||||
1668 | /// the execution frequency of the original IR. | ||||
1669 | /// Copy Identifier: assigned by optimizations that clones the IR. | ||||
1670 | /// Each copy of the IR will be assigned an identifier. | ||||
1671 | /// | ||||
1672 | /// Encoding: | ||||
1673 | /// | ||||
1674 | /// The above 3 components are encoded into a 32bit unsigned integer in | ||||
1675 | /// order. If the lowest bit is 1, the current component is empty, and the | ||||
1676 | /// next component will start in the next bit. Otherwise, the current | ||||
1677 | /// component is non-empty, and its content starts in the next bit. The | ||||
1678 | /// value of each components is either 5 bit or 12 bit: if the 7th bit | ||||
1679 | /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the | ||||
1680 | /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to | ||||
1681 | /// represent the component. Thus, the number of bits used for a component | ||||
1682 | /// is either 0 (if it and all the next components are empty); 1 - if it is | ||||
1683 | /// empty; 7 - if its value is up to and including 0x1f (lsb and msb are both | ||||
1684 | /// 0); or 14, if its value is up to and including 0x1ff. Note that the last | ||||
1685 | /// component is also capped at 0x1ff, even in the case when both first | ||||
1686 | /// components are 0, and we'd technically have 29 bits available. | ||||
1687 | /// | ||||
1688 | /// For precise control over the data being encoded in the discriminator, | ||||
1689 | /// use encodeDiscriminator/decodeDiscriminator. | ||||
1690 | |||||
1691 | inline unsigned getDiscriminator() const; | ||||
1692 | |||||
1693 | // For the regular discriminator, it stands for all empty components if all | ||||
1694 | // the lowest 3 bits are non-zero and all higher 29 bits are unused(zero by | ||||
1695 | // default). Here we fully leverage the higher 29 bits for pseudo probe use. | ||||
1696 | // This is the format: | ||||
1697 | // [2:0] - 0x7 | ||||
1698 | // [31:3] - pseudo probe fields guaranteed to be non-zero as a whole | ||||
1699 | // So if the lower 3 bits is non-zero and the others has at least one | ||||
1700 | // non-zero bit, it guarantees to be a pseudo probe discriminator | ||||
1701 | inline static bool isPseudoProbeDiscriminator(unsigned Discriminator) { | ||||
1702 | return ((Discriminator & 0x7) == 0x7) && (Discriminator & 0xFFFFFFF8); | ||||
1703 | } | ||||
1704 | |||||
1705 | /// Returns a new DILocation with updated \p Discriminator. | ||||
1706 | inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const; | ||||
1707 | |||||
1708 | /// Returns a new DILocation with updated base discriminator \p BD. Only the | ||||
1709 | /// base discriminator is set in the new DILocation, the other encoded values | ||||
1710 | /// are elided. | ||||
1711 | /// If the discriminator cannot be encoded, the function returns None. | ||||
1712 | inline Optional<const DILocation *> cloneWithBaseDiscriminator(unsigned BD) const; | ||||
1713 | |||||
1714 | /// Returns the duplication factor stored in the discriminator, or 1 if no | ||||
1715 | /// duplication factor (or 0) is encoded. | ||||
1716 | inline unsigned getDuplicationFactor() const; | ||||
1717 | |||||
1718 | /// Returns the copy identifier stored in the discriminator. | ||||
1719 | inline unsigned getCopyIdentifier() const; | ||||
1720 | |||||
1721 | /// Returns the base discriminator stored in the discriminator. | ||||
1722 | inline unsigned getBaseDiscriminator() const; | ||||
1723 | |||||
1724 | /// Returns a new DILocation with duplication factor \p DF * current | ||||
1725 | /// duplication factor encoded in the discriminator. The current duplication | ||||
1726 | /// factor is as defined by getDuplicationFactor(). | ||||
1727 | /// Returns None if encoding failed. | ||||
1728 | inline Optional<const DILocation *> cloneByMultiplyingDuplicationFactor(unsigned DF) const; | ||||
1729 | |||||
1730 | /// When two instructions are combined into a single instruction we also | ||||
1731 | /// need to combine the original locations into a single location. | ||||
1732 | /// | ||||
1733 | /// When the locations are the same we can use either location. When they | ||||
1734 | /// differ, we need a third location which is distinct from either. If they | ||||
1735 | /// have the same file/line but have a different discriminator we could | ||||
1736 | /// create a location with a new discriminator. If they are from different | ||||
1737 | /// files/lines the location is ambiguous and can't be represented in a line | ||||
1738 | /// entry. In this case, if \p GenerateLocation is true, we will set the | ||||
1739 | /// merged debug location as line 0 of the nearest common scope where the two | ||||
1740 | /// locations are inlined from. | ||||
1741 | /// | ||||
1742 | /// \p GenerateLocation: Whether the merged location can be generated when | ||||
1743 | /// \p LocA and \p LocB differ. | ||||
1744 | static const DILocation *getMergedLocation(const DILocation *LocA, | ||||
1745 | const DILocation *LocB); | ||||
1746 | |||||
1747 | /// Try to combine the vector of locations passed as input in a single one. | ||||
1748 | /// This function applies getMergedLocation() repeatedly left-to-right. | ||||
1749 | /// | ||||
1750 | /// \p Locs: The locations to be merged. | ||||
1751 | static | ||||
1752 | const DILocation *getMergedLocations(ArrayRef<const DILocation *> Locs); | ||||
1753 | |||||
1754 | /// Return the masked discriminator value for an input discrimnator value D | ||||
1755 | /// (i.e. zero out the (B+1)-th and above bits for D (B is 0-base). | ||||
1756 | // Example: an input of (0x1FF, 7) returns 0xFF. | ||||
1757 | static unsigned getMaskedDiscriminator(unsigned D, unsigned B) { | ||||
1758 | return (D & getN1Bits(B)); | ||||
1759 | } | ||||
1760 | |||||
1761 | /// Return the bits used for base discriminators. | ||||
1762 | static unsigned getBaseDiscriminatorBits() { return getBaseFSBitEnd(); } | ||||
1763 | |||||
1764 | /// Returns the base discriminator for a given encoded discriminator \p D. | ||||
1765 | static unsigned | ||||
1766 | getBaseDiscriminatorFromDiscriminator(unsigned D, | ||||
1767 | bool IsFSDiscriminator = false) { | ||||
1768 | if (IsFSDiscriminator) | ||||
1769 | return getMaskedDiscriminator(D, getBaseDiscriminatorBits()); | ||||
1770 | return getUnsignedFromPrefixEncoding(D); | ||||
1771 | } | ||||
1772 | |||||
1773 | /// Raw encoding of the discriminator. APIs such as cloneWithDuplicationFactor | ||||
1774 | /// have certain special case behavior (e.g. treating empty duplication factor | ||||
1775 | /// as the value '1'). | ||||
1776 | /// This API, in conjunction with cloneWithDiscriminator, may be used to encode | ||||
1777 | /// the raw values provided. \p BD: base discriminator \p DF: duplication factor | ||||
1778 | /// \p CI: copy index | ||||
1779 | /// The return is None if the values cannot be encoded in 32 bits - for | ||||
1780 | /// example, values for BD or DF larger than 12 bits. Otherwise, the return | ||||
1781 | /// is the encoded value. | ||||
1782 | static Optional<unsigned> encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI); | ||||
1783 | |||||
1784 | /// Raw decoder for values in an encoded discriminator D. | ||||
1785 | static void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, | ||||
1786 | unsigned &CI); | ||||
1787 | |||||
1788 | /// Returns the duplication factor for a given encoded discriminator \p D, or | ||||
1789 | /// 1 if no value or 0 is encoded. | ||||
1790 | static unsigned getDuplicationFactorFromDiscriminator(unsigned D) { | ||||
1791 | if (EnableFSDiscriminator) | ||||
1792 | return 1; | ||||
1793 | D = getNextComponentInDiscriminator(D); | ||||
1794 | unsigned Ret = getUnsignedFromPrefixEncoding(D); | ||||
1795 | if (Ret == 0) | ||||
1796 | return 1; | ||||
1797 | return Ret; | ||||
1798 | } | ||||
1799 | |||||
1800 | /// Returns the copy identifier for a given encoded discriminator \p D. | ||||
1801 | static unsigned getCopyIdentifierFromDiscriminator(unsigned D) { | ||||
1802 | return getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator( | ||||
1803 | getNextComponentInDiscriminator(D))); | ||||
1804 | } | ||||
1805 | |||||
1806 | |||||
1807 | Metadata *getRawScope() const { return getOperand(0); } | ||||
1808 | Metadata *getRawInlinedAt() const { | ||||
1809 | if (getNumOperands() == 2) | ||||
1810 | return getOperand(1); | ||||
1811 | return nullptr; | ||||
1812 | } | ||||
1813 | |||||
1814 | static bool classof(const Metadata *MD) { | ||||
1815 | return MD->getMetadataID() == DILocationKind; | ||||
1816 | } | ||||
1817 | }; | ||||
1818 | |||||
1819 | /// Subprogram description. | ||||
1820 | class DISubprogram : public DILocalScope { | ||||
1821 | friend class LLVMContextImpl; | ||||
1822 | friend class MDNode; | ||||
1823 | |||||
1824 | unsigned Line; | ||||
1825 | unsigned ScopeLine; | ||||
1826 | unsigned VirtualIndex; | ||||
1827 | |||||
1828 | /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue | ||||
1829 | /// of method overrides from secondary bases by this amount. It may be | ||||
1830 | /// negative. | ||||
1831 | int ThisAdjustment; | ||||
1832 | |||||
1833 | public: | ||||
1834 | /// Debug info subprogram flags. | ||||
1835 | enum DISPFlags : uint32_t { | ||||
1836 | #define HANDLE_DISP_FLAG(ID, NAME) SPFlag##NAME = ID, | ||||
1837 | #define DISP_FLAG_LARGEST_NEEDED | ||||
1838 | #include "llvm/IR/DebugInfoFlags.def" | ||||
1839 | SPFlagNonvirtual = SPFlagZero, | ||||
1840 | SPFlagVirtuality = SPFlagVirtual | SPFlagPureVirtual, | ||||
1841 | LLVM_MARK_AS_BITMASK_ENUM(SPFlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = SPFlagLargest | ||||
1842 | }; | ||||
1843 | |||||
1844 | static DISPFlags getFlag(StringRef Flag); | ||||
1845 | static StringRef getFlagString(DISPFlags Flag); | ||||
1846 | |||||
1847 | /// Split up a flags bitfield for easier printing. | ||||
1848 | /// | ||||
1849 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||
1850 | /// any remaining (unrecognized) bits. | ||||
1851 | static DISPFlags splitFlags(DISPFlags Flags, | ||||
1852 | SmallVectorImpl<DISPFlags> &SplitFlags); | ||||
1853 | |||||
1854 | // Helper for converting old bitfields to new flags word. | ||||
1855 | static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, | ||||
1856 | bool IsOptimized, | ||||
1857 | unsigned Virtuality = SPFlagNonvirtual, | ||||
1858 | bool IsMainSubprogram = false) { | ||||
1859 | // We're assuming virtuality is the low-order field. | ||||
1860 | static_assert( | ||||
1861 | int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) && | ||||
1862 | int(SPFlagPureVirtual) == int(dwarf::DW_VIRTUALITY_pure_virtual), | ||||
1863 | "Virtuality constant mismatch"); | ||||
1864 | return static_cast<DISPFlags>( | ||||
1865 | (Virtuality & SPFlagVirtuality) | | ||||
1866 | (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) | | ||||
1867 | (IsDefinition ? SPFlagDefinition : SPFlagZero) | | ||||
1868 | (IsOptimized ? SPFlagOptimized : SPFlagZero) | | ||||
1869 | (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero)); | ||||
1870 | } | ||||
1871 | |||||
1872 | private: | ||||
1873 | DIFlags Flags; | ||||
1874 | DISPFlags SPFlags; | ||||
1875 | |||||
1876 | DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
1877 | unsigned ScopeLine, unsigned VirtualIndex, int ThisAdjustment, | ||||
1878 | DIFlags Flags, DISPFlags SPFlags, ArrayRef<Metadata *> Ops) | ||||
1879 | : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, | ||||
1880 | Ops), | ||||
1881 | Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex), | ||||
1882 | ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) { | ||||
1883 | static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range"); | ||||
1884 | } | ||||
1885 | ~DISubprogram() = default; | ||||
1886 | |||||
1887 | static DISubprogram * | ||||
1888 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||
1889 | StringRef LinkageName, DIFile *File, unsigned Line, | ||||
1890 | DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, | ||||
1891 | unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, | ||||
1892 | DISPFlags SPFlags, DICompileUnit *Unit, | ||||
1893 | DITemplateParameterArray TemplateParams, DISubprogram *Declaration, | ||||
1894 | DINodeArray RetainedNodes, DITypeArray ThrownTypes, | ||||
1895 | DINodeArray Annotations, StorageType Storage, | ||||
1896 | bool ShouldCreate = true) { | ||||
1897 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
1898 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||
1899 | ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, | ||||
1900 | Flags, SPFlags, Unit, TemplateParams.get(), Declaration, | ||||
1901 | RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), | ||||
1902 | Storage, ShouldCreate); | ||||
1903 | } | ||||
1904 | static DISubprogram *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
1905 | MDString *Name, MDString *LinkageName, | ||||
1906 | Metadata *File, unsigned Line, Metadata *Type, | ||||
1907 | unsigned ScopeLine, Metadata *ContainingType, | ||||
1908 | unsigned VirtualIndex, int ThisAdjustment, | ||||
1909 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||
1910 | Metadata *TemplateParams, Metadata *Declaration, | ||||
1911 | Metadata *RetainedNodes, Metadata *ThrownTypes, | ||||
1912 | Metadata *Annotations, StorageType Storage, | ||||
1913 | bool ShouldCreate = true); | ||||
1914 | |||||
1915 | TempDISubprogram cloneImpl() const { | ||||
1916 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||
1917 | getFile(), getLine(), getType(), getScopeLine(), | ||||
1918 | getContainingType(), getVirtualIndex(), | ||||
1919 | getThisAdjustment(), getFlags(), getSPFlags(), | ||||
1920 | getUnit(), getTemplateParams(), getDeclaration(), | ||||
1921 | getRetainedNodes(), getThrownTypes(), getAnnotations()); | ||||
1922 | } | ||||
1923 | |||||
1924 | public: | ||||
1925 | DEFINE_MDNODE_GET( | ||||
1926 | DISubprogram, | ||||
1927 | (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, | ||||
1928 | unsigned Line, DISubroutineType *Type, unsigned ScopeLine, | ||||
1929 | DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||
1930 | DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, | ||||
1931 | DITemplateParameterArray TemplateParams = nullptr, | ||||
1932 | DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, | ||||
1933 | DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr), | ||||
1934 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||
1935 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||
1936 | Declaration, RetainedNodes, ThrownTypes, Annotations)) | ||||
1937 | |||||
1938 | DEFINE_MDNODE_GET( | ||||
1939 | DISubprogram, | ||||
1940 | (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, | ||||
1941 | unsigned Line, Metadata *Type, unsigned ScopeLine, | ||||
1942 | Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||
1943 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||
1944 | Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, | ||||
1945 | Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr, | ||||
1946 | Metadata *Annotations = nullptr), | ||||
1947 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||
1948 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||
1949 | Declaration, RetainedNodes, ThrownTypes, Annotations)) | ||||
1950 | |||||
1951 | TempDISubprogram clone() const { return cloneImpl(); } | ||||
1952 | |||||
1953 | /// Returns a new temporary DISubprogram with updated Flags | ||||
1954 | TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { | ||||
1955 | auto NewSP = clone(); | ||||
1956 | NewSP->Flags = NewFlags; | ||||
1957 | return NewSP; | ||||
1958 | } | ||||
1959 | |||||
1960 | public: | ||||
1961 | unsigned getLine() const { return Line; } | ||||
1962 | unsigned getVirtuality() const { return getSPFlags() & SPFlagVirtuality; } | ||||
1963 | unsigned getVirtualIndex() const { return VirtualIndex; } | ||||
1964 | int getThisAdjustment() const { return ThisAdjustment; } | ||||
1965 | unsigned getScopeLine() const { return ScopeLine; } | ||||
1966 | void setScopeLine(unsigned L) { assert(isDistinct())(static_cast <bool> (isDistinct()) ? void (0) : __assert_fail ("isDistinct()", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 1966, __extension__ __PRETTY_FUNCTION__)); ScopeLine = L; } | ||||
1967 | DIFlags getFlags() const { return Flags; } | ||||
1968 | DISPFlags getSPFlags() const { return SPFlags; } | ||||
1969 | bool isLocalToUnit() const { return getSPFlags() & SPFlagLocalToUnit; } | ||||
1970 | bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } | ||||
1971 | bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } | ||||
1972 | bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } | ||||
1973 | |||||
1974 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
1975 | bool isPrivate() const { | ||||
1976 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||
1977 | } | ||||
1978 | bool isProtected() const { | ||||
1979 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||
1980 | } | ||||
1981 | bool isPublic() const { | ||||
1982 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||
1983 | } | ||||
1984 | bool isExplicit() const { return getFlags() & FlagExplicit; } | ||||
1985 | bool isPrototyped() const { return getFlags() & FlagPrototyped; } | ||||
1986 | bool areAllCallsDescribed() const { | ||||
1987 | return getFlags() & FlagAllCallsDescribed; | ||||
1988 | } | ||||
1989 | bool isPure() const { return getSPFlags() & SPFlagPure; } | ||||
1990 | bool isElemental() const { return getSPFlags() & SPFlagElemental; } | ||||
1991 | bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } | ||||
1992 | bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } | ||||
1993 | |||||
1994 | /// Check if this is deleted member function. | ||||
1995 | /// | ||||
1996 | /// Return true if this subprogram is a C++11 special | ||||
1997 | /// member function declared deleted. | ||||
1998 | bool isDeleted() const { return getSPFlags() & SPFlagDeleted; } | ||||
1999 | |||||
2000 | /// Check if this is reference-qualified. | ||||
2001 | /// | ||||
2002 | /// Return true if this subprogram is a C++11 reference-qualified non-static | ||||
2003 | /// member function (void foo() &). | ||||
2004 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||
2005 | |||||
2006 | /// Check if this is rvalue-reference-qualified. | ||||
2007 | /// | ||||
2008 | /// Return true if this subprogram is a C++11 rvalue-reference-qualified | ||||
2009 | /// non-static member function (void foo() &&). | ||||
2010 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||
2011 | |||||
2012 | /// Check if this is marked as noreturn. | ||||
2013 | /// | ||||
2014 | /// Return true if this subprogram is C++11 noreturn or C11 _Noreturn | ||||
2015 | bool isNoReturn() const { return getFlags() & FlagNoReturn; } | ||||
2016 | |||||
2017 | // Check if this routine is a compiler-generated thunk. | ||||
2018 | // | ||||
2019 | // Returns true if this subprogram is a thunk generated by the compiler. | ||||
2020 | bool isThunk() const { return getFlags() & FlagThunk; } | ||||
2021 | |||||
2022 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2023 | |||||
2024 | StringRef getName() const { return getStringOperand(2); } | ||||
2025 | StringRef getLinkageName() const { return getStringOperand(3); } | ||||
2026 | /// Only used by clients of CloneFunction, and only right after the cloning. | ||||
2027 | void replaceLinkageName(MDString *LN) { replaceOperandWith(3, LN); } | ||||
2028 | |||||
2029 | DISubroutineType *getType() const { | ||||
2030 | return cast_or_null<DISubroutineType>(getRawType()); | ||||
2031 | } | ||||
2032 | DIType *getContainingType() const { | ||||
2033 | return cast_or_null<DIType>(getRawContainingType()); | ||||
2034 | } | ||||
2035 | |||||
2036 | DICompileUnit *getUnit() const { | ||||
2037 | return cast_or_null<DICompileUnit>(getRawUnit()); | ||||
2038 | } | ||||
2039 | void replaceUnit(DICompileUnit *CU) { replaceOperandWith(5, CU); } | ||||
2040 | DITemplateParameterArray getTemplateParams() const { | ||||
2041 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||
2042 | } | ||||
2043 | DISubprogram *getDeclaration() const { | ||||
2044 | return cast_or_null<DISubprogram>(getRawDeclaration()); | ||||
2045 | } | ||||
2046 | DINodeArray getRetainedNodes() const { | ||||
2047 | return cast_or_null<MDTuple>(getRawRetainedNodes()); | ||||
2048 | } | ||||
2049 | DITypeArray getThrownTypes() const { | ||||
2050 | return cast_or_null<MDTuple>(getRawThrownTypes()); | ||||
2051 | } | ||||
2052 | DINodeArray getAnnotations() const { | ||||
2053 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||
2054 | } | ||||
2055 | |||||
2056 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2057 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
2058 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(3); } | ||||
2059 | Metadata *getRawType() const { return getOperand(4); } | ||||
2060 | Metadata *getRawUnit() const { return getOperand(5); } | ||||
2061 | Metadata *getRawDeclaration() const { return getOperand(6); } | ||||
2062 | Metadata *getRawRetainedNodes() const { return getOperand(7); } | ||||
2063 | Metadata *getRawContainingType() const { | ||||
2064 | return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr; | ||||
2065 | } | ||||
2066 | Metadata *getRawTemplateParams() const { | ||||
2067 | return getNumOperands() > 9 ? getOperandAs<Metadata>(9) : nullptr; | ||||
2068 | } | ||||
2069 | Metadata *getRawThrownTypes() const { | ||||
2070 | return getNumOperands() > 10 ? getOperandAs<Metadata>(10) : nullptr; | ||||
2071 | } | ||||
2072 | Metadata *getRawAnnotations() const { | ||||
2073 | return getNumOperands() > 11 ? getOperandAs<Metadata>(11) : nullptr; | ||||
2074 | } | ||||
2075 | |||||
2076 | void replaceRawLinkageName(MDString *LinkageName) { | ||||
2077 | replaceOperandWith(3, LinkageName); | ||||
2078 | } | ||||
2079 | |||||
2080 | /// Check if this subprogram describes the given function. | ||||
2081 | /// | ||||
2082 | /// FIXME: Should this be looking through bitcasts? | ||||
2083 | bool describes(const Function *F) const; | ||||
2084 | |||||
2085 | static bool classof(const Metadata *MD) { | ||||
2086 | return MD->getMetadataID() == DISubprogramKind; | ||||
2087 | } | ||||
2088 | }; | ||||
2089 | |||||
2090 | class DILexicalBlockBase : public DILocalScope { | ||||
2091 | protected: | ||||
2092 | DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, | ||||
2093 | ArrayRef<Metadata *> Ops) | ||||
2094 | : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} | ||||
2095 | ~DILexicalBlockBase() = default; | ||||
2096 | |||||
2097 | public: | ||||
2098 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||
2099 | |||||
2100 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2101 | |||||
2102 | static bool classof(const Metadata *MD) { | ||||
2103 | return MD->getMetadataID() == DILexicalBlockKind || | ||||
2104 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||
2105 | } | ||||
2106 | }; | ||||
2107 | |||||
2108 | class DILexicalBlock : public DILexicalBlockBase { | ||||
2109 | friend class LLVMContextImpl; | ||||
2110 | friend class MDNode; | ||||
2111 | |||||
2112 | unsigned Line; | ||||
2113 | uint16_t Column; | ||||
2114 | |||||
2115 | DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
2116 | unsigned Column, ArrayRef<Metadata *> Ops) | ||||
2117 | : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), | ||||
2118 | Column(Column) { | ||||
2119 | assert(Column < (1u << 16) && "Expected 16-bit column")(static_cast <bool> (Column < (1u << 16) && "Expected 16-bit column") ? void (0) : __assert_fail ("Column < (1u << 16) && \"Expected 16-bit column\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 2119, __extension__ __PRETTY_FUNCTION__)); | ||||
2120 | } | ||||
2121 | ~DILexicalBlock() = default; | ||||
2122 | |||||
2123 | static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||
2124 | DIFile *File, unsigned Line, unsigned Column, | ||||
2125 | StorageType Storage, | ||||
2126 | bool ShouldCreate = true) { | ||||
2127 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||
2128 | static_cast<Metadata *>(File), Line, Column, Storage, | ||||
2129 | ShouldCreate); | ||||
2130 | } | ||||
2131 | |||||
2132 | static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
2133 | Metadata *File, unsigned Line, unsigned Column, | ||||
2134 | StorageType Storage, bool ShouldCreate = true); | ||||
2135 | |||||
2136 | TempDILexicalBlock cloneImpl() const { | ||||
2137 | return getTemporary(getContext(), getScope(), getFile(), getLine(), | ||||
2138 | getColumn()); | ||||
2139 | } | ||||
2140 | |||||
2141 | public: | ||||
2142 | DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File, | ||||
2143 | unsigned Line, unsigned Column), | ||||
2144 | (Scope, File, Line, Column)) | ||||
2145 | DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File, | ||||
2146 | unsigned Line, unsigned Column), | ||||
2147 | (Scope, File, Line, Column)) | ||||
2148 | |||||
2149 | TempDILexicalBlock clone() const { return cloneImpl(); } | ||||
2150 | |||||
2151 | unsigned getLine() const { return Line; } | ||||
2152 | unsigned getColumn() const { return Column; } | ||||
2153 | |||||
2154 | static bool classof(const Metadata *MD) { | ||||
2155 | return MD->getMetadataID() == DILexicalBlockKind; | ||||
2156 | } | ||||
2157 | }; | ||||
2158 | |||||
2159 | class DILexicalBlockFile : public DILexicalBlockBase { | ||||
2160 | friend class LLVMContextImpl; | ||||
2161 | friend class MDNode; | ||||
2162 | |||||
2163 | unsigned Discriminator; | ||||
2164 | |||||
2165 | DILexicalBlockFile(LLVMContext &C, StorageType Storage, | ||||
2166 | unsigned Discriminator, ArrayRef<Metadata *> Ops) | ||||
2167 | : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), | ||||
2168 | Discriminator(Discriminator) {} | ||||
2169 | ~DILexicalBlockFile() = default; | ||||
2170 | |||||
2171 | static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||
2172 | DIFile *File, unsigned Discriminator, | ||||
2173 | StorageType Storage, | ||||
2174 | bool ShouldCreate = true) { | ||||
2175 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||
2176 | static_cast<Metadata *>(File), Discriminator, Storage, | ||||
2177 | ShouldCreate); | ||||
2178 | } | ||||
2179 | |||||
2180 | static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
2181 | Metadata *File, unsigned Discriminator, | ||||
2182 | StorageType Storage, | ||||
2183 | bool ShouldCreate = true); | ||||
2184 | |||||
2185 | TempDILexicalBlockFile cloneImpl() const { | ||||
2186 | return getTemporary(getContext(), getScope(), getFile(), | ||||
2187 | getDiscriminator()); | ||||
2188 | } | ||||
2189 | |||||
2190 | public: | ||||
2191 | DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File, | ||||
2192 | unsigned Discriminator), | ||||
2193 | (Scope, File, Discriminator)) | ||||
2194 | DEFINE_MDNODE_GET(DILexicalBlockFile, | ||||
2195 | (Metadata * Scope, Metadata *File, unsigned Discriminator), | ||||
2196 | (Scope, File, Discriminator)) | ||||
2197 | |||||
2198 | TempDILexicalBlockFile clone() const { return cloneImpl(); } | ||||
2199 | unsigned getDiscriminator() const { return Discriminator; } | ||||
2200 | |||||
2201 | static bool classof(const Metadata *MD) { | ||||
2202 | return MD->getMetadataID() == DILexicalBlockFileKind; | ||||
2203 | } | ||||
2204 | }; | ||||
2205 | |||||
2206 | unsigned DILocation::getDiscriminator() const { | ||||
2207 | if (auto *F = dyn_cast<DILexicalBlockFile>(getScope())) | ||||
2208 | return F->getDiscriminator(); | ||||
2209 | return 0; | ||||
2210 | } | ||||
2211 | |||||
2212 | const DILocation * | ||||
2213 | DILocation::cloneWithDiscriminator(unsigned Discriminator) const { | ||||
2214 | DIScope *Scope = getScope(); | ||||
2215 | // Skip all parent DILexicalBlockFile that already have a discriminator | ||||
2216 | // assigned. We do not want to have nested DILexicalBlockFiles that have | ||||
2217 | // mutliple discriminators because only the leaf DILexicalBlockFile's | ||||
2218 | // dominator will be used. | ||||
2219 | for (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope); | ||||
2220 | LBF && LBF->getDiscriminator() != 0; | ||||
2221 | LBF = dyn_cast<DILexicalBlockFile>(Scope)) | ||||
2222 | Scope = LBF->getScope(); | ||||
2223 | DILexicalBlockFile *NewScope = | ||||
2224 | DILexicalBlockFile::get(getContext(), Scope, getFile(), Discriminator); | ||||
2225 | return DILocation::get(getContext(), getLine(), getColumn(), NewScope, | ||||
2226 | getInlinedAt()); | ||||
2227 | } | ||||
2228 | |||||
2229 | unsigned DILocation::getBaseDiscriminator() const { | ||||
2230 | return getBaseDiscriminatorFromDiscriminator(getDiscriminator(), | ||||
2231 | EnableFSDiscriminator); | ||||
2232 | } | ||||
2233 | |||||
2234 | unsigned DILocation::getDuplicationFactor() const { | ||||
2235 | return getDuplicationFactorFromDiscriminator(getDiscriminator()); | ||||
2236 | } | ||||
2237 | |||||
2238 | unsigned DILocation::getCopyIdentifier() const { | ||||
2239 | return getCopyIdentifierFromDiscriminator(getDiscriminator()); | ||||
2240 | } | ||||
2241 | |||||
2242 | Optional<const DILocation *> | ||||
2243 | DILocation::cloneWithBaseDiscriminator(unsigned D) const { | ||||
2244 | unsigned BD, DF, CI; | ||||
2245 | |||||
2246 | if (EnableFSDiscriminator) { | ||||
2247 | BD = getBaseDiscriminator(); | ||||
2248 | if (D == BD) | ||||
2249 | return this; | ||||
2250 | return cloneWithDiscriminator(D); | ||||
2251 | } | ||||
2252 | |||||
2253 | decodeDiscriminator(getDiscriminator(), BD, DF, CI); | ||||
2254 | if (D == BD) | ||||
2255 | return this; | ||||
2256 | if (Optional<unsigned> Encoded = encodeDiscriminator(D, DF, CI)) | ||||
2257 | return cloneWithDiscriminator(*Encoded); | ||||
2258 | return None; | ||||
2259 | } | ||||
2260 | |||||
2261 | Optional<const DILocation *> | ||||
2262 | DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const { | ||||
2263 | assert(!EnableFSDiscriminator && "FSDiscriminator should not call this.")(static_cast <bool> (!EnableFSDiscriminator && "FSDiscriminator should not call this." ) ? void (0) : __assert_fail ("!EnableFSDiscriminator && \"FSDiscriminator should not call this.\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 2263, __extension__ __PRETTY_FUNCTION__)); | ||||
2264 | |||||
2265 | DF *= getDuplicationFactor(); | ||||
2266 | if (DF <= 1) | ||||
2267 | return this; | ||||
2268 | |||||
2269 | unsigned BD = getBaseDiscriminator(); | ||||
2270 | unsigned CI = getCopyIdentifier(); | ||||
2271 | if (Optional<unsigned> D = encodeDiscriminator(BD, DF, CI)) | ||||
2272 | return cloneWithDiscriminator(*D); | ||||
2273 | return None; | ||||
2274 | } | ||||
2275 | |||||
2276 | class DINamespace : public DIScope { | ||||
2277 | friend class LLVMContextImpl; | ||||
2278 | friend class MDNode; | ||||
2279 | |||||
2280 | unsigned ExportSymbols : 1; | ||||
2281 | |||||
2282 | DINamespace(LLVMContext &Context, StorageType Storage, bool ExportSymbols, | ||||
2283 | ArrayRef<Metadata *> Ops) | ||||
2284 | : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, | ||||
2285 | Ops), | ||||
2286 | ExportSymbols(ExportSymbols) {} | ||||
2287 | ~DINamespace() = default; | ||||
2288 | |||||
2289 | static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
2290 | StringRef Name, bool ExportSymbols, | ||||
2291 | StorageType Storage, bool ShouldCreate = true) { | ||||
2292 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
2293 | ExportSymbols, Storage, ShouldCreate); | ||||
2294 | } | ||||
2295 | static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
2296 | MDString *Name, bool ExportSymbols, | ||||
2297 | StorageType Storage, bool ShouldCreate = true); | ||||
2298 | |||||
2299 | TempDINamespace cloneImpl() const { | ||||
2300 | return getTemporary(getContext(), getScope(), getName(), | ||||
2301 | getExportSymbols()); | ||||
2302 | } | ||||
2303 | |||||
2304 | public: | ||||
2305 | DEFINE_MDNODE_GET(DINamespace, | ||||
2306 | (DIScope *Scope, StringRef Name, bool ExportSymbols), | ||||
2307 | (Scope, Name, ExportSymbols)) | ||||
2308 | DEFINE_MDNODE_GET(DINamespace, | ||||
2309 | (Metadata *Scope, MDString *Name, bool ExportSymbols), | ||||
2310 | (Scope, Name, ExportSymbols)) | ||||
2311 | |||||
2312 | TempDINamespace clone() const { return cloneImpl(); } | ||||
2313 | |||||
2314 | bool getExportSymbols() const { return ExportSymbols; } | ||||
2315 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2316 | StringRef getName() const { return getStringOperand(2); } | ||||
2317 | |||||
2318 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2319 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
2320 | |||||
2321 | static bool classof(const Metadata *MD) { | ||||
2322 | return MD->getMetadataID() == DINamespaceKind; | ||||
2323 | } | ||||
2324 | }; | ||||
2325 | |||||
2326 | /// Represents a module in the programming language, for example, a Clang | ||||
2327 | /// module, or a Fortran module. | ||||
2328 | class DIModule : public DIScope { | ||||
2329 | friend class LLVMContextImpl; | ||||
2330 | friend class MDNode; | ||||
2331 | unsigned LineNo; | ||||
2332 | bool IsDecl; | ||||
2333 | |||||
2334 | DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||
2335 | bool IsDecl, ArrayRef<Metadata *> Ops) | ||||
2336 | : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops), | ||||
2337 | LineNo(LineNo), IsDecl(IsDecl) {} | ||||
2338 | ~DIModule() = default; | ||||
2339 | |||||
2340 | static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope, | ||||
2341 | StringRef Name, StringRef ConfigurationMacros, | ||||
2342 | StringRef IncludePath, StringRef APINotesFile, | ||||
2343 | unsigned LineNo, bool IsDecl, StorageType Storage, | ||||
2344 | bool ShouldCreate = true) { | ||||
2345 | return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name), | ||||
2346 | getCanonicalMDString(Context, ConfigurationMacros), | ||||
2347 | getCanonicalMDString(Context, IncludePath), | ||||
2348 | getCanonicalMDString(Context, APINotesFile), LineNo, IsDecl, | ||||
2349 | Storage, ShouldCreate); | ||||
2350 | } | ||||
2351 | static DIModule *getImpl(LLVMContext &Context, Metadata *File, | ||||
2352 | Metadata *Scope, MDString *Name, | ||||
2353 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||
2354 | MDString *APINotesFile, unsigned LineNo, bool IsDecl, | ||||
2355 | StorageType Storage, bool ShouldCreate = true); | ||||
2356 | |||||
2357 | TempDIModule cloneImpl() const { | ||||
2358 | return getTemporary(getContext(), getFile(), getScope(), getName(), | ||||
2359 | getConfigurationMacros(), getIncludePath(), | ||||
2360 | getAPINotesFile(), getLineNo(), getIsDecl()); | ||||
2361 | } | ||||
2362 | |||||
2363 | public: | ||||
2364 | DEFINE_MDNODE_GET(DIModule, | ||||
2365 | (DIFile * File, DIScope *Scope, StringRef Name, | ||||
2366 | StringRef ConfigurationMacros, StringRef IncludePath, | ||||
2367 | StringRef APINotesFile, unsigned LineNo, | ||||
2368 | bool IsDecl = false), | ||||
2369 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||
2370 | APINotesFile, LineNo, IsDecl)) | ||||
2371 | DEFINE_MDNODE_GET(DIModule, | ||||
2372 | (Metadata * File, Metadata *Scope, MDString *Name, | ||||
2373 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||
2374 | MDString *APINotesFile, unsigned LineNo, | ||||
2375 | bool IsDecl = false), | ||||
2376 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||
2377 | APINotesFile, LineNo, IsDecl)) | ||||
2378 | |||||
2379 | TempDIModule clone() const { return cloneImpl(); } | ||||
2380 | |||||
2381 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2382 | StringRef getName() const { return getStringOperand(2); } | ||||
2383 | StringRef getConfigurationMacros() const { return getStringOperand(3); } | ||||
2384 | StringRef getIncludePath() const { return getStringOperand(4); } | ||||
2385 | StringRef getAPINotesFile() const { return getStringOperand(5); } | ||||
2386 | unsigned getLineNo() const { return LineNo; } | ||||
2387 | bool getIsDecl() const { return IsDecl; } | ||||
2388 | |||||
2389 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2390 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
2391 | MDString *getRawConfigurationMacros() const { | ||||
2392 | return getOperandAs<MDString>(3); | ||||
2393 | } | ||||
2394 | MDString *getRawIncludePath() const { return getOperandAs<MDString>(4); } | ||||
2395 | MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(5); } | ||||
2396 | |||||
2397 | static bool classof(const Metadata *MD) { | ||||
2398 | return MD->getMetadataID() == DIModuleKind; | ||||
2399 | } | ||||
2400 | }; | ||||
2401 | |||||
2402 | /// Base class for template parameters. | ||||
2403 | class DITemplateParameter : public DINode { | ||||
2404 | protected: | ||||
2405 | bool IsDefault; | ||||
2406 | |||||
2407 | DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, | ||||
2408 | unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops) | ||||
2409 | : DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {} | ||||
2410 | ~DITemplateParameter() = default; | ||||
2411 | |||||
2412 | public: | ||||
2413 | StringRef getName() const { return getStringOperand(0); } | ||||
2414 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
2415 | |||||
2416 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
2417 | Metadata *getRawType() const { return getOperand(1); } | ||||
2418 | bool isDefault() const { return IsDefault; } | ||||
2419 | |||||
2420 | static bool classof(const Metadata *MD) { | ||||
2421 | return MD->getMetadataID() == DITemplateTypeParameterKind || | ||||
2422 | MD->getMetadataID() == DITemplateValueParameterKind; | ||||
2423 | } | ||||
2424 | }; | ||||
2425 | |||||
2426 | class DITemplateTypeParameter : public DITemplateParameter { | ||||
2427 | friend class LLVMContextImpl; | ||||
2428 | friend class MDNode; | ||||
2429 | |||||
2430 | DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, | ||||
2431 | bool IsDefault, ArrayRef<Metadata *> Ops) | ||||
2432 | : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, | ||||
2433 | dwarf::DW_TAG_template_type_parameter, IsDefault, | ||||
2434 | Ops) {} | ||||
2435 | ~DITemplateTypeParameter() = default; | ||||
2436 | |||||
2437 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, | ||||
2438 | DIType *Type, bool IsDefault, | ||||
2439 | StorageType Storage, | ||||
2440 | bool ShouldCreate = true) { | ||||
2441 | return getImpl(Context, getCanonicalMDString(Context, Name), Type, | ||||
2442 | IsDefault, Storage, ShouldCreate); | ||||
2443 | } | ||||
2444 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, | ||||
2445 | Metadata *Type, bool IsDefault, | ||||
2446 | StorageType Storage, | ||||
2447 | bool ShouldCreate = true); | ||||
2448 | |||||
2449 | TempDITemplateTypeParameter cloneImpl() const { | ||||
2450 | return getTemporary(getContext(), getName(), getType(), isDefault()); | ||||
2451 | } | ||||
2452 | |||||
2453 | public: | ||||
2454 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||
2455 | (StringRef Name, DIType *Type, bool IsDefault), | ||||
2456 | (Name, Type, IsDefault)) | ||||
2457 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||
2458 | (MDString *Name, Metadata *Type, bool IsDefault), | ||||
2459 | (Name, Type, IsDefault)) | ||||
2460 | |||||
2461 | TempDITemplateTypeParameter clone() const { return cloneImpl(); } | ||||
2462 | |||||
2463 | static bool classof(const Metadata *MD) { | ||||
2464 | return MD->getMetadataID() == DITemplateTypeParameterKind; | ||||
2465 | } | ||||
2466 | }; | ||||
2467 | |||||
2468 | class DITemplateValueParameter : public DITemplateParameter { | ||||
2469 | friend class LLVMContextImpl; | ||||
2470 | friend class MDNode; | ||||
2471 | |||||
2472 | DITemplateValueParameter(LLVMContext &Context, StorageType Storage, | ||||
2473 | unsigned Tag, bool IsDefault, | ||||
2474 | ArrayRef<Metadata *> Ops) | ||||
2475 | : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, | ||||
2476 | IsDefault, Ops) {} | ||||
2477 | ~DITemplateValueParameter() = default; | ||||
2478 | |||||
2479 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||
2480 | StringRef Name, DIType *Type, | ||||
2481 | bool IsDefault, Metadata *Value, | ||||
2482 | StorageType Storage, | ||||
2483 | bool ShouldCreate = true) { | ||||
2484 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, | ||||
2485 | IsDefault, Value, Storage, ShouldCreate); | ||||
2486 | } | ||||
2487 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||
2488 | MDString *Name, Metadata *Type, | ||||
2489 | bool IsDefault, Metadata *Value, | ||||
2490 | StorageType Storage, | ||||
2491 | bool ShouldCreate = true); | ||||
2492 | |||||
2493 | TempDITemplateValueParameter cloneImpl() const { | ||||
2494 | return getTemporary(getContext(), getTag(), getName(), getType(), | ||||
2495 | isDefault(), getValue()); | ||||
2496 | } | ||||
2497 | |||||
2498 | public: | ||||
2499 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||
2500 | (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault, | ||||
2501 | Metadata *Value), | ||||
2502 | (Tag, Name, Type, IsDefault, Value)) | ||||
2503 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||
2504 | (unsigned Tag, MDString *Name, Metadata *Type, | ||||
2505 | bool IsDefault, Metadata *Value), | ||||
2506 | (Tag, Name, Type, IsDefault, Value)) | ||||
2507 | |||||
2508 | TempDITemplateValueParameter clone() const { return cloneImpl(); } | ||||
2509 | |||||
2510 | Metadata *getValue() const { return getOperand(2); } | ||||
2511 | |||||
2512 | static bool classof(const Metadata *MD) { | ||||
2513 | return MD->getMetadataID() == DITemplateValueParameterKind; | ||||
2514 | } | ||||
2515 | }; | ||||
2516 | |||||
2517 | /// Base class for variables. | ||||
2518 | class DIVariable : public DINode { | ||||
2519 | unsigned Line; | ||||
2520 | uint32_t AlignInBits; | ||||
2521 | |||||
2522 | protected: | ||||
2523 | DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line, | ||||
2524 | ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0) | ||||
2525 | : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line), | ||||
2526 | AlignInBits(AlignInBits) {} | ||||
2527 | ~DIVariable() = default; | ||||
2528 | |||||
2529 | public: | ||||
2530 | unsigned getLine() const { return Line; } | ||||
2531 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2532 | StringRef getName() const { return getStringOperand(1); } | ||||
2533 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
2534 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
2535 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||
2536 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||
2537 | /// Determines the size of the variable's type. | ||||
2538 | Optional<uint64_t> getSizeInBits() const; | ||||
2539 | |||||
2540 | /// Return the signedness of this variable's type, or None if this type is | ||||
2541 | /// neither signed nor unsigned. | ||||
2542 | Optional<DIBasicType::Signedness> getSignedness() const { | ||||
2543 | if (auto *BT = dyn_cast<DIBasicType>(getType())) | ||||
2544 | return BT->getSignedness(); | ||||
2545 | return None; | ||||
2546 | } | ||||
2547 | |||||
2548 | StringRef getFilename() const { | ||||
2549 | if (auto *F = getFile()) | ||||
2550 | return F->getFilename(); | ||||
2551 | return ""; | ||||
2552 | } | ||||
2553 | |||||
2554 | StringRef getDirectory() const { | ||||
2555 | if (auto *F = getFile()) | ||||
2556 | return F->getDirectory(); | ||||
2557 | return ""; | ||||
2558 | } | ||||
2559 | |||||
2560 | Optional<StringRef> getSource() const { | ||||
2561 | if (auto *F = getFile()) | ||||
2562 | return F->getSource(); | ||||
2563 | return None; | ||||
2564 | } | ||||
2565 | |||||
2566 | Metadata *getRawScope() const { return getOperand(0); } | ||||
2567 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||
2568 | Metadata *getRawFile() const { return getOperand(2); } | ||||
2569 | Metadata *getRawType() const { return getOperand(3); } | ||||
2570 | |||||
2571 | static bool classof(const Metadata *MD) { | ||||
2572 | return MD->getMetadataID() == DILocalVariableKind || | ||||
2573 | MD->getMetadataID() == DIGlobalVariableKind; | ||||
2574 | } | ||||
2575 | }; | ||||
2576 | |||||
2577 | /// DWARF expression. | ||||
2578 | /// | ||||
2579 | /// This is (almost) a DWARF expression that modifies the location of a | ||||
2580 | /// variable, or the location of a single piece of a variable, or (when using | ||||
2581 | /// DW_OP_stack_value) is the constant variable value. | ||||
2582 | /// | ||||
2583 | /// TODO: Co-allocate the expression elements. | ||||
2584 | /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary | ||||
2585 | /// storage types. | ||||
2586 | class DIExpression : public MDNode { | ||||
2587 | friend class LLVMContextImpl; | ||||
2588 | friend class MDNode; | ||||
2589 | |||||
2590 | std::vector<uint64_t> Elements; | ||||
2591 | |||||
2592 | DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) | ||||
2593 | : MDNode(C, DIExpressionKind, Storage, None), | ||||
2594 | Elements(Elements.begin(), Elements.end()) {} | ||||
2595 | ~DIExpression() = default; | ||||
2596 | |||||
2597 | static DIExpression *getImpl(LLVMContext &Context, | ||||
2598 | ArrayRef<uint64_t> Elements, StorageType Storage, | ||||
2599 | bool ShouldCreate = true); | ||||
2600 | |||||
2601 | TempDIExpression cloneImpl() const { | ||||
2602 | return getTemporary(getContext(), getElements()); | ||||
2603 | } | ||||
2604 | |||||
2605 | public: | ||||
2606 | DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements)) | ||||
2607 | |||||
2608 | TempDIExpression clone() const { return cloneImpl(); } | ||||
2609 | |||||
2610 | ArrayRef<uint64_t> getElements() const { return Elements; } | ||||
2611 | |||||
2612 | unsigned getNumElements() const { return Elements.size(); } | ||||
2613 | |||||
2614 | uint64_t getElement(unsigned I) const { | ||||
2615 | assert(I < Elements.size() && "Index out of range")(static_cast <bool> (I < Elements.size() && "Index out of range" ) ? void (0) : __assert_fail ("I < Elements.size() && \"Index out of range\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 2615, __extension__ __PRETTY_FUNCTION__)); | ||||
2616 | return Elements[I]; | ||||
2617 | } | ||||
2618 | |||||
2619 | enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; | ||||
2620 | /// Determine whether this represents a constant value, if so | ||||
2621 | // return it's sign information. | ||||
2622 | llvm::Optional<SignedOrUnsignedConstant> isConstant() const; | ||||
2623 | |||||
2624 | /// Return the number of unique location operands referred to (via | ||||
2625 | /// DW_OP_LLVM_arg) in this expression; this is not necessarily the number of | ||||
2626 | /// instances of DW_OP_LLVM_arg within the expression. | ||||
2627 | /// For example, for the expression: | ||||
2628 | /// (DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_plus, | ||||
2629 | /// DW_OP_LLVM_arg 0, DW_OP_mul) | ||||
2630 | /// This function would return 2, as there are two unique location operands | ||||
2631 | /// (0 and 1). | ||||
2632 | uint64_t getNumLocationOperands() const; | ||||
2633 | |||||
2634 | using element_iterator = ArrayRef<uint64_t>::iterator; | ||||
2635 | |||||
2636 | element_iterator elements_begin() const { return getElements().begin(); } | ||||
2637 | element_iterator elements_end() const { return getElements().end(); } | ||||
2638 | |||||
2639 | /// A lightweight wrapper around an expression operand. | ||||
2640 | /// | ||||
2641 | /// TODO: Store arguments directly and change \a DIExpression to store a | ||||
2642 | /// range of these. | ||||
2643 | class ExprOperand { | ||||
2644 | const uint64_t *Op = nullptr; | ||||
2645 | |||||
2646 | public: | ||||
2647 | ExprOperand() = default; | ||||
2648 | explicit ExprOperand(const uint64_t *Op) : Op(Op) {} | ||||
2649 | |||||
2650 | const uint64_t *get() const { return Op; } | ||||
2651 | |||||
2652 | /// Get the operand code. | ||||
2653 | uint64_t getOp() const { return *Op; } | ||||
2654 | |||||
2655 | /// Get an argument to the operand. | ||||
2656 | /// | ||||
2657 | /// Never returns the operand itself. | ||||
2658 | uint64_t getArg(unsigned I) const { return Op[I + 1]; } | ||||
2659 | |||||
2660 | unsigned getNumArgs() const { return getSize() - 1; } | ||||
2661 | |||||
2662 | /// Return the size of the operand. | ||||
2663 | /// | ||||
2664 | /// Return the number of elements in the operand (1 + args). | ||||
2665 | unsigned getSize() const; | ||||
2666 | |||||
2667 | /// Append the elements of this operand to \p V. | ||||
2668 | void appendToVector(SmallVectorImpl<uint64_t> &V) const { | ||||
2669 | V.append(get(), get() + getSize()); | ||||
2670 | } | ||||
2671 | }; | ||||
2672 | |||||
2673 | /// An iterator for expression operands. | ||||
2674 | class expr_op_iterator { | ||||
2675 | ExprOperand Op; | ||||
2676 | |||||
2677 | public: | ||||
2678 | using iterator_category = std::input_iterator_tag; | ||||
2679 | using value_type = ExprOperand; | ||||
2680 | using difference_type = std::ptrdiff_t; | ||||
2681 | using pointer = value_type *; | ||||
2682 | using reference = value_type &; | ||||
2683 | |||||
2684 | expr_op_iterator() = default; | ||||
2685 | explicit expr_op_iterator(element_iterator I) : Op(I) {} | ||||
2686 | |||||
2687 | element_iterator getBase() const { return Op.get(); } | ||||
2688 | const ExprOperand &operator*() const { return Op; } | ||||
2689 | const ExprOperand *operator->() const { return &Op; } | ||||
2690 | |||||
2691 | expr_op_iterator &operator++() { | ||||
2692 | increment(); | ||||
2693 | return *this; | ||||
2694 | } | ||||
2695 | expr_op_iterator operator++(int) { | ||||
2696 | expr_op_iterator T(*this); | ||||
2697 | increment(); | ||||
2698 | return T; | ||||
2699 | } | ||||
2700 | |||||
2701 | /// Get the next iterator. | ||||
2702 | /// | ||||
2703 | /// \a std::next() doesn't work because this is technically an | ||||
2704 | /// input_iterator, but it's a perfectly valid operation. This is an | ||||
2705 | /// accessor to provide the same functionality. | ||||
2706 | expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } | ||||
2707 | |||||
2708 | bool operator==(const expr_op_iterator &X) const { | ||||
2709 | return getBase() == X.getBase(); | ||||
2710 | } | ||||
2711 | bool operator!=(const expr_op_iterator &X) const { | ||||
2712 | return getBase() != X.getBase(); | ||||
2713 | } | ||||
2714 | |||||
2715 | private: | ||||
2716 | void increment() { Op = ExprOperand(getBase() + Op.getSize()); } | ||||
2717 | }; | ||||
2718 | |||||
2719 | /// Visit the elements via ExprOperand wrappers. | ||||
2720 | /// | ||||
2721 | /// These range iterators visit elements through \a ExprOperand wrappers. | ||||
2722 | /// This is not guaranteed to be a valid range unless \a isValid() gives \c | ||||
2723 | /// true. | ||||
2724 | /// | ||||
2725 | /// \pre \a isValid() gives \c true. | ||||
2726 | /// @{ | ||||
2727 | expr_op_iterator expr_op_begin() const { | ||||
2728 | return expr_op_iterator(elements_begin()); | ||||
2729 | } | ||||
2730 | expr_op_iterator expr_op_end() const { | ||||
2731 | return expr_op_iterator(elements_end()); | ||||
2732 | } | ||||
2733 | iterator_range<expr_op_iterator> expr_ops() const { | ||||
2734 | return {expr_op_begin(), expr_op_end()}; | ||||
2735 | } | ||||
2736 | /// @} | ||||
2737 | |||||
2738 | bool isValid() const; | ||||
2739 | |||||
2740 | static bool classof(const Metadata *MD) { | ||||
2741 | return MD->getMetadataID() == DIExpressionKind; | ||||
2742 | } | ||||
2743 | |||||
2744 | /// Return whether the first element a DW_OP_deref. | ||||
2745 | bool startsWithDeref() const { | ||||
2746 | return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref; | ||||
2747 | } | ||||
2748 | |||||
2749 | /// Holds the characteristics of one fragment of a larger variable. | ||||
2750 | struct FragmentInfo { | ||||
2751 | uint64_t SizeInBits; | ||||
2752 | uint64_t OffsetInBits; | ||||
2753 | }; | ||||
2754 | |||||
2755 | /// Retrieve the details of this fragment expression. | ||||
2756 | static Optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start, | ||||
2757 | expr_op_iterator End); | ||||
2758 | |||||
2759 | /// Retrieve the details of this fragment expression. | ||||
2760 | Optional<FragmentInfo> getFragmentInfo() const { | ||||
2761 | return getFragmentInfo(expr_op_begin(), expr_op_end()); | ||||
2762 | } | ||||
2763 | |||||
2764 | /// Return whether this is a piece of an aggregate variable. | ||||
2765 | bool isFragment() const { return getFragmentInfo().hasValue(); } | ||||
2766 | |||||
2767 | /// Return whether this is an implicit location description. | ||||
2768 | bool isImplicit() const; | ||||
2769 | |||||
2770 | /// Return whether the location is computed on the expression stack, meaning | ||||
2771 | /// it cannot be a simple register location. | ||||
2772 | bool isComplex() const; | ||||
2773 | |||||
2774 | /// Append \p Ops with operations to apply the \p Offset. | ||||
2775 | static void appendOffset(SmallVectorImpl<uint64_t> &Ops, int64_t Offset); | ||||
2776 | |||||
2777 | /// If this is a constant offset, extract it. If there is no expression, | ||||
2778 | /// return true with an offset of zero. | ||||
2779 | bool extractIfOffset(int64_t &Offset) const; | ||||
2780 | |||||
2781 | /// Returns true iff this DIExpression contains at least one instance of | ||||
2782 | /// `DW_OP_LLVM_arg, n` for all n in [0, N). | ||||
2783 | bool hasAllLocationOps(unsigned N) const; | ||||
2784 | |||||
2785 | /// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF | ||||
2786 | /// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address | ||||
2787 | /// Space>. | ||||
2788 | static const DIExpression *extractAddressClass(const DIExpression *Expr, | ||||
2789 | unsigned &AddrClass); | ||||
2790 | |||||
2791 | /// Used for DIExpression::prepend. | ||||
2792 | enum PrependOps : uint8_t { | ||||
2793 | ApplyOffset = 0, | ||||
2794 | DerefBefore = 1 << 0, | ||||
2795 | DerefAfter = 1 << 1, | ||||
2796 | StackValue = 1 << 2, | ||||
2797 | EntryValue = 1 << 3 | ||||
2798 | }; | ||||
2799 | |||||
2800 | /// Prepend \p DIExpr with a deref and offset operation and optionally turn it | ||||
2801 | /// into a stack value or/and an entry value. | ||||
2802 | static DIExpression *prepend(const DIExpression *Expr, uint8_t Flags, | ||||
2803 | int64_t Offset = 0); | ||||
2804 | |||||
2805 | /// Prepend \p DIExpr with the given opcodes and optionally turn it into a | ||||
2806 | /// stack value. | ||||
2807 | static DIExpression *prependOpcodes(const DIExpression *Expr, | ||||
2808 | SmallVectorImpl<uint64_t> &Ops, | ||||
2809 | bool StackValue = false, | ||||
2810 | bool EntryValue = false); | ||||
2811 | |||||
2812 | /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the | ||||
2813 | /// returned expression is a stack value only if \p DIExpr is a stack value. | ||||
2814 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||
2815 | /// the same fragment. | ||||
2816 | static DIExpression *append(const DIExpression *Expr, ArrayRef<uint64_t> Ops); | ||||
2817 | |||||
2818 | /// Convert \p DIExpr into a stack value if it isn't one already by appending | ||||
2819 | /// DW_OP_deref if needed, and appending \p Ops to the resulting expression. | ||||
2820 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||
2821 | /// the same fragment. | ||||
2822 | static DIExpression *appendToStack(const DIExpression *Expr, | ||||
2823 | ArrayRef<uint64_t> Ops); | ||||
2824 | |||||
2825 | /// Create a copy of \p Expr by appending the given list of \p Ops to each | ||||
2826 | /// instance of the operand `DW_OP_LLVM_arg, \p ArgNo`. This is used to | ||||
2827 | /// modify a specific location used by \p Expr, such as when salvaging that | ||||
2828 | /// location. | ||||
2829 | static DIExpression *appendOpsToArg(const DIExpression *Expr, | ||||
2830 | ArrayRef<uint64_t> Ops, unsigned ArgNo, | ||||
2831 | bool StackValue = false); | ||||
2832 | |||||
2833 | /// Create a copy of \p Expr with each instance of | ||||
2834 | /// `DW_OP_LLVM_arg, \p OldArg` replaced with `DW_OP_LLVM_arg, \p NewArg`, | ||||
2835 | /// and each instance of `DW_OP_LLVM_arg, Arg` with `DW_OP_LLVM_arg, Arg - 1` | ||||
2836 | /// for all Arg > \p OldArg. | ||||
2837 | /// This is used when replacing one of the operands of a debug value list | ||||
2838 | /// with another operand in the same list and deleting the old operand. | ||||
2839 | static DIExpression *replaceArg(const DIExpression *Expr, uint64_t OldArg, | ||||
2840 | uint64_t NewArg); | ||||
2841 | |||||
2842 | /// Create a DIExpression to describe one part of an aggregate variable that | ||||
2843 | /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation | ||||
2844 | /// will be appended to the elements of \c Expr. If \c Expr already contains | ||||
2845 | /// a \c DW_OP_LLVM_fragment \c OffsetInBits is interpreted as an offset | ||||
2846 | /// into the existing fragment. | ||||
2847 | /// | ||||
2848 | /// \param OffsetInBits Offset of the piece in bits. | ||||
2849 | /// \param SizeInBits Size of the piece in bits. | ||||
2850 | /// \return Creating a fragment expression may fail if \c Expr | ||||
2851 | /// contains arithmetic operations that would be truncated. | ||||
2852 | static Optional<DIExpression *> | ||||
2853 | createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, | ||||
2854 | unsigned SizeInBits); | ||||
2855 | |||||
2856 | /// Determine the relative position of the fragments passed in. | ||||
2857 | /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, | ||||
2858 | /// 1 if this is entirely after Other. | ||||
2859 | static int fragmentCmp(const FragmentInfo &A, const FragmentInfo &B) { | ||||
2860 | uint64_t l1 = A.OffsetInBits; | ||||
2861 | uint64_t l2 = B.OffsetInBits; | ||||
2862 | uint64_t r1 = l1 + A.SizeInBits; | ||||
2863 | uint64_t r2 = l2 + B.SizeInBits; | ||||
2864 | if (r1 <= l2) | ||||
2865 | return -1; | ||||
2866 | else if (r2 <= l1) | ||||
2867 | return 1; | ||||
2868 | else | ||||
2869 | return 0; | ||||
2870 | } | ||||
2871 | |||||
2872 | using ExtOps = std::array<uint64_t, 6>; | ||||
2873 | |||||
2874 | /// Returns the ops for a zero- or sign-extension in a DIExpression. | ||||
2875 | static ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed); | ||||
2876 | |||||
2877 | /// Append a zero- or sign-extension to \p Expr. Converts the expression to a | ||||
2878 | /// stack value if it isn't one already. | ||||
2879 | static DIExpression *appendExt(const DIExpression *Expr, unsigned FromSize, | ||||
2880 | unsigned ToSize, bool Signed); | ||||
2881 | |||||
2882 | /// Check if fragments overlap between a pair of FragmentInfos. | ||||
2883 | static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B) { | ||||
2884 | return fragmentCmp(A, B) == 0; | ||||
2885 | } | ||||
2886 | |||||
2887 | /// Determine the relative position of the fragments described by this | ||||
2888 | /// DIExpression and \p Other. Calls static fragmentCmp implementation. | ||||
2889 | int fragmentCmp(const DIExpression *Other) const { | ||||
2890 | auto Fragment1 = *getFragmentInfo(); | ||||
2891 | auto Fragment2 = *Other->getFragmentInfo(); | ||||
2892 | return fragmentCmp(Fragment1, Fragment2); | ||||
2893 | } | ||||
2894 | |||||
2895 | /// Check if fragments overlap between this DIExpression and \p Other. | ||||
2896 | bool fragmentsOverlap(const DIExpression *Other) const { | ||||
2897 | if (!isFragment() || !Other->isFragment()) | ||||
2898 | return true; | ||||
2899 | return fragmentCmp(Other) == 0; | ||||
2900 | } | ||||
2901 | |||||
2902 | /// Check if the expression consists of exactly one entry value operand. | ||||
2903 | /// (This is the only configuration of entry values that is supported.) | ||||
2904 | bool isEntryValue() const { | ||||
2905 | return getNumElements() > 0 && | ||||
2906 | getElement(0) == dwarf::DW_OP_LLVM_entry_value; | ||||
2907 | } | ||||
2908 | |||||
2909 | /// Try to shorten an expression with an initial constant operand. | ||||
2910 | /// Returns a new expression and constant on success, or the original | ||||
2911 | /// expression and constant on failure. | ||||
2912 | std::pair<DIExpression *, const ConstantInt *> | ||||
2913 | constantFold(const ConstantInt *CI); | ||||
2914 | }; | ||||
2915 | |||||
2916 | inline bool operator==(const DIExpression::FragmentInfo &A, | ||||
2917 | const DIExpression::FragmentInfo &B) { | ||||
2918 | return std::tie(A.SizeInBits, A.OffsetInBits) == | ||||
2919 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||
2920 | } | ||||
2921 | |||||
2922 | inline bool operator<(const DIExpression::FragmentInfo &A, | ||||
2923 | const DIExpression::FragmentInfo &B) { | ||||
2924 | return std::tie(A.SizeInBits, A.OffsetInBits) < | ||||
2925 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||
2926 | } | ||||
2927 | |||||
2928 | template <> struct DenseMapInfo<DIExpression::FragmentInfo> { | ||||
2929 | using FragInfo = DIExpression::FragmentInfo; | ||||
2930 | static const uint64_t MaxVal = std::numeric_limits<uint64_t>::max(); | ||||
2931 | |||||
2932 | static inline FragInfo getEmptyKey() { return {MaxVal, MaxVal}; } | ||||
2933 | |||||
2934 | static inline FragInfo getTombstoneKey() { return {MaxVal - 1, MaxVal - 1}; } | ||||
2935 | |||||
2936 | static unsigned getHashValue(const FragInfo &Frag) { | ||||
2937 | return (Frag.SizeInBits & 0xffff) << 16 | (Frag.OffsetInBits & 0xffff); | ||||
2938 | } | ||||
2939 | |||||
2940 | static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } | ||||
2941 | }; | ||||
2942 | |||||
2943 | /// Global variables. | ||||
2944 | /// | ||||
2945 | /// TODO: Remove DisplayName. It's always equal to Name. | ||||
2946 | class DIGlobalVariable : public DIVariable { | ||||
2947 | friend class LLVMContextImpl; | ||||
2948 | friend class MDNode; | ||||
2949 | |||||
2950 | bool IsLocalToUnit; | ||||
2951 | bool IsDefinition; | ||||
2952 | |||||
2953 | DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
2954 | bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, | ||||
2955 | ArrayRef<Metadata *> Ops) | ||||
2956 | : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), | ||||
2957 | IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} | ||||
2958 | ~DIGlobalVariable() = default; | ||||
2959 | |||||
2960 | static DIGlobalVariable * | ||||
2961 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||
2962 | StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, | ||||
2963 | bool IsLocalToUnit, bool IsDefinition, | ||||
2964 | DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, | ||||
2965 | uint32_t AlignInBits, DINodeArray Annotations, StorageType Storage, | ||||
2966 | bool ShouldCreate = true) { | ||||
2967 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
2968 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||
2969 | IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, | ||||
2970 | cast_or_null<Metadata>(TemplateParams), AlignInBits, | ||||
2971 | Annotations.get(), Storage, ShouldCreate); | ||||
2972 | } | ||||
2973 | static DIGlobalVariable * | ||||
2974 | getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||
2975 | MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, | ||||
2976 | bool IsLocalToUnit, bool IsDefinition, | ||||
2977 | Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, | ||||
2978 | uint32_t AlignInBits, Metadata *Annotations, StorageType Storage, | ||||
2979 | bool ShouldCreate = true); | ||||
2980 | |||||
2981 | TempDIGlobalVariable cloneImpl() const { | ||||
2982 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||
2983 | getFile(), getLine(), getType(), isLocalToUnit(), | ||||
2984 | isDefinition(), getStaticDataMemberDeclaration(), | ||||
2985 | getTemplateParams(), getAlignInBits(), | ||||
2986 | getAnnotations()); | ||||
2987 | } | ||||
2988 | |||||
2989 | public: | ||||
2990 | DEFINE_MDNODE_GET(DIGlobalVariable, | ||||
2991 | (DIScope * Scope, StringRef Name, StringRef LinkageName, | ||||
2992 | DIFile *File, unsigned Line, DIType *Type, | ||||
2993 | bool IsLocalToUnit, bool IsDefinition, | ||||
2994 | DIDerivedType *StaticDataMemberDeclaration, | ||||
2995 | MDTuple *TemplateParams, uint32_t AlignInBits, | ||||
2996 | DINodeArray Annotations), | ||||
2997 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, | ||||
2998 | IsDefinition, StaticDataMemberDeclaration, TemplateParams, | ||||
2999 | AlignInBits, Annotations)) | ||||
3000 | DEFINE_MDNODE_GET(DIGlobalVariable, | ||||
3001 | (Metadata * Scope, MDString *Name, MDString *LinkageName, | ||||
3002 | Metadata *File, unsigned Line, Metadata *Type, | ||||
3003 | bool IsLocalToUnit, bool IsDefinition, | ||||
3004 | Metadata *StaticDataMemberDeclaration, | ||||
3005 | Metadata *TemplateParams, uint32_t AlignInBits, | ||||
3006 | Metadata *Annotations), | ||||
3007 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, | ||||
3008 | IsDefinition, StaticDataMemberDeclaration, TemplateParams, | ||||
3009 | AlignInBits, Annotations)) | ||||
3010 | |||||
3011 | TempDIGlobalVariable clone() const { return cloneImpl(); } | ||||
3012 | |||||
3013 | bool isLocalToUnit() const { return IsLocalToUnit; } | ||||
3014 | bool isDefinition() const { return IsDefinition; } | ||||
3015 | StringRef getDisplayName() const { return getStringOperand(4); } | ||||
3016 | StringRef getLinkageName() const { return getStringOperand(5); } | ||||
3017 | DIDerivedType *getStaticDataMemberDeclaration() const { | ||||
3018 | return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration()); | ||||
3019 | } | ||||
3020 | DINodeArray getAnnotations() const { | ||||
3021 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||
3022 | } | ||||
3023 | |||||
3024 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } | ||||
3025 | Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } | ||||
3026 | Metadata *getRawTemplateParams() const { return getOperand(7); } | ||||
3027 | MDTuple *getTemplateParams() const { return getOperandAs<MDTuple>(7); } | ||||
3028 | Metadata *getRawAnnotations() const { return getOperand(8); } | ||||
3029 | |||||
3030 | static bool classof(const Metadata *MD) { | ||||
3031 | return MD->getMetadataID() == DIGlobalVariableKind; | ||||
3032 | } | ||||
3033 | }; | ||||
3034 | |||||
3035 | class DICommonBlock : public DIScope { | ||||
3036 | unsigned LineNo; | ||||
3037 | |||||
3038 | friend class LLVMContextImpl; | ||||
3039 | friend class MDNode; | ||||
3040 | |||||
3041 | DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||
3042 | ArrayRef<Metadata *> Ops) | ||||
3043 | : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block, | ||||
3044 | Ops), LineNo(LineNo) {} | ||||
3045 | |||||
3046 | static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
3047 | DIGlobalVariable *Decl, StringRef Name, | ||||
3048 | DIFile *File, unsigned LineNo, | ||||
3049 | StorageType Storage, | ||||
3050 | bool ShouldCreate = true) { | ||||
3051 | return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), | ||||
3052 | File, LineNo, Storage, ShouldCreate); | ||||
3053 | } | ||||
3054 | static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
3055 | Metadata *Decl, MDString *Name, Metadata *File, | ||||
3056 | unsigned LineNo, | ||||
3057 | StorageType Storage, bool ShouldCreate = true); | ||||
3058 | |||||
3059 | TempDICommonBlock cloneImpl() const { | ||||
3060 | return getTemporary(getContext(), getScope(), getDecl(), getName(), | ||||
3061 | getFile(), getLineNo()); | ||||
3062 | } | ||||
3063 | |||||
3064 | public: | ||||
3065 | DEFINE_MDNODE_GET(DICommonBlock, | ||||
3066 | (DIScope *Scope, DIGlobalVariable *Decl, StringRef Name, | ||||
3067 | DIFile *File, unsigned LineNo), | ||||
3068 | (Scope, Decl, Name, File, LineNo)) | ||||
3069 | DEFINE_MDNODE_GET(DICommonBlock, | ||||
3070 | (Metadata *Scope, Metadata *Decl, MDString *Name, | ||||
3071 | Metadata *File, unsigned LineNo), | ||||
3072 | (Scope, Decl, Name, File, LineNo)) | ||||
3073 | |||||
3074 | TempDICommonBlock clone() const { return cloneImpl(); } | ||||
3075 | |||||
3076 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
3077 | DIGlobalVariable *getDecl() const { | ||||
3078 | return cast_or_null<DIGlobalVariable>(getRawDecl()); | ||||
3079 | } | ||||
3080 | StringRef getName() const { return getStringOperand(2); } | ||||
3081 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3082 | unsigned getLineNo() const { return LineNo; } | ||||
3083 | |||||
3084 | Metadata *getRawScope() const { return getOperand(0); } | ||||
3085 | Metadata *getRawDecl() const { return getOperand(1); } | ||||
3086 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
3087 | Metadata *getRawFile() const { return getOperand(3); } | ||||
3088 | |||||
3089 | static bool classof(const Metadata *MD) { | ||||
3090 | return MD->getMetadataID() == DICommonBlockKind; | ||||
3091 | } | ||||
3092 | }; | ||||
3093 | |||||
3094 | /// Local variable. | ||||
3095 | /// | ||||
3096 | /// TODO: Split up flags. | ||||
3097 | class DILocalVariable : public DIVariable { | ||||
3098 | friend class LLVMContextImpl; | ||||
3099 | friend class MDNode; | ||||
3100 | |||||
3101 | unsigned Arg : 16; | ||||
3102 | DIFlags Flags; | ||||
3103 | |||||
3104 | DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
3105 | unsigned Arg, DIFlags Flags, uint32_t AlignInBits, | ||||
3106 | ArrayRef<Metadata *> Ops) | ||||
3107 | : DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBits), | ||||
3108 | Arg(Arg), Flags(Flags) { | ||||
3109 | assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range")(static_cast <bool> (Arg < (1 << 16) && "DILocalVariable: Arg out of range") ? void (0) : __assert_fail ("Arg < (1 << 16) && \"DILocalVariable: Arg out of range\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 3109, __extension__ __PRETTY_FUNCTION__)); | ||||
3110 | } | ||||
3111 | ~DILocalVariable() = default; | ||||
3112 | |||||
3113 | static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
3114 | StringRef Name, DIFile *File, unsigned Line, | ||||
3115 | DIType *Type, unsigned Arg, DIFlags Flags, | ||||
3116 | uint32_t AlignInBits, DINodeArray Annotations, | ||||
3117 | StorageType Storage, bool ShouldCreate = true) { | ||||
3118 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||
3119 | Line, Type, Arg, Flags, AlignInBits, Annotations.get(), Storage, | ||||
3120 | ShouldCreate); | ||||
3121 | } | ||||
3122 | static DILocalVariable *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
3123 | MDString *Name, Metadata *File, unsigned Line, | ||||
3124 | Metadata *Type, unsigned Arg, DIFlags Flags, | ||||
3125 | uint32_t AlignInBits, Metadata *Annotations, | ||||
3126 | StorageType Storage, bool ShouldCreate = true); | ||||
3127 | |||||
3128 | TempDILocalVariable cloneImpl() const { | ||||
3129 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||
3130 | getLine(), getType(), getArg(), getFlags(), | ||||
3131 | getAlignInBits(), getAnnotations()); | ||||
3132 | } | ||||
3133 | |||||
3134 | public: | ||||
3135 | DEFINE_MDNODE_GET(DILocalVariable, | ||||
3136 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||
3137 | unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags, | ||||
3138 | uint32_t AlignInBits, DINodeArray Annotations), | ||||
3139 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, | ||||
3140 | Annotations)) | ||||
3141 | DEFINE_MDNODE_GET(DILocalVariable, | ||||
3142 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||
3143 | unsigned Line, Metadata *Type, unsigned Arg, | ||||
3144 | DIFlags Flags, uint32_t AlignInBits, Metadata *Annotations), | ||||
3145 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, | ||||
3146 | Annotations)) | ||||
3147 | |||||
3148 | TempDILocalVariable clone() const { return cloneImpl(); } | ||||
3149 | |||||
3150 | /// Get the local scope for this variable. | ||||
3151 | /// | ||||
3152 | /// Variables must be defined in a local scope. | ||||
3153 | DILocalScope *getScope() const { | ||||
3154 | return cast<DILocalScope>(DIVariable::getScope()); | ||||
3155 | } | ||||
3156 | |||||
3157 | bool isParameter() const { return Arg; } | ||||
3158 | unsigned getArg() const { return Arg; } | ||||
3159 | DIFlags getFlags() const { return Flags; } | ||||
3160 | |||||
3161 | DINodeArray getAnnotations() const { | ||||
3162 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||
3163 | } | ||||
3164 | Metadata *getRawAnnotations() const { return getOperand(4); } | ||||
3165 | |||||
3166 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
3167 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||
3168 | |||||
3169 | /// Check that a location is valid for this variable. | ||||
3170 | /// | ||||
3171 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||
3172 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||
3173 | /// to a \a DbgInfoIntrinsic.) | ||||
3174 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||
3175 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||
3176 | } | ||||
3177 | |||||
3178 | static bool classof(const Metadata *MD) { | ||||
3179 | return MD->getMetadataID() == DILocalVariableKind; | ||||
3180 | } | ||||
3181 | }; | ||||
3182 | |||||
3183 | /// Label. | ||||
3184 | /// | ||||
3185 | class DILabel : public DINode { | ||||
3186 | friend class LLVMContextImpl; | ||||
3187 | friend class MDNode; | ||||
3188 | |||||
3189 | unsigned Line; | ||||
3190 | |||||
3191 | DILabel(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
3192 | ArrayRef<Metadata *> Ops) | ||||
3193 | : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {} | ||||
3194 | ~DILabel() = default; | ||||
3195 | |||||
3196 | static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
3197 | StringRef Name, DIFile *File, unsigned Line, | ||||
3198 | StorageType Storage, | ||||
3199 | bool ShouldCreate = true) { | ||||
3200 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||
3201 | Line, Storage, ShouldCreate); | ||||
3202 | } | ||||
3203 | static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
3204 | MDString *Name, Metadata *File, unsigned Line, | ||||
3205 | StorageType Storage, | ||||
3206 | bool ShouldCreate = true); | ||||
3207 | |||||
3208 | TempDILabel cloneImpl() const { | ||||
3209 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||
3210 | getLine()); | ||||
3211 | } | ||||
3212 | |||||
3213 | public: | ||||
3214 | DEFINE_MDNODE_GET(DILabel, | ||||
3215 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||
3216 | unsigned Line), | ||||
3217 | (Scope, Name, File, Line)) | ||||
3218 | DEFINE_MDNODE_GET(DILabel, | ||||
3219 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||
3220 | unsigned Line), | ||||
3221 | (Scope, Name, File, Line)) | ||||
3222 | |||||
3223 | TempDILabel clone() const { return cloneImpl(); } | ||||
3224 | |||||
3225 | /// Get the local scope for this label. | ||||
3226 | /// | ||||
3227 | /// Labels must be defined in a local scope. | ||||
3228 | DILocalScope *getScope() const { | ||||
3229 | return cast_or_null<DILocalScope>(getRawScope()); | ||||
3230 | } | ||||
3231 | unsigned getLine() const { return Line; } | ||||
3232 | StringRef getName() const { return getStringOperand(1); } | ||||
3233 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3234 | |||||
3235 | Metadata *getRawScope() const { return getOperand(0); } | ||||
3236 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||
3237 | Metadata *getRawFile() const { return getOperand(2); } | ||||
3238 | |||||
3239 | /// Check that a location is valid for this label. | ||||
3240 | /// | ||||
3241 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||
3242 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||
3243 | /// to a \a DbgInfoIntrinsic.) | ||||
3244 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||
3245 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||
3246 | } | ||||
3247 | |||||
3248 | static bool classof(const Metadata *MD) { | ||||
3249 | return MD->getMetadataID() == DILabelKind; | ||||
3250 | } | ||||
3251 | }; | ||||
3252 | |||||
3253 | class DIObjCProperty : public DINode { | ||||
3254 | friend class LLVMContextImpl; | ||||
3255 | friend class MDNode; | ||||
3256 | |||||
3257 | unsigned Line; | ||||
3258 | unsigned Attributes; | ||||
3259 | |||||
3260 | DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
3261 | unsigned Attributes, ArrayRef<Metadata *> Ops) | ||||
3262 | : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, | ||||
3263 | Ops), | ||||
3264 | Line(Line), Attributes(Attributes) {} | ||||
3265 | ~DIObjCProperty() = default; | ||||
3266 | |||||
3267 | static DIObjCProperty * | ||||
3268 | getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, | ||||
3269 | StringRef GetterName, StringRef SetterName, unsigned Attributes, | ||||
3270 | DIType *Type, StorageType Storage, bool ShouldCreate = true) { | ||||
3271 | return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, | ||||
3272 | getCanonicalMDString(Context, GetterName), | ||||
3273 | getCanonicalMDString(Context, SetterName), Attributes, Type, | ||||
3274 | Storage, ShouldCreate); | ||||
3275 | } | ||||
3276 | static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, | ||||
3277 | Metadata *File, unsigned Line, | ||||
3278 | MDString *GetterName, MDString *SetterName, | ||||
3279 | unsigned Attributes, Metadata *Type, | ||||
3280 | StorageType Storage, bool ShouldCreate = true); | ||||
3281 | |||||
3282 | TempDIObjCProperty cloneImpl() const { | ||||
3283 | return getTemporary(getContext(), getName(), getFile(), getLine(), | ||||
3284 | getGetterName(), getSetterName(), getAttributes(), | ||||
3285 | getType()); | ||||
3286 | } | ||||
3287 | |||||
3288 | public: | ||||
3289 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||
3290 | (StringRef Name, DIFile *File, unsigned Line, | ||||
3291 | StringRef GetterName, StringRef SetterName, | ||||
3292 | unsigned Attributes, DIType *Type), | ||||
3293 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||
3294 | Type)) | ||||
3295 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||
3296 | (MDString * Name, Metadata *File, unsigned Line, | ||||
3297 | MDString *GetterName, MDString *SetterName, | ||||
3298 | unsigned Attributes, Metadata *Type), | ||||
3299 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||
3300 | Type)) | ||||
3301 | |||||
3302 | TempDIObjCProperty clone() const { return cloneImpl(); } | ||||
3303 | |||||
3304 | unsigned getLine() const { return Line; } | ||||
3305 | unsigned getAttributes() const { return Attributes; } | ||||
3306 | StringRef getName() const { return getStringOperand(0); } | ||||
3307 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3308 | StringRef getGetterName() const { return getStringOperand(2); } | ||||
3309 | StringRef getSetterName() const { return getStringOperand(3); } | ||||
3310 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
3311 | |||||
3312 | StringRef getFilename() const { | ||||
3313 | if (auto *F = getFile()) | ||||
3314 | return F->getFilename(); | ||||
3315 | return ""; | ||||
3316 | } | ||||
3317 | |||||
3318 | StringRef getDirectory() const { | ||||
3319 | if (auto *F = getFile()) | ||||
3320 | return F->getDirectory(); | ||||
3321 | return ""; | ||||
3322 | } | ||||
3323 | |||||
3324 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
3325 | Metadata *getRawFile() const { return getOperand(1); } | ||||
3326 | MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } | ||||
3327 | MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } | ||||
3328 | Metadata *getRawType() const { return getOperand(4); } | ||||
3329 | |||||
3330 | static bool classof(const Metadata *MD) { | ||||
3331 | return MD->getMetadataID() == DIObjCPropertyKind; | ||||
3332 | } | ||||
3333 | }; | ||||
3334 | |||||
3335 | /// An imported module (C++ using directive or similar). | ||||
3336 | class DIImportedEntity : public DINode { | ||||
3337 | friend class LLVMContextImpl; | ||||
3338 | friend class MDNode; | ||||
3339 | |||||
3340 | unsigned Line; | ||||
3341 | |||||
3342 | DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
3343 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||
3344 | : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} | ||||
3345 | ~DIImportedEntity() = default; | ||||
3346 | |||||
3347 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||
3348 | DIScope *Scope, DINode *Entity, DIFile *File, | ||||
3349 | unsigned Line, StringRef Name, | ||||
3350 | StorageType Storage, | ||||
3351 | bool ShouldCreate = true) { | ||||
3352 | return getImpl(Context, Tag, Scope, Entity, File, Line, | ||||
3353 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); | ||||
3354 | } | ||||
3355 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||
3356 | Metadata *Scope, Metadata *Entity, | ||||
3357 | Metadata *File, unsigned Line, | ||||
3358 | MDString *Name, StorageType Storage, | ||||
3359 | bool ShouldCreate = true); | ||||
3360 | |||||
3361 | TempDIImportedEntity cloneImpl() const { | ||||
3362 | return getTemporary(getContext(), getTag(), getScope(), getEntity(), | ||||
3363 | getFile(), getLine(), getName()); | ||||
3364 | } | ||||
3365 | |||||
3366 | public: | ||||
3367 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||
3368 | (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File, | ||||
3369 | unsigned Line, StringRef Name = ""), | ||||
3370 | (Tag, Scope, Entity, File, Line, Name)) | ||||
3371 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||
3372 | (unsigned Tag, Metadata *Scope, Metadata *Entity, | ||||
3373 | Metadata *File, unsigned Line, MDString *Name), | ||||
3374 | (Tag, Scope, Entity, File, Line, Name)) | ||||
3375 | |||||
3376 | TempDIImportedEntity clone() const { return cloneImpl(); } | ||||
3377 | |||||
3378 | unsigned getLine() const { return Line; } | ||||
3379 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
3380 | DINode *getEntity() const { return cast_or_null<DINode>(getRawEntity()); } | ||||
3381 | StringRef getName() const { return getStringOperand(2); } | ||||
3382 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3383 | |||||
3384 | Metadata *getRawScope() const { return getOperand(0); } | ||||
3385 | Metadata *getRawEntity() const { return getOperand(1); } | ||||
3386 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
3387 | Metadata *getRawFile() const { return getOperand(3); } | ||||
3388 | |||||
3389 | static bool classof(const Metadata *MD) { | ||||
3390 | return MD->getMetadataID() == DIImportedEntityKind; | ||||
3391 | } | ||||
3392 | }; | ||||
3393 | |||||
3394 | /// A pair of DIGlobalVariable and DIExpression. | ||||
3395 | class DIGlobalVariableExpression : public MDNode { | ||||
3396 | friend class LLVMContextImpl; | ||||
3397 | friend class MDNode; | ||||
3398 | |||||
3399 | DIGlobalVariableExpression(LLVMContext &C, StorageType Storage, | ||||
3400 | ArrayRef<Metadata *> Ops) | ||||
3401 | : MDNode(C, DIGlobalVariableExpressionKind, Storage, Ops) {} | ||||
3402 | ~DIGlobalVariableExpression() = default; | ||||
3403 | |||||
3404 | static DIGlobalVariableExpression * | ||||
3405 | getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Expression, | ||||
3406 | StorageType Storage, bool ShouldCreate = true); | ||||
3407 | |||||
3408 | TempDIGlobalVariableExpression cloneImpl() const { | ||||
3409 | return getTemporary(getContext(), getVariable(), getExpression()); | ||||
3410 | } | ||||
3411 | |||||
3412 | public: | ||||
3413 | DEFINE_MDNODE_GET(DIGlobalVariableExpression, | ||||
3414 | (Metadata * Variable, Metadata *Expression), | ||||
3415 | (Variable, Expression)) | ||||
3416 | |||||
3417 | TempDIGlobalVariableExpression clone() const { return cloneImpl(); } | ||||
3418 | |||||
3419 | Metadata *getRawVariable() const { return getOperand(0); } | ||||
3420 | |||||
3421 | DIGlobalVariable *getVariable() const { | ||||
3422 | return cast_or_null<DIGlobalVariable>(getRawVariable()); | ||||
3423 | } | ||||
3424 | |||||
3425 | Metadata *getRawExpression() const { return getOperand(1); } | ||||
3426 | |||||
3427 | DIExpression *getExpression() const { | ||||
3428 | return cast<DIExpression>(getRawExpression()); | ||||
3429 | } | ||||
3430 | |||||
3431 | static bool classof(const Metadata *MD) { | ||||
3432 | return MD->getMetadataID() == DIGlobalVariableExpressionKind; | ||||
3433 | } | ||||
3434 | }; | ||||
3435 | |||||
3436 | /// Macro Info DWARF-like metadata node. | ||||
3437 | /// | ||||
3438 | /// A metadata node with a DWARF macro info (i.e., a constant named | ||||
3439 | /// \c DW_MACINFO_*, defined in llvm/BinaryFormat/Dwarf.h). Called \a | ||||
3440 | /// DIMacroNode | ||||
3441 | /// because it's potentially used for non-DWARF output. | ||||
3442 | class DIMacroNode : public MDNode { | ||||
3443 | friend class LLVMContextImpl; | ||||
3444 | friend class MDNode; | ||||
3445 | |||||
3446 | protected: | ||||
3447 | DIMacroNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned MIType, | ||||
3448 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) | ||||
3449 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||
3450 | assert(MIType < 1u << 16)(static_cast <bool> (MIType < 1u << 16) ? void (0) : __assert_fail ("MIType < 1u << 16", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 3450, __extension__ __PRETTY_FUNCTION__)); | ||||
3451 | SubclassData16 = MIType; | ||||
3452 | } | ||||
3453 | ~DIMacroNode() = default; | ||||
3454 | |||||
3455 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||
3456 | return cast_or_null<Ty>(getOperand(I)); | ||||
3457 | } | ||||
3458 | |||||
3459 | StringRef getStringOperand(unsigned I) const { | ||||
3460 | if (auto *S = getOperandAs<MDString>(I)) | ||||
3461 | return S->getString(); | ||||
3462 | return StringRef(); | ||||
3463 | } | ||||
3464 | |||||
3465 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||
3466 | if (S.empty()) | ||||
3467 | return nullptr; | ||||
3468 | return MDString::get(Context, S); | ||||
3469 | } | ||||
3470 | |||||
3471 | public: | ||||
3472 | unsigned getMacinfoType() const { return SubclassData16; } | ||||
3473 | |||||
3474 | static bool classof(const Metadata *MD) { | ||||
3475 | switch (MD->getMetadataID()) { | ||||
3476 | default: | ||||
3477 | return false; | ||||
3478 | case DIMacroKind: | ||||
3479 | case DIMacroFileKind: | ||||
3480 | return true; | ||||
3481 | } | ||||
3482 | } | ||||
3483 | }; | ||||
3484 | |||||
3485 | class DIMacro : public DIMacroNode { | ||||
3486 | friend class LLVMContextImpl; | ||||
3487 | friend class MDNode; | ||||
3488 | |||||
3489 | unsigned Line; | ||||
3490 | |||||
3491 | DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line, | ||||
3492 | ArrayRef<Metadata *> Ops) | ||||
3493 | : DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {} | ||||
3494 | ~DIMacro() = default; | ||||
3495 | |||||
3496 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||
3497 | StringRef Name, StringRef Value, StorageType Storage, | ||||
3498 | bool ShouldCreate = true) { | ||||
3499 | return getImpl(Context, MIType, Line, getCanonicalMDString(Context, Name), | ||||
3500 | getCanonicalMDString(Context, Value), Storage, ShouldCreate); | ||||
3501 | } | ||||
3502 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||
3503 | MDString *Name, MDString *Value, StorageType Storage, | ||||
3504 | bool ShouldCreate = true); | ||||
3505 | |||||
3506 | TempDIMacro cloneImpl() const { | ||||
3507 | return getTemporary(getContext(), getMacinfoType(), getLine(), getName(), | ||||
3508 | getValue()); | ||||
3509 | } | ||||
3510 | |||||
3511 | public: | ||||
3512 | DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, StringRef Name, | ||||
3513 | StringRef Value = ""), | ||||
3514 | (MIType, Line, Name, Value)) | ||||
3515 | DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, MDString *Name, | ||||
3516 | MDString *Value), | ||||
3517 | (MIType, Line, Name, Value)) | ||||
3518 | |||||
3519 | TempDIMacro clone() const { return cloneImpl(); } | ||||
3520 | |||||
3521 | unsigned getLine() const { return Line; } | ||||
3522 | |||||
3523 | StringRef getName() const { return getStringOperand(0); } | ||||
3524 | StringRef getValue() const { return getStringOperand(1); } | ||||
3525 | |||||
3526 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
3527 | MDString *getRawValue() const { return getOperandAs<MDString>(1); } | ||||
3528 | |||||
3529 | static bool classof(const Metadata *MD) { | ||||
3530 | return MD->getMetadataID() == DIMacroKind; | ||||
3531 | } | ||||
3532 | }; | ||||
3533 | |||||
3534 | class DIMacroFile : public DIMacroNode { | ||||
3535 | friend class LLVMContextImpl; | ||||
3536 | friend class MDNode; | ||||
3537 | |||||
3538 | unsigned Line; | ||||
3539 | |||||
3540 | DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType, | ||||
3541 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||
3542 | : DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {} | ||||
3543 | ~DIMacroFile() = default; | ||||
3544 | |||||
3545 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||
3546 | unsigned Line, DIFile *File, | ||||
3547 | DIMacroNodeArray Elements, StorageType Storage, | ||||
3548 | bool ShouldCreate = true) { | ||||
3549 | return getImpl(Context, MIType, Line, static_cast<Metadata *>(File), | ||||
3550 | Elements.get(), Storage, ShouldCreate); | ||||
3551 | } | ||||
3552 | |||||
3553 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||
3554 | unsigned Line, Metadata *File, Metadata *Elements, | ||||
3555 | StorageType Storage, bool ShouldCreate = true); | ||||
3556 | |||||
3557 | TempDIMacroFile cloneImpl() const { | ||||
3558 | return getTemporary(getContext(), getMacinfoType(), getLine(), getFile(), | ||||
3559 | getElements()); | ||||
3560 | } | ||||
3561 | |||||
3562 | public: | ||||
3563 | DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, DIFile *File, | ||||
3564 | DIMacroNodeArray Elements), | ||||
3565 | (MIType, Line, File, Elements)) | ||||
3566 | DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, | ||||
3567 | Metadata *File, Metadata *Elements), | ||||
3568 | (MIType, Line, File, Elements)) | ||||
3569 | |||||
3570 | TempDIMacroFile clone() const { return cloneImpl(); } | ||||
3571 | |||||
3572 | void replaceElements(DIMacroNodeArray Elements) { | ||||
3573 | #ifndef NDEBUG | ||||
3574 | for (DIMacroNode *Op : getElements()) | ||||
3575 | assert(is_contained(Elements->operands(), Op) &&(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a macro node during macro node list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a macro node during macro node list replacement\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 3576, __extension__ __PRETTY_FUNCTION__)) | ||||
3576 | "Lost a macro node during macro node list replacement")(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a macro node during macro node list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a macro node during macro node list replacement\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/IR/DebugInfoMetadata.h" , 3576, __extension__ __PRETTY_FUNCTION__)); | ||||
3577 | #endif | ||||
3578 | replaceOperandWith(1, Elements.get()); | ||||
3579 | } | ||||
3580 | |||||
3581 | unsigned getLine() const { return Line; } | ||||
3582 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3583 | |||||
3584 | DIMacroNodeArray getElements() const { | ||||
3585 | return cast_or_null<MDTuple>(getRawElements()); | ||||
3586 | } | ||||
3587 | |||||
3588 | Metadata *getRawFile() const { return getOperand(0); } | ||||
3589 | Metadata *getRawElements() const { return getOperand(1); } | ||||
3590 | |||||
3591 | static bool classof(const Metadata *MD) { | ||||
3592 | return MD->getMetadataID() == DIMacroFileKind; | ||||
3593 | } | ||||
3594 | }; | ||||
3595 | |||||
3596 | /// List of ValueAsMetadata, to be used as an argument to a dbg.value | ||||
3597 | /// intrinsic. | ||||
3598 | class DIArgList : public MDNode { | ||||
3599 | friend class LLVMContextImpl; | ||||
3600 | friend class MDNode; | ||||
3601 | using iterator = SmallVectorImpl<ValueAsMetadata *>::iterator; | ||||
3602 | |||||
3603 | SmallVector<ValueAsMetadata *, 4> Args; | ||||
3604 | |||||
3605 | DIArgList(LLVMContext &C, StorageType Storage, | ||||
3606 | ArrayRef<ValueAsMetadata *> Args) | ||||
3607 | : MDNode(C, DIArgListKind, Storage, None), | ||||
3608 | Args(Args.begin(), Args.end()) { | ||||
3609 | track(); | ||||
3610 | } | ||||
3611 | ~DIArgList() { untrack(); } | ||||
3612 | |||||
3613 | static DIArgList *getImpl(LLVMContext &Context, | ||||
3614 | ArrayRef<ValueAsMetadata *> Args, | ||||
3615 | StorageType Storage, bool ShouldCreate = true); | ||||
3616 | |||||
3617 | TempDIArgList cloneImpl() const { | ||||
3618 | return getTemporary(getContext(), getArgs()); | ||||
3619 | } | ||||
3620 | |||||
3621 | void track(); | ||||
3622 | void untrack(); | ||||
3623 | void dropAllReferences(); | ||||
3624 | |||||
3625 | public: | ||||
3626 | DEFINE_MDNODE_GET(DIArgList, (ArrayRef<ValueAsMetadata *> Args), (Args)) | ||||
3627 | |||||
3628 | TempDIArgList clone() const { return cloneImpl(); } | ||||
3629 | |||||
3630 | ArrayRef<ValueAsMetadata *> getArgs() const { return Args; } | ||||
3631 | |||||
3632 | iterator args_begin() { return Args.begin(); } | ||||
3633 | iterator args_end() { return Args.end(); } | ||||
3634 | |||||
3635 | static bool classof(const Metadata *MD) { | ||||
3636 | return MD->getMetadataID() == DIArgListKind; | ||||
3637 | } | ||||
3638 | |||||
3639 | void handleChangedOperand(void *Ref, Metadata *New); | ||||
3640 | }; | ||||
3641 | |||||
3642 | /// Identifies a unique instance of a variable. | ||||
3643 | /// | ||||
3644 | /// Storage for identifying a potentially inlined instance of a variable, | ||||
3645 | /// or a fragment thereof. This guarantees that exactly one variable instance | ||||
3646 | /// may be identified by this class, even when that variable is a fragment of | ||||
3647 | /// an aggregate variable and/or there is another inlined instance of the same | ||||
3648 | /// source code variable nearby. | ||||
3649 | /// This class does not necessarily uniquely identify that variable: it is | ||||
3650 | /// possible that a DebugVariable with different parameters may point to the | ||||
3651 | /// same variable instance, but not that one DebugVariable points to multiple | ||||
3652 | /// variable instances. | ||||
3653 | class DebugVariable { | ||||
3654 | using FragmentInfo = DIExpression::FragmentInfo; | ||||
3655 | |||||
3656 | const DILocalVariable *Variable; | ||||
3657 | Optional<FragmentInfo> Fragment; | ||||
3658 | const DILocation *InlinedAt; | ||||
3659 | |||||
3660 | /// Fragment that will overlap all other fragments. Used as default when | ||||
3661 | /// caller demands a fragment. | ||||
3662 | static const FragmentInfo DefaultFragment; | ||||
3663 | |||||
3664 | public: | ||||
3665 | DebugVariable(const DILocalVariable *Var, Optional<FragmentInfo> FragmentInfo, | ||||
3666 | const DILocation *InlinedAt) | ||||
3667 | : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} | ||||
3668 | |||||
3669 | DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, | ||||
3670 | const DILocation *InlinedAt) | ||||
3671 | : Variable(Var), | ||||
3672 | Fragment(DIExpr ? DIExpr->getFragmentInfo() : NoneType()), | ||||
3673 | InlinedAt(InlinedAt) {} | ||||
3674 | |||||
3675 | const DILocalVariable *getVariable() const { return Variable; } | ||||
3676 | Optional<FragmentInfo> getFragment() const { return Fragment; } | ||||
3677 | const DILocation *getInlinedAt() const { return InlinedAt; } | ||||
3678 | |||||
3679 | FragmentInfo getFragmentOrDefault() const { | ||||
3680 | return Fragment.getValueOr(DefaultFragment); | ||||
3681 | } | ||||
3682 | |||||
3683 | static bool isDefaultFragment(const FragmentInfo F) { | ||||
3684 | return F == DefaultFragment; | ||||
3685 | } | ||||
3686 | |||||
3687 | bool operator==(const DebugVariable &Other) const { | ||||
3688 | return std::tie(Variable, Fragment, InlinedAt) == | ||||
3689 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||
3690 | } | ||||
3691 | |||||
3692 | bool operator<(const DebugVariable &Other) const { | ||||
3693 | return std::tie(Variable, Fragment, InlinedAt) < | ||||
3694 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||
3695 | } | ||||
3696 | }; | ||||
3697 | |||||
3698 | template <> struct DenseMapInfo<DebugVariable> { | ||||
3699 | using FragmentInfo = DIExpression::FragmentInfo; | ||||
3700 | |||||
3701 | /// Empty key: no key should be generated that has no DILocalVariable. | ||||
3702 | static inline DebugVariable getEmptyKey() { | ||||
3703 | return DebugVariable(nullptr, NoneType(), nullptr); | ||||
3704 | } | ||||
3705 | |||||
3706 | /// Difference in tombstone is that the Optional is meaningful. | ||||
3707 | static inline DebugVariable getTombstoneKey() { | ||||
3708 | return DebugVariable(nullptr, {{0, 0}}, nullptr); | ||||
3709 | } | ||||
3710 | |||||
3711 | static unsigned getHashValue(const DebugVariable &D) { | ||||
3712 | unsigned HV = 0; | ||||
3713 | const Optional<FragmentInfo> Fragment = D.getFragment(); | ||||
3714 | if (Fragment) | ||||
3715 | HV = DenseMapInfo<FragmentInfo>::getHashValue(*Fragment); | ||||
3716 | |||||
3717 | return hash_combine(D.getVariable(), HV, D.getInlinedAt()); | ||||
3718 | } | ||||
3719 | |||||
3720 | static bool isEqual(const DebugVariable &A, const DebugVariable &B) { | ||||
3721 | return A == B; | ||||
3722 | } | ||||
3723 | }; | ||||
3724 | |||||
3725 | } // end namespace llvm | ||||
3726 | |||||
3727 | #undef DEFINE_MDNODE_GET_UNPACK_IMPL | ||||
3728 | #undef DEFINE_MDNODE_GET_UNPACK | ||||
3729 | #undef DEFINE_MDNODE_GET | ||||
3730 | |||||
3731 | #endif // LLVM_IR_DEBUGINFOMETADATA_H |