File: | src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/IR/Verifier.cpp |
Warning: | line 2590, 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 &&((void)0) | ||||
361 | "An instance of this class only works with a specific module!")((void)0); | ||||
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")__builtin_unreachable(); | ||||
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!")((void)0); | ||||
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")((void)0); | ||||
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.hasFnAttribute(Attr)) { | ||||
1828 | StringRef S = Attrs.getAttribute(AttributeList::FunctionIndex, Attr) | ||||
1829 | .getValueAsString(); | ||||
1830 | unsigned N; | ||||
1831 | if (S.getAsInteger(10, N)) | ||||
1832 | CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, V); | ||||
1833 | } | ||||
1834 | } | ||||
1835 | |||||
1836 | // Check parameter attributes against a function type. | ||||
1837 | // The value V is printed in error messages. | ||||
1838 | void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
1839 | const Value *V, bool IsIntrinsic) { | ||||
1840 | if (Attrs.isEmpty()) | ||||
1841 | return; | ||||
1842 | |||||
1843 | if (AttributeListsVisited.insert(Attrs.getRawPointer()).second) { | ||||
1844 | Assert(Attrs.hasParentContext(Context),do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false) | ||||
1845 | "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); | ||||
1846 | for (const auto &AttrSet : Attrs) { | ||||
1847 | 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) | ||||
1848 | "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); | ||||
1849 | for (const auto &A : AttrSet) { | ||||
1850 | Assert(A.hasParentContext(Context),do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false) | ||||
1851 | "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); | ||||
1852 | } | ||||
1853 | } | ||||
1854 | } | ||||
1855 | |||||
1856 | bool SawNest = false; | ||||
1857 | bool SawReturned = false; | ||||
1858 | bool SawSRet = false; | ||||
1859 | bool SawSwiftSelf = false; | ||||
1860 | bool SawSwiftAsync = false; | ||||
1861 | bool SawSwiftError = false; | ||||
1862 | |||||
1863 | // Verify return value attributes. | ||||
1864 | AttributeSet RetAttrs = Attrs.getRetAttributes(); | ||||
1865 | for (Attribute RetAttr : RetAttrs) | ||||
1866 | 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) | ||||
1867 | 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) | ||||
1868 | "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) | ||||
1869 | "' 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) | ||||
1870 | V)do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false); | ||||
1871 | |||||
1872 | verifyParameterAttrs(RetAttrs, FT->getReturnType(), V); | ||||
1873 | |||||
1874 | // Verify parameter attributes. | ||||
1875 | for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { | ||||
1876 | Type *Ty = FT->getParamType(i); | ||||
1877 | AttributeSet ArgAttrs = Attrs.getParamAttributes(i); | ||||
1878 | |||||
1879 | if (!IsIntrinsic) { | ||||
1880 | Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg),do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics",V); return; } } while (false) | ||||
1881 | "immarg attribute only applies to intrinsics",V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics",V); return; } } while (false); | ||||
1882 | Assert(!ArgAttrs.hasAttribute(Attribute::ElementType),do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics." , V); return; } } while (false) | ||||
1883 | "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); | ||||
1884 | } | ||||
1885 | |||||
1886 | verifyParameterAttrs(ArgAttrs, Ty, V); | ||||
1887 | |||||
1888 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
1889 | 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); | ||||
1890 | SawNest = true; | ||||
1891 | } | ||||
1892 | |||||
1893 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
1894 | Assert(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false) | ||||
1895 | V)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false); | ||||
1896 | Assert(Ty->canLosslesslyBitCastTo(FT->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
1897 | "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) | ||||
1898 | V)do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false); | ||||
1899 | SawReturned = true; | ||||
1900 | } | ||||
1901 | |||||
1902 | if (ArgAttrs.hasAttribute(Attribute::StructRet)) { | ||||
1903 | Assert(!SawSRet, "Cannot have multiple 'sret' parameters!", V)do { if (!(!SawSRet)) { CheckFailed("Cannot have multiple 'sret' parameters!" , V); return; } } while (false); | ||||
1904 | 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) | ||||
1905 | "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); | ||||
1906 | SawSRet = true; | ||||
1907 | } | ||||
1908 | |||||
1909 | if (ArgAttrs.hasAttribute(Attribute::SwiftSelf)) { | ||||
1910 | Assert(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V)do { if (!(!SawSwiftSelf)) { CheckFailed("Cannot have multiple 'swiftself' parameters!" , V); return; } } while (false); | ||||
1911 | SawSwiftSelf = true; | ||||
1912 | } | ||||
1913 | |||||
1914 | if (ArgAttrs.hasAttribute(Attribute::SwiftAsync)) { | ||||
1915 | Assert(!SawSwiftAsync, "Cannot have multiple 'swiftasync' parameters!", V)do { if (!(!SawSwiftAsync)) { CheckFailed("Cannot have multiple 'swiftasync' parameters!" , V); return; } } while (false); | ||||
1916 | SawSwiftAsync = true; | ||||
1917 | } | ||||
1918 | |||||
1919 | if (ArgAttrs.hasAttribute(Attribute::SwiftError)) { | ||||
1920 | Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!",do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false) | ||||
1921 | V)do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false); | ||||
1922 | SawSwiftError = true; | ||||
1923 | } | ||||
1924 | |||||
1925 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) { | ||||
1926 | Assert(i == FT->getNumParams() - 1,do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false) | ||||
1927 | "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); | ||||
1928 | } | ||||
1929 | } | ||||
1930 | |||||
1931 | if (!Attrs.hasAttributes(AttributeList::FunctionIndex)) | ||||
1932 | return; | ||||
1933 | |||||
1934 | verifyAttributeTypes(Attrs.getFnAttributes(), V); | ||||
1935 | for (Attribute FnAttr : Attrs.getFnAttributes()) | ||||
1936 | Assert(FnAttr.isStringAttribute() ||do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
1937 | 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) | ||||
1938 | "Attribute '" + FnAttr.getAsString() +do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
1939 | "' 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) | ||||
1940 | V)do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false); | ||||
1941 | |||||
1942 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false) | ||||
1943 | Attrs.hasFnAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false) | ||||
1944 | "Attributes 'readnone and readonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false); | ||||
1945 | |||||
1946 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readnone and writeonly' are incompatible!", V); return ; } } while (false) | ||||
1947 | Attrs.hasFnAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readnone and writeonly' are incompatible!", V); return ; } } while (false) | ||||
1948 | "Attributes 'readnone and writeonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readnone and writeonly' are incompatible!", V); return ; } } while (false); | ||||
1949 | |||||
1950 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadOnly) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadOnly) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readonly and writeonly' are incompatible!", V); return ; } } while (false) | ||||
1951 | Attrs.hasFnAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadOnly) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readonly and writeonly' are incompatible!", V); return ; } } while (false) | ||||
1952 | "Attributes 'readonly and writeonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadOnly) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readonly and writeonly' are incompatible!", V); return ; } } while (false); | ||||
1953 | |||||
1954 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1955 | Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1956 | "Attributes 'readnone and inaccessiblemem_or_argmemonly' are "do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1957 | "incompatible!",do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
1958 | V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false); | ||||
1959 | |||||
1960 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false) | ||||
1961 | Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false) | ||||
1962 | "Attributes 'readnone and inaccessiblememonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false); | ||||
1963 | |||||
1964 | Assert(!(Attrs.hasFnAttribute(Attribute::NoInline) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::NoInline) && Attrs.hasFnAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes 'noinline and alwaysinline' are incompatible!", V ); return; } } while (false) | ||||
1965 | Attrs.hasFnAttribute(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasFnAttribute(Attribute::NoInline) && Attrs.hasFnAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes 'noinline and alwaysinline' are incompatible!", V ); return; } } while (false) | ||||
1966 | "Attributes 'noinline and alwaysinline' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::NoInline) && Attrs.hasFnAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes 'noinline and alwaysinline' are incompatible!", V ); return; } } while (false); | ||||
1967 | |||||
1968 | if (Attrs.hasFnAttribute(Attribute::OptimizeNone)) { | ||||
1969 | Assert(Attrs.hasFnAttribute(Attribute::NoInline),do { if (!(Attrs.hasFnAttribute(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false) | ||||
1970 | "Attribute 'optnone' requires 'noinline'!", V)do { if (!(Attrs.hasFnAttribute(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false); | ||||
1971 | |||||
1972 | Assert(!Attrs.hasFnAttribute(Attribute::OptimizeForSize),do { if (!(!Attrs.hasFnAttribute(Attribute::OptimizeForSize)) ) { CheckFailed("Attributes 'optsize and optnone' are incompatible!" , V); return; } } while (false) | ||||
1973 | "Attributes 'optsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttribute(Attribute::OptimizeForSize)) ) { CheckFailed("Attributes 'optsize and optnone' are incompatible!" , V); return; } } while (false); | ||||
1974 | |||||
1975 | Assert(!Attrs.hasFnAttribute(Attribute::MinSize),do { if (!(!Attrs.hasFnAttribute(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
1976 | "Attributes 'minsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttribute(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
1977 | } | ||||
1978 | |||||
1979 | if (Attrs.hasFnAttribute(Attribute::JumpTable)) { | ||||
1980 | const GlobalValue *GV = cast<GlobalValue>(V); | ||||
1981 | Assert(GV->hasGlobalUnnamedAddr(),do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false) | ||||
1982 | "Attribute 'jumptable' requires 'unnamed_addr'", V)do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false); | ||||
1983 | } | ||||
1984 | |||||
1985 | if (Attrs.hasFnAttribute(Attribute::AllocSize)) { | ||||
1986 | std::pair<unsigned, Optional<unsigned>> Args = | ||||
1987 | Attrs.getAllocSizeArgs(AttributeList::FunctionIndex); | ||||
1988 | |||||
1989 | auto CheckParam = [&](StringRef Name, unsigned ParamNo) { | ||||
1990 | if (ParamNo >= FT->getNumParams()) { | ||||
1991 | CheckFailed("'allocsize' " + Name + " argument is out of bounds", V); | ||||
1992 | return false; | ||||
1993 | } | ||||
1994 | |||||
1995 | if (!FT->getParamType(ParamNo)->isIntegerTy()) { | ||||
1996 | CheckFailed("'allocsize' " + Name + | ||||
1997 | " argument must refer to an integer parameter", | ||||
1998 | V); | ||||
1999 | return false; | ||||
2000 | } | ||||
2001 | |||||
2002 | return true; | ||||
2003 | }; | ||||
2004 | |||||
2005 | if (!CheckParam("element size", Args.first)) | ||||
2006 | return; | ||||
2007 | |||||
2008 | if (Args.second && !CheckParam("number of elements", *Args.second)) | ||||
2009 | return; | ||||
2010 | } | ||||
2011 | |||||
2012 | if (Attrs.hasFnAttribute(Attribute::VScaleRange)) { | ||||
2013 | std::pair<unsigned, unsigned> Args = | ||||
2014 | Attrs.getVScaleRangeArgs(AttributeList::FunctionIndex); | ||||
2015 | |||||
2016 | if (Args.first > Args.second && Args.second != 0) | ||||
2017 | CheckFailed("'vscale_range' minimum cannot be greater than maximum", V); | ||||
2018 | } | ||||
2019 | |||||
2020 | if (Attrs.hasFnAttribute("frame-pointer")) { | ||||
2021 | StringRef FP = Attrs.getAttribute(AttributeList::FunctionIndex, | ||||
2022 | "frame-pointer").getValueAsString(); | ||||
2023 | if (FP != "all" && FP != "non-leaf" && FP != "none") | ||||
2024 | CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V); | ||||
2025 | } | ||||
2026 | |||||
2027 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V); | ||||
2028 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V); | ||||
2029 | checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", V); | ||||
2030 | } | ||||
2031 | |||||
2032 | void Verifier::verifyFunctionMetadata( | ||||
2033 | ArrayRef<std::pair<unsigned, MDNode *>> MDs) { | ||||
2034 | for (const auto &Pair : MDs) { | ||||
2035 | if (Pair.first == LLVMContext::MD_prof) { | ||||
2036 | MDNode *MD = Pair.second; | ||||
2037 | Assert(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
2038 | "!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); | ||||
2039 | |||||
2040 | // Check first operand. | ||||
2041 | 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) | ||||
2042 | MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
2043 | 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) | ||||
2044 | "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); | ||||
2045 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
2046 | StringRef ProfName = MDS->getString(); | ||||
2047 | 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) | ||||
2048 | 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) | ||||
2049 | "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) | ||||
2050 | " 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) | ||||
2051 | 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); | ||||
2052 | |||||
2053 | // Check second operand. | ||||
2054 | 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) | ||||
2055 | MD)do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
2056 | 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) | ||||
2057 | "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); | ||||
2058 | } | ||||
2059 | } | ||||
2060 | } | ||||
2061 | |||||
2062 | void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { | ||||
2063 | if (!ConstantExprVisited.insert(EntryC).second) | ||||
2064 | return; | ||||
2065 | |||||
2066 | SmallVector<const Constant *, 16> Stack; | ||||
2067 | Stack.push_back(EntryC); | ||||
2068 | |||||
2069 | while (!Stack.empty()) { | ||||
2070 | const Constant *C = Stack.pop_back_val(); | ||||
2071 | |||||
2072 | // Check this constant expression. | ||||
2073 | if (const auto *CE = dyn_cast<ConstantExpr>(C)) | ||||
2074 | visitConstantExpr(CE); | ||||
2075 | |||||
2076 | if (const auto *GV = dyn_cast<GlobalValue>(C)) { | ||||
2077 | // Global Values get visited separately, but we do need to make sure | ||||
2078 | // that the global value is in the correct module | ||||
2079 | 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) | ||||
2080 | EntryC, &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false); | ||||
2081 | continue; | ||||
2082 | } | ||||
2083 | |||||
2084 | // Visit all sub-expressions. | ||||
2085 | for (const Use &U : C->operands()) { | ||||
2086 | const auto *OpC = dyn_cast<Constant>(U); | ||||
2087 | if (!OpC) | ||||
2088 | continue; | ||||
2089 | if (!ConstantExprVisited.insert(OpC).second) | ||||
2090 | continue; | ||||
2091 | Stack.push_back(OpC); | ||||
2092 | } | ||||
2093 | } | ||||
2094 | } | ||||
2095 | |||||
2096 | void Verifier::visitConstantExpr(const ConstantExpr *CE) { | ||||
2097 | if (CE->getOpcode() == Instruction::BitCast) | ||||
2098 | 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) | ||||
2099 | CE->getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
2100 | "Invalid bitcast", CE)do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false); | ||||
2101 | } | ||||
2102 | |||||
2103 | bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) { | ||||
2104 | // There shouldn't be more attribute sets than there are parameters plus the | ||||
2105 | // function and return value. | ||||
2106 | return Attrs.getNumAttrSets() <= Params + 2; | ||||
2107 | } | ||||
2108 | |||||
2109 | /// Verify that statepoint intrinsic is well formed. | ||||
2110 | void Verifier::verifyStatepoint(const CallBase &Call) { | ||||
2111 | assert(Call.getCalledFunction() &&((void)0) | ||||
2112 | Call.getCalledFunction()->getIntrinsicID() ==((void)0) | ||||
2113 | Intrinsic::experimental_gc_statepoint)((void)0); | ||||
2114 | |||||
2115 | 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) | ||||
2116 | !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) | ||||
2117 | "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) | ||||
2118 | "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) | ||||
2119 | 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); | ||||
2120 | |||||
2121 | const int64_t NumPatchBytes = | ||||
2122 | cast<ConstantInt>(Call.getArgOperand(1))->getSExtValue(); | ||||
2123 | assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!")((void)0); | ||||
2124 | Assert(NumPatchBytes >= 0,do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
2125 | "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) | ||||
2126 | "positive",do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
2127 | Call)do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false); | ||||
2128 | |||||
2129 | const Value *Target = Call.getArgOperand(2); | ||||
2130 | auto *PT = dyn_cast<PointerType>(Target->getType()); | ||||
2131 | 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) | ||||
2132 | "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); | ||||
2133 | FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType()); | ||||
2134 | |||||
2135 | const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue(); | ||||
2136 | Assert(NumCallArgs >= 0,do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
2137 | "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) | ||||
2138 | "must be positive",do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
2139 | Call)do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false); | ||||
2140 | const int NumParams = (int)TargetFuncType->getNumParams(); | ||||
2141 | if (TargetFuncType->isVarArg()) { | ||||
2142 | Assert(NumCallArgs >= NumParams,do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false) | ||||
2143 | "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); | ||||
2144 | |||||
2145 | // TODO: Remove this limitation | ||||
2146 | 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) | ||||
2147 | "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) | ||||
2148 | "vararg functions yet",do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
2149 | Call)do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false); | ||||
2150 | } else | ||||
2151 | Assert(NumCallArgs == NumParams,do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false) | ||||
2152 | "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); | ||||
2153 | |||||
2154 | const uint64_t Flags | ||||
2155 | = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue(); | ||||
2156 | 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) | ||||
2157 | "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); | ||||
2158 | |||||
2159 | // Verify that the types of the call parameter arguments match | ||||
2160 | // the type of the wrapped callee. | ||||
2161 | AttributeList Attrs = Call.getAttributes(); | ||||
2162 | for (int i = 0; i < NumParams; i++) { | ||||
2163 | Type *ParamType = TargetFuncType->getParamType(i); | ||||
2164 | Type *ArgType = Call.getArgOperand(5 + i)->getType(); | ||||
2165 | Assert(ArgType == ParamType,do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
2166 | "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) | ||||
2167 | "function type",do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
2168 | Call)do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false); | ||||
2169 | |||||
2170 | if (TargetFuncType->isVarArg()) { | ||||
2171 | AttributeSet ArgAttrs = Attrs.getParamAttributes(5 + i); | ||||
2172 | 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) | ||||
2173 | "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) | ||||
2174 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
2175 | } | ||||
2176 | } | ||||
2177 | |||||
2178 | const int EndCallArgsInx = 4 + NumCallArgs; | ||||
2179 | |||||
2180 | const Value *NumTransitionArgsV = Call.getArgOperand(EndCallArgsInx + 1); | ||||
2181 | Assert(isa<ConstantInt>(NumTransitionArgsV),do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2182 | "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) | ||||
2183 | "must be constant integer",do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2184 | Call)do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false); | ||||
2185 | const int NumTransitionArgs = | ||||
2186 | cast<ConstantInt>(NumTransitionArgsV)->getZExtValue(); | ||||
2187 | Assert(NumTransitionArgs == 0,do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false) | ||||
2188 | "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); | ||||
2189 | const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; | ||||
2190 | |||||
2191 | const Value *NumDeoptArgsV = Call.getArgOperand(EndTransitionArgsInx + 1); | ||||
2192 | Assert(isa<ConstantInt>(NumDeoptArgsV),do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2193 | "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) | ||||
2194 | "must be constant integer",do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2195 | Call)do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false); | ||||
2196 | const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue(); | ||||
2197 | Assert(NumDeoptArgs == 0,do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false) | ||||
2198 | "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); | ||||
2199 | |||||
2200 | const int ExpectedNumArgs = 7 + NumCallArgs; | ||||
2201 | Assert(ExpectedNumArgs == (int)Call.arg_size(),do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false) | ||||
2202 | "gc.statepoint too many arguments", Call)do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false); | ||||
2203 | |||||
2204 | // Check that the only uses of this gc.statepoint are gc.result or | ||||
2205 | // gc.relocate calls which are tied to this statepoint and thus part | ||||
2206 | // of the same statepoint sequence | ||||
2207 | for (const User *U : Call.users()) { | ||||
2208 | const CallInst *UserCall = dyn_cast<const CallInst>(U); | ||||
2209 | Assert(UserCall, "illegal use of statepoint token", Call, U)do { if (!(UserCall)) { CheckFailed("illegal use of statepoint token" , Call, U); return; } } while (false); | ||||
2210 | if (!UserCall) | ||||
2211 | continue; | ||||
2212 | 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) | ||||
2213 | "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) | ||||
2214 | "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) | ||||
2215 | 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); | ||||
2216 | if (isa<GCResultInst>(UserCall)) { | ||||
2217 | Assert(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
2218 | "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); | ||||
2219 | } else if (isa<GCRelocateInst>(Call)) { | ||||
2220 | Assert(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
2221 | "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); | ||||
2222 | } | ||||
2223 | } | ||||
2224 | |||||
2225 | // Note: It is legal for a single derived pointer to be listed multiple | ||||
2226 | // times. It's non-optimal, but it is legal. It can also happen after | ||||
2227 | // insertion if we strip a bitcast away. | ||||
2228 | // Note: It is really tempting to check that each base is relocated and | ||||
2229 | // that a derived pointer is never reused as a base pointer. This turns | ||||
2230 | // out to be problematic since optimizations run after safepoint insertion | ||||
2231 | // can recognize equality properties that the insertion logic doesn't know | ||||
2232 | // about. See example statepoint.ll in the verifier subdirectory | ||||
2233 | } | ||||
2234 | |||||
2235 | void Verifier::verifyFrameRecoverIndices() { | ||||
2236 | for (auto &Counts : FrameEscapeInfo) { | ||||
2237 | Function *F = Counts.first; | ||||
2238 | unsigned EscapedObjectCount = Counts.second.first; | ||||
2239 | unsigned MaxRecoveredIndex = Counts.second.second; | ||||
2240 | 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) | ||||
2241 | "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) | ||||
2242 | "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) | ||||
2243 | "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) | ||||
2244 | 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); | ||||
2245 | } | ||||
2246 | } | ||||
2247 | |||||
2248 | static Instruction *getSuccPad(Instruction *Terminator) { | ||||
2249 | BasicBlock *UnwindDest; | ||||
2250 | if (auto *II = dyn_cast<InvokeInst>(Terminator)) | ||||
2251 | UnwindDest = II->getUnwindDest(); | ||||
2252 | else if (auto *CSI = dyn_cast<CatchSwitchInst>(Terminator)) | ||||
2253 | UnwindDest = CSI->getUnwindDest(); | ||||
2254 | else | ||||
2255 | UnwindDest = cast<CleanupReturnInst>(Terminator)->getUnwindDest(); | ||||
2256 | return UnwindDest->getFirstNonPHI(); | ||||
2257 | } | ||||
2258 | |||||
2259 | void Verifier::verifySiblingFuncletUnwinds() { | ||||
2260 | SmallPtrSet<Instruction *, 8> Visited; | ||||
2261 | SmallPtrSet<Instruction *, 8> Active; | ||||
2262 | for (const auto &Pair : SiblingFuncletInfo) { | ||||
2263 | Instruction *PredPad = Pair.first; | ||||
2264 | if (Visited.count(PredPad)) | ||||
2265 | continue; | ||||
2266 | Active.insert(PredPad); | ||||
2267 | Instruction *Terminator = Pair.second; | ||||
2268 | do { | ||||
2269 | Instruction *SuccPad = getSuccPad(Terminator); | ||||
2270 | if (Active.count(SuccPad)) { | ||||
2271 | // Found a cycle; report error | ||||
2272 | Instruction *CyclePad = SuccPad; | ||||
2273 | SmallVector<Instruction *, 8> CycleNodes; | ||||
2274 | do { | ||||
2275 | CycleNodes.push_back(CyclePad); | ||||
2276 | Instruction *CycleTerminator = SiblingFuncletInfo[CyclePad]; | ||||
2277 | if (CycleTerminator != CyclePad) | ||||
2278 | CycleNodes.push_back(CycleTerminator); | ||||
2279 | CyclePad = getSuccPad(CycleTerminator); | ||||
2280 | } while (CyclePad != SuccPad); | ||||
2281 | 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) | ||||
2282 | ArrayRef<Instruction *>(CycleNodes))do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false); | ||||
2283 | } | ||||
2284 | // Don't re-walk a node we've already checked | ||||
2285 | if (!Visited.insert(SuccPad).second) | ||||
2286 | break; | ||||
2287 | // Walk to this successor if it has a map entry. | ||||
2288 | PredPad = SuccPad; | ||||
2289 | auto TermI = SiblingFuncletInfo.find(PredPad); | ||||
2290 | if (TermI == SiblingFuncletInfo.end()) | ||||
2291 | break; | ||||
2292 | Terminator = TermI->second; | ||||
2293 | Active.insert(PredPad); | ||||
2294 | } while (true); | ||||
2295 | // Each node only has one successor, so we've walked all the active | ||||
2296 | // nodes' successors. | ||||
2297 | Active.clear(); | ||||
2298 | } | ||||
2299 | } | ||||
2300 | |||||
2301 | // visitFunction - Verify that a function is ok. | ||||
2302 | // | ||||
2303 | void Verifier::visitFunction(const Function &F) { | ||||
2304 | visitGlobalValue(F); | ||||
2305 | |||||
2306 | // Check function arguments. | ||||
2307 | FunctionType *FT = F.getFunctionType(); | ||||
2308 | unsigned NumArgs = F.arg_size(); | ||||
2309 | |||||
2310 | Assert(&Context == &F.getContext(),do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false) | ||||
| |||||
2311 | "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); | ||||
2312 | |||||
2313 | 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); | ||||
2314 | Assert(FT->getNumParams() == NumArgs,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
2315 | "# 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) | ||||
2316 | FT)do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false); | ||||
2317 | 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) | ||||
2318 | 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) | ||||
2319 | "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); | ||||
2320 | |||||
2321 | Assert(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false) | ||||
2322 | "Invalid struct return type!", &F)do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false); | ||||
2323 | |||||
2324 | AttributeList Attrs = F.getAttributes(); | ||||
2325 | |||||
2326 | Assert(verifyAttributeCount(Attrs, FT->getNumParams()),do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false) | ||||
2327 | "Attribute after last parameter!", &F)do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false); | ||||
2328 | |||||
2329 | bool IsIntrinsic = F.isIntrinsic(); | ||||
2330 | |||||
2331 | // Check function attributes. | ||||
2332 | verifyFunctionAttrs(FT, Attrs, &F, IsIntrinsic); | ||||
2333 | |||||
2334 | // On function declarations/definitions, we do not support the builtin | ||||
2335 | // attribute. We do not check this in VerifyFunctionAttrs since that is | ||||
2336 | // checking for Attributes that can/can not ever be on functions. | ||||
2337 | Assert(!Attrs.hasFnAttribute(Attribute::Builtin),do { if (!(!Attrs.hasFnAttribute(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false) | ||||
2338 | "Attribute 'builtin' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasFnAttribute(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false); | ||||
2339 | |||||
2340 | 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) | ||||
2341 | "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); | ||||
2342 | |||||
2343 | // Check that this function meets the restrictions on this calling convention. | ||||
2344 | // Sometimes varargs is used for perfectly forwarding thunks, so some of these | ||||
2345 | // restrictions can be lifted. | ||||
2346 | switch (F.getCallingConv()) { | ||||
2347 | default: | ||||
2348 | case CallingConv::C: | ||||
2349 | break; | ||||
2350 | case CallingConv::X86_INTR: { | ||||
2351 | Assert(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute::ByVal),do { if (!(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute ::ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false) | ||||
2352 | "Calling convention parameter requires byval", &F)do { if (!(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute ::ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false); | ||||
2353 | break; | ||||
2354 | } | ||||
2355 | case CallingConv::AMDGPU_KERNEL: | ||||
2356 | case CallingConv::SPIR_KERNEL: | ||||
2357 | Assert(F.getReturnType()->isVoidTy(),do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false) | ||||
2358 | "Calling convention requires void return type", &F)do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false); | ||||
2359 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2360 | case CallingConv::AMDGPU_VS: | ||||
2361 | case CallingConv::AMDGPU_HS: | ||||
2362 | case CallingConv::AMDGPU_GS: | ||||
2363 | case CallingConv::AMDGPU_PS: | ||||
2364 | case CallingConv::AMDGPU_CS: | ||||
2365 | Assert(!F.hasStructRetAttr(),do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false) | ||||
2366 | "Calling convention does not allow sret", &F)do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false); | ||||
2367 | if (F.getCallingConv() != CallingConv::SPIR_KERNEL) { | ||||
2368 | const unsigned StackAS = DL.getAllocaAddrSpace(); | ||||
2369 | unsigned i = 0; | ||||
2370 | for (const Argument &Arg : F.args()) { | ||||
2371 | Assert(!Attrs.hasParamAttribute(i, Attribute::ByVal),do { if (!(!Attrs.hasParamAttribute(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false) | ||||
2372 | "Calling convention disallows byval", &F)do { if (!(!Attrs.hasParamAttribute(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false); | ||||
2373 | Assert(!Attrs.hasParamAttribute(i, Attribute::Preallocated),do { if (!(!Attrs.hasParamAttribute(i, Attribute::Preallocated ))) { CheckFailed("Calling convention disallows preallocated" , &F); return; } } while (false) | ||||
2374 | "Calling convention disallows preallocated", &F)do { if (!(!Attrs.hasParamAttribute(i, Attribute::Preallocated ))) { CheckFailed("Calling convention disallows preallocated" , &F); return; } } while (false); | ||||
2375 | Assert(!Attrs.hasParamAttribute(i, Attribute::InAlloca),do { if (!(!Attrs.hasParamAttribute(i, Attribute::InAlloca))) { CheckFailed("Calling convention disallows inalloca", & F); return; } } while (false) | ||||
2376 | "Calling convention disallows inalloca", &F)do { if (!(!Attrs.hasParamAttribute(i, Attribute::InAlloca))) { CheckFailed("Calling convention disallows inalloca", & F); return; } } while (false); | ||||
2377 | |||||
2378 | if (Attrs.hasParamAttribute(i, Attribute::ByRef)) { | ||||
2379 | // FIXME: Should also disallow LDS and GDS, but we don't have the enum | ||||
2380 | // value here. | ||||
2381 | Assert(Arg.getType()->getPointerAddressSpace() != StackAS,do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false) | ||||
2382 | "Calling convention disallows stack byref", &F)do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false); | ||||
2383 | } | ||||
2384 | |||||
2385 | ++i; | ||||
2386 | } | ||||
2387 | } | ||||
2388 | |||||
2389 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2390 | case CallingConv::Fast: | ||||
2391 | case CallingConv::Cold: | ||||
2392 | case CallingConv::Intel_OCL_BI: | ||||
2393 | case CallingConv::PTX_Kernel: | ||||
2394 | case CallingConv::PTX_Device: | ||||
2395 | 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) | ||||
2396 | "perfect forwarding!",do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
2397 | &F)do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false); | ||||
2398 | break; | ||||
2399 | } | ||||
2400 | |||||
2401 | // Check that the argument values match the function type for this function... | ||||
2402 | unsigned i = 0; | ||||
2403 | for (const Argument &Arg : F.args()) { | ||||
2404 | 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) | ||||
2405 | "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) | ||||
2406 | 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); | ||||
2407 | Assert(Arg.getType()->isFirstClassType(),do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false) | ||||
2408 | "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); | ||||
2409 | if (!IsIntrinsic) { | ||||
2410 | Assert(!Arg.getType()->isMetadataTy(),do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false) | ||||
2411 | "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); | ||||
2412 | Assert(!Arg.getType()->isTokenTy(),do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
2413 | "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); | ||||
2414 | 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) | ||||
2415 | "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); | ||||
2416 | } | ||||
2417 | |||||
2418 | // Check that swifterror argument is only used by loads and stores. | ||||
2419 | if (Attrs.hasParamAttribute(i, Attribute::SwiftError)) { | ||||
2420 | verifySwiftErrorValue(&Arg); | ||||
2421 | } | ||||
2422 | ++i; | ||||
2423 | } | ||||
2424 | |||||
2425 | if (!IsIntrinsic) { | ||||
2426 | Assert(!F.getReturnType()->isTokenTy(),do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false) | ||||
2427 | "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); | ||||
2428 | 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) | ||||
2429 | "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); | ||||
2430 | } | ||||
2431 | |||||
2432 | // Get the function metadata attachments. | ||||
2433 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
2434 | F.getAllMetadata(MDs); | ||||
2435 | assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync")((void)0); | ||||
2436 | verifyFunctionMetadata(MDs); | ||||
2437 | |||||
2438 | // Check validity of the personality function | ||||
2439 | if (F.hasPersonalityFn()) { | ||||
2440 | auto *Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); | ||||
2441 | if (Per) | ||||
2442 | 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) | ||||
2443 | "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) | ||||
2444 | &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); | ||||
2445 | } | ||||
2446 | |||||
2447 | if (F.isMaterializable()) { | ||||
2448 | // Function has a body somewhere we can't see. | ||||
2449 | 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) | ||||
2450 | 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); | ||||
2451 | } else if (F.isDeclaration()) { | ||||
2452 | for (const auto &I : MDs) { | ||||
2453 | // This is used for call site debug information. | ||||
2454 | 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) | ||||
2455 | !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) | ||||
2456 | "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) | ||||
2457 | &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); | ||||
2458 | 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) | ||||
2459 | "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); | ||||
2460 | |||||
2461 | // Verify the metadata itself. | ||||
2462 | visitMDNode(*I.second, AreDebugLocsAllowed::Yes); | ||||
2463 | } | ||||
2464 | Assert(!F.hasPersonalityFn(),do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false) | ||||
2465 | "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); | ||||
2466 | } else { | ||||
2467 | // Verify that this function (which has a body) is not named "llvm.*". It | ||||
2468 | // is not legal to define intrinsics. | ||||
2469 | Assert(!IsIntrinsic, "llvm intrinsics cannot be defined!", &F)do { if (!(!IsIntrinsic)) { CheckFailed("llvm intrinsics cannot be defined!" , &F); return; } } while (false); | ||||
2470 | |||||
2471 | // Check the entry node | ||||
2472 | const BasicBlock *Entry = &F.getEntryBlock(); | ||||
2473 | Assert(pred_empty(Entry),do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false) | ||||
2474 | "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); | ||||
2475 | |||||
2476 | // The address of the entry block cannot be taken, unless it is dead. | ||||
2477 | if (Entry->hasAddressTaken()) { | ||||
2478 | 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) | ||||
2479 | "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); | ||||
2480 | } | ||||
2481 | |||||
2482 | unsigned NumDebugAttachments = 0, NumProfAttachments = 0; | ||||
2483 | // Visit metadata attachments. | ||||
2484 | for (const auto &I : MDs) { | ||||
2485 | // Verify that the attachment is legal. | ||||
2486 | auto AllowLocs = AreDebugLocsAllowed::No; | ||||
2487 | switch (I.first) { | ||||
2488 | default: | ||||
2489 | break; | ||||
2490 | case LLVMContext::MD_dbg: { | ||||
2491 | ++NumDebugAttachments; | ||||
2492 | AssertDI(NumDebugAttachments == 1,do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false) | ||||
2493 | "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); | ||||
2494 | 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) | ||||
2495 | "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); | ||||
2496 | 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) | ||||
2497 | "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) | ||||
2498 | &F)do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false); | ||||
2499 | |||||
2500 | auto *SP = cast<DISubprogram>(I.second); | ||||
2501 | const Function *&AttachedTo = DISubprogramAttachments[SP]; | ||||
2502 | AssertDI(!AttachedTo || AttachedTo == &F,do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false) | ||||
2503 | "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); | ||||
2504 | AttachedTo = &F; | ||||
2505 | AllowLocs = AreDebugLocsAllowed::Yes; | ||||
2506 | break; | ||||
2507 | } | ||||
2508 | case LLVMContext::MD_prof: | ||||
2509 | ++NumProfAttachments; | ||||
2510 | Assert(NumProfAttachments == 1,do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false) | ||||
2511 | "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); | ||||
2512 | break; | ||||
2513 | } | ||||
2514 | |||||
2515 | // Verify the metadata itself. | ||||
2516 | visitMDNode(*I.second, AllowLocs); | ||||
2517 | } | ||||
2518 | } | ||||
2519 | |||||
2520 | // If this function is actually an intrinsic, verify that it is only used in | ||||
2521 | // direct call/invokes, never having its "address taken". | ||||
2522 | // Only do this if the module is materialized, otherwise we don't have all the | ||||
2523 | // uses. | ||||
2524 | if (F.isIntrinsic() && F.getParent()->isMaterialized()) { | ||||
2525 | const User *U; | ||||
2526 | if (F.hasAddressTaken(&U)) | ||||
2527 | Assert(false, "Invalid user of intrinsic instruction!", U)do { if (!(false)) { CheckFailed("Invalid user of intrinsic instruction!" , U); return; } } while (false); | ||||
2528 | } | ||||
2529 | |||||
2530 | // Check intrinsics' signatures. | ||||
2531 | switch (F.getIntrinsicID()) { | ||||
2532 | case Intrinsic::experimental_gc_get_pointer_base: { | ||||
2533 | FunctionType *FT = F.getFunctionType(); | ||||
2534 | Assert(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
2535 | Assert(isa<PointerType>(F.getReturnType()),do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false) | ||||
2536 | "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); | ||||
2537 | 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) | ||||
2538 | "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) | ||||
2539 | 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); | ||||
2540 | break; | ||||
2541 | } | ||||
2542 | case Intrinsic::experimental_gc_get_pointer_offset: { | ||||
2543 | FunctionType *FT = F.getFunctionType(); | ||||
2544 | Assert(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
2545 | 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) | ||||
2546 | "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); | ||||
2547 | Assert(F.getReturnType()->isIntegerTy(),do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false) | ||||
2548 | "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); | ||||
2549 | break; | ||||
2550 | } | ||||
2551 | } | ||||
2552 | |||||
2553 | auto *N = F.getSubprogram(); | ||||
2554 | HasDebugInfo = (N != nullptr); | ||||
2555 | if (!HasDebugInfo
| ||||
2556 | return; | ||||
2557 | |||||
2558 | // Check that all !dbg attachments lead to back to N. | ||||
2559 | // | ||||
2560 | // FIXME: Check this incrementally while visiting !dbg attachments. | ||||
2561 | // FIXME: Only check when N is the canonical subprogram for F. | ||||
2562 | SmallPtrSet<const MDNode *, 32> Seen; | ||||
2563 | auto VisitDebugLoc = [&](const Instruction &I, const MDNode *Node) { | ||||
2564 | // Be careful about using DILocation here since we might be dealing with | ||||
2565 | // broken code (this is the Verifier after all). | ||||
2566 | const DILocation *DL = dyn_cast_or_null<DILocation>(Node); | ||||
2567 | if (!DL
| ||||
2568 | return; | ||||
2569 | if (!Seen.insert(DL).second) | ||||
2570 | return; | ||||
2571 | |||||
2572 | Metadata *Parent = DL->getRawScope(); | ||||
2573 | 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) | ||||
2574 | "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) | ||||
2575 | Parent)do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false); | ||||
2576 | |||||
2577 | DILocalScope *Scope = DL->getInlinedAtScope(); | ||||
2578 | Assert(Scope, "Failed to find DILocalScope", DL)do { if (!(Scope)) { CheckFailed("Failed to find DILocalScope" , DL); return; } } while (false); | ||||
2579 | |||||
2580 | if (!Seen.insert(Scope).second) | ||||
2581 | return; | ||||
2582 | |||||
2583 | DISubprogram *SP = Scope->getSubprogram(); | ||||
2584 | |||||
2585 | // Scope and SP could be the same MDNode and we don't want to skip | ||||
2586 | // validation in that case | ||||
2587 | if (SP && ((Scope != SP) && !Seen.insert(SP).second)) | ||||
2588 | return; | ||||
2589 | |||||
2590 | 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) | ||||
| |||||
2591 | "!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) | ||||
2592 | &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); | ||||
2593 | }; | ||||
2594 | for (auto &BB : F) | ||||
2595 | for (auto &I : BB) { | ||||
2596 | VisitDebugLoc(I, I.getDebugLoc().getAsMDNode()); | ||||
2597 | // The llvm.loop annotations also contain two DILocations. | ||||
2598 | if (auto MD = I.getMetadata(LLVMContext::MD_loop)) | ||||
2599 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) | ||||
2600 | VisitDebugLoc(I, dyn_cast_or_null<MDNode>(MD->getOperand(i))); | ||||
2601 | if (BrokenDebugInfo) | ||||
2602 | return; | ||||
2603 | } | ||||
2604 | } | ||||
2605 | |||||
2606 | // verifyBasicBlock - Verify that a basic block is well formed... | ||||
2607 | // | ||||
2608 | void Verifier::visitBasicBlock(BasicBlock &BB) { | ||||
2609 | InstsInThisBlock.clear(); | ||||
2610 | |||||
2611 | // Ensure that basic blocks have terminators! | ||||
2612 | 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); | ||||
2613 | |||||
2614 | // Check constraints that this basic block imposes on all of the PHI nodes in | ||||
2615 | // it. | ||||
2616 | if (isa<PHINode>(BB.front())) { | ||||
2617 | SmallVector<BasicBlock *, 8> Preds(predecessors(&BB)); | ||||
2618 | SmallVector<std::pair<BasicBlock*, Value*>, 8> Values; | ||||
2619 | llvm::sort(Preds); | ||||
2620 | for (const PHINode &PN : BB.phis()) { | ||||
2621 | 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) | ||||
2622 | "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) | ||||
2623 | "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) | ||||
2624 | &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); | ||||
2625 | |||||
2626 | // Get and sort all incoming values in the PHI node... | ||||
2627 | Values.clear(); | ||||
2628 | Values.reserve(PN.getNumIncomingValues()); | ||||
2629 | for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) | ||||
2630 | Values.push_back( | ||||
2631 | std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i))); | ||||
2632 | llvm::sort(Values); | ||||
2633 | |||||
2634 | for (unsigned i = 0, e = Values.size(); i != e; ++i) { | ||||
2635 | // Check to make sure that if there is more than one entry for a | ||||
2636 | // particular basic block in this PHI node, that the incoming values are | ||||
2637 | // all identical. | ||||
2638 | // | ||||
2639 | 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) | ||||
2640 | 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) | ||||
2641 | "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) | ||||
2642 | "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) | ||||
2643 | &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); | ||||
2644 | |||||
2645 | // Check to make sure that the predecessors and PHI node entries are | ||||
2646 | // matched up. | ||||
2647 | 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 ) | ||||
2648 | "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 ) | ||||
2649 | 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 ); | ||||
2650 | } | ||||
2651 | } | ||||
2652 | } | ||||
2653 | |||||
2654 | // Check that all instructions have their parent pointers set up correctly. | ||||
2655 | for (auto &I : BB) | ||||
2656 | { | ||||
2657 | Assert(I.getParent() == &BB, "Instruction has bogus parent pointer!")do { if (!(I.getParent() == &BB)) { CheckFailed("Instruction has bogus parent pointer!" ); return; } } while (false); | ||||
2658 | } | ||||
2659 | } | ||||
2660 | |||||
2661 | void Verifier::visitTerminator(Instruction &I) { | ||||
2662 | // Ensure that terminators only exist at the end of the basic block. | ||||
2663 | 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) | ||||
2664 | "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); | ||||
2665 | visitInstruction(I); | ||||
2666 | } | ||||
2667 | |||||
2668 | void Verifier::visitBranchInst(BranchInst &BI) { | ||||
2669 | if (BI.isConditional()) { | ||||
2670 | 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) | ||||
2671 | "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); | ||||
2672 | } | ||||
2673 | visitTerminator(BI); | ||||
2674 | } | ||||
2675 | |||||
2676 | void Verifier::visitReturnInst(ReturnInst &RI) { | ||||
2677 | Function *F = RI.getParent()->getParent(); | ||||
2678 | unsigned N = RI.getNumOperands(); | ||||
2679 | if (F->getReturnType()->isVoidTy()) | ||||
2680 | 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) | ||||
2681 | "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) | ||||
2682 | "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) | ||||
2683 | &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); | ||||
2684 | else | ||||
2685 | 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) | ||||
2686 | "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) | ||||
2687 | "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) | ||||
2688 | &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); | ||||
2689 | |||||
2690 | // Check to make sure that the return value has necessary properties for | ||||
2691 | // terminators... | ||||
2692 | visitTerminator(RI); | ||||
2693 | } | ||||
2694 | |||||
2695 | void Verifier::visitSwitchInst(SwitchInst &SI) { | ||||
2696 | // Check to make sure that all of the constants in the switch instruction | ||||
2697 | // have the same type as the switched-on value. | ||||
2698 | Type *SwitchTy = SI.getCondition()->getType(); | ||||
2699 | SmallPtrSet<ConstantInt*, 32> Constants; | ||||
2700 | for (auto &Case : SI.cases()) { | ||||
2701 | 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) | ||||
2702 | "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); | ||||
2703 | 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) | ||||
2704 | "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); | ||||
2705 | } | ||||
2706 | |||||
2707 | visitTerminator(SI); | ||||
2708 | } | ||||
2709 | |||||
2710 | void Verifier::visitIndirectBrInst(IndirectBrInst &BI) { | ||||
2711 | Assert(BI.getAddress()->getType()->isPointerTy(),do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false) | ||||
2712 | "Indirectbr operand must have pointer type!", &BI)do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false); | ||||
2713 | for (unsigned i = 0, e = BI.getNumDestinations(); i != e; ++i) | ||||
2714 | 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) | ||||
2715 | "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); | ||||
2716 | |||||
2717 | visitTerminator(BI); | ||||
2718 | } | ||||
2719 | |||||
2720 | void Verifier::visitCallBrInst(CallBrInst &CBI) { | ||||
2721 | 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) | ||||
2722 | &CBI)do { if (!(CBI.isInlineAsm())) { CheckFailed("Callbr is currently only used for asm-goto!" , &CBI); return; } } while (false); | ||||
2723 | const InlineAsm *IA = cast<InlineAsm>(CBI.getCalledOperand()); | ||||
2724 | Assert(!IA->canThrow(), "Unwinding from Callbr is not allowed")do { if (!(!IA->canThrow())) { CheckFailed("Unwinding from Callbr is not allowed" ); return; } } while (false); | ||||
2725 | for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i) | ||||
2726 | 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) | ||||
2727 | "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); | ||||
2728 | for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) { | ||||
2729 | 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) | ||||
2730 | "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); | ||||
2731 | if (isa<BasicBlock>(CBI.getOperand(i))) | ||||
2732 | for (unsigned j = i + 1; j != e; ++j) | ||||
2733 | Assert(CBI.getOperand(i) != CBI.getOperand(j),do { if (!(CBI.getOperand(i) != CBI.getOperand(j))) { CheckFailed ("Duplicate callbr destination!", &CBI); return; } } while (false) | ||||
2734 | "Duplicate callbr destination!", &CBI)do { if (!(CBI.getOperand(i) != CBI.getOperand(j))) { CheckFailed ("Duplicate callbr destination!", &CBI); return; } } while (false); | ||||
2735 | } | ||||
2736 | { | ||||
2737 | SmallPtrSet<BasicBlock *, 4> ArgBBs; | ||||
2738 | for (Value *V : CBI.args()) | ||||
2739 | if (auto *BA = dyn_cast<BlockAddress>(V)) | ||||
2740 | ArgBBs.insert(BA->getBasicBlock()); | ||||
2741 | for (BasicBlock *BB : CBI.getIndirectDests()) | ||||
2742 | 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); | ||||
2743 | } | ||||
2744 | |||||
2745 | visitTerminator(CBI); | ||||
2746 | } | ||||
2747 | |||||
2748 | void Verifier::visitSelectInst(SelectInst &SI) { | ||||
2749 | 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) | ||||
2750 | 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) | ||||
2751 | "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); | ||||
2752 | |||||
2753 | 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) | ||||
2754 | "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); | ||||
2755 | visitInstruction(SI); | ||||
2756 | } | ||||
2757 | |||||
2758 | /// visitUserOp1 - User defined operators shouldn't live beyond the lifetime of | ||||
2759 | /// a pass, if any exist, it's an error. | ||||
2760 | /// | ||||
2761 | void Verifier::visitUserOp1(Instruction &I) { | ||||
2762 | 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); | ||||
2763 | } | ||||
2764 | |||||
2765 | void Verifier::visitTruncInst(TruncInst &I) { | ||||
2766 | // Get the source and destination types | ||||
2767 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2768 | Type *DestTy = I.getType(); | ||||
2769 | |||||
2770 | // Get the size of the types in bits, we'll need this later | ||||
2771 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2772 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2773 | |||||
2774 | Assert(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only operates on integer" , &I); return; } } while (false); | ||||
2775 | Assert(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only produces integer" , &I); return; } } while (false); | ||||
2776 | 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) | ||||
2777 | "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); | ||||
2778 | Assert(SrcBitSize > DestBitSize, "DestTy too big for Trunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for Trunc" , &I); return; } } while (false); | ||||
2779 | |||||
2780 | visitInstruction(I); | ||||
2781 | } | ||||
2782 | |||||
2783 | void Verifier::visitZExtInst(ZExtInst &I) { | ||||
2784 | // Get the source and destination types | ||||
2785 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2786 | Type *DestTy = I.getType(); | ||||
2787 | |||||
2788 | // Get the size of the types in bits, we'll need this later | ||||
2789 | Assert(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only operates on integer" , &I); return; } } while (false); | ||||
2790 | Assert(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only produces an integer" , &I); return; } } while (false); | ||||
2791 | 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) | ||||
2792 | "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); | ||||
2793 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2794 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2795 | |||||
2796 | Assert(SrcBitSize < DestBitSize, "Type too small for ZExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for ZExt" , &I); return; } } while (false); | ||||
2797 | |||||
2798 | visitInstruction(I); | ||||
2799 | } | ||||
2800 | |||||
2801 | void Verifier::visitSExtInst(SExtInst &I) { | ||||
2802 | // Get the source and destination types | ||||
2803 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2804 | Type *DestTy = I.getType(); | ||||
2805 | |||||
2806 | // Get the size of the types in bits, we'll need this later | ||||
2807 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2808 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2809 | |||||
2810 | Assert(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SExt only operates on integer" , &I); return; } } while (false); | ||||
2811 | Assert(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("SExt only produces an integer" , &I); return; } } while (false); | ||||
2812 | 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) | ||||
2813 | "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); | ||||
2814 | Assert(SrcBitSize < DestBitSize, "Type too small for SExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for SExt" , &I); return; } } while (false); | ||||
2815 | |||||
2816 | visitInstruction(I); | ||||
2817 | } | ||||
2818 | |||||
2819 | void Verifier::visitFPTruncInst(FPTruncInst &I) { | ||||
2820 | // Get the source and destination types | ||||
2821 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2822 | Type *DestTy = I.getType(); | ||||
2823 | // Get the size of the types in bits, we'll need this later | ||||
2824 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2825 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2826 | |||||
2827 | Assert(SrcTy->isFPOrFPVectorTy(), "FPTrunc only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only operates on FP" , &I); return; } } while (false); | ||||
2828 | Assert(DestTy->isFPOrFPVectorTy(), "FPTrunc only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only produces an FP" , &I); return; } } while (false); | ||||
2829 | 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) | ||||
2830 | "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); | ||||
2831 | Assert(SrcBitSize > DestBitSize, "DestTy too big for FPTrunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for FPTrunc" , &I); return; } } while (false); | ||||
2832 | |||||
2833 | visitInstruction(I); | ||||
2834 | } | ||||
2835 | |||||
2836 | void Verifier::visitFPExtInst(FPExtInst &I) { | ||||
2837 | // Get the source and destination types | ||||
2838 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2839 | Type *DestTy = I.getType(); | ||||
2840 | |||||
2841 | // Get the size of the types in bits, we'll need this later | ||||
2842 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2843 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2844 | |||||
2845 | Assert(SrcTy->isFPOrFPVectorTy(), "FPExt only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only operates on FP" , &I); return; } } while (false); | ||||
2846 | Assert(DestTy->isFPOrFPVectorTy(), "FPExt only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only produces an FP" , &I); return; } } while (false); | ||||
2847 | 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) | ||||
2848 | "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); | ||||
2849 | Assert(SrcBitSize < DestBitSize, "DestTy too small for FPExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("DestTy too small for FPExt" , &I); return; } } while (false); | ||||
2850 | |||||
2851 | visitInstruction(I); | ||||
2852 | } | ||||
2853 | |||||
2854 | void Verifier::visitUIToFPInst(UIToFPInst &I) { | ||||
2855 | // Get the source and destination types | ||||
2856 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2857 | Type *DestTy = I.getType(); | ||||
2858 | |||||
2859 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2860 | bool DstVec = DestTy->isVectorTy(); | ||||
2861 | |||||
2862 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2863 | "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); | ||||
2864 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
2865 | "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); | ||||
2866 | 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) | ||||
2867 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
2868 | |||||
2869 | if (SrcVec && DstVec) | ||||
2870 | 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) | ||||
2871 | 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) | ||||
2872 | "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); | ||||
2873 | |||||
2874 | visitInstruction(I); | ||||
2875 | } | ||||
2876 | |||||
2877 | void Verifier::visitSIToFPInst(SIToFPInst &I) { | ||||
2878 | // Get the source and destination types | ||||
2879 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2880 | Type *DestTy = I.getType(); | ||||
2881 | |||||
2882 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2883 | bool DstVec = DestTy->isVectorTy(); | ||||
2884 | |||||
2885 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2886 | "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); | ||||
2887 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
2888 | "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); | ||||
2889 | 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) | ||||
2890 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
2891 | |||||
2892 | if (SrcVec && DstVec) | ||||
2893 | 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) | ||||
2894 | 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) | ||||
2895 | "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); | ||||
2896 | |||||
2897 | visitInstruction(I); | ||||
2898 | } | ||||
2899 | |||||
2900 | void Verifier::visitFPToUIInst(FPToUIInst &I) { | ||||
2901 | // Get the source and destination types | ||||
2902 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2903 | Type *DestTy = I.getType(); | ||||
2904 | |||||
2905 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2906 | bool DstVec = DestTy->isVectorTy(); | ||||
2907 | |||||
2908 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2909 | "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); | ||||
2910 | 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) | ||||
2911 | &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToUI source must be FP or FP vector" , &I); return; } } while (false); | ||||
2912 | Assert(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false) | ||||
2913 | "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); | ||||
2914 | |||||
2915 | if (SrcVec && DstVec) | ||||
2916 | 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) | ||||
2917 | 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) | ||||
2918 | "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); | ||||
2919 | |||||
2920 | visitInstruction(I); | ||||
2921 | } | ||||
2922 | |||||
2923 | void Verifier::visitFPToSIInst(FPToSIInst &I) { | ||||
2924 | // Get the source and destination types | ||||
2925 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2926 | Type *DestTy = I.getType(); | ||||
2927 | |||||
2928 | bool SrcVec = SrcTy->isVectorTy(); | ||||
2929 | bool DstVec = DestTy->isVectorTy(); | ||||
2930 | |||||
2931 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
2932 | "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); | ||||
2933 | 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) | ||||
2934 | &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToSI source must be FP or FP vector" , &I); return; } } while (false); | ||||
2935 | Assert(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false) | ||||
2936 | "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); | ||||
2937 | |||||
2938 | if (SrcVec && DstVec) | ||||
2939 | 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) | ||||
2940 | 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) | ||||
2941 | "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); | ||||
2942 | |||||
2943 | visitInstruction(I); | ||||
2944 | } | ||||
2945 | |||||
2946 | void Verifier::visitPtrToIntInst(PtrToIntInst &I) { | ||||
2947 | // Get the source and destination types | ||||
2948 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2949 | Type *DestTy = I.getType(); | ||||
2950 | |||||
2951 | Assert(SrcTy->isPtrOrPtrVectorTy(), "PtrToInt source must be pointer", &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("PtrToInt source must be pointer" , &I); return; } } while (false); | ||||
2952 | |||||
2953 | Assert(DestTy->isIntOrIntVectorTy(), "PtrToInt result must be integral", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("PtrToInt result must be integral" , &I); return; } } while (false); | ||||
2954 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false) | ||||
2955 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false); | ||||
2956 | |||||
2957 | if (SrcTy->isVectorTy()) { | ||||
2958 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
2959 | auto *VDest = cast<VectorType>(DestTy); | ||||
2960 | Assert(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false) | ||||
2961 | "PtrToInt Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false); | ||||
2962 | } | ||||
2963 | |||||
2964 | visitInstruction(I); | ||||
2965 | } | ||||
2966 | |||||
2967 | void Verifier::visitIntToPtrInst(IntToPtrInst &I) { | ||||
2968 | // Get the source and destination types | ||||
2969 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2970 | Type *DestTy = I.getType(); | ||||
2971 | |||||
2972 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false) | ||||
2973 | "IntToPtr source must be an integral", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false); | ||||
2974 | 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); | ||||
2975 | |||||
2976 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false) | ||||
2977 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false); | ||||
2978 | if (SrcTy->isVectorTy()) { | ||||
2979 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
2980 | auto *VDest = cast<VectorType>(DestTy); | ||||
2981 | Assert(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false) | ||||
2982 | "IntToPtr Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false); | ||||
2983 | } | ||||
2984 | visitInstruction(I); | ||||
2985 | } | ||||
2986 | |||||
2987 | void Verifier::visitBitCastInst(BitCastInst &I) { | ||||
2988 | Assert(do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
2989 | 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) | ||||
2990 | "Invalid bitcast", &I)do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false); | ||||
2991 | visitInstruction(I); | ||||
2992 | } | ||||
2993 | |||||
2994 | void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { | ||||
2995 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2996 | Type *DestTy = I.getType(); | ||||
2997 | |||||
2998 | Assert(SrcTy->isPtrOrPtrVectorTy(), "AddrSpaceCast source must be a pointer",do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false) | ||||
2999 | &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false); | ||||
3000 | Assert(DestTy->isPtrOrPtrVectorTy(), "AddrSpaceCast result must be a pointer",do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false) | ||||
3001 | &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false); | ||||
3002 | Assert(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(),do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false) | ||||
3003 | "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); | ||||
3004 | if (auto *SrcVTy = dyn_cast<VectorType>(SrcTy)) | ||||
3005 | Assert(SrcVTy->getElementCount() ==do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
3006 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
3007 | "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); | ||||
3008 | visitInstruction(I); | ||||
3009 | } | ||||
3010 | |||||
3011 | /// visitPHINode - Ensure that a PHI node is well formed. | ||||
3012 | /// | ||||
3013 | void Verifier::visitPHINode(PHINode &PN) { | ||||
3014 | // Ensure that the PHI nodes are all grouped together at the top of the block. | ||||
3015 | // This can be tested by checking whether the instruction before this is | ||||
3016 | // either nonexistent (because this is begin()) or is a PHI node. If not, | ||||
3017 | // then there is some other instruction before a PHI. | ||||
3018 | 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) | ||||
3019 | 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) | ||||
3020 | "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); | ||||
3021 | |||||
3022 | // Check that a PHI doesn't yield a Token. | ||||
3023 | 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); | ||||
3024 | |||||
3025 | // Check that all of the values of the PHI node have the same type as the | ||||
3026 | // result, and that the incoming blocks are really basic blocks. | ||||
3027 | for (Value *IncValue : PN.incoming_values()) { | ||||
3028 | 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) | ||||
3029 | "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); | ||||
3030 | } | ||||
3031 | |||||
3032 | // All other PHI node constraints are checked in the visitBasicBlock method. | ||||
3033 | |||||
3034 | visitInstruction(PN); | ||||
3035 | } | ||||
3036 | |||||
3037 | void Verifier::visitCallBase(CallBase &Call) { | ||||
3038 | Assert(Call.getCalledOperand()->getType()->isPointerTy(),do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false) | ||||
3039 | "Called function must be a pointer!", Call)do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false); | ||||
3040 | PointerType *FPTy = cast<PointerType>(Call.getCalledOperand()->getType()); | ||||
3041 | |||||
3042 | 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) | ||||
3043 | "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); | ||||
3044 | |||||
3045 | FunctionType *FTy = Call.getFunctionType(); | ||||
3046 | |||||
3047 | // Verify that the correct number of arguments are being passed | ||||
3048 | if (FTy->isVarArg()) | ||||
3049 | 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) | ||||
3050 | "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) | ||||
3051 | Call)do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false); | ||||
3052 | else | ||||
3053 | 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) | ||||
3054 | "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); | ||||
3055 | |||||
3056 | // Verify that all arguments to the call match the function type. | ||||
3057 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) | ||||
3058 | 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) | ||||
3059 | "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) | ||||
3060 | 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); | ||||
3061 | |||||
3062 | AttributeList Attrs = Call.getAttributes(); | ||||
3063 | |||||
3064 | Assert(verifyAttributeCount(Attrs, Call.arg_size()),do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false) | ||||
3065 | "Attribute after last parameter!", Call)do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false); | ||||
3066 | |||||
3067 | Function *Callee = | ||||
3068 | dyn_cast<Function>(Call.getCalledOperand()->stripPointerCasts()); | ||||
3069 | bool IsIntrinsic = Callee && Callee->isIntrinsic(); | ||||
3070 | if (IsIntrinsic) | ||||
3071 | Assert(Callee->getValueType() == FTy,do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false) | ||||
3072 | "Intrinsic called with incompatible signature", Call)do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false); | ||||
3073 | |||||
3074 | if (Attrs.hasFnAttribute(Attribute::Speculatable)) { | ||||
3075 | // Don't allow speculatable on call sites, unless the underlying function | ||||
3076 | // declaration is also speculatable. | ||||
3077 | Assert(Callee && Callee->isSpeculatable(),do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false) | ||||
3078 | "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); | ||||
3079 | } | ||||
3080 | |||||
3081 | if (Attrs.hasFnAttribute(Attribute::Preallocated)) { | ||||
3082 | 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) | ||||
3083 | 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) | ||||
3084 | "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) | ||||
3085 | "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); | ||||
3086 | } | ||||
3087 | |||||
3088 | // Verify call attributes. | ||||
3089 | verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic); | ||||
3090 | |||||
3091 | // Conservatively check the inalloca argument. | ||||
3092 | // We have a bug if we can find that there is an underlying alloca without | ||||
3093 | // inalloca. | ||||
3094 | if (Call.hasInAllocaArgument()) { | ||||
3095 | Value *InAllocaArg = Call.getArgOperand(FTy->getNumParams() - 1); | ||||
3096 | if (auto AI = dyn_cast<AllocaInst>(InAllocaArg->stripInBoundsOffsets())) | ||||
3097 | Assert(AI->isUsedWithInAlloca(),do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
3098 | "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); | ||||
3099 | } | ||||
3100 | |||||
3101 | // For each argument of the callsite, if it has the swifterror argument, | ||||
3102 | // make sure the underlying alloca/parameter it comes from has a swifterror as | ||||
3103 | // well. | ||||
3104 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { | ||||
3105 | if (Call.paramHasAttr(i, Attribute::SwiftError)) { | ||||
3106 | Value *SwiftErrorArg = Call.getArgOperand(i); | ||||
3107 | if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) { | ||||
3108 | Assert(AI->isSwiftError(),do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
3109 | "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); | ||||
3110 | continue; | ||||
3111 | } | ||||
3112 | auto ArgI = dyn_cast<Argument>(SwiftErrorArg); | ||||
3113 | Assert(ArgI,do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false) | ||||
3114 | "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) | ||||
3115 | SwiftErrorArg, Call)do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false); | ||||
3116 | Assert(ArgI->hasSwiftErrorAttr(),do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
3117 | "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) | ||||
3118 | Call)do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false); | ||||
3119 | } | ||||
3120 | |||||
3121 | if (Attrs.hasParamAttribute(i, Attribute::ImmArg)) { | ||||
3122 | // Don't allow immarg on call sites, unless the underlying declaration | ||||
3123 | // also has the matching immarg. | ||||
3124 | 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) | ||||
3125 | "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) | ||||
3126 | 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); | ||||
3127 | } | ||||
3128 | |||||
3129 | if (Call.paramHasAttr(i, Attribute::ImmArg)) { | ||||
3130 | Value *ArgVal = Call.getArgOperand(i); | ||||
3131 | 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) | ||||
3132 | "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); | ||||
3133 | } | ||||
3134 | |||||
3135 | if (Call.paramHasAttr(i, Attribute::Preallocated)) { | ||||
3136 | Value *ArgVal = Call.getArgOperand(i); | ||||
3137 | bool hasOB = | ||||
3138 | Call.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0; | ||||
3139 | bool isMustTail = Call.isMustTailCall(); | ||||
3140 | 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) | ||||
3141 | "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) | ||||
3142 | "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) | ||||
3143 | 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); | ||||
3144 | } | ||||
3145 | } | ||||
3146 | |||||
3147 | if (FTy->isVarArg()) { | ||||
3148 | // FIXME? is 'nest' even legal here? | ||||
3149 | bool SawNest = false; | ||||
3150 | bool SawReturned = false; | ||||
3151 | |||||
3152 | for (unsigned Idx = 0; Idx < FTy->getNumParams(); ++Idx) { | ||||
3153 | if (Attrs.hasParamAttribute(Idx, Attribute::Nest)) | ||||
3154 | SawNest = true; | ||||
3155 | if (Attrs.hasParamAttribute(Idx, Attribute::Returned)) | ||||
3156 | SawReturned = true; | ||||
3157 | } | ||||
3158 | |||||
3159 | // Check attributes on the varargs part. | ||||
3160 | for (unsigned Idx = FTy->getNumParams(); Idx < Call.arg_size(); ++Idx) { | ||||
3161 | Type *Ty = Call.getArgOperand(Idx)->getType(); | ||||
3162 | AttributeSet ArgAttrs = Attrs.getParamAttributes(Idx); | ||||
3163 | verifyParameterAttrs(ArgAttrs, Ty, &Call); | ||||
3164 | |||||
3165 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
3166 | 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); | ||||
3167 | SawNest = true; | ||||
3168 | } | ||||
3169 | |||||
3170 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
3171 | Assert(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false) | ||||
3172 | Call)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false); | ||||
3173 | Assert(Ty->canLosslesslyBitCastTo(FTy->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
3174 | "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) | ||||
3175 | "attribute",do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
3176 | Call)do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false); | ||||
3177 | SawReturned = true; | ||||
3178 | } | ||||
3179 | |||||
3180 | // Statepoint intrinsic is vararg but the wrapped function may be not. | ||||
3181 | // Allow sret here and check the wrapped function in verifyStatepoint. | ||||
3182 | if (!Call.getCalledFunction() || | ||||
3183 | Call.getCalledFunction()->getIntrinsicID() != | ||||
3184 | Intrinsic::experimental_gc_statepoint) | ||||
3185 | 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) | ||||
3186 | "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) | ||||
3187 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
3188 | |||||
3189 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) | ||||
3190 | 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) | ||||
3191 | "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); | ||||
3192 | } | ||||
3193 | } | ||||
3194 | |||||
3195 | // Verify that there's no metadata unless it's a direct call to an intrinsic. | ||||
3196 | if (!IsIntrinsic) { | ||||
3197 | for (Type *ParamTy : FTy->params()) { | ||||
3198 | Assert(!ParamTy->isMetadataTy(),do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
3199 | "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); | ||||
3200 | Assert(!ParamTy->isTokenTy(),do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
3201 | "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); | ||||
3202 | } | ||||
3203 | } | ||||
3204 | |||||
3205 | // Verify that indirect calls don't return tokens. | ||||
3206 | if (!Call.getCalledFunction()) { | ||||
3207 | Assert(!FTy->getReturnType()->isTokenTy(),do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false) | ||||
3208 | "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); | ||||
3209 | Assert(!FTy->getReturnType()->isX86_AMXTy(),do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false) | ||||
3210 | "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); | ||||
3211 | } | ||||
3212 | |||||
3213 | if (Function *F = Call.getCalledFunction()) | ||||
3214 | if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) | ||||
3215 | visitIntrinsicCall(ID, Call); | ||||
3216 | |||||
3217 | // Verify that a callsite has at most one "deopt", at most one "funclet", at | ||||
3218 | // most one "gc-transition", at most one "cfguardtarget", | ||||
3219 | // and at most one "preallocated" operand bundle. | ||||
3220 | bool FoundDeoptBundle = false, FoundFuncletBundle = false, | ||||
3221 | FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false, | ||||
3222 | FoundPreallocatedBundle = false, FoundGCLiveBundle = false, | ||||
3223 | FoundAttachedCallBundle = false; | ||||
3224 | for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) { | ||||
3225 | OperandBundleUse BU = Call.getOperandBundleAt(i); | ||||
3226 | uint32_t Tag = BU.getTagID(); | ||||
3227 | if (Tag == LLVMContext::OB_deopt) { | ||||
3228 | Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", Call)do { if (!(!FoundDeoptBundle)) { CheckFailed("Multiple deopt operand bundles" , Call); return; } } while (false); | ||||
3229 | FoundDeoptBundle = true; | ||||
3230 | } else if (Tag == LLVMContext::OB_gc_transition) { | ||||
3231 | Assert(!FoundGCTransitionBundle, "Multiple gc-transition operand bundles",do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false) | ||||
3232 | Call)do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false); | ||||
3233 | FoundGCTransitionBundle = true; | ||||
3234 | } else if (Tag == LLVMContext::OB_funclet) { | ||||
3235 | Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", Call)do { if (!(!FoundFuncletBundle)) { CheckFailed("Multiple funclet operand bundles" , Call); return; } } while (false); | ||||
3236 | FoundFuncletBundle = true; | ||||
3237 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false) | ||||
3238 | "Expected exactly one funclet bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false); | ||||
3239 | 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) | ||||
3240 | "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) | ||||
3241 | Call)do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false); | ||||
3242 | } else if (Tag == LLVMContext::OB_cfguardtarget) { | ||||
3243 | Assert(!FoundCFGuardTargetBundle,do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false) | ||||
3244 | "Multiple CFGuardTarget operand bundles", Call)do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false); | ||||
3245 | FoundCFGuardTargetBundle = true; | ||||
3246 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false) | ||||
3247 | "Expected exactly one cfguardtarget bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false); | ||||
3248 | } else if (Tag == LLVMContext::OB_preallocated) { | ||||
3249 | Assert(!FoundPreallocatedBundle, "Multiple preallocated operand bundles",do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false) | ||||
3250 | Call)do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false); | ||||
3251 | FoundPreallocatedBundle = true; | ||||
3252 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false) | ||||
3253 | "Expected exactly one preallocated bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false); | ||||
3254 | auto Input = dyn_cast<IntrinsicInst>(BU.Inputs.front()); | ||||
3255 | 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 ) | ||||
3256 | 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 ) | ||||
3257 | "\"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 ) | ||||
3258 | "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 ) | ||||
3259 | 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 ); | ||||
3260 | } else if (Tag == LLVMContext::OB_gc_live) { | ||||
3261 | Assert(!FoundGCLiveBundle, "Multiple gc-live operand bundles",do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false) | ||||
3262 | Call)do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false); | ||||
3263 | FoundGCLiveBundle = true; | ||||
3264 | } else if (Tag == LLVMContext::OB_clang_arc_attachedcall) { | ||||
3265 | Assert(!FoundAttachedCallBundle,do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false) | ||||
3266 | "Multiple \"clang.arc.attachedcall\" operand bundles", Call)do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false); | ||||
3267 | FoundAttachedCallBundle = true; | ||||
3268 | } | ||||
3269 | } | ||||
3270 | |||||
3271 | if (FoundAttachedCallBundle) | ||||
3272 | 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) | ||||
3273 | (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) | ||||
3274 | "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) | ||||
3275 | "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) | ||||
3276 | "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) | ||||
3277 | 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); | ||||
3278 | |||||
3279 | // Verify that each inlinable callsite of a debug-info-bearing function in a | ||||
3280 | // debug-info-bearing function has a debug location attached to it. Failure to | ||||
3281 | // do so causes assertion failures when the inliner sets up inline scope info. | ||||
3282 | if (Call.getFunction()->getSubprogram() && Call.getCalledFunction() && | ||||
3283 | Call.getCalledFunction()->getSubprogram()) | ||||
3284 | 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) | ||||
3285 | "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) | ||||
3286 | "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) | ||||
3287 | Call)do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false); | ||||
3288 | |||||
3289 | visitInstruction(Call); | ||||
3290 | } | ||||
3291 | |||||
3292 | void Verifier::verifyTailCCMustTailAttrs(AttrBuilder Attrs, | ||||
3293 | StringRef Context) { | ||||
3294 | Assert(!Attrs.contains(Attribute::InAlloca),do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false) | ||||
3295 | Twine("inalloca attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false); | ||||
3296 | Assert(!Attrs.contains(Attribute::InReg),do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false) | ||||
3297 | Twine("inreg attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false); | ||||
3298 | Assert(!Attrs.contains(Attribute::SwiftError),do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false) | ||||
3299 | Twine("swifterror attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false); | ||||
3300 | Assert(!Attrs.contains(Attribute::Preallocated),do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false) | ||||
3301 | Twine("preallocated attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false); | ||||
3302 | Assert(!Attrs.contains(Attribute::ByRef),do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false) | ||||
3303 | Twine("byref attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false); | ||||
3304 | } | ||||
3305 | |||||
3306 | /// Two types are "congruent" if they are identical, or if they are both pointer | ||||
3307 | /// types with different pointee types and the same address space. | ||||
3308 | static bool isTypeCongruent(Type *L, Type *R) { | ||||
3309 | if (L == R) | ||||
3310 | return true; | ||||
3311 | PointerType *PL = dyn_cast<PointerType>(L); | ||||
3312 | PointerType *PR = dyn_cast<PointerType>(R); | ||||
3313 | if (!PL || !PR) | ||||
3314 | return false; | ||||
3315 | return PL->getAddressSpace() == PR->getAddressSpace(); | ||||
3316 | } | ||||
3317 | |||||
3318 | static AttrBuilder getParameterABIAttributes(int I, AttributeList Attrs) { | ||||
3319 | static const Attribute::AttrKind ABIAttrs[] = { | ||||
3320 | Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, | ||||
3321 | Attribute::InReg, Attribute::StackAlignment, Attribute::SwiftSelf, | ||||
3322 | Attribute::SwiftAsync, Attribute::SwiftError, Attribute::Preallocated, | ||||
3323 | Attribute::ByRef}; | ||||
3324 | AttrBuilder Copy; | ||||
3325 | for (auto AK : ABIAttrs) { | ||||
3326 | Attribute Attr = Attrs.getParamAttributes(I).getAttribute(AK); | ||||
3327 | if (Attr.isValid()) | ||||
3328 | Copy.addAttribute(Attr); | ||||
3329 | } | ||||
3330 | |||||
3331 | // `align` is ABI-affecting only in combination with `byval` or `byref`. | ||||
3332 | if (Attrs.hasParamAttribute(I, Attribute::Alignment) && | ||||
3333 | (Attrs.hasParamAttribute(I, Attribute::ByVal) || | ||||
3334 | Attrs.hasParamAttribute(I, Attribute::ByRef))) | ||||
3335 | Copy.addAlignmentAttr(Attrs.getParamAlignment(I)); | ||||
3336 | return Copy; | ||||
3337 | } | ||||
3338 | |||||
3339 | void Verifier::verifyMustTailCall(CallInst &CI) { | ||||
3340 | 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); | ||||
3341 | |||||
3342 | Function *F = CI.getParent()->getParent(); | ||||
3343 | FunctionType *CallerTy = F->getFunctionType(); | ||||
3344 | FunctionType *CalleeTy = CI.getFunctionType(); | ||||
3345 | Assert(CallerTy->isVarArg() == CalleeTy->isVarArg(),do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false) | ||||
3346 | "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); | ||||
3347 | 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) | ||||
3348 | "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); | ||||
3349 | |||||
3350 | // - The calling conventions of the caller and callee must match. | ||||
3351 | 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) | ||||
3352 | "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); | ||||
3353 | |||||
3354 | // - The call must immediately precede a :ref:`ret <i_ret>` instruction, | ||||
3355 | // or a pointer bitcast followed by a ret instruction. | ||||
3356 | // - The ret instruction must return the (possibly bitcasted) value | ||||
3357 | // produced by the call or void. | ||||
3358 | Value *RetVal = &CI; | ||||
3359 | Instruction *Next = CI.getNextNode(); | ||||
3360 | |||||
3361 | // Handle the optional bitcast. | ||||
3362 | if (BitCastInst *BI = dyn_cast_or_null<BitCastInst>(Next)) { | ||||
3363 | Assert(BI->getOperand(0) == RetVal,do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false) | ||||
3364 | "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); | ||||
3365 | RetVal = BI; | ||||
3366 | Next = BI->getNextNode(); | ||||
3367 | } | ||||
3368 | |||||
3369 | // Check the return. | ||||
3370 | ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next); | ||||
3371 | 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) | ||||
3372 | &CI)do { if (!(Ret)) { CheckFailed("musttail call must precede a ret with an optional bitcast" , &CI); return; } } while (false); | ||||
3373 | 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) | ||||
3374 | 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) | ||||
3375 | "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); | ||||
3376 | |||||
3377 | AttributeList CallerAttrs = F->getAttributes(); | ||||
3378 | AttributeList CalleeAttrs = CI.getAttributes(); | ||||
3379 | if (CI.getCallingConv() == CallingConv::SwiftTail || | ||||
3380 | CI.getCallingConv() == CallingConv::Tail) { | ||||
3381 | StringRef CCName = | ||||
3382 | CI.getCallingConv() == CallingConv::Tail ? "tailcc" : "swifttailcc"; | ||||
3383 | |||||
3384 | // - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes | ||||
3385 | // are allowed in swifttailcc call | ||||
3386 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3387 | AttrBuilder ABIAttrs = getParameterABIAttributes(I, CallerAttrs); | ||||
3388 | SmallString<32> Context{CCName, StringRef(" musttail caller")}; | ||||
3389 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
3390 | } | ||||
3391 | for (int I = 0, E = CalleeTy->getNumParams(); I != E; ++I) { | ||||
3392 | AttrBuilder ABIAttrs = getParameterABIAttributes(I, CalleeAttrs); | ||||
3393 | SmallString<32> Context{CCName, StringRef(" musttail callee")}; | ||||
3394 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
3395 | } | ||||
3396 | // - Varargs functions are not allowed | ||||
3397 | Assert(!CallerTy->isVarArg(), Twine("cannot guarantee ") + CCName +do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false) | ||||
3398 | " tail call for varargs function")do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false); | ||||
3399 | return; | ||||
3400 | } | ||||
3401 | |||||
3402 | // - The caller and callee prototypes must match. Pointer types of | ||||
3403 | // parameters or return types may differ in pointee type, but not | ||||
3404 | // address space. | ||||
3405 | if (!CI.getCalledFunction() || !CI.getCalledFunction()->isIntrinsic()) { | ||||
3406 | 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) | ||||
3407 | "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) | ||||
3408 | &CI)do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false); | ||||
3409 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3410 | Assert(do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
3411 | 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) | ||||
3412 | "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); | ||||
3413 | } | ||||
3414 | } | ||||
3415 | |||||
3416 | // - All ABI-impacting function attributes, such as sret, byval, inreg, | ||||
3417 | // returned, preallocated, and inalloca, must match. | ||||
3418 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3419 | AttrBuilder CallerABIAttrs = getParameterABIAttributes(I, CallerAttrs); | ||||
3420 | AttrBuilder CalleeABIAttrs = getParameterABIAttributes(I, CalleeAttrs); | ||||
3421 | 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) | ||||
3422 | "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) | ||||
3423 | "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) | ||||
3424 | &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); | ||||
3425 | } | ||||
3426 | } | ||||
3427 | |||||
3428 | void Verifier::visitCallInst(CallInst &CI) { | ||||
3429 | visitCallBase(CI); | ||||
3430 | |||||
3431 | if (CI.isMustTailCall()) | ||||
3432 | verifyMustTailCall(CI); | ||||
3433 | } | ||||
3434 | |||||
3435 | void Verifier::visitInvokeInst(InvokeInst &II) { | ||||
3436 | visitCallBase(II); | ||||
3437 | |||||
3438 | // Verify that the first non-PHI instruction of the unwind destination is an | ||||
3439 | // exception handling instruction. | ||||
3440 | Assert(do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
3441 | II.getUnwindDest()->isEHPad(),do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
3442 | "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) | ||||
3443 | &II)do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false); | ||||
3444 | |||||
3445 | visitTerminator(II); | ||||
3446 | } | ||||
3447 | |||||
3448 | /// visitUnaryOperator - Check the argument to the unary operator. | ||||
3449 | /// | ||||
3450 | void Verifier::visitUnaryOperator(UnaryOperator &U) { | ||||
3451 | 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) | ||||
3452 | "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) | ||||
3453 | "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) | ||||
3454 | &U)do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false); | ||||
3455 | |||||
3456 | switch (U.getOpcode()) { | ||||
3457 | // Check that floating-point arithmetic operators are only used with | ||||
3458 | // floating-point operands. | ||||
3459 | case Instruction::FNeg: | ||||
3460 | Assert(U.getType()->isFPOrFPVectorTy(),do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false) | ||||
3461 | "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); | ||||
3462 | break; | ||||
3463 | default: | ||||
3464 | llvm_unreachable("Unknown UnaryOperator opcode!")__builtin_unreachable(); | ||||
3465 | } | ||||
3466 | |||||
3467 | visitInstruction(U); | ||||
3468 | } | ||||
3469 | |||||
3470 | /// visitBinaryOperator - Check that both arguments to the binary operator are | ||||
3471 | /// of the same type! | ||||
3472 | /// | ||||
3473 | void Verifier::visitBinaryOperator(BinaryOperator &B) { | ||||
3474 | 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) | ||||
3475 | "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); | ||||
3476 | |||||
3477 | switch (B.getOpcode()) { | ||||
3478 | // Check that integer arithmetic operators are only used with | ||||
3479 | // integral operands. | ||||
3480 | case Instruction::Add: | ||||
3481 | case Instruction::Sub: | ||||
3482 | case Instruction::Mul: | ||||
3483 | case Instruction::SDiv: | ||||
3484 | case Instruction::UDiv: | ||||
3485 | case Instruction::SRem: | ||||
3486 | case Instruction::URem: | ||||
3487 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false) | ||||
3488 | "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); | ||||
3489 | 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) | ||||
3490 | "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) | ||||
3491 | "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) | ||||
3492 | &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); | ||||
3493 | break; | ||||
3494 | // Check that floating-point arithmetic operators are only used with | ||||
3495 | // floating-point operands. | ||||
3496 | case Instruction::FAdd: | ||||
3497 | case Instruction::FSub: | ||||
3498 | case Instruction::FMul: | ||||
3499 | case Instruction::FDiv: | ||||
3500 | case Instruction::FRem: | ||||
3501 | Assert(B.getType()->isFPOrFPVectorTy(),do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
3502 | "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) | ||||
3503 | "floating-point types!",do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
3504 | &B)do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false); | ||||
3505 | 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) | ||||
3506 | "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) | ||||
3507 | "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) | ||||
3508 | &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); | ||||
3509 | break; | ||||
3510 | // Check that logical operators are only used with integral operands. | ||||
3511 | case Instruction::And: | ||||
3512 | case Instruction::Or: | ||||
3513 | case Instruction::Xor: | ||||
3514 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false) | ||||
3515 | "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); | ||||
3516 | 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) | ||||
3517 | "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) | ||||
3518 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false); | ||||
3519 | break; | ||||
3520 | case Instruction::Shl: | ||||
3521 | case Instruction::LShr: | ||||
3522 | case Instruction::AShr: | ||||
3523 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false) | ||||
3524 | "Shifts only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false); | ||||
3525 | 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) | ||||
3526 | "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); | ||||
3527 | break; | ||||
3528 | default: | ||||
3529 | llvm_unreachable("Unknown BinaryOperator opcode!")__builtin_unreachable(); | ||||
3530 | } | ||||
3531 | |||||
3532 | visitInstruction(B); | ||||
3533 | } | ||||
3534 | |||||
3535 | void Verifier::visitICmpInst(ICmpInst &IC) { | ||||
3536 | // Check that the operands are the same type | ||||
3537 | Type *Op0Ty = IC.getOperand(0)->getType(); | ||||
3538 | Type *Op1Ty = IC.getOperand(1)->getType(); | ||||
3539 | Assert(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false) | ||||
3540 | "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); | ||||
3541 | // Check that the operands are the right type | ||||
3542 | Assert(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy(),do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false) | ||||
3543 | "Invalid operand types for ICmp instruction", &IC)do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false); | ||||
3544 | // Check that the predicate is valid. | ||||
3545 | Assert(IC.isIntPredicate(),do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false) | ||||
3546 | "Invalid predicate in ICmp instruction!", &IC)do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false); | ||||
3547 | |||||
3548 | visitInstruction(IC); | ||||
3549 | } | ||||
3550 | |||||
3551 | void Verifier::visitFCmpInst(FCmpInst &FC) { | ||||
3552 | // Check that the operands are the same type | ||||
3553 | Type *Op0Ty = FC.getOperand(0)->getType(); | ||||
3554 | Type *Op1Ty = FC.getOperand(1)->getType(); | ||||
3555 | Assert(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false) | ||||
3556 | "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); | ||||
3557 | // Check that the operands are the right type | ||||
3558 | Assert(Op0Ty->isFPOrFPVectorTy(),do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false) | ||||
3559 | "Invalid operand types for FCmp instruction", &FC)do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false); | ||||
3560 | // Check that the predicate is valid. | ||||
3561 | Assert(FC.isFPPredicate(),do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false) | ||||
3562 | "Invalid predicate in FCmp instruction!", &FC)do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false); | ||||
3563 | |||||
3564 | visitInstruction(FC); | ||||
3565 | } | ||||
3566 | |||||
3567 | void Verifier::visitExtractElementInst(ExtractElementInst &EI) { | ||||
3568 | Assert(do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false) | ||||
3569 | 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) | ||||
3570 | "Invalid extractelement operands!", &EI)do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false); | ||||
3571 | visitInstruction(EI); | ||||
3572 | } | ||||
3573 | |||||
3574 | void Verifier::visitInsertElementInst(InsertElementInst &IE) { | ||||
3575 | 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) | ||||
3576 | IE.getOperand(2)),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
3577 | "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); | ||||
3578 | visitInstruction(IE); | ||||
3579 | } | ||||
3580 | |||||
3581 | void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) { | ||||
3582 | 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) | ||||
3583 | SV.getShuffleMask()),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
3584 | "Invalid shufflevector operands!", &SV)do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false); | ||||
3585 | visitInstruction(SV); | ||||
3586 | } | ||||
3587 | |||||
3588 | void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { | ||||
3589 | Type *TargetTy = GEP.getPointerOperandType()->getScalarType(); | ||||
3590 | |||||
3591 | 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) | ||||
3592 | "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); | ||||
3593 | Assert(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP)do { if (!(GEP.getSourceElementType()->isSized())) { CheckFailed ("GEP into unsized type!", &GEP); return; } } while (false ); | ||||
3594 | |||||
3595 | SmallVector<Value *, 16> Idxs(GEP.indices()); | ||||
3596 | Assert(all_of(do { if (!(all_of( Idxs, [](Value* V) { return V->getType( )->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
3597 | 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) | ||||
3598 | "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); | ||||
3599 | Type *ElTy = | ||||
3600 | GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs); | ||||
3601 | Assert(ElTy, "Invalid indices for GEP pointer type!", &GEP)do { if (!(ElTy)) { CheckFailed("Invalid indices for GEP pointer type!" , &GEP); return; } } while (false); | ||||
3602 | |||||
3603 | 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) | ||||
3604 | 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) | ||||
3605 | "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); | ||||
3606 | |||||
3607 | if (auto *GEPVTy = dyn_cast<VectorType>(GEP.getType())) { | ||||
3608 | // Additional checks for vector GEPs. | ||||
3609 | ElementCount GEPWidth = GEPVTy->getElementCount(); | ||||
3610 | if (GEP.getPointerOperandType()->isVectorTy()) | ||||
3611 | Assert(do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
3612 | GEPWidth ==do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
3613 | 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) | ||||
3614 | "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); | ||||
3615 | for (Value *Idx : Idxs) { | ||||
3616 | Type *IndexTy = Idx->getType(); | ||||
3617 | if (auto *IndexVTy = dyn_cast<VectorType>(IndexTy)) { | ||||
3618 | ElementCount IndexWidth = IndexVTy->getElementCount(); | ||||
3619 | Assert(IndexWidth == GEPWidth, "Invalid GEP index vector width", &GEP)do { if (!(IndexWidth == GEPWidth)) { CheckFailed("Invalid GEP index vector width" , &GEP); return; } } while (false); | ||||
3620 | } | ||||
3621 | Assert(IndexTy->isIntOrIntVectorTy(),do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false) | ||||
3622 | "All GEP indices should be of integer type")do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false); | ||||
3623 | } | ||||
3624 | } | ||||
3625 | |||||
3626 | if (auto *PTy = dyn_cast<PointerType>(GEP.getType())) { | ||||
3627 | Assert(GEP.getAddressSpace() == PTy->getAddressSpace(),do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false) | ||||
3628 | "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); | ||||
3629 | } | ||||
3630 | |||||
3631 | visitInstruction(GEP); | ||||
3632 | } | ||||
3633 | |||||
3634 | static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { | ||||
3635 | return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); | ||||
3636 | } | ||||
3637 | |||||
3638 | void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { | ||||
3639 | assert(Range && Range == I.getMetadata(LLVMContext::MD_range) &&((void)0) | ||||
3640 | "precondition violation")((void)0); | ||||
3641 | |||||
3642 | unsigned NumOperands = Range->getNumOperands(); | ||||
3643 | Assert(NumOperands % 2 == 0, "Unfinished range!", Range)do { if (!(NumOperands % 2 == 0)) { CheckFailed("Unfinished range!" , Range); return; } } while (false); | ||||
3644 | unsigned NumRanges = NumOperands / 2; | ||||
3645 | 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); | ||||
3646 | |||||
3647 | ConstantRange LastRange(1, true); // Dummy initial value | ||||
3648 | for (unsigned i = 0; i < NumRanges; ++i) { | ||||
3649 | ConstantInt *Low = | ||||
3650 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i)); | ||||
3651 | 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); | ||||
3652 | ConstantInt *High = | ||||
3653 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i + 1)); | ||||
3654 | 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); | ||||
3655 | 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) | ||||
3656 | "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); | ||||
3657 | |||||
3658 | APInt HighV = High->getValue(); | ||||
3659 | APInt LowV = Low->getValue(); | ||||
3660 | ConstantRange CurRange(LowV, HighV); | ||||
3661 | Assert(!CurRange.isEmptySet() && !CurRange.isFullSet(),do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false) | ||||
3662 | "Range must not be empty!", Range)do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false); | ||||
3663 | if (i != 0) { | ||||
3664 | Assert(CurRange.intersectWith(LastRange).isEmptySet(),do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
3665 | "Intervals are overlapping", Range)do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
3666 | 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) | ||||
3667 | Range)do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false); | ||||
3668 | Assert(!isContiguous(CurRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
3669 | Range)do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
3670 | } | ||||
3671 | LastRange = ConstantRange(LowV, HighV); | ||||
3672 | } | ||||
3673 | if (NumRanges > 2) { | ||||
3674 | APInt FirstLow = | ||||
3675 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(0))->getValue(); | ||||
3676 | APInt FirstHigh = | ||||
3677 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(1))->getValue(); | ||||
3678 | ConstantRange FirstRange(FirstLow, FirstHigh); | ||||
3679 | Assert(FirstRange.intersectWith(LastRange).isEmptySet(),do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
3680 | "Intervals are overlapping", Range)do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
3681 | Assert(!isContiguous(FirstRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
3682 | Range)do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
3683 | } | ||||
3684 | } | ||||
3685 | |||||
3686 | void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) { | ||||
3687 | unsigned Size = DL.getTypeSizeInBits(Ty); | ||||
3688 | 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); | ||||
3689 | 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) | ||||
3690 | "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); | ||||
3691 | } | ||||
3692 | |||||
3693 | void Verifier::visitLoadInst(LoadInst &LI) { | ||||
3694 | PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType()); | ||||
3695 | Assert(PTy, "Load operand must be a pointer.", &LI)do { if (!(PTy)) { CheckFailed("Load operand must be a pointer." , &LI); return; } } while (false); | ||||
3696 | Type *ElTy = LI.getType(); | ||||
3697 | Assert(LI.getAlignment() <= Value::MaximumAlignment,do { if (!(LI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &LI ); return; } } while (false) | ||||
3698 | "huge alignment values are unsupported", &LI)do { if (!(LI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &LI ); return; } } while (false); | ||||
3699 | 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); | ||||
3700 | if (LI.isAtomic()) { | ||||
3701 | 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) | ||||
3702 | LI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
3703 | "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); | ||||
3704 | Assert(LI.getAlignment() != 0,do { if (!(LI.getAlignment() != 0)) { CheckFailed("Atomic load must specify explicit alignment" , &LI); return; } } while (false) | ||||
3705 | "Atomic load must specify explicit alignment", &LI)do { if (!(LI.getAlignment() != 0)) { CheckFailed("Atomic load must specify explicit alignment" , &LI); return; } } while (false); | ||||
3706 | 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) | ||||
3707 | "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) | ||||
3708 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
3709 | 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); | ||||
3710 | checkAtomicMemAccessSize(ElTy, &LI); | ||||
3711 | } else { | ||||
3712 | Assert(LI.getSyncScopeID() == SyncScope::System,do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false) | ||||
3713 | "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); | ||||
3714 | } | ||||
3715 | |||||
3716 | visitInstruction(LI); | ||||
3717 | } | ||||
3718 | |||||
3719 | void Verifier::visitStoreInst(StoreInst &SI) { | ||||
3720 | PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType()); | ||||
3721 | Assert(PTy, "Store operand must be a pointer.", &SI)do { if (!(PTy)) { CheckFailed("Store operand must be a pointer." , &SI); return; } } while (false); | ||||
3722 | Type *ElTy = SI.getOperand(0)->getType(); | ||||
3723 | Assert(PTy->isOpaqueOrPointeeTypeMatches(ElTy),do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false) | ||||
3724 | "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); | ||||
3725 | Assert(SI.getAlignment() <= Value::MaximumAlignment,do { if (!(SI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &SI ); return; } } while (false) | ||||
3726 | "huge alignment values are unsupported", &SI)do { if (!(SI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &SI ); return; } } while (false); | ||||
3727 | 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); | ||||
3728 | if (SI.isAtomic()) { | ||||
3729 | 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) | ||||
3730 | SI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
3731 | "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); | ||||
3732 | Assert(SI.getAlignment() != 0,do { if (!(SI.getAlignment() != 0)) { CheckFailed("Atomic store must specify explicit alignment" , &SI); return; } } while (false) | ||||
3733 | "Atomic store must specify explicit alignment", &SI)do { if (!(SI.getAlignment() != 0)) { CheckFailed("Atomic store must specify explicit alignment" , &SI); return; } } while (false); | ||||
3734 | 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) | ||||
3735 | "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) | ||||
3736 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
3737 | 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); | ||||
3738 | checkAtomicMemAccessSize(ElTy, &SI); | ||||
3739 | } else { | ||||
3740 | Assert(SI.getSyncScopeID() == SyncScope::System,do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false) | ||||
3741 | "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); | ||||
3742 | } | ||||
3743 | visitInstruction(SI); | ||||
3744 | } | ||||
3745 | |||||
3746 | /// Check that SwiftErrorVal is used as a swifterror argument in CS. | ||||
3747 | void Verifier::verifySwiftErrorCall(CallBase &Call, | ||||
3748 | const Value *SwiftErrorVal) { | ||||
3749 | for (const auto &I : llvm::enumerate(Call.args())) { | ||||
3750 | if (I.value() == SwiftErrorVal) { | ||||
3751 | 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) | ||||
3752 | "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) | ||||
3753 | "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) | ||||
3754 | 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); | ||||
3755 | } | ||||
3756 | } | ||||
3757 | } | ||||
3758 | |||||
3759 | void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) { | ||||
3760 | // Check that swifterror value is only used by loads, stores, or as | ||||
3761 | // a swifterror argument. | ||||
3762 | for (const User *U : SwiftErrorVal->users()) { | ||||
3763 | 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) | ||||
3764 | 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) | ||||
3765 | "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) | ||||
3766 | "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) | ||||
3767 | 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); | ||||
3768 | // If it is used by a store, check it is the second operand. | ||||
3769 | if (auto StoreI = dyn_cast<StoreInst>(U)) | ||||
3770 | 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) | ||||
3771 | "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) | ||||
3772 | "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); | ||||
3773 | if (auto *Call = dyn_cast<CallBase>(U)) | ||||
3774 | verifySwiftErrorCall(*const_cast<CallBase *>(Call), SwiftErrorVal); | ||||
3775 | } | ||||
3776 | } | ||||
3777 | |||||
3778 | void Verifier::visitAllocaInst(AllocaInst &AI) { | ||||
3779 | SmallPtrSet<Type*, 4> Visited; | ||||
3780 | Assert(AI.getAllocatedType()->isSized(&Visited),do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false) | ||||
3781 | "Cannot allocate unsized type", &AI)do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false); | ||||
3782 | Assert(AI.getArraySize()->getType()->isIntegerTy(),do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false) | ||||
3783 | "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); | ||||
3784 | Assert(AI.getAlignment() <= Value::MaximumAlignment,do { if (!(AI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &AI ); return; } } while (false) | ||||
3785 | "huge alignment values are unsupported", &AI)do { if (!(AI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &AI ); return; } } while (false); | ||||
3786 | |||||
3787 | if (AI.isSwiftError()) { | ||||
3788 | verifySwiftErrorValue(&AI); | ||||
3789 | } | ||||
3790 | |||||
3791 | visitInstruction(AI); | ||||
3792 | } | ||||
3793 | |||||
3794 | void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { | ||||
3795 | Type *ElTy = CXI.getOperand(1)->getType(); | ||||
3796 | Assert(ElTy->isIntOrPtrTy(),do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false) | ||||
3797 | "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); | ||||
3798 | checkAtomicMemAccessSize(ElTy, &CXI); | ||||
3799 | visitInstruction(CXI); | ||||
3800 | } | ||||
3801 | |||||
3802 | void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { | ||||
3803 | Assert(RMWI.getOrdering() != AtomicOrdering::Unordered,do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false) | ||||
3804 | "atomicrmw instructions cannot be unordered.", &RMWI)do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false); | ||||
3805 | auto Op = RMWI.getOperation(); | ||||
3806 | Type *ElTy = RMWI.getOperand(1)->getType(); | ||||
3807 | if (Op == AtomicRMWInst::Xchg) { | ||||
3808 | 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) | ||||
3809 | 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) | ||||
3810 | " 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) | ||||
3811 | &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); | ||||
3812 | } else if (AtomicRMWInst::isFPOperation(Op)) { | ||||
3813 | Assert(ElTy->isFloatingPointTy(), "atomicrmw " +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
3814 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
3815 | " 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) | ||||
3816 | &RMWI, ElTy)do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false); | ||||
3817 | } else { | ||||
3818 | Assert(ElTy->isIntegerTy(), "atomicrmw " +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
3819 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
3820 | " operand must have integer type!",do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
3821 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false); | ||||
3822 | } | ||||
3823 | checkAtomicMemAccessSize(ElTy, &RMWI); | ||||
3824 | 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) | ||||
3825 | "Invalid binary operation!", &RMWI)do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false); | ||||
3826 | visitInstruction(RMWI); | ||||
3827 | } | ||||
3828 | |||||
3829 | void Verifier::visitFenceInst(FenceInst &FI) { | ||||
3830 | const AtomicOrdering Ordering = FI.getOrdering(); | ||||
3831 | 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) | ||||
3832 | 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) | ||||
3833 | 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) | ||||
3834 | 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) | ||||
3835 | "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) | ||||
3836 | "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) | ||||
3837 | &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); | ||||
3838 | visitInstruction(FI); | ||||
3839 | } | ||||
3840 | |||||
3841 | void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { | ||||
3842 | 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) | ||||
3843 | EVI.getIndices()) == EVI.getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
3844 | "Invalid ExtractValueInst operands!", &EVI)do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false); | ||||
3845 | |||||
3846 | visitInstruction(EVI); | ||||
3847 | } | ||||
3848 | |||||
3849 | void Verifier::visitInsertValueInst(InsertValueInst &IVI) { | ||||
3850 | 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) | ||||
3851 | IVI.getIndices()) ==do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
3852 | 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) | ||||
3853 | "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); | ||||
3854 | |||||
3855 | visitInstruction(IVI); | ||||
3856 | } | ||||
3857 | |||||
3858 | static Value *getParentPad(Value *EHPad) { | ||||
3859 | if (auto *FPI = dyn_cast<FuncletPadInst>(EHPad)) | ||||
3860 | return FPI->getParentPad(); | ||||
3861 | |||||
3862 | return cast<CatchSwitchInst>(EHPad)->getParentPad(); | ||||
3863 | } | ||||
3864 | |||||
3865 | void Verifier::visitEHPadPredecessors(Instruction &I) { | ||||
3866 | assert(I.isEHPad())((void)0); | ||||
3867 | |||||
3868 | BasicBlock *BB = I.getParent(); | ||||
3869 | Function *F = BB->getParent(); | ||||
3870 | |||||
3871 | 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); | ||||
3872 | |||||
3873 | if (auto *LPI = dyn_cast<LandingPadInst>(&I)) { | ||||
3874 | // The landingpad instruction defines its parent as a landing pad block. The | ||||
3875 | // landing pad block may be branched to only by the unwind edge of an | ||||
3876 | // invoke. | ||||
3877 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
3878 | const auto *II = dyn_cast<InvokeInst>(PredBB->getTerminator()); | ||||
3879 | 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) | ||||
3880 | "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) | ||||
3881 | "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) | ||||
3882 | 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); | ||||
3883 | } | ||||
3884 | return; | ||||
3885 | } | ||||
3886 | if (auto *CPI = dyn_cast<CatchPadInst>(&I)) { | ||||
3887 | if (!pred_empty(BB)) | ||||
3888 | 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) | ||||
3889 | "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) | ||||
3890 | "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) | ||||
3891 | CPI)do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false); | ||||
3892 | 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) | ||||
3893 | "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) | ||||
3894 | CPI->getCatchSwitch(), CPI)do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false); | ||||
3895 | return; | ||||
3896 | } | ||||
3897 | |||||
3898 | // Verify that each pred has a legal terminator with a legal to/from EH | ||||
3899 | // pad relationship. | ||||
3900 | Instruction *ToPad = &I; | ||||
3901 | Value *ToPadParent = getParentPad(ToPad); | ||||
3902 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
3903 | Instruction *TI = PredBB->getTerminator(); | ||||
3904 | Value *FromPad; | ||||
3905 | if (auto *II = dyn_cast<InvokeInst>(TI)) { | ||||
3906 | 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) | ||||
3907 | "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); | ||||
3908 | if (auto Bundle = II->getOperandBundle(LLVMContext::OB_funclet)) | ||||
3909 | FromPad = Bundle->Inputs[0]; | ||||
3910 | else | ||||
3911 | FromPad = ConstantTokenNone::get(II->getContext()); | ||||
3912 | } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) { | ||||
3913 | FromPad = CRI->getOperand(0); | ||||
3914 | 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); | ||||
3915 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) { | ||||
3916 | FromPad = CSI; | ||||
3917 | } else { | ||||
3918 | 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); | ||||
3919 | } | ||||
3920 | |||||
3921 | // The edge may exit from zero or more nested pads. | ||||
3922 | SmallSet<Value *, 8> Seen; | ||||
3923 | for (;; FromPad = getParentPad(FromPad)) { | ||||
3924 | Assert(FromPad != ToPad,do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false) | ||||
3925 | "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); | ||||
3926 | if (FromPad == ToPadParent) { | ||||
3927 | // This is a legal unwind edge. | ||||
3928 | break; | ||||
3929 | } | ||||
3930 | Assert(!isa<ConstantTokenNone>(FromPad),do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false) | ||||
3931 | "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); | ||||
3932 | Assert(Seen.insert(FromPad).second,do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false) | ||||
3933 | "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); | ||||
3934 | } | ||||
3935 | } | ||||
3936 | } | ||||
3937 | |||||
3938 | void Verifier::visitLandingPadInst(LandingPadInst &LPI) { | ||||
3939 | // The landingpad instruction is ill-formed if it doesn't have any clauses and | ||||
3940 | // isn't a cleanup. | ||||
3941 | 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) | ||||
3942 | "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); | ||||
3943 | |||||
3944 | visitEHPadPredecessors(LPI); | ||||
3945 | |||||
3946 | if (!LandingPadResultTy) | ||||
3947 | LandingPadResultTy = LPI.getType(); | ||||
3948 | else | ||||
3949 | 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) | ||||
3950 | "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) | ||||
3951 | "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) | ||||
3952 | &LPI)do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false); | ||||
3953 | |||||
3954 | Function *F = LPI.getParent()->getParent(); | ||||
3955 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false) | ||||
3956 | "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); | ||||
3957 | |||||
3958 | // The landingpad instruction must be the first non-PHI instruction in the | ||||
3959 | // block. | ||||
3960 | 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) | ||||
3961 | "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) | ||||
3962 | &LPI)do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false); | ||||
3963 | |||||
3964 | for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) { | ||||
3965 | Constant *Clause = LPI.getClause(i); | ||||
3966 | if (LPI.isCatch(i)) { | ||||
3967 | Assert(isa<PointerType>(Clause->getType()),do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false) | ||||
3968 | "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); | ||||
3969 | } else { | ||||
3970 | 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); | ||||
3971 | 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) | ||||
3972 | "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); | ||||
3973 | } | ||||
3974 | } | ||||
3975 | |||||
3976 | visitInstruction(LPI); | ||||
3977 | } | ||||
3978 | |||||
3979 | void Verifier::visitResumeInst(ResumeInst &RI) { | ||||
3980 | Assert(RI.getFunction()->hasPersonalityFn(),do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false) | ||||
3981 | "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); | ||||
3982 | |||||
3983 | if (!LandingPadResultTy) | ||||
3984 | LandingPadResultTy = RI.getValue()->getType(); | ||||
3985 | else | ||||
3986 | 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) | ||||
3987 | "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) | ||||
3988 | "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) | ||||
3989 | &RI)do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false); | ||||
3990 | |||||
3991 | visitTerminator(RI); | ||||
3992 | } | ||||
3993 | |||||
3994 | void Verifier::visitCatchPadInst(CatchPadInst &CPI) { | ||||
3995 | BasicBlock *BB = CPI.getParent(); | ||||
3996 | |||||
3997 | Function *F = BB->getParent(); | ||||
3998 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
3999 | "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); | ||||
4000 | |||||
4001 | 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) | ||||
4002 | "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) | ||||
4003 | CPI.getParentPad())do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false); | ||||
4004 | |||||
4005 | // The catchpad instruction must be the first non-PHI instruction in the | ||||
4006 | // block. | ||||
4007 | Assert(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
4008 | "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); | ||||
4009 | |||||
4010 | visitEHPadPredecessors(CPI); | ||||
4011 | visitFuncletPadInst(CPI); | ||||
4012 | } | ||||
4013 | |||||
4014 | void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) { | ||||
4015 | 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) | ||||
4016 | "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) | ||||
4017 | 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); | ||||
4018 | |||||
4019 | visitTerminator(CatchReturn); | ||||
4020 | } | ||||
4021 | |||||
4022 | void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { | ||||
4023 | BasicBlock *BB = CPI.getParent(); | ||||
4024 | |||||
4025 | Function *F = BB->getParent(); | ||||
4026 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
4027 | "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); | ||||
4028 | |||||
4029 | // The cleanuppad instruction must be the first non-PHI instruction in the | ||||
4030 | // block. | ||||
4031 | Assert(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
4032 | "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) | ||||
4033 | &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
4034 | |||||
4035 | auto *ParentPad = CPI.getParentPad(); | ||||
4036 | 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) | ||||
4037 | "CleanupPadInst has an invalid parent.", &CPI)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false); | ||||
4038 | |||||
4039 | visitEHPadPredecessors(CPI); | ||||
4040 | visitFuncletPadInst(CPI); | ||||
4041 | } | ||||
4042 | |||||
4043 | void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { | ||||
4044 | User *FirstUser = nullptr; | ||||
4045 | Value *FirstUnwindPad = nullptr; | ||||
4046 | SmallVector<FuncletPadInst *, 8> Worklist({&FPI}); | ||||
4047 | SmallSet<FuncletPadInst *, 8> Seen; | ||||
4048 | |||||
4049 | while (!Worklist.empty()) { | ||||
4050 | FuncletPadInst *CurrentPad = Worklist.pop_back_val(); | ||||
4051 | Assert(Seen.insert(CurrentPad).second,do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false) | ||||
4052 | "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); | ||||
4053 | Value *UnresolvedAncestorPad = nullptr; | ||||
4054 | for (User *U : CurrentPad->users()) { | ||||
4055 | BasicBlock *UnwindDest; | ||||
4056 | if (auto *CRI = dyn_cast<CleanupReturnInst>(U)) { | ||||
4057 | UnwindDest = CRI->getUnwindDest(); | ||||
4058 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(U)) { | ||||
4059 | // We allow catchswitch unwind to caller to nest | ||||
4060 | // within an outer pad that unwinds somewhere else, | ||||
4061 | // because catchswitch doesn't have a nounwind variant. | ||||
4062 | // See e.g. SimplifyCFGOpt::SimplifyUnreachable. | ||||
4063 | if (CSI->unwindsToCaller()) | ||||
4064 | continue; | ||||
4065 | UnwindDest = CSI->getUnwindDest(); | ||||
4066 | } else if (auto *II = dyn_cast<InvokeInst>(U)) { | ||||
4067 | UnwindDest = II->getUnwindDest(); | ||||
4068 | } else if (isa<CallInst>(U)) { | ||||
4069 | // Calls which don't unwind may be found inside funclet | ||||
4070 | // pads that unwind somewhere else. We don't *require* | ||||
4071 | // such calls to be annotated nounwind. | ||||
4072 | continue; | ||||
4073 | } else if (auto *CPI = dyn_cast<CleanupPadInst>(U)) { | ||||
4074 | // The unwind dest for a cleanup can only be found by | ||||
4075 | // recursive search. Add it to the worklist, and we'll | ||||
4076 | // search for its first use that determines where it unwinds. | ||||
4077 | Worklist.push_back(CPI); | ||||
4078 | continue; | ||||
4079 | } else { | ||||
4080 | Assert(isa<CatchReturnInst>(U), "Bogus funclet pad use", U)do { if (!(isa<CatchReturnInst>(U))) { CheckFailed("Bogus funclet pad use" , U); return; } } while (false); | ||||
4081 | continue; | ||||
4082 | } | ||||
4083 | |||||
4084 | Value *UnwindPad; | ||||
4085 | bool ExitsFPI; | ||||
4086 | if (UnwindDest) { | ||||
4087 | UnwindPad = UnwindDest->getFirstNonPHI(); | ||||
4088 | if (!cast<Instruction>(UnwindPad)->isEHPad()) | ||||
4089 | continue; | ||||
4090 | Value *UnwindParent = getParentPad(UnwindPad); | ||||
4091 | // Ignore unwind edges that don't exit CurrentPad. | ||||
4092 | if (UnwindParent == CurrentPad) | ||||
4093 | continue; | ||||
4094 | // Determine whether the original funclet pad is exited, | ||||
4095 | // and if we are scanning nested pads determine how many | ||||
4096 | // of them are exited so we can stop searching their | ||||
4097 | // children. | ||||
4098 | Value *ExitedPad = CurrentPad; | ||||
4099 | ExitsFPI = false; | ||||
4100 | do { | ||||
4101 | if (ExitedPad == &FPI) { | ||||
4102 | ExitsFPI = true; | ||||
4103 | // Now we can resolve any ancestors of CurrentPad up to | ||||
4104 | // FPI, but not including FPI since we need to make sure | ||||
4105 | // to check all direct users of FPI for consistency. | ||||
4106 | UnresolvedAncestorPad = &FPI; | ||||
4107 | break; | ||||
4108 | } | ||||
4109 | Value *ExitedParent = getParentPad(ExitedPad); | ||||
4110 | if (ExitedParent == UnwindParent) { | ||||
4111 | // ExitedPad is the ancestor-most pad which this unwind | ||||
4112 | // edge exits, so we can resolve up to it, meaning that | ||||
4113 | // ExitedParent is the first ancestor still unresolved. | ||||
4114 | UnresolvedAncestorPad = ExitedParent; | ||||
4115 | break; | ||||
4116 | } | ||||
4117 | ExitedPad = ExitedParent; | ||||
4118 | } while (!isa<ConstantTokenNone>(ExitedPad)); | ||||
4119 | } else { | ||||
4120 | // Unwinding to caller exits all pads. | ||||
4121 | UnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
4122 | ExitsFPI = true; | ||||
4123 | UnresolvedAncestorPad = &FPI; | ||||
4124 | } | ||||
4125 | |||||
4126 | if (ExitsFPI) { | ||||
4127 | // This unwind edge exits FPI. Make sure it agrees with other | ||||
4128 | // such edges. | ||||
4129 | if (FirstUser) { | ||||
4130 | 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) | ||||
4131 | "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) | ||||
4132 | "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) | ||||
4133 | &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); | ||||
4134 | } else { | ||||
4135 | FirstUser = U; | ||||
4136 | FirstUnwindPad = UnwindPad; | ||||
4137 | // Record cleanup sibling unwinds for verifySiblingFuncletUnwinds | ||||
4138 | if (isa<CleanupPadInst>(&FPI) && !isa<ConstantTokenNone>(UnwindPad) && | ||||
4139 | getParentPad(UnwindPad) == getParentPad(&FPI)) | ||||
4140 | SiblingFuncletInfo[&FPI] = cast<Instruction>(U); | ||||
4141 | } | ||||
4142 | } | ||||
4143 | // Make sure we visit all uses of FPI, but for nested pads stop as | ||||
4144 | // soon as we know where they unwind to. | ||||
4145 | if (CurrentPad != &FPI) | ||||
4146 | break; | ||||
4147 | } | ||||
4148 | if (UnresolvedAncestorPad) { | ||||
4149 | if (CurrentPad == UnresolvedAncestorPad) { | ||||
4150 | // When CurrentPad is FPI itself, we don't mark it as resolved even if | ||||
4151 | // we've found an unwind edge that exits it, because we need to verify | ||||
4152 | // all direct uses of FPI. | ||||
4153 | assert(CurrentPad == &FPI)((void)0); | ||||
4154 | continue; | ||||
4155 | } | ||||
4156 | // Pop off the worklist any nested pads that we've found an unwind | ||||
4157 | // destination for. The pads on the worklist are the uncles, | ||||
4158 | // great-uncles, etc. of CurrentPad. We've found an unwind destination | ||||
4159 | // for all ancestors of CurrentPad up to but not including | ||||
4160 | // UnresolvedAncestorPad. | ||||
4161 | Value *ResolvedPad = CurrentPad; | ||||
4162 | while (!Worklist.empty()) { | ||||
4163 | Value *UnclePad = Worklist.back(); | ||||
4164 | Value *AncestorPad = getParentPad(UnclePad); | ||||
4165 | // Walk ResolvedPad up the ancestor list until we either find the | ||||
4166 | // uncle's parent or the last resolved ancestor. | ||||
4167 | while (ResolvedPad != AncestorPad) { | ||||
4168 | Value *ResolvedParent = getParentPad(ResolvedPad); | ||||
4169 | if (ResolvedParent == UnresolvedAncestorPad) { | ||||
4170 | break; | ||||
4171 | } | ||||
4172 | ResolvedPad = ResolvedParent; | ||||
4173 | } | ||||
4174 | // If the resolved ancestor search didn't find the uncle's parent, | ||||
4175 | // then the uncle is not yet resolved. | ||||
4176 | if (ResolvedPad != AncestorPad) | ||||
4177 | break; | ||||
4178 | // This uncle is resolved, so pop it from the worklist. | ||||
4179 | Worklist.pop_back(); | ||||
4180 | } | ||||
4181 | } | ||||
4182 | } | ||||
4183 | |||||
4184 | if (FirstUnwindPad) { | ||||
4185 | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FPI.getParentPad())) { | ||||
4186 | BasicBlock *SwitchUnwindDest = CatchSwitch->getUnwindDest(); | ||||
4187 | Value *SwitchUnwindPad; | ||||
4188 | if (SwitchUnwindDest) | ||||
4189 | SwitchUnwindPad = SwitchUnwindDest->getFirstNonPHI(); | ||||
4190 | else | ||||
4191 | SwitchUnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
4192 | 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) | ||||
4193 | "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) | ||||
4194 | "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) | ||||
4195 | &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); | ||||
4196 | } | ||||
4197 | } | ||||
4198 | |||||
4199 | visitInstruction(FPI); | ||||
4200 | } | ||||
4201 | |||||
4202 | void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) { | ||||
4203 | BasicBlock *BB = CatchSwitch.getParent(); | ||||
4204 | |||||
4205 | Function *F = BB->getParent(); | ||||
4206 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
4207 | "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) | ||||
4208 | &CatchSwitch)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false); | ||||
4209 | |||||
4210 | // The catchswitch instruction must be the first non-PHI instruction in the | ||||
4211 | // block. | ||||
4212 | Assert(BB->getFirstNonPHI() == &CatchSwitch,do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
4213 | "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) | ||||
4214 | &CatchSwitch)do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false); | ||||
4215 | |||||
4216 | auto *ParentPad = CatchSwitch.getParentPad(); | ||||
4217 | 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) | ||||
4218 | "CatchSwitchInst has an invalid parent.", ParentPad)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false); | ||||
4219 | |||||
4220 | if (BasicBlock *UnwindDest = CatchSwitch.getUnwindDest()) { | ||||
4221 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
4222 | 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) | ||||
4223 | "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) | ||||
4224 | "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) | ||||
4225 | &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); | ||||
4226 | |||||
4227 | // Record catchswitch sibling unwinds for verifySiblingFuncletUnwinds | ||||
4228 | if (getParentPad(I) == ParentPad) | ||||
4229 | SiblingFuncletInfo[&CatchSwitch] = &CatchSwitch; | ||||
4230 | } | ||||
4231 | |||||
4232 | Assert(CatchSwitch.getNumHandlers() != 0,do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false) | ||||
4233 | "CatchSwitchInst cannot have empty handler list", &CatchSwitch)do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false); | ||||
4234 | |||||
4235 | for (BasicBlock *Handler : CatchSwitch.handlers()) { | ||||
4236 | Assert(isa<CatchPadInst>(Handler->getFirstNonPHI()),do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false) | ||||
4237 | "CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler)do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false); | ||||
4238 | } | ||||
4239 | |||||
4240 | visitEHPadPredecessors(CatchSwitch); | ||||
4241 | visitTerminator(CatchSwitch); | ||||
4242 | } | ||||
4243 | |||||
4244 | void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) { | ||||
4245 | 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) | ||||
4246 | "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) | ||||
4247 | 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); | ||||
4248 | |||||
4249 | if (BasicBlock *UnwindDest = CRI.getUnwindDest()) { | ||||
4250 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
4251 | 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) | ||||
4252 | "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) | ||||
4253 | "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) | ||||
4254 | &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); | ||||
4255 | } | ||||
4256 | |||||
4257 | visitTerminator(CRI); | ||||
4258 | } | ||||
4259 | |||||
4260 | void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { | ||||
4261 | Instruction *Op = cast<Instruction>(I.getOperand(i)); | ||||
4262 | // If the we have an invalid invoke, don't try to compute the dominance. | ||||
4263 | // We already reject it in the invoke specific checks and the dominance | ||||
4264 | // computation doesn't handle multiple edges. | ||||
4265 | if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) { | ||||
4266 | if (II->getNormalDest() == II->getUnwindDest()) | ||||
4267 | return; | ||||
4268 | } | ||||
4269 | |||||
4270 | // Quick check whether the def has already been encountered in the same block. | ||||
4271 | // PHI nodes are not checked to prevent accepting preceding PHIs, because PHI | ||||
4272 | // uses are defined to happen on the incoming edge, not at the instruction. | ||||
4273 | // | ||||
4274 | // FIXME: If this operand is a MetadataAsValue (wrapping a LocalAsMetadata) | ||||
4275 | // wrapping an SSA value, assert that we've already encountered it. See | ||||
4276 | // related FIXME in Mapper::mapLocalAsMetadata in ValueMapper.cpp. | ||||
4277 | if (!isa<PHINode>(I) && InstsInThisBlock.count(Op)) | ||||
4278 | return; | ||||
4279 | |||||
4280 | const Use &U = I.getOperandUse(i); | ||||
4281 | Assert(DT.dominates(Op, U),do { if (!(DT.dominates(Op, U))) { CheckFailed("Instruction does not dominate all uses!" , Op, &I); return; } } while (false) | ||||
4282 | "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); | ||||
4283 | } | ||||
4284 | |||||
4285 | void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) { | ||||
4286 | 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 ) | ||||
4287 | "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 ); | ||||
4288 | 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) | ||||
4289 | "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) | ||||
4290 | " 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); | ||||
4291 | 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) | ||||
4292 | "take one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false); | ||||
4293 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0)); | ||||
4294 | 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) | ||||
4295 | "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); | ||||
4296 | } | ||||
4297 | |||||
4298 | void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) { | ||||
4299 | Assert(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
4300 | "!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); | ||||
4301 | |||||
4302 | // Check first operand. | ||||
4303 | 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); | ||||
4304 | 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) | ||||
4305 | "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); | ||||
4306 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
4307 | StringRef ProfName = MDS->getString(); | ||||
4308 | |||||
4309 | // Check consistency of !prof branch_weights metadata. | ||||
4310 | if (ProfName.equals("branch_weights")) { | ||||
4311 | if (isa<InvokeInst>(&I)) { | ||||
4312 | 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) | ||||
4313 | "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); | ||||
4314 | } else { | ||||
4315 | unsigned ExpectedNumOperands = 0; | ||||
4316 | if (BranchInst *BI = dyn_cast<BranchInst>(&I)) | ||||
4317 | ExpectedNumOperands = BI->getNumSuccessors(); | ||||
4318 | else if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) | ||||
4319 | ExpectedNumOperands = SI->getNumSuccessors(); | ||||
4320 | else if (isa<CallInst>(&I)) | ||||
4321 | ExpectedNumOperands = 1; | ||||
4322 | else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(&I)) | ||||
4323 | ExpectedNumOperands = IBI->getNumDestinations(); | ||||
4324 | else if (isa<SelectInst>(&I)) | ||||
4325 | ExpectedNumOperands = 2; | ||||
4326 | else | ||||
4327 | CheckFailed("!prof branch_weights are not allowed for this instruction", | ||||
4328 | MD); | ||||
4329 | |||||
4330 | Assert(MD->getNumOperands() == 1 + ExpectedNumOperands,do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false) | ||||
4331 | "Wrong number of operands", MD)do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false); | ||||
4332 | } | ||||
4333 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) { | ||||
4334 | auto &MDO = MD->getOperand(i); | ||||
4335 | Assert(MDO, "second operand should not be null", MD)do { if (!(MDO)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
4336 | 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) | ||||
4337 | "!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); | ||||
4338 | } | ||||
4339 | } | ||||
4340 | } | ||||
4341 | |||||
4342 | void Verifier::visitAnnotationMetadata(MDNode *Annotation) { | ||||
4343 | Assert(isa<MDTuple>(Annotation), "annotation must be a tuple")do { if (!(isa<MDTuple>(Annotation))) { CheckFailed("annotation must be a tuple" ); return; } } while (false); | ||||
4344 | Assert(Annotation->getNumOperands() >= 1,do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false) | ||||
4345 | "annotation must have at least one operand")do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false); | ||||
4346 | for (const MDOperand &Op : Annotation->operands()) | ||||
4347 | Assert(isa<MDString>(Op.get()), "operands must be strings")do { if (!(isa<MDString>(Op.get()))) { CheckFailed("operands must be strings" ); return; } } while (false); | ||||
4348 | } | ||||
4349 | |||||
4350 | /// verifyInstruction - Verify that an instruction is well formed. | ||||
4351 | /// | ||||
4352 | void Verifier::visitInstruction(Instruction &I) { | ||||
4353 | BasicBlock *BB = I.getParent(); | ||||
4354 | Assert(BB, "Instruction not embedded in basic block!", &I)do { if (!(BB)) { CheckFailed("Instruction not embedded in basic block!" , &I); return; } } while (false); | ||||
4355 | |||||
4356 | if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential | ||||
4357 | for (User *U : I.users()) { | ||||
4358 | 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) | ||||
4359 | "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); | ||||
4360 | } | ||||
4361 | } | ||||
4362 | |||||
4363 | // Check that void typed values don't have names | ||||
4364 | 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) | ||||
4365 | "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); | ||||
4366 | |||||
4367 | // Check that the return value of the instruction is either void or a legal | ||||
4368 | // value type. | ||||
4369 | 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) | ||||
4370 | "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); | ||||
4371 | |||||
4372 | // Check that the instruction doesn't produce metadata. Calls are already | ||||
4373 | // checked against the callee type. | ||||
4374 | 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) | ||||
4375 | "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); | ||||
4376 | |||||
4377 | // Check that all uses of the instruction, if they are instructions | ||||
4378 | // themselves, actually have parent basic blocks. If the use is not an | ||||
4379 | // instruction, it is an error! | ||||
4380 | for (Use &U : I.uses()) { | ||||
4381 | if (Instruction *Used = dyn_cast<Instruction>(U.getUser())) | ||||
4382 | Assert(Used->getParent() != nullptr,do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
4383 | "Instruction referencing"do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
4384 | " 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) | ||||
4385 | &I, Used)do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false); | ||||
4386 | else { | ||||
4387 | CheckFailed("Use of instruction is not an instruction!", U); | ||||
4388 | return; | ||||
4389 | } | ||||
4390 | } | ||||
4391 | |||||
4392 | // Get a pointer to the call base of the instruction if it is some form of | ||||
4393 | // call. | ||||
4394 | const CallBase *CBI = dyn_cast<CallBase>(&I); | ||||
4395 | |||||
4396 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { | ||||
4397 | 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); | ||||
4398 | |||||
4399 | // Check to make sure that only first-class-values are operands to | ||||
4400 | // instructions. | ||||
4401 | if (!I.getOperand(i)->getType()->isFirstClassType()) { | ||||
4402 | 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); | ||||
4403 | } | ||||
4404 | |||||
4405 | if (Function *F = dyn_cast<Function>(I.getOperand(i))) { | ||||
4406 | // Check to make sure that the "address of" an intrinsic function is never | ||||
4407 | // taken. | ||||
4408 | 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) | ||||
4409 | (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) | ||||
4410 | "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); | ||||
4411 | 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) | ||||
4412 | !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) | ||||
4413 | 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) | ||||
4414 | 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) | ||||
4415 | 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) | ||||
4416 | 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) | ||||
4417 | 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) | ||||
4418 | 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) | ||||
4419 | 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) | ||||
4420 | 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) | ||||
4421 | 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) | ||||
4422 | 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) | ||||
4423 | 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) | ||||
4424 | "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) | ||||
4425 | "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) | ||||
4426 | &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); | ||||
4427 | 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 ) | ||||
4428 | &I, &M, F, F->getParent())do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ); | ||||
4429 | } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { | ||||
4430 | Assert(OpBB->getParent() == BB->getParent(),do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false) | ||||
4431 | "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); | ||||
4432 | } else if (Argument *OpArg = dyn_cast<Argument>(I.getOperand(i))) { | ||||
4433 | Assert(OpArg->getParent() == BB->getParent(),do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false) | ||||
4434 | "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); | ||||
4435 | } else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) { | ||||
4436 | 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) | ||||
4437 | &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false); | ||||
4438 | } else if (isa<Instruction>(I.getOperand(i))) { | ||||
4439 | verifyDominatesUse(I, i); | ||||
4440 | } else if (isa<InlineAsm>(I.getOperand(i))) { | ||||
4441 | 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) | ||||
4442 | "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); | ||||
4443 | } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { | ||||
4444 | if (CE->getType()->isPtrOrPtrVectorTy()) { | ||||
4445 | // If we have a ConstantExpr pointer, we need to see if it came from an | ||||
4446 | // illegal bitcast. | ||||
4447 | visitConstantExprsRecursively(CE); | ||||
4448 | } | ||||
4449 | } | ||||
4450 | } | ||||
4451 | |||||
4452 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_fpmath)) { | ||||
4453 | Assert(I.getType()->isFPOrFPVectorTy(),do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false) | ||||
4454 | "fpmath requires a floating point result!", &I)do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false); | ||||
4455 | Assert(MD->getNumOperands() == 1, "fpmath takes one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("fpmath takes one operand!" , &I); return; } } while (false); | ||||
4456 | if (ConstantFP *CFP0 = | ||||
4457 | mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { | ||||
4458 | const APFloat &Accuracy = CFP0->getValueAPF(); | ||||
4459 | Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle(),do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false) | ||||
4460 | "fpmath accuracy must have float type", &I)do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false); | ||||
4461 | Assert(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(),do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false) | ||||
4462 | "fpmath accuracy not a positive number!", &I)do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false); | ||||
4463 | } else { | ||||
4464 | Assert(false, "invalid fpmath accuracy!", &I)do { if (!(false)) { CheckFailed("invalid fpmath accuracy!", & I); return; } } while (false); | ||||
4465 | } | ||||
4466 | } | ||||
4467 | |||||
4468 | if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) { | ||||
4469 | 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) | ||||
4470 | "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); | ||||
4471 | visitRangeMetadata(I, Range, I.getType()); | ||||
4472 | } | ||||
4473 | |||||
4474 | if (I.getMetadata(LLVMContext::MD_nonnull)) { | ||||
4475 | 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) | ||||
4476 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false); | ||||
4477 | 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) | ||||
4478 | "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) | ||||
4479 | " 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) | ||||
4480 | &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false); | ||||
4481 | } | ||||
4482 | |||||
4483 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable)) | ||||
4484 | visitDereferenceableMetadata(I, MD); | ||||
4485 | |||||
4486 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) | ||||
4487 | visitDereferenceableMetadata(I, MD); | ||||
4488 | |||||
4489 | if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) | ||||
4490 | TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); | ||||
4491 | |||||
4492 | if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { | ||||
4493 | 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) | ||||
4494 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false); | ||||
4495 | 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) | ||||
4496 | "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); | ||||
4497 | Assert(AlignMD->getNumOperands() == 1, "align takes one operand!", &I)do { if (!(AlignMD->getNumOperands() == 1)) { CheckFailed( "align takes one operand!", &I); return; } } while (false ); | ||||
4498 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(AlignMD->getOperand(0)); | ||||
4499 | 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) | ||||
4500 | "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); | ||||
4501 | uint64_t Align = CI->getZExtValue(); | ||||
4502 | Assert(isPowerOf2_64(Align),do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false) | ||||
4503 | "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); | ||||
4504 | Assert(Align <= Value::MaximumAlignment,do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false) | ||||
4505 | "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); | ||||
4506 | } | ||||
4507 | |||||
4508 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_prof)) | ||||
4509 | visitProfMetadata(I, MD); | ||||
4510 | |||||
4511 | if (MDNode *Annotation = I.getMetadata(LLVMContext::MD_annotation)) | ||||
4512 | visitAnnotationMetadata(Annotation); | ||||
4513 | |||||
4514 | if (MDNode *N = I.getDebugLoc().getAsMDNode()) { | ||||
4515 | 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); | ||||
4516 | visitMDNode(*N, AreDebugLocsAllowed::Yes); | ||||
4517 | } | ||||
4518 | |||||
4519 | if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { | ||||
4520 | verifyFragmentExpression(*DII); | ||||
4521 | verifyNotEntryValue(*DII); | ||||
4522 | } | ||||
4523 | |||||
4524 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
4525 | I.getAllMetadata(MDs); | ||||
4526 | for (auto Attachment : MDs) { | ||||
4527 | unsigned Kind = Attachment.first; | ||||
4528 | auto AllowLocs = | ||||
4529 | (Kind == LLVMContext::MD_dbg || Kind == LLVMContext::MD_loop) | ||||
4530 | ? AreDebugLocsAllowed::Yes | ||||
4531 | : AreDebugLocsAllowed::No; | ||||
4532 | visitMDNode(*Attachment.second, AllowLocs); | ||||
4533 | } | ||||
4534 | |||||
4535 | InstsInThisBlock.insert(&I); | ||||
4536 | } | ||||
4537 | |||||
4538 | /// Allow intrinsics to be verified in different ways. | ||||
4539 | void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { | ||||
4540 | Function *IF = Call.getCalledFunction(); | ||||
4541 | Assert(IF->isDeclaration(), "Intrinsic functions should never be defined!",do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false) | ||||
4542 | IF)do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false); | ||||
4543 | |||||
4544 | // Verify that the intrinsic prototype lines up with what the .td files | ||||
4545 | // describe. | ||||
4546 | FunctionType *IFTy = IF->getFunctionType(); | ||||
4547 | bool IsVarArg = IFTy->isVarArg(); | ||||
4548 | |||||
4549 | SmallVector<Intrinsic::IITDescriptor, 8> Table; | ||||
4550 | getIntrinsicInfoTableEntries(ID, Table); | ||||
4551 | ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; | ||||
4552 | |||||
4553 | // Walk the descriptors to extract overloaded types. | ||||
4554 | SmallVector<Type *, 4> ArgTys; | ||||
4555 | Intrinsic::MatchIntrinsicTypesResult Res = | ||||
4556 | Intrinsic::matchIntrinsicSignature(IFTy, TableRef, ArgTys); | ||||
4557 | Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false) | ||||
4558 | "Intrinsic has incorrect return type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false); | ||||
4559 | Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false) | ||||
4560 | "Intrinsic has incorrect argument type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false); | ||||
4561 | |||||
4562 | // Verify if the intrinsic call matches the vararg property. | ||||
4563 | if (IsVarArg) | ||||
4564 | Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false) | ||||
4565 | "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); | ||||
4566 | else | ||||
4567 | Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false) | ||||
4568 | "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); | ||||
4569 | |||||
4570 | // All descriptors should be absorbed by now. | ||||
4571 | Assert(TableRef.empty(), "Intrinsic has too few arguments!", IF)do { if (!(TableRef.empty())) { CheckFailed("Intrinsic has too few arguments!" , IF); return; } } while (false); | ||||
4572 | |||||
4573 | // Now that we have the intrinsic ID and the actual argument types (and we | ||||
4574 | // know they are legal for the intrinsic!) get the intrinsic name through the | ||||
4575 | // usual means. This allows us to verify the mangling of argument types into | ||||
4576 | // the name. | ||||
4577 | const std::string ExpectedName = | ||||
4578 | Intrinsic::getName(ID, ArgTys, IF->getParent(), IFTy); | ||||
4579 | 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) | ||||
4580 | "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) | ||||
4581 | "Should be: " +do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
4582 | ExpectedName,do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
4583 | IF)do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false); | ||||
4584 | |||||
4585 | // If the intrinsic takes MDNode arguments, verify that they are either global | ||||
4586 | // or are local to *this* function. | ||||
4587 | for (Value *V : Call.args()) { | ||||
4588 | if (auto *MD = dyn_cast<MetadataAsValue>(V)) | ||||
4589 | visitMetadataAsValue(*MD, Call.getCaller()); | ||||
4590 | if (auto *Const = dyn_cast<Constant>(V)) | ||||
4591 | Assert(!Const->getType()->isX86_AMXTy(),do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false) | ||||
4592 | "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); | ||||
4593 | } | ||||
4594 | |||||
4595 | switch (ID) { | ||||
4596 | default: | ||||
4597 | break; | ||||
4598 | case Intrinsic::assume: { | ||||
4599 | for (auto &Elem : Call.bundle_op_infos()) { | ||||
4600 | 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) | ||||
4601 | 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) | ||||
4602 | "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); | ||||
4603 | Attribute::AttrKind Kind = | ||||
4604 | Attribute::getAttrKindFromName(Elem.Tag->getKey()); | ||||
4605 | unsigned ArgCount = Elem.End - Elem.Begin; | ||||
4606 | if (Kind == Attribute::Alignment) { | ||||
4607 | Assert(ArgCount <= 3 && ArgCount >= 2,do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments"); return ; } } while (false) | ||||
4608 | "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); | ||||
4609 | 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) | ||||
4610 | "first argument should be a pointer")do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer"); return ; } } while (false); | ||||
4611 | 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) | ||||
4612 | "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); | ||||
4613 | if (ArgCount == 3) | ||||
4614 | 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) | ||||
4615 | "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); | ||||
4616 | return; | ||||
4617 | } | ||||
4618 | Assert(ArgCount <= 2, "to many arguments")do { if (!(ArgCount <= 2)) { CheckFailed("to many arguments" ); return; } } while (false); | ||||
4619 | if (Kind == Attribute::None) | ||||
4620 | break; | ||||
4621 | if (Attribute::isIntAttrKind(Kind)) { | ||||
4622 | Assert(ArgCount == 2, "this attribute should have 2 arguments")do { if (!(ArgCount == 2)) { CheckFailed("this attribute should have 2 arguments" ); return; } } while (false); | ||||
4623 | 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) | ||||
4624 | "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); | ||||
4625 | } else if (Attribute::canUseAsParamAttr(Kind)) { | ||||
4626 | Assert((ArgCount) == 1, "this attribute should have one argument")do { if (!((ArgCount) == 1)) { CheckFailed("this attribute should have one argument" ); return; } } while (false); | ||||
4627 | } else if (Attribute::canUseAsFnAttr(Kind)) { | ||||
4628 | Assert((ArgCount) == 0, "this attribute has no argument")do { if (!((ArgCount) == 0)) { CheckFailed("this attribute has no argument" ); return; } } while (false); | ||||
4629 | } | ||||
4630 | } | ||||
4631 | break; | ||||
4632 | } | ||||
4633 | case Intrinsic::coro_id: { | ||||
4634 | auto *InfoArg = Call.getArgOperand(3)->stripPointerCasts(); | ||||
4635 | if (isa<ConstantPointerNull>(InfoArg)) | ||||
4636 | break; | ||||
4637 | auto *GV = dyn_cast<GlobalVariable>(InfoArg); | ||||
4638 | 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) | ||||
4639 | "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) | ||||
4640 | "constant")do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false); | ||||
4641 | Constant *Init = GV->getInitializer(); | ||||
4642 | 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) | ||||
4643 | "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) | ||||
4644 | "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); | ||||
4645 | break; | ||||
4646 | } | ||||
4647 | #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ | ||||
4648 | case Intrinsic::INTRINSIC: | ||||
4649 | #include "llvm/IR/ConstrainedOps.def" | ||||
4650 | visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(Call)); | ||||
4651 | break; | ||||
4652 | case Intrinsic::dbg_declare: // llvm.dbg.declare | ||||
4653 | 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) | ||||
4654 | "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); | ||||
4655 | visitDbgIntrinsic("declare", cast<DbgVariableIntrinsic>(Call)); | ||||
4656 | break; | ||||
4657 | case Intrinsic::dbg_addr: // llvm.dbg.addr | ||||
4658 | visitDbgIntrinsic("addr", cast<DbgVariableIntrinsic>(Call)); | ||||
4659 | break; | ||||
4660 | case Intrinsic::dbg_value: // llvm.dbg.value | ||||
4661 | visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call)); | ||||
4662 | break; | ||||
4663 | case Intrinsic::dbg_label: // llvm.dbg.label | ||||
4664 | visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call)); | ||||
4665 | break; | ||||
4666 | case Intrinsic::memcpy: | ||||
4667 | case Intrinsic::memcpy_inline: | ||||
4668 | case Intrinsic::memmove: | ||||
4669 | case Intrinsic::memset: { | ||||
4670 | const auto *MI = cast<MemIntrinsic>(&Call); | ||||
4671 | auto IsValidAlignment = [&](unsigned Alignment) -> bool { | ||||
4672 | return Alignment == 0 || isPowerOf2_32(Alignment); | ||||
4673 | }; | ||||
4674 | 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) | ||||
4675 | "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) | ||||
4676 | 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); | ||||
4677 | if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) { | ||||
4678 | 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) | ||||
4679 | "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) | ||||
4680 | 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); | ||||
4681 | } | ||||
4682 | |||||
4683 | break; | ||||
4684 | } | ||||
4685 | case Intrinsic::memcpy_element_unordered_atomic: | ||||
4686 | case Intrinsic::memmove_element_unordered_atomic: | ||||
4687 | case Intrinsic::memset_element_unordered_atomic: { | ||||
4688 | const auto *AMI = cast<AtomicMemIntrinsic>(&Call); | ||||
4689 | |||||
4690 | ConstantInt *ElementSizeCI = | ||||
4691 | cast<ConstantInt>(AMI->getRawElementSizeInBytes()); | ||||
4692 | const APInt &ElementSizeVal = ElementSizeCI->getValue(); | ||||
4693 | 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) | ||||
4694 | "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) | ||||
4695 | "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) | ||||
4696 | 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); | ||||
4697 | |||||
4698 | auto IsValidAlignment = [&](uint64_t Alignment) { | ||||
4699 | return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment); | ||||
4700 | }; | ||||
4701 | uint64_t DstAlignment = AMI->getDestAlignment(); | ||||
4702 | Assert(IsValidAlignment(DstAlignment),do { if (!(IsValidAlignment(DstAlignment))) { CheckFailed("incorrect alignment of the destination argument" , Call); return; } } while (false) | ||||
4703 | "incorrect alignment of the destination argument", Call)do { if (!(IsValidAlignment(DstAlignment))) { CheckFailed("incorrect alignment of the destination argument" , Call); return; } } while (false); | ||||
4704 | if (const auto *AMT = dyn_cast<AtomicMemTransferInst>(AMI)) { | ||||
4705 | uint64_t SrcAlignment = AMT->getSourceAlignment(); | ||||
4706 | Assert(IsValidAlignment(SrcAlignment),do { if (!(IsValidAlignment(SrcAlignment))) { CheckFailed("incorrect alignment of the source argument" , Call); return; } } while (false) | ||||
4707 | "incorrect alignment of the source argument", Call)do { if (!(IsValidAlignment(SrcAlignment))) { CheckFailed("incorrect alignment of the source argument" , Call); return; } } while (false); | ||||
4708 | } | ||||
4709 | break; | ||||
4710 | } | ||||
4711 | case Intrinsic::call_preallocated_setup: { | ||||
4712 | auto *NumArgs = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
4713 | Assert(NumArgs != nullptr,do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false) | ||||
4714 | "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); | ||||
4715 | bool FoundCall = false; | ||||
4716 | for (User *U : Call.users()) { | ||||
4717 | auto *UseCall = dyn_cast<CallBase>(U); | ||||
4718 | Assert(UseCall != nullptr,do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false) | ||||
4719 | "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); | ||||
4720 | const Function *Fn = UseCall->getCalledFunction(); | ||||
4721 | if (Fn && Fn->getIntrinsicID() == Intrinsic::call_preallocated_arg) { | ||||
4722 | auto *AllocArgIndex = dyn_cast<ConstantInt>(UseCall->getArgOperand(1)); | ||||
4723 | Assert(AllocArgIndex != nullptr,do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false) | ||||
4724 | "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); | ||||
4725 | auto AllocArgIndexInt = AllocArgIndex->getValue(); | ||||
4726 | 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) | ||||
4727 | 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) | ||||
4728 | "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) | ||||
4729 | "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) | ||||
4730 | "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); | ||||
4731 | } else if (Fn && Fn->getIntrinsicID() == | ||||
4732 | Intrinsic::call_preallocated_teardown) { | ||||
4733 | // nothing to do | ||||
4734 | } else { | ||||
4735 | 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) | ||||
4736 | "llvm.call.preallocated.setup")do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
4737 | FoundCall = true; | ||||
4738 | size_t NumPreallocatedArgs = 0; | ||||
4739 | for (unsigned i = 0; i < UseCall->getNumArgOperands(); i++) { | ||||
4740 | if (UseCall->paramHasAttr(i, Attribute::Preallocated)) { | ||||
4741 | ++NumPreallocatedArgs; | ||||
4742 | } | ||||
4743 | } | ||||
4744 | Assert(NumPreallocatedArgs != 0,do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
4745 | "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) | ||||
4746 | "preallocated arguments")do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false); | ||||
4747 | 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) | ||||
4748 | "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) | ||||
4749 | "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) | ||||
4750 | "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) | ||||
4751 | 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); | ||||
4752 | // getOperandBundle() cannot be called if more than one of the operand | ||||
4753 | // bundle exists. There is already a check elsewhere for this, so skip | ||||
4754 | // here if we see more than one. | ||||
4755 | if (UseCall->countOperandBundlesOfType(LLVMContext::OB_preallocated) > | ||||
4756 | 1) { | ||||
4757 | return; | ||||
4758 | } | ||||
4759 | auto PreallocatedBundle = | ||||
4760 | UseCall->getOperandBundle(LLVMContext::OB_preallocated); | ||||
4761 | Assert(PreallocatedBundle,do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
4762 | "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) | ||||
4763 | "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); | ||||
4764 | 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) | ||||
4765 | "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) | ||||
4766 | "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); | ||||
4767 | } | ||||
4768 | } | ||||
4769 | break; | ||||
4770 | } | ||||
4771 | case Intrinsic::call_preallocated_arg: { | ||||
4772 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
4773 | 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) | ||||
4774 | 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) | ||||
4775 | "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) | ||||
4776 | "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); | ||||
4777 | 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) | ||||
4778 | "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) | ||||
4779 | "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); | ||||
4780 | break; | ||||
4781 | } | ||||
4782 | case Intrinsic::call_preallocated_teardown: { | ||||
4783 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
4784 | 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) | ||||
4785 | 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) | ||||
4786 | "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) | ||||
4787 | "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); | ||||
4788 | break; | ||||
4789 | } | ||||
4790 | case Intrinsic::gcroot: | ||||
4791 | case Intrinsic::gcwrite: | ||||
4792 | case Intrinsic::gcread: | ||||
4793 | if (ID == Intrinsic::gcroot) { | ||||
4794 | AllocaInst *AI = | ||||
4795 | dyn_cast<AllocaInst>(Call.getArgOperand(0)->stripPointerCasts()); | ||||
4796 | 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); | ||||
4797 | 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) | ||||
4798 | "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); | ||||
4799 | if (!AI->getAllocatedType()->isPointerTy()) { | ||||
4800 | 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) | ||||
4801 | "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) | ||||
4802 | "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) | ||||
4803 | 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); | ||||
4804 | } | ||||
4805 | } | ||||
4806 | |||||
4807 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
4808 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
4809 | break; | ||||
4810 | case Intrinsic::init_trampoline: | ||||
4811 | 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) | ||||
4812 | "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) | ||||
4813 | Call)do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false); | ||||
4814 | break; | ||||
4815 | case Intrinsic::prefetch: | ||||
4816 | 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) | ||||
4817 | 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) | ||||
4818 | "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); | ||||
4819 | break; | ||||
4820 | case Intrinsic::stackprotector: | ||||
4821 | 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) | ||||
4822 | "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); | ||||
4823 | break; | ||||
4824 | case Intrinsic::localescape: { | ||||
4825 | BasicBlock *BB = Call.getParent(); | ||||
4826 | Assert(BB == &BB->getParent()->front(),do { if (!(BB == &BB->getParent()->front())) { CheckFailed ("llvm.localescape used outside of entry block", Call); return ; } } while (false) | ||||
4827 | "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); | ||||
4828 | Assert(!SawFrameEscape,do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false) | ||||
4829 | "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); | ||||
4830 | for (Value *Arg : Call.args()) { | ||||
4831 | if (isa<ConstantPointerNull>(Arg)) | ||||
4832 | continue; // Null values are allowed as placeholders. | ||||
4833 | auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts()); | ||||
4834 | Assert(AI && AI->isStaticAlloca(),do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false) | ||||
4835 | "llvm.localescape only accepts static allocas", Call)do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false); | ||||
4836 | } | ||||
4837 | FrameEscapeInfo[BB->getParent()].first = Call.getNumArgOperands(); | ||||
4838 | SawFrameEscape = true; | ||||
4839 | break; | ||||
4840 | } | ||||
4841 | case Intrinsic::localrecover: { | ||||
4842 | Value *FnArg = Call.getArgOperand(0)->stripPointerCasts(); | ||||
4843 | Function *Fn = dyn_cast<Function>(FnArg); | ||||
4844 | 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) | ||||
4845 | "llvm.localrecover first "do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
4846 | "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) | ||||
4847 | Call)do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false); | ||||
4848 | auto *IdxArg = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
4849 | auto &Entry = FrameEscapeInfo[Fn]; | ||||
4850 | Entry.second = unsigned( | ||||
4851 | std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1)); | ||||
4852 | break; | ||||
4853 | } | ||||
4854 | |||||
4855 | case Intrinsic::experimental_gc_statepoint: | ||||
4856 | if (auto *CI = dyn_cast<CallInst>(&Call)) | ||||
4857 | Assert(!CI->isInlineAsm(),do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false) | ||||
4858 | "gc.statepoint support for inline assembly unimplemented", CI)do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false); | ||||
4859 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
4860 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
4861 | |||||
4862 | verifyStatepoint(Call); | ||||
4863 | break; | ||||
4864 | case Intrinsic::experimental_gc_result: { | ||||
4865 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
4866 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
4867 | // Are we tied to a statepoint properly? | ||||
4868 | const auto *StatepointCall = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
4869 | const Function *StatepointFn = | ||||
4870 | StatepointCall ? StatepointCall->getCalledFunction() : nullptr; | ||||
4871 | 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) | ||||
4872 | 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) | ||||
4873 | 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) | ||||
4874 | "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) | ||||
4875 | 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); | ||||
4876 | |||||
4877 | // Assert that result type matches wrapped callee. | ||||
4878 | const Value *Target = StatepointCall->getArgOperand(2); | ||||
4879 | auto *PT = cast<PointerType>(Target->getType()); | ||||
4880 | auto *TargetFuncType = cast<FunctionType>(PT->getElementType()); | ||||
4881 | 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) | ||||
4882 | "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); | ||||
4883 | break; | ||||
4884 | } | ||||
4885 | case Intrinsic::experimental_gc_relocate: { | ||||
4886 | Assert(Call.getNumArgOperands() == 3, "wrong number of arguments", Call)do { if (!(Call.getNumArgOperands() == 3)) { CheckFailed("wrong number of arguments" , Call); return; } } while (false); | ||||
4887 | |||||
4888 | 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) | ||||
4889 | "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); | ||||
4890 | |||||
4891 | // Check that this relocate is correctly tied to the statepoint | ||||
4892 | |||||
4893 | // This is case for relocate on the unwinding path of an invoke statepoint | ||||
4894 | if (LandingPadInst *LandingPad = | ||||
4895 | dyn_cast<LandingPadInst>(Call.getArgOperand(0))) { | ||||
4896 | |||||
4897 | const BasicBlock *InvokeBB = | ||||
4898 | LandingPad->getParent()->getUniquePredecessor(); | ||||
4899 | |||||
4900 | // Landingpad relocates should have only one predecessor with invoke | ||||
4901 | // statepoint terminator | ||||
4902 | Assert(InvokeBB, "safepoints should have unique landingpads",do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false) | ||||
4903 | LandingPad->getParent())do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false); | ||||
4904 | Assert(InvokeBB->getTerminator(), "safepoint block should be well formed",do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false) | ||||
4905 | InvokeBB)do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false); | ||||
4906 | Assert(isa<GCStatepointInst>(InvokeBB->getTerminator()),do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false) | ||||
4907 | "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); | ||||
4908 | } else { | ||||
4909 | // In all other cases relocate should be tied to the statepoint directly. | ||||
4910 | // This covers relocates on a normal return path of invoke statepoint and | ||||
4911 | // relocates of a call statepoint. | ||||
4912 | auto Token = Call.getArgOperand(0); | ||||
4913 | Assert(isa<GCStatepointInst>(Token),do { if (!(isa<GCStatepointInst>(Token))) { CheckFailed ("gc relocate is incorrectly tied to the statepoint", Call, Token ); return; } } while (false) | ||||
4914 | "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); | ||||
4915 | } | ||||
4916 | |||||
4917 | // Verify rest of the relocate arguments. | ||||
4918 | const CallBase &StatepointCall = | ||||
4919 | *cast<GCRelocateInst>(Call).getStatepoint(); | ||||
4920 | |||||
4921 | // Both the base and derived must be piped through the safepoint. | ||||
4922 | Value *Base = Call.getArgOperand(1); | ||||
4923 | Assert(isa<ConstantInt>(Base),do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false) | ||||
4924 | "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); | ||||
4925 | |||||
4926 | Value *Derived = Call.getArgOperand(2); | ||||
4927 | Assert(isa<ConstantInt>(Derived),do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false) | ||||
4928 | "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); | ||||
4929 | |||||
4930 | const uint64_t BaseIndex = cast<ConstantInt>(Base)->getZExtValue(); | ||||
4931 | const uint64_t DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue(); | ||||
4932 | |||||
4933 | // Check the bounds | ||||
4934 | if (auto Opt = StatepointCall.getOperandBundle(LLVMContext::OB_gc_live)) { | ||||
4935 | Assert(BaseIndex < Opt->Inputs.size(),do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false) | ||||
4936 | "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); | ||||
4937 | Assert(DerivedIndex < Opt->Inputs.size(),do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false) | ||||
4938 | "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); | ||||
4939 | } | ||||
4940 | |||||
4941 | // Relocated value must be either a pointer type or vector-of-pointer type, | ||||
4942 | // but gc_relocate does not need to return the same pointer type as the | ||||
4943 | // relocated pointer. It can be casted to the correct type later if it's | ||||
4944 | // desired. However, they must have the same address space and 'vectorness' | ||||
4945 | GCRelocateInst &Relocate = cast<GCRelocateInst>(Call); | ||||
4946 | 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) | ||||
4947 | "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); | ||||
4948 | |||||
4949 | auto ResultType = Call.getType(); | ||||
4950 | auto DerivedType = Relocate.getDerivedPtr()->getType(); | ||||
4951 | 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) | ||||
4952 | "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) | ||||
4953 | Call)do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false); | ||||
4954 | Assert(do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
4955 | ResultType->getPointerAddressSpace() ==do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
4956 | DerivedType->getPointerAddressSpace(),do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
4957 | "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) | ||||
4958 | Call)do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false); | ||||
4959 | break; | ||||
4960 | } | ||||
4961 | case Intrinsic::eh_exceptioncode: | ||||
4962 | case Intrinsic::eh_exceptionpointer: { | ||||
4963 | 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) | ||||
4964 | "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); | ||||
4965 | break; | ||||
4966 | } | ||||
4967 | case Intrinsic::get_active_lane_mask: { | ||||
4968 | 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) | ||||
4969 | "vector", Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false); | ||||
4970 | auto *ElemTy = Call.getType()->getScalarType(); | ||||
4971 | 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) | ||||
4972 | "i1", Call)do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false); | ||||
4973 | break; | ||||
4974 | } | ||||
4975 | case Intrinsic::masked_load: { | ||||
4976 | 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) | ||||
4977 | Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false); | ||||
4978 | |||||
4979 | Value *Ptr = Call.getArgOperand(0); | ||||
4980 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
4981 | Value *Mask = Call.getArgOperand(2); | ||||
4982 | Value *PassThru = Call.getArgOperand(3); | ||||
4983 | 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) | ||||
4984 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false); | ||||
4985 | Assert(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false) | ||||
4986 | "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); | ||||
4987 | |||||
4988 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
4989 | Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false) | ||||
4990 | "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); | ||||
4991 | 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) | ||||
4992 | "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); | ||||
4993 | 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) | ||||
4994 | 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) | ||||
4995 | "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); | ||||
4996 | break; | ||||
4997 | } | ||||
4998 | case Intrinsic::masked_store: { | ||||
4999 | Value *Val = Call.getArgOperand(0); | ||||
5000 | Value *Ptr = Call.getArgOperand(1); | ||||
5001 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5002 | Value *Mask = Call.getArgOperand(3); | ||||
5003 | 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) | ||||
5004 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false); | ||||
5005 | Assert(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false) | ||||
5006 | "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); | ||||
5007 | |||||
5008 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
5009 | Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false) | ||||
5010 | "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); | ||||
5011 | 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) | ||||
5012 | 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) | ||||
5013 | "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); | ||||
5014 | break; | ||||
5015 | } | ||||
5016 | |||||
5017 | case Intrinsic::masked_gather: { | ||||
5018 | const APInt &Alignment = | ||||
5019 | cast<ConstantInt>(Call.getArgOperand(1))->getValue(); | ||||
5020 | 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) | ||||
5021 | "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); | ||||
5022 | break; | ||||
5023 | } | ||||
5024 | case Intrinsic::masked_scatter: { | ||||
5025 | const APInt &Alignment = | ||||
5026 | cast<ConstantInt>(Call.getArgOperand(2))->getValue(); | ||||
5027 | 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) | ||||
5028 | "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); | ||||
5029 | break; | ||||
5030 | } | ||||
5031 | |||||
5032 | case Intrinsic::experimental_guard: { | ||||
5033 | 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); | ||||
5034 | 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) | ||||
5035 | "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) | ||||
5036 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
5037 | break; | ||||
5038 | } | ||||
5039 | |||||
5040 | case Intrinsic::experimental_deoptimize: { | ||||
5041 | Assert(isa<CallInst>(Call), "experimental_deoptimize cannot be invoked",do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false) | ||||
5042 | Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false); | ||||
5043 | 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) | ||||
5044 | "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) | ||||
5045 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
5046 | 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) | ||||
5047 | "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); | ||||
5048 | |||||
5049 | if (isa<CallInst>(Call)) { | ||||
5050 | auto *RI = dyn_cast<ReturnInst>(Call.getNextNode()); | ||||
5051 | Assert(RI,do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false) | ||||
5052 | "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); | ||||
5053 | |||||
5054 | if (!Call.getType()->isVoidTy() && RI) | ||||
5055 | 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) | ||||
5056 | "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) | ||||
5057 | "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); | ||||
5058 | } | ||||
5059 | |||||
5060 | break; | ||||
5061 | } | ||||
5062 | case Intrinsic::vector_reduce_and: | ||||
5063 | case Intrinsic::vector_reduce_or: | ||||
5064 | case Intrinsic::vector_reduce_xor: | ||||
5065 | case Intrinsic::vector_reduce_add: | ||||
5066 | case Intrinsic::vector_reduce_mul: | ||||
5067 | case Intrinsic::vector_reduce_smax: | ||||
5068 | case Intrinsic::vector_reduce_smin: | ||||
5069 | case Intrinsic::vector_reduce_umax: | ||||
5070 | case Intrinsic::vector_reduce_umin: { | ||||
5071 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
5072 | Assert(ArgTy->isIntOrIntVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5073 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5074 | break; | ||||
5075 | } | ||||
5076 | case Intrinsic::vector_reduce_fmax: | ||||
5077 | case Intrinsic::vector_reduce_fmin: { | ||||
5078 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
5079 | Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5080 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5081 | break; | ||||
5082 | } | ||||
5083 | case Intrinsic::vector_reduce_fadd: | ||||
5084 | case Intrinsic::vector_reduce_fmul: { | ||||
5085 | // Unlike the other reductions, the first argument is a start value. The | ||||
5086 | // second argument is the vector to be reduced. | ||||
5087 | Type *ArgTy = Call.getArgOperand(1)->getType(); | ||||
5088 | Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5089 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5090 | break; | ||||
5091 | } | ||||
5092 | case Intrinsic::smul_fix: | ||||
5093 | case Intrinsic::smul_fix_sat: | ||||
5094 | case Intrinsic::umul_fix: | ||||
5095 | case Intrinsic::umul_fix_sat: | ||||
5096 | case Intrinsic::sdiv_fix: | ||||
5097 | case Intrinsic::sdiv_fix_sat: | ||||
5098 | case Intrinsic::udiv_fix: | ||||
5099 | case Intrinsic::udiv_fix_sat: { | ||||
5100 | Value *Op1 = Call.getArgOperand(0); | ||||
5101 | Value *Op2 = Call.getArgOperand(1); | ||||
5102 | 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) | ||||
5103 | "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) | ||||
5104 | "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); | ||||
5105 | 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) | ||||
5106 | "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) | ||||
5107 | "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); | ||||
5108 | |||||
5109 | auto *Op3 = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5110 | 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) | ||||
5111 | "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); | ||||
5112 | |||||
5113 | if (ID == Intrinsic::smul_fix || ID == Intrinsic::smul_fix_sat || | ||||
5114 | ID == Intrinsic::sdiv_fix || ID == Intrinsic::sdiv_fix_sat) { | ||||
5115 | 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) | ||||
5116 | 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) | ||||
5117 | "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) | ||||
5118 | "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); | ||||
5119 | } else { | ||||
5120 | 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) | ||||
5121 | "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) | ||||
5122 | "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); | ||||
5123 | } | ||||
5124 | break; | ||||
5125 | } | ||||
5126 | case Intrinsic::lround: | ||||
5127 | case Intrinsic::llround: | ||||
5128 | case Intrinsic::lrint: | ||||
5129 | case Intrinsic::llrint: { | ||||
5130 | Type *ValTy = Call.getArgOperand(0)->getType(); | ||||
5131 | Type *ResultTy = Call.getType(); | ||||
5132 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false) | ||||
5133 | "Intrinsic does not support vectors", &Call)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false); | ||||
5134 | break; | ||||
5135 | } | ||||
5136 | case Intrinsic::bswap: { | ||||
5137 | Type *Ty = Call.getType(); | ||||
5138 | unsigned Size = Ty->getScalarSizeInBits(); | ||||
5139 | 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); | ||||
5140 | break; | ||||
5141 | } | ||||
5142 | case Intrinsic::invariant_start: { | ||||
5143 | ConstantInt *InvariantSize = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
5144 | 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) | ||||
5145 | (!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) | ||||
5146 | "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) | ||||
5147 | &Call)do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false); | ||||
5148 | break; | ||||
5149 | } | ||||
5150 | case Intrinsic::matrix_multiply: | ||||
5151 | case Intrinsic::matrix_transpose: | ||||
5152 | case Intrinsic::matrix_column_major_load: | ||||
5153 | case Intrinsic::matrix_column_major_store: { | ||||
5154 | Function *IF = Call.getCalledFunction(); | ||||
5155 | ConstantInt *Stride = nullptr; | ||||
5156 | ConstantInt *NumRows; | ||||
5157 | ConstantInt *NumColumns; | ||||
5158 | VectorType *ResultTy; | ||||
5159 | Type *Op0ElemTy = nullptr; | ||||
5160 | Type *Op1ElemTy = nullptr; | ||||
5161 | switch (ID) { | ||||
5162 | case Intrinsic::matrix_multiply: | ||||
5163 | NumRows = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5164 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5165 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5166 | Op0ElemTy = | ||||
5167 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5168 | Op1ElemTy = | ||||
5169 | cast<VectorType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
5170 | break; | ||||
5171 | case Intrinsic::matrix_transpose: | ||||
5172 | NumRows = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
5173 | NumColumns = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5174 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5175 | Op0ElemTy = | ||||
5176 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5177 | break; | ||||
5178 | case Intrinsic::matrix_column_major_load: | ||||
5179 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(1)); | ||||
5180 | NumRows = cast<ConstantInt>(Call.getArgOperand(3)); | ||||
5181 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5182 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5183 | Op0ElemTy = | ||||
5184 | cast<PointerType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5185 | break; | ||||
5186 | case Intrinsic::matrix_column_major_store: | ||||
5187 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5188 | NumRows = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5189 | NumColumns = cast<ConstantInt>(Call.getArgOperand(5)); | ||||
5190 | ResultTy = cast<VectorType>(Call.getArgOperand(0)->getType()); | ||||
5191 | Op0ElemTy = | ||||
5192 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5193 | Op1ElemTy = | ||||
5194 | cast<PointerType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
5195 | break; | ||||
5196 | default: | ||||
5197 | llvm_unreachable("unexpected intrinsic")__builtin_unreachable(); | ||||
5198 | } | ||||
5199 | |||||
5200 | 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) | ||||
5201 | 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) | ||||
5202 | "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); | ||||
5203 | |||||
5204 | 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) | ||||
5205 | "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) | ||||
5206 | "vector!", IF)do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false); | ||||
5207 | |||||
5208 | if (Op1ElemTy) | ||||
5209 | 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) | ||||
5210 | "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) | ||||
5211 | "vector!", IF)do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false); | ||||
5212 | |||||
5213 | 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) | ||||
5214 | 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) | ||||
5215 | "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); | ||||
5216 | |||||
5217 | if (Stride) | ||||
5218 | 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) | ||||
5219 | "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); | ||||
5220 | |||||
5221 | break; | ||||
5222 | } | ||||
5223 | case Intrinsic::experimental_stepvector: { | ||||
5224 | VectorType *VecTy = dyn_cast<VectorType>(Call.getType()); | ||||
5225 | 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) | ||||
5226 | 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) | ||||
5227 | "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) | ||||
5228 | "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) | ||||
5229 | &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); | ||||
5230 | break; | ||||
5231 | } | ||||
5232 | case Intrinsic::experimental_vector_insert: { | ||||
5233 | Value *Vec = Call.getArgOperand(0); | ||||
5234 | Value *SubVec = Call.getArgOperand(1); | ||||
5235 | Value *Idx = Call.getArgOperand(2); | ||||
5236 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
5237 | |||||
5238 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
5239 | VectorType *SubVecTy = cast<VectorType>(SubVec->getType()); | ||||
5240 | |||||
5241 | ElementCount VecEC = VecTy->getElementCount(); | ||||
5242 | ElementCount SubVecEC = SubVecTy->getElementCount(); | ||||
5243 | 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) | ||||
5244 | "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) | ||||
5245 | "type.",do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
5246 | &Call)do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false); | ||||
5247 | 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) | ||||
5248 | "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) | ||||
5249 | "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); | ||||
5250 | |||||
5251 | // If this insertion is not the 'mixed' case where a fixed vector is | ||||
5252 | // inserted into a scalable vector, ensure that the insertion of the | ||||
5253 | // subvector does not overrun the parent vector. | ||||
5254 | if (VecEC.isScalable() == SubVecEC.isScalable()) { | ||||
5255 | 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) | ||||
5256 | 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) | ||||
5257 | 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) | ||||
5258 | "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) | ||||
5259 | "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); | ||||
5260 | } | ||||
5261 | break; | ||||
5262 | } | ||||
5263 | case Intrinsic::experimental_vector_extract: { | ||||
5264 | Value *Vec = Call.getArgOperand(0); | ||||
5265 | Value *Idx = Call.getArgOperand(1); | ||||
5266 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
5267 | |||||
5268 | VectorType *ResultTy = cast<VectorType>(Call.getType()); | ||||
5269 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
5270 | |||||
5271 | ElementCount VecEC = VecTy->getElementCount(); | ||||
5272 | ElementCount ResultEC = ResultTy->getElementCount(); | ||||
5273 | |||||
5274 | 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) | ||||
5275 | "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) | ||||
5276 | "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) | ||||
5277 | &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); | ||||
5278 | 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) | ||||
5279 | "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) | ||||
5280 | "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); | ||||
5281 | |||||
5282 | // If this extraction is not the 'mixed' case where a fixed vector is is | ||||
5283 | // extracted from a scalable vector, ensure that the extraction does not | ||||
5284 | // overrun the parent vector. | ||||
5285 | if (VecEC.isScalable() == ResultEC.isScalable()) { | ||||
5286 | Assert(IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false) | ||||
5287 | IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false) | ||||
5288 | "experimental_vector_extract would overrun.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false); | ||||
5289 | } | ||||
5290 | break; | ||||
5291 | } | ||||
5292 | case Intrinsic::experimental_noalias_scope_decl: { | ||||
5293 | NoAliasScopeDecls.push_back(cast<IntrinsicInst>(&Call)); | ||||
5294 | break; | ||||
5295 | } | ||||
5296 | case Intrinsic::preserve_array_access_index: | ||||
5297 | case Intrinsic::preserve_struct_access_index: { | ||||
5298 | Type *ElemTy = Call.getAttributes().getParamElementType(0); | ||||
5299 | Assert(ElemTy,do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
5300 | "Intrinsic requires elementtype attribute on first argument.",do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
5301 | &Call)do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false); | ||||
5302 | break; | ||||
5303 | } | ||||
5304 | }; | ||||
5305 | } | ||||
5306 | |||||
5307 | /// Carefully grab the subprogram from a local scope. | ||||
5308 | /// | ||||
5309 | /// This carefully grabs the subprogram from a local scope, avoiding the | ||||
5310 | /// built-in assertions that would typically fire. | ||||
5311 | static DISubprogram *getSubprogram(Metadata *LocalScope) { | ||||
5312 | if (!LocalScope) | ||||
5313 | return nullptr; | ||||
5314 | |||||
5315 | if (auto *SP = dyn_cast<DISubprogram>(LocalScope)) | ||||
5316 | return SP; | ||||
5317 | |||||
5318 | if (auto *LB = dyn_cast<DILexicalBlockBase>(LocalScope)) | ||||
5319 | return getSubprogram(LB->getRawScope()); | ||||
5320 | |||||
5321 | // Just return null; broken scope chains are checked elsewhere. | ||||
5322 | assert(!isa<DILocalScope>(LocalScope) && "Unknown type of local scope")((void)0); | ||||
5323 | return nullptr; | ||||
5324 | } | ||||
5325 | |||||
5326 | void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { | ||||
5327 | unsigned NumOperands; | ||||
5328 | bool HasRoundingMD; | ||||
5329 | switch (FPI.getIntrinsicID()) { | ||||
5330 | #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ | ||||
5331 | case Intrinsic::INTRINSIC: \ | ||||
5332 | NumOperands = NARG; \ | ||||
5333 | HasRoundingMD = ROUND_MODE; \ | ||||
5334 | break; | ||||
5335 | #include "llvm/IR/ConstrainedOps.def" | ||||
5336 | default: | ||||
5337 | llvm_unreachable("Invalid constrained FP intrinsic!")__builtin_unreachable(); | ||||
5338 | } | ||||
5339 | NumOperands += (1 + HasRoundingMD); | ||||
5340 | // Compare intrinsics carry an extra predicate metadata operand. | ||||
5341 | if (isa<ConstrainedFPCmpIntrinsic>(FPI)) | ||||
5342 | NumOperands += 1; | ||||
5343 | Assert((FPI.getNumArgOperands() == NumOperands),do { if (!((FPI.getNumArgOperands() == NumOperands))) { CheckFailed ("invalid arguments for constrained FP intrinsic", &FPI); return; } } while (false) | ||||
5344 | "invalid arguments for constrained FP intrinsic", &FPI)do { if (!((FPI.getNumArgOperands() == NumOperands))) { CheckFailed ("invalid arguments for constrained FP intrinsic", &FPI); return; } } while (false); | ||||
5345 | |||||
5346 | switch (FPI.getIntrinsicID()) { | ||||
5347 | case Intrinsic::experimental_constrained_lrint: | ||||
5348 | case Intrinsic::experimental_constrained_llrint: { | ||||
5349 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
5350 | Type *ResultTy = FPI.getType(); | ||||
5351 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
5352 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
5353 | } | ||||
5354 | break; | ||||
5355 | |||||
5356 | case Intrinsic::experimental_constrained_lround: | ||||
5357 | case Intrinsic::experimental_constrained_llround: { | ||||
5358 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
5359 | Type *ResultTy = FPI.getType(); | ||||
5360 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
5361 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
5362 | break; | ||||
5363 | } | ||||
5364 | |||||
5365 | case Intrinsic::experimental_constrained_fcmp: | ||||
5366 | case Intrinsic::experimental_constrained_fcmps: { | ||||
5367 | auto Pred = cast<ConstrainedFPCmpIntrinsic>(&FPI)->getPredicate(); | ||||
5368 | Assert(CmpInst::isFPPredicate(Pred),do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false) | ||||
5369 | "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); | ||||
5370 | break; | ||||
5371 | } | ||||
5372 | |||||
5373 | case Intrinsic::experimental_constrained_fptosi: | ||||
5374 | case Intrinsic::experimental_constrained_fptoui: { | ||||
5375 | Value *Operand = FPI.getArgOperand(0); | ||||
5376 | uint64_t NumSrcElem = 0; | ||||
5377 | Assert(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false) | ||||
5378 | "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); | ||||
5379 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5380 | NumSrcElem = cast<FixedVectorType>(OperandT)->getNumElements(); | ||||
5381 | } | ||||
5382 | |||||
5383 | Operand = &FPI; | ||||
5384 | 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) | ||||
5385 | "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); | ||||
5386 | Assert(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false) | ||||
5387 | "Intrinsic result must be an integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false); | ||||
5388 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5389 | 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) | ||||
5390 | "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) | ||||
5391 | &FPI)do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
5392 | } | ||||
5393 | } | ||||
5394 | break; | ||||
5395 | |||||
5396 | case Intrinsic::experimental_constrained_sitofp: | ||||
5397 | case Intrinsic::experimental_constrained_uitofp: { | ||||
5398 | Value *Operand = FPI.getArgOperand(0); | ||||
5399 | uint64_t NumSrcElem = 0; | ||||
5400 | Assert(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false) | ||||
5401 | "Intrinsic first argument must be integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false); | ||||
5402 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5403 | NumSrcElem = cast<FixedVectorType>(OperandT)->getNumElements(); | ||||
5404 | } | ||||
5405 | |||||
5406 | Operand = &FPI; | ||||
5407 | 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) | ||||
5408 | "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); | ||||
5409 | Assert(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false) | ||||
5410 | "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); | ||||
5411 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
5412 | 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) | ||||
5413 | "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) | ||||
5414 | &FPI)do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
5415 | } | ||||
5416 | } break; | ||||
5417 | |||||
5418 | case Intrinsic::experimental_constrained_fptrunc: | ||||
5419 | case Intrinsic::experimental_constrained_fpext: { | ||||
5420 | Value *Operand = FPI.getArgOperand(0); | ||||
5421 | Type *OperandTy = Operand->getType(); | ||||
5422 | Value *Result = &FPI; | ||||
5423 | Type *ResultTy = Result->getType(); | ||||
5424 | Assert(OperandTy->isFPOrFPVectorTy(),do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false) | ||||
5425 | "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); | ||||
5426 | Assert(ResultTy->isFPOrFPVectorTy(),do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false) | ||||
5427 | "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); | ||||
5428 | 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) | ||||
5429 | "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); | ||||
5430 | if (OperandTy->isVectorTy()) { | ||||
5431 | 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) | ||||
5432 | 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) | ||||
5433 | "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) | ||||
5434 | &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); | ||||
5435 | } | ||||
5436 | if (FPI.getIntrinsicID() == Intrinsic::experimental_constrained_fptrunc) { | ||||
5437 | 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) | ||||
5438 | "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) | ||||
5439 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false); | ||||
5440 | } else { | ||||
5441 | 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) | ||||
5442 | "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) | ||||
5443 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false); | ||||
5444 | } | ||||
5445 | } | ||||
5446 | break; | ||||
5447 | |||||
5448 | default: | ||||
5449 | break; | ||||
5450 | } | ||||
5451 | |||||
5452 | // If a non-metadata argument is passed in a metadata slot then the | ||||
5453 | // error will be caught earlier when the incorrect argument doesn't | ||||
5454 | // match the specification in the intrinsic call table. Thus, no | ||||
5455 | // argument type check is needed here. | ||||
5456 | |||||
5457 | Assert(FPI.getExceptionBehavior().hasValue(),do { if (!(FPI.getExceptionBehavior().hasValue())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false) | ||||
5458 | "invalid exception behavior argument", &FPI)do { if (!(FPI.getExceptionBehavior().hasValue())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false); | ||||
5459 | if (HasRoundingMD) { | ||||
5460 | Assert(FPI.getRoundingMode().hasValue(),do { if (!(FPI.getRoundingMode().hasValue())) { CheckFailed("invalid rounding mode argument" , &FPI); return; } } while (false) | ||||
5461 | "invalid rounding mode argument", &FPI)do { if (!(FPI.getRoundingMode().hasValue())) { CheckFailed("invalid rounding mode argument" , &FPI); return; } } while (false); | ||||
5462 | } | ||||
5463 | } | ||||
5464 | |||||
5465 | void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { | ||||
5466 | auto *MD = DII.getRawLocation(); | ||||
5467 | 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) | ||||
5468 | (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) | ||||
5469 | "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); | ||||
5470 | AssertDI(isa<DILocalVariable>(DII.getRawVariable()),do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
5471 | "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) | ||||
5472 | DII.getRawVariable())do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false); | ||||
5473 | AssertDI(isa<DIExpression>(DII.getRawExpression()),do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
5474 | "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 ) | ||||
5475 | DII.getRawExpression())do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ); | ||||
5476 | |||||
5477 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
5478 | if (MDNode *N = DII.getDebugLoc().getAsMDNode()) | ||||
5479 | if (!isa<DILocation>(N)) | ||||
5480 | return; | ||||
5481 | |||||
5482 | BasicBlock *BB = DII.getParent(); | ||||
5483 | Function *F = BB ? BB->getParent() : nullptr; | ||||
5484 | |||||
5485 | // The scopes for variables and !dbg attachments must agree. | ||||
5486 | DILocalVariable *Var = DII.getVariable(); | ||||
5487 | DILocation *Loc = DII.getDebugLoc(); | ||||
5488 | 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) | ||||
5489 | &DII, BB, F)do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false); | ||||
5490 | |||||
5491 | DISubprogram *VarSP = getSubprogram(Var->getRawScope()); | ||||
5492 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
5493 | if (!VarSP || !LocSP) | ||||
5494 | return; // Broken scope chains are checked elsewhere. | ||||
5495 | |||||
5496 | 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) | ||||
5497 | " 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) | ||||
5498 | &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) | ||||
5499 | 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); | ||||
5500 | |||||
5501 | // This check is redundant with one in visitLocalVariable(). | ||||
5502 | AssertDI(isType(Var->getRawType()), "invalid type ref", Var,do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false) | ||||
5503 | Var->getRawType())do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false); | ||||
5504 | verifyFnArgs(DII); | ||||
5505 | } | ||||
5506 | |||||
5507 | void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) { | ||||
5508 | AssertDI(isa<DILabel>(DLI.getRawLabel()),do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
5509 | "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) | ||||
5510 | DLI.getRawLabel())do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false); | ||||
5511 | |||||
5512 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
5513 | if (MDNode *N = DLI.getDebugLoc().getAsMDNode()) | ||||
5514 | if (!isa<DILocation>(N)) | ||||
5515 | return; | ||||
5516 | |||||
5517 | BasicBlock *BB = DLI.getParent(); | ||||
5518 | Function *F = BB ? BB->getParent() : nullptr; | ||||
5519 | |||||
5520 | // The scopes for variables and !dbg attachments must agree. | ||||
5521 | DILabel *Label = DLI.getLabel(); | ||||
5522 | DILocation *Loc = DLI.getDebugLoc(); | ||||
5523 | 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) | ||||
5524 | &DLI, BB, F)do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false); | ||||
5525 | |||||
5526 | DISubprogram *LabelSP = getSubprogram(Label->getRawScope()); | ||||
5527 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
5528 | if (!LabelSP || !LocSP) | ||||
5529 | return; | ||||
5530 | |||||
5531 | 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) | ||||
5532 | " 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) | ||||
5533 | &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) | ||||
5534 | 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); | ||||
5535 | } | ||||
5536 | |||||
5537 | void Verifier::verifyFragmentExpression(const DbgVariableIntrinsic &I) { | ||||
5538 | DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); | ||||
5539 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
5540 | |||||
5541 | // We don't know whether this intrinsic verified correctly. | ||||
5542 | if (!V || !E || !E->isValid()) | ||||
5543 | return; | ||||
5544 | |||||
5545 | // Nothing to do if this isn't a DW_OP_LLVM_fragment expression. | ||||
5546 | auto Fragment = E->getFragmentInfo(); | ||||
5547 | if (!Fragment) | ||||
5548 | return; | ||||
5549 | |||||
5550 | // The frontend helps out GDB by emitting the members of local anonymous | ||||
5551 | // unions as artificial local variables with shared storage. When SROA splits | ||||
5552 | // the storage for artificial local variables that are smaller than the entire | ||||
5553 | // union, the overhang piece will be outside of the allotted space for the | ||||
5554 | // variable and this check fails. | ||||
5555 | // FIXME: Remove this check as soon as clang stops doing this; it hides bugs. | ||||
5556 | if (V->isArtificial()) | ||||
5557 | return; | ||||
5558 | |||||
5559 | verifyFragmentExpression(*V, *Fragment, &I); | ||||
5560 | } | ||||
5561 | |||||
5562 | template <typename ValueOrMetadata> | ||||
5563 | void Verifier::verifyFragmentExpression(const DIVariable &V, | ||||
5564 | DIExpression::FragmentInfo Fragment, | ||||
5565 | ValueOrMetadata *Desc) { | ||||
5566 | // If there's no size, the type is broken, but that should be checked | ||||
5567 | // elsewhere. | ||||
5568 | auto VarSize = V.getSizeInBits(); | ||||
5569 | if (!VarSize) | ||||
5570 | return; | ||||
5571 | |||||
5572 | unsigned FragSize = Fragment.SizeInBits; | ||||
5573 | unsigned FragOffset = Fragment.OffsetInBits; | ||||
5574 | AssertDI(FragSize + FragOffset <= *VarSize,do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false) | ||||
5575 | "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); | ||||
5576 | AssertDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V)do { if (!(FragSize != *VarSize)) { DebugInfoCheckFailed("fragment covers entire variable" , Desc, &V); return; } } while (false); | ||||
5577 | } | ||||
5578 | |||||
5579 | void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) { | ||||
5580 | // This function does not take the scope of noninlined function arguments into | ||||
5581 | // account. Don't run it if current function is nodebug, because it may | ||||
5582 | // contain inlined debug intrinsics. | ||||
5583 | if (!HasDebugInfo) | ||||
5584 | return; | ||||
5585 | |||||
5586 | // For performance reasons only check non-inlined ones. | ||||
5587 | if (I.getDebugLoc()->getInlinedAt()) | ||||
5588 | return; | ||||
5589 | |||||
5590 | DILocalVariable *Var = I.getVariable(); | ||||
5591 | AssertDI(Var, "dbg intrinsic without variable")do { if (!(Var)) { DebugInfoCheckFailed("dbg intrinsic without variable" ); return; } } while (false); | ||||
5592 | |||||
5593 | unsigned ArgNo = Var->getArg(); | ||||
5594 | if (!ArgNo) | ||||
5595 | return; | ||||
5596 | |||||
5597 | // Verify there are no duplicate function argument debug info entries. | ||||
5598 | // These will cause hard-to-debug assertions in the DWARF backend. | ||||
5599 | if (DebugFnArgs.size() < ArgNo) | ||||
5600 | DebugFnArgs.resize(ArgNo, nullptr); | ||||
5601 | |||||
5602 | auto *Prev = DebugFnArgs[ArgNo - 1]; | ||||
5603 | DebugFnArgs[ArgNo - 1] = Var; | ||||
5604 | 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) | ||||
5605 | Prev, Var)do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false); | ||||
5606 | } | ||||
5607 | |||||
5608 | void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) { | ||||
5609 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
5610 | |||||
5611 | // We don't know whether this intrinsic verified correctly. | ||||
5612 | if (!E || !E->isValid()) | ||||
5613 | return; | ||||
5614 | |||||
5615 | 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); | ||||
5616 | } | ||||
5617 | |||||
5618 | void Verifier::verifyCompileUnits() { | ||||
5619 | // When more than one Module is imported into the same context, such as during | ||||
5620 | // an LTO build before linking the modules, ODR type uniquing may cause types | ||||
5621 | // to point to a different CU. This check does not make sense in this case. | ||||
5622 | if (M.getContext().isODRUniquingDebugTypes()) | ||||
5623 | return; | ||||
5624 | auto *CUs = M.getNamedMetadata("llvm.dbg.cu"); | ||||
5625 | SmallPtrSet<const Metadata *, 2> Listed; | ||||
5626 | if (CUs) | ||||
5627 | Listed.insert(CUs->op_begin(), CUs->op_end()); | ||||
5628 | for (auto *CU : CUVisited) | ||||
5629 | 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); | ||||
5630 | CUVisited.clear(); | ||||
5631 | } | ||||
5632 | |||||
5633 | void Verifier::verifyDeoptimizeCallingConvs() { | ||||
5634 | if (DeoptimizeDeclarations.empty()) | ||||
5635 | return; | ||||
5636 | |||||
5637 | const Function *First = DeoptimizeDeclarations[0]; | ||||
5638 | for (auto *F : makeArrayRef(DeoptimizeDeclarations).slice(1)) { | ||||
5639 | 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) | ||||
5640 | "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) | ||||
5641 | "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) | ||||
5642 | 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); | ||||
5643 | } | ||||
5644 | } | ||||
5645 | |||||
5646 | void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) { | ||||
5647 | bool HasSource = F.getSource().hasValue(); | ||||
5648 | if (!HasSourceDebugInfo.count(&U)) | ||||
5649 | HasSourceDebugInfo[&U] = HasSource; | ||||
5650 | AssertDI(HasSource == HasSourceDebugInfo[&U],do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ) | ||||
5651 | "inconsistent use of embedded source")do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ); | ||||
5652 | } | ||||
5653 | |||||
5654 | void Verifier::verifyNoAliasScopeDecl() { | ||||
5655 | if (NoAliasScopeDecls.empty()) | ||||
5656 | return; | ||||
5657 | |||||
5658 | // only a single scope must be declared at a time. | ||||
5659 | for (auto *II : NoAliasScopeDecls) { | ||||
5660 | assert(II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl &&((void)0) | ||||
5661 | "Not a llvm.experimental.noalias.scope.decl ?")((void)0); | ||||
5662 | const auto *ScopeListMV = dyn_cast<MetadataAsValue>( | ||||
5663 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
5664 | Assert(ScopeListMV != nullptr,do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
5665 | "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) | ||||
5666 | "argument",do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
5667 | II)do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false); | ||||
5668 | |||||
5669 | const auto *ScopeListMD = dyn_cast<MDNode>(ScopeListMV->getMetadata()); | ||||
5670 | 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) | ||||
5671 | II)do { if (!(ScopeListMD != nullptr)) { CheckFailed("!id.scope.list must point to an MDNode" , II); return; } } while (false); | ||||
5672 | 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) | ||||
5673 | "!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); | ||||
5674 | } | ||||
5675 | |||||
5676 | // Only check the domination rule when requested. Once all passes have been | ||||
5677 | // adapted this option can go away. | ||||
5678 | if (!VerifyNoAliasScopeDomination) | ||||
5679 | return; | ||||
5680 | |||||
5681 | // Now sort the intrinsics based on the scope MDNode so that declarations of | ||||
5682 | // the same scopes are next to each other. | ||||
5683 | auto GetScope = [](IntrinsicInst *II) { | ||||
5684 | const auto *ScopeListMV = cast<MetadataAsValue>( | ||||
5685 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
5686 | return &cast<MDNode>(ScopeListMV->getMetadata())->getOperand(0); | ||||
5687 | }; | ||||
5688 | |||||
5689 | // We are sorting on MDNode pointers here. For valid input IR this is ok. | ||||
5690 | // TODO: Sort on Metadata ID to avoid non-deterministic error messages. | ||||
5691 | auto Compare = [GetScope](IntrinsicInst *Lhs, IntrinsicInst *Rhs) { | ||||
5692 | return GetScope(Lhs) < GetScope(Rhs); | ||||
5693 | }; | ||||
5694 | |||||
5695 | llvm::sort(NoAliasScopeDecls, Compare); | ||||
5696 | |||||
5697 | // Go over the intrinsics and check that for the same scope, they are not | ||||
5698 | // dominating each other. | ||||
5699 | auto ItCurrent = NoAliasScopeDecls.begin(); | ||||
5700 | while (ItCurrent != NoAliasScopeDecls.end()) { | ||||
5701 | auto CurScope = GetScope(*ItCurrent); | ||||
5702 | auto ItNext = ItCurrent; | ||||
5703 | do { | ||||
5704 | ++ItNext; | ||||
5705 | } while (ItNext != NoAliasScopeDecls.end() && | ||||
5706 | GetScope(*ItNext) == CurScope); | ||||
5707 | |||||
5708 | // [ItCurrent, ItNext) represents the declarations for the same scope. | ||||
5709 | // Ensure they are not dominating each other.. but only if it is not too | ||||
5710 | // expensive. | ||||
5711 | if (ItNext - ItCurrent < 32) | ||||
5712 | for (auto *I : llvm::make_range(ItCurrent, ItNext)) | ||||
5713 | for (auto *J : llvm::make_range(ItCurrent, ItNext)) | ||||
5714 | if (I != J) | ||||
5715 | 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) | ||||
5716 | "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) | ||||
5717 | "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) | ||||
5718 | I)do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false); | ||||
5719 | ItCurrent = ItNext; | ||||
5720 | } | ||||
5721 | } | ||||
5722 | |||||
5723 | //===----------------------------------------------------------------------===// | ||||
5724 | // Implement the public interfaces to this file... | ||||
5725 | //===----------------------------------------------------------------------===// | ||||
5726 | |||||
5727 | bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { | ||||
5728 | Function &F = const_cast<Function &>(f); | ||||
5729 | |||||
5730 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
5731 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true, *f.getParent()); | ||||
5732 | |||||
5733 | // Note that this function's return value is inverted from what you would | ||||
5734 | // expect of a function called "verify". | ||||
5735 | return !V.verify(F); | ||||
5736 | } | ||||
5737 | |||||
5738 | bool llvm::verifyModule(const Module &M, raw_ostream *OS, | ||||
5739 | bool *BrokenDebugInfo) { | ||||
5740 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
5741 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo, M); | ||||
5742 | |||||
5743 | bool Broken = false; | ||||
5744 | for (const Function &F : M) | ||||
5745 | Broken |= !V.verify(F); | ||||
5746 | |||||
5747 | Broken |= !V.verify(); | ||||
5748 | if (BrokenDebugInfo) | ||||
5749 | *BrokenDebugInfo = V.hasBrokenDebugInfo(); | ||||
5750 | // Note that this function's return value is inverted from what you would | ||||
5751 | // expect of a function called "verify". | ||||
5752 | return Broken; | ||||
5753 | } | ||||
5754 | |||||
5755 | namespace { | ||||
5756 | |||||
5757 | struct VerifierLegacyPass : public FunctionPass { | ||||
5758 | static char ID; | ||||
5759 | |||||
5760 | std::unique_ptr<Verifier> V; | ||||
5761 | bool FatalErrors = true; | ||||
5762 | |||||
5763 | VerifierLegacyPass() : FunctionPass(ID) { | ||||
5764 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
5765 | } | ||||
5766 | explicit VerifierLegacyPass(bool FatalErrors) | ||||
5767 | : FunctionPass(ID), | ||||
5768 | FatalErrors(FatalErrors) { | ||||
5769 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
5770 | } | ||||
5771 | |||||
5772 | bool doInitialization(Module &M) override { | ||||
5773 | V = std::make_unique<Verifier>( | ||||
5774 | &dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false, M); | ||||
5775 | return false; | ||||
5776 | } | ||||
5777 | |||||
5778 | bool runOnFunction(Function &F) override { | ||||
5779 | if (!V->verify(F) && FatalErrors) { | ||||
5780 | errs() << "in function " << F.getName() << '\n'; | ||||
5781 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
5782 | } | ||||
5783 | return false; | ||||
5784 | } | ||||
5785 | |||||
5786 | bool doFinalization(Module &M) override { | ||||
5787 | bool HasErrors = false; | ||||
5788 | for (Function &F : M) | ||||
5789 | if (F.isDeclaration()) | ||||
5790 | HasErrors |= !V->verify(F); | ||||
5791 | |||||
5792 | HasErrors |= !V->verify(); | ||||
5793 | if (FatalErrors && (HasErrors || V->hasBrokenDebugInfo())) | ||||
5794 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
5795 | return false; | ||||
5796 | } | ||||
5797 | |||||
5798 | void getAnalysisUsage(AnalysisUsage &AU) const override { | ||||
5799 | AU.setPreservesAll(); | ||||
5800 | } | ||||
5801 | }; | ||||
5802 | |||||
5803 | } // end anonymous namespace | ||||
5804 | |||||
5805 | /// Helper to issue failure from the TBAA verification | ||||
5806 | template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) { | ||||
5807 | if (Diagnostic) | ||||
5808 | return Diagnostic->CheckFailed(Args...); | ||||
5809 | } | ||||
5810 | |||||
5811 | #define AssertTBAA(C, ...)do { if (!(C)) { CheckFailed(...); return false; } } while (false ) \ | ||||
5812 | do { \ | ||||
5813 | if (!(C)) { \ | ||||
5814 | CheckFailed(__VA_ARGS__); \ | ||||
5815 | return false; \ | ||||
5816 | } \ | ||||
5817 | } while (false) | ||||
5818 | |||||
5819 | /// Verify that \p BaseNode can be used as the "base type" in the struct-path | ||||
5820 | /// TBAA scheme. This means \p BaseNode is either a scalar node, or a | ||||
5821 | /// struct-type node describing an aggregate data structure (like a struct). | ||||
5822 | TBAAVerifier::TBAABaseNodeSummary | ||||
5823 | TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode, | ||||
5824 | bool IsNewFormat) { | ||||
5825 | if (BaseNode->getNumOperands() < 2) { | ||||
5826 | CheckFailed("Base nodes must have at least two operands", &I, BaseNode); | ||||
5827 | return {true, ~0u}; | ||||
5828 | } | ||||
5829 | |||||
5830 | auto Itr = TBAABaseNodes.find(BaseNode); | ||||
5831 | if (Itr != TBAABaseNodes.end()) | ||||
5832 | return Itr->second; | ||||
5833 | |||||
5834 | auto Result = verifyTBAABaseNodeImpl(I, BaseNode, IsNewFormat); | ||||
5835 | auto InsertResult = TBAABaseNodes.insert({BaseNode, Result}); | ||||
5836 | (void)InsertResult; | ||||
5837 | assert(InsertResult.second && "We just checked!")((void)0); | ||||
5838 | return Result; | ||||
5839 | } | ||||
5840 | |||||
5841 | TBAAVerifier::TBAABaseNodeSummary | ||||
5842 | TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode, | ||||
5843 | bool IsNewFormat) { | ||||
5844 | const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u}; | ||||
5845 | |||||
5846 | if (BaseNode->getNumOperands() == 2) { | ||||
5847 | // Scalar nodes can only be accessed at offset 0. | ||||
5848 | return isValidScalarTBAANode(BaseNode) | ||||
5849 | ? TBAAVerifier::TBAABaseNodeSummary({false, 0}) | ||||
5850 | : InvalidNode; | ||||
5851 | } | ||||
5852 | |||||
5853 | if (IsNewFormat) { | ||||
5854 | if (BaseNode->getNumOperands() % 3 != 0) { | ||||
5855 | CheckFailed("Access tag nodes must have the number of operands that is a " | ||||
5856 | "multiple of 3!", BaseNode); | ||||
5857 | return InvalidNode; | ||||
5858 | } | ||||
5859 | } else { | ||||
5860 | if (BaseNode->getNumOperands() % 2 != 1) { | ||||
5861 | CheckFailed("Struct tag nodes must have an odd number of operands!", | ||||
5862 | BaseNode); | ||||
5863 | return InvalidNode; | ||||
5864 | } | ||||
5865 | } | ||||
5866 | |||||
5867 | // Check the type size field. | ||||
5868 | if (IsNewFormat) { | ||||
5869 | auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
5870 | BaseNode->getOperand(1)); | ||||
5871 | if (!TypeSizeNode) { | ||||
5872 | CheckFailed("Type size nodes must be constants!", &I, BaseNode); | ||||
5873 | return InvalidNode; | ||||
5874 | } | ||||
5875 | } | ||||
5876 | |||||
5877 | // Check the type name field. In the new format it can be anything. | ||||
5878 | if (!IsNewFormat && !isa<MDString>(BaseNode->getOperand(0))) { | ||||
5879 | CheckFailed("Struct tag nodes have a string as their first operand", | ||||
5880 | BaseNode); | ||||
5881 | return InvalidNode; | ||||
5882 | } | ||||
5883 | |||||
5884 | bool Failed = false; | ||||
5885 | |||||
5886 | Optional<APInt> PrevOffset; | ||||
5887 | unsigned BitWidth = ~0u; | ||||
5888 | |||||
5889 | // We've already checked that BaseNode is not a degenerate root node with one | ||||
5890 | // operand in \c verifyTBAABaseNode, so this loop should run at least once. | ||||
5891 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
5892 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
5893 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
5894 | Idx += NumOpsPerField) { | ||||
5895 | const MDOperand &FieldTy = BaseNode->getOperand(Idx); | ||||
5896 | const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1); | ||||
5897 | if (!isa<MDNode>(FieldTy)) { | ||||
5898 | CheckFailed("Incorrect field entry in struct type node!", &I, BaseNode); | ||||
5899 | Failed = true; | ||||
5900 | continue; | ||||
5901 | } | ||||
5902 | |||||
5903 | auto *OffsetEntryCI = | ||||
5904 | mdconst::dyn_extract_or_null<ConstantInt>(FieldOffset); | ||||
5905 | if (!OffsetEntryCI) { | ||||
5906 | CheckFailed("Offset entries must be constants!", &I, BaseNode); | ||||
5907 | Failed = true; | ||||
5908 | continue; | ||||
5909 | } | ||||
5910 | |||||
5911 | if (BitWidth == ~0u) | ||||
5912 | BitWidth = OffsetEntryCI->getBitWidth(); | ||||
5913 | |||||
5914 | if (OffsetEntryCI->getBitWidth() != BitWidth) { | ||||
5915 | CheckFailed( | ||||
5916 | "Bitwidth between the offsets and struct type entries must match", &I, | ||||
5917 | BaseNode); | ||||
5918 | Failed = true; | ||||
5919 | continue; | ||||
5920 | } | ||||
5921 | |||||
5922 | // NB! As far as I can tell, we generate a non-strictly increasing offset | ||||
5923 | // sequence only from structs that have zero size bit fields. When | ||||
5924 | // recursing into a contained struct in \c getFieldNodeFromTBAABaseNode we | ||||
5925 | // pick the field lexically the latest in struct type metadata node. This | ||||
5926 | // mirrors the actual behavior of the alias analysis implementation. | ||||
5927 | bool IsAscending = | ||||
5928 | !PrevOffset || PrevOffset->ule(OffsetEntryCI->getValue()); | ||||
5929 | |||||
5930 | if (!IsAscending) { | ||||
5931 | CheckFailed("Offsets must be increasing!", &I, BaseNode); | ||||
5932 | Failed = true; | ||||
5933 | } | ||||
5934 | |||||
5935 | PrevOffset = OffsetEntryCI->getValue(); | ||||
5936 | |||||
5937 | if (IsNewFormat) { | ||||
5938 | auto *MemberSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
5939 | BaseNode->getOperand(Idx + 2)); | ||||
5940 | if (!MemberSizeNode) { | ||||
5941 | CheckFailed("Member size entries must be constants!", &I, BaseNode); | ||||
5942 | Failed = true; | ||||
5943 | continue; | ||||
5944 | } | ||||
5945 | } | ||||
5946 | } | ||||
5947 | |||||
5948 | return Failed ? InvalidNode | ||||
5949 | : TBAAVerifier::TBAABaseNodeSummary(false, BitWidth); | ||||
5950 | } | ||||
5951 | |||||
5952 | static bool IsRootTBAANode(const MDNode *MD) { | ||||
5953 | return MD->getNumOperands() < 2; | ||||
5954 | } | ||||
5955 | |||||
5956 | static bool IsScalarTBAANodeImpl(const MDNode *MD, | ||||
5957 | SmallPtrSetImpl<const MDNode *> &Visited) { | ||||
5958 | if (MD->getNumOperands() != 2 && MD->getNumOperands() != 3) | ||||
5959 | return false; | ||||
5960 | |||||
5961 | if (!isa<MDString>(MD->getOperand(0))) | ||||
5962 | return false; | ||||
5963 | |||||
5964 | if (MD->getNumOperands() == 3) { | ||||
5965 | auto *Offset = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2)); | ||||
5966 | if (!(Offset && Offset->isZero() && isa<MDString>(MD->getOperand(0)))) | ||||
5967 | return false; | ||||
5968 | } | ||||
5969 | |||||
5970 | auto *Parent = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
5971 | return Parent && Visited.insert(Parent).second && | ||||
5972 | (IsRootTBAANode(Parent) || IsScalarTBAANodeImpl(Parent, Visited)); | ||||
5973 | } | ||||
5974 | |||||
5975 | bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) { | ||||
5976 | auto ResultIt = TBAAScalarNodes.find(MD); | ||||
5977 | if (ResultIt != TBAAScalarNodes.end()) | ||||
5978 | return ResultIt->second; | ||||
5979 | |||||
5980 | SmallPtrSet<const MDNode *, 4> Visited; | ||||
5981 | bool Result = IsScalarTBAANodeImpl(MD, Visited); | ||||
5982 | auto InsertResult = TBAAScalarNodes.insert({MD, Result}); | ||||
5983 | (void)InsertResult; | ||||
5984 | assert(InsertResult.second && "Just checked!")((void)0); | ||||
5985 | |||||
5986 | return Result; | ||||
5987 | } | ||||
5988 | |||||
5989 | /// Returns the field node at the offset \p Offset in \p BaseNode. Update \p | ||||
5990 | /// Offset in place to be the offset within the field node returned. | ||||
5991 | /// | ||||
5992 | /// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode. | ||||
5993 | MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, | ||||
5994 | const MDNode *BaseNode, | ||||
5995 | APInt &Offset, | ||||
5996 | bool IsNewFormat) { | ||||
5997 | assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!")((void)0); | ||||
5998 | |||||
5999 | // Scalar nodes have only one possible "field" -- their parent in the access | ||||
6000 | // hierarchy. Offset must be zero at this point, but our caller is supposed | ||||
6001 | // to Assert that. | ||||
6002 | if (BaseNode->getNumOperands() == 2) | ||||
6003 | return cast<MDNode>(BaseNode->getOperand(1)); | ||||
6004 | |||||
6005 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
6006 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
6007 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
6008 | Idx += NumOpsPerField) { | ||||
6009 | auto *OffsetEntryCI = | ||||
6010 | mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1)); | ||||
6011 | if (OffsetEntryCI->getValue().ugt(Offset)) { | ||||
6012 | if (Idx == FirstFieldOpNo) { | ||||
6013 | CheckFailed("Could not find TBAA parent in struct type node", &I, | ||||
6014 | BaseNode, &Offset); | ||||
6015 | return nullptr; | ||||
6016 | } | ||||
6017 | |||||
6018 | unsigned PrevIdx = Idx - NumOpsPerField; | ||||
6019 | auto *PrevOffsetEntryCI = | ||||
6020 | mdconst::extract<ConstantInt>(BaseNode->getOperand(PrevIdx + 1)); | ||||
6021 | Offset -= PrevOffsetEntryCI->getValue(); | ||||
6022 | return cast<MDNode>(BaseNode->getOperand(PrevIdx)); | ||||
6023 | } | ||||
6024 | } | ||||
6025 | |||||
6026 | unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField; | ||||
6027 | auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( | ||||
6028 | BaseNode->getOperand(LastIdx + 1)); | ||||
6029 | Offset -= LastOffsetEntryCI->getValue(); | ||||
6030 | return cast<MDNode>(BaseNode->getOperand(LastIdx)); | ||||
6031 | } | ||||
6032 | |||||
6033 | static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { | ||||
6034 | if (!Type || Type->getNumOperands() < 3) | ||||
6035 | return false; | ||||
6036 | |||||
6037 | // In the new format type nodes shall have a reference to the parent type as | ||||
6038 | // its first operand. | ||||
6039 | MDNode *Parent = dyn_cast_or_null<MDNode>(Type->getOperand(0)); | ||||
6040 | if (!Parent) | ||||
6041 | return false; | ||||
6042 | |||||
6043 | return true; | ||||
6044 | } | ||||
6045 | |||||
6046 | bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { | ||||
6047 | 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) | ||||
6048 | 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) | ||||
6049 | 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) | ||||
6050 | "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); | ||||
6051 | |||||
6052 | bool IsStructPathTBAA = | ||||
6053 | isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; | ||||
6054 | |||||
6055 | AssertTBAA(do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
6056 | IsStructPathTBAA,do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
6057 | "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); | ||||
6058 | |||||
6059 | MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0)); | ||||
6060 | MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
6061 | |||||
6062 | bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); | ||||
6063 | |||||
6064 | if (IsNewFormat) { | ||||
6065 | 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) | ||||
6066 | "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); | ||||
6067 | } else { | ||||
6068 | 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) | ||||
6069 | "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); | ||||
6070 | } | ||||
6071 | |||||
6072 | // Check the access size field. | ||||
6073 | if (IsNewFormat) { | ||||
6074 | auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6075 | MD->getOperand(3)); | ||||
6076 | 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); | ||||
6077 | } | ||||
6078 | |||||
6079 | // Check the immutability flag. | ||||
6080 | unsigned ImmutabilityFlagOpNo = IsNewFormat ? 4 : 3; | ||||
6081 | if (MD->getNumOperands() == ImmutabilityFlagOpNo + 1) { | ||||
6082 | auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6083 | MD->getOperand(ImmutabilityFlagOpNo)); | ||||
6084 | AssertTBAA(IsImmutableCI,do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
6085 | "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) | ||||
6086 | &I, MD)do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false); | ||||
6087 | 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) | ||||
6088 | 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) | ||||
6089 | "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) | ||||
6090 | &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); | ||||
6091 | } | ||||
6092 | |||||
6093 | 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) | ||||
6094 | "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) | ||||
6095 | "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) | ||||
6096 | &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); | ||||
6097 | |||||
6098 | if (!IsNewFormat) { | ||||
6099 | AssertTBAA(isValidScalarTBAANode(AccessType),do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
6100 | "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) | ||||
6101 | AccessType)do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false); | ||||
6102 | } | ||||
6103 | |||||
6104 | auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2)); | ||||
6105 | AssertTBAA(OffsetCI, "Offset must be constant integer", &I, MD)do { if (!(OffsetCI)) { CheckFailed("Offset must be constant integer" , &I, MD); return false; } } while (false); | ||||
6106 | |||||
6107 | APInt Offset = OffsetCI->getValue(); | ||||
6108 | bool SeenAccessTypeInPath = false; | ||||
6109 | |||||
6110 | SmallPtrSet<MDNode *, 4> StructPath; | ||||
6111 | |||||
6112 | for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); | ||||
6113 | BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, | ||||
6114 | IsNewFormat)) { | ||||
6115 | if (!StructPath.insert(BaseNode).second) { | ||||
6116 | CheckFailed("Cycle detected in struct path", &I, MD); | ||||
6117 | return false; | ||||
6118 | } | ||||
6119 | |||||
6120 | bool Invalid; | ||||
6121 | unsigned BaseNodeBitWidth; | ||||
6122 | std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode, | ||||
6123 | IsNewFormat); | ||||
6124 | |||||
6125 | // If the base node is invalid in itself, then we've already printed all the | ||||
6126 | // errors we wanted to print. | ||||
6127 | if (Invalid) | ||||
6128 | return false; | ||||
6129 | |||||
6130 | SeenAccessTypeInPath |= BaseNode == AccessType; | ||||
6131 | |||||
6132 | if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType) | ||||
6133 | 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) | ||||
6134 | &I, MD, &Offset)do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false); | ||||
6135 | |||||
6136 | 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) | ||||
6137 | (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) | ||||
6138 | (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) | ||||
6139 | "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) | ||||
6140 | 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); | ||||
6141 | |||||
6142 | if (IsNewFormat && SeenAccessTypeInPath) | ||||
6143 | break; | ||||
6144 | } | ||||
6145 | |||||
6146 | 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) | ||||
6147 | &I, MD)do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false); | ||||
6148 | return true; | ||||
6149 | } | ||||
6150 | |||||
6151 | char VerifierLegacyPass::ID = 0; | ||||
6152 | 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)); } | ||||
6153 | |||||
6154 | FunctionPass *llvm::createVerifierPass(bool FatalErrors) { | ||||
6155 | return new VerifierLegacyPass(FatalErrors); | ||||
6156 | } | ||||
6157 | |||||
6158 | AnalysisKey VerifierAnalysis::Key; | ||||
6159 | VerifierAnalysis::Result VerifierAnalysis::run(Module &M, | ||||
6160 | ModuleAnalysisManager &) { | ||||
6161 | Result Res; | ||||
6162 | Res.IRBroken = llvm::verifyModule(M, &dbgs(), &Res.DebugInfoBroken); | ||||
6163 | return Res; | ||||
6164 | } | ||||
6165 | |||||
6166 | VerifierAnalysis::Result VerifierAnalysis::run(Function &F, | ||||
6167 | FunctionAnalysisManager &) { | ||||
6168 | return { llvm::verifyFunction(F, &dbgs()), false }; | ||||
6169 | } | ||||
6170 | |||||
6171 | PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { | ||||
6172 | auto Res = AM.getResult<VerifierAnalysis>(M); | ||||
6173 | if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) | ||||
6174 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
6175 | |||||
6176 | return PreservedAnalyses::all(); | ||||
6177 | } | ||||
6178 | |||||
6179 | PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { | ||||
6180 | auto res = AM.getResult<VerifierAnalysis>(F); | ||||
6181 | if (res.IRBroken && FatalErrors) | ||||
6182 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
6183 | |||||
6184 | return PreservedAnalyses::all(); | ||||
6185 | } |
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)((void)0); | ||||
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")((void)0); | ||||
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, StorageType Storage, bool ShouldCreate = true) { | ||||
940 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, | ||||
941 | Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, | ||||
942 | DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate); | ||||
943 | } | ||||
944 | static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
945 | MDString *Name, Metadata *File, unsigned Line, | ||||
946 | Metadata *Scope, Metadata *BaseType, | ||||
947 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
948 | uint64_t OffsetInBits, | ||||
949 | Optional<unsigned> DWARFAddressSpace, | ||||
950 | DIFlags Flags, Metadata *ExtraData, | ||||
951 | StorageType Storage, bool ShouldCreate = true); | ||||
952 | |||||
953 | TempDIDerivedType cloneImpl() const { | ||||
954 | return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), | ||||
955 | getScope(), getBaseType(), getSizeInBits(), | ||||
956 | getAlignInBits(), getOffsetInBits(), | ||||
957 | getDWARFAddressSpace(), getFlags(), getExtraData()); | ||||
958 | } | ||||
959 | |||||
960 | public: | ||||
961 | DEFINE_MDNODE_GET(DIDerivedType, | ||||
962 | (unsigned Tag, MDString *Name, Metadata *File, | ||||
963 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||
964 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
965 | uint64_t OffsetInBits, | ||||
966 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
967 | Metadata *ExtraData = nullptr), | ||||
968 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||
969 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||
970 | ExtraData)) | ||||
971 | DEFINE_MDNODE_GET(DIDerivedType, | ||||
972 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||
973 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
974 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
975 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
976 | Metadata *ExtraData = nullptr), | ||||
977 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||
978 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||
979 | ExtraData)) | ||||
980 | |||||
981 | TempDIDerivedType clone() const { return cloneImpl(); } | ||||
982 | |||||
983 | /// Get the base type this is derived from. | ||||
984 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||
985 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||
986 | |||||
987 | /// \returns The DWARF address space of the memory pointed to or referenced by | ||||
988 | /// a pointer or reference type respectively. | ||||
989 | Optional<unsigned> getDWARFAddressSpace() const { return DWARFAddressSpace; } | ||||
990 | |||||
991 | /// Get extra data associated with this derived type. | ||||
992 | /// | ||||
993 | /// Class type for pointer-to-members, objective-c property node for ivars, | ||||
994 | /// global constant wrapper for static members, or virtual base pointer offset | ||||
995 | /// for inheritance. | ||||
996 | /// | ||||
997 | /// TODO: Separate out types that need this extra operand: pointer-to-member | ||||
998 | /// types and member fields (static members and ivars). | ||||
999 | Metadata *getExtraData() const { return getRawExtraData(); } | ||||
1000 | Metadata *getRawExtraData() const { return getOperand(4); } | ||||
1001 | |||||
1002 | /// Get casted version of extra data. | ||||
1003 | /// @{ | ||||
1004 | DIType *getClassType() const { | ||||
1005 | assert(getTag() == dwarf::DW_TAG_ptr_to_member_type)((void)0); | ||||
1006 | return cast_or_null<DIType>(getExtraData()); | ||||
1007 | } | ||||
1008 | |||||
1009 | DIObjCProperty *getObjCProperty() const { | ||||
1010 | return dyn_cast_or_null<DIObjCProperty>(getExtraData()); | ||||
1011 | } | ||||
1012 | |||||
1013 | uint32_t getVBPtrOffset() const { | ||||
1014 | assert(getTag() == dwarf::DW_TAG_inheritance)((void)0); | ||||
1015 | if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1016 | if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue())) | ||||
1017 | return static_cast<uint32_t>(CI->getZExtValue()); | ||||
1018 | return 0; | ||||
1019 | } | ||||
1020 | |||||
1021 | Constant *getStorageOffsetInBits() const { | ||||
1022 | assert(getTag() == dwarf::DW_TAG_member && isBitField())((void)0); | ||||
1023 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1024 | return C->getValue(); | ||||
1025 | return nullptr; | ||||
1026 | } | ||||
1027 | |||||
1028 | Constant *getConstant() const { | ||||
1029 | assert(getTag() == dwarf::DW_TAG_member && isStaticMember())((void)0); | ||||
1030 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1031 | return C->getValue(); | ||||
1032 | return nullptr; | ||||
1033 | } | ||||
1034 | Constant *getDiscriminantValue() const { | ||||
1035 | assert(getTag() == dwarf::DW_TAG_member && !isStaticMember())((void)0); | ||||
1036 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
1037 | return C->getValue(); | ||||
1038 | return nullptr; | ||||
1039 | } | ||||
1040 | /// @} | ||||
1041 | |||||
1042 | static bool classof(const Metadata *MD) { | ||||
1043 | return MD->getMetadataID() == DIDerivedTypeKind; | ||||
1044 | } | ||||
1045 | }; | ||||
1046 | |||||
1047 | /// Composite types. | ||||
1048 | /// | ||||
1049 | /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). | ||||
1050 | /// TODO: Create a custom, unrelated node for DW_TAG_array_type. | ||||
1051 | class DICompositeType : public DIType { | ||||
1052 | friend class LLVMContextImpl; | ||||
1053 | friend class MDNode; | ||||
1054 | |||||
1055 | unsigned RuntimeLang; | ||||
1056 | |||||
1057 | DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
1058 | unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, | ||||
1059 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1060 | ArrayRef<Metadata *> Ops) | ||||
1061 | : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, | ||||
1062 | AlignInBits, OffsetInBits, Flags, Ops), | ||||
1063 | RuntimeLang(RuntimeLang) {} | ||||
1064 | ~DICompositeType() = default; | ||||
1065 | |||||
1066 | /// Change fields in place. | ||||
1067 | void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, | ||||
1068 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
1069 | uint64_t OffsetInBits, DIFlags Flags) { | ||||
1070 | assert(isDistinct() && "Only distinct nodes can mutate")((void)0); | ||||
1071 | assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate")((void)0); | ||||
1072 | this->RuntimeLang = RuntimeLang; | ||||
1073 | DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||
1074 | } | ||||
1075 | |||||
1076 | static DICompositeType * | ||||
1077 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, | ||||
1078 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
1079 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1080 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||
1081 | DITemplateParameterArray TemplateParams, StringRef Identifier, | ||||
1082 | DIDerivedType *Discriminator, Metadata *DataLocation, | ||||
1083 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||
1084 | StorageType Storage, bool ShouldCreate = true) { | ||||
1085 | return getImpl( | ||||
1086 | Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, | ||||
1087 | BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), | ||||
1088 | RuntimeLang, VTableHolder, TemplateParams.get(), | ||||
1089 | getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, | ||||
1090 | Associated, Allocated, Rank, Storage, ShouldCreate); | ||||
1091 | } | ||||
1092 | static DICompositeType * | ||||
1093 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||
1094 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||
1095 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
1096 | DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, | ||||
1097 | Metadata *VTableHolder, Metadata *TemplateParams, | ||||
1098 | MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, | ||||
1099 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||
1100 | StorageType Storage, bool ShouldCreate = true); | ||||
1101 | |||||
1102 | TempDICompositeType cloneImpl() const { | ||||
1103 | return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), | ||||
1104 | getScope(), getBaseType(), getSizeInBits(), | ||||
1105 | getAlignInBits(), getOffsetInBits(), getFlags(), | ||||
1106 | getElements(), getRuntimeLang(), getVTableHolder(), | ||||
1107 | getTemplateParams(), getIdentifier(), | ||||
1108 | getDiscriminator(), getRawDataLocation(), | ||||
1109 | getRawAssociated(), getRawAllocated(), getRawRank()); | ||||
1110 | } | ||||
1111 | |||||
1112 | public: | ||||
1113 | DEFINE_MDNODE_GET( | ||||
1114 | DICompositeType, | ||||
1115 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||
1116 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
1117 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1118 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||
1119 | DITemplateParameterArray TemplateParams = nullptr, | ||||
1120 | StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, | ||||
1121 | Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, | ||||
1122 | Metadata *Allocated = nullptr, Metadata *Rank = nullptr), | ||||
1123 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||
1124 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||
1125 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) | ||||
1126 | DEFINE_MDNODE_GET( | ||||
1127 | DICompositeType, | ||||
1128 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, | ||||
1129 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, | ||||
1130 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
1131 | Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, | ||||
1132 | Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, | ||||
1133 | Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, | ||||
1134 | Metadata *Associated = nullptr, Metadata *Allocated = nullptr, | ||||
1135 | Metadata *Rank = nullptr), | ||||
1136 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||
1137 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||
1138 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) | ||||
1139 | |||||
1140 | TempDICompositeType clone() const { return cloneImpl(); } | ||||
1141 | |||||
1142 | /// Get a DICompositeType with the given ODR identifier. | ||||
1143 | /// | ||||
1144 | /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped | ||||
1145 | /// DICompositeType for the given ODR \c Identifier. If none exists, creates | ||||
1146 | /// a new node. | ||||
1147 | /// | ||||
1148 | /// Else, returns \c nullptr. | ||||
1149 | static DICompositeType * | ||||
1150 | getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||
1151 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||
1152 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
1153 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||
1154 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||
1155 | Metadata *TemplateParams, Metadata *Discriminator, | ||||
1156 | Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, | ||||
1157 | Metadata *Rank); | ||||
1158 | static DICompositeType *getODRTypeIfExists(LLVMContext &Context, | ||||
1159 | MDString &Identifier); | ||||
1160 | |||||
1161 | /// Build a DICompositeType with the given ODR identifier. | ||||
1162 | /// | ||||
1163 | /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If | ||||
1164 | /// it doesn't exist, creates a new one. If it does exist and \a | ||||
1165 | /// isForwardDecl(), and the new arguments would be a definition, mutates the | ||||
1166 | /// the type in place. In either case, returns the type. | ||||
1167 | /// | ||||
1168 | /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns | ||||
1169 | /// nullptr. | ||||
1170 | static DICompositeType * | ||||
1171 | buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||
1172 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||
1173 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
1174 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||
1175 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||
1176 | Metadata *TemplateParams, Metadata *Discriminator, | ||||
1177 | Metadata *DataLocation, Metadata *Associated, | ||||
1178 | Metadata *Allocated, Metadata *Rank); | ||||
1179 | |||||
1180 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||
1181 | DINodeArray getElements() const { | ||||
1182 | return cast_or_null<MDTuple>(getRawElements()); | ||||
1183 | } | ||||
1184 | DIType *getVTableHolder() const { | ||||
1185 | return cast_or_null<DIType>(getRawVTableHolder()); | ||||
1186 | } | ||||
1187 | DITemplateParameterArray getTemplateParams() const { | ||||
1188 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||
1189 | } | ||||
1190 | StringRef getIdentifier() const { return getStringOperand(7); } | ||||
1191 | unsigned getRuntimeLang() const { return RuntimeLang; } | ||||
1192 | |||||
1193 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||
1194 | Metadata *getRawElements() const { return getOperand(4); } | ||||
1195 | Metadata *getRawVTableHolder() const { return getOperand(5); } | ||||
1196 | Metadata *getRawTemplateParams() const { return getOperand(6); } | ||||
1197 | MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } | ||||
1198 | Metadata *getRawDiscriminator() const { return getOperand(8); } | ||||
1199 | DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); } | ||||
1200 | Metadata *getRawDataLocation() const { return getOperand(9); } | ||||
1201 | DIVariable *getDataLocation() const { | ||||
1202 | return dyn_cast_or_null<DIVariable>(getRawDataLocation()); | ||||
1203 | } | ||||
1204 | DIExpression *getDataLocationExp() const { | ||||
1205 | return dyn_cast_or_null<DIExpression>(getRawDataLocation()); | ||||
1206 | } | ||||
1207 | Metadata *getRawAssociated() const { return getOperand(10); } | ||||
1208 | DIVariable *getAssociated() const { | ||||
1209 | return dyn_cast_or_null<DIVariable>(getRawAssociated()); | ||||
1210 | } | ||||
1211 | DIExpression *getAssociatedExp() const { | ||||
1212 | return dyn_cast_or_null<DIExpression>(getRawAssociated()); | ||||
1213 | } | ||||
1214 | Metadata *getRawAllocated() const { return getOperand(11); } | ||||
1215 | DIVariable *getAllocated() const { | ||||
1216 | return dyn_cast_or_null<DIVariable>(getRawAllocated()); | ||||
1217 | } | ||||
1218 | DIExpression *getAllocatedExp() const { | ||||
1219 | return dyn_cast_or_null<DIExpression>(getRawAllocated()); | ||||
1220 | } | ||||
1221 | Metadata *getRawRank() const { return getOperand(12); } | ||||
1222 | ConstantInt *getRankConst() const { | ||||
1223 | if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawRank())) | ||||
1224 | return dyn_cast_or_null<ConstantInt>(MD->getValue()); | ||||
1225 | return nullptr; | ||||
1226 | } | ||||
1227 | DIExpression *getRankExp() const { | ||||
1228 | return dyn_cast_or_null<DIExpression>(getRawRank()); | ||||
1229 | } | ||||
1230 | |||||
1231 | /// Replace operands. | ||||
1232 | /// | ||||
1233 | /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision | ||||
1234 | /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track | ||||
1235 | /// of its movement if necessary. | ||||
1236 | /// @{ | ||||
1237 | void replaceElements(DINodeArray Elements) { | ||||
1238 | #ifndef NDEBUG1 | ||||
1239 | for (DINode *Op : getElements()) | ||||
1240 | assert(is_contained(Elements->operands(), Op) &&((void)0) | ||||
1241 | "Lost a member during member list replacement")((void)0); | ||||
1242 | #endif | ||||
1243 | replaceOperandWith(4, Elements.get()); | ||||
1244 | } | ||||
1245 | |||||
1246 | void replaceVTableHolder(DIType *VTableHolder) { | ||||
1247 | replaceOperandWith(5, VTableHolder); | ||||
1248 | } | ||||
1249 | |||||
1250 | void replaceTemplateParams(DITemplateParameterArray TemplateParams) { | ||||
1251 | replaceOperandWith(6, TemplateParams.get()); | ||||
1252 | } | ||||
1253 | /// @} | ||||
1254 | |||||
1255 | static bool classof(const Metadata *MD) { | ||||
1256 | return MD->getMetadataID() == DICompositeTypeKind; | ||||
1257 | } | ||||
1258 | }; | ||||
1259 | |||||
1260 | /// Type array for a subprogram. | ||||
1261 | /// | ||||
1262 | /// TODO: Fold the array of types in directly as operands. | ||||
1263 | class DISubroutineType : public DIType { | ||||
1264 | friend class LLVMContextImpl; | ||||
1265 | friend class MDNode; | ||||
1266 | |||||
1267 | /// The calling convention used with DW_AT_calling_convention. Actually of | ||||
1268 | /// type dwarf::CallingConvention. | ||||
1269 | uint8_t CC; | ||||
1270 | |||||
1271 | DISubroutineType(LLVMContext &C, StorageType Storage, DIFlags Flags, | ||||
1272 | uint8_t CC, ArrayRef<Metadata *> Ops) | ||||
1273 | : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, | ||||
1274 | 0, 0, 0, 0, Flags, Ops), | ||||
1275 | CC(CC) {} | ||||
1276 | ~DISubroutineType() = default; | ||||
1277 | |||||
1278 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||
1279 | uint8_t CC, DITypeRefArray TypeArray, | ||||
1280 | StorageType Storage, | ||||
1281 | bool ShouldCreate = true) { | ||||
1282 | return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); | ||||
1283 | } | ||||
1284 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||
1285 | uint8_t CC, Metadata *TypeArray, | ||||
1286 | StorageType Storage, | ||||
1287 | bool ShouldCreate = true); | ||||
1288 | |||||
1289 | TempDISubroutineType cloneImpl() const { | ||||
1290 | return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); | ||||
1291 | } | ||||
1292 | |||||
1293 | public: | ||||
1294 | DEFINE_MDNODE_GET(DISubroutineType, | ||||
1295 | (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), | ||||
1296 | (Flags, CC, TypeArray)) | ||||
1297 | DEFINE_MDNODE_GET(DISubroutineType, | ||||
1298 | (DIFlags Flags, uint8_t CC, Metadata *TypeArray), | ||||
1299 | (Flags, CC, TypeArray)) | ||||
1300 | |||||
1301 | TempDISubroutineType clone() const { return cloneImpl(); } | ||||
1302 | |||||
1303 | uint8_t getCC() const { return CC; } | ||||
1304 | |||||
1305 | DITypeRefArray getTypeArray() const { | ||||
1306 | return cast_or_null<MDTuple>(getRawTypeArray()); | ||||
1307 | } | ||||
1308 | |||||
1309 | Metadata *getRawTypeArray() const { return getOperand(3); } | ||||
1310 | |||||
1311 | static bool classof(const Metadata *MD) { | ||||
1312 | return MD->getMetadataID() == DISubroutineTypeKind; | ||||
1313 | } | ||||
1314 | }; | ||||
1315 | |||||
1316 | /// Compile unit. | ||||
1317 | class DICompileUnit : public DIScope { | ||||
1318 | friend class LLVMContextImpl; | ||||
1319 | friend class MDNode; | ||||
1320 | |||||
1321 | public: | ||||
1322 | enum DebugEmissionKind : unsigned { | ||||
1323 | NoDebug = 0, | ||||
1324 | FullDebug, | ||||
1325 | LineTablesOnly, | ||||
1326 | DebugDirectivesOnly, | ||||
1327 | LastEmissionKind = DebugDirectivesOnly | ||||
1328 | }; | ||||
1329 | |||||
1330 | enum class DebugNameTableKind : unsigned { | ||||
1331 | Default = 0, | ||||
1332 | GNU = 1, | ||||
1333 | None = 2, | ||||
1334 | LastDebugNameTableKind = None | ||||
1335 | }; | ||||
1336 | |||||
1337 | static Optional<DebugEmissionKind> getEmissionKind(StringRef Str); | ||||
1338 | static const char *emissionKindString(DebugEmissionKind EK); | ||||
1339 | static Optional<DebugNameTableKind> getNameTableKind(StringRef Str); | ||||
1340 | static const char *nameTableKindString(DebugNameTableKind PK); | ||||
1341 | |||||
1342 | private: | ||||
1343 | unsigned SourceLanguage; | ||||
1344 | bool IsOptimized; | ||||
1345 | unsigned RuntimeVersion; | ||||
1346 | unsigned EmissionKind; | ||||
1347 | uint64_t DWOId; | ||||
1348 | bool SplitDebugInlining; | ||||
1349 | bool DebugInfoForProfiling; | ||||
1350 | unsigned NameTableKind; | ||||
1351 | bool RangesBaseAddress; | ||||
1352 | |||||
1353 | DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, | ||||
1354 | bool IsOptimized, unsigned RuntimeVersion, | ||||
1355 | unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, | ||||
1356 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||
1357 | bool RangesBaseAddress, ArrayRef<Metadata *> Ops) | ||||
1358 | : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), | ||||
1359 | SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), | ||||
1360 | RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), | ||||
1361 | DWOId(DWOId), SplitDebugInlining(SplitDebugInlining), | ||||
1362 | DebugInfoForProfiling(DebugInfoForProfiling), | ||||
1363 | NameTableKind(NameTableKind), RangesBaseAddress(RangesBaseAddress) { | ||||
1364 | assert(Storage != Uniqued)((void)0); | ||||
1365 | } | ||||
1366 | ~DICompileUnit() = default; | ||||
1367 | |||||
1368 | static DICompileUnit * | ||||
1369 | getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, | ||||
1370 | StringRef Producer, bool IsOptimized, StringRef Flags, | ||||
1371 | unsigned RuntimeVersion, StringRef SplitDebugFilename, | ||||
1372 | unsigned EmissionKind, DICompositeTypeArray EnumTypes, | ||||
1373 | DIScopeArray RetainedTypes, | ||||
1374 | DIGlobalVariableExpressionArray GlobalVariables, | ||||
1375 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, | ||||
1376 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, | ||||
1377 | unsigned NameTableKind, bool RangesBaseAddress, StringRef SysRoot, | ||||
1378 | StringRef SDK, StorageType Storage, bool ShouldCreate = true) { | ||||
1379 | return getImpl( | ||||
1380 | Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), | ||||
1381 | IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, | ||||
1382 | getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, | ||||
1383 | EnumTypes.get(), RetainedTypes.get(), GlobalVariables.get(), | ||||
1384 | ImportedEntities.get(), Macros.get(), DWOId, SplitDebugInlining, | ||||
1385 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, | ||||
1386 | getCanonicalMDString(Context, SysRoot), | ||||
1387 | getCanonicalMDString(Context, SDK), Storage, ShouldCreate); | ||||
1388 | } | ||||
1389 | static DICompileUnit * | ||||
1390 | getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, | ||||
1391 | MDString *Producer, bool IsOptimized, MDString *Flags, | ||||
1392 | unsigned RuntimeVersion, MDString *SplitDebugFilename, | ||||
1393 | unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, | ||||
1394 | Metadata *GlobalVariables, Metadata *ImportedEntities, | ||||
1395 | Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, | ||||
1396 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||
1397 | bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, | ||||
1398 | StorageType Storage, bool ShouldCreate = true); | ||||
1399 | |||||
1400 | TempDICompileUnit cloneImpl() const { | ||||
1401 | return getTemporary( | ||||
1402 | getContext(), getSourceLanguage(), getFile(), getProducer(), | ||||
1403 | isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), | ||||
1404 | getEmissionKind(), getEnumTypes(), getRetainedTypes(), | ||||
1405 | getGlobalVariables(), getImportedEntities(), getMacros(), DWOId, | ||||
1406 | getSplitDebugInlining(), getDebugInfoForProfiling(), getNameTableKind(), | ||||
1407 | getRangesBaseAddress(), getSysRoot(), getSDK()); | ||||
1408 | } | ||||
1409 | |||||
1410 | public: | ||||
1411 | static void get() = delete; | ||||
1412 | static void getIfExists() = delete; | ||||
1413 | |||||
1414 | 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 )); } | ||||
1415 | 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 )); } | ||||
1416 | (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 )); } | ||||
1417 | 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 )); } | ||||
1418 | 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 )); } | ||||
1419 | 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 )); } | ||||
1420 | 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 )); } | ||||
1421 | 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 )); } | ||||
1422 | 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 )); } | ||||
1423 | 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 )); } | ||||
1424 | 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 )); } | ||||
1425 | (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 )); } | ||||
1426 | 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 )); } | ||||
1427 | 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 )); } | ||||
1428 | 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 )); } | ||||
1429 | 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 )); } | ||||
1430 | 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)); } | ||||
1431 | 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)); } | ||||
1432 | (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)); } | ||||
1433 | 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)); } | ||||
1434 | 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)); } | ||||
1435 | 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)); } | ||||
1436 | 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)); } | ||||
1437 | 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)); } | ||||
1438 | 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)); } | ||||
1439 | 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)); } | ||||
1440 | (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)); } | ||||
1441 | 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)); } | ||||
1442 | 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)); } | ||||
1443 | 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)); } | ||||
1444 | |||||
1445 | TempDICompileUnit clone() const { return cloneImpl(); } | ||||
1446 | |||||
1447 | unsigned getSourceLanguage() const { return SourceLanguage; } | ||||
1448 | bool isOptimized() const { return IsOptimized; } | ||||
1449 | unsigned getRuntimeVersion() const { return RuntimeVersion; } | ||||
1450 | DebugEmissionKind getEmissionKind() const { | ||||
1451 | return (DebugEmissionKind)EmissionKind; | ||||
1452 | } | ||||
1453 | bool isDebugDirectivesOnly() const { | ||||
1454 | return EmissionKind == DebugDirectivesOnly; | ||||
1455 | } | ||||
1456 | bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; } | ||||
1457 | DebugNameTableKind getNameTableKind() const { | ||||
1458 | return (DebugNameTableKind)NameTableKind; | ||||
1459 | } | ||||
1460 | bool getRangesBaseAddress() const { return RangesBaseAddress; } | ||||
1461 | StringRef getProducer() const { return getStringOperand(1); } | ||||
1462 | StringRef getFlags() const { return getStringOperand(2); } | ||||
1463 | StringRef getSplitDebugFilename() const { return getStringOperand(3); } | ||||
1464 | DICompositeTypeArray getEnumTypes() const { | ||||
1465 | return cast_or_null<MDTuple>(getRawEnumTypes()); | ||||
1466 | } | ||||
1467 | DIScopeArray getRetainedTypes() const { | ||||
1468 | return cast_or_null<MDTuple>(getRawRetainedTypes()); | ||||
1469 | } | ||||
1470 | DIGlobalVariableExpressionArray getGlobalVariables() const { | ||||
1471 | return cast_or_null<MDTuple>(getRawGlobalVariables()); | ||||
1472 | } | ||||
1473 | DIImportedEntityArray getImportedEntities() const { | ||||
1474 | return cast_or_null<MDTuple>(getRawImportedEntities()); | ||||
1475 | } | ||||
1476 | DIMacroNodeArray getMacros() const { | ||||
1477 | return cast_or_null<MDTuple>(getRawMacros()); | ||||
1478 | } | ||||
1479 | uint64_t getDWOId() const { return DWOId; } | ||||
1480 | void setDWOId(uint64_t DwoId) { DWOId = DwoId; } | ||||
1481 | bool getSplitDebugInlining() const { return SplitDebugInlining; } | ||||
1482 | void setSplitDebugInlining(bool SplitDebugInlining) { | ||||
1483 | this->SplitDebugInlining = SplitDebugInlining; | ||||
1484 | } | ||||
1485 | StringRef getSysRoot() const { return getStringOperand(9); } | ||||
1486 | StringRef getSDK() const { return getStringOperand(10); } | ||||
1487 | |||||
1488 | MDString *getRawProducer() const { return getOperandAs<MDString>(1); } | ||||
1489 | MDString *getRawFlags() const { return getOperandAs<MDString>(2); } | ||||
1490 | MDString *getRawSplitDebugFilename() const { | ||||
1491 | return getOperandAs<MDString>(3); | ||||
1492 | } | ||||
1493 | Metadata *getRawEnumTypes() const { return getOperand(4); } | ||||
1494 | Metadata *getRawRetainedTypes() const { return getOperand(5); } | ||||
1495 | Metadata *getRawGlobalVariables() const { return getOperand(6); } | ||||
1496 | Metadata *getRawImportedEntities() const { return getOperand(7); } | ||||
1497 | Metadata *getRawMacros() const { return getOperand(8); } | ||||
1498 | MDString *getRawSysRoot() const { return getOperandAs<MDString>(9); } | ||||
1499 | MDString *getRawSDK() const { return getOperandAs<MDString>(10); } | ||||
1500 | |||||
1501 | /// Replace arrays. | ||||
1502 | /// | ||||
1503 | /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and | ||||
1504 | /// deleted on a uniquing collision. In practice, uniquing collisions on \a | ||||
1505 | /// DICompileUnit should be fairly rare. | ||||
1506 | /// @{ | ||||
1507 | void replaceEnumTypes(DICompositeTypeArray N) { | ||||
1508 | replaceOperandWith(4, N.get()); | ||||
1509 | } | ||||
1510 | void replaceRetainedTypes(DITypeArray N) { | ||||
1511 | replaceOperandWith(5, N.get()); | ||||
1512 | } | ||||
1513 | void replaceGlobalVariables(DIGlobalVariableExpressionArray N) { | ||||
1514 | replaceOperandWith(6, N.get()); | ||||
1515 | } | ||||
1516 | void replaceImportedEntities(DIImportedEntityArray N) { | ||||
1517 | replaceOperandWith(7, N.get()); | ||||
1518 | } | ||||
1519 | void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); } | ||||
1520 | /// @} | ||||
1521 | |||||
1522 | static bool classof(const Metadata *MD) { | ||||
1523 | return MD->getMetadataID() == DICompileUnitKind; | ||||
1524 | } | ||||
1525 | }; | ||||
1526 | |||||
1527 | /// A scope for locals. | ||||
1528 | /// | ||||
1529 | /// A legal scope for lexical blocks, local variables, and debug info | ||||
1530 | /// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a | ||||
1531 | /// DILexicalBlockFile. | ||||
1532 | class DILocalScope : public DIScope { | ||||
1533 | protected: | ||||
1534 | DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
1535 | ArrayRef<Metadata *> Ops) | ||||
1536 | : DIScope(C, ID, Storage, Tag, Ops) {} | ||||
1537 | ~DILocalScope() = default; | ||||
1538 | |||||
1539 | public: | ||||
1540 | /// Get the subprogram for this scope. | ||||
1541 | /// | ||||
1542 | /// Return this if it's an \a DISubprogram; otherwise, look up the scope | ||||
1543 | /// chain. | ||||
1544 | DISubprogram *getSubprogram() const; | ||||
1545 | |||||
1546 | /// Get the first non DILexicalBlockFile scope of this scope. | ||||
1547 | /// | ||||
1548 | /// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the | ||||
1549 | /// scope chain. | ||||
1550 | DILocalScope *getNonLexicalBlockFileScope() const; | ||||
1551 | |||||
1552 | static bool classof(const Metadata *MD) { | ||||
1553 | return MD->getMetadataID() == DISubprogramKind || | ||||
1554 | MD->getMetadataID() == DILexicalBlockKind || | ||||
1555 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||
1556 | } | ||||
1557 | }; | ||||
1558 | |||||
1559 | /// Debug location. | ||||
1560 | /// | ||||
1561 | /// A debug location in source code, used for debug info and otherwise. | ||||
1562 | class DILocation : public MDNode { | ||||
1563 | friend class LLVMContextImpl; | ||||
1564 | friend class MDNode; | ||||
1565 | |||||
1566 | DILocation(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
1567 | unsigned Column, ArrayRef<Metadata *> MDs, bool ImplicitCode); | ||||
1568 | ~DILocation() { dropAllReferences(); } | ||||
1569 | |||||
1570 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||
1571 | unsigned Column, Metadata *Scope, | ||||
1572 | Metadata *InlinedAt, bool ImplicitCode, | ||||
1573 | StorageType Storage, bool ShouldCreate = true); | ||||
1574 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||
1575 | unsigned Column, DILocalScope *Scope, | ||||
1576 | DILocation *InlinedAt, bool ImplicitCode, | ||||
1577 | StorageType Storage, bool ShouldCreate = true) { | ||||
1578 | return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), | ||||
1579 | static_cast<Metadata *>(InlinedAt), ImplicitCode, Storage, | ||||
1580 | ShouldCreate); | ||||
1581 | } | ||||
1582 | |||||
1583 | TempDILocation cloneImpl() const { | ||||
1584 | // Get the raw scope/inlinedAt since it is possible to invoke this on | ||||
1585 | // a DILocation containing temporary metadata. | ||||
1586 | return getTemporary(getContext(), getLine(), getColumn(), getRawScope(), | ||||
1587 | getRawInlinedAt(), isImplicitCode()); | ||||
1588 | } | ||||
1589 | |||||
1590 | public: | ||||
1591 | // Disallow replacing operands. | ||||
1592 | void replaceOperandWith(unsigned I, Metadata *New) = delete; | ||||
1593 | |||||
1594 | DEFINE_MDNODE_GET(DILocation, | ||||
1595 | (unsigned Line, unsigned Column, Metadata *Scope, | ||||
1596 | Metadata *InlinedAt = nullptr, bool ImplicitCode = false), | ||||
1597 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||
1598 | DEFINE_MDNODE_GET(DILocation, | ||||
1599 | (unsigned Line, unsigned Column, DILocalScope *Scope, | ||||
1600 | DILocation *InlinedAt = nullptr, | ||||
1601 | bool ImplicitCode = false), | ||||
1602 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||
1603 | |||||
1604 | /// Return a (temporary) clone of this. | ||||
1605 | TempDILocation clone() const { return cloneImpl(); } | ||||
1606 | |||||
1607 | unsigned getLine() const { return SubclassData32; } | ||||
1608 | unsigned getColumn() const { return SubclassData16; } | ||||
1609 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||
1610 | |||||
1611 | DILocation *getInlinedAt() const { | ||||
1612 | return cast_or_null<DILocation>(getRawInlinedAt()); | ||||
1613 | } | ||||
1614 | |||||
1615 | /// Check if the location corresponds to an implicit code. | ||||
1616 | /// When the ImplicitCode flag is true, it means that the Instruction | ||||
1617 | /// with this DILocation has been added by the front-end but it hasn't been | ||||
1618 | /// written explicitly by the user (e.g. cleanup stuff in C++ put on a closing | ||||
1619 | /// bracket). It's useful for code coverage to not show a counter on "empty" | ||||
1620 | /// lines. | ||||
1621 | bool isImplicitCode() const { return SubclassData1; } | ||||
1622 | void setImplicitCode(bool ImplicitCode) { SubclassData1 = ImplicitCode; } | ||||
1623 | |||||
1624 | DIFile *getFile() const { return getScope()->getFile(); } | ||||
1625 | StringRef getFilename() const { return getScope()->getFilename(); } | ||||
1626 | StringRef getDirectory() const { return getScope()->getDirectory(); } | ||||
1627 | Optional<StringRef> getSource() const { return getScope()->getSource(); } | ||||
1628 | |||||
1629 | /// Get the scope where this is inlined. | ||||
1630 | /// | ||||
1631 | /// Walk through \a getInlinedAt() and return \a getScope() from the deepest | ||||
1632 | /// location. | ||||
1633 | DILocalScope *getInlinedAtScope() const { | ||||
1634 | if (auto *IA
| ||||
1635 | return IA->getInlinedAtScope(); | ||||
1636 | return getScope(); | ||||
1637 | } | ||||
1638 | |||||
1639 | /// Get the DWARF discriminator. | ||||
1640 | /// | ||||
1641 | /// DWARF discriminators distinguish identical file locations between | ||||
1642 | /// instructions that are on different basic blocks. | ||||
1643 | /// | ||||
1644 | /// There are 3 components stored in discriminator, from lower bits: | ||||
1645 | /// | ||||
1646 | /// Base discriminator: assigned by AddDiscriminators pass to identify IRs | ||||
1647 | /// that are defined by the same source line, but | ||||
1648 | /// different basic blocks. | ||||
1649 | /// Duplication factor: assigned by optimizations that will scale down | ||||
1650 | /// the execution frequency of the original IR. | ||||
1651 | /// Copy Identifier: assigned by optimizations that clones the IR. | ||||
1652 | /// Each copy of the IR will be assigned an identifier. | ||||
1653 | /// | ||||
1654 | /// Encoding: | ||||
1655 | /// | ||||
1656 | /// The above 3 components are encoded into a 32bit unsigned integer in | ||||
1657 | /// order. If the lowest bit is 1, the current component is empty, and the | ||||
1658 | /// next component will start in the next bit. Otherwise, the current | ||||
1659 | /// component is non-empty, and its content starts in the next bit. The | ||||
1660 | /// value of each components is either 5 bit or 12 bit: if the 7th bit | ||||
1661 | /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the | ||||
1662 | /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to | ||||
1663 | /// represent the component. Thus, the number of bits used for a component | ||||
1664 | /// is either 0 (if it and all the next components are empty); 1 - if it is | ||||
1665 | /// empty; 7 - if its value is up to and including 0x1f (lsb and msb are both | ||||
1666 | /// 0); or 14, if its value is up to and including 0x1ff. Note that the last | ||||
1667 | /// component is also capped at 0x1ff, even in the case when both first | ||||
1668 | /// components are 0, and we'd technically have 29 bits available. | ||||
1669 | /// | ||||
1670 | /// For precise control over the data being encoded in the discriminator, | ||||
1671 | /// use encodeDiscriminator/decodeDiscriminator. | ||||
1672 | |||||
1673 | inline unsigned getDiscriminator() const; | ||||
1674 | |||||
1675 | // For the regular discriminator, it stands for all empty components if all | ||||
1676 | // the lowest 3 bits are non-zero and all higher 29 bits are unused(zero by | ||||
1677 | // default). Here we fully leverage the higher 29 bits for pseudo probe use. | ||||
1678 | // This is the format: | ||||
1679 | // [2:0] - 0x7 | ||||
1680 | // [31:3] - pseudo probe fields guaranteed to be non-zero as a whole | ||||
1681 | // So if the lower 3 bits is non-zero and the others has at least one | ||||
1682 | // non-zero bit, it guarantees to be a pseudo probe discriminator | ||||
1683 | inline static bool isPseudoProbeDiscriminator(unsigned Discriminator) { | ||||
1684 | return ((Discriminator & 0x7) == 0x7) && (Discriminator & 0xFFFFFFF8); | ||||
1685 | } | ||||
1686 | |||||
1687 | /// Returns a new DILocation with updated \p Discriminator. | ||||
1688 | inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const; | ||||
1689 | |||||
1690 | /// Returns a new DILocation with updated base discriminator \p BD. Only the | ||||
1691 | /// base discriminator is set in the new DILocation, the other encoded values | ||||
1692 | /// are elided. | ||||
1693 | /// If the discriminator cannot be encoded, the function returns None. | ||||
1694 | inline Optional<const DILocation *> cloneWithBaseDiscriminator(unsigned BD) const; | ||||
1695 | |||||
1696 | /// Returns the duplication factor stored in the discriminator, or 1 if no | ||||
1697 | /// duplication factor (or 0) is encoded. | ||||
1698 | inline unsigned getDuplicationFactor() const; | ||||
1699 | |||||
1700 | /// Returns the copy identifier stored in the discriminator. | ||||
1701 | inline unsigned getCopyIdentifier() const; | ||||
1702 | |||||
1703 | /// Returns the base discriminator stored in the discriminator. | ||||
1704 | inline unsigned getBaseDiscriminator() const; | ||||
1705 | |||||
1706 | /// Returns a new DILocation with duplication factor \p DF * current | ||||
1707 | /// duplication factor encoded in the discriminator. The current duplication | ||||
1708 | /// factor is as defined by getDuplicationFactor(). | ||||
1709 | /// Returns None if encoding failed. | ||||
1710 | inline Optional<const DILocation *> cloneByMultiplyingDuplicationFactor(unsigned DF) const; | ||||
1711 | |||||
1712 | /// When two instructions are combined into a single instruction we also | ||||
1713 | /// need to combine the original locations into a single location. | ||||
1714 | /// | ||||
1715 | /// When the locations are the same we can use either location. When they | ||||
1716 | /// differ, we need a third location which is distinct from either. If they | ||||
1717 | /// have the same file/line but have a different discriminator we could | ||||
1718 | /// create a location with a new discriminator. If they are from different | ||||
1719 | /// files/lines the location is ambiguous and can't be represented in a line | ||||
1720 | /// entry. In this case, if \p GenerateLocation is true, we will set the | ||||
1721 | /// merged debug location as line 0 of the nearest common scope where the two | ||||
1722 | /// locations are inlined from. | ||||
1723 | /// | ||||
1724 | /// \p GenerateLocation: Whether the merged location can be generated when | ||||
1725 | /// \p LocA and \p LocB differ. | ||||
1726 | static const DILocation *getMergedLocation(const DILocation *LocA, | ||||
1727 | const DILocation *LocB); | ||||
1728 | |||||
1729 | /// Try to combine the vector of locations passed as input in a single one. | ||||
1730 | /// This function applies getMergedLocation() repeatedly left-to-right. | ||||
1731 | /// | ||||
1732 | /// \p Locs: The locations to be merged. | ||||
1733 | static | ||||
1734 | const DILocation *getMergedLocations(ArrayRef<const DILocation *> Locs); | ||||
1735 | |||||
1736 | /// Return the masked discriminator value for an input discrimnator value D | ||||
1737 | /// (i.e. zero out the (B+1)-th and above bits for D (B is 0-base). | ||||
1738 | // Example: an input of (0x1FF, 7) returns 0xFF. | ||||
1739 | static unsigned getMaskedDiscriminator(unsigned D, unsigned B) { | ||||
1740 | return (D & getN1Bits(B)); | ||||
1741 | } | ||||
1742 | |||||
1743 | /// Return the bits used for base discriminators. | ||||
1744 | static unsigned getBaseDiscriminatorBits() { return getBaseFSBitEnd(); } | ||||
1745 | |||||
1746 | /// Returns the base discriminator for a given encoded discriminator \p D. | ||||
1747 | static unsigned | ||||
1748 | getBaseDiscriminatorFromDiscriminator(unsigned D, | ||||
1749 | bool IsFSDiscriminator = false) { | ||||
1750 | if (IsFSDiscriminator) | ||||
1751 | return getMaskedDiscriminator(D, getBaseDiscriminatorBits()); | ||||
1752 | return getUnsignedFromPrefixEncoding(D); | ||||
1753 | } | ||||
1754 | |||||
1755 | /// Raw encoding of the discriminator. APIs such as cloneWithDuplicationFactor | ||||
1756 | /// have certain special case behavior (e.g. treating empty duplication factor | ||||
1757 | /// as the value '1'). | ||||
1758 | /// This API, in conjunction with cloneWithDiscriminator, may be used to encode | ||||
1759 | /// the raw values provided. \p BD: base discriminator \p DF: duplication factor | ||||
1760 | /// \p CI: copy index | ||||
1761 | /// The return is None if the values cannot be encoded in 32 bits - for | ||||
1762 | /// example, values for BD or DF larger than 12 bits. Otherwise, the return | ||||
1763 | /// is the encoded value. | ||||
1764 | static Optional<unsigned> encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI); | ||||
1765 | |||||
1766 | /// Raw decoder for values in an encoded discriminator D. | ||||
1767 | static void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, | ||||
1768 | unsigned &CI); | ||||
1769 | |||||
1770 | /// Returns the duplication factor for a given encoded discriminator \p D, or | ||||
1771 | /// 1 if no value or 0 is encoded. | ||||
1772 | static unsigned getDuplicationFactorFromDiscriminator(unsigned D) { | ||||
1773 | if (EnableFSDiscriminator) | ||||
1774 | return 1; | ||||
1775 | D = getNextComponentInDiscriminator(D); | ||||
1776 | unsigned Ret = getUnsignedFromPrefixEncoding(D); | ||||
1777 | if (Ret == 0) | ||||
1778 | return 1; | ||||
1779 | return Ret; | ||||
1780 | } | ||||
1781 | |||||
1782 | /// Returns the copy identifier for a given encoded discriminator \p D. | ||||
1783 | static unsigned getCopyIdentifierFromDiscriminator(unsigned D) { | ||||
1784 | return getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator( | ||||
1785 | getNextComponentInDiscriminator(D))); | ||||
1786 | } | ||||
1787 | |||||
1788 | |||||
1789 | Metadata *getRawScope() const { return getOperand(0); } | ||||
1790 | Metadata *getRawInlinedAt() const { | ||||
1791 | if (getNumOperands() == 2) | ||||
1792 | return getOperand(1); | ||||
1793 | return nullptr; | ||||
1794 | } | ||||
1795 | |||||
1796 | static bool classof(const Metadata *MD) { | ||||
1797 | return MD->getMetadataID() == DILocationKind; | ||||
1798 | } | ||||
1799 | }; | ||||
1800 | |||||
1801 | /// Subprogram description. | ||||
1802 | class DISubprogram : public DILocalScope { | ||||
1803 | friend class LLVMContextImpl; | ||||
1804 | friend class MDNode; | ||||
1805 | |||||
1806 | unsigned Line; | ||||
1807 | unsigned ScopeLine; | ||||
1808 | unsigned VirtualIndex; | ||||
1809 | |||||
1810 | /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue | ||||
1811 | /// of method overrides from secondary bases by this amount. It may be | ||||
1812 | /// negative. | ||||
1813 | int ThisAdjustment; | ||||
1814 | |||||
1815 | public: | ||||
1816 | /// Debug info subprogram flags. | ||||
1817 | enum DISPFlags : uint32_t { | ||||
1818 | #define HANDLE_DISP_FLAG(ID, NAME) SPFlag##NAME = ID, | ||||
1819 | #define DISP_FLAG_LARGEST_NEEDED | ||||
1820 | #include "llvm/IR/DebugInfoFlags.def" | ||||
1821 | SPFlagNonvirtual = SPFlagZero, | ||||
1822 | SPFlagVirtuality = SPFlagVirtual | SPFlagPureVirtual, | ||||
1823 | LLVM_MARK_AS_BITMASK_ENUM(SPFlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = SPFlagLargest | ||||
1824 | }; | ||||
1825 | |||||
1826 | static DISPFlags getFlag(StringRef Flag); | ||||
1827 | static StringRef getFlagString(DISPFlags Flag); | ||||
1828 | |||||
1829 | /// Split up a flags bitfield for easier printing. | ||||
1830 | /// | ||||
1831 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||
1832 | /// any remaining (unrecognized) bits. | ||||
1833 | static DISPFlags splitFlags(DISPFlags Flags, | ||||
1834 | SmallVectorImpl<DISPFlags> &SplitFlags); | ||||
1835 | |||||
1836 | // Helper for converting old bitfields to new flags word. | ||||
1837 | static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, | ||||
1838 | bool IsOptimized, | ||||
1839 | unsigned Virtuality = SPFlagNonvirtual, | ||||
1840 | bool IsMainSubprogram = false) { | ||||
1841 | // We're assuming virtuality is the low-order field. | ||||
1842 | static_assert( | ||||
1843 | int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) && | ||||
1844 | int(SPFlagPureVirtual) == int(dwarf::DW_VIRTUALITY_pure_virtual), | ||||
1845 | "Virtuality constant mismatch"); | ||||
1846 | return static_cast<DISPFlags>( | ||||
1847 | (Virtuality & SPFlagVirtuality) | | ||||
1848 | (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) | | ||||
1849 | (IsDefinition ? SPFlagDefinition : SPFlagZero) | | ||||
1850 | (IsOptimized ? SPFlagOptimized : SPFlagZero) | | ||||
1851 | (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero)); | ||||
1852 | } | ||||
1853 | |||||
1854 | private: | ||||
1855 | DIFlags Flags; | ||||
1856 | DISPFlags SPFlags; | ||||
1857 | |||||
1858 | DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
1859 | unsigned ScopeLine, unsigned VirtualIndex, int ThisAdjustment, | ||||
1860 | DIFlags Flags, DISPFlags SPFlags, ArrayRef<Metadata *> Ops) | ||||
1861 | : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, | ||||
1862 | Ops), | ||||
1863 | Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex), | ||||
1864 | ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) { | ||||
1865 | static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range"); | ||||
1866 | } | ||||
1867 | ~DISubprogram() = default; | ||||
1868 | |||||
1869 | static DISubprogram * | ||||
1870 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||
1871 | StringRef LinkageName, DIFile *File, unsigned Line, | ||||
1872 | DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, | ||||
1873 | unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, | ||||
1874 | DISPFlags SPFlags, DICompileUnit *Unit, | ||||
1875 | DITemplateParameterArray TemplateParams, DISubprogram *Declaration, | ||||
1876 | DINodeArray RetainedNodes, DITypeArray ThrownTypes, | ||||
1877 | StorageType Storage, bool ShouldCreate = true) { | ||||
1878 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
1879 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||
1880 | ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, | ||||
1881 | Flags, SPFlags, Unit, TemplateParams.get(), Declaration, | ||||
1882 | RetainedNodes.get(), ThrownTypes.get(), Storage, | ||||
1883 | ShouldCreate); | ||||
1884 | } | ||||
1885 | static DISubprogram *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
1886 | MDString *Name, MDString *LinkageName, | ||||
1887 | Metadata *File, unsigned Line, Metadata *Type, | ||||
1888 | unsigned ScopeLine, Metadata *ContainingType, | ||||
1889 | unsigned VirtualIndex, int ThisAdjustment, | ||||
1890 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||
1891 | Metadata *TemplateParams, Metadata *Declaration, | ||||
1892 | Metadata *RetainedNodes, Metadata *ThrownTypes, | ||||
1893 | StorageType Storage, bool ShouldCreate = true); | ||||
1894 | |||||
1895 | TempDISubprogram cloneImpl() const { | ||||
1896 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||
1897 | getFile(), getLine(), getType(), getScopeLine(), | ||||
1898 | getContainingType(), getVirtualIndex(), | ||||
1899 | getThisAdjustment(), getFlags(), getSPFlags(), | ||||
1900 | getUnit(), getTemplateParams(), getDeclaration(), | ||||
1901 | getRetainedNodes(), getThrownTypes()); | ||||
1902 | } | ||||
1903 | |||||
1904 | public: | ||||
1905 | DEFINE_MDNODE_GET( | ||||
1906 | DISubprogram, | ||||
1907 | (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, | ||||
1908 | unsigned Line, DISubroutineType *Type, unsigned ScopeLine, | ||||
1909 | DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||
1910 | DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, | ||||
1911 | DITemplateParameterArray TemplateParams = nullptr, | ||||
1912 | DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, | ||||
1913 | DITypeArray ThrownTypes = nullptr), | ||||
1914 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||
1915 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||
1916 | Declaration, RetainedNodes, ThrownTypes)) | ||||
1917 | |||||
1918 | DEFINE_MDNODE_GET( | ||||
1919 | DISubprogram, | ||||
1920 | (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, | ||||
1921 | unsigned Line, Metadata *Type, unsigned ScopeLine, | ||||
1922 | Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||
1923 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||
1924 | Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, | ||||
1925 | Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr), | ||||
1926 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||
1927 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||
1928 | Declaration, RetainedNodes, ThrownTypes)) | ||||
1929 | |||||
1930 | TempDISubprogram clone() const { return cloneImpl(); } | ||||
1931 | |||||
1932 | /// Returns a new temporary DISubprogram with updated Flags | ||||
1933 | TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { | ||||
1934 | auto NewSP = clone(); | ||||
1935 | NewSP->Flags = NewFlags; | ||||
1936 | return NewSP; | ||||
1937 | } | ||||
1938 | |||||
1939 | public: | ||||
1940 | unsigned getLine() const { return Line; } | ||||
1941 | unsigned getVirtuality() const { return getSPFlags() & SPFlagVirtuality; } | ||||
1942 | unsigned getVirtualIndex() const { return VirtualIndex; } | ||||
1943 | int getThisAdjustment() const { return ThisAdjustment; } | ||||
1944 | unsigned getScopeLine() const { return ScopeLine; } | ||||
1945 | void setScopeLine(unsigned L) { assert(isDistinct())((void)0); ScopeLine = L; } | ||||
1946 | DIFlags getFlags() const { return Flags; } | ||||
1947 | DISPFlags getSPFlags() const { return SPFlags; } | ||||
1948 | bool isLocalToUnit() const { return getSPFlags() & SPFlagLocalToUnit; } | ||||
1949 | bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } | ||||
1950 | bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } | ||||
1951 | bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } | ||||
1952 | |||||
1953 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
1954 | bool isPrivate() const { | ||||
1955 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||
1956 | } | ||||
1957 | bool isProtected() const { | ||||
1958 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||
1959 | } | ||||
1960 | bool isPublic() const { | ||||
1961 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||
1962 | } | ||||
1963 | bool isExplicit() const { return getFlags() & FlagExplicit; } | ||||
1964 | bool isPrototyped() const { return getFlags() & FlagPrototyped; } | ||||
1965 | bool areAllCallsDescribed() const { | ||||
1966 | return getFlags() & FlagAllCallsDescribed; | ||||
1967 | } | ||||
1968 | bool isPure() const { return getSPFlags() & SPFlagPure; } | ||||
1969 | bool isElemental() const { return getSPFlags() & SPFlagElemental; } | ||||
1970 | bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } | ||||
1971 | bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } | ||||
1972 | |||||
1973 | /// Check if this is deleted member function. | ||||
1974 | /// | ||||
1975 | /// Return true if this subprogram is a C++11 special | ||||
1976 | /// member function declared deleted. | ||||
1977 | bool isDeleted() const { return getSPFlags() & SPFlagDeleted; } | ||||
1978 | |||||
1979 | /// Check if this is reference-qualified. | ||||
1980 | /// | ||||
1981 | /// Return true if this subprogram is a C++11 reference-qualified non-static | ||||
1982 | /// member function (void foo() &). | ||||
1983 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||
1984 | |||||
1985 | /// Check if this is rvalue-reference-qualified. | ||||
1986 | /// | ||||
1987 | /// Return true if this subprogram is a C++11 rvalue-reference-qualified | ||||
1988 | /// non-static member function (void foo() &&). | ||||
1989 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||
1990 | |||||
1991 | /// Check if this is marked as noreturn. | ||||
1992 | /// | ||||
1993 | /// Return true if this subprogram is C++11 noreturn or C11 _Noreturn | ||||
1994 | bool isNoReturn() const { return getFlags() & FlagNoReturn; } | ||||
1995 | |||||
1996 | // Check if this routine is a compiler-generated thunk. | ||||
1997 | // | ||||
1998 | // Returns true if this subprogram is a thunk generated by the compiler. | ||||
1999 | bool isThunk() const { return getFlags() & FlagThunk; } | ||||
2000 | |||||
2001 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2002 | |||||
2003 | StringRef getName() const { return getStringOperand(2); } | ||||
2004 | StringRef getLinkageName() const { return getStringOperand(3); } | ||||
2005 | /// Only used by clients of CloneFunction, and only right after the cloning. | ||||
2006 | void replaceLinkageName(MDString *LN) { replaceOperandWith(3, LN); } | ||||
2007 | |||||
2008 | DISubroutineType *getType() const { | ||||
2009 | return cast_or_null<DISubroutineType>(getRawType()); | ||||
2010 | } | ||||
2011 | DIType *getContainingType() const { | ||||
2012 | return cast_or_null<DIType>(getRawContainingType()); | ||||
2013 | } | ||||
2014 | |||||
2015 | DICompileUnit *getUnit() const { | ||||
2016 | return cast_or_null<DICompileUnit>(getRawUnit()); | ||||
2017 | } | ||||
2018 | void replaceUnit(DICompileUnit *CU) { replaceOperandWith(5, CU); } | ||||
2019 | DITemplateParameterArray getTemplateParams() const { | ||||
2020 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||
2021 | } | ||||
2022 | DISubprogram *getDeclaration() const { | ||||
2023 | return cast_or_null<DISubprogram>(getRawDeclaration()); | ||||
2024 | } | ||||
2025 | DINodeArray getRetainedNodes() const { | ||||
2026 | return cast_or_null<MDTuple>(getRawRetainedNodes()); | ||||
2027 | } | ||||
2028 | DITypeArray getThrownTypes() const { | ||||
2029 | return cast_or_null<MDTuple>(getRawThrownTypes()); | ||||
2030 | } | ||||
2031 | |||||
2032 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2033 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
2034 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(3); } | ||||
2035 | Metadata *getRawType() const { return getOperand(4); } | ||||
2036 | Metadata *getRawUnit() const { return getOperand(5); } | ||||
2037 | Metadata *getRawDeclaration() const { return getOperand(6); } | ||||
2038 | Metadata *getRawRetainedNodes() const { return getOperand(7); } | ||||
2039 | Metadata *getRawContainingType() const { | ||||
2040 | return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr; | ||||
2041 | } | ||||
2042 | Metadata *getRawTemplateParams() const { | ||||
2043 | return getNumOperands() > 9 ? getOperandAs<Metadata>(9) : nullptr; | ||||
2044 | } | ||||
2045 | Metadata *getRawThrownTypes() const { | ||||
2046 | return getNumOperands() > 10 ? getOperandAs<Metadata>(10) : nullptr; | ||||
2047 | } | ||||
2048 | |||||
2049 | void replaceRawLinkageName(MDString *LinkageName) { | ||||
2050 | replaceOperandWith(3, LinkageName); | ||||
2051 | } | ||||
2052 | |||||
2053 | /// Check if this subprogram describes the given function. | ||||
2054 | /// | ||||
2055 | /// FIXME: Should this be looking through bitcasts? | ||||
2056 | bool describes(const Function *F) const; | ||||
2057 | |||||
2058 | static bool classof(const Metadata *MD) { | ||||
2059 | return MD->getMetadataID() == DISubprogramKind; | ||||
2060 | } | ||||
2061 | }; | ||||
2062 | |||||
2063 | class DILexicalBlockBase : public DILocalScope { | ||||
2064 | protected: | ||||
2065 | DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, | ||||
2066 | ArrayRef<Metadata *> Ops) | ||||
2067 | : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} | ||||
2068 | ~DILexicalBlockBase() = default; | ||||
2069 | |||||
2070 | public: | ||||
2071 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||
2072 | |||||
2073 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2074 | |||||
2075 | static bool classof(const Metadata *MD) { | ||||
2076 | return MD->getMetadataID() == DILexicalBlockKind || | ||||
2077 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||
2078 | } | ||||
2079 | }; | ||||
2080 | |||||
2081 | class DILexicalBlock : public DILexicalBlockBase { | ||||
2082 | friend class LLVMContextImpl; | ||||
2083 | friend class MDNode; | ||||
2084 | |||||
2085 | unsigned Line; | ||||
2086 | uint16_t Column; | ||||
2087 | |||||
2088 | DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
2089 | unsigned Column, ArrayRef<Metadata *> Ops) | ||||
2090 | : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), | ||||
2091 | Column(Column) { | ||||
2092 | assert(Column < (1u << 16) && "Expected 16-bit column")((void)0); | ||||
2093 | } | ||||
2094 | ~DILexicalBlock() = default; | ||||
2095 | |||||
2096 | static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||
2097 | DIFile *File, unsigned Line, unsigned Column, | ||||
2098 | StorageType Storage, | ||||
2099 | bool ShouldCreate = true) { | ||||
2100 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||
2101 | static_cast<Metadata *>(File), Line, Column, Storage, | ||||
2102 | ShouldCreate); | ||||
2103 | } | ||||
2104 | |||||
2105 | static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
2106 | Metadata *File, unsigned Line, unsigned Column, | ||||
2107 | StorageType Storage, bool ShouldCreate = true); | ||||
2108 | |||||
2109 | TempDILexicalBlock cloneImpl() const { | ||||
2110 | return getTemporary(getContext(), getScope(), getFile(), getLine(), | ||||
2111 | getColumn()); | ||||
2112 | } | ||||
2113 | |||||
2114 | public: | ||||
2115 | DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File, | ||||
2116 | unsigned Line, unsigned Column), | ||||
2117 | (Scope, File, Line, Column)) | ||||
2118 | DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File, | ||||
2119 | unsigned Line, unsigned Column), | ||||
2120 | (Scope, File, Line, Column)) | ||||
2121 | |||||
2122 | TempDILexicalBlock clone() const { return cloneImpl(); } | ||||
2123 | |||||
2124 | unsigned getLine() const { return Line; } | ||||
2125 | unsigned getColumn() const { return Column; } | ||||
2126 | |||||
2127 | static bool classof(const Metadata *MD) { | ||||
2128 | return MD->getMetadataID() == DILexicalBlockKind; | ||||
2129 | } | ||||
2130 | }; | ||||
2131 | |||||
2132 | class DILexicalBlockFile : public DILexicalBlockBase { | ||||
2133 | friend class LLVMContextImpl; | ||||
2134 | friend class MDNode; | ||||
2135 | |||||
2136 | unsigned Discriminator; | ||||
2137 | |||||
2138 | DILexicalBlockFile(LLVMContext &C, StorageType Storage, | ||||
2139 | unsigned Discriminator, ArrayRef<Metadata *> Ops) | ||||
2140 | : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), | ||||
2141 | Discriminator(Discriminator) {} | ||||
2142 | ~DILexicalBlockFile() = default; | ||||
2143 | |||||
2144 | static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||
2145 | DIFile *File, unsigned Discriminator, | ||||
2146 | StorageType Storage, | ||||
2147 | bool ShouldCreate = true) { | ||||
2148 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||
2149 | static_cast<Metadata *>(File), Discriminator, Storage, | ||||
2150 | ShouldCreate); | ||||
2151 | } | ||||
2152 | |||||
2153 | static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
2154 | Metadata *File, unsigned Discriminator, | ||||
2155 | StorageType Storage, | ||||
2156 | bool ShouldCreate = true); | ||||
2157 | |||||
2158 | TempDILexicalBlockFile cloneImpl() const { | ||||
2159 | return getTemporary(getContext(), getScope(), getFile(), | ||||
2160 | getDiscriminator()); | ||||
2161 | } | ||||
2162 | |||||
2163 | public: | ||||
2164 | DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File, | ||||
2165 | unsigned Discriminator), | ||||
2166 | (Scope, File, Discriminator)) | ||||
2167 | DEFINE_MDNODE_GET(DILexicalBlockFile, | ||||
2168 | (Metadata * Scope, Metadata *File, unsigned Discriminator), | ||||
2169 | (Scope, File, Discriminator)) | ||||
2170 | |||||
2171 | TempDILexicalBlockFile clone() const { return cloneImpl(); } | ||||
2172 | unsigned getDiscriminator() const { return Discriminator; } | ||||
2173 | |||||
2174 | static bool classof(const Metadata *MD) { | ||||
2175 | return MD->getMetadataID() == DILexicalBlockFileKind; | ||||
2176 | } | ||||
2177 | }; | ||||
2178 | |||||
2179 | unsigned DILocation::getDiscriminator() const { | ||||
2180 | if (auto *F = dyn_cast<DILexicalBlockFile>(getScope())) | ||||
2181 | return F->getDiscriminator(); | ||||
2182 | return 0; | ||||
2183 | } | ||||
2184 | |||||
2185 | const DILocation * | ||||
2186 | DILocation::cloneWithDiscriminator(unsigned Discriminator) const { | ||||
2187 | DIScope *Scope = getScope(); | ||||
2188 | // Skip all parent DILexicalBlockFile that already have a discriminator | ||||
2189 | // assigned. We do not want to have nested DILexicalBlockFiles that have | ||||
2190 | // mutliple discriminators because only the leaf DILexicalBlockFile's | ||||
2191 | // dominator will be used. | ||||
2192 | for (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope); | ||||
2193 | LBF && LBF->getDiscriminator() != 0; | ||||
2194 | LBF = dyn_cast<DILexicalBlockFile>(Scope)) | ||||
2195 | Scope = LBF->getScope(); | ||||
2196 | DILexicalBlockFile *NewScope = | ||||
2197 | DILexicalBlockFile::get(getContext(), Scope, getFile(), Discriminator); | ||||
2198 | return DILocation::get(getContext(), getLine(), getColumn(), NewScope, | ||||
2199 | getInlinedAt()); | ||||
2200 | } | ||||
2201 | |||||
2202 | unsigned DILocation::getBaseDiscriminator() const { | ||||
2203 | return getBaseDiscriminatorFromDiscriminator(getDiscriminator(), | ||||
2204 | EnableFSDiscriminator); | ||||
2205 | } | ||||
2206 | |||||
2207 | unsigned DILocation::getDuplicationFactor() const { | ||||
2208 | return getDuplicationFactorFromDiscriminator(getDiscriminator()); | ||||
2209 | } | ||||
2210 | |||||
2211 | unsigned DILocation::getCopyIdentifier() const { | ||||
2212 | return getCopyIdentifierFromDiscriminator(getDiscriminator()); | ||||
2213 | } | ||||
2214 | |||||
2215 | Optional<const DILocation *> DILocation::cloneWithBaseDiscriminator(unsigned D) const { | ||||
2216 | unsigned BD, DF, CI; | ||||
2217 | |||||
2218 | if (EnableFSDiscriminator) { | ||||
2219 | BD = getBaseDiscriminator(); | ||||
2220 | if (D == BD) | ||||
2221 | return this; | ||||
2222 | return cloneWithDiscriminator(D); | ||||
2223 | } | ||||
2224 | |||||
2225 | decodeDiscriminator(getDiscriminator(), BD, DF, CI); | ||||
2226 | if (D == BD) | ||||
2227 | return this; | ||||
2228 | if (Optional<unsigned> Encoded = encodeDiscriminator(D, DF, CI)) | ||||
2229 | return cloneWithDiscriminator(*Encoded); | ||||
2230 | return None; | ||||
2231 | } | ||||
2232 | |||||
2233 | Optional<const DILocation *> DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const { | ||||
2234 | assert(!EnableFSDiscriminator && "FSDiscriminator should not call this.")((void)0); | ||||
2235 | |||||
2236 | DF *= getDuplicationFactor(); | ||||
2237 | if (DF <= 1) | ||||
2238 | return this; | ||||
2239 | |||||
2240 | unsigned BD = getBaseDiscriminator(); | ||||
2241 | unsigned CI = getCopyIdentifier(); | ||||
2242 | if (Optional<unsigned> D = encodeDiscriminator(BD, DF, CI)) | ||||
2243 | return cloneWithDiscriminator(*D); | ||||
2244 | return None; | ||||
2245 | } | ||||
2246 | |||||
2247 | class DINamespace : public DIScope { | ||||
2248 | friend class LLVMContextImpl; | ||||
2249 | friend class MDNode; | ||||
2250 | |||||
2251 | unsigned ExportSymbols : 1; | ||||
2252 | |||||
2253 | DINamespace(LLVMContext &Context, StorageType Storage, bool ExportSymbols, | ||||
2254 | ArrayRef<Metadata *> Ops) | ||||
2255 | : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, | ||||
2256 | Ops), | ||||
2257 | ExportSymbols(ExportSymbols) {} | ||||
2258 | ~DINamespace() = default; | ||||
2259 | |||||
2260 | static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
2261 | StringRef Name, bool ExportSymbols, | ||||
2262 | StorageType Storage, bool ShouldCreate = true) { | ||||
2263 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
2264 | ExportSymbols, Storage, ShouldCreate); | ||||
2265 | } | ||||
2266 | static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
2267 | MDString *Name, bool ExportSymbols, | ||||
2268 | StorageType Storage, bool ShouldCreate = true); | ||||
2269 | |||||
2270 | TempDINamespace cloneImpl() const { | ||||
2271 | return getTemporary(getContext(), getScope(), getName(), | ||||
2272 | getExportSymbols()); | ||||
2273 | } | ||||
2274 | |||||
2275 | public: | ||||
2276 | DEFINE_MDNODE_GET(DINamespace, | ||||
2277 | (DIScope *Scope, StringRef Name, bool ExportSymbols), | ||||
2278 | (Scope, Name, ExportSymbols)) | ||||
2279 | DEFINE_MDNODE_GET(DINamespace, | ||||
2280 | (Metadata *Scope, MDString *Name, bool ExportSymbols), | ||||
2281 | (Scope, Name, ExportSymbols)) | ||||
2282 | |||||
2283 | TempDINamespace clone() const { return cloneImpl(); } | ||||
2284 | |||||
2285 | bool getExportSymbols() const { return ExportSymbols; } | ||||
2286 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2287 | StringRef getName() const { return getStringOperand(2); } | ||||
2288 | |||||
2289 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2290 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
2291 | |||||
2292 | static bool classof(const Metadata *MD) { | ||||
2293 | return MD->getMetadataID() == DINamespaceKind; | ||||
2294 | } | ||||
2295 | }; | ||||
2296 | |||||
2297 | /// Represents a module in the programming language, for example, a Clang | ||||
2298 | /// module, or a Fortran module. | ||||
2299 | class DIModule : public DIScope { | ||||
2300 | friend class LLVMContextImpl; | ||||
2301 | friend class MDNode; | ||||
2302 | unsigned LineNo; | ||||
2303 | bool IsDecl; | ||||
2304 | |||||
2305 | DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||
2306 | bool IsDecl, ArrayRef<Metadata *> Ops) | ||||
2307 | : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops), | ||||
2308 | LineNo(LineNo), IsDecl(IsDecl) {} | ||||
2309 | ~DIModule() = default; | ||||
2310 | |||||
2311 | static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope, | ||||
2312 | StringRef Name, StringRef ConfigurationMacros, | ||||
2313 | StringRef IncludePath, StringRef APINotesFile, | ||||
2314 | unsigned LineNo, bool IsDecl, StorageType Storage, | ||||
2315 | bool ShouldCreate = true) { | ||||
2316 | return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name), | ||||
2317 | getCanonicalMDString(Context, ConfigurationMacros), | ||||
2318 | getCanonicalMDString(Context, IncludePath), | ||||
2319 | getCanonicalMDString(Context, APINotesFile), LineNo, IsDecl, | ||||
2320 | Storage, ShouldCreate); | ||||
2321 | } | ||||
2322 | static DIModule *getImpl(LLVMContext &Context, Metadata *File, | ||||
2323 | Metadata *Scope, MDString *Name, | ||||
2324 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||
2325 | MDString *APINotesFile, unsigned LineNo, bool IsDecl, | ||||
2326 | StorageType Storage, bool ShouldCreate = true); | ||||
2327 | |||||
2328 | TempDIModule cloneImpl() const { | ||||
2329 | return getTemporary(getContext(), getFile(), getScope(), getName(), | ||||
2330 | getConfigurationMacros(), getIncludePath(), | ||||
2331 | getAPINotesFile(), getLineNo(), getIsDecl()); | ||||
2332 | } | ||||
2333 | |||||
2334 | public: | ||||
2335 | DEFINE_MDNODE_GET(DIModule, | ||||
2336 | (DIFile * File, DIScope *Scope, StringRef Name, | ||||
2337 | StringRef ConfigurationMacros, StringRef IncludePath, | ||||
2338 | StringRef APINotesFile, unsigned LineNo, | ||||
2339 | bool IsDecl = false), | ||||
2340 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||
2341 | APINotesFile, LineNo, IsDecl)) | ||||
2342 | DEFINE_MDNODE_GET(DIModule, | ||||
2343 | (Metadata * File, Metadata *Scope, MDString *Name, | ||||
2344 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||
2345 | MDString *APINotesFile, unsigned LineNo, | ||||
2346 | bool IsDecl = false), | ||||
2347 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||
2348 | APINotesFile, LineNo, IsDecl)) | ||||
2349 | |||||
2350 | TempDIModule clone() const { return cloneImpl(); } | ||||
2351 | |||||
2352 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2353 | StringRef getName() const { return getStringOperand(2); } | ||||
2354 | StringRef getConfigurationMacros() const { return getStringOperand(3); } | ||||
2355 | StringRef getIncludePath() const { return getStringOperand(4); } | ||||
2356 | StringRef getAPINotesFile() const { return getStringOperand(5); } | ||||
2357 | unsigned getLineNo() const { return LineNo; } | ||||
2358 | bool getIsDecl() const { return IsDecl; } | ||||
2359 | |||||
2360 | Metadata *getRawScope() const { return getOperand(1); } | ||||
2361 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
2362 | MDString *getRawConfigurationMacros() const { | ||||
2363 | return getOperandAs<MDString>(3); | ||||
2364 | } | ||||
2365 | MDString *getRawIncludePath() const { return getOperandAs<MDString>(4); } | ||||
2366 | MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(5); } | ||||
2367 | |||||
2368 | static bool classof(const Metadata *MD) { | ||||
2369 | return MD->getMetadataID() == DIModuleKind; | ||||
2370 | } | ||||
2371 | }; | ||||
2372 | |||||
2373 | /// Base class for template parameters. | ||||
2374 | class DITemplateParameter : public DINode { | ||||
2375 | protected: | ||||
2376 | bool IsDefault; | ||||
2377 | |||||
2378 | DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, | ||||
2379 | unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops) | ||||
2380 | : DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {} | ||||
2381 | ~DITemplateParameter() = default; | ||||
2382 | |||||
2383 | public: | ||||
2384 | StringRef getName() const { return getStringOperand(0); } | ||||
2385 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
2386 | |||||
2387 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
2388 | Metadata *getRawType() const { return getOperand(1); } | ||||
2389 | bool isDefault() const { return IsDefault; } | ||||
2390 | |||||
2391 | static bool classof(const Metadata *MD) { | ||||
2392 | return MD->getMetadataID() == DITemplateTypeParameterKind || | ||||
2393 | MD->getMetadataID() == DITemplateValueParameterKind; | ||||
2394 | } | ||||
2395 | }; | ||||
2396 | |||||
2397 | class DITemplateTypeParameter : public DITemplateParameter { | ||||
2398 | friend class LLVMContextImpl; | ||||
2399 | friend class MDNode; | ||||
2400 | |||||
2401 | DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, | ||||
2402 | bool IsDefault, ArrayRef<Metadata *> Ops) | ||||
2403 | : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, | ||||
2404 | dwarf::DW_TAG_template_type_parameter, IsDefault, | ||||
2405 | Ops) {} | ||||
2406 | ~DITemplateTypeParameter() = default; | ||||
2407 | |||||
2408 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, | ||||
2409 | DIType *Type, bool IsDefault, | ||||
2410 | StorageType Storage, | ||||
2411 | bool ShouldCreate = true) { | ||||
2412 | return getImpl(Context, getCanonicalMDString(Context, Name), Type, | ||||
2413 | IsDefault, Storage, ShouldCreate); | ||||
2414 | } | ||||
2415 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, | ||||
2416 | Metadata *Type, bool IsDefault, | ||||
2417 | StorageType Storage, | ||||
2418 | bool ShouldCreate = true); | ||||
2419 | |||||
2420 | TempDITemplateTypeParameter cloneImpl() const { | ||||
2421 | return getTemporary(getContext(), getName(), getType(), isDefault()); | ||||
2422 | } | ||||
2423 | |||||
2424 | public: | ||||
2425 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||
2426 | (StringRef Name, DIType *Type, bool IsDefault), | ||||
2427 | (Name, Type, IsDefault)) | ||||
2428 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||
2429 | (MDString *Name, Metadata *Type, bool IsDefault), | ||||
2430 | (Name, Type, IsDefault)) | ||||
2431 | |||||
2432 | TempDITemplateTypeParameter clone() const { return cloneImpl(); } | ||||
2433 | |||||
2434 | static bool classof(const Metadata *MD) { | ||||
2435 | return MD->getMetadataID() == DITemplateTypeParameterKind; | ||||
2436 | } | ||||
2437 | }; | ||||
2438 | |||||
2439 | class DITemplateValueParameter : public DITemplateParameter { | ||||
2440 | friend class LLVMContextImpl; | ||||
2441 | friend class MDNode; | ||||
2442 | |||||
2443 | DITemplateValueParameter(LLVMContext &Context, StorageType Storage, | ||||
2444 | unsigned Tag, bool IsDefault, | ||||
2445 | ArrayRef<Metadata *> Ops) | ||||
2446 | : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, | ||||
2447 | IsDefault, Ops) {} | ||||
2448 | ~DITemplateValueParameter() = default; | ||||
2449 | |||||
2450 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||
2451 | StringRef Name, DIType *Type, | ||||
2452 | bool IsDefault, Metadata *Value, | ||||
2453 | StorageType Storage, | ||||
2454 | bool ShouldCreate = true) { | ||||
2455 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, | ||||
2456 | IsDefault, Value, Storage, ShouldCreate); | ||||
2457 | } | ||||
2458 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||
2459 | MDString *Name, Metadata *Type, | ||||
2460 | bool IsDefault, Metadata *Value, | ||||
2461 | StorageType Storage, | ||||
2462 | bool ShouldCreate = true); | ||||
2463 | |||||
2464 | TempDITemplateValueParameter cloneImpl() const { | ||||
2465 | return getTemporary(getContext(), getTag(), getName(), getType(), | ||||
2466 | isDefault(), getValue()); | ||||
2467 | } | ||||
2468 | |||||
2469 | public: | ||||
2470 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||
2471 | (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault, | ||||
2472 | Metadata *Value), | ||||
2473 | (Tag, Name, Type, IsDefault, Value)) | ||||
2474 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||
2475 | (unsigned Tag, MDString *Name, Metadata *Type, | ||||
2476 | bool IsDefault, Metadata *Value), | ||||
2477 | (Tag, Name, Type, IsDefault, Value)) | ||||
2478 | |||||
2479 | TempDITemplateValueParameter clone() const { return cloneImpl(); } | ||||
2480 | |||||
2481 | Metadata *getValue() const { return getOperand(2); } | ||||
2482 | |||||
2483 | static bool classof(const Metadata *MD) { | ||||
2484 | return MD->getMetadataID() == DITemplateValueParameterKind; | ||||
2485 | } | ||||
2486 | }; | ||||
2487 | |||||
2488 | /// Base class for variables. | ||||
2489 | class DIVariable : public DINode { | ||||
2490 | unsigned Line; | ||||
2491 | uint32_t AlignInBits; | ||||
2492 | |||||
2493 | protected: | ||||
2494 | DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line, | ||||
2495 | ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0) | ||||
2496 | : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line), | ||||
2497 | AlignInBits(AlignInBits) {} | ||||
2498 | ~DIVariable() = default; | ||||
2499 | |||||
2500 | public: | ||||
2501 | unsigned getLine() const { return Line; } | ||||
2502 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
2503 | StringRef getName() const { return getStringOperand(1); } | ||||
2504 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
2505 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
2506 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||
2507 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||
2508 | /// Determines the size of the variable's type. | ||||
2509 | Optional<uint64_t> getSizeInBits() const; | ||||
2510 | |||||
2511 | /// Return the signedness of this variable's type, or None if this type is | ||||
2512 | /// neither signed nor unsigned. | ||||
2513 | Optional<DIBasicType::Signedness> getSignedness() const { | ||||
2514 | if (auto *BT = dyn_cast<DIBasicType>(getType())) | ||||
2515 | return BT->getSignedness(); | ||||
2516 | return None; | ||||
2517 | } | ||||
2518 | |||||
2519 | StringRef getFilename() const { | ||||
2520 | if (auto *F = getFile()) | ||||
2521 | return F->getFilename(); | ||||
2522 | return ""; | ||||
2523 | } | ||||
2524 | |||||
2525 | StringRef getDirectory() const { | ||||
2526 | if (auto *F = getFile()) | ||||
2527 | return F->getDirectory(); | ||||
2528 | return ""; | ||||
2529 | } | ||||
2530 | |||||
2531 | Optional<StringRef> getSource() const { | ||||
2532 | if (auto *F = getFile()) | ||||
2533 | return F->getSource(); | ||||
2534 | return None; | ||||
2535 | } | ||||
2536 | |||||
2537 | Metadata *getRawScope() const { return getOperand(0); } | ||||
2538 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||
2539 | Metadata *getRawFile() const { return getOperand(2); } | ||||
2540 | Metadata *getRawType() const { return getOperand(3); } | ||||
2541 | |||||
2542 | static bool classof(const Metadata *MD) { | ||||
2543 | return MD->getMetadataID() == DILocalVariableKind || | ||||
2544 | MD->getMetadataID() == DIGlobalVariableKind; | ||||
2545 | } | ||||
2546 | }; | ||||
2547 | |||||
2548 | /// DWARF expression. | ||||
2549 | /// | ||||
2550 | /// This is (almost) a DWARF expression that modifies the location of a | ||||
2551 | /// variable, or the location of a single piece of a variable, or (when using | ||||
2552 | /// DW_OP_stack_value) is the constant variable value. | ||||
2553 | /// | ||||
2554 | /// TODO: Co-allocate the expression elements. | ||||
2555 | /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary | ||||
2556 | /// storage types. | ||||
2557 | class DIExpression : public MDNode { | ||||
2558 | friend class LLVMContextImpl; | ||||
2559 | friend class MDNode; | ||||
2560 | |||||
2561 | std::vector<uint64_t> Elements; | ||||
2562 | |||||
2563 | DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) | ||||
2564 | : MDNode(C, DIExpressionKind, Storage, None), | ||||
2565 | Elements(Elements.begin(), Elements.end()) {} | ||||
2566 | ~DIExpression() = default; | ||||
2567 | |||||
2568 | static DIExpression *getImpl(LLVMContext &Context, | ||||
2569 | ArrayRef<uint64_t> Elements, StorageType Storage, | ||||
2570 | bool ShouldCreate = true); | ||||
2571 | |||||
2572 | TempDIExpression cloneImpl() const { | ||||
2573 | return getTemporary(getContext(), getElements()); | ||||
2574 | } | ||||
2575 | |||||
2576 | public: | ||||
2577 | DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements)) | ||||
2578 | |||||
2579 | TempDIExpression clone() const { return cloneImpl(); } | ||||
2580 | |||||
2581 | ArrayRef<uint64_t> getElements() const { return Elements; } | ||||
2582 | |||||
2583 | unsigned getNumElements() const { return Elements.size(); } | ||||
2584 | |||||
2585 | uint64_t getElement(unsigned I) const { | ||||
2586 | assert(I < Elements.size() && "Index out of range")((void)0); | ||||
2587 | return Elements[I]; | ||||
2588 | } | ||||
2589 | |||||
2590 | enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; | ||||
2591 | /// Determine whether this represents a constant value, if so | ||||
2592 | // return it's sign information. | ||||
2593 | llvm::Optional<SignedOrUnsignedConstant> isConstant() const; | ||||
2594 | |||||
2595 | /// Return the number of unique location operands referred to (via | ||||
2596 | /// DW_OP_LLVM_arg) in this expression; this is not necessarily the number of | ||||
2597 | /// instances of DW_OP_LLVM_arg within the expression. | ||||
2598 | /// For example, for the expression: | ||||
2599 | /// (DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_plus, | ||||
2600 | /// DW_OP_LLVM_arg 0, DW_OP_mul) | ||||
2601 | /// This function would return 2, as there are two unique location operands | ||||
2602 | /// (0 and 1). | ||||
2603 | uint64_t getNumLocationOperands() const; | ||||
2604 | |||||
2605 | using element_iterator = ArrayRef<uint64_t>::iterator; | ||||
2606 | |||||
2607 | element_iterator elements_begin() const { return getElements().begin(); } | ||||
2608 | element_iterator elements_end() const { return getElements().end(); } | ||||
2609 | |||||
2610 | /// A lightweight wrapper around an expression operand. | ||||
2611 | /// | ||||
2612 | /// TODO: Store arguments directly and change \a DIExpression to store a | ||||
2613 | /// range of these. | ||||
2614 | class ExprOperand { | ||||
2615 | const uint64_t *Op = nullptr; | ||||
2616 | |||||
2617 | public: | ||||
2618 | ExprOperand() = default; | ||||
2619 | explicit ExprOperand(const uint64_t *Op) : Op(Op) {} | ||||
2620 | |||||
2621 | const uint64_t *get() const { return Op; } | ||||
2622 | |||||
2623 | /// Get the operand code. | ||||
2624 | uint64_t getOp() const { return *Op; } | ||||
2625 | |||||
2626 | /// Get an argument to the operand. | ||||
2627 | /// | ||||
2628 | /// Never returns the operand itself. | ||||
2629 | uint64_t getArg(unsigned I) const { return Op[I + 1]; } | ||||
2630 | |||||
2631 | unsigned getNumArgs() const { return getSize() - 1; } | ||||
2632 | |||||
2633 | /// Return the size of the operand. | ||||
2634 | /// | ||||
2635 | /// Return the number of elements in the operand (1 + args). | ||||
2636 | unsigned getSize() const; | ||||
2637 | |||||
2638 | /// Append the elements of this operand to \p V. | ||||
2639 | void appendToVector(SmallVectorImpl<uint64_t> &V) const { | ||||
2640 | V.append(get(), get() + getSize()); | ||||
2641 | } | ||||
2642 | }; | ||||
2643 | |||||
2644 | /// An iterator for expression operands. | ||||
2645 | class expr_op_iterator { | ||||
2646 | ExprOperand Op; | ||||
2647 | |||||
2648 | public: | ||||
2649 | using iterator_category = std::input_iterator_tag; | ||||
2650 | using value_type = ExprOperand; | ||||
2651 | using difference_type = std::ptrdiff_t; | ||||
2652 | using pointer = value_type *; | ||||
2653 | using reference = value_type &; | ||||
2654 | |||||
2655 | expr_op_iterator() = default; | ||||
2656 | explicit expr_op_iterator(element_iterator I) : Op(I) {} | ||||
2657 | |||||
2658 | element_iterator getBase() const { return Op.get(); } | ||||
2659 | const ExprOperand &operator*() const { return Op; } | ||||
2660 | const ExprOperand *operator->() const { return &Op; } | ||||
2661 | |||||
2662 | expr_op_iterator &operator++() { | ||||
2663 | increment(); | ||||
2664 | return *this; | ||||
2665 | } | ||||
2666 | expr_op_iterator operator++(int) { | ||||
2667 | expr_op_iterator T(*this); | ||||
2668 | increment(); | ||||
2669 | return T; | ||||
2670 | } | ||||
2671 | |||||
2672 | /// Get the next iterator. | ||||
2673 | /// | ||||
2674 | /// \a std::next() doesn't work because this is technically an | ||||
2675 | /// input_iterator, but it's a perfectly valid operation. This is an | ||||
2676 | /// accessor to provide the same functionality. | ||||
2677 | expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } | ||||
2678 | |||||
2679 | bool operator==(const expr_op_iterator &X) const { | ||||
2680 | return getBase() == X.getBase(); | ||||
2681 | } | ||||
2682 | bool operator!=(const expr_op_iterator &X) const { | ||||
2683 | return getBase() != X.getBase(); | ||||
2684 | } | ||||
2685 | |||||
2686 | private: | ||||
2687 | void increment() { Op = ExprOperand(getBase() + Op.getSize()); } | ||||
2688 | }; | ||||
2689 | |||||
2690 | /// Visit the elements via ExprOperand wrappers. | ||||
2691 | /// | ||||
2692 | /// These range iterators visit elements through \a ExprOperand wrappers. | ||||
2693 | /// This is not guaranteed to be a valid range unless \a isValid() gives \c | ||||
2694 | /// true. | ||||
2695 | /// | ||||
2696 | /// \pre \a isValid() gives \c true. | ||||
2697 | /// @{ | ||||
2698 | expr_op_iterator expr_op_begin() const { | ||||
2699 | return expr_op_iterator(elements_begin()); | ||||
2700 | } | ||||
2701 | expr_op_iterator expr_op_end() const { | ||||
2702 | return expr_op_iterator(elements_end()); | ||||
2703 | } | ||||
2704 | iterator_range<expr_op_iterator> expr_ops() const { | ||||
2705 | return {expr_op_begin(), expr_op_end()}; | ||||
2706 | } | ||||
2707 | /// @} | ||||
2708 | |||||
2709 | bool isValid() const; | ||||
2710 | |||||
2711 | static bool classof(const Metadata *MD) { | ||||
2712 | return MD->getMetadataID() == DIExpressionKind; | ||||
2713 | } | ||||
2714 | |||||
2715 | /// Return whether the first element a DW_OP_deref. | ||||
2716 | bool startsWithDeref() const { | ||||
2717 | return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref; | ||||
2718 | } | ||||
2719 | |||||
2720 | /// Holds the characteristics of one fragment of a larger variable. | ||||
2721 | struct FragmentInfo { | ||||
2722 | uint64_t SizeInBits; | ||||
2723 | uint64_t OffsetInBits; | ||||
2724 | }; | ||||
2725 | |||||
2726 | /// Retrieve the details of this fragment expression. | ||||
2727 | static Optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start, | ||||
2728 | expr_op_iterator End); | ||||
2729 | |||||
2730 | /// Retrieve the details of this fragment expression. | ||||
2731 | Optional<FragmentInfo> getFragmentInfo() const { | ||||
2732 | return getFragmentInfo(expr_op_begin(), expr_op_end()); | ||||
2733 | } | ||||
2734 | |||||
2735 | /// Return whether this is a piece of an aggregate variable. | ||||
2736 | bool isFragment() const { return getFragmentInfo().hasValue(); } | ||||
2737 | |||||
2738 | /// Return whether this is an implicit location description. | ||||
2739 | bool isImplicit() const; | ||||
2740 | |||||
2741 | /// Return whether the location is computed on the expression stack, meaning | ||||
2742 | /// it cannot be a simple register location. | ||||
2743 | bool isComplex() const; | ||||
2744 | |||||
2745 | /// Append \p Ops with operations to apply the \p Offset. | ||||
2746 | static void appendOffset(SmallVectorImpl<uint64_t> &Ops, int64_t Offset); | ||||
2747 | |||||
2748 | /// If this is a constant offset, extract it. If there is no expression, | ||||
2749 | /// return true with an offset of zero. | ||||
2750 | bool extractIfOffset(int64_t &Offset) const; | ||||
2751 | |||||
2752 | /// Returns true iff this DIExpression contains at least one instance of | ||||
2753 | /// `DW_OP_LLVM_arg, n` for all n in [0, N). | ||||
2754 | bool hasAllLocationOps(unsigned N) const; | ||||
2755 | |||||
2756 | /// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF | ||||
2757 | /// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address | ||||
2758 | /// Space>. | ||||
2759 | static const DIExpression *extractAddressClass(const DIExpression *Expr, | ||||
2760 | unsigned &AddrClass); | ||||
2761 | |||||
2762 | /// Used for DIExpression::prepend. | ||||
2763 | enum PrependOps : uint8_t { | ||||
2764 | ApplyOffset = 0, | ||||
2765 | DerefBefore = 1 << 0, | ||||
2766 | DerefAfter = 1 << 1, | ||||
2767 | StackValue = 1 << 2, | ||||
2768 | EntryValue = 1 << 3 | ||||
2769 | }; | ||||
2770 | |||||
2771 | /// Prepend \p DIExpr with a deref and offset operation and optionally turn it | ||||
2772 | /// into a stack value or/and an entry value. | ||||
2773 | static DIExpression *prepend(const DIExpression *Expr, uint8_t Flags, | ||||
2774 | int64_t Offset = 0); | ||||
2775 | |||||
2776 | /// Prepend \p DIExpr with the given opcodes and optionally turn it into a | ||||
2777 | /// stack value. | ||||
2778 | static DIExpression *prependOpcodes(const DIExpression *Expr, | ||||
2779 | SmallVectorImpl<uint64_t> &Ops, | ||||
2780 | bool StackValue = false, | ||||
2781 | bool EntryValue = false); | ||||
2782 | |||||
2783 | /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the | ||||
2784 | /// returned expression is a stack value only if \p DIExpr is a stack value. | ||||
2785 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||
2786 | /// the same fragment. | ||||
2787 | static DIExpression *append(const DIExpression *Expr, ArrayRef<uint64_t> Ops); | ||||
2788 | |||||
2789 | /// Convert \p DIExpr into a stack value if it isn't one already by appending | ||||
2790 | /// DW_OP_deref if needed, and appending \p Ops to the resulting expression. | ||||
2791 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||
2792 | /// the same fragment. | ||||
2793 | static DIExpression *appendToStack(const DIExpression *Expr, | ||||
2794 | ArrayRef<uint64_t> Ops); | ||||
2795 | |||||
2796 | /// Create a copy of \p Expr by appending the given list of \p Ops to each | ||||
2797 | /// instance of the operand `DW_OP_LLVM_arg, \p ArgNo`. This is used to | ||||
2798 | /// modify a specific location used by \p Expr, such as when salvaging that | ||||
2799 | /// location. | ||||
2800 | static DIExpression *appendOpsToArg(const DIExpression *Expr, | ||||
2801 | ArrayRef<uint64_t> Ops, unsigned ArgNo, | ||||
2802 | bool StackValue = false); | ||||
2803 | |||||
2804 | /// Create a copy of \p Expr with each instance of | ||||
2805 | /// `DW_OP_LLVM_arg, \p OldArg` replaced with `DW_OP_LLVM_arg, \p NewArg`, | ||||
2806 | /// and each instance of `DW_OP_LLVM_arg, Arg` with `DW_OP_LLVM_arg, Arg - 1` | ||||
2807 | /// for all Arg > \p OldArg. | ||||
2808 | /// This is used when replacing one of the operands of a debug value list | ||||
2809 | /// with another operand in the same list and deleting the old operand. | ||||
2810 | static DIExpression *replaceArg(const DIExpression *Expr, uint64_t OldArg, | ||||
2811 | uint64_t NewArg); | ||||
2812 | |||||
2813 | /// Create a DIExpression to describe one part of an aggregate variable that | ||||
2814 | /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation | ||||
2815 | /// will be appended to the elements of \c Expr. If \c Expr already contains | ||||
2816 | /// a \c DW_OP_LLVM_fragment \c OffsetInBits is interpreted as an offset | ||||
2817 | /// into the existing fragment. | ||||
2818 | /// | ||||
2819 | /// \param OffsetInBits Offset of the piece in bits. | ||||
2820 | /// \param SizeInBits Size of the piece in bits. | ||||
2821 | /// \return Creating a fragment expression may fail if \c Expr | ||||
2822 | /// contains arithmetic operations that would be truncated. | ||||
2823 | static Optional<DIExpression *> | ||||
2824 | createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, | ||||
2825 | unsigned SizeInBits); | ||||
2826 | |||||
2827 | /// Determine the relative position of the fragments passed in. | ||||
2828 | /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, | ||||
2829 | /// 1 if this is entirely after Other. | ||||
2830 | static int fragmentCmp(const FragmentInfo &A, const FragmentInfo &B) { | ||||
2831 | uint64_t l1 = A.OffsetInBits; | ||||
2832 | uint64_t l2 = B.OffsetInBits; | ||||
2833 | uint64_t r1 = l1 + A.SizeInBits; | ||||
2834 | uint64_t r2 = l2 + B.SizeInBits; | ||||
2835 | if (r1 <= l2) | ||||
2836 | return -1; | ||||
2837 | else if (r2 <= l1) | ||||
2838 | return 1; | ||||
2839 | else | ||||
2840 | return 0; | ||||
2841 | } | ||||
2842 | |||||
2843 | using ExtOps = std::array<uint64_t, 6>; | ||||
2844 | |||||
2845 | /// Returns the ops for a zero- or sign-extension in a DIExpression. | ||||
2846 | static ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed); | ||||
2847 | |||||
2848 | /// Append a zero- or sign-extension to \p Expr. Converts the expression to a | ||||
2849 | /// stack value if it isn't one already. | ||||
2850 | static DIExpression *appendExt(const DIExpression *Expr, unsigned FromSize, | ||||
2851 | unsigned ToSize, bool Signed); | ||||
2852 | |||||
2853 | /// Check if fragments overlap between a pair of FragmentInfos. | ||||
2854 | static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B) { | ||||
2855 | return fragmentCmp(A, B) == 0; | ||||
2856 | } | ||||
2857 | |||||
2858 | /// Determine the relative position of the fragments described by this | ||||
2859 | /// DIExpression and \p Other. Calls static fragmentCmp implementation. | ||||
2860 | int fragmentCmp(const DIExpression *Other) const { | ||||
2861 | auto Fragment1 = *getFragmentInfo(); | ||||
2862 | auto Fragment2 = *Other->getFragmentInfo(); | ||||
2863 | return fragmentCmp(Fragment1, Fragment2); | ||||
2864 | } | ||||
2865 | |||||
2866 | /// Check if fragments overlap between this DIExpression and \p Other. | ||||
2867 | bool fragmentsOverlap(const DIExpression *Other) const { | ||||
2868 | if (!isFragment() || !Other->isFragment()) | ||||
2869 | return true; | ||||
2870 | return fragmentCmp(Other) == 0; | ||||
2871 | } | ||||
2872 | |||||
2873 | /// Check if the expression consists of exactly one entry value operand. | ||||
2874 | /// (This is the only configuration of entry values that is supported.) | ||||
2875 | bool isEntryValue() const { | ||||
2876 | return getNumElements() > 0 && | ||||
2877 | getElement(0) == dwarf::DW_OP_LLVM_entry_value; | ||||
2878 | } | ||||
2879 | }; | ||||
2880 | |||||
2881 | inline bool operator==(const DIExpression::FragmentInfo &A, | ||||
2882 | const DIExpression::FragmentInfo &B) { | ||||
2883 | return std::tie(A.SizeInBits, A.OffsetInBits) == | ||||
2884 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||
2885 | } | ||||
2886 | |||||
2887 | inline bool operator<(const DIExpression::FragmentInfo &A, | ||||
2888 | const DIExpression::FragmentInfo &B) { | ||||
2889 | return std::tie(A.SizeInBits, A.OffsetInBits) < | ||||
2890 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||
2891 | } | ||||
2892 | |||||
2893 | template <> struct DenseMapInfo<DIExpression::FragmentInfo> { | ||||
2894 | using FragInfo = DIExpression::FragmentInfo; | ||||
2895 | static const uint64_t MaxVal = std::numeric_limits<uint64_t>::max(); | ||||
2896 | |||||
2897 | static inline FragInfo getEmptyKey() { return {MaxVal, MaxVal}; } | ||||
2898 | |||||
2899 | static inline FragInfo getTombstoneKey() { return {MaxVal - 1, MaxVal - 1}; } | ||||
2900 | |||||
2901 | static unsigned getHashValue(const FragInfo &Frag) { | ||||
2902 | return (Frag.SizeInBits & 0xffff) << 16 | (Frag.OffsetInBits & 0xffff); | ||||
2903 | } | ||||
2904 | |||||
2905 | static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } | ||||
2906 | }; | ||||
2907 | |||||
2908 | /// Global variables. | ||||
2909 | /// | ||||
2910 | /// TODO: Remove DisplayName. It's always equal to Name. | ||||
2911 | class DIGlobalVariable : public DIVariable { | ||||
2912 | friend class LLVMContextImpl; | ||||
2913 | friend class MDNode; | ||||
2914 | |||||
2915 | bool IsLocalToUnit; | ||||
2916 | bool IsDefinition; | ||||
2917 | |||||
2918 | DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
2919 | bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, | ||||
2920 | ArrayRef<Metadata *> Ops) | ||||
2921 | : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), | ||||
2922 | IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} | ||||
2923 | ~DIGlobalVariable() = default; | ||||
2924 | |||||
2925 | static DIGlobalVariable * | ||||
2926 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||
2927 | StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, | ||||
2928 | bool IsLocalToUnit, bool IsDefinition, | ||||
2929 | DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, | ||||
2930 | uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true) { | ||||
2931 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
2932 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||
2933 | IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, | ||||
2934 | cast_or_null<Metadata>(TemplateParams), AlignInBits, Storage, | ||||
2935 | ShouldCreate); | ||||
2936 | } | ||||
2937 | static DIGlobalVariable * | ||||
2938 | getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||
2939 | MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, | ||||
2940 | bool IsLocalToUnit, bool IsDefinition, | ||||
2941 | Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, | ||||
2942 | uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true); | ||||
2943 | |||||
2944 | TempDIGlobalVariable cloneImpl() const { | ||||
2945 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||
2946 | getFile(), getLine(), getType(), isLocalToUnit(), | ||||
2947 | isDefinition(), getStaticDataMemberDeclaration(), | ||||
2948 | getTemplateParams(), getAlignInBits()); | ||||
2949 | } | ||||
2950 | |||||
2951 | public: | ||||
2952 | DEFINE_MDNODE_GET(DIGlobalVariable, | ||||
2953 | (DIScope * Scope, StringRef Name, StringRef LinkageName, | ||||
2954 | DIFile *File, unsigned Line, DIType *Type, | ||||
2955 | bool IsLocalToUnit, bool IsDefinition, | ||||
2956 | DIDerivedType *StaticDataMemberDeclaration, | ||||
2957 | MDTuple *TemplateParams, uint32_t AlignInBits), | ||||
2958 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, | ||||
2959 | IsDefinition, StaticDataMemberDeclaration, TemplateParams, | ||||
2960 | AlignInBits)) | ||||
2961 | DEFINE_MDNODE_GET(DIGlobalVariable, | ||||
2962 | (Metadata * Scope, MDString *Name, MDString *LinkageName, | ||||
2963 | Metadata *File, unsigned Line, Metadata *Type, | ||||
2964 | bool IsLocalToUnit, bool IsDefinition, | ||||
2965 | Metadata *StaticDataMemberDeclaration, | ||||
2966 | Metadata *TemplateParams, uint32_t AlignInBits), | ||||
2967 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, | ||||
2968 | IsDefinition, StaticDataMemberDeclaration, TemplateParams, | ||||
2969 | AlignInBits)) | ||||
2970 | |||||
2971 | TempDIGlobalVariable clone() const { return cloneImpl(); } | ||||
2972 | |||||
2973 | bool isLocalToUnit() const { return IsLocalToUnit; } | ||||
2974 | bool isDefinition() const { return IsDefinition; } | ||||
2975 | StringRef getDisplayName() const { return getStringOperand(4); } | ||||
2976 | StringRef getLinkageName() const { return getStringOperand(5); } | ||||
2977 | DIDerivedType *getStaticDataMemberDeclaration() const { | ||||
2978 | return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration()); | ||||
2979 | } | ||||
2980 | |||||
2981 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } | ||||
2982 | Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } | ||||
2983 | Metadata *getRawTemplateParams() const { return getOperand(7); } | ||||
2984 | MDTuple *getTemplateParams() const { return getOperandAs<MDTuple>(7); } | ||||
2985 | |||||
2986 | static bool classof(const Metadata *MD) { | ||||
2987 | return MD->getMetadataID() == DIGlobalVariableKind; | ||||
2988 | } | ||||
2989 | }; | ||||
2990 | |||||
2991 | class DICommonBlock : public DIScope { | ||||
2992 | unsigned LineNo; | ||||
2993 | |||||
2994 | friend class LLVMContextImpl; | ||||
2995 | friend class MDNode; | ||||
2996 | |||||
2997 | DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||
2998 | ArrayRef<Metadata *> Ops) | ||||
2999 | : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block, | ||||
3000 | Ops), LineNo(LineNo) {} | ||||
3001 | |||||
3002 | static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
3003 | DIGlobalVariable *Decl, StringRef Name, | ||||
3004 | DIFile *File, unsigned LineNo, | ||||
3005 | StorageType Storage, | ||||
3006 | bool ShouldCreate = true) { | ||||
3007 | return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), | ||||
3008 | File, LineNo, Storage, ShouldCreate); | ||||
3009 | } | ||||
3010 | static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
3011 | Metadata *Decl, MDString *Name, Metadata *File, | ||||
3012 | unsigned LineNo, | ||||
3013 | StorageType Storage, bool ShouldCreate = true); | ||||
3014 | |||||
3015 | TempDICommonBlock cloneImpl() const { | ||||
3016 | return getTemporary(getContext(), getScope(), getDecl(), getName(), | ||||
3017 | getFile(), getLineNo()); | ||||
3018 | } | ||||
3019 | |||||
3020 | public: | ||||
3021 | DEFINE_MDNODE_GET(DICommonBlock, | ||||
3022 | (DIScope *Scope, DIGlobalVariable *Decl, StringRef Name, | ||||
3023 | DIFile *File, unsigned LineNo), | ||||
3024 | (Scope, Decl, Name, File, LineNo)) | ||||
3025 | DEFINE_MDNODE_GET(DICommonBlock, | ||||
3026 | (Metadata *Scope, Metadata *Decl, MDString *Name, | ||||
3027 | Metadata *File, unsigned LineNo), | ||||
3028 | (Scope, Decl, Name, File, LineNo)) | ||||
3029 | |||||
3030 | TempDICommonBlock clone() const { return cloneImpl(); } | ||||
3031 | |||||
3032 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
3033 | DIGlobalVariable *getDecl() const { | ||||
3034 | return cast_or_null<DIGlobalVariable>(getRawDecl()); | ||||
3035 | } | ||||
3036 | StringRef getName() const { return getStringOperand(2); } | ||||
3037 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3038 | unsigned getLineNo() const { return LineNo; } | ||||
3039 | |||||
3040 | Metadata *getRawScope() const { return getOperand(0); } | ||||
3041 | Metadata *getRawDecl() const { return getOperand(1); } | ||||
3042 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
3043 | Metadata *getRawFile() const { return getOperand(3); } | ||||
3044 | |||||
3045 | static bool classof(const Metadata *MD) { | ||||
3046 | return MD->getMetadataID() == DICommonBlockKind; | ||||
3047 | } | ||||
3048 | }; | ||||
3049 | |||||
3050 | /// Local variable. | ||||
3051 | /// | ||||
3052 | /// TODO: Split up flags. | ||||
3053 | class DILocalVariable : public DIVariable { | ||||
3054 | friend class LLVMContextImpl; | ||||
3055 | friend class MDNode; | ||||
3056 | |||||
3057 | unsigned Arg : 16; | ||||
3058 | DIFlags Flags; | ||||
3059 | |||||
3060 | DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
3061 | unsigned Arg, DIFlags Flags, uint32_t AlignInBits, | ||||
3062 | ArrayRef<Metadata *> Ops) | ||||
3063 | : DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBits), | ||||
3064 | Arg(Arg), Flags(Flags) { | ||||
3065 | assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range")((void)0); | ||||
3066 | } | ||||
3067 | ~DILocalVariable() = default; | ||||
3068 | |||||
3069 | static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
3070 | StringRef Name, DIFile *File, unsigned Line, | ||||
3071 | DIType *Type, unsigned Arg, DIFlags Flags, | ||||
3072 | uint32_t AlignInBits, StorageType Storage, | ||||
3073 | bool ShouldCreate = true) { | ||||
3074 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||
3075 | Line, Type, Arg, Flags, AlignInBits, Storage, ShouldCreate); | ||||
3076 | } | ||||
3077 | static DILocalVariable *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
3078 | MDString *Name, Metadata *File, unsigned Line, | ||||
3079 | Metadata *Type, unsigned Arg, DIFlags Flags, | ||||
3080 | uint32_t AlignInBits, StorageType Storage, | ||||
3081 | bool ShouldCreate = true); | ||||
3082 | |||||
3083 | TempDILocalVariable cloneImpl() const { | ||||
3084 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||
3085 | getLine(), getType(), getArg(), getFlags(), | ||||
3086 | getAlignInBits()); | ||||
3087 | } | ||||
3088 | |||||
3089 | public: | ||||
3090 | DEFINE_MDNODE_GET(DILocalVariable, | ||||
3091 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||
3092 | unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags, | ||||
3093 | uint32_t AlignInBits), | ||||
3094 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits)) | ||||
3095 | DEFINE_MDNODE_GET(DILocalVariable, | ||||
3096 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||
3097 | unsigned Line, Metadata *Type, unsigned Arg, | ||||
3098 | DIFlags Flags, uint32_t AlignInBits), | ||||
3099 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits)) | ||||
3100 | |||||
3101 | TempDILocalVariable clone() const { return cloneImpl(); } | ||||
3102 | |||||
3103 | /// Get the local scope for this variable. | ||||
3104 | /// | ||||
3105 | /// Variables must be defined in a local scope. | ||||
3106 | DILocalScope *getScope() const { | ||||
3107 | return cast<DILocalScope>(DIVariable::getScope()); | ||||
3108 | } | ||||
3109 | |||||
3110 | bool isParameter() const { return Arg; } | ||||
3111 | unsigned getArg() const { return Arg; } | ||||
3112 | DIFlags getFlags() const { return Flags; } | ||||
3113 | |||||
3114 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
3115 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||
3116 | |||||
3117 | /// Check that a location is valid for this variable. | ||||
3118 | /// | ||||
3119 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||
3120 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||
3121 | /// to a \a DbgInfoIntrinsic.) | ||||
3122 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||
3123 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||
3124 | } | ||||
3125 | |||||
3126 | static bool classof(const Metadata *MD) { | ||||
3127 | return MD->getMetadataID() == DILocalVariableKind; | ||||
3128 | } | ||||
3129 | }; | ||||
3130 | |||||
3131 | /// Label. | ||||
3132 | /// | ||||
3133 | class DILabel : public DINode { | ||||
3134 | friend class LLVMContextImpl; | ||||
3135 | friend class MDNode; | ||||
3136 | |||||
3137 | unsigned Line; | ||||
3138 | |||||
3139 | DILabel(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
3140 | ArrayRef<Metadata *> Ops) | ||||
3141 | : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {} | ||||
3142 | ~DILabel() = default; | ||||
3143 | |||||
3144 | static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
3145 | StringRef Name, DIFile *File, unsigned Line, | ||||
3146 | StorageType Storage, | ||||
3147 | bool ShouldCreate = true) { | ||||
3148 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||
3149 | Line, Storage, ShouldCreate); | ||||
3150 | } | ||||
3151 | static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
3152 | MDString *Name, Metadata *File, unsigned Line, | ||||
3153 | StorageType Storage, | ||||
3154 | bool ShouldCreate = true); | ||||
3155 | |||||
3156 | TempDILabel cloneImpl() const { | ||||
3157 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||
3158 | getLine()); | ||||
3159 | } | ||||
3160 | |||||
3161 | public: | ||||
3162 | DEFINE_MDNODE_GET(DILabel, | ||||
3163 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||
3164 | unsigned Line), | ||||
3165 | (Scope, Name, File, Line)) | ||||
3166 | DEFINE_MDNODE_GET(DILabel, | ||||
3167 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||
3168 | unsigned Line), | ||||
3169 | (Scope, Name, File, Line)) | ||||
3170 | |||||
3171 | TempDILabel clone() const { return cloneImpl(); } | ||||
3172 | |||||
3173 | /// Get the local scope for this label. | ||||
3174 | /// | ||||
3175 | /// Labels must be defined in a local scope. | ||||
3176 | DILocalScope *getScope() const { | ||||
3177 | return cast_or_null<DILocalScope>(getRawScope()); | ||||
3178 | } | ||||
3179 | unsigned getLine() const { return Line; } | ||||
3180 | StringRef getName() const { return getStringOperand(1); } | ||||
3181 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3182 | |||||
3183 | Metadata *getRawScope() const { return getOperand(0); } | ||||
3184 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||
3185 | Metadata *getRawFile() const { return getOperand(2); } | ||||
3186 | |||||
3187 | /// Check that a location is valid for this label. | ||||
3188 | /// | ||||
3189 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||
3190 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||
3191 | /// to a \a DbgInfoIntrinsic.) | ||||
3192 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||
3193 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||
3194 | } | ||||
3195 | |||||
3196 | static bool classof(const Metadata *MD) { | ||||
3197 | return MD->getMetadataID() == DILabelKind; | ||||
3198 | } | ||||
3199 | }; | ||||
3200 | |||||
3201 | class DIObjCProperty : public DINode { | ||||
3202 | friend class LLVMContextImpl; | ||||
3203 | friend class MDNode; | ||||
3204 | |||||
3205 | unsigned Line; | ||||
3206 | unsigned Attributes; | ||||
3207 | |||||
3208 | DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
3209 | unsigned Attributes, ArrayRef<Metadata *> Ops) | ||||
3210 | : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, | ||||
3211 | Ops), | ||||
3212 | Line(Line), Attributes(Attributes) {} | ||||
3213 | ~DIObjCProperty() = default; | ||||
3214 | |||||
3215 | static DIObjCProperty * | ||||
3216 | getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, | ||||
3217 | StringRef GetterName, StringRef SetterName, unsigned Attributes, | ||||
3218 | DIType *Type, StorageType Storage, bool ShouldCreate = true) { | ||||
3219 | return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, | ||||
3220 | getCanonicalMDString(Context, GetterName), | ||||
3221 | getCanonicalMDString(Context, SetterName), Attributes, Type, | ||||
3222 | Storage, ShouldCreate); | ||||
3223 | } | ||||
3224 | static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, | ||||
3225 | Metadata *File, unsigned Line, | ||||
3226 | MDString *GetterName, MDString *SetterName, | ||||
3227 | unsigned Attributes, Metadata *Type, | ||||
3228 | StorageType Storage, bool ShouldCreate = true); | ||||
3229 | |||||
3230 | TempDIObjCProperty cloneImpl() const { | ||||
3231 | return getTemporary(getContext(), getName(), getFile(), getLine(), | ||||
3232 | getGetterName(), getSetterName(), getAttributes(), | ||||
3233 | getType()); | ||||
3234 | } | ||||
3235 | |||||
3236 | public: | ||||
3237 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||
3238 | (StringRef Name, DIFile *File, unsigned Line, | ||||
3239 | StringRef GetterName, StringRef SetterName, | ||||
3240 | unsigned Attributes, DIType *Type), | ||||
3241 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||
3242 | Type)) | ||||
3243 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||
3244 | (MDString * Name, Metadata *File, unsigned Line, | ||||
3245 | MDString *GetterName, MDString *SetterName, | ||||
3246 | unsigned Attributes, Metadata *Type), | ||||
3247 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||
3248 | Type)) | ||||
3249 | |||||
3250 | TempDIObjCProperty clone() const { return cloneImpl(); } | ||||
3251 | |||||
3252 | unsigned getLine() const { return Line; } | ||||
3253 | unsigned getAttributes() const { return Attributes; } | ||||
3254 | StringRef getName() const { return getStringOperand(0); } | ||||
3255 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3256 | StringRef getGetterName() const { return getStringOperand(2); } | ||||
3257 | StringRef getSetterName() const { return getStringOperand(3); } | ||||
3258 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
3259 | |||||
3260 | StringRef getFilename() const { | ||||
3261 | if (auto *F = getFile()) | ||||
3262 | return F->getFilename(); | ||||
3263 | return ""; | ||||
3264 | } | ||||
3265 | |||||
3266 | StringRef getDirectory() const { | ||||
3267 | if (auto *F = getFile()) | ||||
3268 | return F->getDirectory(); | ||||
3269 | return ""; | ||||
3270 | } | ||||
3271 | |||||
3272 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
3273 | Metadata *getRawFile() const { return getOperand(1); } | ||||
3274 | MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } | ||||
3275 | MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } | ||||
3276 | Metadata *getRawType() const { return getOperand(4); } | ||||
3277 | |||||
3278 | static bool classof(const Metadata *MD) { | ||||
3279 | return MD->getMetadataID() == DIObjCPropertyKind; | ||||
3280 | } | ||||
3281 | }; | ||||
3282 | |||||
3283 | /// An imported module (C++ using directive or similar). | ||||
3284 | class DIImportedEntity : public DINode { | ||||
3285 | friend class LLVMContextImpl; | ||||
3286 | friend class MDNode; | ||||
3287 | |||||
3288 | unsigned Line; | ||||
3289 | |||||
3290 | DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
3291 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||
3292 | : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} | ||||
3293 | ~DIImportedEntity() = default; | ||||
3294 | |||||
3295 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||
3296 | DIScope *Scope, DINode *Entity, DIFile *File, | ||||
3297 | unsigned Line, StringRef Name, | ||||
3298 | StorageType Storage, | ||||
3299 | bool ShouldCreate = true) { | ||||
3300 | return getImpl(Context, Tag, Scope, Entity, File, Line, | ||||
3301 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); | ||||
3302 | } | ||||
3303 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||
3304 | Metadata *Scope, Metadata *Entity, | ||||
3305 | Metadata *File, unsigned Line, | ||||
3306 | MDString *Name, StorageType Storage, | ||||
3307 | bool ShouldCreate = true); | ||||
3308 | |||||
3309 | TempDIImportedEntity cloneImpl() const { | ||||
3310 | return getTemporary(getContext(), getTag(), getScope(), getEntity(), | ||||
3311 | getFile(), getLine(), getName()); | ||||
3312 | } | ||||
3313 | |||||
3314 | public: | ||||
3315 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||
3316 | (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File, | ||||
3317 | unsigned Line, StringRef Name = ""), | ||||
3318 | (Tag, Scope, Entity, File, Line, Name)) | ||||
3319 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||
3320 | (unsigned Tag, Metadata *Scope, Metadata *Entity, | ||||
3321 | Metadata *File, unsigned Line, MDString *Name), | ||||
3322 | (Tag, Scope, Entity, File, Line, Name)) | ||||
3323 | |||||
3324 | TempDIImportedEntity clone() const { return cloneImpl(); } | ||||
3325 | |||||
3326 | unsigned getLine() const { return Line; } | ||||
3327 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
3328 | DINode *getEntity() const { return cast_or_null<DINode>(getRawEntity()); } | ||||
3329 | StringRef getName() const { return getStringOperand(2); } | ||||
3330 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3331 | |||||
3332 | Metadata *getRawScope() const { return getOperand(0); } | ||||
3333 | Metadata *getRawEntity() const { return getOperand(1); } | ||||
3334 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
3335 | Metadata *getRawFile() const { return getOperand(3); } | ||||
3336 | |||||
3337 | static bool classof(const Metadata *MD) { | ||||
3338 | return MD->getMetadataID() == DIImportedEntityKind; | ||||
3339 | } | ||||
3340 | }; | ||||
3341 | |||||
3342 | /// A pair of DIGlobalVariable and DIExpression. | ||||
3343 | class DIGlobalVariableExpression : public MDNode { | ||||
3344 | friend class LLVMContextImpl; | ||||
3345 | friend class MDNode; | ||||
3346 | |||||
3347 | DIGlobalVariableExpression(LLVMContext &C, StorageType Storage, | ||||
3348 | ArrayRef<Metadata *> Ops) | ||||
3349 | : MDNode(C, DIGlobalVariableExpressionKind, Storage, Ops) {} | ||||
3350 | ~DIGlobalVariableExpression() = default; | ||||
3351 | |||||
3352 | static DIGlobalVariableExpression * | ||||
3353 | getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Expression, | ||||
3354 | StorageType Storage, bool ShouldCreate = true); | ||||
3355 | |||||
3356 | TempDIGlobalVariableExpression cloneImpl() const { | ||||
3357 | return getTemporary(getContext(), getVariable(), getExpression()); | ||||
3358 | } | ||||
3359 | |||||
3360 | public: | ||||
3361 | DEFINE_MDNODE_GET(DIGlobalVariableExpression, | ||||
3362 | (Metadata * Variable, Metadata *Expression), | ||||
3363 | (Variable, Expression)) | ||||
3364 | |||||
3365 | TempDIGlobalVariableExpression clone() const { return cloneImpl(); } | ||||
3366 | |||||
3367 | Metadata *getRawVariable() const { return getOperand(0); } | ||||
3368 | |||||
3369 | DIGlobalVariable *getVariable() const { | ||||
3370 | return cast_or_null<DIGlobalVariable>(getRawVariable()); | ||||
3371 | } | ||||
3372 | |||||
3373 | Metadata *getRawExpression() const { return getOperand(1); } | ||||
3374 | |||||
3375 | DIExpression *getExpression() const { | ||||
3376 | return cast<DIExpression>(getRawExpression()); | ||||
3377 | } | ||||
3378 | |||||
3379 | static bool classof(const Metadata *MD) { | ||||
3380 | return MD->getMetadataID() == DIGlobalVariableExpressionKind; | ||||
3381 | } | ||||
3382 | }; | ||||
3383 | |||||
3384 | /// Macro Info DWARF-like metadata node. | ||||
3385 | /// | ||||
3386 | /// A metadata node with a DWARF macro info (i.e., a constant named | ||||
3387 | /// \c DW_MACINFO_*, defined in llvm/BinaryFormat/Dwarf.h). Called \a | ||||
3388 | /// DIMacroNode | ||||
3389 | /// because it's potentially used for non-DWARF output. | ||||
3390 | class DIMacroNode : public MDNode { | ||||
3391 | friend class LLVMContextImpl; | ||||
3392 | friend class MDNode; | ||||
3393 | |||||
3394 | protected: | ||||
3395 | DIMacroNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned MIType, | ||||
3396 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) | ||||
3397 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||
3398 | assert(MIType < 1u << 16)((void)0); | ||||
3399 | SubclassData16 = MIType; | ||||
3400 | } | ||||
3401 | ~DIMacroNode() = default; | ||||
3402 | |||||
3403 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||
3404 | return cast_or_null<Ty>(getOperand(I)); | ||||
3405 | } | ||||
3406 | |||||
3407 | StringRef getStringOperand(unsigned I) const { | ||||
3408 | if (auto *S = getOperandAs<MDString>(I)) | ||||
3409 | return S->getString(); | ||||
3410 | return StringRef(); | ||||
3411 | } | ||||
3412 | |||||
3413 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||
3414 | if (S.empty()) | ||||
3415 | return nullptr; | ||||
3416 | return MDString::get(Context, S); | ||||
3417 | } | ||||
3418 | |||||
3419 | public: | ||||
3420 | unsigned getMacinfoType() const { return SubclassData16; } | ||||
3421 | |||||
3422 | static bool classof(const Metadata *MD) { | ||||
3423 | switch (MD->getMetadataID()) { | ||||
3424 | default: | ||||
3425 | return false; | ||||
3426 | case DIMacroKind: | ||||
3427 | case DIMacroFileKind: | ||||
3428 | return true; | ||||
3429 | } | ||||
3430 | } | ||||
3431 | }; | ||||
3432 | |||||
3433 | class DIMacro : public DIMacroNode { | ||||
3434 | friend class LLVMContextImpl; | ||||
3435 | friend class MDNode; | ||||
3436 | |||||
3437 | unsigned Line; | ||||
3438 | |||||
3439 | DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line, | ||||
3440 | ArrayRef<Metadata *> Ops) | ||||
3441 | : DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {} | ||||
3442 | ~DIMacro() = default; | ||||
3443 | |||||
3444 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||
3445 | StringRef Name, StringRef Value, StorageType Storage, | ||||
3446 | bool ShouldCreate = true) { | ||||
3447 | return getImpl(Context, MIType, Line, getCanonicalMDString(Context, Name), | ||||
3448 | getCanonicalMDString(Context, Value), Storage, ShouldCreate); | ||||
3449 | } | ||||
3450 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||
3451 | MDString *Name, MDString *Value, StorageType Storage, | ||||
3452 | bool ShouldCreate = true); | ||||
3453 | |||||
3454 | TempDIMacro cloneImpl() const { | ||||
3455 | return getTemporary(getContext(), getMacinfoType(), getLine(), getName(), | ||||
3456 | getValue()); | ||||
3457 | } | ||||
3458 | |||||
3459 | public: | ||||
3460 | DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, StringRef Name, | ||||
3461 | StringRef Value = ""), | ||||
3462 | (MIType, Line, Name, Value)) | ||||
3463 | DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, MDString *Name, | ||||
3464 | MDString *Value), | ||||
3465 | (MIType, Line, Name, Value)) | ||||
3466 | |||||
3467 | TempDIMacro clone() const { return cloneImpl(); } | ||||
3468 | |||||
3469 | unsigned getLine() const { return Line; } | ||||
3470 | |||||
3471 | StringRef getName() const { return getStringOperand(0); } | ||||
3472 | StringRef getValue() const { return getStringOperand(1); } | ||||
3473 | |||||
3474 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
3475 | MDString *getRawValue() const { return getOperandAs<MDString>(1); } | ||||
3476 | |||||
3477 | static bool classof(const Metadata *MD) { | ||||
3478 | return MD->getMetadataID() == DIMacroKind; | ||||
3479 | } | ||||
3480 | }; | ||||
3481 | |||||
3482 | class DIMacroFile : public DIMacroNode { | ||||
3483 | friend class LLVMContextImpl; | ||||
3484 | friend class MDNode; | ||||
3485 | |||||
3486 | unsigned Line; | ||||
3487 | |||||
3488 | DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType, | ||||
3489 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||
3490 | : DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {} | ||||
3491 | ~DIMacroFile() = default; | ||||
3492 | |||||
3493 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||
3494 | unsigned Line, DIFile *File, | ||||
3495 | DIMacroNodeArray Elements, StorageType Storage, | ||||
3496 | bool ShouldCreate = true) { | ||||
3497 | return getImpl(Context, MIType, Line, static_cast<Metadata *>(File), | ||||
3498 | Elements.get(), Storage, ShouldCreate); | ||||
3499 | } | ||||
3500 | |||||
3501 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||
3502 | unsigned Line, Metadata *File, Metadata *Elements, | ||||
3503 | StorageType Storage, bool ShouldCreate = true); | ||||
3504 | |||||
3505 | TempDIMacroFile cloneImpl() const { | ||||
3506 | return getTemporary(getContext(), getMacinfoType(), getLine(), getFile(), | ||||
3507 | getElements()); | ||||
3508 | } | ||||
3509 | |||||
3510 | public: | ||||
3511 | DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, DIFile *File, | ||||
3512 | DIMacroNodeArray Elements), | ||||
3513 | (MIType, Line, File, Elements)) | ||||
3514 | DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, | ||||
3515 | Metadata *File, Metadata *Elements), | ||||
3516 | (MIType, Line, File, Elements)) | ||||
3517 | |||||
3518 | TempDIMacroFile clone() const { return cloneImpl(); } | ||||
3519 | |||||
3520 | void replaceElements(DIMacroNodeArray Elements) { | ||||
3521 | #ifndef NDEBUG1 | ||||
3522 | for (DIMacroNode *Op : getElements()) | ||||
3523 | assert(is_contained(Elements->operands(), Op) &&((void)0) | ||||
3524 | "Lost a macro node during macro node list replacement")((void)0); | ||||
3525 | #endif | ||||
3526 | replaceOperandWith(1, Elements.get()); | ||||
3527 | } | ||||
3528 | |||||
3529 | unsigned getLine() const { return Line; } | ||||
3530 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
3531 | |||||
3532 | DIMacroNodeArray getElements() const { | ||||
3533 | return cast_or_null<MDTuple>(getRawElements()); | ||||
3534 | } | ||||
3535 | |||||
3536 | Metadata *getRawFile() const { return getOperand(0); } | ||||
3537 | Metadata *getRawElements() const { return getOperand(1); } | ||||
3538 | |||||
3539 | static bool classof(const Metadata *MD) { | ||||
3540 | return MD->getMetadataID() == DIMacroFileKind; | ||||
3541 | } | ||||
3542 | }; | ||||
3543 | |||||
3544 | /// List of ValueAsMetadata, to be used as an argument to a dbg.value | ||||
3545 | /// intrinsic. | ||||
3546 | class DIArgList : public MDNode { | ||||
3547 | friend class LLVMContextImpl; | ||||
3548 | friend class MDNode; | ||||
3549 | using iterator = SmallVectorImpl<ValueAsMetadata *>::iterator; | ||||
3550 | |||||
3551 | SmallVector<ValueAsMetadata *, 4> Args; | ||||
3552 | |||||
3553 | DIArgList(LLVMContext &C, StorageType Storage, | ||||
3554 | ArrayRef<ValueAsMetadata *> Args) | ||||
3555 | : MDNode(C, DIArgListKind, Storage, None), | ||||
3556 | Args(Args.begin(), Args.end()) { | ||||
3557 | track(); | ||||
3558 | } | ||||
3559 | ~DIArgList() { untrack(); } | ||||
3560 | |||||
3561 | static DIArgList *getImpl(LLVMContext &Context, | ||||
3562 | ArrayRef<ValueAsMetadata *> Args, | ||||
3563 | StorageType Storage, bool ShouldCreate = true); | ||||
3564 | |||||
3565 | TempDIArgList cloneImpl() const { | ||||
3566 | return getTemporary(getContext(), getArgs()); | ||||
3567 | } | ||||
3568 | |||||
3569 | void track(); | ||||
3570 | void untrack(); | ||||
3571 | void dropAllReferences(); | ||||
3572 | |||||
3573 | public: | ||||
3574 | DEFINE_MDNODE_GET(DIArgList, (ArrayRef<ValueAsMetadata *> Args), (Args)) | ||||
3575 | |||||
3576 | TempDIArgList clone() const { return cloneImpl(); } | ||||
3577 | |||||
3578 | ArrayRef<ValueAsMetadata *> getArgs() const { return Args; } | ||||
3579 | |||||
3580 | iterator args_begin() { return Args.begin(); } | ||||
3581 | iterator args_end() { return Args.end(); } | ||||
3582 | |||||
3583 | static bool classof(const Metadata *MD) { | ||||
3584 | return MD->getMetadataID() == DIArgListKind; | ||||
3585 | } | ||||
3586 | |||||
3587 | void handleChangedOperand(void *Ref, Metadata *New); | ||||
3588 | }; | ||||
3589 | |||||
3590 | /// Identifies a unique instance of a variable. | ||||
3591 | /// | ||||
3592 | /// Storage for identifying a potentially inlined instance of a variable, | ||||
3593 | /// or a fragment thereof. This guarantees that exactly one variable instance | ||||
3594 | /// may be identified by this class, even when that variable is a fragment of | ||||
3595 | /// an aggregate variable and/or there is another inlined instance of the same | ||||
3596 | /// source code variable nearby. | ||||
3597 | /// This class does not necessarily uniquely identify that variable: it is | ||||
3598 | /// possible that a DebugVariable with different parameters may point to the | ||||
3599 | /// same variable instance, but not that one DebugVariable points to multiple | ||||
3600 | /// variable instances. | ||||
3601 | class DebugVariable { | ||||
3602 | using FragmentInfo = DIExpression::FragmentInfo; | ||||
3603 | |||||
3604 | const DILocalVariable *Variable; | ||||
3605 | Optional<FragmentInfo> Fragment; | ||||
3606 | const DILocation *InlinedAt; | ||||
3607 | |||||
3608 | /// Fragment that will overlap all other fragments. Used as default when | ||||
3609 | /// caller demands a fragment. | ||||
3610 | static const FragmentInfo DefaultFragment; | ||||
3611 | |||||
3612 | public: | ||||
3613 | DebugVariable(const DILocalVariable *Var, Optional<FragmentInfo> FragmentInfo, | ||||
3614 | const DILocation *InlinedAt) | ||||
3615 | : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} | ||||
3616 | |||||
3617 | DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, | ||||
3618 | const DILocation *InlinedAt) | ||||
3619 | : Variable(Var), | ||||
3620 | Fragment(DIExpr ? DIExpr->getFragmentInfo() : NoneType()), | ||||
3621 | InlinedAt(InlinedAt) {} | ||||
3622 | |||||
3623 | const DILocalVariable *getVariable() const { return Variable; } | ||||
3624 | Optional<FragmentInfo> getFragment() const { return Fragment; } | ||||
3625 | const DILocation *getInlinedAt() const { return InlinedAt; } | ||||
3626 | |||||
3627 | FragmentInfo getFragmentOrDefault() const { | ||||
3628 | return Fragment.getValueOr(DefaultFragment); | ||||
3629 | } | ||||
3630 | |||||
3631 | static bool isDefaultFragment(const FragmentInfo F) { | ||||
3632 | return F == DefaultFragment; | ||||
3633 | } | ||||
3634 | |||||
3635 | bool operator==(const DebugVariable &Other) const { | ||||
3636 | return std::tie(Variable, Fragment, InlinedAt) == | ||||
3637 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||
3638 | } | ||||
3639 | |||||
3640 | bool operator<(const DebugVariable &Other) const { | ||||
3641 | return std::tie(Variable, Fragment, InlinedAt) < | ||||
3642 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||
3643 | } | ||||
3644 | }; | ||||
3645 | |||||
3646 | template <> struct DenseMapInfo<DebugVariable> { | ||||
3647 | using FragmentInfo = DIExpression::FragmentInfo; | ||||
3648 | |||||
3649 | /// Empty key: no key should be generated that has no DILocalVariable. | ||||
3650 | static inline DebugVariable getEmptyKey() { | ||||
3651 | return DebugVariable(nullptr, NoneType(), nullptr); | ||||
3652 | } | ||||
3653 | |||||
3654 | /// Difference in tombstone is that the Optional is meaningful. | ||||
3655 | static inline DebugVariable getTombstoneKey() { | ||||
3656 | return DebugVariable(nullptr, {{0, 0}}, nullptr); | ||||
3657 | } | ||||
3658 | |||||
3659 | static unsigned getHashValue(const DebugVariable &D) { | ||||
3660 | unsigned HV = 0; | ||||
3661 | const Optional<FragmentInfo> Fragment = D.getFragment(); | ||||
3662 | if (Fragment) | ||||
3663 | HV = DenseMapInfo<FragmentInfo>::getHashValue(*Fragment); | ||||
3664 | |||||
3665 | return hash_combine(D.getVariable(), HV, D.getInlinedAt()); | ||||
3666 | } | ||||
3667 | |||||
3668 | static bool isEqual(const DebugVariable &A, const DebugVariable &B) { | ||||
3669 | return A == B; | ||||
3670 | } | ||||
3671 | }; | ||||
3672 | |||||
3673 | } // end namespace llvm | ||||
3674 | |||||
3675 | #undef DEFINE_MDNODE_GET_UNPACK_IMPL | ||||
3676 | #undef DEFINE_MDNODE_GET_UNPACK | ||||
3677 | #undef DEFINE_MDNODE_GET | ||||
3678 | |||||
3679 | #endif // LLVM_IR_DEBUGINFOMETADATA_H |