File: | build/source/llvm/lib/IR/Verifier.cpp |
Warning: | line 2822, 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 | // basic correctness 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 | // * All basic blocks should only end with terminator insts, not contain them | ||||
27 | // * The entry node to a function must not have predecessors | ||||
28 | // * All Instructions must be embedded into a basic block | ||||
29 | // * Functions cannot take a void-typed parameter | ||||
30 | // * Verify that a function's argument list agrees with it's declared type. | ||||
31 | // * It is illegal to specify a name for a void value. | ||||
32 | // * It is illegal to have a internal global value with no initializer | ||||
33 | // * It is illegal to have a ret instruction that returns a value that does not | ||||
34 | // agree with the function return value type. | ||||
35 | // * Function call argument types match the function prototype | ||||
36 | // * A landing pad is defined by a landingpad instruction, and can be jumped to | ||||
37 | // only by the unwind edge of an invoke instruction. | ||||
38 | // * A landingpad instruction must be the first non-PHI instruction in the | ||||
39 | // block. | ||||
40 | // * Landingpad instructions must be in a function with a personality function. | ||||
41 | // * All other things that are tested by asserts spread about the code... | ||||
42 | // | ||||
43 | //===----------------------------------------------------------------------===// | ||||
44 | |||||
45 | #include "llvm/IR/Verifier.h" | ||||
46 | #include "llvm/ADT/APFloat.h" | ||||
47 | #include "llvm/ADT/APInt.h" | ||||
48 | #include "llvm/ADT/ArrayRef.h" | ||||
49 | #include "llvm/ADT/DenseMap.h" | ||||
50 | #include "llvm/ADT/MapVector.h" | ||||
51 | #include "llvm/ADT/STLExtras.h" | ||||
52 | #include "llvm/ADT/SmallPtrSet.h" | ||||
53 | #include "llvm/ADT/SmallSet.h" | ||||
54 | #include "llvm/ADT/SmallVector.h" | ||||
55 | #include "llvm/ADT/StringExtras.h" | ||||
56 | #include "llvm/ADT/StringMap.h" | ||||
57 | #include "llvm/ADT/StringRef.h" | ||||
58 | #include "llvm/ADT/Twine.h" | ||||
59 | #include "llvm/BinaryFormat/Dwarf.h" | ||||
60 | #include "llvm/IR/Argument.h" | ||||
61 | #include "llvm/IR/Attributes.h" | ||||
62 | #include "llvm/IR/BasicBlock.h" | ||||
63 | #include "llvm/IR/CFG.h" | ||||
64 | #include "llvm/IR/CallingConv.h" | ||||
65 | #include "llvm/IR/Comdat.h" | ||||
66 | #include "llvm/IR/Constant.h" | ||||
67 | #include "llvm/IR/ConstantRange.h" | ||||
68 | #include "llvm/IR/Constants.h" | ||||
69 | #include "llvm/IR/DataLayout.h" | ||||
70 | #include "llvm/IR/DebugInfo.h" | ||||
71 | #include "llvm/IR/DebugInfoMetadata.h" | ||||
72 | #include "llvm/IR/DebugLoc.h" | ||||
73 | #include "llvm/IR/DerivedTypes.h" | ||||
74 | #include "llvm/IR/Dominators.h" | ||||
75 | #include "llvm/IR/EHPersonalities.h" | ||||
76 | #include "llvm/IR/Function.h" | ||||
77 | #include "llvm/IR/GCStrategy.h" | ||||
78 | #include "llvm/IR/GlobalAlias.h" | ||||
79 | #include "llvm/IR/GlobalValue.h" | ||||
80 | #include "llvm/IR/GlobalVariable.h" | ||||
81 | #include "llvm/IR/InlineAsm.h" | ||||
82 | #include "llvm/IR/InstVisitor.h" | ||||
83 | #include "llvm/IR/InstrTypes.h" | ||||
84 | #include "llvm/IR/Instruction.h" | ||||
85 | #include "llvm/IR/Instructions.h" | ||||
86 | #include "llvm/IR/IntrinsicInst.h" | ||||
87 | #include "llvm/IR/Intrinsics.h" | ||||
88 | #include "llvm/IR/IntrinsicsAArch64.h" | ||||
89 | #include "llvm/IR/IntrinsicsARM.h" | ||||
90 | #include "llvm/IR/IntrinsicsWebAssembly.h" | ||||
91 | #include "llvm/IR/LLVMContext.h" | ||||
92 | #include "llvm/IR/Metadata.h" | ||||
93 | #include "llvm/IR/Module.h" | ||||
94 | #include "llvm/IR/ModuleSlotTracker.h" | ||||
95 | #include "llvm/IR/PassManager.h" | ||||
96 | #include "llvm/IR/Statepoint.h" | ||||
97 | #include "llvm/IR/Type.h" | ||||
98 | #include "llvm/IR/Use.h" | ||||
99 | #include "llvm/IR/User.h" | ||||
100 | #include "llvm/IR/Value.h" | ||||
101 | #include "llvm/InitializePasses.h" | ||||
102 | #include "llvm/Pass.h" | ||||
103 | #include "llvm/Support/AtomicOrdering.h" | ||||
104 | #include "llvm/Support/Casting.h" | ||||
105 | #include "llvm/Support/CommandLine.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 <optional> | ||||
114 | #include <string> | ||||
115 | #include <utility> | ||||
116 | |||||
117 | using namespace llvm; | ||||
118 | |||||
119 | static cl::opt<bool> VerifyNoAliasScopeDomination( | ||||
120 | "verify-noalias-scope-decl-dom", cl::Hidden, cl::init(false), | ||||
121 | cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical " | ||||
122 | "scopes are not dominating")); | ||||
123 | |||||
124 | namespace llvm { | ||||
125 | |||||
126 | struct VerifierSupport { | ||||
127 | raw_ostream *OS; | ||||
128 | const Module &M; | ||||
129 | ModuleSlotTracker MST; | ||||
130 | Triple TT; | ||||
131 | const DataLayout &DL; | ||||
132 | LLVMContext &Context; | ||||
133 | |||||
134 | /// Track the brokenness of the module while recursively visiting. | ||||
135 | bool Broken = false; | ||||
136 | /// Broken debug info can be "recovered" from by stripping the debug info. | ||||
137 | bool BrokenDebugInfo = false; | ||||
138 | /// Whether to treat broken debug info as an error. | ||||
139 | bool TreatBrokenDebugInfoAsError = true; | ||||
140 | |||||
141 | explicit VerifierSupport(raw_ostream *OS, const Module &M) | ||||
142 | : OS(OS), M(M), MST(&M), TT(M.getTargetTriple()), DL(M.getDataLayout()), | ||||
143 | Context(M.getContext()) {} | ||||
144 | |||||
145 | private: | ||||
146 | void Write(const Module *M) { | ||||
147 | *OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; | ||||
148 | } | ||||
149 | |||||
150 | void Write(const Value *V) { | ||||
151 | if (V) | ||||
152 | Write(*V); | ||||
153 | } | ||||
154 | |||||
155 | void Write(const Value &V) { | ||||
156 | if (isa<Instruction>(V)) { | ||||
157 | V.print(*OS, MST); | ||||
158 | *OS << '\n'; | ||||
159 | } else { | ||||
160 | V.printAsOperand(*OS, true, MST); | ||||
161 | *OS << '\n'; | ||||
162 | } | ||||
163 | } | ||||
164 | |||||
165 | void Write(const Metadata *MD) { | ||||
166 | if (!MD) | ||||
167 | return; | ||||
168 | MD->print(*OS, MST, &M); | ||||
169 | *OS << '\n'; | ||||
170 | } | ||||
171 | |||||
172 | template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) { | ||||
173 | Write(MD.get()); | ||||
174 | } | ||||
175 | |||||
176 | void Write(const NamedMDNode *NMD) { | ||||
177 | if (!NMD) | ||||
178 | return; | ||||
179 | NMD->print(*OS, MST); | ||||
180 | *OS << '\n'; | ||||
181 | } | ||||
182 | |||||
183 | void Write(Type *T) { | ||||
184 | if (!T) | ||||
185 | return; | ||||
186 | *OS << ' ' << *T; | ||||
187 | } | ||||
188 | |||||
189 | void Write(const Comdat *C) { | ||||
190 | if (!C) | ||||
191 | return; | ||||
192 | *OS << *C; | ||||
193 | } | ||||
194 | |||||
195 | void Write(const APInt *AI) { | ||||
196 | if (!AI) | ||||
197 | return; | ||||
198 | *OS << *AI << '\n'; | ||||
199 | } | ||||
200 | |||||
201 | void Write(const unsigned i) { *OS << i << '\n'; } | ||||
202 | |||||
203 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
204 | void Write(const Attribute *A) { | ||||
205 | if (!A) | ||||
206 | return; | ||||
207 | *OS << A->getAsString() << '\n'; | ||||
208 | } | ||||
209 | |||||
210 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
211 | void Write(const AttributeSet *AS) { | ||||
212 | if (!AS) | ||||
213 | return; | ||||
214 | *OS << AS->getAsString() << '\n'; | ||||
215 | } | ||||
216 | |||||
217 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
218 | void Write(const AttributeList *AL) { | ||||
219 | if (!AL) | ||||
220 | return; | ||||
221 | AL->print(*OS); | ||||
222 | } | ||||
223 | |||||
224 | template <typename T> void Write(ArrayRef<T> Vs) { | ||||
225 | for (const T &V : Vs) | ||||
226 | Write(V); | ||||
227 | } | ||||
228 | |||||
229 | template <typename T1, typename... Ts> | ||||
230 | void WriteTs(const T1 &V1, const Ts &... Vs) { | ||||
231 | Write(V1); | ||||
232 | WriteTs(Vs...); | ||||
233 | } | ||||
234 | |||||
235 | template <typename... Ts> void WriteTs() {} | ||||
236 | |||||
237 | public: | ||||
238 | /// A check failed, so printout out the condition and the message. | ||||
239 | /// | ||||
240 | /// This provides a nice place to put a breakpoint if you want to see why | ||||
241 | /// something is not correct. | ||||
242 | void CheckFailed(const Twine &Message) { | ||||
243 | if (OS) | ||||
244 | *OS << Message << '\n'; | ||||
245 | Broken = true; | ||||
246 | } | ||||
247 | |||||
248 | /// A check failed (with values to print). | ||||
249 | /// | ||||
250 | /// This calls the Message-only version so that the above is easier to set a | ||||
251 | /// breakpoint on. | ||||
252 | template <typename T1, typename... Ts> | ||||
253 | void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { | ||||
254 | CheckFailed(Message); | ||||
255 | if (OS) | ||||
256 | WriteTs(V1, Vs...); | ||||
257 | } | ||||
258 | |||||
259 | /// A debug info check failed. | ||||
260 | void DebugInfoCheckFailed(const Twine &Message) { | ||||
261 | if (OS) | ||||
262 | *OS << Message << '\n'; | ||||
263 | Broken |= TreatBrokenDebugInfoAsError; | ||||
264 | BrokenDebugInfo = true; | ||||
265 | } | ||||
266 | |||||
267 | /// A debug info check failed (with values to print). | ||||
268 | template <typename T1, typename... Ts> | ||||
269 | void DebugInfoCheckFailed(const Twine &Message, const T1 &V1, | ||||
270 | const Ts &... Vs) { | ||||
271 | DebugInfoCheckFailed(Message); | ||||
272 | if (OS) | ||||
273 | WriteTs(V1, Vs...); | ||||
274 | } | ||||
275 | }; | ||||
276 | |||||
277 | } // namespace llvm | ||||
278 | |||||
279 | namespace { | ||||
280 | |||||
281 | class Verifier : public InstVisitor<Verifier>, VerifierSupport { | ||||
282 | friend class InstVisitor<Verifier>; | ||||
283 | |||||
284 | // ISD::ArgFlagsTy::MemAlign only have 4 bits for alignment, so | ||||
285 | // the alignment size should not exceed 2^15. Since encode(Align) | ||||
286 | // would plus the shift value by 1, the alignment size should | ||||
287 | // not exceed 2^14, otherwise it can NOT be properly lowered | ||||
288 | // in backend. | ||||
289 | static constexpr unsigned ParamMaxAlignment = 1 << 14; | ||||
290 | DominatorTree DT; | ||||
291 | |||||
292 | /// When verifying a basic block, keep track of all of the | ||||
293 | /// instructions we have seen so far. | ||||
294 | /// | ||||
295 | /// This allows us to do efficient dominance checks for the case when an | ||||
296 | /// instruction has an operand that is an instruction in the same block. | ||||
297 | SmallPtrSet<Instruction *, 16> InstsInThisBlock; | ||||
298 | |||||
299 | /// Keep track of the metadata nodes that have been checked already. | ||||
300 | SmallPtrSet<const Metadata *, 32> MDNodes; | ||||
301 | |||||
302 | /// Keep track which DISubprogram is attached to which function. | ||||
303 | DenseMap<const DISubprogram *, const Function *> DISubprogramAttachments; | ||||
304 | |||||
305 | /// Track all DICompileUnits visited. | ||||
306 | SmallPtrSet<const Metadata *, 2> CUVisited; | ||||
307 | |||||
308 | /// The result type for a landingpad. | ||||
309 | Type *LandingPadResultTy; | ||||
310 | |||||
311 | /// Whether we've seen a call to @llvm.localescape in this function | ||||
312 | /// already. | ||||
313 | bool SawFrameEscape; | ||||
314 | |||||
315 | /// Whether the current function has a DISubprogram attached to it. | ||||
316 | bool HasDebugInfo = false; | ||||
317 | |||||
318 | /// The current source language. | ||||
319 | dwarf::SourceLanguage CurrentSourceLang = dwarf::DW_LANG_lo_user; | ||||
320 | |||||
321 | /// Whether source was present on the first DIFile encountered in each CU. | ||||
322 | DenseMap<const DICompileUnit *, bool> HasSourceDebugInfo; | ||||
323 | |||||
324 | /// Stores the count of how many objects were passed to llvm.localescape for a | ||||
325 | /// given function and the largest index passed to llvm.localrecover. | ||||
326 | DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo; | ||||
327 | |||||
328 | // Maps catchswitches and cleanuppads that unwind to siblings to the | ||||
329 | // terminators that indicate the unwind, used to detect cycles therein. | ||||
330 | MapVector<Instruction *, Instruction *> SiblingFuncletInfo; | ||||
331 | |||||
332 | /// Cache which blocks are in which funclet, if an EH funclet personality is | ||||
333 | /// in use. Otherwise empty. | ||||
334 | DenseMap<BasicBlock *, ColorVector> BlockEHFuncletColors; | ||||
335 | |||||
336 | /// Cache of constants visited in search of ConstantExprs. | ||||
337 | SmallPtrSet<const Constant *, 32> ConstantExprVisited; | ||||
338 | |||||
339 | /// Cache of declarations of the llvm.experimental.deoptimize.<ty> intrinsic. | ||||
340 | SmallVector<const Function *, 4> DeoptimizeDeclarations; | ||||
341 | |||||
342 | /// Cache of attribute lists verified. | ||||
343 | SmallPtrSet<const void *, 32> AttributeListsVisited; | ||||
344 | |||||
345 | // Verify that this GlobalValue is only used in this module. | ||||
346 | // This map is used to avoid visiting uses twice. We can arrive at a user | ||||
347 | // twice, if they have multiple operands. In particular for very large | ||||
348 | // constant expressions, we can arrive at a particular user many times. | ||||
349 | SmallPtrSet<const Value *, 32> GlobalValueVisited; | ||||
350 | |||||
351 | // Keeps track of duplicate function argument debug info. | ||||
352 | SmallVector<const DILocalVariable *, 16> DebugFnArgs; | ||||
353 | |||||
354 | TBAAVerifier TBAAVerifyHelper; | ||||
355 | |||||
356 | SmallVector<IntrinsicInst *, 4> NoAliasScopeDecls; | ||||
357 | |||||
358 | void checkAtomicMemAccessSize(Type *Ty, const Instruction *I); | ||||
359 | |||||
360 | public: | ||||
361 | explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError, | ||||
362 | const Module &M) | ||||
363 | : VerifierSupport(OS, M), LandingPadResultTy(nullptr), | ||||
364 | SawFrameEscape(false), TBAAVerifyHelper(this) { | ||||
365 | TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError; | ||||
366 | } | ||||
367 | |||||
368 | bool hasBrokenDebugInfo() const { return BrokenDebugInfo; } | ||||
369 | |||||
370 | bool verify(const Function &F) { | ||||
371 | assert(F.getParent() == &M &&(static_cast <bool> (F.getParent() == &M && "An instance of this class only works with a specific module!" ) ? void (0) : __assert_fail ("F.getParent() == &M && \"An instance of this class only works with a specific module!\"" , "llvm/lib/IR/Verifier.cpp", 372, __extension__ __PRETTY_FUNCTION__ )) | ||||
372 | "An instance of this class only works with a specific module!")(static_cast <bool> (F.getParent() == &M && "An instance of this class only works with a specific module!" ) ? void (0) : __assert_fail ("F.getParent() == &M && \"An instance of this class only works with a specific module!\"" , "llvm/lib/IR/Verifier.cpp", 372, __extension__ __PRETTY_FUNCTION__ )); | ||||
373 | |||||
374 | // First ensure the function is well-enough formed to compute dominance | ||||
375 | // information, and directly compute a dominance tree. We don't rely on the | ||||
376 | // pass manager to provide this as it isolates us from a potentially | ||||
377 | // out-of-date dominator tree and makes it significantly more complex to run | ||||
378 | // this code outside of a pass manager. | ||||
379 | // FIXME: It's really gross that we have to cast away constness here. | ||||
380 | if (!F.empty()) | ||||
381 | DT.recalculate(const_cast<Function &>(F)); | ||||
382 | |||||
383 | for (const BasicBlock &BB : F) { | ||||
384 | if (!BB.empty() && BB.back().isTerminator()) | ||||
385 | continue; | ||||
386 | |||||
387 | if (OS) { | ||||
388 | *OS << "Basic Block in function '" << F.getName() | ||||
389 | << "' does not have terminator!\n"; | ||||
390 | BB.printAsOperand(*OS, true, MST); | ||||
391 | *OS << "\n"; | ||||
392 | } | ||||
393 | return false; | ||||
394 | } | ||||
395 | |||||
396 | Broken = false; | ||||
397 | // FIXME: We strip const here because the inst visitor strips const. | ||||
398 | visit(const_cast<Function &>(F)); | ||||
399 | verifySiblingFuncletUnwinds(); | ||||
400 | InstsInThisBlock.clear(); | ||||
401 | DebugFnArgs.clear(); | ||||
402 | LandingPadResultTy = nullptr; | ||||
403 | SawFrameEscape = false; | ||||
404 | SiblingFuncletInfo.clear(); | ||||
405 | verifyNoAliasScopeDecl(); | ||||
406 | NoAliasScopeDecls.clear(); | ||||
407 | |||||
408 | return !Broken; | ||||
409 | } | ||||
410 | |||||
411 | /// Verify the module that this instance of \c Verifier was initialized with. | ||||
412 | bool verify() { | ||||
413 | Broken = false; | ||||
414 | |||||
415 | // Collect all declarations of the llvm.experimental.deoptimize intrinsic. | ||||
416 | for (const Function &F : M) | ||||
417 | if (F.getIntrinsicID() == Intrinsic::experimental_deoptimize) | ||||
418 | DeoptimizeDeclarations.push_back(&F); | ||||
419 | |||||
420 | // Now that we've visited every function, verify that we never asked to | ||||
421 | // recover a frame index that wasn't escaped. | ||||
422 | verifyFrameRecoverIndices(); | ||||
423 | for (const GlobalVariable &GV : M.globals()) | ||||
424 | visitGlobalVariable(GV); | ||||
425 | |||||
426 | for (const GlobalAlias &GA : M.aliases()) | ||||
427 | visitGlobalAlias(GA); | ||||
428 | |||||
429 | for (const GlobalIFunc &GI : M.ifuncs()) | ||||
430 | visitGlobalIFunc(GI); | ||||
431 | |||||
432 | for (const NamedMDNode &NMD : M.named_metadata()) | ||||
433 | visitNamedMDNode(NMD); | ||||
434 | |||||
435 | for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) | ||||
436 | visitComdat(SMEC.getValue()); | ||||
437 | |||||
438 | visitModuleFlags(); | ||||
439 | visitModuleIdents(); | ||||
440 | visitModuleCommandLines(); | ||||
441 | |||||
442 | verifyCompileUnits(); | ||||
443 | |||||
444 | verifyDeoptimizeCallingConvs(); | ||||
445 | DISubprogramAttachments.clear(); | ||||
446 | return !Broken; | ||||
447 | } | ||||
448 | |||||
449 | private: | ||||
450 | /// Whether a metadata node is allowed to be, or contain, a DILocation. | ||||
451 | enum class AreDebugLocsAllowed { No, Yes }; | ||||
452 | |||||
453 | // Verification methods... | ||||
454 | void visitGlobalValue(const GlobalValue &GV); | ||||
455 | void visitGlobalVariable(const GlobalVariable &GV); | ||||
456 | void visitGlobalAlias(const GlobalAlias &GA); | ||||
457 | void visitGlobalIFunc(const GlobalIFunc &GI); | ||||
458 | void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); | ||||
459 | void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited, | ||||
460 | const GlobalAlias &A, const Constant &C); | ||||
461 | void visitNamedMDNode(const NamedMDNode &NMD); | ||||
462 | void visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs); | ||||
463 | void visitMetadataAsValue(const MetadataAsValue &MD, Function *F); | ||||
464 | void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); | ||||
465 | void visitComdat(const Comdat &C); | ||||
466 | void visitModuleIdents(); | ||||
467 | void visitModuleCommandLines(); | ||||
468 | void visitModuleFlags(); | ||||
469 | void visitModuleFlag(const MDNode *Op, | ||||
470 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
471 | SmallVectorImpl<const MDNode *> &Requirements); | ||||
472 | void visitModuleFlagCGProfileEntry(const MDOperand &MDO); | ||||
473 | void visitFunction(const Function &F); | ||||
474 | void visitBasicBlock(BasicBlock &BB); | ||||
475 | void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); | ||||
476 | void visitDereferenceableMetadata(Instruction &I, MDNode *MD); | ||||
477 | void visitProfMetadata(Instruction &I, MDNode *MD); | ||||
478 | void visitCallStackMetadata(MDNode *MD); | ||||
479 | void visitMemProfMetadata(Instruction &I, MDNode *MD); | ||||
480 | void visitCallsiteMetadata(Instruction &I, MDNode *MD); | ||||
481 | void visitDIAssignIDMetadata(Instruction &I, MDNode *MD); | ||||
482 | void visitAnnotationMetadata(MDNode *Annotation); | ||||
483 | void visitAliasScopeMetadata(const MDNode *MD); | ||||
484 | void visitAliasScopeListMetadata(const MDNode *MD); | ||||
485 | void visitAccessGroupMetadata(const MDNode *MD); | ||||
486 | |||||
487 | template <class Ty> bool isValidMetadataArray(const MDTuple &N); | ||||
488 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); | ||||
489 | #include "llvm/IR/Metadata.def" | ||||
490 | void visitDIScope(const DIScope &N); | ||||
491 | void visitDIVariable(const DIVariable &N); | ||||
492 | void visitDILexicalBlockBase(const DILexicalBlockBase &N); | ||||
493 | void visitDITemplateParameter(const DITemplateParameter &N); | ||||
494 | |||||
495 | void visitTemplateParams(const MDNode &N, const Metadata &RawParams); | ||||
496 | |||||
497 | // InstVisitor overrides... | ||||
498 | using InstVisitor<Verifier>::visit; | ||||
499 | void visit(Instruction &I); | ||||
500 | |||||
501 | void visitTruncInst(TruncInst &I); | ||||
502 | void visitZExtInst(ZExtInst &I); | ||||
503 | void visitSExtInst(SExtInst &I); | ||||
504 | void visitFPTruncInst(FPTruncInst &I); | ||||
505 | void visitFPExtInst(FPExtInst &I); | ||||
506 | void visitFPToUIInst(FPToUIInst &I); | ||||
507 | void visitFPToSIInst(FPToSIInst &I); | ||||
508 | void visitUIToFPInst(UIToFPInst &I); | ||||
509 | void visitSIToFPInst(SIToFPInst &I); | ||||
510 | void visitIntToPtrInst(IntToPtrInst &I); | ||||
511 | void visitPtrToIntInst(PtrToIntInst &I); | ||||
512 | void visitBitCastInst(BitCastInst &I); | ||||
513 | void visitAddrSpaceCastInst(AddrSpaceCastInst &I); | ||||
514 | void visitPHINode(PHINode &PN); | ||||
515 | void visitCallBase(CallBase &Call); | ||||
516 | void visitUnaryOperator(UnaryOperator &U); | ||||
517 | void visitBinaryOperator(BinaryOperator &B); | ||||
518 | void visitICmpInst(ICmpInst &IC); | ||||
519 | void visitFCmpInst(FCmpInst &FC); | ||||
520 | void visitExtractElementInst(ExtractElementInst &EI); | ||||
521 | void visitInsertElementInst(InsertElementInst &EI); | ||||
522 | void visitShuffleVectorInst(ShuffleVectorInst &EI); | ||||
523 | void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); } | ||||
524 | void visitCallInst(CallInst &CI); | ||||
525 | void visitInvokeInst(InvokeInst &II); | ||||
526 | void visitGetElementPtrInst(GetElementPtrInst &GEP); | ||||
527 | void visitLoadInst(LoadInst &LI); | ||||
528 | void visitStoreInst(StoreInst &SI); | ||||
529 | void verifyDominatesUse(Instruction &I, unsigned i); | ||||
530 | void visitInstruction(Instruction &I); | ||||
531 | void visitTerminator(Instruction &I); | ||||
532 | void visitBranchInst(BranchInst &BI); | ||||
533 | void visitReturnInst(ReturnInst &RI); | ||||
534 | void visitSwitchInst(SwitchInst &SI); | ||||
535 | void visitIndirectBrInst(IndirectBrInst &BI); | ||||
536 | void visitCallBrInst(CallBrInst &CBI); | ||||
537 | void visitSelectInst(SelectInst &SI); | ||||
538 | void visitUserOp1(Instruction &I); | ||||
539 | void visitUserOp2(Instruction &I) { visitUserOp1(I); } | ||||
540 | void visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call); | ||||
541 | void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); | ||||
542 | void visitVPIntrinsic(VPIntrinsic &VPI); | ||||
543 | void visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII); | ||||
544 | void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI); | ||||
545 | void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); | ||||
546 | void visitAtomicRMWInst(AtomicRMWInst &RMWI); | ||||
547 | void visitFenceInst(FenceInst &FI); | ||||
548 | void visitAllocaInst(AllocaInst &AI); | ||||
549 | void visitExtractValueInst(ExtractValueInst &EVI); | ||||
550 | void visitInsertValueInst(InsertValueInst &IVI); | ||||
551 | void visitEHPadPredecessors(Instruction &I); | ||||
552 | void visitLandingPadInst(LandingPadInst &LPI); | ||||
553 | void visitResumeInst(ResumeInst &RI); | ||||
554 | void visitCatchPadInst(CatchPadInst &CPI); | ||||
555 | void visitCatchReturnInst(CatchReturnInst &CatchReturn); | ||||
556 | void visitCleanupPadInst(CleanupPadInst &CPI); | ||||
557 | void visitFuncletPadInst(FuncletPadInst &FPI); | ||||
558 | void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch); | ||||
559 | void visitCleanupReturnInst(CleanupReturnInst &CRI); | ||||
560 | |||||
561 | void verifySwiftErrorCall(CallBase &Call, const Value *SwiftErrorVal); | ||||
562 | void verifySwiftErrorValue(const Value *SwiftErrorVal); | ||||
563 | void verifyTailCCMustTailAttrs(const AttrBuilder &Attrs, StringRef Context); | ||||
564 | void verifyMustTailCall(CallInst &CI); | ||||
565 | bool verifyAttributeCount(AttributeList Attrs, unsigned Params); | ||||
566 | void verifyAttributeTypes(AttributeSet Attrs, const Value *V); | ||||
567 | void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V); | ||||
568 | void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
569 | const Value *V); | ||||
570 | void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
571 | const Value *V, bool IsIntrinsic, bool IsInlineAsm); | ||||
572 | void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs); | ||||
573 | |||||
574 | void visitConstantExprsRecursively(const Constant *EntryC); | ||||
575 | void visitConstantExpr(const ConstantExpr *CE); | ||||
576 | void verifyInlineAsmCall(const CallBase &Call); | ||||
577 | void verifyStatepoint(const CallBase &Call); | ||||
578 | void verifyFrameRecoverIndices(); | ||||
579 | void verifySiblingFuncletUnwinds(); | ||||
580 | |||||
581 | void verifyFragmentExpression(const DbgVariableIntrinsic &I); | ||||
582 | template <typename ValueOrMetadata> | ||||
583 | void verifyFragmentExpression(const DIVariable &V, | ||||
584 | DIExpression::FragmentInfo Fragment, | ||||
585 | ValueOrMetadata *Desc); | ||||
586 | void verifyFnArgs(const DbgVariableIntrinsic &I); | ||||
587 | void verifyNotEntryValue(const DbgVariableIntrinsic &I); | ||||
588 | |||||
589 | /// Module-level debug info verification... | ||||
590 | void verifyCompileUnits(); | ||||
591 | |||||
592 | /// Module-level verification that all @llvm.experimental.deoptimize | ||||
593 | /// declarations share the same calling convention. | ||||
594 | void verifyDeoptimizeCallingConvs(); | ||||
595 | |||||
596 | void verifyAttachedCallBundle(const CallBase &Call, | ||||
597 | const OperandBundleUse &BU); | ||||
598 | |||||
599 | /// Verify all-or-nothing property of DIFile source attribute within a CU. | ||||
600 | void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F); | ||||
601 | |||||
602 | /// Verify the llvm.experimental.noalias.scope.decl declarations | ||||
603 | void verifyNoAliasScopeDecl(); | ||||
604 | }; | ||||
605 | |||||
606 | } // end anonymous namespace | ||||
607 | |||||
608 | /// We know that cond should be true, if not print an error message. | ||||
609 | #define Check(C, ...)do { if (!(C)) { CheckFailed(...); return; } } while (false) \ | ||||
610 | do { \ | ||||
611 | if (!(C)) { \ | ||||
612 | CheckFailed(__VA_ARGS__); \ | ||||
613 | return; \ | ||||
614 | } \ | ||||
615 | } while (false) | ||||
616 | |||||
617 | /// We know that a debug info condition should be true, if not print | ||||
618 | /// an error message. | ||||
619 | #define CheckDI(C, ...)do { if (!(C)) { DebugInfoCheckFailed(...); return; } } while (false) \ | ||||
620 | do { \ | ||||
621 | if (!(C)) { \ | ||||
622 | DebugInfoCheckFailed(__VA_ARGS__); \ | ||||
623 | return; \ | ||||
624 | } \ | ||||
625 | } while (false) | ||||
626 | |||||
627 | void Verifier::visit(Instruction &I) { | ||||
628 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) | ||||
629 | Check(I.getOperand(i) != nullptr, "Operand is null", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Operand is null" , &I); return; } } while (false); | ||||
630 | InstVisitor<Verifier>::visit(I); | ||||
631 | } | ||||
632 | |||||
633 | // Helper to iterate over indirect users. By returning false, the callback can ask to stop traversing further. | ||||
634 | static void forEachUser(const Value *User, | ||||
635 | SmallPtrSet<const Value *, 32> &Visited, | ||||
636 | llvm::function_ref<bool(const Value *)> Callback) { | ||||
637 | if (!Visited.insert(User).second) | ||||
638 | return; | ||||
639 | |||||
640 | SmallVector<const Value *> WorkList; | ||||
641 | append_range(WorkList, User->materialized_users()); | ||||
642 | while (!WorkList.empty()) { | ||||
643 | const Value *Cur = WorkList.pop_back_val(); | ||||
644 | if (!Visited.insert(Cur).second) | ||||
645 | continue; | ||||
646 | if (Callback(Cur)) | ||||
647 | append_range(WorkList, Cur->materialized_users()); | ||||
648 | } | ||||
649 | } | ||||
650 | |||||
651 | void Verifier::visitGlobalValue(const GlobalValue &GV) { | ||||
652 | Check(!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) | ||||
653 | "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); | ||||
654 | |||||
655 | if (const GlobalObject *GO = dyn_cast<GlobalObject>(&GV)) { | ||||
656 | |||||
657 | if (MaybeAlign A = GO->getAlign()) { | ||||
658 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", GO); return; } } while (false) | ||||
659 | "huge alignment values are unsupported", GO)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", GO); return; } } while (false); | ||||
660 | } | ||||
661 | |||||
662 | if (const MDNode *Associated = | ||||
663 | GO->getMetadata(LLVMContext::MD_associated)) { | ||||
664 | Check(Associated->getNumOperands() == 1,do { if (!(Associated->getNumOperands() == 1)) { CheckFailed ("associated metadata must have one operand", &GV, Associated ); return; } } while (false) | ||||
665 | "associated metadata must have one operand", &GV, Associated)do { if (!(Associated->getNumOperands() == 1)) { CheckFailed ("associated metadata must have one operand", &GV, Associated ); return; } } while (false); | ||||
666 | const Metadata *Op = Associated->getOperand(0).get(); | ||||
667 | Check(Op, "associated metadata must have a global value", GO, Associated)do { if (!(Op)) { CheckFailed("associated metadata must have a global value" , GO, Associated); return; } } while (false); | ||||
668 | |||||
669 | const auto *VM = dyn_cast_or_null<ValueAsMetadata>(Op); | ||||
670 | Check(VM, "associated metadata must be ValueAsMetadata", GO, Associated)do { if (!(VM)) { CheckFailed("associated metadata must be ValueAsMetadata" , GO, Associated); return; } } while (false); | ||||
671 | if (VM) { | ||||
672 | Check(isa<PointerType>(VM->getValue()->getType()),do { if (!(isa<PointerType>(VM->getValue()->getType ()))) { CheckFailed("associated value must be pointer typed", GV, Associated); return; } } while (false) | ||||
673 | "associated value must be pointer typed", GV, Associated)do { if (!(isa<PointerType>(VM->getValue()->getType ()))) { CheckFailed("associated value must be pointer typed", GV, Associated); return; } } while (false); | ||||
674 | |||||
675 | const Value *Stripped = VM->getValue()->stripPointerCastsAndAliases(); | ||||
676 | Check(isa<GlobalObject>(Stripped) || isa<Constant>(Stripped),do { if (!(isa<GlobalObject>(Stripped) || isa<Constant >(Stripped))) { CheckFailed("associated metadata must point to a GlobalObject" , GO, Stripped); return; } } while (false) | ||||
677 | "associated metadata must point to a GlobalObject", GO, Stripped)do { if (!(isa<GlobalObject>(Stripped) || isa<Constant >(Stripped))) { CheckFailed("associated metadata must point to a GlobalObject" , GO, Stripped); return; } } while (false); | ||||
678 | Check(Stripped != GO,do { if (!(Stripped != GO)) { CheckFailed("global values should not associate to themselves" , GO, Associated); return; } } while (false) | ||||
679 | "global values should not associate to themselves", GO,do { if (!(Stripped != GO)) { CheckFailed("global values should not associate to themselves" , GO, Associated); return; } } while (false) | ||||
680 | Associated)do { if (!(Stripped != GO)) { CheckFailed("global values should not associate to themselves" , GO, Associated); return; } } while (false); | ||||
681 | } | ||||
682 | } | ||||
683 | } | ||||
684 | Check(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),do { if (!(!GV.hasAppendingLinkage() || isa<GlobalVariable >(GV))) { CheckFailed("Only global variables can have appending linkage!" , &GV); return; } } while (false) | ||||
685 | "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); | ||||
686 | |||||
687 | if (GV.hasAppendingLinkage()) { | ||||
688 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV); | ||||
689 | Check(GVar && GVar->getValueType()->isArrayTy(),do { if (!(GVar && GVar->getValueType()->isArrayTy ())) { CheckFailed("Only global arrays can have appending linkage!" , GVar); return; } } while (false) | ||||
690 | "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); | ||||
691 | } | ||||
692 | |||||
693 | if (GV.isDeclarationForLinker()) | ||||
694 | Check(!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); | ||||
695 | |||||
696 | if (GV.hasDLLExportStorageClass()) { | ||||
697 | Check(!GV.hasHiddenVisibility(),do { if (!(!GV.hasHiddenVisibility())) { CheckFailed("dllexport GlobalValue must have default or protected visibility" , &GV); return; } } while (false) | ||||
698 | "dllexport GlobalValue must have default or protected visibility",do { if (!(!GV.hasHiddenVisibility())) { CheckFailed("dllexport GlobalValue must have default or protected visibility" , &GV); return; } } while (false) | ||||
699 | &GV)do { if (!(!GV.hasHiddenVisibility())) { CheckFailed("dllexport GlobalValue must have default or protected visibility" , &GV); return; } } while (false); | ||||
700 | } | ||||
701 | if (GV.hasDLLImportStorageClass()) { | ||||
702 | Check(GV.hasDefaultVisibility(),do { if (!(GV.hasDefaultVisibility())) { CheckFailed("dllimport GlobalValue must have default visibility" , &GV); return; } } while (false) | ||||
703 | "dllimport GlobalValue must have default visibility", &GV)do { if (!(GV.hasDefaultVisibility())) { CheckFailed("dllimport GlobalValue must have default visibility" , &GV); return; } } while (false); | ||||
704 | Check(!GV.isDSOLocal(), "GlobalValue with DLLImport Storage is dso_local!",do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false) | ||||
705 | &GV)do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false); | ||||
706 | |||||
707 | Check((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) | ||||
708 | (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) | ||||
709 | 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) | ||||
710 | "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); | ||||
711 | } | ||||
712 | |||||
713 | if (GV.isImplicitDSOLocal()) | ||||
714 | Check(GV.isDSOLocal(),do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
715 | "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) | ||||
716 | "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) | ||||
717 | &GV)do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false); | ||||
718 | |||||
719 | forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool { | ||||
720 | if (const Instruction *I = dyn_cast<Instruction>(V)) { | ||||
721 | if (!I->getParent() || !I->getParent()->getParent()) | ||||
722 | CheckFailed("Global is referenced by parentless instruction!", &GV, &M, | ||||
723 | I); | ||||
724 | else if (I->getParent()->getParent()->getParent() != &M) | ||||
725 | CheckFailed("Global is referenced in a different module!", &GV, &M, I, | ||||
726 | I->getParent()->getParent(), | ||||
727 | I->getParent()->getParent()->getParent()); | ||||
728 | return false; | ||||
729 | } else if (const Function *F = dyn_cast<Function>(V)) { | ||||
730 | if (F->getParent() != &M) | ||||
731 | CheckFailed("Global is used by function in a different module", &GV, &M, | ||||
732 | F, F->getParent()); | ||||
733 | return false; | ||||
734 | } | ||||
735 | return true; | ||||
736 | }); | ||||
737 | } | ||||
738 | |||||
739 | void Verifier::visitGlobalVariable(const GlobalVariable &GV) { | ||||
740 | if (GV.hasInitializer()) { | ||||
741 | Check(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) | ||||
742 | "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) | ||||
743 | "variable type!",do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
744 | &GV)do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false); | ||||
745 | // If the global has common linkage, it must have a zero initializer and | ||||
746 | // cannot be constant. | ||||
747 | if (GV.hasCommonLinkage()) { | ||||
748 | Check(GV.getInitializer()->isNullValue(),do { if (!(GV.getInitializer()->isNullValue())) { CheckFailed ("'common' global must have a zero initializer!", &GV); return ; } } while (false) | ||||
749 | "'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); | ||||
750 | Check(!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) | ||||
751 | &GV)do { if (!(!GV.isConstant())) { CheckFailed("'common' global may not be marked constant!" , &GV); return; } } while (false); | ||||
752 | Check(!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); | ||||
753 | } | ||||
754 | } | ||||
755 | |||||
756 | if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || | ||||
757 | GV.getName() == "llvm.global_dtors")) { | ||||
758 | Check(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
759 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
760 | Check(GV.materialized_use_empty(),do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false) | ||||
761 | "invalid uses of intrinsic global variable", &GV)do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false); | ||||
762 | |||||
763 | // Don't worry about emitting an error for it not being an array, | ||||
764 | // visitGlobalValue will complain on appending non-array. | ||||
765 | if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) { | ||||
766 | StructType *STy = dyn_cast<StructType>(ATy->getElementType()); | ||||
767 | PointerType *FuncPtrTy = | ||||
768 | FunctionType::get(Type::getVoidTy(Context), false)-> | ||||
769 | getPointerTo(DL.getProgramAddressSpace()); | ||||
770 | Check(STy && (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) | ||||
771 | 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) | ||||
772 | 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) | ||||
773 | "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); | ||||
774 | Check(STy->getNumElements() == 3,do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify ptr null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
775 | "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 ptr null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
776 | "specify ptr 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 ptr null to migrate from the obsoleted 2-field form" ); return; } } while (false); | ||||
777 | Type *ETy = STy->getTypeAtIndex(2); | ||||
778 | Type *Int8Ty = Type::getInt8Ty(ETy->getContext()); | ||||
779 | Check(ETy->isPointerTy() &&do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false) | ||||
780 | 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) | ||||
781 | "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); | ||||
782 | } | ||||
783 | } | ||||
784 | |||||
785 | if (GV.hasName() && (GV.getName() == "llvm.used" || | ||||
786 | GV.getName() == "llvm.compiler.used")) { | ||||
787 | Check(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
788 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
789 | Check(GV.materialized_use_empty(),do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false) | ||||
790 | "invalid uses of intrinsic global variable", &GV)do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false); | ||||
791 | |||||
792 | Type *GVType = GV.getValueType(); | ||||
793 | if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) { | ||||
794 | PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType()); | ||||
795 | Check(PTy, "wrong type for intrinsic global variable", &GV)do { if (!(PTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false); | ||||
796 | if (GV.hasInitializer()) { | ||||
797 | const Constant *Init = GV.getInitializer(); | ||||
798 | const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); | ||||
799 | Check(InitArray, "wrong initalizer for intrinsic global variable",do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false) | ||||
800 | Init)do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false); | ||||
801 | for (Value *Op : InitArray->operands()) { | ||||
802 | Value *V = Op->stripPointerCasts(); | ||||
803 | Check(isa<GlobalVariable>(V) || isa<Function>(V) ||do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed(Twine("invalid " ) + GV.getName() + " member", V); return; } } while (false) | ||||
804 | isa<GlobalAlias>(V),do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed(Twine("invalid " ) + GV.getName() + " member", V); return; } } while (false) | ||||
805 | Twine("invalid ") + GV.getName() + " member", V)do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed(Twine("invalid " ) + GV.getName() + " member", V); return; } } while (false); | ||||
806 | Check(V->hasName(),do { if (!(V->hasName())) { CheckFailed(Twine("members of " ) + GV.getName() + " must be named", V); return; } } while (false ) | ||||
807 | Twine("members of ") + GV.getName() + " must be named", V)do { if (!(V->hasName())) { CheckFailed(Twine("members of " ) + GV.getName() + " must be named", V); return; } } while (false ); | ||||
808 | } | ||||
809 | } | ||||
810 | } | ||||
811 | } | ||||
812 | |||||
813 | // Visit any debug info attachments. | ||||
814 | SmallVector<MDNode *, 1> MDs; | ||||
815 | GV.getMetadata(LLVMContext::MD_dbg, MDs); | ||||
816 | for (auto *MD : MDs) { | ||||
817 | if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD)) | ||||
818 | visitDIGlobalVariableExpression(*GVE); | ||||
819 | else | ||||
820 | CheckDI(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) | ||||
821 | "DIGlobalVariableExpression")do { if (!(false)) { DebugInfoCheckFailed("!dbg attachment of global variable must be a " "DIGlobalVariableExpression"); return; } } while (false); | ||||
822 | } | ||||
823 | |||||
824 | // Scalable vectors cannot be global variables, since we don't know | ||||
825 | // the runtime size. If the global is an array containing scalable vectors, | ||||
826 | // that will be caught by the isValidElementType methods in StructType or | ||||
827 | // ArrayType instead. | ||||
828 | Check(!isa<ScalableVectorType>(GV.getValueType()),do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false) | ||||
829 | "Globals cannot contain scalable vectors", &GV)do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false); | ||||
830 | |||||
831 | if (auto *STy = dyn_cast<StructType>(GV.getValueType())) | ||||
832 | Check(!STy->containsScalableVectorType(),do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false) | ||||
833 | "Globals cannot contain scalable vectors", &GV)do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false); | ||||
834 | |||||
835 | // Check if it's a target extension type that disallows being used as a | ||||
836 | // global. | ||||
837 | if (auto *TTy = dyn_cast<TargetExtType>(GV.getValueType())) | ||||
838 | Check(TTy->hasProperty(TargetExtType::CanBeGlobal),do { if (!(TTy->hasProperty(TargetExtType::CanBeGlobal))) { CheckFailed("Global @" + GV.getName() + " has illegal target extension type" , TTy); return; } } while (false) | ||||
839 | "Global @" + GV.getName() + " has illegal target extension type",do { if (!(TTy->hasProperty(TargetExtType::CanBeGlobal))) { CheckFailed("Global @" + GV.getName() + " has illegal target extension type" , TTy); return; } } while (false) | ||||
840 | TTy)do { if (!(TTy->hasProperty(TargetExtType::CanBeGlobal))) { CheckFailed("Global @" + GV.getName() + " has illegal target extension type" , TTy); return; } } while (false); | ||||
841 | |||||
842 | if (!GV.hasInitializer()) { | ||||
843 | visitGlobalValue(GV); | ||||
844 | return; | ||||
845 | } | ||||
846 | |||||
847 | // Walk any aggregate initializers looking for bitcasts between address spaces | ||||
848 | visitConstantExprsRecursively(GV.getInitializer()); | ||||
849 | |||||
850 | visitGlobalValue(GV); | ||||
851 | } | ||||
852 | |||||
853 | void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { | ||||
854 | SmallPtrSet<const GlobalAlias*, 4> Visited; | ||||
855 | Visited.insert(&GA); | ||||
856 | visitAliaseeSubExpr(Visited, GA, C); | ||||
857 | } | ||||
858 | |||||
859 | void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited, | ||||
860 | const GlobalAlias &GA, const Constant &C) { | ||||
861 | if (GA.hasAvailableExternallyLinkage()) { | ||||
862 | Check(isa<GlobalValue>(C) &&do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
863 | cast<GlobalValue>(C).hasAvailableExternallyLinkage(),do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
864 | "available_externally alias must point to available_externally "do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
865 | "global value",do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
866 | &GA)do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false); | ||||
867 | } | ||||
868 | if (const auto *GV = dyn_cast<GlobalValue>(&C)) { | ||||
869 | if (!GA.hasAvailableExternallyLinkage()) { | ||||
870 | Check(!GV->isDeclarationForLinker(), "Alias must point to a definition",do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false) | ||||
871 | &GA)do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false); | ||||
872 | } | ||||
873 | |||||
874 | if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { | ||||
875 | Check(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); | ||||
876 | |||||
877 | Check(!GA2->isInterposable(),do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false) | ||||
878 | "Alias cannot point to an interposable alias", &GA)do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false); | ||||
879 | } else { | ||||
880 | // Only continue verifying subexpressions of GlobalAliases. | ||||
881 | // Do not recurse into global initializers. | ||||
882 | return; | ||||
883 | } | ||||
884 | } | ||||
885 | |||||
886 | if (const auto *CE = dyn_cast<ConstantExpr>(&C)) | ||||
887 | visitConstantExprsRecursively(CE); | ||||
888 | |||||
889 | for (const Use &U : C.operands()) { | ||||
890 | Value *V = &*U; | ||||
891 | if (const auto *GA2 = dyn_cast<GlobalAlias>(V)) | ||||
892 | visitAliaseeSubExpr(Visited, GA, *GA2->getAliasee()); | ||||
893 | else if (const auto *C2 = dyn_cast<Constant>(V)) | ||||
894 | visitAliaseeSubExpr(Visited, GA, *C2); | ||||
895 | } | ||||
896 | } | ||||
897 | |||||
898 | void Verifier::visitGlobalAlias(const GlobalAlias &GA) { | ||||
899 | Check(GlobalAlias::isValidLinkage(GA.getLinkage()),do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, external, or available_externally linkage!", & GA); return; } } while (false) | ||||
900 | "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, external, or available_externally linkage!", & GA); return; } } while (false) | ||||
901 | "weak_odr, external, or available_externally linkage!",do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, external, or available_externally linkage!", & GA); return; } } while (false) | ||||
902 | &GA)do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, external, or available_externally linkage!", & GA); return; } } while (false); | ||||
903 | const Constant *Aliasee = GA.getAliasee(); | ||||
904 | Check(Aliasee, "Aliasee cannot be NULL!", &GA)do { if (!(Aliasee)) { CheckFailed("Aliasee cannot be NULL!", &GA); return; } } while (false); | ||||
905 | Check(GA.getType() == Aliasee->getType(),do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false) | ||||
906 | "Alias and aliasee types should match!", &GA)do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false); | ||||
907 | |||||
908 | Check(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) | ||||
909 | "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); | ||||
910 | |||||
911 | visitAliaseeSubExpr(GA, *Aliasee); | ||||
912 | |||||
913 | visitGlobalValue(GA); | ||||
914 | } | ||||
915 | |||||
916 | void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) { | ||||
917 | Check(GlobalIFunc::isValidLinkage(GI.getLinkage()),do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false) | ||||
918 | "IFunc should have private, internal, linkonce, weak, linkonce_odr, "do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false) | ||||
919 | "weak_odr, or external linkage!",do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false) | ||||
920 | &GI)do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false); | ||||
921 | // Pierce through ConstantExprs and GlobalAliases and check that the resolver | ||||
922 | // is a Function definition. | ||||
923 | const Function *Resolver = GI.getResolverFunction(); | ||||
924 | Check(Resolver, "IFunc must have a Function resolver", &GI)do { if (!(Resolver)) { CheckFailed("IFunc must have a Function resolver" , &GI); return; } } while (false); | ||||
925 | Check(!Resolver->isDeclarationForLinker(),do { if (!(!Resolver->isDeclarationForLinker())) { CheckFailed ("IFunc resolver must be a definition", &GI); return; } } while (false) | ||||
926 | "IFunc resolver must be a definition", &GI)do { if (!(!Resolver->isDeclarationForLinker())) { CheckFailed ("IFunc resolver must be a definition", &GI); return; } } while (false); | ||||
927 | |||||
928 | // Check that the immediate resolver operand (prior to any bitcasts) has the | ||||
929 | // correct type. | ||||
930 | const Type *ResolverTy = GI.getResolver()->getType(); | ||||
931 | |||||
932 | Check(isa<PointerType>(Resolver->getFunctionType()->getReturnType()),do { if (!(isa<PointerType>(Resolver->getFunctionType ()->getReturnType()))) { CheckFailed("IFunc resolver must return a pointer" , &GI); return; } } while (false) | ||||
933 | "IFunc resolver must return a pointer", &GI)do { if (!(isa<PointerType>(Resolver->getFunctionType ()->getReturnType()))) { CheckFailed("IFunc resolver must return a pointer" , &GI); return; } } while (false); | ||||
934 | |||||
935 | const Type *ResolverFuncTy = | ||||
936 | GlobalIFunc::getResolverFunctionType(GI.getValueType()); | ||||
937 | Check(ResolverTy == ResolverFuncTy->getPointerTo(GI.getAddressSpace()),do { if (!(ResolverTy == ResolverFuncTy->getPointerTo(GI.getAddressSpace ()))) { CheckFailed("IFunc resolver has incorrect type", & GI); return; } } while (false) | ||||
938 | "IFunc resolver has incorrect type", &GI)do { if (!(ResolverTy == ResolverFuncTy->getPointerTo(GI.getAddressSpace ()))) { CheckFailed("IFunc resolver has incorrect type", & GI); return; } } while (false); | ||||
939 | } | ||||
940 | |||||
941 | void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { | ||||
942 | // There used to be various other llvm.dbg.* nodes, but we don't support | ||||
943 | // upgrading them and we want to reserve the namespace for future uses. | ||||
944 | if (NMD.getName().startswith("llvm.dbg.")) | ||||
945 | CheckDI(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) | ||||
946 | "unrecognized named metadata node in the llvm.dbg namespace", &NMD)do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false); | ||||
947 | for (const MDNode *MD : NMD.operands()) { | ||||
948 | if (NMD.getName() == "llvm.dbg.cu") | ||||
949 | CheckDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD)do { if (!(MD && isa<DICompileUnit>(MD))) { DebugInfoCheckFailed ("invalid compile unit", &NMD, MD); return; } } while (false ); | ||||
950 | |||||
951 | if (!MD) | ||||
952 | continue; | ||||
953 | |||||
954 | visitMDNode(*MD, AreDebugLocsAllowed::Yes); | ||||
955 | } | ||||
956 | } | ||||
957 | |||||
958 | void Verifier::visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs) { | ||||
959 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
960 | // avoids infinite recursion here, as well as being an optimization. | ||||
961 | if (!MDNodes.insert(&MD).second) | ||||
962 | return; | ||||
963 | |||||
964 | Check(&MD.getContext() == &Context,do { if (!(&MD.getContext() == &Context)) { CheckFailed ("MDNode context does not match Module context!", &MD); return ; } } while (false) | ||||
965 | "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); | ||||
966 | |||||
967 | switch (MD.getMetadataID()) { | ||||
968 | default: | ||||
969 | llvm_unreachable("Invalid MDNode subclass")::llvm::llvm_unreachable_internal("Invalid MDNode subclass", "llvm/lib/IR/Verifier.cpp" , 969); | ||||
970 | case Metadata::MDTupleKind: | ||||
971 | break; | ||||
972 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ | ||||
973 | case Metadata::CLASS##Kind: \ | ||||
974 | visit##CLASS(cast<CLASS>(MD)); \ | ||||
975 | break; | ||||
976 | #include "llvm/IR/Metadata.def" | ||||
977 | } | ||||
978 | |||||
979 | for (const Metadata *Op : MD.operands()) { | ||||
980 | if (!Op) | ||||
981 | continue; | ||||
982 | Check(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!",do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false) | ||||
983 | &MD, Op)do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false); | ||||
984 | CheckDI(!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) | ||||
985 | "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); | ||||
986 | if (auto *N = dyn_cast<MDNode>(Op)) { | ||||
987 | visitMDNode(*N, AllowLocs); | ||||
988 | continue; | ||||
989 | } | ||||
990 | if (auto *V = dyn_cast<ValueAsMetadata>(Op)) { | ||||
991 | visitValueAsMetadata(*V, nullptr); | ||||
992 | continue; | ||||
993 | } | ||||
994 | } | ||||
995 | |||||
996 | // Check these last, so we diagnose problems in operands first. | ||||
997 | Check(!MD.isTemporary(), "Expected no forward declarations!", &MD)do { if (!(!MD.isTemporary())) { CheckFailed("Expected no forward declarations!" , &MD); return; } } while (false); | ||||
998 | Check(MD.isResolved(), "All nodes should be resolved!", &MD)do { if (!(MD.isResolved())) { CheckFailed("All nodes should be resolved!" , &MD); return; } } while (false); | ||||
999 | } | ||||
1000 | |||||
1001 | void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) { | ||||
1002 | Check(MD.getValue(), "Expected valid value", &MD)do { if (!(MD.getValue())) { CheckFailed("Expected valid value" , &MD); return; } } while (false); | ||||
1003 | Check(!MD.getValue()->getType()->isMetadataTy(),do { if (!(!MD.getValue()->getType()->isMetadataTy())) { CheckFailed("Unexpected metadata round-trip through values", &MD, MD.getValue()); return; } } while (false) | ||||
1004 | "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); | ||||
1005 | |||||
1006 | auto *L = dyn_cast<LocalAsMetadata>(&MD); | ||||
1007 | if (!L) | ||||
1008 | return; | ||||
1009 | |||||
1010 | Check(F, "function-local metadata used outside a function", L)do { if (!(F)) { CheckFailed("function-local metadata used outside a function" , L); return; } } while (false); | ||||
1011 | |||||
1012 | // If this was an instruction, bb, or argument, verify that it is in the | ||||
1013 | // function that we expect. | ||||
1014 | Function *ActualF = nullptr; | ||||
1015 | if (Instruction *I = dyn_cast<Instruction>(L->getValue())) { | ||||
1016 | Check(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); | ||||
1017 | ActualF = I->getParent()->getParent(); | ||||
1018 | } else if (BasicBlock *BB = dyn_cast<BasicBlock>(L->getValue())) | ||||
1019 | ActualF = BB->getParent(); | ||||
1020 | else if (Argument *A = dyn_cast<Argument>(L->getValue())) | ||||
1021 | ActualF = A->getParent(); | ||||
1022 | assert(ActualF && "Unimplemented function local metadata case!")(static_cast <bool> (ActualF && "Unimplemented function local metadata case!" ) ? void (0) : __assert_fail ("ActualF && \"Unimplemented function local metadata case!\"" , "llvm/lib/IR/Verifier.cpp", 1022, __extension__ __PRETTY_FUNCTION__ )); | ||||
1023 | |||||
1024 | Check(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); | ||||
1025 | } | ||||
1026 | |||||
1027 | void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { | ||||
1028 | Metadata *MD = MDV.getMetadata(); | ||||
1029 | if (auto *N = dyn_cast<MDNode>(MD)) { | ||||
1030 | visitMDNode(*N, AreDebugLocsAllowed::No); | ||||
1031 | return; | ||||
1032 | } | ||||
1033 | |||||
1034 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
1035 | // avoids infinite recursion here, as well as being an optimization. | ||||
1036 | if (!MDNodes.insert(MD).second) | ||||
1037 | return; | ||||
1038 | |||||
1039 | if (auto *V = dyn_cast<ValueAsMetadata>(MD)) | ||||
1040 | visitValueAsMetadata(*V, F); | ||||
1041 | } | ||||
1042 | |||||
1043 | static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); } | ||||
1044 | static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); } | ||||
1045 | static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); } | ||||
1046 | |||||
1047 | void Verifier::visitDILocation(const DILocation &N) { | ||||
1048 | CheckDI(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) | ||||
1049 | "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); | ||||
1050 | if (auto *IA = N.getRawInlinedAt()) | ||||
1051 | CheckDI(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); | ||||
1052 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
1053 | CheckDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
1054 | } | ||||
1055 | |||||
1056 | void Verifier::visitGenericDINode(const GenericDINode &N) { | ||||
1057 | CheckDI(N.getTag(), "invalid tag", &N)do { if (!(N.getTag())) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
1058 | } | ||||
1059 | |||||
1060 | void Verifier::visitDIScope(const DIScope &N) { | ||||
1061 | if (auto *F = N.getRawFile()) | ||||
1062 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1063 | } | ||||
1064 | |||||
1065 | void Verifier::visitDISubrange(const DISubrange &N) { | ||||
1066 | CheckDI(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); | ||||
1067 | bool HasAssumedSizedArraySupport = dwarf::isFortran(CurrentSourceLang); | ||||
1068 | CheckDI(HasAssumedSizedArraySupport || N.getRawCountNode() ||do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
1069 | N.getRawUpperBound(),do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
1070 | "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); | ||||
1071 | CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("Subrange can have any one of count or upperBound", &N); return; } } while (false) | ||||
1072 | "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); | ||||
1073 | auto *CBound = N.getRawCountNode(); | ||||
1074 | CheckDI(!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) | ||||
1075 | 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) | ||||
1076 | "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); | ||||
1077 | auto Count = N.getCount(); | ||||
1078 | CheckDI(!Count || !isa<ConstantInt *>(Count) ||do { if (!(!Count || !isa<ConstantInt *>(Count) || cast <ConstantInt *>(Count)->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
1079 | cast<ConstantInt *>(Count)->getSExtValue() >= -1,do { if (!(!Count || !isa<ConstantInt *>(Count) || cast <ConstantInt *>(Count)->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
1080 | "invalid subrange count", &N)do { if (!(!Count || !isa<ConstantInt *>(Count) || cast <ConstantInt *>(Count)->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false); | ||||
1081 | auto *LBound = N.getRawLowerBound(); | ||||
1082 | CheckDI(!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) | ||||
1083 | 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) | ||||
1084 | "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) | ||||
1085 | &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); | ||||
1086 | auto *UBound = N.getRawUpperBound(); | ||||
1087 | CheckDI(!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) | ||||
1088 | 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) | ||||
1089 | "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) | ||||
1090 | &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); | ||||
1091 | auto *Stride = N.getRawStride(); | ||||
1092 | CheckDI(!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) | ||||
1093 | 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) | ||||
1094 | "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); | ||||
1095 | } | ||||
1096 | |||||
1097 | void Verifier::visitDIGenericSubrange(const DIGenericSubrange &N) { | ||||
1098 | CheckDI(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); | ||||
1099 | CheckDI(N.getRawCountNode() || N.getRawUpperBound(),do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false) | ||||
1100 | "GenericSubrange must contain count or upperBound", &N)do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false); | ||||
1101 | CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange can have any one of count or upperBound", & N); return; } } while (false) | ||||
1102 | "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); | ||||
1103 | auto *CBound = N.getRawCountNode(); | ||||
1104 | CheckDI(!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) | ||||
1105 | "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); | ||||
1106 | auto *LBound = N.getRawLowerBound(); | ||||
1107 | CheckDI(LBound, "GenericSubrange must contain lowerBound", &N)do { if (!(LBound)) { DebugInfoCheckFailed("GenericSubrange must contain lowerBound" , &N); return; } } while (false); | ||||
1108 | CheckDI(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) | ||||
1109 | "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) | ||||
1110 | &N)do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
1111 | auto *UBound = N.getRawUpperBound(); | ||||
1112 | CheckDI(!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) | ||||
1113 | "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) | ||||
1114 | &N)do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
1115 | auto *Stride = N.getRawStride(); | ||||
1116 | CheckDI(Stride, "GenericSubrange must contain stride", &N)do { if (!(Stride)) { DebugInfoCheckFailed("GenericSubrange must contain stride" , &N); return; } } while (false); | ||||
1117 | CheckDI(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) | ||||
1118 | "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); | ||||
1119 | } | ||||
1120 | |||||
1121 | void Verifier::visitDIEnumerator(const DIEnumerator &N) { | ||||
1122 | CheckDI(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_enumerator)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1123 | } | ||||
1124 | |||||
1125 | void Verifier::visitDIBasicType(const DIBasicType &N) { | ||||
1126 | CheckDI(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) | ||||
1127 | 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) | ||||
1128 | 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) | ||||
1129 | "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); | ||||
1130 | } | ||||
1131 | |||||
1132 | void Verifier::visitDIStringType(const DIStringType &N) { | ||||
1133 | CheckDI(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); | ||||
1134 | CheckDI(!(N.isBigEndian() && N.isLittleEndian()), "has conflicting flags",do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false) | ||||
1135 | &N)do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false); | ||||
1136 | } | ||||
1137 | |||||
1138 | void Verifier::visitDIDerivedType(const DIDerivedType &N) { | ||||
1139 | // Common scope checks. | ||||
1140 | visitDIScope(N); | ||||
1141 | |||||
1142 | CheckDI(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_immutable_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) | ||||
1143 | 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_immutable_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) | ||||
1144 | 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_immutable_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) | ||||
1145 | 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_immutable_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) | ||||
1146 | 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_immutable_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) | ||||
1147 | 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_immutable_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) | ||||
1148 | N.getTag() == dwarf::DW_TAG_immutable_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_immutable_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) | ||||
1149 | 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_immutable_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) | ||||
1150 | 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_immutable_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) | ||||
1151 | 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_immutable_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) | ||||
1152 | 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_immutable_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) | ||||
1153 | 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_immutable_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) | ||||
1154 | 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_immutable_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) | ||||
1155 | 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_immutable_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) | ||||
1156 | "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_immutable_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); | ||||
1157 | if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) { | ||||
1158 | CheckDI(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) | ||||
1159 | N.getRawExtraData())do { if (!(isType(N.getRawExtraData()))) { DebugInfoCheckFailed ("invalid pointer to member type", &N, N.getRawExtraData( )); return; } } while (false); | ||||
1160 | } | ||||
1161 | |||||
1162 | if (N.getTag() == dwarf::DW_TAG_set_type) { | ||||
1163 | if (auto *T = N.getRawBaseType()) { | ||||
1164 | auto *Enum = dyn_cast_or_null<DICompositeType>(T); | ||||
1165 | auto *Basic = dyn_cast_or_null<DIBasicType>(T); | ||||
1166 | CheckDI(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) | ||||
1167 | (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) | ||||
1168 | (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) | ||||
1169 | 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) | ||||
1170 | 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) | ||||
1171 | 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) | ||||
1172 | 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) | ||||
1173 | "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); | ||||
1174 | } | ||||
1175 | } | ||||
1176 | |||||
1177 | CheckDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
1178 | CheckDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
1179 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
1180 | |||||
1181 | if (N.getDWARFAddressSpace()) { | ||||
1182 | CheckDI(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) | ||||
1183 | 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) | ||||
1184 | 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) | ||||
1185 | "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) | ||||
1186 | &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); | ||||
1187 | } | ||||
1188 | } | ||||
1189 | |||||
1190 | /// Detect mutually exclusive flags. | ||||
1191 | static bool hasConflictingReferenceFlags(unsigned Flags) { | ||||
1192 | return ((Flags & DINode::FlagLValueReference) && | ||||
1193 | (Flags & DINode::FlagRValueReference)) || | ||||
1194 | ((Flags & DINode::FlagTypePassByValue) && | ||||
1195 | (Flags & DINode::FlagTypePassByReference)); | ||||
1196 | } | ||||
1197 | |||||
1198 | void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) { | ||||
1199 | auto *Params = dyn_cast<MDTuple>(&RawParams); | ||||
1200 | CheckDI(Params, "invalid template params", &N, &RawParams)do { if (!(Params)) { DebugInfoCheckFailed("invalid template params" , &N, &RawParams); return; } } while (false); | ||||
1201 | for (Metadata *Op : Params->operands()) { | ||||
1202 | CheckDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false) | ||||
1203 | &N, Params, Op)do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false); | ||||
1204 | } | ||||
1205 | } | ||||
1206 | |||||
1207 | void Verifier::visitDICompositeType(const DICompositeType &N) { | ||||
1208 | // Common scope checks. | ||||
1209 | visitDIScope(N); | ||||
1210 | |||||
1211 | CheckDI(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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1212 | 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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1213 | 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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1214 | 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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1215 | 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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1216 | 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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1217 | N.getTag() == dwarf::DW_TAG_namelist,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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
1218 | "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 || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1219 | |||||
1220 | CheckDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
1221 | CheckDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
1222 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
1223 | |||||
1224 | CheckDI(!N.getRawElements() || isa<MDTuple>(N.getRawElements()),do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false) | ||||
1225 | "invalid composite elements", &N, N.getRawElements())do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false); | ||||
1226 | CheckDI(isType(N.getRawVTableHolder()), "invalid vtable holder", &N,do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false) | ||||
1227 | N.getRawVTableHolder())do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false); | ||||
1228 | CheckDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
1229 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
1230 | unsigned DIBlockByRefStruct = 1 << 4; | ||||
1231 | CheckDI((N.getFlags() & DIBlockByRefStruct) == 0,do { if (!((N.getFlags() & DIBlockByRefStruct) == 0)) { DebugInfoCheckFailed ("DIBlockByRefStruct on DICompositeType is no longer supported" , &N); return; } } while (false) | ||||
1232 | "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); | ||||
1233 | |||||
1234 | if (N.isVector()) { | ||||
1235 | const DINodeArray Elements = N.getElements(); | ||||
1236 | CheckDI(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) | ||||
1237 | 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) | ||||
1238 | "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); | ||||
1239 | } | ||||
1240 | |||||
1241 | if (auto *Params = N.getRawTemplateParams()) | ||||
1242 | visitTemplateParams(N, *Params); | ||||
1243 | |||||
1244 | if (auto *D = N.getRawDiscriminator()) { | ||||
1245 | CheckDI(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) | ||||
1246 | "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); | ||||
1247 | } | ||||
1248 | |||||
1249 | if (N.getRawDataLocation()) { | ||||
1250 | CheckDI(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) | ||||
1251 | "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); | ||||
1252 | } | ||||
1253 | |||||
1254 | if (N.getRawAssociated()) { | ||||
1255 | CheckDI(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) | ||||
1256 | "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); | ||||
1257 | } | ||||
1258 | |||||
1259 | if (N.getRawAllocated()) { | ||||
1260 | CheckDI(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) | ||||
1261 | "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); | ||||
1262 | } | ||||
1263 | |||||
1264 | if (N.getRawRank()) { | ||||
1265 | CheckDI(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 ) | ||||
1266 | "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 ); | ||||
1267 | } | ||||
1268 | } | ||||
1269 | |||||
1270 | void Verifier::visitDISubroutineType(const DISubroutineType &N) { | ||||
1271 | CheckDI(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); | ||||
1272 | if (auto *Types = N.getRawTypeArray()) { | ||||
1273 | CheckDI(isa<MDTuple>(Types), "invalid composite elements", &N, Types)do { if (!(isa<MDTuple>(Types))) { DebugInfoCheckFailed ("invalid composite elements", &N, Types); return; } } while (false); | ||||
1274 | for (Metadata *Ty : N.getTypeArray()->operands()) { | ||||
1275 | CheckDI(isType(Ty), "invalid subroutine type ref", &N, Types, Ty)do { if (!(isType(Ty))) { DebugInfoCheckFailed("invalid subroutine type ref" , &N, Types, Ty); return; } } while (false); | ||||
1276 | } | ||||
1277 | } | ||||
1278 | CheckDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
1279 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
1280 | } | ||||
1281 | |||||
1282 | void Verifier::visitDIFile(const DIFile &N) { | ||||
1283 | CheckDI(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); | ||||
1284 | std::optional<DIFile::ChecksumInfo<StringRef>> Checksum = N.getChecksum(); | ||||
1285 | if (Checksum) { | ||||
1286 | CheckDI(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last,do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false) | ||||
1287 | "invalid checksum kind", &N)do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false); | ||||
1288 | size_t Size; | ||||
1289 | switch (Checksum->Kind) { | ||||
1290 | case DIFile::CSK_MD5: | ||||
1291 | Size = 32; | ||||
1292 | break; | ||||
1293 | case DIFile::CSK_SHA1: | ||||
1294 | Size = 40; | ||||
1295 | break; | ||||
1296 | case DIFile::CSK_SHA256: | ||||
1297 | Size = 64; | ||||
1298 | break; | ||||
1299 | } | ||||
1300 | CheckDI(Checksum->Value.size() == Size, "invalid checksum length", &N)do { if (!(Checksum->Value.size() == Size)) { DebugInfoCheckFailed ("invalid checksum length", &N); return; } } while (false ); | ||||
1301 | CheckDI(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) | ||||
1302 | "invalid checksum", &N)do { if (!(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos)) { DebugInfoCheckFailed("invalid checksum", &N); return; } } while (false); | ||||
1303 | } | ||||
1304 | } | ||||
1305 | |||||
1306 | void Verifier::visitDICompileUnit(const DICompileUnit &N) { | ||||
1307 | CheckDI(N.isDistinct(), "compile units must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("compile units must be distinct" , &N); return; } } while (false); | ||||
1308 | CheckDI(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); | ||||
1309 | |||||
1310 | // Don't bother verifying the compilation directory or producer string | ||||
1311 | // as those could be empty. | ||||
1312 | CheckDI(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) | ||||
1313 | N.getRawFile())do { if (!(N.getRawFile() && isa<DIFile>(N.getRawFile ()))) { DebugInfoCheckFailed("invalid file", &N, N.getRawFile ()); return; } } while (false); | ||||
1314 | CheckDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false) | ||||
1315 | N.getFile())do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false); | ||||
1316 | |||||
1317 | CurrentSourceLang = (dwarf::SourceLanguage)N.getSourceLanguage(); | ||||
1318 | |||||
1319 | verifySourceDebugInfo(N, *N.getFile()); | ||||
1320 | |||||
1321 | CheckDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false) | ||||
1322 | "invalid emission kind", &N)do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false); | ||||
1323 | |||||
1324 | if (auto *Array = N.getRawEnumTypes()) { | ||||
1325 | CheckDI(isa<MDTuple>(Array), "invalid enum list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid enum list", &N, Array); return; } } while (false ); | ||||
1326 | for (Metadata *Op : N.getEnumTypes()->operands()) { | ||||
1327 | auto *Enum = dyn_cast_or_null<DICompositeType>(Op); | ||||
1328 | CheckDI(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) | ||||
1329 | "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); | ||||
1330 | } | ||||
1331 | } | ||||
1332 | if (auto *Array = N.getRawRetainedTypes()) { | ||||
1333 | CheckDI(isa<MDTuple>(Array), "invalid retained type list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid retained type list", &N, Array); return; } } while (false); | ||||
1334 | for (Metadata *Op : N.getRetainedTypes()->operands()) { | ||||
1335 | CheckDI(do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
1336 | Op && (isa<DIType>(Op) || (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) | ||||
1337 | !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) | ||||
1338 | "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); | ||||
1339 | } | ||||
1340 | } | ||||
1341 | if (auto *Array = N.getRawGlobalVariables()) { | ||||
1342 | CheckDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid global variable list", &N, Array); return; } } while (false); | ||||
1343 | for (Metadata *Op : N.getGlobalVariables()->operands()) { | ||||
1344 | CheckDI(Op && (isa<DIGlobalVariableExpression>(Op)),do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false) | ||||
1345 | "invalid global variable ref", &N, Op)do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false); | ||||
1346 | } | ||||
1347 | } | ||||
1348 | if (auto *Array = N.getRawImportedEntities()) { | ||||
1349 | CheckDI(isa<MDTuple>(Array), "invalid imported entity list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid imported entity list", &N, Array); return; } } while (false); | ||||
1350 | for (Metadata *Op : N.getImportedEntities()->operands()) { | ||||
1351 | CheckDI(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref",do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false) | ||||
1352 | &N, Op)do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false); | ||||
1353 | } | ||||
1354 | } | ||||
1355 | if (auto *Array = N.getRawMacros()) { | ||||
1356 | CheckDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
1357 | for (Metadata *Op : N.getMacros()->operands()) { | ||||
1358 | CheckDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
1359 | } | ||||
1360 | } | ||||
1361 | CUVisited.insert(&N); | ||||
1362 | } | ||||
1363 | |||||
1364 | void Verifier::visitDISubprogram(const DISubprogram &N) { | ||||
1365 | CheckDI(N.getTag() == dwarf::DW_TAG_subprogram, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subprogram)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1366 | CheckDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
1367 | if (auto *F = N.getRawFile()) | ||||
1368 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1369 | else | ||||
1370 | CheckDI(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); | ||||
1371 | if (auto *T = N.getRawType()) | ||||
1372 | CheckDI(isa<DISubroutineType>(T), "invalid subroutine type", &N, T)do { if (!(isa<DISubroutineType>(T))) { DebugInfoCheckFailed ("invalid subroutine type", &N, T); return; } } while (false ); | ||||
1373 | CheckDI(isType(N.getRawContainingType()), "invalid containing type", &N,do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false) | ||||
1374 | N.getRawContainingType())do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false); | ||||
1375 | if (auto *Params = N.getRawTemplateParams()) | ||||
1376 | visitTemplateParams(N, *Params); | ||||
1377 | if (auto *S = N.getRawDeclaration()) | ||||
1378 | CheckDI(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) | ||||
1379 | "invalid subprogram declaration", &N, S)do { if (!(isa<DISubprogram>(S) && !cast<DISubprogram >(S)->isDefinition())) { DebugInfoCheckFailed("invalid subprogram declaration" , &N, S); return; } } while (false); | ||||
1380 | if (auto *RawNode = N.getRawRetainedNodes()) { | ||||
1381 | auto *Node = dyn_cast<MDTuple>(RawNode); | ||||
1382 | CheckDI(Node, "invalid retained nodes list", &N, RawNode)do { if (!(Node)) { DebugInfoCheckFailed("invalid retained nodes list" , &N, RawNode); return; } } while (false); | ||||
1383 | for (Metadata *Op : Node->operands()) { | ||||
1384 | CheckDI(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) | ||||
1385 | "invalid retained nodes, expected DILocalVariable or DILabel", &N,do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false) | ||||
1386 | 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); | ||||
1387 | } | ||||
1388 | } | ||||
1389 | CheckDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
1390 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
1391 | |||||
1392 | auto *Unit = N.getRawUnit(); | ||||
1393 | if (N.isDefinition()) { | ||||
1394 | // Subprogram definitions (not part of the type hierarchy). | ||||
1395 | CheckDI(N.isDistinct(), "subprogram definitions must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("subprogram definitions must be distinct" , &N); return; } } while (false); | ||||
1396 | CheckDI(Unit, "subprogram definitions must have a compile unit", &N)do { if (!(Unit)) { DebugInfoCheckFailed("subprogram definitions must have a compile unit" , &N); return; } } while (false); | ||||
1397 | CheckDI(isa<DICompileUnit>(Unit), "invalid unit type", &N, Unit)do { if (!(isa<DICompileUnit>(Unit))) { DebugInfoCheckFailed ("invalid unit type", &N, Unit); return; } } while (false ); | ||||
1398 | if (N.getFile()) | ||||
1399 | verifySourceDebugInfo(*N.getUnit(), *N.getFile()); | ||||
1400 | } else { | ||||
1401 | // Subprogram declarations (part of the type hierarchy). | ||||
1402 | CheckDI(!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); | ||||
1403 | CheckDI(!N.getRawDeclaration(),do { if (!(!N.getRawDeclaration())) { DebugInfoCheckFailed("subprogram declaration must not have a declaration field" ); return; } } while (false) | ||||
1404 | "subprogram declaration must not have a declaration field")do { if (!(!N.getRawDeclaration())) { DebugInfoCheckFailed("subprogram declaration must not have a declaration field" ); return; } } while (false); | ||||
1405 | } | ||||
1406 | |||||
1407 | if (auto *RawThrownTypes = N.getRawThrownTypes()) { | ||||
1408 | auto *ThrownTypes = dyn_cast<MDTuple>(RawThrownTypes); | ||||
1409 | CheckDI(ThrownTypes, "invalid thrown types list", &N, RawThrownTypes)do { if (!(ThrownTypes)) { DebugInfoCheckFailed("invalid thrown types list" , &N, RawThrownTypes); return; } } while (false); | ||||
1410 | for (Metadata *Op : ThrownTypes->operands()) | ||||
1411 | CheckDI(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) | ||||
1412 | Op)do { if (!(Op && isa<DIType>(Op))) { DebugInfoCheckFailed ("invalid thrown type", &N, ThrownTypes, Op); return; } } while (false); | ||||
1413 | } | ||||
1414 | |||||
1415 | if (N.areAllCallsDescribed()) | ||||
1416 | CheckDI(N.isDefinition(),do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false) | ||||
1417 | "DIFlagAllCallsDescribed must be attached to a definition")do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false); | ||||
1418 | } | ||||
1419 | |||||
1420 | void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { | ||||
1421 | CheckDI(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); | ||||
1422 | CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false) | ||||
1423 | "invalid local scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false); | ||||
1424 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
1425 | CheckDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
1426 | } | ||||
1427 | |||||
1428 | void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { | ||||
1429 | visitDILexicalBlockBase(N); | ||||
1430 | |||||
1431 | CheckDI(N.getLine() || !N.getColumn(),do { if (!(N.getLine() || !N.getColumn())) { DebugInfoCheckFailed ("cannot have column info without line info", &N); return ; } } while (false) | ||||
1432 | "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); | ||||
1433 | } | ||||
1434 | |||||
1435 | void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { | ||||
1436 | visitDILexicalBlockBase(N); | ||||
1437 | } | ||||
1438 | |||||
1439 | void Verifier::visitDICommonBlock(const DICommonBlock &N) { | ||||
1440 | CheckDI(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); | ||||
1441 | if (auto *S = N.getRawScope()) | ||||
1442 | CheckDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
1443 | if (auto *S = N.getRawDecl()) | ||||
1444 | CheckDI(isa<DIGlobalVariable>(S), "invalid declaration", &N, S)do { if (!(isa<DIGlobalVariable>(S))) { DebugInfoCheckFailed ("invalid declaration", &N, S); return; } } while (false); | ||||
1445 | } | ||||
1446 | |||||
1447 | void Verifier::visitDINamespace(const DINamespace &N) { | ||||
1448 | CheckDI(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_namespace)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1449 | if (auto *S = N.getRawScope()) | ||||
1450 | CheckDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
1451 | } | ||||
1452 | |||||
1453 | void Verifier::visitDIMacro(const DIMacro &N) { | ||||
1454 | CheckDI(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) | ||||
1455 | 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) | ||||
1456 | "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); | ||||
1457 | CheckDI(!N.getName().empty(), "anonymous macro", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous macro" , &N); return; } } while (false); | ||||
1458 | if (!N.getValue().empty()) { | ||||
1459 | assert(N.getValue().data()[0] != ' ' && "Macro value has a space prefix")(static_cast <bool> (N.getValue().data()[0] != ' ' && "Macro value has a space prefix") ? void (0) : __assert_fail ("N.getValue().data()[0] != ' ' && \"Macro value has a space prefix\"" , "llvm/lib/IR/Verifier.cpp", 1459, __extension__ __PRETTY_FUNCTION__ )); | ||||
1460 | } | ||||
1461 | } | ||||
1462 | |||||
1463 | void Verifier::visitDIMacroFile(const DIMacroFile &N) { | ||||
1464 | CheckDI(N.getMacinfoType() == dwarf::DW_MACINFO_start_file,do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false) | ||||
1465 | "invalid macinfo type", &N)do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false); | ||||
1466 | if (auto *F = N.getRawFile()) | ||||
1467 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1468 | |||||
1469 | if (auto *Array = N.getRawElements()) { | ||||
1470 | CheckDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
1471 | for (Metadata *Op : N.getElements()->operands()) { | ||||
1472 | CheckDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
1473 | } | ||||
1474 | } | ||||
1475 | } | ||||
1476 | |||||
1477 | void Verifier::visitDIArgList(const DIArgList &N) { | ||||
1478 | CheckDI(!N.getNumOperands(),do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
1479 | "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) | ||||
1480 | "ValueAsMetadata",do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
1481 | &N)do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false); | ||||
1482 | } | ||||
1483 | |||||
1484 | void Verifier::visitDIModule(const DIModule &N) { | ||||
1485 | CheckDI(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_module)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1486 | CheckDI(!N.getName().empty(), "anonymous module", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous module" , &N); return; } } while (false); | ||||
1487 | } | ||||
1488 | |||||
1489 | void Verifier::visitDITemplateParameter(const DITemplateParameter &N) { | ||||
1490 | CheckDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
1491 | } | ||||
1492 | |||||
1493 | void Verifier::visitDITemplateTypeParameter(const DITemplateTypeParameter &N) { | ||||
1494 | visitDITemplateParameter(N); | ||||
1495 | |||||
1496 | CheckDI(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) | ||||
1497 | &N)do { if (!(N.getTag() == dwarf::DW_TAG_template_type_parameter )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
1498 | } | ||||
1499 | |||||
1500 | void Verifier::visitDITemplateValueParameter( | ||||
1501 | const DITemplateValueParameter &N) { | ||||
1502 | visitDITemplateParameter(N); | ||||
1503 | |||||
1504 | CheckDI(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) | ||||
1505 | 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) | ||||
1506 | 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) | ||||
1507 | "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); | ||||
1508 | } | ||||
1509 | |||||
1510 | void Verifier::visitDIVariable(const DIVariable &N) { | ||||
1511 | if (auto *S = N.getRawScope()) | ||||
1512 | CheckDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
1513 | if (auto *F = N.getRawFile()) | ||||
1514 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1515 | } | ||||
1516 | |||||
1517 | void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { | ||||
1518 | // Checks common to all variables. | ||||
1519 | visitDIVariable(N); | ||||
1520 | |||||
1521 | CheckDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1522 | CheckDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
1523 | // Check only if the global variable is not an extern | ||||
1524 | if (N.isDefinition()) | ||||
1525 | CheckDI(N.getType(), "missing global variable type", &N)do { if (!(N.getType())) { DebugInfoCheckFailed("missing global variable type" , &N); return; } } while (false); | ||||
1526 | if (auto *Member = N.getRawStaticDataMemberDeclaration()) { | ||||
1527 | CheckDI(isa<DIDerivedType>(Member),do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false) | ||||
1528 | "invalid static data member declaration", &N, Member)do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false); | ||||
1529 | } | ||||
1530 | } | ||||
1531 | |||||
1532 | void Verifier::visitDILocalVariable(const DILocalVariable &N) { | ||||
1533 | // Checks common to all variables. | ||||
1534 | visitDIVariable(N); | ||||
1535 | |||||
1536 | CheckDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
1537 | CheckDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1538 | CheckDI(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) | ||||
1539 | "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); | ||||
1540 | if (auto Ty = N.getType()) | ||||
1541 | CheckDI(!isa<DISubroutineType>(Ty), "invalid type", &N, N.getType())do { if (!(!isa<DISubroutineType>(Ty))) { DebugInfoCheckFailed ("invalid type", &N, N.getType()); return; } } while (false ); | ||||
1542 | } | ||||
1543 | |||||
1544 | void Verifier::visitDIAssignID(const DIAssignID &N) { | ||||
1545 | CheckDI(!N.getNumOperands(), "DIAssignID has no arguments", &N)do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIAssignID has no arguments" , &N); return; } } while (false); | ||||
1546 | CheckDI(N.isDistinct(), "DIAssignID must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("DIAssignID must be distinct" , &N); return; } } while (false); | ||||
1547 | } | ||||
1548 | |||||
1549 | void Verifier::visitDILabel(const DILabel &N) { | ||||
1550 | if (auto *S = N.getRawScope()) | ||||
1551 | CheckDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
1552 | if (auto *F = N.getRawFile()) | ||||
1553 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1554 | |||||
1555 | CheckDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_label)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
1556 | CheckDI(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) | ||||
1557 | "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); | ||||
1558 | } | ||||
1559 | |||||
1560 | void Verifier::visitDIExpression(const DIExpression &N) { | ||||
1561 | CheckDI(N.isValid(), "invalid expression", &N)do { if (!(N.isValid())) { DebugInfoCheckFailed("invalid expression" , &N); return; } } while (false); | ||||
1562 | } | ||||
1563 | |||||
1564 | void Verifier::visitDIGlobalVariableExpression( | ||||
1565 | const DIGlobalVariableExpression &GVE) { | ||||
1566 | CheckDI(GVE.getVariable(), "missing variable")do { if (!(GVE.getVariable())) { DebugInfoCheckFailed("missing variable" ); return; } } while (false); | ||||
1567 | if (auto *Var = GVE.getVariable()) | ||||
1568 | visitDIGlobalVariable(*Var); | ||||
1569 | if (auto *Expr = GVE.getExpression()) { | ||||
1570 | visitDIExpression(*Expr); | ||||
1571 | if (auto Fragment = Expr->getFragmentInfo()) | ||||
1572 | verifyFragmentExpression(*GVE.getVariable(), *Fragment, &GVE); | ||||
1573 | } | ||||
1574 | } | ||||
1575 | |||||
1576 | void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { | ||||
1577 | CheckDI(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); | ||||
1578 | if (auto *T = N.getRawType()) | ||||
1579 | CheckDI(isType(T), "invalid type ref", &N, T)do { if (!(isType(T))) { DebugInfoCheckFailed("invalid type ref" , &N, T); return; } } while (false); | ||||
1580 | if (auto *F = N.getRawFile()) | ||||
1581 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
1582 | } | ||||
1583 | |||||
1584 | void Verifier::visitDIImportedEntity(const DIImportedEntity &N) { | ||||
1585 | CheckDI(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) | ||||
1586 | 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) | ||||
1587 | "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); | ||||
1588 | if (auto *S = N.getRawScope()) | ||||
1589 | CheckDI(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); | ||||
1590 | CheckDI(isDINode(N.getRawEntity()), "invalid imported entity", &N,do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false) | ||||
1591 | N.getRawEntity())do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false); | ||||
1592 | } | ||||
1593 | |||||
1594 | void Verifier::visitComdat(const Comdat &C) { | ||||
1595 | // In COFF the Module is invalid if the GlobalValue has private linkage. | ||||
1596 | // Entities with private linkage don't have entries in the symbol table. | ||||
1597 | if (TT.isOSBinFormatCOFF()) | ||||
1598 | if (const GlobalValue *GV = M.getNamedValue(C.getName())) | ||||
1599 | Check(!GV->hasPrivateLinkage(), "comdat global value has private linkage",do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false) | ||||
1600 | GV)do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false); | ||||
1601 | } | ||||
1602 | |||||
1603 | void Verifier::visitModuleIdents() { | ||||
1604 | const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); | ||||
1605 | if (!Idents) | ||||
1606 | return; | ||||
1607 | |||||
1608 | // llvm.ident takes a list of metadata entry. Each entry has only one string. | ||||
1609 | // Scan each llvm.ident entry and make sure that this requirement is met. | ||||
1610 | for (const MDNode *N : Idents->operands()) { | ||||
1611 | Check(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.ident metadata" , N); return; } } while (false) | ||||
1612 | "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); | ||||
1613 | Check(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) | ||||
1614 | ("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) | ||||
1615 | "(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) | ||||
1616 | 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); | ||||
1617 | } | ||||
1618 | } | ||||
1619 | |||||
1620 | void Verifier::visitModuleCommandLines() { | ||||
1621 | const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline"); | ||||
1622 | if (!CommandLines) | ||||
1623 | return; | ||||
1624 | |||||
1625 | // llvm.commandline takes a list of metadata entry. Each entry has only one | ||||
1626 | // string. Scan each llvm.commandline entry and make sure that this | ||||
1627 | // requirement is met. | ||||
1628 | for (const MDNode *N : CommandLines->operands()) { | ||||
1629 | Check(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.commandline metadata" , N); return; } } while (false) | ||||
1630 | "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); | ||||
1631 | Check(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) | ||||
1632 | ("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) | ||||
1633 | "(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) | ||||
1634 | 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); | ||||
1635 | } | ||||
1636 | } | ||||
1637 | |||||
1638 | void Verifier::visitModuleFlags() { | ||||
1639 | const NamedMDNode *Flags = M.getModuleFlagsMetadata(); | ||||
1640 | if (!Flags) return; | ||||
1641 | |||||
1642 | // Scan each flag, and track the flags and requirements. | ||||
1643 | DenseMap<const MDString*, const MDNode*> SeenIDs; | ||||
1644 | SmallVector<const MDNode*, 16> Requirements; | ||||
1645 | for (const MDNode *MDN : Flags->operands()) | ||||
1646 | visitModuleFlag(MDN, SeenIDs, Requirements); | ||||
1647 | |||||
1648 | // Validate that the requirements in the module are valid. | ||||
1649 | for (const MDNode *Requirement : Requirements) { | ||||
1650 | const MDString *Flag = cast<MDString>(Requirement->getOperand(0)); | ||||
1651 | const Metadata *ReqValue = Requirement->getOperand(1); | ||||
1652 | |||||
1653 | const MDNode *Op = SeenIDs.lookup(Flag); | ||||
1654 | if (!Op) { | ||||
1655 | CheckFailed("invalid requirement on flag, flag is not present in module", | ||||
1656 | Flag); | ||||
1657 | continue; | ||||
1658 | } | ||||
1659 | |||||
1660 | if (Op->getOperand(2) != ReqValue) { | ||||
1661 | CheckFailed(("invalid requirement on flag, " | ||||
1662 | "flag does not have the required value"), | ||||
1663 | Flag); | ||||
1664 | continue; | ||||
1665 | } | ||||
1666 | } | ||||
1667 | } | ||||
1668 | |||||
1669 | void | ||||
1670 | Verifier::visitModuleFlag(const MDNode *Op, | ||||
1671 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
1672 | SmallVectorImpl<const MDNode *> &Requirements) { | ||||
1673 | // Each module flag should have three arguments, the merge behavior (a | ||||
1674 | // constant int), the flag ID (an MDString), and the value. | ||||
1675 | Check(Op->getNumOperands() == 3,do { if (!(Op->getNumOperands() == 3)) { CheckFailed("incorrect number of operands in module flag" , Op); return; } } while (false) | ||||
1676 | "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); | ||||
1677 | Module::ModFlagBehavior MFB; | ||||
1678 | if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { | ||||
1679 | Check(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) | ||||
1680 | "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) | ||||
1681 | 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); | ||||
1682 | Check(false,do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false) | ||||
1683 | "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) | ||||
1684 | Op->getOperand(0))do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false); | ||||
1685 | } | ||||
1686 | MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1)); | ||||
1687 | Check(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) | ||||
1688 | Op->getOperand(1))do { if (!(ID)) { CheckFailed("invalid ID operand in module flag (expected metadata string)" , Op->getOperand(1)); return; } } while (false); | ||||
1689 | |||||
1690 | // Check the values for behaviors with additional requirements. | ||||
1691 | switch (MFB) { | ||||
1692 | case Module::Error: | ||||
1693 | case Module::Warning: | ||||
1694 | case Module::Override: | ||||
1695 | // These behavior types accept any value. | ||||
1696 | break; | ||||
1697 | |||||
1698 | case Module::Min: { | ||||
1699 | auto *V = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
1700 | Check(V && V->getValue().isNonNegative(),do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false) | ||||
1701 | "invalid value for 'min' module flag (expected constant non-negative "do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false) | ||||
1702 | "integer)",do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false) | ||||
1703 | Op->getOperand(2))do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false); | ||||
1704 | break; | ||||
1705 | } | ||||
1706 | |||||
1707 | case Module::Max: { | ||||
1708 | Check(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) | ||||
1709 | "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) | ||||
1710 | 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); | ||||
1711 | break; | ||||
1712 | } | ||||
1713 | |||||
1714 | case Module::Require: { | ||||
1715 | // The value should itself be an MDNode with two operands, a flag ID (an | ||||
1716 | // MDString), and a value. | ||||
1717 | MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2)); | ||||
1718 | Check(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) | ||||
1719 | "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) | ||||
1720 | 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); | ||||
1721 | Check(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) | ||||
1722 | ("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) | ||||
1723 | "(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) | ||||
1724 | 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); | ||||
1725 | |||||
1726 | // Append it to the list of requirements, to check once all module flags are | ||||
1727 | // scanned. | ||||
1728 | Requirements.push_back(Value); | ||||
1729 | break; | ||||
1730 | } | ||||
1731 | |||||
1732 | case Module::Append: | ||||
1733 | case Module::AppendUnique: { | ||||
1734 | // These behavior types require the operand be an MDNode. | ||||
1735 | Check(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) | ||||
1736 | "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) | ||||
1737 | "(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) | ||||
1738 | 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); | ||||
1739 | break; | ||||
1740 | } | ||||
1741 | } | ||||
1742 | |||||
1743 | // Unless this is a "requires" flag, check the ID is unique. | ||||
1744 | if (MFB != Module::Require) { | ||||
1745 | bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; | ||||
1746 | Check(Inserted,do { if (!(Inserted)) { CheckFailed("module flag identifiers must be unique (or of 'require' type)" , ID); return; } } while (false) | ||||
1747 | "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); | ||||
1748 | } | ||||
1749 | |||||
1750 | if (ID->getString() == "wchar_size") { | ||||
1751 | ConstantInt *Value | ||||
1752 | = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
1753 | Check(Value, "wchar_size metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("wchar_size metadata requires constant integer argument" ); return; } } while (false); | ||||
1754 | } | ||||
1755 | |||||
1756 | if (ID->getString() == "Linker Options") { | ||||
1757 | // If the llvm.linker.options named metadata exists, we assume that the | ||||
1758 | // bitcode reader has upgraded the module flag. Otherwise the flag might | ||||
1759 | // have been created by a client directly. | ||||
1760 | Check(M.getNamedMetadata("llvm.linker.options"),do { if (!(M.getNamedMetadata("llvm.linker.options"))) { CheckFailed ("'Linker Options' named metadata no longer supported"); return ; } } while (false) | ||||
1761 | "'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); | ||||
1762 | } | ||||
1763 | |||||
1764 | if (ID->getString() == "SemanticInterposition") { | ||||
1765 | ConstantInt *Value = | ||||
1766 | mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
1767 | Check(Value,do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false) | ||||
1768 | "SemanticInterposition metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false); | ||||
1769 | } | ||||
1770 | |||||
1771 | if (ID->getString() == "CG Profile") { | ||||
1772 | for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands()) | ||||
1773 | visitModuleFlagCGProfileEntry(MDO); | ||||
1774 | } | ||||
1775 | } | ||||
1776 | |||||
1777 | void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) { | ||||
1778 | auto CheckFunction = [&](const MDOperand &FuncMDO) { | ||||
1779 | if (!FuncMDO) | ||||
1780 | return; | ||||
1781 | auto F = dyn_cast<ValueAsMetadata>(FuncMDO); | ||||
1782 | Check(F && isa<Function>(F->getValue()->stripPointerCasts()),do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false) | ||||
1783 | "expected a Function or null", FuncMDO)do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false); | ||||
1784 | }; | ||||
1785 | auto Node = dyn_cast_or_null<MDNode>(MDO); | ||||
1786 | Check(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO)do { if (!(Node && Node->getNumOperands() == 3)) { CheckFailed("expected a MDNode triple", MDO); return; } } while (false); | ||||
1787 | CheckFunction(Node->getOperand(0)); | ||||
1788 | CheckFunction(Node->getOperand(1)); | ||||
1789 | auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2)); | ||||
1790 | Check(Count && Count->getType()->isIntegerTy(),do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false) | ||||
1791 | "expected an integer constant", Node->getOperand(2))do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false); | ||||
1792 | } | ||||
1793 | |||||
1794 | void Verifier::verifyAttributeTypes(AttributeSet Attrs, const Value *V) { | ||||
1795 | for (Attribute A : Attrs) { | ||||
1796 | |||||
1797 | if (A.isStringAttribute()) { | ||||
1798 | #define GET_ATTR_NAMES | ||||
1799 | #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) | ||||
1800 | #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \ | ||||
1801 | if (A.getKindAsString() == #DISPLAY_NAME) { \ | ||||
1802 | auto V = A.getValueAsString(); \ | ||||
1803 | if (!(V.empty() || V == "true" || V == "false")) \ | ||||
1804 | CheckFailed("invalid value for '" #DISPLAY_NAME "' attribute: " + V + \ | ||||
1805 | ""); \ | ||||
1806 | } | ||||
1807 | |||||
1808 | #include "llvm/IR/Attributes.inc" | ||||
1809 | continue; | ||||
1810 | } | ||||
1811 | |||||
1812 | if (A.isIntAttribute() != Attribute::isIntAttrKind(A.getKindAsEnum())) { | ||||
1813 | CheckFailed("Attribute '" + A.getAsString() + "' should have an Argument", | ||||
1814 | V); | ||||
1815 | return; | ||||
1816 | } | ||||
1817 | } | ||||
1818 | } | ||||
1819 | |||||
1820 | // VerifyParameterAttrs - Check the given attributes for an argument or return | ||||
1821 | // value of the specified type. The value V is printed in error messages. | ||||
1822 | void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, | ||||
1823 | const Value *V) { | ||||
1824 | if (!Attrs.hasAttributes()) | ||||
1825 | return; | ||||
1826 | |||||
1827 | verifyAttributeTypes(Attrs, V); | ||||
1828 | |||||
1829 | for (Attribute Attr : Attrs) | ||||
1830 | Check(Attr.isStringAttribute() ||do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
1831 | 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) | ||||
1832 | "Attribute '" + Attr.getAsString() + "' 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) | ||||
1833 | V)do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false); | ||||
1834 | |||||
1835 | if (Attrs.hasAttribute(Attribute::ImmArg)) { | ||||
1836 | Check(Attrs.getNumAttributes() == 1,do { if (!(Attrs.getNumAttributes() == 1)) { CheckFailed("Attribute 'immarg' is incompatible with other attributes" , V); return; } } while (false) | ||||
1837 | "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); | ||||
1838 | } | ||||
1839 | |||||
1840 | // Check for mutually incompatible attributes. Only inreg is compatible with | ||||
1841 | // sret. | ||||
1842 | unsigned AttrCount = 0; | ||||
1843 | AttrCount += Attrs.hasAttribute(Attribute::ByVal); | ||||
1844 | AttrCount += Attrs.hasAttribute(Attribute::InAlloca); | ||||
1845 | AttrCount += Attrs.hasAttribute(Attribute::Preallocated); | ||||
1846 | AttrCount += Attrs.hasAttribute(Attribute::StructRet) || | ||||
1847 | Attrs.hasAttribute(Attribute::InReg); | ||||
1848 | AttrCount += Attrs.hasAttribute(Attribute::Nest); | ||||
1849 | AttrCount += Attrs.hasAttribute(Attribute::ByRef); | ||||
1850 | Check(AttrCount <= 1,do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
1851 | "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) | ||||
1852 | "'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) | ||||
1853 | V)do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false); | ||||
1854 | |||||
1855 | Check(!(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) | ||||
1856 | 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) | ||||
1857 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
1858 | "'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) | ||||
1859 | V)do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false); | ||||
1860 | |||||
1861 | Check(!(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) | ||||
1862 | 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) | ||||
1863 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
1864 | "'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) | ||||
1865 | V)do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false); | ||||
1866 | |||||
1867 | Check(!(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) | ||||
1868 | 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) | ||||
1869 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
1870 | "'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) | ||||
1871 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false); | ||||
1872 | |||||
1873 | Check(!(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) | ||||
1874 | 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) | ||||
1875 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
1876 | "'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) | ||||
1877 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false); | ||||
1878 | |||||
1879 | Check(!(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) | ||||
1880 | 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) | ||||
1881 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
1882 | "'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) | ||||
1883 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false); | ||||
1884 | |||||
1885 | Check(!(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) | ||||
1886 | 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) | ||||
1887 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
1888 | "'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) | ||||
1889 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false); | ||||
1890 | |||||
1891 | Check(!(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) | ||||
1892 | 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) | ||||
1893 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
1894 | "'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) | ||||
1895 | V)do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false); | ||||
1896 | |||||
1897 | AttributeMask IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty); | ||||
1898 | for (Attribute Attr : Attrs) { | ||||
1899 | if (!Attr.isStringAttribute() && | ||||
1900 | IncompatibleAttrs.contains(Attr.getKindAsEnum())) { | ||||
1901 | CheckFailed("Attribute '" + Attr.getAsString() + | ||||
1902 | "' applied to incompatible type!", V); | ||||
1903 | return; | ||||
1904 | } | ||||
1905 | } | ||||
1906 | |||||
1907 | if (PointerType *PTy = dyn_cast<PointerType>(Ty)) { | ||||
1908 | if (Attrs.hasAttribute(Attribute::ByVal)) { | ||||
1909 | if (Attrs.hasAttribute(Attribute::Alignment)) { | ||||
1910 | Align AttrAlign = Attrs.getAlignment().valueOrOne(); | ||||
1911 | Align MaxAlign(ParamMaxAlignment); | ||||
1912 | Check(AttrAlign <= MaxAlign,do { if (!(AttrAlign <= MaxAlign)) { CheckFailed("Attribute 'align' exceed the max size 2^14" , V); return; } } while (false) | ||||
1913 | "Attribute 'align' exceed the max size 2^14", V)do { if (!(AttrAlign <= MaxAlign)) { CheckFailed("Attribute 'align' exceed the max size 2^14" , V); return; } } while (false); | ||||
1914 | } | ||||
1915 | SmallPtrSet<Type *, 4> Visited; | ||||
1916 | Check(Attrs.getByValType()->isSized(&Visited),do { if (!(Attrs.getByValType()->isSized(&Visited))) { CheckFailed("Attribute 'byval' does not support unsized types!" , V); return; } } while (false) | ||||
1917 | "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); | ||||
1918 | } | ||||
1919 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
1920 | SmallPtrSet<Type *, 4> Visited; | ||||
1921 | Check(Attrs.getByRefType()->isSized(&Visited),do { if (!(Attrs.getByRefType()->isSized(&Visited))) { CheckFailed("Attribute 'byref' does not support unsized types!" , V); return; } } while (false) | ||||
1922 | "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); | ||||
1923 | } | ||||
1924 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
1925 | SmallPtrSet<Type *, 4> Visited; | ||||
1926 | Check(Attrs.getInAllocaType()->isSized(&Visited),do { if (!(Attrs.getInAllocaType()->isSized(&Visited)) ) { CheckFailed("Attribute 'inalloca' does not support unsized types!" , V); return; } } while (false) | ||||
1927 | "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); | ||||
1928 | } | ||||
1929 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
1930 | SmallPtrSet<Type *, 4> Visited; | ||||
1931 | Check(Attrs.getPreallocatedType()->isSized(&Visited),do { if (!(Attrs.getPreallocatedType()->isSized(&Visited ))) { CheckFailed("Attribute 'preallocated' does not support unsized types!" , V); return; } } while (false) | ||||
1932 | "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); | ||||
1933 | } | ||||
1934 | if (!PTy->isOpaque()) { | ||||
1935 | if (!isa<PointerType>(PTy->getNonOpaquePointerElementType())) | ||||
1936 | Check(!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) | ||||
1937 | "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) | ||||
1938 | "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) | ||||
1939 | V)do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false); | ||||
1940 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
1941 | Check(Attrs.getByRefType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getByRefType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false) | ||||
1942 | "Attribute 'byref' type does not match parameter!", V)do { if (!(Attrs.getByRefType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false); | ||||
1943 | } | ||||
1944 | |||||
1945 | if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) { | ||||
1946 | Check(Attrs.getByValType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getByValType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false) | ||||
1947 | "Attribute 'byval' type does not match parameter!", V)do { if (!(Attrs.getByValType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false); | ||||
1948 | } | ||||
1949 | |||||
1950 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
1951 | Check(Attrs.getPreallocatedType() ==do { if (!(Attrs.getPreallocatedType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false) | ||||
1952 | PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getPreallocatedType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false) | ||||
1953 | "Attribute 'preallocated' type does not match parameter!", V)do { if (!(Attrs.getPreallocatedType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false); | ||||
1954 | } | ||||
1955 | |||||
1956 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
1957 | Check(Attrs.getInAllocaType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getInAllocaType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false) | ||||
1958 | "Attribute 'inalloca' type does not match parameter!", V)do { if (!(Attrs.getInAllocaType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false); | ||||
1959 | } | ||||
1960 | |||||
1961 | if (Attrs.hasAttribute(Attribute::ElementType)) { | ||||
1962 | Check(Attrs.getElementType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getElementType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false) | ||||
1963 | "Attribute 'elementtype' type does not match parameter!", V)do { if (!(Attrs.getElementType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false); | ||||
1964 | } | ||||
1965 | } | ||||
1966 | } | ||||
1967 | |||||
1968 | if (Attrs.hasAttribute(Attribute::NoFPClass)) { | ||||
1969 | uint64_t Val = Attrs.getAttribute(Attribute::NoFPClass).getValueAsInt(); | ||||
1970 | Check(Val != 0, "Attribute 'nofpclass' must have at least one test bit set",do { if (!(Val != 0)) { CheckFailed("Attribute 'nofpclass' must have at least one test bit set" , V); return; } } while (false) | ||||
1971 | V)do { if (!(Val != 0)) { CheckFailed("Attribute 'nofpclass' must have at least one test bit set" , V); return; } } while (false); | ||||
1972 | Check((Val & ~static_cast<unsigned>(fcAllFlags)) == 0,do { if (!((Val & ~static_cast<unsigned>(fcAllFlags )) == 0)) { CheckFailed("Invalid value for 'nofpclass' test mask" , V); return; } } while (false) | ||||
1973 | "Invalid value for 'nofpclass' test mask", V)do { if (!((Val & ~static_cast<unsigned>(fcAllFlags )) == 0)) { CheckFailed("Invalid value for 'nofpclass' test mask" , V); return; } } while (false); | ||||
1974 | } | ||||
1975 | } | ||||
1976 | |||||
1977 | void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
1978 | const Value *V) { | ||||
1979 | if (Attrs.hasFnAttr(Attr)) { | ||||
1980 | StringRef S = Attrs.getFnAttr(Attr).getValueAsString(); | ||||
1981 | unsigned N; | ||||
1982 | if (S.getAsInteger(10, N)) | ||||
1983 | CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, V); | ||||
1984 | } | ||||
1985 | } | ||||
1986 | |||||
1987 | // Check parameter attributes against a function type. | ||||
1988 | // The value V is printed in error messages. | ||||
1989 | void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
1990 | const Value *V, bool IsIntrinsic, | ||||
1991 | bool IsInlineAsm) { | ||||
1992 | if (Attrs.isEmpty()) | ||||
1993 | return; | ||||
1994 | |||||
1995 | if (AttributeListsVisited.insert(Attrs.getRawPointer()).second) { | ||||
1996 | Check(Attrs.hasParentContext(Context),do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false) | ||||
1997 | "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); | ||||
1998 | for (const auto &AttrSet : Attrs) { | ||||
1999 | Check(!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) | ||||
2000 | "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); | ||||
2001 | for (const auto &A : AttrSet) { | ||||
2002 | Check(A.hasParentContext(Context),do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false) | ||||
2003 | "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); | ||||
2004 | } | ||||
2005 | } | ||||
2006 | } | ||||
2007 | |||||
2008 | bool SawNest = false; | ||||
2009 | bool SawReturned = false; | ||||
2010 | bool SawSRet = false; | ||||
2011 | bool SawSwiftSelf = false; | ||||
2012 | bool SawSwiftAsync = false; | ||||
2013 | bool SawSwiftError = false; | ||||
2014 | |||||
2015 | // Verify return value attributes. | ||||
2016 | AttributeSet RetAttrs = Attrs.getRetAttrs(); | ||||
2017 | for (Attribute RetAttr : RetAttrs) | ||||
2018 | Check(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) | ||||
2019 | 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) | ||||
2020 | "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) | ||||
2021 | "' 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) | ||||
2022 | V)do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false); | ||||
2023 | |||||
2024 | verifyParameterAttrs(RetAttrs, FT->getReturnType(), V); | ||||
2025 | |||||
2026 | // Verify parameter attributes. | ||||
2027 | for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { | ||||
2028 | Type *Ty = FT->getParamType(i); | ||||
2029 | AttributeSet ArgAttrs = Attrs.getParamAttrs(i); | ||||
2030 | |||||
2031 | if (!IsIntrinsic) { | ||||
2032 | Check(!ArgAttrs.hasAttribute(Attribute::ImmArg),do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics", V); return; } } while (false) | ||||
2033 | "immarg attribute only applies to intrinsics", V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics", V); return; } } while (false); | ||||
2034 | if (!IsInlineAsm) | ||||
2035 | Check(!ArgAttrs.hasAttribute(Attribute::ElementType),do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false) | ||||
2036 | "Attribute 'elementtype' can only be applied to intrinsics"do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false) | ||||
2037 | " and inline asm.",do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false) | ||||
2038 | V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false); | ||||
2039 | } | ||||
2040 | |||||
2041 | verifyParameterAttrs(ArgAttrs, Ty, V); | ||||
2042 | |||||
2043 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
2044 | Check(!SawNest, "More than one parameter has attribute nest!", V)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , V); return; } } while (false); | ||||
2045 | SawNest = true; | ||||
2046 | } | ||||
2047 | |||||
2048 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
2049 | Check(!SawReturned, "More than one parameter has attribute returned!", V)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false); | ||||
2050 | Check(Ty->canLosslesslyBitCastTo(FT->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
2051 | "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) | ||||
2052 | V)do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false); | ||||
2053 | SawReturned = true; | ||||
2054 | } | ||||
2055 | |||||
2056 | if (ArgAttrs.hasAttribute(Attribute::StructRet)) { | ||||
2057 | Check(!SawSRet, "Cannot have multiple 'sret' parameters!", V)do { if (!(!SawSRet)) { CheckFailed("Cannot have multiple 'sret' parameters!" , V); return; } } while (false); | ||||
2058 | Check(i == 0 || i == 1,do { if (!(i == 0 || i == 1)) { CheckFailed("Attribute 'sret' is not on first or second parameter!" , V); return; } } while (false) | ||||
2059 | "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); | ||||
2060 | SawSRet = true; | ||||
2061 | } | ||||
2062 | |||||
2063 | if (ArgAttrs.hasAttribute(Attribute::SwiftSelf)) { | ||||
2064 | Check(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V)do { if (!(!SawSwiftSelf)) { CheckFailed("Cannot have multiple 'swiftself' parameters!" , V); return; } } while (false); | ||||
2065 | SawSwiftSelf = true; | ||||
2066 | } | ||||
2067 | |||||
2068 | if (ArgAttrs.hasAttribute(Attribute::SwiftAsync)) { | ||||
2069 | Check(!SawSwiftAsync, "Cannot have multiple 'swiftasync' parameters!", V)do { if (!(!SawSwiftAsync)) { CheckFailed("Cannot have multiple 'swiftasync' parameters!" , V); return; } } while (false); | ||||
2070 | SawSwiftAsync = true; | ||||
2071 | } | ||||
2072 | |||||
2073 | if (ArgAttrs.hasAttribute(Attribute::SwiftError)) { | ||||
2074 | Check(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!", V)do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false); | ||||
2075 | SawSwiftError = true; | ||||
2076 | } | ||||
2077 | |||||
2078 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) { | ||||
2079 | Check(i == FT->getNumParams() - 1,do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false) | ||||
2080 | "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); | ||||
2081 | } | ||||
2082 | } | ||||
2083 | |||||
2084 | if (!Attrs.hasFnAttrs()) | ||||
2085 | return; | ||||
2086 | |||||
2087 | verifyAttributeTypes(Attrs.getFnAttrs(), V); | ||||
2088 | for (Attribute FnAttr : Attrs.getFnAttrs()) | ||||
2089 | Check(FnAttr.isStringAttribute() ||do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
2090 | 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) | ||||
2091 | "Attribute '" + FnAttr.getAsString() +do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
2092 | "' 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) | ||||
2093 | V)do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false); | ||||
2094 | |||||
2095 | Check(!(Attrs.hasFnAttr(Attribute::NoInline) &&do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
2096 | Attrs.hasFnAttr(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
2097 | "Attributes 'noinline and alwaysinline' are incompatible!", V)do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false); | ||||
2098 | |||||
2099 | if (Attrs.hasFnAttr(Attribute::OptimizeNone)) { | ||||
2100 | Check(Attrs.hasFnAttr(Attribute::NoInline),do { if (!(Attrs.hasFnAttr(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false) | ||||
2101 | "Attribute 'optnone' requires 'noinline'!", V)do { if (!(Attrs.hasFnAttr(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false); | ||||
2102 | |||||
2103 | Check(!Attrs.hasFnAttr(Attribute::OptimizeForSize),do { if (!(!Attrs.hasFnAttr(Attribute::OptimizeForSize))) { CheckFailed ("Attributes 'optsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
2104 | "Attributes 'optsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttr(Attribute::OptimizeForSize))) { CheckFailed ("Attributes 'optsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
2105 | |||||
2106 | Check(!Attrs.hasFnAttr(Attribute::MinSize),do { if (!(!Attrs.hasFnAttr(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
2107 | "Attributes 'minsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttr(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
2108 | } | ||||
2109 | |||||
2110 | if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled")) { | ||||
2111 | Check(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"),do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false) | ||||
2112 | "Attributes 'aarch64_pstate_sm_enabled and "do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false) | ||||
2113 | "aarch64_pstate_sm_compatible' are incompatible!",do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false) | ||||
2114 | V)do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false); | ||||
2115 | } | ||||
2116 | |||||
2117 | if (Attrs.hasFnAttr("aarch64_pstate_za_new")) { | ||||
2118 | Check(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"),do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false) | ||||
2119 | "Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' "do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false) | ||||
2120 | "are incompatible!",do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false) | ||||
2121 | V)do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false); | ||||
2122 | |||||
2123 | Check(!Attrs.hasFnAttr("aarch64_pstate_za_shared"),do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false) | ||||
2124 | "Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' "do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false) | ||||
2125 | "are incompatible!",do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false) | ||||
2126 | V)do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false); | ||||
2127 | } | ||||
2128 | |||||
2129 | if (Attrs.hasFnAttr(Attribute::JumpTable)) { | ||||
2130 | const GlobalValue *GV = cast<GlobalValue>(V); | ||||
2131 | Check(GV->hasGlobalUnnamedAddr(),do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false) | ||||
2132 | "Attribute 'jumptable' requires 'unnamed_addr'", V)do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false); | ||||
2133 | } | ||||
2134 | |||||
2135 | if (auto Args = Attrs.getFnAttrs().getAllocSizeArgs()) { | ||||
2136 | auto CheckParam = [&](StringRef Name, unsigned ParamNo) { | ||||
2137 | if (ParamNo >= FT->getNumParams()) { | ||||
2138 | CheckFailed("'allocsize' " + Name + " argument is out of bounds", V); | ||||
2139 | return false; | ||||
2140 | } | ||||
2141 | |||||
2142 | if (!FT->getParamType(ParamNo)->isIntegerTy()) { | ||||
2143 | CheckFailed("'allocsize' " + Name + | ||||
2144 | " argument must refer to an integer parameter", | ||||
2145 | V); | ||||
2146 | return false; | ||||
2147 | } | ||||
2148 | |||||
2149 | return true; | ||||
2150 | }; | ||||
2151 | |||||
2152 | if (!CheckParam("element size", Args->first)) | ||||
2153 | return; | ||||
2154 | |||||
2155 | if (Args->second && !CheckParam("number of elements", *Args->second)) | ||||
2156 | return; | ||||
2157 | } | ||||
2158 | |||||
2159 | if (Attrs.hasFnAttr(Attribute::AllocKind)) { | ||||
2160 | AllocFnKind K = Attrs.getAllocKind(); | ||||
2161 | AllocFnKind Type = | ||||
2162 | K & (AllocFnKind::Alloc | AllocFnKind::Realloc | AllocFnKind::Free); | ||||
2163 | if (!is_contained( | ||||
2164 | {AllocFnKind::Alloc, AllocFnKind::Realloc, AllocFnKind::Free}, | ||||
2165 | Type)) | ||||
2166 | CheckFailed( | ||||
2167 | "'allockind()' requires exactly one of alloc, realloc, and free"); | ||||
2168 | if ((Type == AllocFnKind::Free) && | ||||
2169 | ((K & (AllocFnKind::Uninitialized | AllocFnKind::Zeroed | | ||||
2170 | AllocFnKind::Aligned)) != AllocFnKind::Unknown)) | ||||
2171 | CheckFailed("'allockind(\"free\")' doesn't allow uninitialized, zeroed, " | ||||
2172 | "or aligned modifiers."); | ||||
2173 | AllocFnKind ZeroedUninit = AllocFnKind::Uninitialized | AllocFnKind::Zeroed; | ||||
2174 | if ((K & ZeroedUninit) == ZeroedUninit) | ||||
2175 | CheckFailed("'allockind()' can't be both zeroed and uninitialized"); | ||||
2176 | } | ||||
2177 | |||||
2178 | if (Attrs.hasFnAttr(Attribute::VScaleRange)) { | ||||
2179 | unsigned VScaleMin = Attrs.getFnAttrs().getVScaleRangeMin(); | ||||
2180 | if (VScaleMin == 0) | ||||
2181 | CheckFailed("'vscale_range' minimum must be greater than 0", V); | ||||
2182 | |||||
2183 | std::optional<unsigned> VScaleMax = Attrs.getFnAttrs().getVScaleRangeMax(); | ||||
2184 | if (VScaleMax && VScaleMin > VScaleMax) | ||||
2185 | CheckFailed("'vscale_range' minimum cannot be greater than maximum", V); | ||||
2186 | } | ||||
2187 | |||||
2188 | if (Attrs.hasFnAttr("frame-pointer")) { | ||||
2189 | StringRef FP = Attrs.getFnAttr("frame-pointer").getValueAsString(); | ||||
2190 | if (FP != "all" && FP != "non-leaf" && FP != "none") | ||||
2191 | CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V); | ||||
2192 | } | ||||
2193 | |||||
2194 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V); | ||||
2195 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V); | ||||
2196 | checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", V); | ||||
2197 | } | ||||
2198 | |||||
2199 | void Verifier::verifyFunctionMetadata( | ||||
2200 | ArrayRef<std::pair<unsigned, MDNode *>> MDs) { | ||||
2201 | for (const auto &Pair : MDs) { | ||||
2202 | if (Pair.first == LLVMContext::MD_prof) { | ||||
2203 | MDNode *MD = Pair.second; | ||||
2204 | Check(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
2205 | "!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); | ||||
2206 | |||||
2207 | // Check first operand. | ||||
2208 | Check(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) | ||||
2209 | MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
2210 | Check(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) | ||||
2211 | "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); | ||||
2212 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
2213 | StringRef ProfName = MDS->getString(); | ||||
2214 | Check(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) | ||||
2215 | 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) | ||||
2216 | "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) | ||||
2217 | " 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) | ||||
2218 | 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); | ||||
2219 | |||||
2220 | // Check second operand. | ||||
2221 | Check(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) | ||||
2222 | MD)do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
2223 | Check(isa<ConstantAsMetadata>(MD->getOperand(1)),do { if (!(isa<ConstantAsMetadata>(MD->getOperand(1) ))) { CheckFailed("expected integer argument to function_entry_count" , MD); return; } } while (false) | ||||
2224 | "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); | ||||
2225 | } else if (Pair.first == LLVMContext::MD_kcfi_type) { | ||||
2226 | MDNode *MD = Pair.second; | ||||
2227 | Check(MD->getNumOperands() == 1,do { if (!(MD->getNumOperands() == 1)) { CheckFailed("!kcfi_type must have exactly one operand" , MD); return; } } while (false) | ||||
2228 | "!kcfi_type must have exactly one operand", MD)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("!kcfi_type must have exactly one operand" , MD); return; } } while (false); | ||||
2229 | Check(MD->getOperand(0) != nullptr, "!kcfi_type operand must not be null",do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("!kcfi_type operand must not be null" , MD); return; } } while (false) | ||||
2230 | MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("!kcfi_type operand must not be null" , MD); return; } } while (false); | ||||
2231 | Check(isa<ConstantAsMetadata>(MD->getOperand(0)),do { if (!(isa<ConstantAsMetadata>(MD->getOperand(0) ))) { CheckFailed("expected a constant operand for !kcfi_type" , MD); return; } } while (false) | ||||
2232 | "expected a constant operand for !kcfi_type", MD)do { if (!(isa<ConstantAsMetadata>(MD->getOperand(0) ))) { CheckFailed("expected a constant operand for !kcfi_type" , MD); return; } } while (false); | ||||
2233 | Constant *C = cast<ConstantAsMetadata>(MD->getOperand(0))->getValue(); | ||||
2234 | Check(isa<ConstantInt>(C),do { if (!(isa<ConstantInt>(C))) { CheckFailed("expected a constant integer operand for !kcfi_type" , MD); return; } } while (false) | ||||
2235 | "expected a constant integer operand for !kcfi_type", MD)do { if (!(isa<ConstantInt>(C))) { CheckFailed("expected a constant integer operand for !kcfi_type" , MD); return; } } while (false); | ||||
2236 | IntegerType *Type = cast<ConstantInt>(C)->getType(); | ||||
2237 | Check(Type->getBitWidth() == 32,do { if (!(Type->getBitWidth() == 32)) { CheckFailed("expected a 32-bit integer constant operand for !kcfi_type" , MD); return; } } while (false) | ||||
2238 | "expected a 32-bit integer constant operand for !kcfi_type", MD)do { if (!(Type->getBitWidth() == 32)) { CheckFailed("expected a 32-bit integer constant operand for !kcfi_type" , MD); return; } } while (false); | ||||
2239 | } | ||||
2240 | } | ||||
2241 | } | ||||
2242 | |||||
2243 | void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { | ||||
2244 | if (!ConstantExprVisited.insert(EntryC).second) | ||||
2245 | return; | ||||
2246 | |||||
2247 | SmallVector<const Constant *, 16> Stack; | ||||
2248 | Stack.push_back(EntryC); | ||||
2249 | |||||
2250 | while (!Stack.empty()) { | ||||
2251 | const Constant *C = Stack.pop_back_val(); | ||||
2252 | |||||
2253 | // Check this constant expression. | ||||
2254 | if (const auto *CE = dyn_cast<ConstantExpr>(C)) | ||||
2255 | visitConstantExpr(CE); | ||||
2256 | |||||
2257 | if (const auto *GV = dyn_cast<GlobalValue>(C)) { | ||||
2258 | // Global Values get visited separately, but we do need to make sure | ||||
2259 | // that the global value is in the correct module | ||||
2260 | Check(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) | ||||
2261 | EntryC, &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false); | ||||
2262 | continue; | ||||
2263 | } | ||||
2264 | |||||
2265 | // Visit all sub-expressions. | ||||
2266 | for (const Use &U : C->operands()) { | ||||
2267 | const auto *OpC = dyn_cast<Constant>(U); | ||||
2268 | if (!OpC) | ||||
2269 | continue; | ||||
2270 | if (!ConstantExprVisited.insert(OpC).second) | ||||
2271 | continue; | ||||
2272 | Stack.push_back(OpC); | ||||
2273 | } | ||||
2274 | } | ||||
2275 | } | ||||
2276 | |||||
2277 | void Verifier::visitConstantExpr(const ConstantExpr *CE) { | ||||
2278 | if (CE->getOpcode() == Instruction::BitCast) | ||||
2279 | Check(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) | ||||
2280 | CE->getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
2281 | "Invalid bitcast", CE)do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false); | ||||
2282 | } | ||||
2283 | |||||
2284 | bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) { | ||||
2285 | // There shouldn't be more attribute sets than there are parameters plus the | ||||
2286 | // function and return value. | ||||
2287 | return Attrs.getNumAttrSets() <= Params + 2; | ||||
2288 | } | ||||
2289 | |||||
2290 | void Verifier::verifyInlineAsmCall(const CallBase &Call) { | ||||
2291 | const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand()); | ||||
2292 | unsigned ArgNo = 0; | ||||
2293 | unsigned LabelNo = 0; | ||||
2294 | for (const InlineAsm::ConstraintInfo &CI : IA->ParseConstraints()) { | ||||
2295 | if (CI.Type == InlineAsm::isLabel) { | ||||
2296 | ++LabelNo; | ||||
2297 | continue; | ||||
2298 | } | ||||
2299 | |||||
2300 | // Only deal with constraints that correspond to call arguments. | ||||
2301 | if (!CI.hasArg()) | ||||
2302 | continue; | ||||
2303 | |||||
2304 | if (CI.isIndirect) { | ||||
2305 | const Value *Arg = Call.getArgOperand(ArgNo); | ||||
2306 | Check(Arg->getType()->isPointerTy(),do { if (!(Arg->getType()->isPointerTy())) { CheckFailed ("Operand for indirect constraint must have pointer type", & Call); return; } } while (false) | ||||
2307 | "Operand for indirect constraint must have pointer type", &Call)do { if (!(Arg->getType()->isPointerTy())) { CheckFailed ("Operand for indirect constraint must have pointer type", & Call); return; } } while (false); | ||||
2308 | |||||
2309 | Check(Call.getParamElementType(ArgNo),do { if (!(Call.getParamElementType(ArgNo))) { CheckFailed("Operand for indirect constraint must have elementtype attribute" , &Call); return; } } while (false) | ||||
2310 | "Operand for indirect constraint must have elementtype attribute",do { if (!(Call.getParamElementType(ArgNo))) { CheckFailed("Operand for indirect constraint must have elementtype attribute" , &Call); return; } } while (false) | ||||
2311 | &Call)do { if (!(Call.getParamElementType(ArgNo))) { CheckFailed("Operand for indirect constraint must have elementtype attribute" , &Call); return; } } while (false); | ||||
2312 | } else { | ||||
2313 | Check(!Call.paramHasAttr(ArgNo, Attribute::ElementType),do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false) | ||||
2314 | "Elementtype attribute can only be applied for indirect "do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false) | ||||
2315 | "constraints",do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false) | ||||
2316 | &Call)do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false); | ||||
2317 | } | ||||
2318 | |||||
2319 | ArgNo++; | ||||
2320 | } | ||||
2321 | |||||
2322 | if (auto *CallBr = dyn_cast<CallBrInst>(&Call)) { | ||||
2323 | Check(LabelNo == CallBr->getNumIndirectDests(),do { if (!(LabelNo == CallBr->getNumIndirectDests())) { CheckFailed ("Number of label constraints does not match number of callbr dests" , &Call); return; } } while (false) | ||||
2324 | "Number of label constraints does not match number of callbr dests",do { if (!(LabelNo == CallBr->getNumIndirectDests())) { CheckFailed ("Number of label constraints does not match number of callbr dests" , &Call); return; } } while (false) | ||||
2325 | &Call)do { if (!(LabelNo == CallBr->getNumIndirectDests())) { CheckFailed ("Number of label constraints does not match number of callbr dests" , &Call); return; } } while (false); | ||||
2326 | } else { | ||||
2327 | Check(LabelNo == 0, "Label constraints can only be used with callbr",do { if (!(LabelNo == 0)) { CheckFailed("Label constraints can only be used with callbr" , &Call); return; } } while (false) | ||||
2328 | &Call)do { if (!(LabelNo == 0)) { CheckFailed("Label constraints can only be used with callbr" , &Call); return; } } while (false); | ||||
2329 | } | ||||
2330 | } | ||||
2331 | |||||
2332 | /// Verify that statepoint intrinsic is well formed. | ||||
2333 | void Verifier::verifyStatepoint(const CallBase &Call) { | ||||
2334 | assert(Call.getCalledFunction() &&(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "llvm/lib/IR/Verifier.cpp", 2336, __extension__ __PRETTY_FUNCTION__ )) | ||||
2335 | Call.getCalledFunction()->getIntrinsicID() ==(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "llvm/lib/IR/Verifier.cpp", 2336, __extension__ __PRETTY_FUNCTION__ )) | ||||
2336 | Intrinsic::experimental_gc_statepoint)(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "llvm/lib/IR/Verifier.cpp", 2336, __extension__ __PRETTY_FUNCTION__ )); | ||||
2337 | |||||
2338 | Check(!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) | ||||
2339 | !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) | ||||
2340 | "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) | ||||
2341 | "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) | ||||
2342 | 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); | ||||
2343 | |||||
2344 | const int64_t NumPatchBytes = | ||||
2345 | cast<ConstantInt>(Call.getArgOperand(1))->getSExtValue(); | ||||
2346 | assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!")(static_cast <bool> (isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!") ? void (0) : __assert_fail ("isInt<32>(NumPatchBytes) && \"NumPatchBytesV is an i32!\"" , "llvm/lib/IR/Verifier.cpp", 2346, __extension__ __PRETTY_FUNCTION__ )); | ||||
2347 | Check(NumPatchBytes >= 0,do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
2348 | "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) | ||||
2349 | "positive",do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
2350 | Call)do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false); | ||||
2351 | |||||
2352 | Type *TargetElemType = Call.getParamElementType(2); | ||||
2353 | Check(TargetElemType,do { if (!(TargetElemType)) { CheckFailed("gc.statepoint callee argument must have elementtype attribute" , Call); return; } } while (false) | ||||
2354 | "gc.statepoint callee argument must have elementtype attribute", Call)do { if (!(TargetElemType)) { CheckFailed("gc.statepoint callee argument must have elementtype attribute" , Call); return; } } while (false); | ||||
2355 | FunctionType *TargetFuncType = dyn_cast<FunctionType>(TargetElemType); | ||||
2356 | Check(TargetFuncType,do { if (!(TargetFuncType)) { CheckFailed("gc.statepoint callee elementtype must be function type" , Call); return; } } while (false) | ||||
2357 | "gc.statepoint callee elementtype must be function type", Call)do { if (!(TargetFuncType)) { CheckFailed("gc.statepoint callee elementtype must be function type" , Call); return; } } while (false); | ||||
2358 | |||||
2359 | const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue(); | ||||
2360 | Check(NumCallArgs >= 0,do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
2361 | "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) | ||||
2362 | "must be positive",do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
2363 | Call)do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false); | ||||
2364 | const int NumParams = (int)TargetFuncType->getNumParams(); | ||||
2365 | if (TargetFuncType->isVarArg()) { | ||||
2366 | Check(NumCallArgs >= NumParams,do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false) | ||||
2367 | "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); | ||||
2368 | |||||
2369 | // TODO: Remove this limitation | ||||
2370 | Check(TargetFuncType->getReturnType()->isVoidTy(),do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
2371 | "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) | ||||
2372 | "vararg functions yet",do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
2373 | Call)do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false); | ||||
2374 | } else | ||||
2375 | Check(NumCallArgs == NumParams,do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false) | ||||
2376 | "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); | ||||
2377 | |||||
2378 | const uint64_t Flags | ||||
2379 | = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue(); | ||||
2380 | Check((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) | ||||
2381 | "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); | ||||
2382 | |||||
2383 | // Verify that the types of the call parameter arguments match | ||||
2384 | // the type of the wrapped callee. | ||||
2385 | AttributeList Attrs = Call.getAttributes(); | ||||
2386 | for (int i = 0; i < NumParams; i++) { | ||||
2387 | Type *ParamType = TargetFuncType->getParamType(i); | ||||
2388 | Type *ArgType = Call.getArgOperand(5 + i)->getType(); | ||||
2389 | Check(ArgType == ParamType,do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
2390 | "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) | ||||
2391 | "function type",do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
2392 | Call)do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false); | ||||
2393 | |||||
2394 | if (TargetFuncType->isVarArg()) { | ||||
2395 | AttributeSet ArgAttrs = Attrs.getParamAttrs(5 + i); | ||||
2396 | Check(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
2397 | "Attribute 'sret' cannot be used for vararg call arguments!", Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
2398 | } | ||||
2399 | } | ||||
2400 | |||||
2401 | const int EndCallArgsInx = 4 + NumCallArgs; | ||||
2402 | |||||
2403 | const Value *NumTransitionArgsV = Call.getArgOperand(EndCallArgsInx + 1); | ||||
2404 | Check(isa<ConstantInt>(NumTransitionArgsV),do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2405 | "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) | ||||
2406 | "must be constant integer",do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2407 | Call)do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false); | ||||
2408 | const int NumTransitionArgs = | ||||
2409 | cast<ConstantInt>(NumTransitionArgsV)->getZExtValue(); | ||||
2410 | Check(NumTransitionArgs == 0,do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false) | ||||
2411 | "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); | ||||
2412 | const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; | ||||
2413 | |||||
2414 | const Value *NumDeoptArgsV = Call.getArgOperand(EndTransitionArgsInx + 1); | ||||
2415 | Check(isa<ConstantInt>(NumDeoptArgsV),do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2416 | "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) | ||||
2417 | "must be constant integer",do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
2418 | Call)do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false); | ||||
2419 | const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue(); | ||||
2420 | Check(NumDeoptArgs == 0,do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false) | ||||
2421 | "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); | ||||
2422 | |||||
2423 | const int ExpectedNumArgs = 7 + NumCallArgs; | ||||
2424 | Check(ExpectedNumArgs == (int)Call.arg_size(),do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false) | ||||
2425 | "gc.statepoint too many arguments", Call)do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false); | ||||
2426 | |||||
2427 | // Check that the only uses of this gc.statepoint are gc.result or | ||||
2428 | // gc.relocate calls which are tied to this statepoint and thus part | ||||
2429 | // of the same statepoint sequence | ||||
2430 | for (const User *U : Call.users()) { | ||||
2431 | const CallInst *UserCall = dyn_cast<const CallInst>(U); | ||||
2432 | Check(UserCall, "illegal use of statepoint token", Call, U)do { if (!(UserCall)) { CheckFailed("illegal use of statepoint token" , Call, U); return; } } while (false); | ||||
2433 | if (!UserCall) | ||||
2434 | continue; | ||||
2435 | Check(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) | ||||
2436 | "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) | ||||
2437 | "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) | ||||
2438 | 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); | ||||
2439 | if (isa<GCResultInst>(UserCall)) { | ||||
2440 | Check(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
2441 | "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); | ||||
2442 | } else if (isa<GCRelocateInst>(Call)) { | ||||
2443 | Check(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
2444 | "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); | ||||
2445 | } | ||||
2446 | } | ||||
2447 | |||||
2448 | // Note: It is legal for a single derived pointer to be listed multiple | ||||
2449 | // times. It's non-optimal, but it is legal. It can also happen after | ||||
2450 | // insertion if we strip a bitcast away. | ||||
2451 | // Note: It is really tempting to check that each base is relocated and | ||||
2452 | // that a derived pointer is never reused as a base pointer. This turns | ||||
2453 | // out to be problematic since optimizations run after safepoint insertion | ||||
2454 | // can recognize equality properties that the insertion logic doesn't know | ||||
2455 | // about. See example statepoint.ll in the verifier subdirectory | ||||
2456 | } | ||||
2457 | |||||
2458 | void Verifier::verifyFrameRecoverIndices() { | ||||
2459 | for (auto &Counts : FrameEscapeInfo) { | ||||
2460 | Function *F = Counts.first; | ||||
2461 | unsigned EscapedObjectCount = Counts.second.first; | ||||
2462 | unsigned MaxRecoveredIndex = Counts.second.second; | ||||
2463 | Check(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) | ||||
2464 | "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) | ||||
2465 | "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) | ||||
2466 | "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) | ||||
2467 | 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); | ||||
2468 | } | ||||
2469 | } | ||||
2470 | |||||
2471 | static Instruction *getSuccPad(Instruction *Terminator) { | ||||
2472 | BasicBlock *UnwindDest; | ||||
2473 | if (auto *II = dyn_cast<InvokeInst>(Terminator)) | ||||
2474 | UnwindDest = II->getUnwindDest(); | ||||
2475 | else if (auto *CSI = dyn_cast<CatchSwitchInst>(Terminator)) | ||||
2476 | UnwindDest = CSI->getUnwindDest(); | ||||
2477 | else | ||||
2478 | UnwindDest = cast<CleanupReturnInst>(Terminator)->getUnwindDest(); | ||||
2479 | return UnwindDest->getFirstNonPHI(); | ||||
2480 | } | ||||
2481 | |||||
2482 | void Verifier::verifySiblingFuncletUnwinds() { | ||||
2483 | SmallPtrSet<Instruction *, 8> Visited; | ||||
2484 | SmallPtrSet<Instruction *, 8> Active; | ||||
2485 | for (const auto &Pair : SiblingFuncletInfo) { | ||||
2486 | Instruction *PredPad = Pair.first; | ||||
2487 | if (Visited.count(PredPad)) | ||||
2488 | continue; | ||||
2489 | Active.insert(PredPad); | ||||
2490 | Instruction *Terminator = Pair.second; | ||||
2491 | do { | ||||
2492 | Instruction *SuccPad = getSuccPad(Terminator); | ||||
2493 | if (Active.count(SuccPad)) { | ||||
2494 | // Found a cycle; report error | ||||
2495 | Instruction *CyclePad = SuccPad; | ||||
2496 | SmallVector<Instruction *, 8> CycleNodes; | ||||
2497 | do { | ||||
2498 | CycleNodes.push_back(CyclePad); | ||||
2499 | Instruction *CycleTerminator = SiblingFuncletInfo[CyclePad]; | ||||
2500 | if (CycleTerminator != CyclePad) | ||||
2501 | CycleNodes.push_back(CycleTerminator); | ||||
2502 | CyclePad = getSuccPad(CycleTerminator); | ||||
2503 | } while (CyclePad != SuccPad); | ||||
2504 | Check(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) | ||||
2505 | ArrayRef<Instruction *>(CycleNodes))do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false); | ||||
2506 | } | ||||
2507 | // Don't re-walk a node we've already checked | ||||
2508 | if (!Visited.insert(SuccPad).second) | ||||
2509 | break; | ||||
2510 | // Walk to this successor if it has a map entry. | ||||
2511 | PredPad = SuccPad; | ||||
2512 | auto TermI = SiblingFuncletInfo.find(PredPad); | ||||
2513 | if (TermI == SiblingFuncletInfo.end()) | ||||
2514 | break; | ||||
2515 | Terminator = TermI->second; | ||||
2516 | Active.insert(PredPad); | ||||
2517 | } while (true); | ||||
2518 | // Each node only has one successor, so we've walked all the active | ||||
2519 | // nodes' successors. | ||||
2520 | Active.clear(); | ||||
2521 | } | ||||
2522 | } | ||||
2523 | |||||
2524 | // visitFunction - Verify that a function is ok. | ||||
2525 | // | ||||
2526 | void Verifier::visitFunction(const Function &F) { | ||||
2527 | visitGlobalValue(F); | ||||
2528 | |||||
2529 | // Check function arguments. | ||||
2530 | FunctionType *FT = F.getFunctionType(); | ||||
2531 | unsigned NumArgs = F.arg_size(); | ||||
2532 | |||||
2533 | Check(&Context == &F.getContext(),do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false) | ||||
| |||||
2534 | "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); | ||||
2535 | |||||
2536 | Check(!F.hasCommonLinkage(), "Functions may not have common linkage", &F)do { if (!(!F.hasCommonLinkage())) { CheckFailed("Functions may not have common linkage" , &F); return; } } while (false); | ||||
2537 | Check(FT->getNumParams() == NumArgs,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
2538 | "# 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) | ||||
2539 | FT)do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false); | ||||
2540 | Check(F.getReturnType()->isFirstClassType() ||do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false) | ||||
2541 | 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) | ||||
2542 | "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); | ||||
2543 | |||||
2544 | Check(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false) | ||||
2545 | "Invalid struct return type!", &F)do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false); | ||||
2546 | |||||
2547 | AttributeList Attrs = F.getAttributes(); | ||||
2548 | |||||
2549 | Check(verifyAttributeCount(Attrs, FT->getNumParams()),do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false) | ||||
2550 | "Attribute after last parameter!", &F)do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false); | ||||
2551 | |||||
2552 | bool IsIntrinsic = F.isIntrinsic(); | ||||
2553 | |||||
2554 | // Check function attributes. | ||||
2555 | verifyFunctionAttrs(FT, Attrs, &F, IsIntrinsic, /* IsInlineAsm */ false); | ||||
2556 | |||||
2557 | // On function declarations/definitions, we do not support the builtin | ||||
2558 | // attribute. We do not check this in VerifyFunctionAttrs since that is | ||||
2559 | // checking for Attributes that can/can not ever be on functions. | ||||
2560 | Check(!Attrs.hasFnAttr(Attribute::Builtin),do { if (!(!Attrs.hasFnAttr(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false) | ||||
2561 | "Attribute 'builtin' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasFnAttr(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false); | ||||
2562 | |||||
2563 | Check(!Attrs.hasAttrSomewhere(Attribute::ElementType),do { if (!(!Attrs.hasAttrSomewhere(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to a callsite." , &F); return; } } while (false) | ||||
2564 | "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); | ||||
2565 | |||||
2566 | // Check that this function meets the restrictions on this calling convention. | ||||
2567 | // Sometimes varargs is used for perfectly forwarding thunks, so some of these | ||||
2568 | // restrictions can be lifted. | ||||
2569 | switch (F.getCallingConv()) { | ||||
2570 | default: | ||||
2571 | case CallingConv::C: | ||||
2572 | break; | ||||
2573 | case CallingConv::X86_INTR: { | ||||
2574 | Check(F.arg_empty() || Attrs.hasParamAttr(0, Attribute::ByVal),do { if (!(F.arg_empty() || Attrs.hasParamAttr(0, Attribute:: ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false) | ||||
2575 | "Calling convention parameter requires byval", &F)do { if (!(F.arg_empty() || Attrs.hasParamAttr(0, Attribute:: ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false); | ||||
2576 | break; | ||||
2577 | } | ||||
2578 | case CallingConv::AMDGPU_KERNEL: | ||||
2579 | case CallingConv::SPIR_KERNEL: | ||||
2580 | Check(F.getReturnType()->isVoidTy(),do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false) | ||||
2581 | "Calling convention requires void return type", &F)do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false); | ||||
2582 | [[fallthrough]]; | ||||
2583 | case CallingConv::AMDGPU_VS: | ||||
2584 | case CallingConv::AMDGPU_HS: | ||||
2585 | case CallingConv::AMDGPU_GS: | ||||
2586 | case CallingConv::AMDGPU_PS: | ||||
2587 | case CallingConv::AMDGPU_CS: | ||||
2588 | Check(!F.hasStructRetAttr(), "Calling convention does not allow sret", &F)do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false); | ||||
2589 | if (F.getCallingConv() != CallingConv::SPIR_KERNEL) { | ||||
2590 | const unsigned StackAS = DL.getAllocaAddrSpace(); | ||||
2591 | unsigned i = 0; | ||||
2592 | for (const Argument &Arg : F.args()) { | ||||
2593 | Check(!Attrs.hasParamAttr(i, Attribute::ByVal),do { if (!(!Attrs.hasParamAttr(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false) | ||||
2594 | "Calling convention disallows byval", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false); | ||||
2595 | Check(!Attrs.hasParamAttr(i, Attribute::Preallocated),do { if (!(!Attrs.hasParamAttr(i, Attribute::Preallocated))) { CheckFailed("Calling convention disallows preallocated", & F); return; } } while (false) | ||||
2596 | "Calling convention disallows preallocated", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::Preallocated))) { CheckFailed("Calling convention disallows preallocated", & F); return; } } while (false); | ||||
2597 | Check(!Attrs.hasParamAttr(i, Attribute::InAlloca),do { if (!(!Attrs.hasParamAttr(i, Attribute::InAlloca))) { CheckFailed ("Calling convention disallows inalloca", &F); return; } } while (false) | ||||
2598 | "Calling convention disallows inalloca", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::InAlloca))) { CheckFailed ("Calling convention disallows inalloca", &F); return; } } while (false); | ||||
2599 | |||||
2600 | if (Attrs.hasParamAttr(i, Attribute::ByRef)) { | ||||
2601 | // FIXME: Should also disallow LDS and GDS, but we don't have the enum | ||||
2602 | // value here. | ||||
2603 | Check(Arg.getType()->getPointerAddressSpace() != StackAS,do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false) | ||||
2604 | "Calling convention disallows stack byref", &F)do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false); | ||||
2605 | } | ||||
2606 | |||||
2607 | ++i; | ||||
2608 | } | ||||
2609 | } | ||||
2610 | |||||
2611 | [[fallthrough]]; | ||||
2612 | case CallingConv::Fast: | ||||
2613 | case CallingConv::Cold: | ||||
2614 | case CallingConv::Intel_OCL_BI: | ||||
2615 | case CallingConv::PTX_Kernel: | ||||
2616 | case CallingConv::PTX_Device: | ||||
2617 | Check(!F.isVarArg(),do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
2618 | "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) | ||||
2619 | "perfect forwarding!",do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
2620 | &F)do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false); | ||||
2621 | break; | ||||
2622 | } | ||||
2623 | |||||
2624 | // Check that the argument values match the function type for this function... | ||||
2625 | unsigned i = 0; | ||||
2626 | for (const Argument &Arg : F.args()) { | ||||
2627 | Check(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) | ||||
2628 | "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) | ||||
2629 | 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); | ||||
2630 | Check(Arg.getType()->isFirstClassType(),do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false) | ||||
2631 | "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); | ||||
2632 | if (!IsIntrinsic) { | ||||
2633 | Check(!Arg.getType()->isMetadataTy(),do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false) | ||||
2634 | "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); | ||||
2635 | Check(!Arg.getType()->isTokenTy(),do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
2636 | "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); | ||||
2637 | Check(!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) | ||||
2638 | "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); | ||||
2639 | } | ||||
2640 | |||||
2641 | // Check that swifterror argument is only used by loads and stores. | ||||
2642 | if (Attrs.hasParamAttr(i, Attribute::SwiftError)) { | ||||
2643 | verifySwiftErrorValue(&Arg); | ||||
2644 | } | ||||
2645 | ++i; | ||||
2646 | } | ||||
2647 | |||||
2648 | if (!IsIntrinsic) { | ||||
2649 | Check(!F.getReturnType()->isTokenTy(),do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false) | ||||
2650 | "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); | ||||
2651 | Check(!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) | ||||
2652 | "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); | ||||
2653 | } | ||||
2654 | |||||
2655 | // Get the function metadata attachments. | ||||
2656 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
2657 | F.getAllMetadata(MDs); | ||||
2658 | assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync")(static_cast <bool> (F.hasMetadata() != MDs.empty() && "Bit out-of-sync") ? void (0) : __assert_fail ("F.hasMetadata() != MDs.empty() && \"Bit out-of-sync\"" , "llvm/lib/IR/Verifier.cpp", 2658, __extension__ __PRETTY_FUNCTION__ )); | ||||
2659 | verifyFunctionMetadata(MDs); | ||||
2660 | |||||
2661 | // Check validity of the personality function | ||||
2662 | if (F.hasPersonalityFn()) { | ||||
2663 | auto *Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); | ||||
2664 | if (Per) | ||||
2665 | Check(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) | ||||
2666 | "Referencing personality function in another module!", &F,do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false) | ||||
2667 | 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); | ||||
2668 | } | ||||
2669 | |||||
2670 | // EH funclet coloring can be expensive, recompute on-demand | ||||
2671 | BlockEHFuncletColors.clear(); | ||||
2672 | |||||
2673 | if (F.isMaterializable()) { | ||||
2674 | // Function has a body somewhere we can't see. | ||||
2675 | Check(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) | ||||
2676 | 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); | ||||
2677 | } else if (F.isDeclaration()) { | ||||
2678 | for (const auto &I : MDs) { | ||||
2679 | // This is used for call site debug information. | ||||
2680 | CheckDI(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) | ||||
2681 | !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) | ||||
2682 | "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) | ||||
2683 | &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); | ||||
2684 | Check(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) | ||||
2685 | "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); | ||||
2686 | |||||
2687 | // Verify the metadata itself. | ||||
2688 | visitMDNode(*I.second, AreDebugLocsAllowed::Yes); | ||||
2689 | } | ||||
2690 | Check(!F.hasPersonalityFn(),do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false) | ||||
2691 | "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); | ||||
2692 | } else { | ||||
2693 | // Verify that this function (which has a body) is not named "llvm.*". It | ||||
2694 | // is not legal to define intrinsics. | ||||
2695 | Check(!IsIntrinsic, "llvm intrinsics cannot be defined!", &F)do { if (!(!IsIntrinsic)) { CheckFailed("llvm intrinsics cannot be defined!" , &F); return; } } while (false); | ||||
2696 | |||||
2697 | // Check the entry node | ||||
2698 | const BasicBlock *Entry = &F.getEntryBlock(); | ||||
2699 | Check(pred_empty(Entry),do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false) | ||||
2700 | "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); | ||||
2701 | |||||
2702 | // The address of the entry block cannot be taken, unless it is dead. | ||||
2703 | if (Entry->hasAddressTaken()) { | ||||
2704 | Check(!BlockAddress::lookup(Entry)->isConstantUsed(),do { if (!(!BlockAddress::lookup(Entry)->isConstantUsed()) ) { CheckFailed("blockaddress may not be used with the entry block!" , Entry); return; } } while (false) | ||||
2705 | "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); | ||||
2706 | } | ||||
2707 | |||||
2708 | unsigned NumDebugAttachments = 0, NumProfAttachments = 0, | ||||
2709 | NumKCFIAttachments = 0; | ||||
2710 | // Visit metadata attachments. | ||||
2711 | for (const auto &I : MDs) { | ||||
2712 | // Verify that the attachment is legal. | ||||
2713 | auto AllowLocs = AreDebugLocsAllowed::No; | ||||
2714 | switch (I.first) { | ||||
2715 | default: | ||||
2716 | break; | ||||
2717 | case LLVMContext::MD_dbg: { | ||||
2718 | ++NumDebugAttachments; | ||||
2719 | CheckDI(NumDebugAttachments == 1,do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false) | ||||
2720 | "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); | ||||
2721 | CheckDI(isa<DISubprogram>(I.second),do { if (!(isa<DISubprogram>(I.second))) { DebugInfoCheckFailed ("function !dbg attachment must be a subprogram", &F, I.second ); return; } } while (false) | ||||
2722 | "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); | ||||
2723 | CheckDI(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) | ||||
2724 | "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) | ||||
2725 | &F)do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false); | ||||
2726 | |||||
2727 | auto *SP = cast<DISubprogram>(I.second); | ||||
2728 | const Function *&AttachedTo = DISubprogramAttachments[SP]; | ||||
2729 | CheckDI(!AttachedTo || AttachedTo == &F,do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false) | ||||
2730 | "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); | ||||
2731 | AttachedTo = &F; | ||||
2732 | AllowLocs = AreDebugLocsAllowed::Yes; | ||||
2733 | break; | ||||
2734 | } | ||||
2735 | case LLVMContext::MD_prof: | ||||
2736 | ++NumProfAttachments; | ||||
2737 | Check(NumProfAttachments == 1,do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false) | ||||
2738 | "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); | ||||
2739 | break; | ||||
2740 | case LLVMContext::MD_kcfi_type: | ||||
2741 | ++NumKCFIAttachments; | ||||
2742 | Check(NumKCFIAttachments == 1,do { if (!(NumKCFIAttachments == 1)) { CheckFailed("function must have a single !kcfi_type attachment" , &F, I.second); return; } } while (false) | ||||
2743 | "function must have a single !kcfi_type attachment", &F,do { if (!(NumKCFIAttachments == 1)) { CheckFailed("function must have a single !kcfi_type attachment" , &F, I.second); return; } } while (false) | ||||
2744 | I.second)do { if (!(NumKCFIAttachments == 1)) { CheckFailed("function must have a single !kcfi_type attachment" , &F, I.second); return; } } while (false); | ||||
2745 | break; | ||||
2746 | } | ||||
2747 | |||||
2748 | // Verify the metadata itself. | ||||
2749 | visitMDNode(*I.second, AllowLocs); | ||||
2750 | } | ||||
2751 | } | ||||
2752 | |||||
2753 | // If this function is actually an intrinsic, verify that it is only used in | ||||
2754 | // direct call/invokes, never having its "address taken". | ||||
2755 | // Only do this if the module is materialized, otherwise we don't have all the | ||||
2756 | // uses. | ||||
2757 | if (F.isIntrinsic() && F.getParent()->isMaterialized()) { | ||||
2758 | const User *U; | ||||
2759 | if (F.hasAddressTaken(&U, false, true, false, | ||||
2760 | /*IgnoreARCAttachedCall=*/true)) | ||||
2761 | Check(false, "Invalid user of intrinsic instruction!", U)do { if (!(false)) { CheckFailed("Invalid user of intrinsic instruction!" , U); return; } } while (false); | ||||
2762 | } | ||||
2763 | |||||
2764 | // Check intrinsics' signatures. | ||||
2765 | switch (F.getIntrinsicID()) { | ||||
2766 | case Intrinsic::experimental_gc_get_pointer_base: { | ||||
2767 | FunctionType *FT = F.getFunctionType(); | ||||
2768 | Check(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
2769 | Check(isa<PointerType>(F.getReturnType()),do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false) | ||||
2770 | "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); | ||||
2771 | Check(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) | ||||
2772 | "gc.get.pointer.base operand and result must be of the same type", 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); | ||||
2773 | break; | ||||
2774 | } | ||||
2775 | case Intrinsic::experimental_gc_get_pointer_offset: { | ||||
2776 | FunctionType *FT = F.getFunctionType(); | ||||
2777 | Check(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
2778 | Check(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) | ||||
2779 | "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); | ||||
2780 | Check(F.getReturnType()->isIntegerTy(),do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false) | ||||
2781 | "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); | ||||
2782 | break; | ||||
2783 | } | ||||
2784 | } | ||||
2785 | |||||
2786 | auto *N = F.getSubprogram(); | ||||
2787 | HasDebugInfo = (N != nullptr); | ||||
2788 | if (!HasDebugInfo
| ||||
2789 | return; | ||||
2790 | |||||
2791 | // Check that all !dbg attachments lead to back to N. | ||||
2792 | // | ||||
2793 | // FIXME: Check this incrementally while visiting !dbg attachments. | ||||
2794 | // FIXME: Only check when N is the canonical subprogram for F. | ||||
2795 | SmallPtrSet<const MDNode *, 32> Seen; | ||||
2796 | auto VisitDebugLoc = [&](const Instruction &I, const MDNode *Node) { | ||||
2797 | // Be careful about using DILocation here since we might be dealing with | ||||
2798 | // broken code (this is the Verifier after all). | ||||
2799 | const DILocation *DL = dyn_cast_or_null<DILocation>(Node); | ||||
2800 | if (!DL
| ||||
2801 | return; | ||||
2802 | if (!Seen.insert(DL).second) | ||||
2803 | return; | ||||
2804 | |||||
2805 | Metadata *Parent = DL->getRawScope(); | ||||
2806 | CheckDI(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) | ||||
2807 | "DILocation's scope must be a DILocalScope", N, &F, &I, DL, Parent)do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false); | ||||
2808 | |||||
2809 | DILocalScope *Scope = DL->getInlinedAtScope(); | ||||
2810 | Check(Scope, "Failed to find DILocalScope", DL)do { if (!(Scope)) { CheckFailed("Failed to find DILocalScope" , DL); return; } } while (false); | ||||
2811 | |||||
2812 | if (!Seen.insert(Scope).second) | ||||
2813 | return; | ||||
2814 | |||||
2815 | DISubprogram *SP = Scope->getSubprogram(); | ||||
2816 | |||||
2817 | // Scope and SP could be the same MDNode and we don't want to skip | ||||
2818 | // validation in that case | ||||
2819 | if (SP && ((Scope != SP) && !Seen.insert(SP).second)) | ||||
2820 | return; | ||||
2821 | |||||
2822 | CheckDI(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) | ||||
| |||||
2823 | "!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) | ||||
2824 | &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); | ||||
2825 | }; | ||||
2826 | for (auto &BB : F) | ||||
2827 | for (auto &I : BB) { | ||||
2828 | VisitDebugLoc(I, I.getDebugLoc().getAsMDNode()); | ||||
2829 | // The llvm.loop annotations also contain two DILocations. | ||||
2830 | if (auto MD = I.getMetadata(LLVMContext::MD_loop)) | ||||
2831 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) | ||||
2832 | VisitDebugLoc(I, dyn_cast_or_null<MDNode>(MD->getOperand(i))); | ||||
2833 | if (BrokenDebugInfo) | ||||
2834 | return; | ||||
2835 | } | ||||
2836 | } | ||||
2837 | |||||
2838 | // verifyBasicBlock - Verify that a basic block is well formed... | ||||
2839 | // | ||||
2840 | void Verifier::visitBasicBlock(BasicBlock &BB) { | ||||
2841 | InstsInThisBlock.clear(); | ||||
2842 | |||||
2843 | // Ensure that basic blocks have terminators! | ||||
2844 | Check(BB.getTerminator(), "Basic Block does not have terminator!", &BB)do { if (!(BB.getTerminator())) { CheckFailed("Basic Block does not have terminator!" , &BB); return; } } while (false); | ||||
2845 | |||||
2846 | // Check constraints that this basic block imposes on all of the PHI nodes in | ||||
2847 | // it. | ||||
2848 | if (isa<PHINode>(BB.front())) { | ||||
2849 | SmallVector<BasicBlock *, 8> Preds(predecessors(&BB)); | ||||
2850 | SmallVector<std::pair<BasicBlock*, Value*>, 8> Values; | ||||
2851 | llvm::sort(Preds); | ||||
2852 | for (const PHINode &PN : BB.phis()) { | ||||
2853 | Check(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) | ||||
2854 | "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) | ||||
2855 | "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) | ||||
2856 | &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); | ||||
2857 | |||||
2858 | // Get and sort all incoming values in the PHI node... | ||||
2859 | Values.clear(); | ||||
2860 | Values.reserve(PN.getNumIncomingValues()); | ||||
2861 | for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) | ||||
2862 | Values.push_back( | ||||
2863 | std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i))); | ||||
2864 | llvm::sort(Values); | ||||
2865 | |||||
2866 | for (unsigned i = 0, e = Values.size(); i != e; ++i) { | ||||
2867 | // Check to make sure that if there is more than one entry for a | ||||
2868 | // particular basic block in this PHI node, that the incoming values are | ||||
2869 | // all identical. | ||||
2870 | // | ||||
2871 | Check(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) | ||||
2872 | 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) | ||||
2873 | "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) | ||||
2874 | "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) | ||||
2875 | &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); | ||||
2876 | |||||
2877 | // Check to make sure that the predecessors and PHI node entries are | ||||
2878 | // matched up. | ||||
2879 | Check(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 ) | ||||
2880 | "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 ) | ||||
2881 | 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 ); | ||||
2882 | } | ||||
2883 | } | ||||
2884 | } | ||||
2885 | |||||
2886 | // Check that all instructions have their parent pointers set up correctly. | ||||
2887 | for (auto &I : BB) | ||||
2888 | { | ||||
2889 | Check(I.getParent() == &BB, "Instruction has bogus parent pointer!")do { if (!(I.getParent() == &BB)) { CheckFailed("Instruction has bogus parent pointer!" ); return; } } while (false); | ||||
2890 | } | ||||
2891 | } | ||||
2892 | |||||
2893 | void Verifier::visitTerminator(Instruction &I) { | ||||
2894 | // Ensure that terminators only exist at the end of the basic block. | ||||
2895 | Check(&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) | ||||
2896 | "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); | ||||
2897 | visitInstruction(I); | ||||
2898 | } | ||||
2899 | |||||
2900 | void Verifier::visitBranchInst(BranchInst &BI) { | ||||
2901 | if (BI.isConditional()) { | ||||
2902 | Check(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) | ||||
2903 | "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); | ||||
2904 | } | ||||
2905 | visitTerminator(BI); | ||||
2906 | } | ||||
2907 | |||||
2908 | void Verifier::visitReturnInst(ReturnInst &RI) { | ||||
2909 | Function *F = RI.getParent()->getParent(); | ||||
2910 | unsigned N = RI.getNumOperands(); | ||||
2911 | if (F->getReturnType()->isVoidTy()) | ||||
2912 | Check(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) | ||||
2913 | "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) | ||||
2914 | "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) | ||||
2915 | &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); | ||||
2916 | else | ||||
2917 | Check(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) | ||||
2918 | "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) | ||||
2919 | "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) | ||||
2920 | &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); | ||||
2921 | |||||
2922 | // Check to make sure that the return value has necessary properties for | ||||
2923 | // terminators... | ||||
2924 | visitTerminator(RI); | ||||
2925 | } | ||||
2926 | |||||
2927 | void Verifier::visitSwitchInst(SwitchInst &SI) { | ||||
2928 | Check(SI.getType()->isVoidTy(), "Switch must have void result type!", &SI)do { if (!(SI.getType()->isVoidTy())) { CheckFailed("Switch must have void result type!" , &SI); return; } } while (false); | ||||
2929 | // Check to make sure that all of the constants in the switch instruction | ||||
2930 | // have the same type as the switched-on value. | ||||
2931 | Type *SwitchTy = SI.getCondition()->getType(); | ||||
2932 | SmallPtrSet<ConstantInt*, 32> Constants; | ||||
2933 | for (auto &Case : SI.cases()) { | ||||
2934 | Check(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex() * 2 + 2)),do { if (!(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex () * 2 + 2)))) { CheckFailed("Case value is not a constant integer." , &SI); return; } } while (false) | ||||
2935 | "Case value is not a constant integer.", &SI)do { if (!(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex () * 2 + 2)))) { CheckFailed("Case value is not a constant integer." , &SI); return; } } while (false); | ||||
2936 | Check(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) | ||||
2937 | "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); | ||||
2938 | Check(Constants.insert(Case.getCaseValue()).second,do { if (!(Constants.insert(Case.getCaseValue()).second)) { CheckFailed ("Duplicate integer as switch case", &SI, Case.getCaseValue ()); return; } } while (false) | ||||
2939 | "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); | ||||
2940 | } | ||||
2941 | |||||
2942 | visitTerminator(SI); | ||||
2943 | } | ||||
2944 | |||||
2945 | void Verifier::visitIndirectBrInst(IndirectBrInst &BI) { | ||||
2946 | Check(BI.getAddress()->getType()->isPointerTy(),do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false) | ||||
2947 | "Indirectbr operand must have pointer type!", &BI)do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false); | ||||
2948 | for (unsigned i = 0, e = BI.getNumDestinations(); i != e; ++i) | ||||
2949 | Check(BI.getDestination(i)->getType()->isLabelTy(),do { if (!(BI.getDestination(i)->getType()->isLabelTy() )) { CheckFailed("Indirectbr destinations must all have pointer type!" , &BI); return; } } while (false) | ||||
2950 | "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); | ||||
2951 | |||||
2952 | visitTerminator(BI); | ||||
2953 | } | ||||
2954 | |||||
2955 | void Verifier::visitCallBrInst(CallBrInst &CBI) { | ||||
2956 | Check(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!", &CBI)do { if (!(CBI.isInlineAsm())) { CheckFailed("Callbr is currently only used for asm-goto!" , &CBI); return; } } while (false); | ||||
2957 | const InlineAsm *IA = cast<InlineAsm>(CBI.getCalledOperand()); | ||||
2958 | Check(!IA->canThrow(), "Unwinding from Callbr is not allowed")do { if (!(!IA->canThrow())) { CheckFailed("Unwinding from Callbr is not allowed" ); return; } } while (false); | ||||
2959 | |||||
2960 | verifyInlineAsmCall(CBI); | ||||
2961 | visitTerminator(CBI); | ||||
2962 | } | ||||
2963 | |||||
2964 | void Verifier::visitSelectInst(SelectInst &SI) { | ||||
2965 | Check(!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) | ||||
2966 | 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) | ||||
2967 | "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); | ||||
2968 | |||||
2969 | Check(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) | ||||
2970 | "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); | ||||
2971 | visitInstruction(SI); | ||||
2972 | } | ||||
2973 | |||||
2974 | /// visitUserOp1 - User defined operators shouldn't live beyond the lifetime of | ||||
2975 | /// a pass, if any exist, it's an error. | ||||
2976 | /// | ||||
2977 | void Verifier::visitUserOp1(Instruction &I) { | ||||
2978 | Check(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); | ||||
2979 | } | ||||
2980 | |||||
2981 | void Verifier::visitTruncInst(TruncInst &I) { | ||||
2982 | // Get the source and destination types | ||||
2983 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
2984 | Type *DestTy = I.getType(); | ||||
2985 | |||||
2986 | // Get the size of the types in bits, we'll need this later | ||||
2987 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
2988 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
2989 | |||||
2990 | Check(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only operates on integer" , &I); return; } } while (false); | ||||
2991 | Check(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only produces integer" , &I); return; } } while (false); | ||||
2992 | Check(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) | ||||
2993 | "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); | ||||
2994 | Check(SrcBitSize > DestBitSize, "DestTy too big for Trunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for Trunc" , &I); return; } } while (false); | ||||
2995 | |||||
2996 | visitInstruction(I); | ||||
2997 | } | ||||
2998 | |||||
2999 | void Verifier::visitZExtInst(ZExtInst &I) { | ||||
3000 | // Get the source and destination types | ||||
3001 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3002 | Type *DestTy = I.getType(); | ||||
3003 | |||||
3004 | // Get the size of the types in bits, we'll need this later | ||||
3005 | Check(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only operates on integer" , &I); return; } } while (false); | ||||
3006 | Check(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only produces an integer" , &I); return; } } while (false); | ||||
3007 | Check(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) | ||||
3008 | "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); | ||||
3009 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
3010 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
3011 | |||||
3012 | Check(SrcBitSize < DestBitSize, "Type too small for ZExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for ZExt" , &I); return; } } while (false); | ||||
3013 | |||||
3014 | visitInstruction(I); | ||||
3015 | } | ||||
3016 | |||||
3017 | void Verifier::visitSExtInst(SExtInst &I) { | ||||
3018 | // Get the source and destination types | ||||
3019 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3020 | Type *DestTy = I.getType(); | ||||
3021 | |||||
3022 | // Get the size of the types in bits, we'll need this later | ||||
3023 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
3024 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
3025 | |||||
3026 | Check(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SExt only operates on integer" , &I); return; } } while (false); | ||||
3027 | Check(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("SExt only produces an integer" , &I); return; } } while (false); | ||||
3028 | Check(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) | ||||
3029 | "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); | ||||
3030 | Check(SrcBitSize < DestBitSize, "Type too small for SExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for SExt" , &I); return; } } while (false); | ||||
3031 | |||||
3032 | visitInstruction(I); | ||||
3033 | } | ||||
3034 | |||||
3035 | void Verifier::visitFPTruncInst(FPTruncInst &I) { | ||||
3036 | // Get the source and destination types | ||||
3037 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3038 | Type *DestTy = I.getType(); | ||||
3039 | // Get the size of the types in bits, we'll need this later | ||||
3040 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
3041 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
3042 | |||||
3043 | Check(SrcTy->isFPOrFPVectorTy(), "FPTrunc only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only operates on FP" , &I); return; } } while (false); | ||||
3044 | Check(DestTy->isFPOrFPVectorTy(), "FPTrunc only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only produces an FP" , &I); return; } } while (false); | ||||
3045 | Check(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) | ||||
3046 | "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); | ||||
3047 | Check(SrcBitSize > DestBitSize, "DestTy too big for FPTrunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for FPTrunc" , &I); return; } } while (false); | ||||
3048 | |||||
3049 | visitInstruction(I); | ||||
3050 | } | ||||
3051 | |||||
3052 | void Verifier::visitFPExtInst(FPExtInst &I) { | ||||
3053 | // Get the source and destination types | ||||
3054 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3055 | Type *DestTy = I.getType(); | ||||
3056 | |||||
3057 | // Get the size of the types in bits, we'll need this later | ||||
3058 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
3059 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
3060 | |||||
3061 | Check(SrcTy->isFPOrFPVectorTy(), "FPExt only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only operates on FP" , &I); return; } } while (false); | ||||
3062 | Check(DestTy->isFPOrFPVectorTy(), "FPExt only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only produces an FP" , &I); return; } } while (false); | ||||
3063 | Check(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) | ||||
3064 | "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); | ||||
3065 | Check(SrcBitSize < DestBitSize, "DestTy too small for FPExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("DestTy too small for FPExt" , &I); return; } } while (false); | ||||
3066 | |||||
3067 | visitInstruction(I); | ||||
3068 | } | ||||
3069 | |||||
3070 | void Verifier::visitUIToFPInst(UIToFPInst &I) { | ||||
3071 | // Get the source and destination types | ||||
3072 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3073 | Type *DestTy = I.getType(); | ||||
3074 | |||||
3075 | bool SrcVec = SrcTy->isVectorTy(); | ||||
3076 | bool DstVec = DestTy->isVectorTy(); | ||||
3077 | |||||
3078 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
3079 | "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); | ||||
3080 | Check(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
3081 | "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); | ||||
3082 | Check(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) | ||||
3083 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
3084 | |||||
3085 | if (SrcVec && DstVec) | ||||
3086 | Check(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) | ||||
3087 | 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) | ||||
3088 | "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); | ||||
3089 | |||||
3090 | visitInstruction(I); | ||||
3091 | } | ||||
3092 | |||||
3093 | void Verifier::visitSIToFPInst(SIToFPInst &I) { | ||||
3094 | // Get the source and destination types | ||||
3095 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3096 | Type *DestTy = I.getType(); | ||||
3097 | |||||
3098 | bool SrcVec = SrcTy->isVectorTy(); | ||||
3099 | bool DstVec = DestTy->isVectorTy(); | ||||
3100 | |||||
3101 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
3102 | "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); | ||||
3103 | Check(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
3104 | "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); | ||||
3105 | Check(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) | ||||
3106 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
3107 | |||||
3108 | if (SrcVec && DstVec) | ||||
3109 | Check(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) | ||||
3110 | 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) | ||||
3111 | "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); | ||||
3112 | |||||
3113 | visitInstruction(I); | ||||
3114 | } | ||||
3115 | |||||
3116 | void Verifier::visitFPToUIInst(FPToUIInst &I) { | ||||
3117 | // Get the source and destination types | ||||
3118 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3119 | Type *DestTy = I.getType(); | ||||
3120 | |||||
3121 | bool SrcVec = SrcTy->isVectorTy(); | ||||
3122 | bool DstVec = DestTy->isVectorTy(); | ||||
3123 | |||||
3124 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
3125 | "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); | ||||
3126 | Check(SrcTy->isFPOrFPVectorTy(), "FPToUI source must be FP or FP vector", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToUI source must be FP or FP vector" , &I); return; } } while (false); | ||||
3127 | Check(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false) | ||||
3128 | "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); | ||||
3129 | |||||
3130 | if (SrcVec && DstVec) | ||||
3131 | Check(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) | ||||
3132 | 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) | ||||
3133 | "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); | ||||
3134 | |||||
3135 | visitInstruction(I); | ||||
3136 | } | ||||
3137 | |||||
3138 | void Verifier::visitFPToSIInst(FPToSIInst &I) { | ||||
3139 | // Get the source and destination types | ||||
3140 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3141 | Type *DestTy = I.getType(); | ||||
3142 | |||||
3143 | bool SrcVec = SrcTy->isVectorTy(); | ||||
3144 | bool DstVec = DestTy->isVectorTy(); | ||||
3145 | |||||
3146 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
3147 | "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); | ||||
3148 | Check(SrcTy->isFPOrFPVectorTy(), "FPToSI source must be FP or FP vector", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToSI source must be FP or FP vector" , &I); return; } } while (false); | ||||
3149 | Check(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false) | ||||
3150 | "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); | ||||
3151 | |||||
3152 | if (SrcVec && DstVec) | ||||
3153 | Check(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) | ||||
3154 | 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) | ||||
3155 | "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); | ||||
3156 | |||||
3157 | visitInstruction(I); | ||||
3158 | } | ||||
3159 | |||||
3160 | void Verifier::visitPtrToIntInst(PtrToIntInst &I) { | ||||
3161 | // Get the source and destination types | ||||
3162 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3163 | Type *DestTy = I.getType(); | ||||
3164 | |||||
3165 | Check(SrcTy->isPtrOrPtrVectorTy(), "PtrToInt source must be pointer", &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("PtrToInt source must be pointer" , &I); return; } } while (false); | ||||
3166 | |||||
3167 | Check(DestTy->isIntOrIntVectorTy(), "PtrToInt result must be integral", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("PtrToInt result must be integral" , &I); return; } } while (false); | ||||
3168 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false) | ||||
3169 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false); | ||||
3170 | |||||
3171 | if (SrcTy->isVectorTy()) { | ||||
3172 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
3173 | auto *VDest = cast<VectorType>(DestTy); | ||||
3174 | Check(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false) | ||||
3175 | "PtrToInt Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false); | ||||
3176 | } | ||||
3177 | |||||
3178 | visitInstruction(I); | ||||
3179 | } | ||||
3180 | |||||
3181 | void Verifier::visitIntToPtrInst(IntToPtrInst &I) { | ||||
3182 | // Get the source and destination types | ||||
3183 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3184 | Type *DestTy = I.getType(); | ||||
3185 | |||||
3186 | Check(SrcTy->isIntOrIntVectorTy(), "IntToPtr source must be an integral", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false); | ||||
3187 | Check(DestTy->isPtrOrPtrVectorTy(), "IntToPtr result must be a pointer", &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("IntToPtr result must be a pointer" , &I); return; } } while (false); | ||||
3188 | |||||
3189 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false) | ||||
3190 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false); | ||||
3191 | if (SrcTy->isVectorTy()) { | ||||
3192 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
3193 | auto *VDest = cast<VectorType>(DestTy); | ||||
3194 | Check(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false) | ||||
3195 | "IntToPtr Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false); | ||||
3196 | } | ||||
3197 | visitInstruction(I); | ||||
3198 | } | ||||
3199 | |||||
3200 | void Verifier::visitBitCastInst(BitCastInst &I) { | ||||
3201 | Check(do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
3202 | 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) | ||||
3203 | "Invalid bitcast", &I)do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false); | ||||
3204 | visitInstruction(I); | ||||
3205 | } | ||||
3206 | |||||
3207 | void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { | ||||
3208 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
3209 | Type *DestTy = I.getType(); | ||||
3210 | |||||
3211 | Check(SrcTy->isPtrOrPtrVectorTy(), "AddrSpaceCast source must be a pointer",do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false) | ||||
3212 | &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false); | ||||
3213 | Check(DestTy->isPtrOrPtrVectorTy(), "AddrSpaceCast result must be a pointer",do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false) | ||||
3214 | &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false); | ||||
3215 | Check(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(),do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false) | ||||
3216 | "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); | ||||
3217 | if (auto *SrcVTy = dyn_cast<VectorType>(SrcTy)) | ||||
3218 | Check(SrcVTy->getElementCount() ==do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
3219 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
3220 | "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); | ||||
3221 | visitInstruction(I); | ||||
3222 | } | ||||
3223 | |||||
3224 | /// visitPHINode - Ensure that a PHI node is well formed. | ||||
3225 | /// | ||||
3226 | void Verifier::visitPHINode(PHINode &PN) { | ||||
3227 | // Ensure that the PHI nodes are all grouped together at the top of the block. | ||||
3228 | // This can be tested by checking whether the instruction before this is | ||||
3229 | // either nonexistent (because this is begin()) or is a PHI node. If not, | ||||
3230 | // then there is some other instruction before a PHI. | ||||
3231 | Check(&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) | ||||
3232 | 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) | ||||
3233 | "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); | ||||
3234 | |||||
3235 | // Check that a PHI doesn't yield a Token. | ||||
3236 | Check(!PN.getType()->isTokenTy(), "PHI nodes cannot have token type!")do { if (!(!PN.getType()->isTokenTy())) { CheckFailed("PHI nodes cannot have token type!" ); return; } } while (false); | ||||
3237 | |||||
3238 | // Check that all of the values of the PHI node have the same type as the | ||||
3239 | // result, and that the incoming blocks are really basic blocks. | ||||
3240 | for (Value *IncValue : PN.incoming_values()) { | ||||
3241 | Check(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) | ||||
3242 | "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); | ||||
3243 | } | ||||
3244 | |||||
3245 | // All other PHI node constraints are checked in the visitBasicBlock method. | ||||
3246 | |||||
3247 | visitInstruction(PN); | ||||
3248 | } | ||||
3249 | |||||
3250 | void Verifier::visitCallBase(CallBase &Call) { | ||||
3251 | Check(Call.getCalledOperand()->getType()->isPointerTy(),do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false) | ||||
3252 | "Called function must be a pointer!", Call)do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false); | ||||
3253 | PointerType *FPTy = cast<PointerType>(Call.getCalledOperand()->getType()); | ||||
3254 | |||||
3255 | Check(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) | ||||
3256 | "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); | ||||
3257 | |||||
3258 | FunctionType *FTy = Call.getFunctionType(); | ||||
3259 | |||||
3260 | // Verify that the correct number of arguments are being passed | ||||
3261 | if (FTy->isVarArg()) | ||||
3262 | Check(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) | ||||
3263 | "Called function requires more parameters than were provided!", Call)do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false); | ||||
3264 | else | ||||
3265 | Check(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) | ||||
3266 | "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); | ||||
3267 | |||||
3268 | // Verify that all arguments to the call match the function type. | ||||
3269 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) | ||||
3270 | Check(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) | ||||
3271 | "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) | ||||
3272 | 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); | ||||
3273 | |||||
3274 | AttributeList Attrs = Call.getAttributes(); | ||||
3275 | |||||
3276 | Check(verifyAttributeCount(Attrs, Call.arg_size()),do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false) | ||||
3277 | "Attribute after last parameter!", Call)do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false); | ||||
3278 | |||||
3279 | Function *Callee = | ||||
3280 | dyn_cast<Function>(Call.getCalledOperand()->stripPointerCasts()); | ||||
3281 | bool IsIntrinsic = Callee && Callee->isIntrinsic(); | ||||
3282 | if (IsIntrinsic) | ||||
3283 | Check(Callee->getValueType() == FTy,do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false) | ||||
3284 | "Intrinsic called with incompatible signature", Call)do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false); | ||||
3285 | |||||
3286 | auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) { | ||||
3287 | if (!Ty->isSized()) | ||||
3288 | return; | ||||
3289 | Align ABIAlign = DL.getABITypeAlign(Ty); | ||||
3290 | Align MaxAlign(ParamMaxAlignment); | ||||
3291 | Check(ABIAlign <= MaxAlign,do { if (!(ABIAlign <= MaxAlign)) { CheckFailed("Incorrect alignment of " + Message + " to called function!", Call); return; } } while (false) | ||||
3292 | "Incorrect alignment of " + Message + " to called function!", Call)do { if (!(ABIAlign <= MaxAlign)) { CheckFailed("Incorrect alignment of " + Message + " to called function!", Call); return; } } while (false); | ||||
3293 | }; | ||||
3294 | |||||
3295 | if (!IsIntrinsic) { | ||||
3296 | VerifyTypeAlign(FTy->getReturnType(), "return type"); | ||||
3297 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { | ||||
3298 | Type *Ty = FTy->getParamType(i); | ||||
3299 | VerifyTypeAlign(Ty, "argument passed"); | ||||
3300 | } | ||||
3301 | } | ||||
3302 | |||||
3303 | if (Attrs.hasFnAttr(Attribute::Speculatable)) { | ||||
3304 | // Don't allow speculatable on call sites, unless the underlying function | ||||
3305 | // declaration is also speculatable. | ||||
3306 | Check(Callee && Callee->isSpeculatable(),do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false) | ||||
3307 | "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); | ||||
3308 | } | ||||
3309 | |||||
3310 | if (Attrs.hasFnAttr(Attribute::Preallocated)) { | ||||
3311 | Check(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) | ||||
3312 | 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) | ||||
3313 | "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) | ||||
3314 | "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); | ||||
3315 | } | ||||
3316 | |||||
3317 | // Verify call attributes. | ||||
3318 | verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic, Call.isInlineAsm()); | ||||
3319 | |||||
3320 | // Conservatively check the inalloca argument. | ||||
3321 | // We have a bug if we can find that there is an underlying alloca without | ||||
3322 | // inalloca. | ||||
3323 | if (Call.hasInAllocaArgument()) { | ||||
3324 | Value *InAllocaArg = Call.getArgOperand(FTy->getNumParams() - 1); | ||||
3325 | if (auto AI = dyn_cast<AllocaInst>(InAllocaArg->stripInBoundsOffsets())) | ||||
3326 | Check(AI->isUsedWithInAlloca(),do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
3327 | "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); | ||||
3328 | } | ||||
3329 | |||||
3330 | // For each argument of the callsite, if it has the swifterror argument, | ||||
3331 | // make sure the underlying alloca/parameter it comes from has a swifterror as | ||||
3332 | // well. | ||||
3333 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { | ||||
3334 | if (Call.paramHasAttr(i, Attribute::SwiftError)) { | ||||
3335 | Value *SwiftErrorArg = Call.getArgOperand(i); | ||||
3336 | if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) { | ||||
3337 | Check(AI->isSwiftError(),do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
3338 | "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); | ||||
3339 | continue; | ||||
3340 | } | ||||
3341 | auto ArgI = dyn_cast<Argument>(SwiftErrorArg); | ||||
3342 | Check(ArgI, "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) | ||||
3343 | SwiftErrorArg, Call)do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false); | ||||
3344 | Check(ArgI->hasSwiftErrorAttr(),do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
3345 | "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) | ||||
3346 | Call)do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false); | ||||
3347 | } | ||||
3348 | |||||
3349 | if (Attrs.hasParamAttr(i, Attribute::ImmArg)) { | ||||
3350 | // Don't allow immarg on call sites, unless the underlying declaration | ||||
3351 | // also has the matching immarg. | ||||
3352 | Check(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) | ||||
3353 | "immarg may not apply only to call sites", Call.getArgOperand(i),do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false) | ||||
3354 | 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); | ||||
3355 | } | ||||
3356 | |||||
3357 | if (Call.paramHasAttr(i, Attribute::ImmArg)) { | ||||
3358 | Value *ArgVal = Call.getArgOperand(i); | ||||
3359 | Check(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) | ||||
3360 | "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); | ||||
3361 | } | ||||
3362 | |||||
3363 | if (Call.paramHasAttr(i, Attribute::Preallocated)) { | ||||
3364 | Value *ArgVal = Call.getArgOperand(i); | ||||
3365 | bool hasOB = | ||||
3366 | Call.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0; | ||||
3367 | bool isMustTail = Call.isMustTailCall(); | ||||
3368 | Check(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) | ||||
3369 | "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) | ||||
3370 | "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) | ||||
3371 | 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); | ||||
3372 | } | ||||
3373 | } | ||||
3374 | |||||
3375 | if (FTy->isVarArg()) { | ||||
3376 | // FIXME? is 'nest' even legal here? | ||||
3377 | bool SawNest = false; | ||||
3378 | bool SawReturned = false; | ||||
3379 | |||||
3380 | for (unsigned Idx = 0; Idx < FTy->getNumParams(); ++Idx) { | ||||
3381 | if (Attrs.hasParamAttr(Idx, Attribute::Nest)) | ||||
3382 | SawNest = true; | ||||
3383 | if (Attrs.hasParamAttr(Idx, Attribute::Returned)) | ||||
3384 | SawReturned = true; | ||||
3385 | } | ||||
3386 | |||||
3387 | // Check attributes on the varargs part. | ||||
3388 | for (unsigned Idx = FTy->getNumParams(); Idx < Call.arg_size(); ++Idx) { | ||||
3389 | Type *Ty = Call.getArgOperand(Idx)->getType(); | ||||
3390 | AttributeSet ArgAttrs = Attrs.getParamAttrs(Idx); | ||||
3391 | verifyParameterAttrs(ArgAttrs, Ty, &Call); | ||||
3392 | |||||
3393 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
3394 | Check(!SawNest, "More than one parameter has attribute nest!", Call)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , Call); return; } } while (false); | ||||
3395 | SawNest = true; | ||||
3396 | } | ||||
3397 | |||||
3398 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
3399 | Check(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false) | ||||
3400 | Call)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false); | ||||
3401 | Check(Ty->canLosslesslyBitCastTo(FTy->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
3402 | "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) | ||||
3403 | "attribute",do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
3404 | Call)do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false); | ||||
3405 | SawReturned = true; | ||||
3406 | } | ||||
3407 | |||||
3408 | // Statepoint intrinsic is vararg but the wrapped function may be not. | ||||
3409 | // Allow sret here and check the wrapped function in verifyStatepoint. | ||||
3410 | if (!Call.getCalledFunction() || | ||||
3411 | Call.getCalledFunction()->getIntrinsicID() != | ||||
3412 | Intrinsic::experimental_gc_statepoint) | ||||
3413 | Check(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
3414 | "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) | ||||
3415 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
3416 | |||||
3417 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) | ||||
3418 | Check(Idx == Call.arg_size() - 1,do { if (!(Idx == Call.arg_size() - 1)) { CheckFailed("inalloca isn't on the last argument!" , Call); return; } } while (false) | ||||
3419 | "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); | ||||
3420 | } | ||||
3421 | } | ||||
3422 | |||||
3423 | // Verify that there's no metadata unless it's a direct call to an intrinsic. | ||||
3424 | if (!IsIntrinsic) { | ||||
3425 | for (Type *ParamTy : FTy->params()) { | ||||
3426 | Check(!ParamTy->isMetadataTy(),do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
3427 | "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); | ||||
3428 | Check(!ParamTy->isTokenTy(),do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
3429 | "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); | ||||
3430 | } | ||||
3431 | } | ||||
3432 | |||||
3433 | // Verify that indirect calls don't return tokens. | ||||
3434 | if (!Call.getCalledFunction()) { | ||||
3435 | Check(!FTy->getReturnType()->isTokenTy(),do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false) | ||||
3436 | "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); | ||||
3437 | Check(!FTy->getReturnType()->isX86_AMXTy(),do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false) | ||||
3438 | "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); | ||||
3439 | } | ||||
3440 | |||||
3441 | if (Function *F = Call.getCalledFunction()) | ||||
3442 | if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) | ||||
3443 | visitIntrinsicCall(ID, Call); | ||||
3444 | |||||
3445 | // Verify that a callsite has at most one "deopt", at most one "funclet", at | ||||
3446 | // most one "gc-transition", at most one "cfguardtarget", at most one | ||||
3447 | // "preallocated" operand bundle, and at most one "ptrauth" operand bundle. | ||||
3448 | bool FoundDeoptBundle = false, FoundFuncletBundle = false, | ||||
3449 | FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false, | ||||
3450 | FoundPreallocatedBundle = false, FoundGCLiveBundle = false, | ||||
3451 | FoundPtrauthBundle = false, FoundKCFIBundle = false, | ||||
3452 | FoundAttachedCallBundle = false; | ||||
3453 | for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) { | ||||
3454 | OperandBundleUse BU = Call.getOperandBundleAt(i); | ||||
3455 | uint32_t Tag = BU.getTagID(); | ||||
3456 | if (Tag == LLVMContext::OB_deopt) { | ||||
3457 | Check(!FoundDeoptBundle, "Multiple deopt operand bundles", Call)do { if (!(!FoundDeoptBundle)) { CheckFailed("Multiple deopt operand bundles" , Call); return; } } while (false); | ||||
3458 | FoundDeoptBundle = true; | ||||
3459 | } else if (Tag == LLVMContext::OB_gc_transition) { | ||||
3460 | Check(!FoundGCTransitionBundle, "Multiple gc-transition operand bundles",do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false) | ||||
3461 | Call)do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false); | ||||
3462 | FoundGCTransitionBundle = true; | ||||
3463 | } else if (Tag == LLVMContext::OB_funclet) { | ||||
3464 | Check(!FoundFuncletBundle, "Multiple funclet operand bundles", Call)do { if (!(!FoundFuncletBundle)) { CheckFailed("Multiple funclet operand bundles" , Call); return; } } while (false); | ||||
3465 | FoundFuncletBundle = true; | ||||
3466 | Check(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false) | ||||
3467 | "Expected exactly one funclet bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false); | ||||
3468 | Check(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) | ||||
3469 | "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) | ||||
3470 | Call)do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false); | ||||
3471 | } else if (Tag == LLVMContext::OB_cfguardtarget) { | ||||
3472 | Check(!FoundCFGuardTargetBundle, "Multiple CFGuardTarget operand bundles",do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false) | ||||
3473 | Call)do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false); | ||||
3474 | FoundCFGuardTargetBundle = true; | ||||
3475 | Check(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false) | ||||
3476 | "Expected exactly one cfguardtarget bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false); | ||||
3477 | } else if (Tag == LLVMContext::OB_ptrauth) { | ||||
3478 | Check(!FoundPtrauthBundle, "Multiple ptrauth operand bundles", Call)do { if (!(!FoundPtrauthBundle)) { CheckFailed("Multiple ptrauth operand bundles" , Call); return; } } while (false); | ||||
3479 | FoundPtrauthBundle = true; | ||||
3480 | Check(BU.Inputs.size() == 2,do { if (!(BU.Inputs.size() == 2)) { CheckFailed("Expected exactly two ptrauth bundle operands" , Call); return; } } while (false) | ||||
3481 | "Expected exactly two ptrauth bundle operands", Call)do { if (!(BU.Inputs.size() == 2)) { CheckFailed("Expected exactly two ptrauth bundle operands" , Call); return; } } while (false); | ||||
3482 | Check(isa<ConstantInt>(BU.Inputs[0]) &&do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Ptrauth bundle key operand must be an i32 constant", Call); return ; } } while (false) | ||||
3483 | BU.Inputs[0]->getType()->isIntegerTy(32),do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Ptrauth bundle key operand must be an i32 constant", Call); return ; } } while (false) | ||||
3484 | "Ptrauth bundle key operand must be an i32 constant", Call)do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Ptrauth bundle key operand must be an i32 constant", Call); return ; } } while (false); | ||||
3485 | Check(BU.Inputs[1]->getType()->isIntegerTy(64),do { if (!(BU.Inputs[1]->getType()->isIntegerTy(64))) { CheckFailed("Ptrauth bundle discriminator operand must be an i64" , Call); return; } } while (false) | ||||
3486 | "Ptrauth bundle discriminator operand must be an i64", Call)do { if (!(BU.Inputs[1]->getType()->isIntegerTy(64))) { CheckFailed("Ptrauth bundle discriminator operand must be an i64" , Call); return; } } while (false); | ||||
3487 | } else if (Tag == LLVMContext::OB_kcfi) { | ||||
3488 | Check(!FoundKCFIBundle, "Multiple kcfi operand bundles", Call)do { if (!(!FoundKCFIBundle)) { CheckFailed("Multiple kcfi operand bundles" , Call); return; } } while (false); | ||||
3489 | FoundKCFIBundle = true; | ||||
3490 | Check(BU.Inputs.size() == 1, "Expected exactly one kcfi bundle operand",do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one kcfi bundle operand" , Call); return; } } while (false) | ||||
3491 | Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one kcfi bundle operand" , Call); return; } } while (false); | ||||
3492 | Check(isa<ConstantInt>(BU.Inputs[0]) &&do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Kcfi bundle operand must be an i32 constant", Call); return; } } while (false) | ||||
3493 | BU.Inputs[0]->getType()->isIntegerTy(32),do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Kcfi bundle operand must be an i32 constant", Call); return; } } while (false) | ||||
3494 | "Kcfi bundle operand must be an i32 constant", Call)do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Kcfi bundle operand must be an i32 constant", Call); return; } } while (false); | ||||
3495 | } else if (Tag == LLVMContext::OB_preallocated) { | ||||
3496 | Check(!FoundPreallocatedBundle, "Multiple preallocated operand bundles",do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false) | ||||
3497 | Call)do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false); | ||||
3498 | FoundPreallocatedBundle = true; | ||||
3499 | Check(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false) | ||||
3500 | "Expected exactly one preallocated bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false); | ||||
3501 | auto Input = dyn_cast<IntrinsicInst>(BU.Inputs.front()); | ||||
3502 | Check(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 ) | ||||
3503 | 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 ) | ||||
3504 | "\"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 ) | ||||
3505 | "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 ) | ||||
3506 | 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 ); | ||||
3507 | } else if (Tag == LLVMContext::OB_gc_live) { | ||||
3508 | Check(!FoundGCLiveBundle, "Multiple gc-live operand bundles", Call)do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false); | ||||
3509 | FoundGCLiveBundle = true; | ||||
3510 | } else if (Tag == LLVMContext::OB_clang_arc_attachedcall) { | ||||
3511 | Check(!FoundAttachedCallBundle,do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false) | ||||
3512 | "Multiple \"clang.arc.attachedcall\" operand bundles", Call)do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false); | ||||
3513 | FoundAttachedCallBundle = true; | ||||
3514 | verifyAttachedCallBundle(Call, BU); | ||||
3515 | } | ||||
3516 | } | ||||
3517 | |||||
3518 | // Verify that callee and callsite agree on whether to use pointer auth. | ||||
3519 | Check(!(Call.getCalledFunction() && FoundPtrauthBundle),do { if (!(!(Call.getCalledFunction() && FoundPtrauthBundle ))) { CheckFailed("Direct call cannot have a ptrauth bundle", Call); return; } } while (false) | ||||
3520 | "Direct call cannot have a ptrauth bundle", Call)do { if (!(!(Call.getCalledFunction() && FoundPtrauthBundle ))) { CheckFailed("Direct call cannot have a ptrauth bundle", Call); return; } } while (false); | ||||
3521 | |||||
3522 | // Verify that each inlinable callsite of a debug-info-bearing function in a | ||||
3523 | // debug-info-bearing function has a debug location attached to it. Failure to | ||||
3524 | // do so causes assertion failures when the inliner sets up inline scope info | ||||
3525 | // (Interposable functions are not inlinable, neither are functions without | ||||
3526 | // definitions.) | ||||
3527 | if (Call.getFunction()->getSubprogram() && Call.getCalledFunction() && | ||||
3528 | !Call.getCalledFunction()->isInterposable() && | ||||
3529 | !Call.getCalledFunction()->isDeclaration() && | ||||
3530 | Call.getCalledFunction()->getSubprogram()) | ||||
3531 | CheckDI(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) | ||||
3532 | "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) | ||||
3533 | "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) | ||||
3534 | Call)do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false); | ||||
3535 | |||||
3536 | if (Call.isInlineAsm()) | ||||
3537 | verifyInlineAsmCall(Call); | ||||
3538 | |||||
3539 | visitInstruction(Call); | ||||
3540 | } | ||||
3541 | |||||
3542 | void Verifier::verifyTailCCMustTailAttrs(const AttrBuilder &Attrs, | ||||
3543 | StringRef Context) { | ||||
3544 | Check(!Attrs.contains(Attribute::InAlloca),do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false) | ||||
3545 | Twine("inalloca attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false); | ||||
3546 | Check(!Attrs.contains(Attribute::InReg),do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false) | ||||
3547 | Twine("inreg attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false); | ||||
3548 | Check(!Attrs.contains(Attribute::SwiftError),do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false) | ||||
3549 | Twine("swifterror attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false); | ||||
3550 | Check(!Attrs.contains(Attribute::Preallocated),do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false) | ||||
3551 | Twine("preallocated attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false); | ||||
3552 | Check(!Attrs.contains(Attribute::ByRef),do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false) | ||||
3553 | Twine("byref attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false); | ||||
3554 | } | ||||
3555 | |||||
3556 | /// Two types are "congruent" if they are identical, or if they are both pointer | ||||
3557 | /// types with different pointee types and the same address space. | ||||
3558 | static bool isTypeCongruent(Type *L, Type *R) { | ||||
3559 | if (L == R) | ||||
3560 | return true; | ||||
3561 | PointerType *PL = dyn_cast<PointerType>(L); | ||||
3562 | PointerType *PR = dyn_cast<PointerType>(R); | ||||
3563 | if (!PL || !PR) | ||||
3564 | return false; | ||||
3565 | return PL->getAddressSpace() == PR->getAddressSpace(); | ||||
3566 | } | ||||
3567 | |||||
3568 | static AttrBuilder getParameterABIAttributes(LLVMContext& C, unsigned I, AttributeList Attrs) { | ||||
3569 | static const Attribute::AttrKind ABIAttrs[] = { | ||||
3570 | Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, | ||||
3571 | Attribute::InReg, Attribute::StackAlignment, Attribute::SwiftSelf, | ||||
3572 | Attribute::SwiftAsync, Attribute::SwiftError, Attribute::Preallocated, | ||||
3573 | Attribute::ByRef}; | ||||
3574 | AttrBuilder Copy(C); | ||||
3575 | for (auto AK : ABIAttrs) { | ||||
3576 | Attribute Attr = Attrs.getParamAttrs(I).getAttribute(AK); | ||||
3577 | if (Attr.isValid()) | ||||
3578 | Copy.addAttribute(Attr); | ||||
3579 | } | ||||
3580 | |||||
3581 | // `align` is ABI-affecting only in combination with `byval` or `byref`. | ||||
3582 | if (Attrs.hasParamAttr(I, Attribute::Alignment) && | ||||
3583 | (Attrs.hasParamAttr(I, Attribute::ByVal) || | ||||
3584 | Attrs.hasParamAttr(I, Attribute::ByRef))) | ||||
3585 | Copy.addAlignmentAttr(Attrs.getParamAlignment(I)); | ||||
3586 | return Copy; | ||||
3587 | } | ||||
3588 | |||||
3589 | void Verifier::verifyMustTailCall(CallInst &CI) { | ||||
3590 | Check(!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); | ||||
3591 | |||||
3592 | Function *F = CI.getParent()->getParent(); | ||||
3593 | FunctionType *CallerTy = F->getFunctionType(); | ||||
3594 | FunctionType *CalleeTy = CI.getFunctionType(); | ||||
3595 | Check(CallerTy->isVarArg() == CalleeTy->isVarArg(),do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false) | ||||
3596 | "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); | ||||
3597 | Check(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) | ||||
3598 | "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); | ||||
3599 | |||||
3600 | // - The calling conventions of the caller and callee must match. | ||||
3601 | Check(F->getCallingConv() == CI.getCallingConv(),do { if (!(F->getCallingConv() == CI.getCallingConv())) { CheckFailed ("cannot guarantee tail call due to mismatched calling conv", &CI); return; } } while (false) | ||||
3602 | "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); | ||||
3603 | |||||
3604 | // - The call must immediately precede a :ref:`ret <i_ret>` instruction, | ||||
3605 | // or a pointer bitcast followed by a ret instruction. | ||||
3606 | // - The ret instruction must return the (possibly bitcasted) value | ||||
3607 | // produced by the call or void. | ||||
3608 | Value *RetVal = &CI; | ||||
3609 | Instruction *Next = CI.getNextNode(); | ||||
3610 | |||||
3611 | // Handle the optional bitcast. | ||||
3612 | if (BitCastInst *BI = dyn_cast_or_null<BitCastInst>(Next)) { | ||||
3613 | Check(BI->getOperand(0) == RetVal,do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false) | ||||
3614 | "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); | ||||
3615 | RetVal = BI; | ||||
3616 | Next = BI->getNextNode(); | ||||
3617 | } | ||||
3618 | |||||
3619 | // Check the return. | ||||
3620 | ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next); | ||||
3621 | Check(Ret, "musttail call must precede a ret with an optional bitcast", &CI)do { if (!(Ret)) { CheckFailed("musttail call must precede a ret with an optional bitcast" , &CI); return; } } while (false); | ||||
3622 | Check(!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) | ||||
3623 | 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) | ||||
3624 | "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); | ||||
3625 | |||||
3626 | AttributeList CallerAttrs = F->getAttributes(); | ||||
3627 | AttributeList CalleeAttrs = CI.getAttributes(); | ||||
3628 | if (CI.getCallingConv() == CallingConv::SwiftTail || | ||||
3629 | CI.getCallingConv() == CallingConv::Tail) { | ||||
3630 | StringRef CCName = | ||||
3631 | CI.getCallingConv() == CallingConv::Tail ? "tailcc" : "swifttailcc"; | ||||
3632 | |||||
3633 | // - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes | ||||
3634 | // are allowed in swifttailcc call | ||||
3635 | for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3636 | AttrBuilder ABIAttrs = getParameterABIAttributes(F->getContext(), I, CallerAttrs); | ||||
3637 | SmallString<32> Context{CCName, StringRef(" musttail caller")}; | ||||
3638 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
3639 | } | ||||
3640 | for (unsigned I = 0, E = CalleeTy->getNumParams(); I != E; ++I) { | ||||
3641 | AttrBuilder ABIAttrs = getParameterABIAttributes(F->getContext(), I, CalleeAttrs); | ||||
3642 | SmallString<32> Context{CCName, StringRef(" musttail callee")}; | ||||
3643 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
3644 | } | ||||
3645 | // - Varargs functions are not allowed | ||||
3646 | Check(!CallerTy->isVarArg(), Twine("cannot guarantee ") + CCName +do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false) | ||||
3647 | " tail call for varargs function")do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false); | ||||
3648 | return; | ||||
3649 | } | ||||
3650 | |||||
3651 | // - The caller and callee prototypes must match. Pointer types of | ||||
3652 | // parameters or return types may differ in pointee type, but not | ||||
3653 | // address space. | ||||
3654 | if (!CI.getCalledFunction() || !CI.getCalledFunction()->isIntrinsic()) { | ||||
3655 | Check(CallerTy->getNumParams() == CalleeTy->getNumParams(),do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false) | ||||
3656 | "cannot guarantee tail call due to mismatched parameter counts", &CI)do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false); | ||||
3657 | for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3658 | Check(do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
3659 | 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) | ||||
3660 | "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); | ||||
3661 | } | ||||
3662 | } | ||||
3663 | |||||
3664 | // - All ABI-impacting function attributes, such as sret, byval, inreg, | ||||
3665 | // returned, preallocated, and inalloca, must match. | ||||
3666 | for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
3667 | AttrBuilder CallerABIAttrs = getParameterABIAttributes(F->getContext(), I, CallerAttrs); | ||||
3668 | AttrBuilder CalleeABIAttrs = getParameterABIAttributes(F->getContext(), I, CalleeAttrs); | ||||
3669 | Check(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) | ||||
3670 | "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) | ||||
3671 | "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) | ||||
3672 | &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); | ||||
3673 | } | ||||
3674 | } | ||||
3675 | |||||
3676 | void Verifier::visitCallInst(CallInst &CI) { | ||||
3677 | visitCallBase(CI); | ||||
3678 | |||||
3679 | if (CI.isMustTailCall()) | ||||
3680 | verifyMustTailCall(CI); | ||||
3681 | } | ||||
3682 | |||||
3683 | void Verifier::visitInvokeInst(InvokeInst &II) { | ||||
3684 | visitCallBase(II); | ||||
3685 | |||||
3686 | // Verify that the first non-PHI instruction of the unwind destination is an | ||||
3687 | // exception handling instruction. | ||||
3688 | Check(do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
3689 | II.getUnwindDest()->isEHPad(),do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
3690 | "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) | ||||
3691 | &II)do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false); | ||||
3692 | |||||
3693 | visitTerminator(II); | ||||
3694 | } | ||||
3695 | |||||
3696 | /// visitUnaryOperator - Check the argument to the unary operator. | ||||
3697 | /// | ||||
3698 | void Verifier::visitUnaryOperator(UnaryOperator &U) { | ||||
3699 | Check(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) | ||||
3700 | "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) | ||||
3701 | "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) | ||||
3702 | &U)do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false); | ||||
3703 | |||||
3704 | switch (U.getOpcode()) { | ||||
3705 | // Check that floating-point arithmetic operators are only used with | ||||
3706 | // floating-point operands. | ||||
3707 | case Instruction::FNeg: | ||||
3708 | Check(U.getType()->isFPOrFPVectorTy(),do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false) | ||||
3709 | "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); | ||||
3710 | break; | ||||
3711 | default: | ||||
3712 | llvm_unreachable("Unknown UnaryOperator opcode!")::llvm::llvm_unreachable_internal("Unknown UnaryOperator opcode!" , "llvm/lib/IR/Verifier.cpp", 3712); | ||||
3713 | } | ||||
3714 | |||||
3715 | visitInstruction(U); | ||||
3716 | } | ||||
3717 | |||||
3718 | /// visitBinaryOperator - Check that both arguments to the binary operator are | ||||
3719 | /// of the same type! | ||||
3720 | /// | ||||
3721 | void Verifier::visitBinaryOperator(BinaryOperator &B) { | ||||
3722 | Check(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) | ||||
3723 | "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); | ||||
3724 | |||||
3725 | switch (B.getOpcode()) { | ||||
3726 | // Check that integer arithmetic operators are only used with | ||||
3727 | // integral operands. | ||||
3728 | case Instruction::Add: | ||||
3729 | case Instruction::Sub: | ||||
3730 | case Instruction::Mul: | ||||
3731 | case Instruction::SDiv: | ||||
3732 | case Instruction::UDiv: | ||||
3733 | case Instruction::SRem: | ||||
3734 | case Instruction::URem: | ||||
3735 | Check(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false) | ||||
3736 | "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); | ||||
3737 | Check(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) | ||||
3738 | "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) | ||||
3739 | "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) | ||||
3740 | &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); | ||||
3741 | break; | ||||
3742 | // Check that floating-point arithmetic operators are only used with | ||||
3743 | // floating-point operands. | ||||
3744 | case Instruction::FAdd: | ||||
3745 | case Instruction::FSub: | ||||
3746 | case Instruction::FMul: | ||||
3747 | case Instruction::FDiv: | ||||
3748 | case Instruction::FRem: | ||||
3749 | Check(B.getType()->isFPOrFPVectorTy(),do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
3750 | "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) | ||||
3751 | "floating-point types!",do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
3752 | &B)do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false); | ||||
3753 | Check(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) | ||||
3754 | "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) | ||||
3755 | "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) | ||||
3756 | &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); | ||||
3757 | break; | ||||
3758 | // Check that logical operators are only used with integral operands. | ||||
3759 | case Instruction::And: | ||||
3760 | case Instruction::Or: | ||||
3761 | case Instruction::Xor: | ||||
3762 | Check(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false) | ||||
3763 | "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); | ||||
3764 | Check(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) | ||||
3765 | "Logical operators must have same type for operands and result!", &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false); | ||||
3766 | break; | ||||
3767 | case Instruction::Shl: | ||||
3768 | case Instruction::LShr: | ||||
3769 | case Instruction::AShr: | ||||
3770 | Check(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false) | ||||
3771 | "Shifts only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false); | ||||
3772 | Check(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) | ||||
3773 | "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); | ||||
3774 | break; | ||||
3775 | default: | ||||
3776 | llvm_unreachable("Unknown BinaryOperator opcode!")::llvm::llvm_unreachable_internal("Unknown BinaryOperator opcode!" , "llvm/lib/IR/Verifier.cpp", 3776); | ||||
3777 | } | ||||
3778 | |||||
3779 | visitInstruction(B); | ||||
3780 | } | ||||
3781 | |||||
3782 | void Verifier::visitICmpInst(ICmpInst &IC) { | ||||
3783 | // Check that the operands are the same type | ||||
3784 | Type *Op0Ty = IC.getOperand(0)->getType(); | ||||
3785 | Type *Op1Ty = IC.getOperand(1)->getType(); | ||||
3786 | Check(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false) | ||||
3787 | "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); | ||||
3788 | // Check that the operands are the right type | ||||
3789 | Check(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy(),do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false) | ||||
3790 | "Invalid operand types for ICmp instruction", &IC)do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false); | ||||
3791 | // Check that the predicate is valid. | ||||
3792 | Check(IC.isIntPredicate(), "Invalid predicate in ICmp instruction!", &IC)do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false); | ||||
3793 | |||||
3794 | visitInstruction(IC); | ||||
3795 | } | ||||
3796 | |||||
3797 | void Verifier::visitFCmpInst(FCmpInst &FC) { | ||||
3798 | // Check that the operands are the same type | ||||
3799 | Type *Op0Ty = FC.getOperand(0)->getType(); | ||||
3800 | Type *Op1Ty = FC.getOperand(1)->getType(); | ||||
3801 | Check(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false) | ||||
3802 | "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); | ||||
3803 | // Check that the operands are the right type | ||||
3804 | Check(Op0Ty->isFPOrFPVectorTy(), "Invalid operand types for FCmp instruction",do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false) | ||||
3805 | &FC)do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false); | ||||
3806 | // Check that the predicate is valid. | ||||
3807 | Check(FC.isFPPredicate(), "Invalid predicate in FCmp instruction!", &FC)do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false); | ||||
3808 | |||||
3809 | visitInstruction(FC); | ||||
3810 | } | ||||
3811 | |||||
3812 | void Verifier::visitExtractElementInst(ExtractElementInst &EI) { | ||||
3813 | Check(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) | ||||
3814 | "Invalid extractelement operands!", &EI)do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false); | ||||
3815 | visitInstruction(EI); | ||||
3816 | } | ||||
3817 | |||||
3818 | void Verifier::visitInsertElementInst(InsertElementInst &IE) { | ||||
3819 | Check(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) | ||||
3820 | IE.getOperand(2)),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
3821 | "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); | ||||
3822 | visitInstruction(IE); | ||||
3823 | } | ||||
3824 | |||||
3825 | void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) { | ||||
3826 | Check(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) | ||||
3827 | SV.getShuffleMask()),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
3828 | "Invalid shufflevector operands!", &SV)do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false); | ||||
3829 | visitInstruction(SV); | ||||
3830 | } | ||||
3831 | |||||
3832 | void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { | ||||
3833 | Type *TargetTy = GEP.getPointerOperandType()->getScalarType(); | ||||
3834 | |||||
3835 | Check(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) | ||||
3836 | "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); | ||||
3837 | Check(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP)do { if (!(GEP.getSourceElementType()->isSized())) { CheckFailed ("GEP into unsized type!", &GEP); return; } } while (false ); | ||||
3838 | |||||
3839 | SmallVector<Value *, 16> Idxs(GEP.indices()); | ||||
3840 | Check(do { if (!(all_of(Idxs, [](Value *V) { return V->getType() ->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
3841 | all_of(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) | ||||
3842 | "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); | ||||
3843 | Type *ElTy = | ||||
3844 | GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs); | ||||
3845 | Check(ElTy, "Invalid indices for GEP pointer type!", &GEP)do { if (!(ElTy)) { CheckFailed("Invalid indices for GEP pointer type!" , &GEP); return; } } while (false); | ||||
3846 | |||||
3847 | Check(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) | ||||
3848 | 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) | ||||
3849 | "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); | ||||
3850 | |||||
3851 | if (auto *GEPVTy = dyn_cast<VectorType>(GEP.getType())) { | ||||
3852 | // Additional checks for vector GEPs. | ||||
3853 | ElementCount GEPWidth = GEPVTy->getElementCount(); | ||||
3854 | if (GEP.getPointerOperandType()->isVectorTy()) | ||||
3855 | Check(do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
3856 | GEPWidth ==do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
3857 | 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) | ||||
3858 | "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); | ||||
3859 | for (Value *Idx : Idxs) { | ||||
3860 | Type *IndexTy = Idx->getType(); | ||||
3861 | if (auto *IndexVTy = dyn_cast<VectorType>(IndexTy)) { | ||||
3862 | ElementCount IndexWidth = IndexVTy->getElementCount(); | ||||
3863 | Check(IndexWidth == GEPWidth, "Invalid GEP index vector width", &GEP)do { if (!(IndexWidth == GEPWidth)) { CheckFailed("Invalid GEP index vector width" , &GEP); return; } } while (false); | ||||
3864 | } | ||||
3865 | Check(IndexTy->isIntOrIntVectorTy(),do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false) | ||||
3866 | "All GEP indices should be of integer type")do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false); | ||||
3867 | } | ||||
3868 | } | ||||
3869 | |||||
3870 | if (auto *PTy = dyn_cast<PointerType>(GEP.getType())) { | ||||
3871 | Check(GEP.getAddressSpace() == PTy->getAddressSpace(),do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false) | ||||
3872 | "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); | ||||
3873 | } | ||||
3874 | |||||
3875 | visitInstruction(GEP); | ||||
3876 | } | ||||
3877 | |||||
3878 | static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { | ||||
3879 | return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); | ||||
3880 | } | ||||
3881 | |||||
3882 | void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { | ||||
3883 | assert(Range && Range == I.getMetadata(LLVMContext::MD_range) &&(static_cast <bool> (Range && Range == I.getMetadata (LLVMContext::MD_range) && "precondition violation") ? void (0) : __assert_fail ("Range && Range == I.getMetadata(LLVMContext::MD_range) && \"precondition violation\"" , "llvm/lib/IR/Verifier.cpp", 3884, __extension__ __PRETTY_FUNCTION__ )) | ||||
3884 | "precondition violation")(static_cast <bool> (Range && Range == I.getMetadata (LLVMContext::MD_range) && "precondition violation") ? void (0) : __assert_fail ("Range && Range == I.getMetadata(LLVMContext::MD_range) && \"precondition violation\"" , "llvm/lib/IR/Verifier.cpp", 3884, __extension__ __PRETTY_FUNCTION__ )); | ||||
3885 | |||||
3886 | unsigned NumOperands = Range->getNumOperands(); | ||||
3887 | Check(NumOperands % 2 == 0, "Unfinished range!", Range)do { if (!(NumOperands % 2 == 0)) { CheckFailed("Unfinished range!" , Range); return; } } while (false); | ||||
3888 | unsigned NumRanges = NumOperands / 2; | ||||
3889 | Check(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); | ||||
3890 | |||||
3891 | ConstantRange LastRange(1, true); // Dummy initial value | ||||
3892 | for (unsigned i = 0; i < NumRanges; ++i) { | ||||
3893 | ConstantInt *Low = | ||||
3894 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i)); | ||||
3895 | Check(Low, "The lower limit must be an integer!", Low)do { if (!(Low)) { CheckFailed("The lower limit must be an integer!" , Low); return; } } while (false); | ||||
3896 | ConstantInt *High = | ||||
3897 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i + 1)); | ||||
3898 | Check(High, "The upper limit must be an integer!", High)do { if (!(High)) { CheckFailed("The upper limit must be an integer!" , High); return; } } while (false); | ||||
3899 | Check(High->getType() == Low->getType() &&do { if (!(High->getType() == Low->getType() && High->getType() == Ty->getScalarType())) { CheckFailed ("Range types must match instruction type!", &I); return; } } while (false) | ||||
3900 | High->getType() == Ty->getScalarType(),do { if (!(High->getType() == Low->getType() && High->getType() == Ty->getScalarType())) { CheckFailed ("Range types must match instruction type!", &I); return; } } while (false) | ||||
3901 | "Range types must match instruction type!", &I)do { if (!(High->getType() == Low->getType() && High->getType() == Ty->getScalarType())) { CheckFailed ("Range types must match instruction type!", &I); return; } } while (false); | ||||
3902 | |||||
3903 | APInt HighV = High->getValue(); | ||||
3904 | APInt LowV = Low->getValue(); | ||||
3905 | ConstantRange CurRange(LowV, HighV); | ||||
3906 | Check(!CurRange.isEmptySet() && !CurRange.isFullSet(),do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false) | ||||
3907 | "Range must not be empty!", Range)do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false); | ||||
3908 | if (i != 0) { | ||||
3909 | Check(CurRange.intersectWith(LastRange).isEmptySet(),do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
3910 | "Intervals are overlapping", Range)do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
3911 | Check(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) | ||||
3912 | Range)do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false); | ||||
3913 | Check(!isContiguous(CurRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
3914 | Range)do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
3915 | } | ||||
3916 | LastRange = ConstantRange(LowV, HighV); | ||||
3917 | } | ||||
3918 | if (NumRanges > 2) { | ||||
3919 | APInt FirstLow = | ||||
3920 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(0))->getValue(); | ||||
3921 | APInt FirstHigh = | ||||
3922 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(1))->getValue(); | ||||
3923 | ConstantRange FirstRange(FirstLow, FirstHigh); | ||||
3924 | Check(FirstRange.intersectWith(LastRange).isEmptySet(),do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
3925 | "Intervals are overlapping", Range)do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
3926 | Check(!isContiguous(FirstRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
3927 | Range)do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
3928 | } | ||||
3929 | } | ||||
3930 | |||||
3931 | void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) { | ||||
3932 | unsigned Size = DL.getTypeSizeInBits(Ty); | ||||
3933 | Check(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); | ||||
3934 | Check(!(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) | ||||
3935 | "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); | ||||
3936 | } | ||||
3937 | |||||
3938 | void Verifier::visitLoadInst(LoadInst &LI) { | ||||
3939 | PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType()); | ||||
3940 | Check(PTy, "Load operand must be a pointer.", &LI)do { if (!(PTy)) { CheckFailed("Load operand must be a pointer." , &LI); return; } } while (false); | ||||
3941 | Type *ElTy = LI.getType(); | ||||
3942 | if (MaybeAlign A = LI.getAlign()) { | ||||
3943 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &LI); return; } } while (false) | ||||
3944 | "huge alignment values are unsupported", &LI)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &LI); return; } } while (false); | ||||
3945 | } | ||||
3946 | Check(ElTy->isSized(), "loading unsized types is not allowed", &LI)do { if (!(ElTy->isSized())) { CheckFailed("loading unsized types is not allowed" , &LI); return; } } while (false); | ||||
3947 | if (LI.isAtomic()) { | ||||
3948 | Check(LI.getOrdering() != AtomicOrdering::Release &&do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
3949 | LI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
3950 | "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); | ||||
3951 | Check(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) | ||||
3952 | "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) | ||||
3953 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
3954 | 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); | ||||
3955 | checkAtomicMemAccessSize(ElTy, &LI); | ||||
3956 | } else { | ||||
3957 | Check(LI.getSyncScopeID() == SyncScope::System,do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false) | ||||
3958 | "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); | ||||
3959 | } | ||||
3960 | |||||
3961 | visitInstruction(LI); | ||||
3962 | } | ||||
3963 | |||||
3964 | void Verifier::visitStoreInst(StoreInst &SI) { | ||||
3965 | PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType()); | ||||
3966 | Check(PTy, "Store operand must be a pointer.", &SI)do { if (!(PTy)) { CheckFailed("Store operand must be a pointer." , &SI); return; } } while (false); | ||||
3967 | Type *ElTy = SI.getOperand(0)->getType(); | ||||
3968 | Check(PTy->isOpaqueOrPointeeTypeMatches(ElTy),do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false) | ||||
3969 | "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); | ||||
3970 | if (MaybeAlign A = SI.getAlign()) { | ||||
3971 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &SI); return; } } while (false) | ||||
3972 | "huge alignment values are unsupported", &SI)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &SI); return; } } while (false); | ||||
3973 | } | ||||
3974 | Check(ElTy->isSized(), "storing unsized types is not allowed", &SI)do { if (!(ElTy->isSized())) { CheckFailed("storing unsized types is not allowed" , &SI); return; } } while (false); | ||||
3975 | if (SI.isAtomic()) { | ||||
3976 | Check(SI.getOrdering() != AtomicOrdering::Acquire &&do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
3977 | SI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
3978 | "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); | ||||
3979 | Check(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) | ||||
3980 | "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) | ||||
3981 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
3982 | 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); | ||||
3983 | checkAtomicMemAccessSize(ElTy, &SI); | ||||
3984 | } else { | ||||
3985 | Check(SI.getSyncScopeID() == SyncScope::System,do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false) | ||||
3986 | "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); | ||||
3987 | } | ||||
3988 | visitInstruction(SI); | ||||
3989 | } | ||||
3990 | |||||
3991 | /// Check that SwiftErrorVal is used as a swifterror argument in CS. | ||||
3992 | void Verifier::verifySwiftErrorCall(CallBase &Call, | ||||
3993 | const Value *SwiftErrorVal) { | ||||
3994 | for (const auto &I : llvm::enumerate(Call.args())) { | ||||
3995 | if (I.value() == SwiftErrorVal) { | ||||
3996 | Check(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) | ||||
3997 | "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) | ||||
3998 | "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) | ||||
3999 | 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); | ||||
4000 | } | ||||
4001 | } | ||||
4002 | } | ||||
4003 | |||||
4004 | void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) { | ||||
4005 | // Check that swifterror value is only used by loads, stores, or as | ||||
4006 | // a swifterror argument. | ||||
4007 | for (const User *U : SwiftErrorVal->users()) { | ||||
4008 | Check(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) | ||||
4009 | 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) | ||||
4010 | "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) | ||||
4011 | "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) | ||||
4012 | 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); | ||||
4013 | // If it is used by a store, check it is the second operand. | ||||
4014 | if (auto StoreI = dyn_cast<StoreInst>(U)) | ||||
4015 | Check(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) | ||||
4016 | "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) | ||||
4017 | "by stores",do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
4018 | 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); | ||||
4019 | if (auto *Call = dyn_cast<CallBase>(U)) | ||||
4020 | verifySwiftErrorCall(*const_cast<CallBase *>(Call), SwiftErrorVal); | ||||
4021 | } | ||||
4022 | } | ||||
4023 | |||||
4024 | void Verifier::visitAllocaInst(AllocaInst &AI) { | ||||
4025 | SmallPtrSet<Type*, 4> Visited; | ||||
4026 | Check(AI.getAllocatedType()->isSized(&Visited),do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false) | ||||
4027 | "Cannot allocate unsized type", &AI)do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false); | ||||
4028 | Check(AI.getArraySize()->getType()->isIntegerTy(),do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false) | ||||
4029 | "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); | ||||
4030 | if (MaybeAlign A = AI.getAlign()) { | ||||
4031 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &AI); return; } } while (false) | ||||
4032 | "huge alignment values are unsupported", &AI)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &AI); return; } } while (false); | ||||
4033 | } | ||||
4034 | |||||
4035 | if (AI.isSwiftError()) { | ||||
4036 | Check(AI.getAllocatedType()->isPointerTy(),do { if (!(AI.getAllocatedType()->isPointerTy())) { CheckFailed ("swifterror alloca must have pointer type", &AI); return ; } } while (false) | ||||
4037 | "swifterror alloca must have pointer type", &AI)do { if (!(AI.getAllocatedType()->isPointerTy())) { CheckFailed ("swifterror alloca must have pointer type", &AI); return ; } } while (false); | ||||
4038 | Check(!AI.isArrayAllocation(),do { if (!(!AI.isArrayAllocation())) { CheckFailed("swifterror alloca must not be array allocation" , &AI); return; } } while (false) | ||||
4039 | "swifterror alloca must not be array allocation", &AI)do { if (!(!AI.isArrayAllocation())) { CheckFailed("swifterror alloca must not be array allocation" , &AI); return; } } while (false); | ||||
4040 | verifySwiftErrorValue(&AI); | ||||
4041 | } | ||||
4042 | |||||
4043 | visitInstruction(AI); | ||||
4044 | } | ||||
4045 | |||||
4046 | void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { | ||||
4047 | Type *ElTy = CXI.getOperand(1)->getType(); | ||||
4048 | Check(ElTy->isIntOrPtrTy(),do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false) | ||||
4049 | "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); | ||||
4050 | checkAtomicMemAccessSize(ElTy, &CXI); | ||||
4051 | visitInstruction(CXI); | ||||
4052 | } | ||||
4053 | |||||
4054 | void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { | ||||
4055 | Check(RMWI.getOrdering() != AtomicOrdering::Unordered,do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false) | ||||
4056 | "atomicrmw instructions cannot be unordered.", &RMWI)do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false); | ||||
4057 | auto Op = RMWI.getOperation(); | ||||
4058 | Type *ElTy = RMWI.getOperand(1)->getType(); | ||||
4059 | if (Op == AtomicRMWInst::Xchg) { | ||||
4060 | Check(ElTy->isIntegerTy() || ElTy->isFloatingPointTy() ||do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
4061 | ElTy->isPointerTy(),do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
4062 | "atomicrmw " + AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
4063 | " operand must have integer or floating point type!",do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
4064 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false); | ||||
4065 | } else if (AtomicRMWInst::isFPOperation(Op)) { | ||||
4066 | Check(ElTy->isFloatingPointTy(),do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
4067 | "atomicrmw " + AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
4068 | " 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) | ||||
4069 | &RMWI, ElTy)do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false); | ||||
4070 | } else { | ||||
4071 | Check(ElTy->isIntegerTy(),do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
4072 | "atomicrmw " + AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
4073 | " operand must have integer type!",do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
4074 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false); | ||||
4075 | } | ||||
4076 | checkAtomicMemAccessSize(ElTy, &RMWI); | ||||
4077 | Check(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) | ||||
4078 | "Invalid binary operation!", &RMWI)do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false); | ||||
4079 | visitInstruction(RMWI); | ||||
4080 | } | ||||
4081 | |||||
4082 | void Verifier::visitFenceInst(FenceInst &FI) { | ||||
4083 | const AtomicOrdering Ordering = FI.getOrdering(); | ||||
4084 | Check(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) | ||||
4085 | 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) | ||||
4086 | 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) | ||||
4087 | 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) | ||||
4088 | "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) | ||||
4089 | "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) | ||||
4090 | &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); | ||||
4091 | visitInstruction(FI); | ||||
4092 | } | ||||
4093 | |||||
4094 | void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { | ||||
4095 | Check(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
4096 | EVI.getIndices()) == EVI.getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
4097 | "Invalid ExtractValueInst operands!", &EVI)do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false); | ||||
4098 | |||||
4099 | visitInstruction(EVI); | ||||
4100 | } | ||||
4101 | |||||
4102 | void Verifier::visitInsertValueInst(InsertValueInst &IVI) { | ||||
4103 | Check(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) | ||||
4104 | IVI.getIndices()) ==do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
4105 | 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) | ||||
4106 | "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); | ||||
4107 | |||||
4108 | visitInstruction(IVI); | ||||
4109 | } | ||||
4110 | |||||
4111 | static Value *getParentPad(Value *EHPad) { | ||||
4112 | if (auto *FPI = dyn_cast<FuncletPadInst>(EHPad)) | ||||
4113 | return FPI->getParentPad(); | ||||
4114 | |||||
4115 | return cast<CatchSwitchInst>(EHPad)->getParentPad(); | ||||
4116 | } | ||||
4117 | |||||
4118 | void Verifier::visitEHPadPredecessors(Instruction &I) { | ||||
4119 | assert(I.isEHPad())(static_cast <bool> (I.isEHPad()) ? void (0) : __assert_fail ("I.isEHPad()", "llvm/lib/IR/Verifier.cpp", 4119, __extension__ __PRETTY_FUNCTION__)); | ||||
4120 | |||||
4121 | BasicBlock *BB = I.getParent(); | ||||
4122 | Function *F = BB->getParent(); | ||||
4123 | |||||
4124 | Check(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); | ||||
4125 | |||||
4126 | if (auto *LPI = dyn_cast<LandingPadInst>(&I)) { | ||||
4127 | // The landingpad instruction defines its parent as a landing pad block. The | ||||
4128 | // landing pad block may be branched to only by the unwind edge of an | ||||
4129 | // invoke. | ||||
4130 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
4131 | const auto *II = dyn_cast<InvokeInst>(PredBB->getTerminator()); | ||||
4132 | Check(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) | ||||
4133 | "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) | ||||
4134 | "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) | ||||
4135 | 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); | ||||
4136 | } | ||||
4137 | return; | ||||
4138 | } | ||||
4139 | if (auto *CPI = dyn_cast<CatchPadInst>(&I)) { | ||||
4140 | if (!pred_empty(BB)) | ||||
4141 | Check(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) | ||||
4142 | "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) | ||||
4143 | "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) | ||||
4144 | CPI)do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false); | ||||
4145 | Check(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) | ||||
4146 | "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) | ||||
4147 | CPI->getCatchSwitch(), CPI)do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false); | ||||
4148 | return; | ||||
4149 | } | ||||
4150 | |||||
4151 | // Verify that each pred has a legal terminator with a legal to/from EH | ||||
4152 | // pad relationship. | ||||
4153 | Instruction *ToPad = &I; | ||||
4154 | Value *ToPadParent = getParentPad(ToPad); | ||||
4155 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
4156 | Instruction *TI = PredBB->getTerminator(); | ||||
4157 | Value *FromPad; | ||||
4158 | if (auto *II = dyn_cast<InvokeInst>(TI)) { | ||||
4159 | Check(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) | ||||
4160 | "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); | ||||
4161 | if (auto Bundle = II->getOperandBundle(LLVMContext::OB_funclet)) | ||||
4162 | FromPad = Bundle->Inputs[0]; | ||||
4163 | else | ||||
4164 | FromPad = ConstantTokenNone::get(II->getContext()); | ||||
4165 | } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) { | ||||
4166 | FromPad = CRI->getOperand(0); | ||||
4167 | Check(FromPad != ToPadParent, "A cleanupret must exit its cleanup", CRI)do { if (!(FromPad != ToPadParent)) { CheckFailed("A cleanupret must exit its cleanup" , CRI); return; } } while (false); | ||||
4168 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) { | ||||
4169 | FromPad = CSI; | ||||
4170 | } else { | ||||
4171 | Check(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); | ||||
4172 | } | ||||
4173 | |||||
4174 | // The edge may exit from zero or more nested pads. | ||||
4175 | SmallSet<Value *, 8> Seen; | ||||
4176 | for (;; FromPad = getParentPad(FromPad)) { | ||||
4177 | Check(FromPad != ToPad,do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false) | ||||
4178 | "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); | ||||
4179 | if (FromPad == ToPadParent) { | ||||
4180 | // This is a legal unwind edge. | ||||
4181 | break; | ||||
4182 | } | ||||
4183 | Check(!isa<ConstantTokenNone>(FromPad),do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false) | ||||
4184 | "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); | ||||
4185 | Check(Seen.insert(FromPad).second, "EH pad jumps through a cycle of pads",do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false) | ||||
4186 | FromPad)do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false); | ||||
4187 | |||||
4188 | // This will be diagnosed on the corresponding instruction already. We | ||||
4189 | // need the extra check here to make sure getParentPad() works. | ||||
4190 | Check(isa<FuncletPadInst>(FromPad) || isa<CatchSwitchInst>(FromPad),do { if (!(isa<FuncletPadInst>(FromPad) || isa<CatchSwitchInst >(FromPad))) { CheckFailed("Parent pad must be catchpad/cleanuppad/catchswitch" , TI); return; } } while (false) | ||||
4191 | "Parent pad must be catchpad/cleanuppad/catchswitch", TI)do { if (!(isa<FuncletPadInst>(FromPad) || isa<CatchSwitchInst >(FromPad))) { CheckFailed("Parent pad must be catchpad/cleanuppad/catchswitch" , TI); return; } } while (false); | ||||
4192 | } | ||||
4193 | } | ||||
4194 | } | ||||
4195 | |||||
4196 | void Verifier::visitLandingPadInst(LandingPadInst &LPI) { | ||||
4197 | // The landingpad instruction is ill-formed if it doesn't have any clauses and | ||||
4198 | // isn't a cleanup. | ||||
4199 | Check(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) | ||||
4200 | "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); | ||||
4201 | |||||
4202 | visitEHPadPredecessors(LPI); | ||||
4203 | |||||
4204 | if (!LandingPadResultTy) | ||||
4205 | LandingPadResultTy = LPI.getType(); | ||||
4206 | else | ||||
4207 | Check(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) | ||||
4208 | "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) | ||||
4209 | "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) | ||||
4210 | &LPI)do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false); | ||||
4211 | |||||
4212 | Function *F = LPI.getParent()->getParent(); | ||||
4213 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false) | ||||
4214 | "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); | ||||
4215 | |||||
4216 | // The landingpad instruction must be the first non-PHI instruction in the | ||||
4217 | // block. | ||||
4218 | Check(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) | ||||
4219 | "LandingPadInst not the first non-PHI instruction in the block.", &LPI)do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false); | ||||
4220 | |||||
4221 | for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) { | ||||
4222 | Constant *Clause = LPI.getClause(i); | ||||
4223 | if (LPI.isCatch(i)) { | ||||
4224 | Check(isa<PointerType>(Clause->getType()),do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false) | ||||
4225 | "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); | ||||
4226 | } else { | ||||
4227 | Check(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); | ||||
4228 | Check(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) | ||||
4229 | "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); | ||||
4230 | } | ||||
4231 | } | ||||
4232 | |||||
4233 | visitInstruction(LPI); | ||||
4234 | } | ||||
4235 | |||||
4236 | void Verifier::visitResumeInst(ResumeInst &RI) { | ||||
4237 | Check(RI.getFunction()->hasPersonalityFn(),do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false) | ||||
4238 | "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); | ||||
4239 | |||||
4240 | if (!LandingPadResultTy) | ||||
4241 | LandingPadResultTy = RI.getValue()->getType(); | ||||
4242 | else | ||||
4243 | Check(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) | ||||
4244 | "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) | ||||
4245 | "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) | ||||
4246 | &RI)do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false); | ||||
4247 | |||||
4248 | visitTerminator(RI); | ||||
4249 | } | ||||
4250 | |||||
4251 | void Verifier::visitCatchPadInst(CatchPadInst &CPI) { | ||||
4252 | BasicBlock *BB = CPI.getParent(); | ||||
4253 | |||||
4254 | Function *F = BB->getParent(); | ||||
4255 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
4256 | "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); | ||||
4257 | |||||
4258 | Check(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) | ||||
4259 | "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) | ||||
4260 | CPI.getParentPad())do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false); | ||||
4261 | |||||
4262 | // The catchpad instruction must be the first non-PHI instruction in the | ||||
4263 | // block. | ||||
4264 | Check(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
4265 | "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); | ||||
4266 | |||||
4267 | visitEHPadPredecessors(CPI); | ||||
4268 | visitFuncletPadInst(CPI); | ||||
4269 | } | ||||
4270 | |||||
4271 | void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) { | ||||
4272 | Check(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) | ||||
4273 | "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) | ||||
4274 | 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); | ||||
4275 | |||||
4276 | visitTerminator(CatchReturn); | ||||
4277 | } | ||||
4278 | |||||
4279 | void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { | ||||
4280 | BasicBlock *BB = CPI.getParent(); | ||||
4281 | |||||
4282 | Function *F = BB->getParent(); | ||||
4283 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
4284 | "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); | ||||
4285 | |||||
4286 | // The cleanuppad instruction must be the first non-PHI instruction in the | ||||
4287 | // block. | ||||
4288 | Check(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
4289 | "CleanupPadInst not the first non-PHI instruction in the block.", &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
4290 | |||||
4291 | auto *ParentPad = CPI.getParentPad(); | ||||
4292 | Check(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false) | ||||
4293 | "CleanupPadInst has an invalid parent.", &CPI)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false); | ||||
4294 | |||||
4295 | visitEHPadPredecessors(CPI); | ||||
4296 | visitFuncletPadInst(CPI); | ||||
4297 | } | ||||
4298 | |||||
4299 | void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { | ||||
4300 | User *FirstUser = nullptr; | ||||
4301 | Value *FirstUnwindPad = nullptr; | ||||
4302 | SmallVector<FuncletPadInst *, 8> Worklist({&FPI}); | ||||
4303 | SmallSet<FuncletPadInst *, 8> Seen; | ||||
4304 | |||||
4305 | while (!Worklist.empty()) { | ||||
4306 | FuncletPadInst *CurrentPad = Worklist.pop_back_val(); | ||||
4307 | Check(Seen.insert(CurrentPad).second,do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false) | ||||
4308 | "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); | ||||
4309 | Value *UnresolvedAncestorPad = nullptr; | ||||
4310 | for (User *U : CurrentPad->users()) { | ||||
4311 | BasicBlock *UnwindDest; | ||||
4312 | if (auto *CRI = dyn_cast<CleanupReturnInst>(U)) { | ||||
4313 | UnwindDest = CRI->getUnwindDest(); | ||||
4314 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(U)) { | ||||
4315 | // We allow catchswitch unwind to caller to nest | ||||
4316 | // within an outer pad that unwinds somewhere else, | ||||
4317 | // because catchswitch doesn't have a nounwind variant. | ||||
4318 | // See e.g. SimplifyCFGOpt::SimplifyUnreachable. | ||||
4319 | if (CSI->unwindsToCaller()) | ||||
4320 | continue; | ||||
4321 | UnwindDest = CSI->getUnwindDest(); | ||||
4322 | } else if (auto *II = dyn_cast<InvokeInst>(U)) { | ||||
4323 | UnwindDest = II->getUnwindDest(); | ||||
4324 | } else if (isa<CallInst>(U)) { | ||||
4325 | // Calls which don't unwind may be found inside funclet | ||||
4326 | // pads that unwind somewhere else. We don't *require* | ||||
4327 | // such calls to be annotated nounwind. | ||||
4328 | continue; | ||||
4329 | } else if (auto *CPI = dyn_cast<CleanupPadInst>(U)) { | ||||
4330 | // The unwind dest for a cleanup can only be found by | ||||
4331 | // recursive search. Add it to the worklist, and we'll | ||||
4332 | // search for its first use that determines where it unwinds. | ||||
4333 | Worklist.push_back(CPI); | ||||
4334 | continue; | ||||
4335 | } else { | ||||
4336 | Check(isa<CatchReturnInst>(U), "Bogus funclet pad use", U)do { if (!(isa<CatchReturnInst>(U))) { CheckFailed("Bogus funclet pad use" , U); return; } } while (false); | ||||
4337 | continue; | ||||
4338 | } | ||||
4339 | |||||
4340 | Value *UnwindPad; | ||||
4341 | bool ExitsFPI; | ||||
4342 | if (UnwindDest) { | ||||
4343 | UnwindPad = UnwindDest->getFirstNonPHI(); | ||||
4344 | if (!cast<Instruction>(UnwindPad)->isEHPad()) | ||||
4345 | continue; | ||||
4346 | Value *UnwindParent = getParentPad(UnwindPad); | ||||
4347 | // Ignore unwind edges that don't exit CurrentPad. | ||||
4348 | if (UnwindParent == CurrentPad) | ||||
4349 | continue; | ||||
4350 | // Determine whether the original funclet pad is exited, | ||||
4351 | // and if we are scanning nested pads determine how many | ||||
4352 | // of them are exited so we can stop searching their | ||||
4353 | // children. | ||||
4354 | Value *ExitedPad = CurrentPad; | ||||
4355 | ExitsFPI = false; | ||||
4356 | do { | ||||
4357 | if (ExitedPad == &FPI) { | ||||
4358 | ExitsFPI = true; | ||||
4359 | // Now we can resolve any ancestors of CurrentPad up to | ||||
4360 | // FPI, but not including FPI since we need to make sure | ||||
4361 | // to check all direct users of FPI for consistency. | ||||
4362 | UnresolvedAncestorPad = &FPI; | ||||
4363 | break; | ||||
4364 | } | ||||
4365 | Value *ExitedParent = getParentPad(ExitedPad); | ||||
4366 | if (ExitedParent == UnwindParent) { | ||||
4367 | // ExitedPad is the ancestor-most pad which this unwind | ||||
4368 | // edge exits, so we can resolve up to it, meaning that | ||||
4369 | // ExitedParent is the first ancestor still unresolved. | ||||
4370 | UnresolvedAncestorPad = ExitedParent; | ||||
4371 | break; | ||||
4372 | } | ||||
4373 | ExitedPad = ExitedParent; | ||||
4374 | } while (!isa<ConstantTokenNone>(ExitedPad)); | ||||
4375 | } else { | ||||
4376 | // Unwinding to caller exits all pads. | ||||
4377 | UnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
4378 | ExitsFPI = true; | ||||
4379 | UnresolvedAncestorPad = &FPI; | ||||
4380 | } | ||||
4381 | |||||
4382 | if (ExitsFPI) { | ||||
4383 | // This unwind edge exits FPI. Make sure it agrees with other | ||||
4384 | // such edges. | ||||
4385 | if (FirstUser) { | ||||
4386 | Check(UnwindPad == FirstUnwindPad,do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
4387 | "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) | ||||
4388 | "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) | ||||
4389 | "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) | ||||
4390 | &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); | ||||
4391 | } else { | ||||
4392 | FirstUser = U; | ||||
4393 | FirstUnwindPad = UnwindPad; | ||||
4394 | // Record cleanup sibling unwinds for verifySiblingFuncletUnwinds | ||||
4395 | if (isa<CleanupPadInst>(&FPI) && !isa<ConstantTokenNone>(UnwindPad) && | ||||
4396 | getParentPad(UnwindPad) == getParentPad(&FPI)) | ||||
4397 | SiblingFuncletInfo[&FPI] = cast<Instruction>(U); | ||||
4398 | } | ||||
4399 | } | ||||
4400 | // Make sure we visit all uses of FPI, but for nested pads stop as | ||||
4401 | // soon as we know where they unwind to. | ||||
4402 | if (CurrentPad != &FPI) | ||||
4403 | break; | ||||
4404 | } | ||||
4405 | if (UnresolvedAncestorPad) { | ||||
4406 | if (CurrentPad == UnresolvedAncestorPad) { | ||||
4407 | // When CurrentPad is FPI itself, we don't mark it as resolved even if | ||||
4408 | // we've found an unwind edge that exits it, because we need to verify | ||||
4409 | // all direct uses of FPI. | ||||
4410 | assert(CurrentPad == &FPI)(static_cast <bool> (CurrentPad == &FPI) ? void (0) : __assert_fail ("CurrentPad == &FPI", "llvm/lib/IR/Verifier.cpp" , 4410, __extension__ __PRETTY_FUNCTION__)); | ||||
4411 | continue; | ||||
4412 | } | ||||
4413 | // Pop off the worklist any nested pads that we've found an unwind | ||||
4414 | // destination for. The pads on the worklist are the uncles, | ||||
4415 | // great-uncles, etc. of CurrentPad. We've found an unwind destination | ||||
4416 | // for all ancestors of CurrentPad up to but not including | ||||
4417 | // UnresolvedAncestorPad. | ||||
4418 | Value *ResolvedPad = CurrentPad; | ||||
4419 | while (!Worklist.empty()) { | ||||
4420 | Value *UnclePad = Worklist.back(); | ||||
4421 | Value *AncestorPad = getParentPad(UnclePad); | ||||
4422 | // Walk ResolvedPad up the ancestor list until we either find the | ||||
4423 | // uncle's parent or the last resolved ancestor. | ||||
4424 | while (ResolvedPad != AncestorPad) { | ||||
4425 | Value *ResolvedParent = getParentPad(ResolvedPad); | ||||
4426 | if (ResolvedParent == UnresolvedAncestorPad) { | ||||
4427 | break; | ||||
4428 | } | ||||
4429 | ResolvedPad = ResolvedParent; | ||||
4430 | } | ||||
4431 | // If the resolved ancestor search didn't find the uncle's parent, | ||||
4432 | // then the uncle is not yet resolved. | ||||
4433 | if (ResolvedPad != AncestorPad) | ||||
4434 | break; | ||||
4435 | // This uncle is resolved, so pop it from the worklist. | ||||
4436 | Worklist.pop_back(); | ||||
4437 | } | ||||
4438 | } | ||||
4439 | } | ||||
4440 | |||||
4441 | if (FirstUnwindPad) { | ||||
4442 | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FPI.getParentPad())) { | ||||
4443 | BasicBlock *SwitchUnwindDest = CatchSwitch->getUnwindDest(); | ||||
4444 | Value *SwitchUnwindPad; | ||||
4445 | if (SwitchUnwindDest) | ||||
4446 | SwitchUnwindPad = SwitchUnwindDest->getFirstNonPHI(); | ||||
4447 | else | ||||
4448 | SwitchUnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
4449 | Check(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) | ||||
4450 | "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) | ||||
4451 | "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) | ||||
4452 | &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); | ||||
4453 | } | ||||
4454 | } | ||||
4455 | |||||
4456 | visitInstruction(FPI); | ||||
4457 | } | ||||
4458 | |||||
4459 | void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) { | ||||
4460 | BasicBlock *BB = CatchSwitch.getParent(); | ||||
4461 | |||||
4462 | Function *F = BB->getParent(); | ||||
4463 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
4464 | "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) | ||||
4465 | &CatchSwitch)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false); | ||||
4466 | |||||
4467 | // The catchswitch instruction must be the first non-PHI instruction in the | ||||
4468 | // block. | ||||
4469 | Check(BB->getFirstNonPHI() == &CatchSwitch,do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
4470 | "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) | ||||
4471 | &CatchSwitch)do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false); | ||||
4472 | |||||
4473 | auto *ParentPad = CatchSwitch.getParentPad(); | ||||
4474 | Check(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false) | ||||
4475 | "CatchSwitchInst has an invalid parent.", ParentPad)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false); | ||||
4476 | |||||
4477 | if (BasicBlock *UnwindDest = CatchSwitch.getUnwindDest()) { | ||||
4478 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
4479 | Check(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) | ||||
4480 | "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) | ||||
4481 | "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) | ||||
4482 | &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); | ||||
4483 | |||||
4484 | // Record catchswitch sibling unwinds for verifySiblingFuncletUnwinds | ||||
4485 | if (getParentPad(I) == ParentPad) | ||||
4486 | SiblingFuncletInfo[&CatchSwitch] = &CatchSwitch; | ||||
4487 | } | ||||
4488 | |||||
4489 | Check(CatchSwitch.getNumHandlers() != 0,do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false) | ||||
4490 | "CatchSwitchInst cannot have empty handler list", &CatchSwitch)do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false); | ||||
4491 | |||||
4492 | for (BasicBlock *Handler : CatchSwitch.handlers()) { | ||||
4493 | Check(isa<CatchPadInst>(Handler->getFirstNonPHI()),do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false) | ||||
4494 | "CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler)do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false); | ||||
4495 | } | ||||
4496 | |||||
4497 | visitEHPadPredecessors(CatchSwitch); | ||||
4498 | visitTerminator(CatchSwitch); | ||||
4499 | } | ||||
4500 | |||||
4501 | void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) { | ||||
4502 | Check(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) | ||||
4503 | "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) | ||||
4504 | 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); | ||||
4505 | |||||
4506 | if (BasicBlock *UnwindDest = CRI.getUnwindDest()) { | ||||
4507 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
4508 | Check(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) | ||||
4509 | "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) | ||||
4510 | "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) | ||||
4511 | &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); | ||||
4512 | } | ||||
4513 | |||||
4514 | visitTerminator(CRI); | ||||
4515 | } | ||||
4516 | |||||
4517 | void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { | ||||
4518 | Instruction *Op = cast<Instruction>(I.getOperand(i)); | ||||
4519 | // If the we have an invalid invoke, don't try to compute the dominance. | ||||
4520 | // We already reject it in the invoke specific checks and the dominance | ||||
4521 | // computation doesn't handle multiple edges. | ||||
4522 | if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) { | ||||
4523 | if (II->getNormalDest() == II->getUnwindDest()) | ||||
4524 | return; | ||||
4525 | } | ||||
4526 | |||||
4527 | // Quick check whether the def has already been encountered in the same block. | ||||
4528 | // PHI nodes are not checked to prevent accepting preceding PHIs, because PHI | ||||
4529 | // uses are defined to happen on the incoming edge, not at the instruction. | ||||
4530 | // | ||||
4531 | // FIXME: If this operand is a MetadataAsValue (wrapping a LocalAsMetadata) | ||||
4532 | // wrapping an SSA value, assert that we've already encountered it. See | ||||
4533 | // related FIXME in Mapper::mapLocalAsMetadata in ValueMapper.cpp. | ||||
4534 | if (!isa<PHINode>(I) && InstsInThisBlock.count(Op)) | ||||
4535 | return; | ||||
4536 | |||||
4537 | const Use &U = I.getOperandUse(i); | ||||
4538 | Check(DT.dominates(Op, U), "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); | ||||
4539 | } | ||||
4540 | |||||
4541 | void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) { | ||||
4542 | Check(I.getType()->isPointerTy(),do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
4543 | "dereferenceable, dereferenceable_or_null "do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
4544 | "apply only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
4545 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ); | ||||
4546 | Check((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) | ||||
4547 | "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) | ||||
4548 | " and inttoptr instructions, use attributes for calls or invokes",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) | ||||
4549 | &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); | ||||
4550 | Check(MD->getNumOperands() == 1,do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
4551 | "dereferenceable, dereferenceable_or_null "do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
4552 | "take one operand!",do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
4553 | &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false); | ||||
4554 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0)); | ||||
4555 | Check(CI && CI->getType()->isIntegerTy(64),do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
4556 | "dereferenceable, "do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
4557 | "dereferenceable_or_null metadata value must be an i64!",do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
4558 | &I)do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false); | ||||
4559 | } | ||||
4560 | |||||
4561 | void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) { | ||||
4562 | Check(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
4563 | "!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); | ||||
4564 | |||||
4565 | // Check first operand. | ||||
4566 | Check(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); | ||||
4567 | Check(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) | ||||
4568 | "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); | ||||
4569 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
4570 | StringRef ProfName = MDS->getString(); | ||||
4571 | |||||
4572 | // Check consistency of !prof branch_weights metadata. | ||||
4573 | if (ProfName.equals("branch_weights")) { | ||||
4574 | if (isa<InvokeInst>(&I)) { | ||||
4575 | Check(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) | ||||
4576 | "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); | ||||
4577 | } else { | ||||
4578 | unsigned ExpectedNumOperands = 0; | ||||
4579 | if (BranchInst *BI = dyn_cast<BranchInst>(&I)) | ||||
4580 | ExpectedNumOperands = BI->getNumSuccessors(); | ||||
4581 | else if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) | ||||
4582 | ExpectedNumOperands = SI->getNumSuccessors(); | ||||
4583 | else if (isa<CallInst>(&I)) | ||||
4584 | ExpectedNumOperands = 1; | ||||
4585 | else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(&I)) | ||||
4586 | ExpectedNumOperands = IBI->getNumDestinations(); | ||||
4587 | else if (isa<SelectInst>(&I)) | ||||
4588 | ExpectedNumOperands = 2; | ||||
4589 | else if (CallBrInst *CI = dyn_cast<CallBrInst>(&I)) | ||||
4590 | ExpectedNumOperands = CI->getNumSuccessors(); | ||||
4591 | else | ||||
4592 | CheckFailed("!prof branch_weights are not allowed for this instruction", | ||||
4593 | MD); | ||||
4594 | |||||
4595 | Check(MD->getNumOperands() == 1 + ExpectedNumOperands,do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false) | ||||
4596 | "Wrong number of operands", MD)do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false); | ||||
4597 | } | ||||
4598 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) { | ||||
4599 | auto &MDO = MD->getOperand(i); | ||||
4600 | Check(MDO, "second operand should not be null", MD)do { if (!(MDO)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
4601 | Check(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) | ||||
4602 | "!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); | ||||
4603 | } | ||||
4604 | } | ||||
4605 | } | ||||
4606 | |||||
4607 | void Verifier::visitDIAssignIDMetadata(Instruction &I, MDNode *MD) { | ||||
4608 | assert(I.hasMetadata(LLVMContext::MD_DIAssignID))(static_cast <bool> (I.hasMetadata(LLVMContext::MD_DIAssignID )) ? void (0) : __assert_fail ("I.hasMetadata(LLVMContext::MD_DIAssignID)" , "llvm/lib/IR/Verifier.cpp", 4608, __extension__ __PRETTY_FUNCTION__ )); | ||||
4609 | bool ExpectedInstTy = | ||||
4610 | isa<AllocaInst>(I) || isa<StoreInst>(I) || isa<MemIntrinsic>(I); | ||||
4611 | CheckDI(ExpectedInstTy, "!DIAssignID attached to unexpected instruction kind",do { if (!(ExpectedInstTy)) { DebugInfoCheckFailed("!DIAssignID attached to unexpected instruction kind" , I, MD); return; } } while (false) | ||||
4612 | I, MD)do { if (!(ExpectedInstTy)) { DebugInfoCheckFailed("!DIAssignID attached to unexpected instruction kind" , I, MD); return; } } while (false); | ||||
4613 | // Iterate over the MetadataAsValue uses of the DIAssignID - these should | ||||
4614 | // only be found as DbgAssignIntrinsic operands. | ||||
4615 | if (auto *AsValue = MetadataAsValue::getIfExists(Context, MD)) { | ||||
4616 | for (auto *User : AsValue->users()) { | ||||
4617 | CheckDI(isa<DbgAssignIntrinsic>(User),do { if (!(isa<DbgAssignIntrinsic>(User))) { DebugInfoCheckFailed ("!DIAssignID should only be used by llvm.dbg.assign intrinsics" , MD, User); return; } } while (false) | ||||
4618 | "!DIAssignID should only be used by llvm.dbg.assign intrinsics",do { if (!(isa<DbgAssignIntrinsic>(User))) { DebugInfoCheckFailed ("!DIAssignID should only be used by llvm.dbg.assign intrinsics" , MD, User); return; } } while (false) | ||||
4619 | MD, User)do { if (!(isa<DbgAssignIntrinsic>(User))) { DebugInfoCheckFailed ("!DIAssignID should only be used by llvm.dbg.assign intrinsics" , MD, User); return; } } while (false); | ||||
4620 | // All of the dbg.assign intrinsics should be in the same function as I. | ||||
4621 | if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(User)) | ||||
4622 | CheckDI(DAI->getFunction() == I.getFunction(),do { if (!(DAI->getFunction() == I.getFunction())) { DebugInfoCheckFailed ("dbg.assign not in same function as inst", DAI, &I); return ; } } while (false) | ||||
4623 | "dbg.assign not in same function as inst", DAI, &I)do { if (!(DAI->getFunction() == I.getFunction())) { DebugInfoCheckFailed ("dbg.assign not in same function as inst", DAI, &I); return ; } } while (false); | ||||
4624 | } | ||||
4625 | } | ||||
4626 | } | ||||
4627 | |||||
4628 | void Verifier::visitCallStackMetadata(MDNode *MD) { | ||||
4629 | // Call stack metadata should consist of a list of at least 1 constant int | ||||
4630 | // (representing a hash of the location). | ||||
4631 | Check(MD->getNumOperands() >= 1,do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("call stack metadata should have at least 1 operand" , MD); return; } } while (false) | ||||
4632 | "call stack metadata should have at least 1 operand", MD)do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("call stack metadata should have at least 1 operand" , MD); return; } } while (false); | ||||
4633 | |||||
4634 | for (const auto &Op : MD->operands()) | ||||
4635 | Check(mdconst::dyn_extract_or_null<ConstantInt>(Op),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ))) { CheckFailed("call stack metadata operand should be constant integer" , Op); return; } } while (false) | ||||
4636 | "call stack metadata operand should be constant integer", Op)do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ))) { CheckFailed("call stack metadata operand should be constant integer" , Op); return; } } while (false); | ||||
4637 | } | ||||
4638 | |||||
4639 | void Verifier::visitMemProfMetadata(Instruction &I, MDNode *MD) { | ||||
4640 | Check(isa<CallBase>(I), "!memprof metadata should only exist on calls", &I)do { if (!(isa<CallBase>(I))) { CheckFailed("!memprof metadata should only exist on calls" , &I); return; } } while (false); | ||||
4641 | Check(MD->getNumOperands() >= 1,do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false) | ||||
4642 | "!memprof annotations should have at least 1 metadata operand "do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false) | ||||
4643 | "(MemInfoBlock)",do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false) | ||||
4644 | MD)do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false); | ||||
4645 | |||||
4646 | // Check each MIB | ||||
4647 | for (auto &MIBOp : MD->operands()) { | ||||
4648 | MDNode *MIB = dyn_cast<MDNode>(MIBOp); | ||||
4649 | // The first operand of an MIB should be the call stack metadata. | ||||
4650 | // There rest of the operands should be MDString tags, and there should be | ||||
4651 | // at least one. | ||||
4652 | Check(MIB->getNumOperands() >= 2,do { if (!(MIB->getNumOperands() >= 2)) { CheckFailed("Each !memprof MemInfoBlock should have at least 2 operands" , MIB); return; } } while (false) | ||||
4653 | "Each !memprof MemInfoBlock should have at least 2 operands", MIB)do { if (!(MIB->getNumOperands() >= 2)) { CheckFailed("Each !memprof MemInfoBlock should have at least 2 operands" , MIB); return; } } while (false); | ||||
4654 | |||||
4655 | // Check call stack metadata (first operand). | ||||
4656 | Check(MIB->getOperand(0) != nullptr,do { if (!(MIB->getOperand(0) != nullptr)) { CheckFailed("!memprof MemInfoBlock first operand should not be null" , MIB); return; } } while (false) | ||||
4657 | "!memprof MemInfoBlock first operand should not be null", MIB)do { if (!(MIB->getOperand(0) != nullptr)) { CheckFailed("!memprof MemInfoBlock first operand should not be null" , MIB); return; } } while (false); | ||||
4658 | Check(isa<MDNode>(MIB->getOperand(0)),do { if (!(isa<MDNode>(MIB->getOperand(0)))) { CheckFailed ("!memprof MemInfoBlock first operand should be an MDNode", MIB ); return; } } while (false) | ||||
4659 | "!memprof MemInfoBlock first operand should be an MDNode", MIB)do { if (!(isa<MDNode>(MIB->getOperand(0)))) { CheckFailed ("!memprof MemInfoBlock first operand should be an MDNode", MIB ); return; } } while (false); | ||||
4660 | MDNode *StackMD = dyn_cast<MDNode>(MIB->getOperand(0)); | ||||
4661 | visitCallStackMetadata(StackMD); | ||||
4662 | |||||
4663 | // Check that remaining operands are MDString. | ||||
4664 | Check(llvm::all_of(llvm::drop_begin(MIB->operands()),do { if (!(llvm::all_of(llvm::drop_begin(MIB->operands()), [](const MDOperand &Op) { return isa<MDString>(Op) ; }))) { CheckFailed("Not all !memprof MemInfoBlock operands 1 to N are MDString" , MIB); return; } } while (false) | ||||
4665 | [](const MDOperand &Op) { return isa<MDString>(Op); }),do { if (!(llvm::all_of(llvm::drop_begin(MIB->operands()), [](const MDOperand &Op) { return isa<MDString>(Op) ; }))) { CheckFailed("Not all !memprof MemInfoBlock operands 1 to N are MDString" , MIB); return; } } while (false) | ||||
4666 | "Not all !memprof MemInfoBlock operands 1 to N are MDString", MIB)do { if (!(llvm::all_of(llvm::drop_begin(MIB->operands()), [](const MDOperand &Op) { return isa<MDString>(Op) ; }))) { CheckFailed("Not all !memprof MemInfoBlock operands 1 to N are MDString" , MIB); return; } } while (false); | ||||
4667 | } | ||||
4668 | } | ||||
4669 | |||||
4670 | void Verifier::visitCallsiteMetadata(Instruction &I, MDNode *MD) { | ||||
4671 | Check(isa<CallBase>(I), "!callsite metadata should only exist on calls", &I)do { if (!(isa<CallBase>(I))) { CheckFailed("!callsite metadata should only exist on calls" , &I); return; } } while (false); | ||||
4672 | // Verify the partial callstack annotated from memprof profiles. This callsite | ||||
4673 | // is a part of a profiled allocation callstack. | ||||
4674 | visitCallStackMetadata(MD); | ||||
4675 | } | ||||
4676 | |||||
4677 | void Verifier::visitAnnotationMetadata(MDNode *Annotation) { | ||||
4678 | Check(isa<MDTuple>(Annotation), "annotation must be a tuple")do { if (!(isa<MDTuple>(Annotation))) { CheckFailed("annotation must be a tuple" ); return; } } while (false); | ||||
4679 | Check(Annotation->getNumOperands() >= 1,do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false) | ||||
4680 | "annotation must have at least one operand")do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false); | ||||
4681 | for (const MDOperand &Op : Annotation->operands()) { | ||||
4682 | bool TupleOfStrings = | ||||
4683 | isa<MDTuple>(Op.get()) && | ||||
4684 | all_of(cast<MDTuple>(Op)->operands(), [](auto &Annotation) { | ||||
4685 | return isa<MDString>(Annotation.get()); | ||||
4686 | }); | ||||
4687 | Check(isa<MDString>(Op.get()) || TupleOfStrings,do { if (!(isa<MDString>(Op.get()) || TupleOfStrings)) { CheckFailed("operands must be a string or a tuple of strings" ); return; } } while (false) | ||||
4688 | "operands must be a string or a tuple of strings")do { if (!(isa<MDString>(Op.get()) || TupleOfStrings)) { CheckFailed("operands must be a string or a tuple of strings" ); return; } } while (false); | ||||
4689 | } | ||||
4690 | } | ||||
4691 | |||||
4692 | void Verifier::visitAliasScopeMetadata(const MDNode *MD) { | ||||
4693 | unsigned NumOps = MD->getNumOperands(); | ||||
4694 | Check(NumOps >= 2 && NumOps <= 3, "scope must have two or three operands",do { if (!(NumOps >= 2 && NumOps <= 3)) { CheckFailed ("scope must have two or three operands", MD); return; } } while (false) | ||||
4695 | MD)do { if (!(NumOps >= 2 && NumOps <= 3)) { CheckFailed ("scope must have two or three operands", MD); return; } } while (false); | ||||
4696 | Check(MD->getOperand(0).get() == MD || isa<MDString>(MD->getOperand(0)),do { if (!(MD->getOperand(0).get() == MD || isa<MDString >(MD->getOperand(0)))) { CheckFailed("first scope operand must be self-referential or string" , MD); return; } } while (false) | ||||
4697 | "first scope operand must be self-referential or string", MD)do { if (!(MD->getOperand(0).get() == MD || isa<MDString >(MD->getOperand(0)))) { CheckFailed("first scope operand must be self-referential or string" , MD); return; } } while (false); | ||||
4698 | if (NumOps == 3) | ||||
4699 | Check(isa<MDString>(MD->getOperand(2)),do { if (!(isa<MDString>(MD->getOperand(2)))) { CheckFailed ("third scope operand must be string (if used)", MD); return; } } while (false) | ||||
4700 | "third scope operand must be string (if used)", MD)do { if (!(isa<MDString>(MD->getOperand(2)))) { CheckFailed ("third scope operand must be string (if used)", MD); return; } } while (false); | ||||
4701 | |||||
4702 | MDNode *Domain = dyn_cast<MDNode>(MD->getOperand(1)); | ||||
4703 | Check(Domain != nullptr, "second scope operand must be MDNode", MD)do { if (!(Domain != nullptr)) { CheckFailed("second scope operand must be MDNode" , MD); return; } } while (false); | ||||
4704 | |||||
4705 | unsigned NumDomainOps = Domain->getNumOperands(); | ||||
4706 | Check(NumDomainOps >= 1 && NumDomainOps <= 2,do { if (!(NumDomainOps >= 1 && NumDomainOps <= 2)) { CheckFailed("domain must have one or two operands", Domain ); return; } } while (false) | ||||
4707 | "domain must have one or two operands", Domain)do { if (!(NumDomainOps >= 1 && NumDomainOps <= 2)) { CheckFailed("domain must have one or two operands", Domain ); return; } } while (false); | ||||
4708 | Check(Domain->getOperand(0).get() == Domain ||do { if (!(Domain->getOperand(0).get() == Domain || isa< MDString>(Domain->getOperand(0)))) { CheckFailed("first domain operand must be self-referential or string" , Domain); return; } } while (false) | ||||
4709 | isa<MDString>(Domain->getOperand(0)),do { if (!(Domain->getOperand(0).get() == Domain || isa< MDString>(Domain->getOperand(0)))) { CheckFailed("first domain operand must be self-referential or string" , Domain); return; } } while (false) | ||||
4710 | "first domain operand must be self-referential or string", Domain)do { if (!(Domain->getOperand(0).get() == Domain || isa< MDString>(Domain->getOperand(0)))) { CheckFailed("first domain operand must be self-referential or string" , Domain); return; } } while (false); | ||||
4711 | if (NumDomainOps == 2) | ||||
4712 | Check(isa<MDString>(Domain->getOperand(1)),do { if (!(isa<MDString>(Domain->getOperand(1)))) { CheckFailed ("second domain operand must be string (if used)", Domain); return ; } } while (false) | ||||
4713 | "second domain operand must be string (if used)", Domain)do { if (!(isa<MDString>(Domain->getOperand(1)))) { CheckFailed ("second domain operand must be string (if used)", Domain); return ; } } while (false); | ||||
4714 | } | ||||
4715 | |||||
4716 | void Verifier::visitAliasScopeListMetadata(const MDNode *MD) { | ||||
4717 | for (const MDOperand &Op : MD->operands()) { | ||||
4718 | const MDNode *OpMD = dyn_cast<MDNode>(Op); | ||||
4719 | Check(OpMD != nullptr, "scope list must consist of MDNodes", MD)do { if (!(OpMD != nullptr)) { CheckFailed("scope list must consist of MDNodes" , MD); return; } } while (false); | ||||
4720 | visitAliasScopeMetadata(OpMD); | ||||
4721 | } | ||||
4722 | } | ||||
4723 | |||||
4724 | void Verifier::visitAccessGroupMetadata(const MDNode *MD) { | ||||
4725 | auto IsValidAccessScope = [](const MDNode *MD) { | ||||
4726 | return MD->getNumOperands() == 0 && MD->isDistinct(); | ||||
4727 | }; | ||||
4728 | |||||
4729 | // It must be either an access scope itself... | ||||
4730 | if (IsValidAccessScope(MD)) | ||||
4731 | return; | ||||
4732 | |||||
4733 | // ...or a list of access scopes. | ||||
4734 | for (const MDOperand &Op : MD->operands()) { | ||||
4735 | const MDNode *OpMD = dyn_cast<MDNode>(Op); | ||||
4736 | Check(OpMD != nullptr, "Access scope list must consist of MDNodes", MD)do { if (!(OpMD != nullptr)) { CheckFailed("Access scope list must consist of MDNodes" , MD); return; } } while (false); | ||||
4737 | Check(IsValidAccessScope(OpMD),do { if (!(IsValidAccessScope(OpMD))) { CheckFailed("Access scope list contains invalid access scope" , MD); return; } } while (false) | ||||
4738 | "Access scope list contains invalid access scope", MD)do { if (!(IsValidAccessScope(OpMD))) { CheckFailed("Access scope list contains invalid access scope" , MD); return; } } while (false); | ||||
4739 | } | ||||
4740 | } | ||||
4741 | |||||
4742 | /// verifyInstruction - Verify that an instruction is well formed. | ||||
4743 | /// | ||||
4744 | void Verifier::visitInstruction(Instruction &I) { | ||||
4745 | BasicBlock *BB = I.getParent(); | ||||
4746 | Check(BB, "Instruction not embedded in basic block!", &I)do { if (!(BB)) { CheckFailed("Instruction not embedded in basic block!" , &I); return; } } while (false); | ||||
4747 | |||||
4748 | if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential | ||||
4749 | for (User *U : I.users()) { | ||||
4750 | Check(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) | ||||
4751 | "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); | ||||
4752 | } | ||||
4753 | } | ||||
4754 | |||||
4755 | // Check that void typed values don't have names | ||||
4756 | Check(!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) | ||||
4757 | "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); | ||||
4758 | |||||
4759 | // Check that the return value of the instruction is either void or a legal | ||||
4760 | // value type. | ||||
4761 | Check(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) | ||||
4762 | "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); | ||||
4763 | |||||
4764 | // Check that the instruction doesn't produce metadata. Calls are already | ||||
4765 | // checked against the callee type. | ||||
4766 | Check(!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) | ||||
4767 | "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); | ||||
4768 | |||||
4769 | // Check that all uses of the instruction, if they are instructions | ||||
4770 | // themselves, actually have parent basic blocks. If the use is not an | ||||
4771 | // instruction, it is an error! | ||||
4772 | for (Use &U : I.uses()) { | ||||
4773 | if (Instruction *Used = dyn_cast<Instruction>(U.getUser())) | ||||
4774 | Check(Used->getParent() != nullptr,do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
4775 | "Instruction referencing"do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
4776 | " 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) | ||||
4777 | &I, Used)do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false); | ||||
4778 | else { | ||||
4779 | CheckFailed("Use of instruction is not an instruction!", U); | ||||
4780 | return; | ||||
4781 | } | ||||
4782 | } | ||||
4783 | |||||
4784 | // Get a pointer to the call base of the instruction if it is some form of | ||||
4785 | // call. | ||||
4786 | const CallBase *CBI = dyn_cast<CallBase>(&I); | ||||
4787 | |||||
4788 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { | ||||
4789 | Check(I.getOperand(i) != nullptr, "Instruction has null operand!", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Instruction has null operand!" , &I); return; } } while (false); | ||||
4790 | |||||
4791 | // Check to make sure that only first-class-values are operands to | ||||
4792 | // instructions. | ||||
4793 | if (!I.getOperand(i)->getType()->isFirstClassType()) { | ||||
4794 | Check(false, "Instruction operands must be first-class values!", &I)do { if (!(false)) { CheckFailed("Instruction operands must be first-class values!" , &I); return; } } while (false); | ||||
4795 | } | ||||
4796 | |||||
4797 | if (Function *F = dyn_cast<Function>(I.getOperand(i))) { | ||||
4798 | // This code checks whether the function is used as the operand of a | ||||
4799 | // clang_arc_attachedcall operand bundle. | ||||
4800 | auto IsAttachedCallOperand = [](Function *F, const CallBase *CBI, | ||||
4801 | int Idx) { | ||||
4802 | return CBI && CBI->isOperandBundleOfType( | ||||
4803 | LLVMContext::OB_clang_arc_attachedcall, Idx); | ||||
4804 | }; | ||||
4805 | |||||
4806 | // Check to make sure that the "address of" an intrinsic function is never | ||||
4807 | // taken. Ignore cases where the address of the intrinsic function is used | ||||
4808 | // as the argument of operand bundle "clang.arc.attachedcall" as those | ||||
4809 | // cases are handled in verifyAttachedCallBundle. | ||||
4810 | Check((!F->isIntrinsic() ||do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false) | ||||
4811 | (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)) ||do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false) | ||||
4812 | IsAttachedCallOperand(F, CBI, i)),do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false) | ||||
4813 | "Cannot take the address of an intrinsic!", &I)do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false); | ||||
4814 | Check(!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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4815 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4816 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4817 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4818 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4819 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4820 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4821 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4822 | F->getIntrinsicID() ==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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4823 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4824 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4825 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4826 | 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4827 | IsAttachedCallOperand(F, CBI, 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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4828 | "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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4829 | "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall",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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
4830 | &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 || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false); | ||||
4831 | Check(F->getParent() == &M, "Referencing function in another module!", &I,do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ) | ||||
4832 | &M, F, F->getParent())do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ); | ||||
4833 | } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { | ||||
4834 | Check(OpBB->getParent() == BB->getParent(),do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false) | ||||
4835 | "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); | ||||
4836 | } else if (Argument *OpArg = dyn_cast<Argument>(I.getOperand(i))) { | ||||
4837 | Check(OpArg->getParent() == BB->getParent(),do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false) | ||||
4838 | "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); | ||||
4839 | } else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) { | ||||
4840 | Check(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) | ||||
4841 | &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false); | ||||
4842 | } else if (isa<Instruction>(I.getOperand(i))) { | ||||
4843 | verifyDominatesUse(I, i); | ||||
4844 | } else if (isa<InlineAsm>(I.getOperand(i))) { | ||||
4845 | Check(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) | ||||
4846 | "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); | ||||
4847 | } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { | ||||
4848 | if (CE->getType()->isPtrOrPtrVectorTy()) { | ||||
4849 | // If we have a ConstantExpr pointer, we need to see if it came from an | ||||
4850 | // illegal bitcast. | ||||
4851 | visitConstantExprsRecursively(CE); | ||||
4852 | } | ||||
4853 | } | ||||
4854 | } | ||||
4855 | |||||
4856 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_fpmath)) { | ||||
4857 | Check(I.getType()->isFPOrFPVectorTy(),do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false) | ||||
4858 | "fpmath requires a floating point result!", &I)do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false); | ||||
4859 | Check(MD->getNumOperands() == 1, "fpmath takes one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("fpmath takes one operand!" , &I); return; } } while (false); | ||||
4860 | if (ConstantFP *CFP0 = | ||||
4861 | mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { | ||||
4862 | const APFloat &Accuracy = CFP0->getValueAPF(); | ||||
4863 | Check(&Accuracy.getSemantics() == &APFloat::IEEEsingle(),do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false) | ||||
4864 | "fpmath accuracy must have float type", &I)do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false); | ||||
4865 | Check(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(),do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false) | ||||
4866 | "fpmath accuracy not a positive number!", &I)do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false); | ||||
4867 | } else { | ||||
4868 | Check(false, "invalid fpmath accuracy!", &I)do { if (!(false)) { CheckFailed("invalid fpmath accuracy!", & I); return; } } while (false); | ||||
4869 | } | ||||
4870 | } | ||||
4871 | |||||
4872 | if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) { | ||||
4873 | Check(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) | ||||
4874 | "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); | ||||
4875 | visitRangeMetadata(I, Range, I.getType()); | ||||
4876 | } | ||||
4877 | |||||
4878 | if (I.hasMetadata(LLVMContext::MD_invariant_group)) { | ||||
4879 | Check(isa<LoadInst>(I) || isa<StoreInst>(I),do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I)) ) { CheckFailed("invariant.group metadata is only for loads and stores" , &I); return; } } while (false) | ||||
4880 | "invariant.group metadata is only for loads and stores", &I)do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I)) ) { CheckFailed("invariant.group metadata is only for loads and stores" , &I); return; } } while (false); | ||||
4881 | } | ||||
4882 | |||||
4883 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_nonnull)) { | ||||
4884 | Check(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) | ||||
4885 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false); | ||||
4886 | Check(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) | ||||
4887 | "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) | ||||
4888 | " 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) | ||||
4889 | &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false); | ||||
4890 | Check(MD->getNumOperands() == 0, "nonnull metadata must be empty", &I)do { if (!(MD->getNumOperands() == 0)) { CheckFailed("nonnull metadata must be empty" , &I); return; } } while (false); | ||||
4891 | } | ||||
4892 | |||||
4893 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable)) | ||||
4894 | visitDereferenceableMetadata(I, MD); | ||||
4895 | |||||
4896 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) | ||||
4897 | visitDereferenceableMetadata(I, MD); | ||||
4898 | |||||
4899 | if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) | ||||
4900 | TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); | ||||
4901 | |||||
4902 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias)) | ||||
4903 | visitAliasScopeListMetadata(MD); | ||||
4904 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_alias_scope)) | ||||
4905 | visitAliasScopeListMetadata(MD); | ||||
4906 | |||||
4907 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_access_group)) | ||||
4908 | visitAccessGroupMetadata(MD); | ||||
4909 | |||||
4910 | if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { | ||||
4911 | Check(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) | ||||
4912 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false); | ||||
4913 | Check(isa<LoadInst>(I),do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false) | ||||
4914 | "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) | ||||
4915 | "use attributes for calls or invokes",do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false) | ||||
4916 | &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false); | ||||
4917 | Check(AlignMD->getNumOperands() == 1, "align takes one operand!", &I)do { if (!(AlignMD->getNumOperands() == 1)) { CheckFailed( "align takes one operand!", &I); return; } } while (false ); | ||||
4918 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(AlignMD->getOperand(0)); | ||||
4919 | Check(CI && CI->getType()->isIntegerTy(64),do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("align metadata value must be an i64!", & I); return; } } while (false) | ||||
4920 | "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); | ||||
4921 | uint64_t Align = CI->getZExtValue(); | ||||
4922 | Check(isPowerOf2_64(Align), "align metadata value must be a power of 2!",do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false) | ||||
4923 | &I)do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false); | ||||
4924 | Check(Align <= Value::MaximumAlignment,do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false) | ||||
4925 | "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); | ||||
4926 | } | ||||
4927 | |||||
4928 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_prof)) | ||||
4929 | visitProfMetadata(I, MD); | ||||
4930 | |||||
4931 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_memprof)) | ||||
4932 | visitMemProfMetadata(I, MD); | ||||
4933 | |||||
4934 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_callsite)) | ||||
4935 | visitCallsiteMetadata(I, MD); | ||||
4936 | |||||
4937 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_DIAssignID)) | ||||
4938 | visitDIAssignIDMetadata(I, MD); | ||||
4939 | |||||
4940 | if (MDNode *Annotation = I.getMetadata(LLVMContext::MD_annotation)) | ||||
4941 | visitAnnotationMetadata(Annotation); | ||||
4942 | |||||
4943 | if (MDNode *N = I.getDebugLoc().getAsMDNode()) { | ||||
4944 | CheckDI(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N)do { if (!(isa<DILocation>(N))) { DebugInfoCheckFailed( "invalid !dbg metadata attachment", &I, N); return; } } while (false); | ||||
4945 | visitMDNode(*N, AreDebugLocsAllowed::Yes); | ||||
4946 | } | ||||
4947 | |||||
4948 | if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { | ||||
4949 | verifyFragmentExpression(*DII); | ||||
4950 | verifyNotEntryValue(*DII); | ||||
4951 | } | ||||
4952 | |||||
4953 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
4954 | I.getAllMetadata(MDs); | ||||
4955 | for (auto Attachment : MDs) { | ||||
4956 | unsigned Kind = Attachment.first; | ||||
4957 | auto AllowLocs = | ||||
4958 | (Kind == LLVMContext::MD_dbg || Kind == LLVMContext::MD_loop) | ||||
4959 | ? AreDebugLocsAllowed::Yes | ||||
4960 | : AreDebugLocsAllowed::No; | ||||
4961 | visitMDNode(*Attachment.second, AllowLocs); | ||||
4962 | } | ||||
4963 | |||||
4964 | InstsInThisBlock.insert(&I); | ||||
4965 | } | ||||
4966 | |||||
4967 | /// Allow intrinsics to be verified in different ways. | ||||
4968 | void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { | ||||
4969 | Function *IF = Call.getCalledFunction(); | ||||
4970 | Check(IF->isDeclaration(), "Intrinsic functions should never be defined!",do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false) | ||||
4971 | IF)do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false); | ||||
4972 | |||||
4973 | // Verify that the intrinsic prototype lines up with what the .td files | ||||
4974 | // describe. | ||||
4975 | FunctionType *IFTy = IF->getFunctionType(); | ||||
4976 | bool IsVarArg = IFTy->isVarArg(); | ||||
4977 | |||||
4978 | SmallVector<Intrinsic::IITDescriptor, 8> Table; | ||||
4979 | getIntrinsicInfoTableEntries(ID, Table); | ||||
4980 | ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; | ||||
4981 | |||||
4982 | // Walk the descriptors to extract overloaded types. | ||||
4983 | SmallVector<Type *, 4> ArgTys; | ||||
4984 | Intrinsic::MatchIntrinsicTypesResult Res = | ||||
4985 | Intrinsic::matchIntrinsicSignature(IFTy, TableRef, ArgTys); | ||||
4986 | Check(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false) | ||||
4987 | "Intrinsic has incorrect return type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false); | ||||
4988 | Check(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false) | ||||
4989 | "Intrinsic has incorrect argument type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false); | ||||
4990 | |||||
4991 | // Verify if the intrinsic call matches the vararg property. | ||||
4992 | if (IsVarArg) | ||||
4993 | Check(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false) | ||||
4994 | "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); | ||||
4995 | else | ||||
4996 | Check(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false) | ||||
4997 | "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); | ||||
4998 | |||||
4999 | // All descriptors should be absorbed by now. | ||||
5000 | Check(TableRef.empty(), "Intrinsic has too few arguments!", IF)do { if (!(TableRef.empty())) { CheckFailed("Intrinsic has too few arguments!" , IF); return; } } while (false); | ||||
5001 | |||||
5002 | // Now that we have the intrinsic ID and the actual argument types (and we | ||||
5003 | // know they are legal for the intrinsic!) get the intrinsic name through the | ||||
5004 | // usual means. This allows us to verify the mangling of argument types into | ||||
5005 | // the name. | ||||
5006 | const std::string ExpectedName = | ||||
5007 | Intrinsic::getName(ID, ArgTys, IF->getParent(), IFTy); | ||||
5008 | Check(ExpectedName == IF->getName(),do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
5009 | "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) | ||||
5010 | "Should be: " +do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
5011 | ExpectedName,do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
5012 | IF)do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false); | ||||
5013 | |||||
5014 | // If the intrinsic takes MDNode arguments, verify that they are either global | ||||
5015 | // or are local to *this* function. | ||||
5016 | for (Value *V : Call.args()) { | ||||
5017 | if (auto *MD = dyn_cast<MetadataAsValue>(V)) | ||||
5018 | visitMetadataAsValue(*MD, Call.getCaller()); | ||||
5019 | if (auto *Const = dyn_cast<Constant>(V)) | ||||
5020 | Check(!Const->getType()->isX86_AMXTy(),do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false) | ||||
5021 | "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); | ||||
5022 | } | ||||
5023 | |||||
5024 | switch (ID) { | ||||
5025 | default: | ||||
5026 | break; | ||||
5027 | case Intrinsic::assume: { | ||||
5028 | for (auto &Elem : Call.bundle_op_infos()) { | ||||
5029 | unsigned ArgCount = Elem.End - Elem.Begin; | ||||
5030 | // Separate storage assumptions are special insofar as they're the only | ||||
5031 | // operand bundles allowed on assumes that aren't parameter attributes. | ||||
5032 | if (Elem.Tag->getKey() == "separate_storage") { | ||||
5033 | Check(ArgCount == 2,do { if (!(ArgCount == 2)) { CheckFailed("separate_storage assumptions should have 2 arguments" , Call); return; } } while (false) | ||||
5034 | "separate_storage assumptions should have 2 arguments", Call)do { if (!(ArgCount == 2)) { CheckFailed("separate_storage assumptions should have 2 arguments" , Call); return; } } while (false); | ||||
5035 | Check(Call.getOperand(Elem.Begin)->getType()->isPointerTy() &&do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false) | ||||
5036 | Call.getOperand(Elem.Begin + 1)->getType()->isPointerTy(),do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false) | ||||
5037 | "arguments to separate_storage assumptions should be pointers",do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false) | ||||
5038 | Call)do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false); | ||||
5039 | return; | ||||
5040 | } | ||||
5041 | Check(Elem.Tag->getKey() == "ignore" ||do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" , Call); return; } } while (false) | ||||
5042 | Attribute::isExistingAttribute(Elem.Tag->getKey()),do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" , Call); return; } } while (false) | ||||
5043 | "tags must be valid attribute names", Call)do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" , Call); return; } } while (false); | ||||
5044 | Attribute::AttrKind Kind = | ||||
5045 | Attribute::getAttrKindFromName(Elem.Tag->getKey()); | ||||
5046 | if (Kind == Attribute::Alignment) { | ||||
5047 | Check(ArgCount <= 3 && ArgCount >= 2,do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments", Call); return; } } while (false) | ||||
5048 | "alignment assumptions should have 2 or 3 arguments", Call)do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments", Call); return; } } while (false); | ||||
5049 | Check(Call.getOperand(Elem.Begin)->getType()->isPointerTy(),do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer", Call ); return; } } while (false) | ||||
5050 | "first argument should be a pointer", Call)do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer", Call ); return; } } while (false); | ||||
5051 | Check(Call.getOperand(Elem.Begin + 1)->getType()->isIntegerTy(),do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" , Call); return; } } while (false) | ||||
5052 | "second argument should be an integer", Call)do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" , Call); return; } } while (false); | ||||
5053 | if (ArgCount == 3) | ||||
5054 | Check(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" , Call); return; } } while (false) | ||||
5055 | "third argument should be an integer if present", Call)do { if (!(Call.getOperand(Elem.Begin + 2)->getType()-> isIntegerTy())) { CheckFailed("third argument should be an integer if present" , Call); return; } } while (false); | ||||
5056 | return; | ||||
5057 | } | ||||
5058 | Check(ArgCount <= 2, "too many arguments", Call)do { if (!(ArgCount <= 2)) { CheckFailed("too many arguments" , Call); return; } } while (false); | ||||
5059 | if (Kind == Attribute::None) | ||||
5060 | break; | ||||
5061 | if (Attribute::isIntAttrKind(Kind)) { | ||||
5062 | Check(ArgCount == 2, "this attribute should have 2 arguments", Call)do { if (!(ArgCount == 2)) { CheckFailed("this attribute should have 2 arguments" , Call); return; } } while (false); | ||||
5063 | Check(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" , Call); return; } } while (false) | ||||
5064 | "the second argument should be a constant integral value", Call)do { if (!(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)))) { CheckFailed("the second argument should be a constant integral value" , Call); return; } } while (false); | ||||
5065 | } else if (Attribute::canUseAsParamAttr(Kind)) { | ||||
5066 | Check((ArgCount) == 1, "this attribute should have one argument", Call)do { if (!((ArgCount) == 1)) { CheckFailed("this attribute should have one argument" , Call); return; } } while (false); | ||||
5067 | } else if (Attribute::canUseAsFnAttr(Kind)) { | ||||
5068 | Check((ArgCount) == 0, "this attribute has no argument", Call)do { if (!((ArgCount) == 0)) { CheckFailed("this attribute has no argument" , Call); return; } } while (false); | ||||
5069 | } | ||||
5070 | } | ||||
5071 | break; | ||||
5072 | } | ||||
5073 | case Intrinsic::coro_id: { | ||||
5074 | auto *InfoArg = Call.getArgOperand(3)->stripPointerCasts(); | ||||
5075 | if (isa<ConstantPointerNull>(InfoArg)) | ||||
5076 | break; | ||||
5077 | auto *GV = dyn_cast<GlobalVariable>(InfoArg); | ||||
5078 | Check(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) | ||||
5079 | "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) | ||||
5080 | "constant")do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false); | ||||
5081 | Constant *Init = GV->getInitializer(); | ||||
5082 | Check(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) | ||||
5083 | "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) | ||||
5084 | "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); | ||||
5085 | break; | ||||
5086 | } | ||||
5087 | case Intrinsic::is_fpclass: { | ||||
5088 | const ConstantInt *TestMask = cast<ConstantInt>(Call.getOperand(1)); | ||||
5089 | Check((TestMask->getZExtValue() & ~static_cast<unsigned>(fcAllFlags)) == 0,do { if (!((TestMask->getZExtValue() & ~static_cast< unsigned>(fcAllFlags)) == 0)) { CheckFailed("unsupported bits for llvm.is.fpclass test mask" ); return; } } while (false) | ||||
5090 | "unsupported bits for llvm.is.fpclass test mask")do { if (!((TestMask->getZExtValue() & ~static_cast< unsigned>(fcAllFlags)) == 0)) { CheckFailed("unsupported bits for llvm.is.fpclass test mask" ); return; } } while (false); | ||||
5091 | break; | ||||
5092 | } | ||||
5093 | case Intrinsic::fptrunc_round: { | ||||
5094 | // Check the rounding mode | ||||
5095 | Metadata *MD = nullptr; | ||||
5096 | auto *MAV = dyn_cast<MetadataAsValue>(Call.getOperand(1)); | ||||
5097 | if (MAV) | ||||
5098 | MD = MAV->getMetadata(); | ||||
5099 | |||||
5100 | Check(MD != nullptr, "missing rounding mode argument", Call)do { if (!(MD != nullptr)) { CheckFailed("missing rounding mode argument" , Call); return; } } while (false); | ||||
5101 | |||||
5102 | Check(isa<MDString>(MD),do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false) | ||||
5103 | ("invalid value for llvm.fptrunc.round metadata operand"do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false) | ||||
5104 | " (the operand should be a string)"),do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false) | ||||
5105 | MD)do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false); | ||||
5106 | |||||
5107 | std::optional<RoundingMode> RoundMode = | ||||
5108 | convertStrToRoundingMode(cast<MDString>(MD)->getString()); | ||||
5109 | Check(RoundMode && *RoundMode != RoundingMode::Dynamic,do { if (!(RoundMode && *RoundMode != RoundingMode::Dynamic )) { CheckFailed("unsupported rounding mode argument", Call); return; } } while (false) | ||||
5110 | "unsupported rounding mode argument", Call)do { if (!(RoundMode && *RoundMode != RoundingMode::Dynamic )) { CheckFailed("unsupported rounding mode argument", Call); return; } } while (false); | ||||
5111 | break; | ||||
5112 | } | ||||
5113 | #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID: | ||||
5114 | #include "llvm/IR/VPIntrinsics.def" | ||||
5115 | visitVPIntrinsic(cast<VPIntrinsic>(Call)); | ||||
5116 | break; | ||||
5117 | #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ | ||||
5118 | case Intrinsic::INTRINSIC: | ||||
5119 | #include "llvm/IR/ConstrainedOps.def" | ||||
5120 | visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(Call)); | ||||
5121 | break; | ||||
5122 | case Intrinsic::dbg_declare: // llvm.dbg.declare | ||||
5123 | Check(isa<MetadataAsValue>(Call.getArgOperand(0)),do { if (!(isa<MetadataAsValue>(Call.getArgOperand(0))) ) { CheckFailed("invalid llvm.dbg.declare intrinsic call 1", Call ); return; } } while (false) | ||||
5124 | "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); | ||||
5125 | visitDbgIntrinsic("declare", cast<DbgVariableIntrinsic>(Call)); | ||||
5126 | break; | ||||
5127 | case Intrinsic::dbg_value: // llvm.dbg.value | ||||
5128 | visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call)); | ||||
5129 | break; | ||||
5130 | case Intrinsic::dbg_assign: // llvm.dbg.assign | ||||
5131 | visitDbgIntrinsic("assign", cast<DbgVariableIntrinsic>(Call)); | ||||
5132 | break; | ||||
5133 | case Intrinsic::dbg_label: // llvm.dbg.label | ||||
5134 | visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call)); | ||||
5135 | break; | ||||
5136 | case Intrinsic::memcpy: | ||||
5137 | case Intrinsic::memcpy_inline: | ||||
5138 | case Intrinsic::memmove: | ||||
5139 | case Intrinsic::memset: | ||||
5140 | case Intrinsic::memset_inline: { | ||||
5141 | break; | ||||
5142 | } | ||||
5143 | case Intrinsic::memcpy_element_unordered_atomic: | ||||
5144 | case Intrinsic::memmove_element_unordered_atomic: | ||||
5145 | case Intrinsic::memset_element_unordered_atomic: { | ||||
5146 | const auto *AMI = cast<AtomicMemIntrinsic>(&Call); | ||||
5147 | |||||
5148 | ConstantInt *ElementSizeCI = | ||||
5149 | cast<ConstantInt>(AMI->getRawElementSizeInBytes()); | ||||
5150 | const APInt &ElementSizeVal = ElementSizeCI->getValue(); | ||||
5151 | Check(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) | ||||
5152 | "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) | ||||
5153 | "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) | ||||
5154 | 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); | ||||
5155 | |||||
5156 | auto IsValidAlignment = [&](MaybeAlign Alignment) { | ||||
5157 | return Alignment && ElementSizeVal.ule(Alignment->value()); | ||||
5158 | }; | ||||
5159 | Check(IsValidAlignment(AMI->getDestAlign()),do { if (!(IsValidAlignment(AMI->getDestAlign()))) { CheckFailed ("incorrect alignment of the destination argument", Call); return ; } } while (false) | ||||
5160 | "incorrect alignment of the destination argument", Call)do { if (!(IsValidAlignment(AMI->getDestAlign()))) { CheckFailed ("incorrect alignment of the destination argument", Call); return ; } } while (false); | ||||
5161 | if (const auto *AMT = dyn_cast<AtomicMemTransferInst>(AMI)) { | ||||
5162 | Check(IsValidAlignment(AMT->getSourceAlign()),do { if (!(IsValidAlignment(AMT->getSourceAlign()))) { CheckFailed ("incorrect alignment of the source argument", Call); return; } } while (false) | ||||
5163 | "incorrect alignment of the source argument", Call)do { if (!(IsValidAlignment(AMT->getSourceAlign()))) { CheckFailed ("incorrect alignment of the source argument", Call); return; } } while (false); | ||||
5164 | } | ||||
5165 | break; | ||||
5166 | } | ||||
5167 | case Intrinsic::call_preallocated_setup: { | ||||
5168 | auto *NumArgs = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
5169 | Check(NumArgs != nullptr,do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false) | ||||
5170 | "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); | ||||
5171 | bool FoundCall = false; | ||||
5172 | for (User *U : Call.users()) { | ||||
5173 | auto *UseCall = dyn_cast<CallBase>(U); | ||||
5174 | Check(UseCall != nullptr,do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false) | ||||
5175 | "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); | ||||
5176 | const Function *Fn = UseCall->getCalledFunction(); | ||||
5177 | if (Fn && Fn->getIntrinsicID() == Intrinsic::call_preallocated_arg) { | ||||
5178 | auto *AllocArgIndex = dyn_cast<ConstantInt>(UseCall->getArgOperand(1)); | ||||
5179 | Check(AllocArgIndex != nullptr,do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false) | ||||
5180 | "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); | ||||
5181 | auto AllocArgIndexInt = AllocArgIndex->getValue(); | ||||
5182 | Check(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) | ||||
5183 | 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) | ||||
5184 | "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) | ||||
5185 | "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) | ||||
5186 | "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); | ||||
5187 | } else if (Fn && Fn->getIntrinsicID() == | ||||
5188 | Intrinsic::call_preallocated_teardown) { | ||||
5189 | // nothing to do | ||||
5190 | } else { | ||||
5191 | Check(!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) | ||||
5192 | "llvm.call.preallocated.setup")do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
5193 | FoundCall = true; | ||||
5194 | size_t NumPreallocatedArgs = 0; | ||||
5195 | for (unsigned i = 0; i < UseCall->arg_size(); i++) { | ||||
5196 | if (UseCall->paramHasAttr(i, Attribute::Preallocated)) { | ||||
5197 | ++NumPreallocatedArgs; | ||||
5198 | } | ||||
5199 | } | ||||
5200 | Check(NumPreallocatedArgs != 0,do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
5201 | "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) | ||||
5202 | "preallocated arguments")do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false); | ||||
5203 | Check(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) | ||||
5204 | "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) | ||||
5205 | "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) | ||||
5206 | "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) | ||||
5207 | 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); | ||||
5208 | // getOperandBundle() cannot be called if more than one of the operand | ||||
5209 | // bundle exists. There is already a check elsewhere for this, so skip | ||||
5210 | // here if we see more than one. | ||||
5211 | if (UseCall->countOperandBundlesOfType(LLVMContext::OB_preallocated) > | ||||
5212 | 1) { | ||||
5213 | return; | ||||
5214 | } | ||||
5215 | auto PreallocatedBundle = | ||||
5216 | UseCall->getOperandBundle(LLVMContext::OB_preallocated); | ||||
5217 | Check(PreallocatedBundle,do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
5218 | "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) | ||||
5219 | "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); | ||||
5220 | Check(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) | ||||
5221 | "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) | ||||
5222 | "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); | ||||
5223 | } | ||||
5224 | } | ||||
5225 | break; | ||||
5226 | } | ||||
5227 | case Intrinsic::call_preallocated_arg: { | ||||
5228 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
5229 | Check(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) | ||||
5230 | 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) | ||||
5231 | "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) | ||||
5232 | "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); | ||||
5233 | Check(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) | ||||
5234 | "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) | ||||
5235 | "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); | ||||
5236 | break; | ||||
5237 | } | ||||
5238 | case Intrinsic::call_preallocated_teardown: { | ||||
5239 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
5240 | Check(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) | ||||
5241 | 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) | ||||
5242 | "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) | ||||
5243 | "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); | ||||
5244 | break; | ||||
5245 | } | ||||
5246 | case Intrinsic::gcroot: | ||||
5247 | case Intrinsic::gcwrite: | ||||
5248 | case Intrinsic::gcread: | ||||
5249 | if (ID == Intrinsic::gcroot) { | ||||
5250 | AllocaInst *AI = | ||||
5251 | dyn_cast<AllocaInst>(Call.getArgOperand(0)->stripPointerCasts()); | ||||
5252 | Check(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); | ||||
5253 | Check(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) | ||||
5254 | "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); | ||||
5255 | if (!AI->getAllocatedType()->isPointerTy()) { | ||||
5256 | Check(!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) | ||||
5257 | "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) | ||||
5258 | "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) | ||||
5259 | 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); | ||||
5260 | } | ||||
5261 | } | ||||
5262 | |||||
5263 | Check(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
5264 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
5265 | break; | ||||
5266 | case Intrinsic::init_trampoline: | ||||
5267 | Check(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) | ||||
5268 | "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) | ||||
5269 | Call)do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false); | ||||
5270 | break; | ||||
5271 | case Intrinsic::prefetch: | ||||
5272 | Check(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("rw argument to llvm.prefetch must be 0-1" , Call); return; } } while (false) | ||||
5273 | "rw argument to llvm.prefetch must be 0-1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("rw argument to llvm.prefetch must be 0-1" , Call); return; } } while (false); | ||||
5274 | Check(cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4,do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("locality argument to llvm.prefetch must be 0-4" , Call); return; } } while (false) | ||||
5275 | "locality argument to llvm.prefetch must be 0-4", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("locality argument to llvm.prefetch must be 0-4" , Call); return; } } while (false); | ||||
5276 | Check(cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("cache type argument to llvm.prefetch must be 0-1" , Call); return; } } while (false) | ||||
5277 | "cache type argument to llvm.prefetch must be 0-1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("cache type argument to llvm.prefetch must be 0-1" , Call); return; } } while (false); | ||||
5278 | break; | ||||
5279 | case Intrinsic::stackprotector: | ||||
5280 | Check(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) | ||||
5281 | "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); | ||||
5282 | break; | ||||
5283 | case Intrinsic::localescape: { | ||||
5284 | BasicBlock *BB = Call.getParent(); | ||||
5285 | Check(BB->isEntryBlock(), "llvm.localescape used outside of entry block",do { if (!(BB->isEntryBlock())) { CheckFailed("llvm.localescape used outside of entry block" , Call); return; } } while (false) | ||||
5286 | Call)do { if (!(BB->isEntryBlock())) { CheckFailed("llvm.localescape used outside of entry block" , Call); return; } } while (false); | ||||
5287 | Check(!SawFrameEscape, "multiple calls to llvm.localescape in one function",do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false) | ||||
5288 | Call)do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false); | ||||
5289 | for (Value *Arg : Call.args()) { | ||||
5290 | if (isa<ConstantPointerNull>(Arg)) | ||||
5291 | continue; // Null values are allowed as placeholders. | ||||
5292 | auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts()); | ||||
5293 | Check(AI && AI->isStaticAlloca(),do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false) | ||||
5294 | "llvm.localescape only accepts static allocas", Call)do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false); | ||||
5295 | } | ||||
5296 | FrameEscapeInfo[BB->getParent()].first = Call.arg_size(); | ||||
5297 | SawFrameEscape = true; | ||||
5298 | break; | ||||
5299 | } | ||||
5300 | case Intrinsic::localrecover: { | ||||
5301 | Value *FnArg = Call.getArgOperand(0)->stripPointerCasts(); | ||||
5302 | Function *Fn = dyn_cast<Function>(FnArg); | ||||
5303 | Check(Fn && !Fn->isDeclaration(),do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
5304 | "llvm.localrecover first "do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
5305 | "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) | ||||
5306 | Call)do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false); | ||||
5307 | auto *IdxArg = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5308 | auto &Entry = FrameEscapeInfo[Fn]; | ||||
5309 | Entry.second = unsigned( | ||||
5310 | std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1)); | ||||
5311 | break; | ||||
5312 | } | ||||
5313 | |||||
5314 | case Intrinsic::experimental_gc_statepoint: | ||||
5315 | if (auto *CI = dyn_cast<CallInst>(&Call)) | ||||
5316 | Check(!CI->isInlineAsm(),do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false) | ||||
5317 | "gc.statepoint support for inline assembly unimplemented", CI)do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false); | ||||
5318 | Check(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
5319 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
5320 | |||||
5321 | verifyStatepoint(Call); | ||||
5322 | break; | ||||
5323 | case Intrinsic::experimental_gc_result: { | ||||
5324 | Check(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
5325 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
5326 | |||||
5327 | auto *Statepoint = Call.getArgOperand(0); | ||||
5328 | if (isa<UndefValue>(Statepoint)) | ||||
5329 | break; | ||||
5330 | |||||
5331 | // Are we tied to a statepoint properly? | ||||
5332 | const auto *StatepointCall = dyn_cast<CallBase>(Statepoint); | ||||
5333 | const Function *StatepointFn = | ||||
5334 | StatepointCall ? StatepointCall->getCalledFunction() : nullptr; | ||||
5335 | Check(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) | ||||
5336 | 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) | ||||
5337 | 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) | ||||
5338 | "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) | ||||
5339 | 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); | ||||
5340 | |||||
5341 | // Check that result type matches wrapped callee. | ||||
5342 | auto *TargetFuncType = | ||||
5343 | cast<FunctionType>(StatepointCall->getParamElementType(2)); | ||||
5344 | Check(Call.getType() == TargetFuncType->getReturnType(),do { if (!(Call.getType() == TargetFuncType->getReturnType ())) { CheckFailed("gc.result result type does not match wrapped callee" , Call); return; } } while (false) | ||||
5345 | "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); | ||||
5346 | break; | ||||
5347 | } | ||||
5348 | case Intrinsic::experimental_gc_relocate: { | ||||
5349 | Check(Call.arg_size() == 3, "wrong number of arguments", Call)do { if (!(Call.arg_size() == 3)) { CheckFailed("wrong number of arguments" , Call); return; } } while (false); | ||||
5350 | |||||
5351 | Check(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) | ||||
5352 | "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); | ||||
5353 | |||||
5354 | // Check that this relocate is correctly tied to the statepoint | ||||
5355 | |||||
5356 | // This is case for relocate on the unwinding path of an invoke statepoint | ||||
5357 | if (LandingPadInst *LandingPad = | ||||
5358 | dyn_cast<LandingPadInst>(Call.getArgOperand(0))) { | ||||
5359 | |||||
5360 | const BasicBlock *InvokeBB = | ||||
5361 | LandingPad->getParent()->getUniquePredecessor(); | ||||
5362 | |||||
5363 | // Landingpad relocates should have only one predecessor with invoke | ||||
5364 | // statepoint terminator | ||||
5365 | Check(InvokeBB, "safepoints should have unique landingpads",do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false) | ||||
5366 | LandingPad->getParent())do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false); | ||||
5367 | Check(InvokeBB->getTerminator(), "safepoint block should be well formed",do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false) | ||||
5368 | InvokeBB)do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false); | ||||
5369 | Check(isa<GCStatepointInst>(InvokeBB->getTerminator()),do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false) | ||||
5370 | "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); | ||||
5371 | } else { | ||||
5372 | // In all other cases relocate should be tied to the statepoint directly. | ||||
5373 | // This covers relocates on a normal return path of invoke statepoint and | ||||
5374 | // relocates of a call statepoint. | ||||
5375 | auto *Token = Call.getArgOperand(0); | ||||
5376 | Check(isa<GCStatepointInst>(Token) || isa<UndefValue>(Token),do { if (!(isa<GCStatepointInst>(Token) || isa<UndefValue >(Token))) { CheckFailed("gc relocate is incorrectly tied to the statepoint" , Call, Token); return; } } while (false) | ||||
5377 | "gc relocate is incorrectly tied to the statepoint", Call, Token)do { if (!(isa<GCStatepointInst>(Token) || isa<UndefValue >(Token))) { CheckFailed("gc relocate is incorrectly tied to the statepoint" , Call, Token); return; } } while (false); | ||||
5378 | } | ||||
5379 | |||||
5380 | // Verify rest of the relocate arguments. | ||||
5381 | const Value &StatepointCall = *cast<GCRelocateInst>(Call).getStatepoint(); | ||||
5382 | |||||
5383 | // Both the base and derived must be piped through the safepoint. | ||||
5384 | Value *Base = Call.getArgOperand(1); | ||||
5385 | Check(isa<ConstantInt>(Base),do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false) | ||||
5386 | "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); | ||||
5387 | |||||
5388 | Value *Derived = Call.getArgOperand(2); | ||||
5389 | Check(isa<ConstantInt>(Derived),do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false) | ||||
5390 | "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); | ||||
5391 | |||||
5392 | const uint64_t BaseIndex = cast<ConstantInt>(Base)->getZExtValue(); | ||||
5393 | const uint64_t DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue(); | ||||
5394 | |||||
5395 | // Check the bounds | ||||
5396 | if (isa<UndefValue>(StatepointCall)) | ||||
5397 | break; | ||||
5398 | if (auto Opt = cast<GCStatepointInst>(StatepointCall) | ||||
5399 | .getOperandBundle(LLVMContext::OB_gc_live)) { | ||||
5400 | Check(BaseIndex < Opt->Inputs.size(),do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false) | ||||
5401 | "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); | ||||
5402 | Check(DerivedIndex < Opt->Inputs.size(),do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false) | ||||
5403 | "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); | ||||
5404 | } | ||||
5405 | |||||
5406 | // Relocated value must be either a pointer type or vector-of-pointer type, | ||||
5407 | // but gc_relocate does not need to return the same pointer type as the | ||||
5408 | // relocated pointer. It can be casted to the correct type later if it's | ||||
5409 | // desired. However, they must have the same address space and 'vectorness' | ||||
5410 | GCRelocateInst &Relocate = cast<GCRelocateInst>(Call); | ||||
5411 | auto *ResultType = Call.getType(); | ||||
5412 | auto *DerivedType = Relocate.getDerivedPtr()->getType(); | ||||
5413 | auto *BaseType = Relocate.getBasePtr()->getType(); | ||||
5414 | |||||
5415 | Check(BaseType->isPtrOrPtrVectorTy(),do { if (!(BaseType->isPtrOrPtrVectorTy())) { CheckFailed( "gc.relocate: relocated value must be a pointer", Call); return ; } } while (false) | ||||
5416 | "gc.relocate: relocated value must be a pointer", Call)do { if (!(BaseType->isPtrOrPtrVectorTy())) { CheckFailed( "gc.relocate: relocated value must be a pointer", Call); return ; } } while (false); | ||||
5417 | Check(DerivedType->isPtrOrPtrVectorTy(),do { if (!(DerivedType->isPtrOrPtrVectorTy())) { CheckFailed ("gc.relocate: relocated value must be a pointer", Call); return ; } } while (false) | ||||
5418 | "gc.relocate: relocated value must be a pointer", Call)do { if (!(DerivedType->isPtrOrPtrVectorTy())) { CheckFailed ("gc.relocate: relocated value must be a pointer", Call); return ; } } while (false); | ||||
5419 | |||||
5420 | Check(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) | ||||
5421 | "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) | ||||
5422 | Call)do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false); | ||||
5423 | Check(do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
5424 | ResultType->getPointerAddressSpace() ==do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
5425 | DerivedType->getPointerAddressSpace(),do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
5426 | "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) | ||||
5427 | Call)do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false); | ||||
5428 | |||||
5429 | auto GC = llvm::getGCStrategy(Relocate.getFunction()->getGC()); | ||||
5430 | Check(GC, "gc.relocate: calling function must have GCStrategy",do { if (!(GC)) { CheckFailed("gc.relocate: calling function must have GCStrategy" , Call.getFunction()); return; } } while (false) | ||||
5431 | Call.getFunction())do { if (!(GC)) { CheckFailed("gc.relocate: calling function must have GCStrategy" , Call.getFunction()); return; } } while (false); | ||||
5432 | if (GC) { | ||||
5433 | auto isGCPtr = [&GC](Type *PTy) { | ||||
5434 | return GC->isGCManagedPointer(PTy->getScalarType()).value_or(true); | ||||
5435 | }; | ||||
5436 | Check(isGCPtr(ResultType), "gc.relocate: must return gc pointer", Call)do { if (!(isGCPtr(ResultType))) { CheckFailed("gc.relocate: must return gc pointer" , Call); return; } } while (false); | ||||
5437 | Check(isGCPtr(BaseType),do { if (!(isGCPtr(BaseType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false) | ||||
5438 | "gc.relocate: relocated value must be a gc pointer", Call)do { if (!(isGCPtr(BaseType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false); | ||||
5439 | Check(isGCPtr(DerivedType),do { if (!(isGCPtr(DerivedType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false) | ||||
5440 | "gc.relocate: relocated value must be a gc pointer", Call)do { if (!(isGCPtr(DerivedType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false); | ||||
5441 | } | ||||
5442 | break; | ||||
5443 | } | ||||
5444 | case Intrinsic::eh_exceptioncode: | ||||
5445 | case Intrinsic::eh_exceptionpointer: { | ||||
5446 | Check(isa<CatchPadInst>(Call.getArgOperand(0)),do { if (!(isa<CatchPadInst>(Call.getArgOperand(0)))) { CheckFailed("eh.exceptionpointer argument must be a catchpad" , Call); return; } } while (false) | ||||
5447 | "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); | ||||
5448 | break; | ||||
5449 | } | ||||
5450 | case Intrinsic::get_active_lane_mask: { | ||||
5451 | Check(Call.getType()->isVectorTy(),do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false) | ||||
5452 | "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) | ||||
5453 | "vector",do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false) | ||||
5454 | Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false); | ||||
5455 | auto *ElemTy = Call.getType()->getScalarType(); | ||||
5456 | Check(ElemTy->isIntegerTy(1),do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false) | ||||
5457 | "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) | ||||
5458 | "i1",do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false) | ||||
5459 | Call)do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false); | ||||
5460 | break; | ||||
5461 | } | ||||
5462 | case Intrinsic::masked_load: { | ||||
5463 | Check(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) | ||||
5464 | Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false); | ||||
5465 | |||||
5466 | Value *Ptr = Call.getArgOperand(0); | ||||
5467 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
5468 | Value *Mask = Call.getArgOperand(2); | ||||
5469 | Value *PassThru = Call.getArgOperand(3); | ||||
5470 | Check(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) | ||||
5471 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false); | ||||
5472 | Check(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false) | ||||
5473 | "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); | ||||
5474 | |||||
5475 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
5476 | Check(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false) | ||||
5477 | "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); | ||||
5478 | Check(PassThru->getType() == Call.getType(),do { if (!(PassThru->getType() == Call.getType())) { CheckFailed ("masked_load: pass through and return type must match", Call ); return; } } while (false) | ||||
5479 | "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); | ||||
5480 | Check(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) | ||||
5481 | 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) | ||||
5482 | "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); | ||||
5483 | break; | ||||
5484 | } | ||||
5485 | case Intrinsic::masked_store: { | ||||
5486 | Value *Val = Call.getArgOperand(0); | ||||
5487 | Value *Ptr = Call.getArgOperand(1); | ||||
5488 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5489 | Value *Mask = Call.getArgOperand(3); | ||||
5490 | Check(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) | ||||
5491 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false); | ||||
5492 | Check(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false) | ||||
5493 | "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); | ||||
5494 | |||||
5495 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
5496 | Check(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false) | ||||
5497 | "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); | ||||
5498 | Check(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) | ||||
5499 | 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) | ||||
5500 | "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); | ||||
5501 | break; | ||||
5502 | } | ||||
5503 | |||||
5504 | case Intrinsic::masked_gather: { | ||||
5505 | const APInt &Alignment = | ||||
5506 | cast<ConstantInt>(Call.getArgOperand(1))->getValue(); | ||||
5507 | Check(Alignment.isZero() || Alignment.isPowerOf2(),do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_gather: alignment must be 0 or a power of 2", Call); return; } } while (false) | ||||
5508 | "masked_gather: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_gather: alignment must be 0 or a power of 2", Call); return; } } while (false); | ||||
5509 | break; | ||||
5510 | } | ||||
5511 | case Intrinsic::masked_scatter: { | ||||
5512 | const APInt &Alignment = | ||||
5513 | cast<ConstantInt>(Call.getArgOperand(2))->getValue(); | ||||
5514 | Check(Alignment.isZero() || Alignment.isPowerOf2(),do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_scatter: alignment must be 0 or a power of 2", Call) ; return; } } while (false) | ||||
5515 | "masked_scatter: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_scatter: alignment must be 0 or a power of 2", Call) ; return; } } while (false); | ||||
5516 | break; | ||||
5517 | } | ||||
5518 | |||||
5519 | case Intrinsic::experimental_guard: { | ||||
5520 | Check(isa<CallInst>(Call), "experimental_guard cannot be invoked", Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_guard cannot be invoked" , Call); return; } } while (false); | ||||
5521 | Check(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) | ||||
5522 | "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) | ||||
5523 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
5524 | break; | ||||
5525 | } | ||||
5526 | |||||
5527 | case Intrinsic::experimental_deoptimize: { | ||||
5528 | Check(isa<CallInst>(Call), "experimental_deoptimize cannot be invoked",do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false) | ||||
5529 | Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false); | ||||
5530 | Check(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) | ||||
5531 | "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) | ||||
5532 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
5533 | Check(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) | ||||
5534 | "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); | ||||
5535 | |||||
5536 | if (isa<CallInst>(Call)) { | ||||
5537 | auto *RI = dyn_cast<ReturnInst>(Call.getNextNode()); | ||||
5538 | Check(RI,do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false) | ||||
5539 | "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); | ||||
5540 | |||||
5541 | if (!Call.getType()->isVoidTy() && RI) | ||||
5542 | Check(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) | ||||
5543 | "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) | ||||
5544 | "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); | ||||
5545 | } | ||||
5546 | |||||
5547 | break; | ||||
5548 | } | ||||
5549 | case Intrinsic::vector_reduce_and: | ||||
5550 | case Intrinsic::vector_reduce_or: | ||||
5551 | case Intrinsic::vector_reduce_xor: | ||||
5552 | case Intrinsic::vector_reduce_add: | ||||
5553 | case Intrinsic::vector_reduce_mul: | ||||
5554 | case Intrinsic::vector_reduce_smax: | ||||
5555 | case Intrinsic::vector_reduce_smin: | ||||
5556 | case Intrinsic::vector_reduce_umax: | ||||
5557 | case Intrinsic::vector_reduce_umin: { | ||||
5558 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
5559 | Check(ArgTy->isIntOrIntVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5560 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5561 | break; | ||||
5562 | } | ||||
5563 | case Intrinsic::vector_reduce_fmax: | ||||
5564 | case Intrinsic::vector_reduce_fmin: { | ||||
5565 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
5566 | Check(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5567 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5568 | break; | ||||
5569 | } | ||||
5570 | case Intrinsic::vector_reduce_fadd: | ||||
5571 | case Intrinsic::vector_reduce_fmul: { | ||||
5572 | // Unlike the other reductions, the first argument is a start value. The | ||||
5573 | // second argument is the vector to be reduced. | ||||
5574 | Type *ArgTy = Call.getArgOperand(1)->getType(); | ||||
5575 | Check(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
5576 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
5577 | break; | ||||
5578 | } | ||||
5579 | case Intrinsic::smul_fix: | ||||
5580 | case Intrinsic::smul_fix_sat: | ||||
5581 | case Intrinsic::umul_fix: | ||||
5582 | case Intrinsic::umul_fix_sat: | ||||
5583 | case Intrinsic::sdiv_fix: | ||||
5584 | case Intrinsic::sdiv_fix_sat: | ||||
5585 | case Intrinsic::udiv_fix: | ||||
5586 | case Intrinsic::udiv_fix_sat: { | ||||
5587 | Value *Op1 = Call.getArgOperand(0); | ||||
5588 | Value *Op2 = Call.getArgOperand(1); | ||||
5589 | Check(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) | ||||
5590 | "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) | ||||
5591 | "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); | ||||
5592 | Check(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) | ||||
5593 | "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) | ||||
5594 | "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); | ||||
5595 | |||||
5596 | auto *Op3 = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5597 | Check(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) | ||||
5598 | "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); | ||||
5599 | |||||
5600 | if (ID == Intrinsic::smul_fix || ID == Intrinsic::smul_fix_sat || | ||||
5601 | ID == Intrinsic::sdiv_fix || ID == Intrinsic::sdiv_fix_sat) { | ||||
5602 | Check(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) | ||||
5603 | "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) | ||||
5604 | "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); | ||||
5605 | } else { | ||||
5606 | Check(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) | ||||
5607 | "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) | ||||
5608 | "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); | ||||
5609 | } | ||||
5610 | break; | ||||
5611 | } | ||||
5612 | case Intrinsic::lround: | ||||
5613 | case Intrinsic::llround: | ||||
5614 | case Intrinsic::lrint: | ||||
5615 | case Intrinsic::llrint: { | ||||
5616 | Type *ValTy = Call.getArgOperand(0)->getType(); | ||||
5617 | Type *ResultTy = Call.getType(); | ||||
5618 | Check(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false) | ||||
5619 | "Intrinsic does not support vectors", &Call)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false); | ||||
5620 | break; | ||||
5621 | } | ||||
5622 | case Intrinsic::bswap: { | ||||
5623 | Type *Ty = Call.getType(); | ||||
5624 | unsigned Size = Ty->getScalarSizeInBits(); | ||||
5625 | Check(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); | ||||
5626 | break; | ||||
5627 | } | ||||
5628 | case Intrinsic::invariant_start: { | ||||
5629 | ConstantInt *InvariantSize = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
5630 | Check(InvariantSize &&do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
5631 | (!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) | ||||
5632 | "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) | ||||
5633 | &Call)do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false); | ||||
5634 | break; | ||||
5635 | } | ||||
5636 | case Intrinsic::matrix_multiply: | ||||
5637 | case Intrinsic::matrix_transpose: | ||||
5638 | case Intrinsic::matrix_column_major_load: | ||||
5639 | case Intrinsic::matrix_column_major_store: { | ||||
5640 | Function *IF = Call.getCalledFunction(); | ||||
5641 | ConstantInt *Stride = nullptr; | ||||
5642 | ConstantInt *NumRows; | ||||
5643 | ConstantInt *NumColumns; | ||||
5644 | VectorType *ResultTy; | ||||
5645 | Type *Op0ElemTy = nullptr; | ||||
5646 | Type *Op1ElemTy = nullptr; | ||||
5647 | switch (ID) { | ||||
5648 | case Intrinsic::matrix_multiply: { | ||||
5649 | NumRows = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5650 | ConstantInt *N = cast<ConstantInt>(Call.getArgOperand(3)); | ||||
5651 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5652 | Check(cast<FixedVectorType>(Call.getArgOperand(0)->getType())do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5653 | ->getNumElements() ==do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5654 | NumRows->getZExtValue() * N->getZExtValue(),do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5655 | "First argument of a matrix operation does not match specified "do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5656 | "shape!")do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false); | ||||
5657 | Check(cast<FixedVectorType>(Call.getArgOperand(1)->getType())do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5658 | ->getNumElements() ==do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5659 | N->getZExtValue() * NumColumns->getZExtValue(),do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5660 | "Second argument of a matrix operation does not match specified "do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
5661 | "shape!")do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false); | ||||
5662 | |||||
5663 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5664 | Op0ElemTy = | ||||
5665 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5666 | Op1ElemTy = | ||||
5667 | cast<VectorType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
5668 | break; | ||||
5669 | } | ||||
5670 | case Intrinsic::matrix_transpose: | ||||
5671 | NumRows = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
5672 | NumColumns = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5673 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5674 | Op0ElemTy = | ||||
5675 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5676 | break; | ||||
5677 | case Intrinsic::matrix_column_major_load: { | ||||
5678 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(1)); | ||||
5679 | NumRows = cast<ConstantInt>(Call.getArgOperand(3)); | ||||
5680 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5681 | ResultTy = cast<VectorType>(Call.getType()); | ||||
5682 | |||||
5683 | PointerType *Op0PtrTy = | ||||
5684 | cast<PointerType>(Call.getArgOperand(0)->getType()); | ||||
5685 | if (!Op0PtrTy->isOpaque()) | ||||
5686 | Op0ElemTy = Op0PtrTy->getNonOpaquePointerElementType(); | ||||
5687 | break; | ||||
5688 | } | ||||
5689 | case Intrinsic::matrix_column_major_store: { | ||||
5690 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(2)); | ||||
5691 | NumRows = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
5692 | NumColumns = cast<ConstantInt>(Call.getArgOperand(5)); | ||||
5693 | ResultTy = cast<VectorType>(Call.getArgOperand(0)->getType()); | ||||
5694 | Op0ElemTy = | ||||
5695 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
5696 | |||||
5697 | PointerType *Op1PtrTy = | ||||
5698 | cast<PointerType>(Call.getArgOperand(1)->getType()); | ||||
5699 | if (!Op1PtrTy->isOpaque()) | ||||
5700 | Op1ElemTy = Op1PtrTy->getNonOpaquePointerElementType(); | ||||
5701 | break; | ||||
5702 | } | ||||
5703 | default: | ||||
5704 | llvm_unreachable("unexpected intrinsic")::llvm::llvm_unreachable_internal("unexpected intrinsic", "llvm/lib/IR/Verifier.cpp" , 5704); | ||||
5705 | } | ||||
5706 | |||||
5707 | Check(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) | ||||
5708 | 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) | ||||
5709 | "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); | ||||
5710 | |||||
5711 | if (Op0ElemTy) | ||||
5712 | Check(ResultTy->getElementType() == Op0ElemTy,do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
5713 | "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) | ||||
5714 | "vector!",do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
5715 | IF)do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false); | ||||
5716 | |||||
5717 | if (Op1ElemTy) | ||||
5718 | Check(ResultTy->getElementType() == Op1ElemTy,do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
5719 | "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) | ||||
5720 | "vector!",do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
5721 | IF)do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false); | ||||
5722 | |||||
5723 | Check(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) | ||||
5724 | 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) | ||||
5725 | "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); | ||||
5726 | |||||
5727 | if (Stride) | ||||
5728 | Check(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) | ||||
5729 | "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); | ||||
5730 | |||||
5731 | break; | ||||
5732 | } | ||||
5733 | case Intrinsic::experimental_vector_splice: { | ||||
5734 | VectorType *VecTy = cast<VectorType>(Call.getType()); | ||||
5735 | int64_t Idx = cast<ConstantInt>(Call.getArgOperand(2))->getSExtValue(); | ||||
5736 | int64_t KnownMinNumElements = VecTy->getElementCount().getKnownMinValue(); | ||||
5737 | if (Call.getParent() && Call.getParent()->getParent()) { | ||||
5738 | AttributeList Attrs = Call.getParent()->getParent()->getAttributes(); | ||||
5739 | if (Attrs.hasFnAttr(Attribute::VScaleRange)) | ||||
5740 | KnownMinNumElements *= Attrs.getFnAttrs().getVScaleRangeMin(); | ||||
5741 | } | ||||
5742 | Check((Idx < 0 && std::abs(Idx) <= KnownMinNumElements) ||do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
5743 | (Idx >= 0 && Idx < KnownMinNumElements),do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
5744 | "The splice index exceeds the range [-VL, VL-1] where VL is the "do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
5745 | "known minimum number of elements in the vector. For scalable "do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
5746 | "vectors the minimum number of elements is determined from "do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
5747 | "vscale_range.",do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
5748 | &Call)do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false); | ||||
5749 | break; | ||||
5750 | } | ||||
5751 | case Intrinsic::experimental_stepvector: { | ||||
5752 | VectorType *VecTy = dyn_cast<VectorType>(Call.getType()); | ||||
5753 | Check(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) | ||||
5754 | 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) | ||||
5755 | "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) | ||||
5756 | "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) | ||||
5757 | &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); | ||||
5758 | break; | ||||
5759 | } | ||||
5760 | case Intrinsic::vector_insert: { | ||||
5761 | Value *Vec = Call.getArgOperand(0); | ||||
5762 | Value *SubVec = Call.getArgOperand(1); | ||||
5763 | Value *Idx = Call.getArgOperand(2); | ||||
5764 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
5765 | |||||
5766 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
5767 | VectorType *SubVecTy = cast<VectorType>(SubVec->getType()); | ||||
5768 | |||||
5769 | ElementCount VecEC = VecTy->getElementCount(); | ||||
5770 | ElementCount SubVecEC = SubVecTy->getElementCount(); | ||||
5771 | Check(VecTy->getElementType() == SubVecTy->getElementType(),do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
5772 | "vector_insert parameters must have the same element "do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
5773 | "type.",do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
5774 | &Call)do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false); | ||||
5775 | Check(IdxN % SubVecEC.getKnownMinValue() == 0,do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("vector_insert index must be a constant multiple of " "the subvector's known minimum vector length." ); return; } } while (false) | ||||
5776 | "vector_insert index must be a constant multiple of "do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("vector_insert index must be a constant multiple of " "the subvector's known minimum vector length." ); return; } } while (false) | ||||
5777 | "the subvector's known minimum vector length.")do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("vector_insert index must be a constant multiple of " "the subvector's known minimum vector length." ); return; } } while (false); | ||||
5778 | |||||
5779 | // If this insertion is not the 'mixed' case where a fixed vector is | ||||
5780 | // inserted into a scalable vector, ensure that the insertion of the | ||||
5781 | // subvector does not overrun the parent vector. | ||||
5782 | if (VecEC.isScalable() == SubVecEC.isScalable()) { | ||||
5783 | Check(IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
5784 | IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
5785 | "subvector operand of vector_insert would overrun the "do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
5786 | "vector being inserted into.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false); | ||||
5787 | } | ||||
5788 | break; | ||||
5789 | } | ||||
5790 | case Intrinsic::vector_extract: { | ||||
5791 | Value *Vec = Call.getArgOperand(0); | ||||
5792 | Value *Idx = Call.getArgOperand(1); | ||||
5793 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
5794 | |||||
5795 | VectorType *ResultTy = cast<VectorType>(Call.getType()); | ||||
5796 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
5797 | |||||
5798 | ElementCount VecEC = VecTy->getElementCount(); | ||||
5799 | ElementCount ResultEC = ResultTy->getElementCount(); | ||||
5800 | |||||
5801 | Check(ResultTy->getElementType() == VecTy->getElementType(),do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
5802 | "vector_extract result must have the same element "do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
5803 | "type as the input vector.",do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
5804 | &Call)do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false); | ||||
5805 | Check(IdxN % ResultEC.getKnownMinValue() == 0,do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("vector_extract index must be a constant multiple of " "the result type's known minimum vector length." ); return; } } while (false) | ||||
5806 | "vector_extract index must be a constant multiple of "do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("vector_extract index must be a constant multiple of " "the result type's known minimum vector length." ); return; } } while (false) | ||||
5807 | "the result type's known minimum vector length.")do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("vector_extract index must be a constant multiple of " "the result type's known minimum vector length." ); return; } } while (false); | ||||
5808 | |||||
5809 | // If this extraction is not the 'mixed' case where a fixed vector is is | ||||
5810 | // extracted from a scalable vector, ensure that the extraction does not | ||||
5811 | // overrun the parent vector. | ||||
5812 | if (VecEC.isScalable() == ResultEC.isScalable()) { | ||||
5813 | Check(IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("vector_extract would overrun."); return; } } while (false) | ||||
5814 | IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("vector_extract would overrun."); return; } } while (false) | ||||
5815 | "vector_extract would overrun.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("vector_extract would overrun."); return; } } while (false); | ||||
5816 | } | ||||
5817 | break; | ||||
5818 | } | ||||
5819 | case Intrinsic::experimental_noalias_scope_decl: { | ||||
5820 | NoAliasScopeDecls.push_back(cast<IntrinsicInst>(&Call)); | ||||
5821 | break; | ||||
5822 | } | ||||
5823 | case Intrinsic::preserve_array_access_index: | ||||
5824 | case Intrinsic::preserve_struct_access_index: | ||||
5825 | case Intrinsic::aarch64_ldaxr: | ||||
5826 | case Intrinsic::aarch64_ldxr: | ||||
5827 | case Intrinsic::arm_ldaex: | ||||
5828 | case Intrinsic::arm_ldrex: { | ||||
5829 | Type *ElemTy = Call.getParamElementType(0); | ||||
5830 | Check(ElemTy, "Intrinsic requires elementtype attribute on first argument.",do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
5831 | &Call)do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false); | ||||
5832 | break; | ||||
5833 | } | ||||
5834 | case Intrinsic::aarch64_stlxr: | ||||
5835 | case Intrinsic::aarch64_stxr: | ||||
5836 | case Intrinsic::arm_stlex: | ||||
5837 | case Intrinsic::arm_strex: { | ||||
5838 | Type *ElemTy = Call.getAttributes().getParamElementType(1); | ||||
5839 | Check(ElemTy,do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on second argument." , &Call); return; } } while (false) | ||||
5840 | "Intrinsic requires elementtype attribute on second argument.",do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on second argument." , &Call); return; } } while (false) | ||||
5841 | &Call)do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on second argument." , &Call); return; } } while (false); | ||||
5842 | break; | ||||
5843 | } | ||||
5844 | case Intrinsic::aarch64_prefetch: { | ||||
5845 | Check(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("write argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false) | ||||
5846 | "write argument to llvm.aarch64.prefetch must be 0 or 1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("write argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false); | ||||
5847 | Check(cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4,do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("target argument to llvm.aarch64.prefetch must be 0-3" , Call); return; } } while (false) | ||||
5848 | "target argument to llvm.aarch64.prefetch must be 0-3", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("target argument to llvm.aarch64.prefetch must be 0-3" , Call); return; } } while (false); | ||||
5849 | Check(cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("stream argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false) | ||||
5850 | "stream argument to llvm.aarch64.prefetch must be 0 or 1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("stream argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false); | ||||
5851 | Check(cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(4))-> getZExtValue() < 2)) { CheckFailed("isdata argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false) | ||||
5852 | "isdata argument to llvm.aarch64.prefetch must be 0 or 1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(4))-> getZExtValue() < 2)) { CheckFailed("isdata argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false); | ||||
5853 | break; | ||||
5854 | } | ||||
5855 | case Intrinsic::callbr_landingpad: { | ||||
5856 | const auto *CBR = dyn_cast<CallBrInst>(Call.getOperand(0)); | ||||
5857 | Check(CBR, "intrinstic requires callbr operand", &Call)do { if (!(CBR)) { CheckFailed("intrinstic requires callbr operand" , &Call); return; } } while (false); | ||||
5858 | if (!CBR) | ||||
5859 | break; | ||||
5860 | |||||
5861 | const BasicBlock *LandingPadBB = Call.getParent(); | ||||
5862 | const BasicBlock *PredBB = LandingPadBB->getUniquePredecessor(); | ||||
5863 | if (!PredBB) { | ||||
5864 | CheckFailed("Intrinsic in block must have 1 unique predecessor", &Call); | ||||
5865 | break; | ||||
5866 | } | ||||
5867 | if (!isa<CallBrInst>(PredBB->getTerminator())) { | ||||
5868 | CheckFailed("Intrinsic must have corresponding callbr in predecessor", | ||||
5869 | &Call); | ||||
5870 | break; | ||||
5871 | } | ||||
5872 | Check(llvm::any_of(CBR->getIndirectDests(),do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
5873 | [LandingPadBB](const BasicBlock *IndDest) {do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
5874 | return IndDest == LandingPadBB;do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
5875 | }),do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
5876 | "Intrinsic's corresponding callbr must have intrinsic's parent basic "do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
5877 | "block in indirect destination list",do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
5878 | &Call)do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false); | ||||
5879 | const Instruction &First = *LandingPadBB->begin(); | ||||
5880 | Check(&First == &Call, "No other instructions may proceed intrinsic",do { if (!(&First == &Call)) { CheckFailed("No other instructions may proceed intrinsic" , &Call); return; } } while (false) | ||||
5881 | &Call)do { if (!(&First == &Call)) { CheckFailed("No other instructions may proceed intrinsic" , &Call); return; } } while (false); | ||||
5882 | break; | ||||
5883 | } | ||||
5884 | }; | ||||
5885 | |||||
5886 | // Verify that there aren't any unmediated control transfers between funclets. | ||||
5887 | if (IntrinsicInst::mayLowerToFunctionCall(ID)) { | ||||
5888 | Function *F = Call.getParent()->getParent(); | ||||
5889 | if (F->hasPersonalityFn() && | ||||
5890 | isScopedEHPersonality(classifyEHPersonality(F->getPersonalityFn()))) { | ||||
5891 | // Run EH funclet coloring on-demand and cache results for other intrinsic | ||||
5892 | // calls in this function | ||||
5893 | if (BlockEHFuncletColors.empty()) | ||||
5894 | BlockEHFuncletColors = colorEHFunclets(*F); | ||||
5895 | |||||
5896 | // Check for catch-/cleanup-pad in first funclet block | ||||
5897 | bool InEHFunclet = false; | ||||
5898 | BasicBlock *CallBB = Call.getParent(); | ||||
5899 | const ColorVector &CV = BlockEHFuncletColors.find(CallBB)->second; | ||||
5900 | assert(CV.size() > 0 && "Uncolored block")(static_cast <bool> (CV.size() > 0 && "Uncolored block" ) ? void (0) : __assert_fail ("CV.size() > 0 && \"Uncolored block\"" , "llvm/lib/IR/Verifier.cpp", 5900, __extension__ __PRETTY_FUNCTION__ )); | ||||
5901 | for (BasicBlock *ColorFirstBB : CV) | ||||
5902 | if (dyn_cast_or_null<FuncletPadInst>(ColorFirstBB->getFirstNonPHI())) | ||||
5903 | InEHFunclet = true; | ||||
5904 | |||||
5905 | // Check for funclet operand bundle | ||||
5906 | bool HasToken = false; | ||||
5907 | for (unsigned I = 0, E = Call.getNumOperandBundles(); I != E; ++I) | ||||
5908 | if (Call.getOperandBundleAt(I).getTagID() == LLVMContext::OB_funclet) | ||||
5909 | HasToken = true; | ||||
5910 | |||||
5911 | // This would cause silent code truncation in WinEHPrepare | ||||
5912 | if (InEHFunclet) | ||||
5913 | Check(HasToken, "Missing funclet token on intrinsic call", &Call)do { if (!(HasToken)) { CheckFailed("Missing funclet token on intrinsic call" , &Call); return; } } while (false); | ||||
5914 | } | ||||
5915 | } | ||||
5916 | } | ||||
5917 | |||||
5918 | /// Carefully grab the subprogram from a local scope. | ||||
5919 | /// | ||||
5920 | /// This carefully grabs the subprogram from a local scope, avoiding the | ||||
5921 | /// built-in assertions that would typically fire. | ||||
5922 | static DISubprogram *getSubprogram(Metadata *LocalScope) { | ||||
5923 | if (!LocalScope) | ||||
5924 | return nullptr; | ||||
5925 | |||||
5926 | if (auto *SP = dyn_cast<DISubprogram>(LocalScope)) | ||||
5927 | return SP; | ||||
5928 | |||||
5929 | if (auto *LB = dyn_cast<DILexicalBlockBase>(LocalScope)) | ||||
5930 | return getSubprogram(LB->getRawScope()); | ||||
5931 | |||||
5932 | // Just return null; broken scope chains are checked elsewhere. | ||||
5933 | assert(!isa<DILocalScope>(LocalScope) && "Unknown type of local scope")(static_cast <bool> (!isa<DILocalScope>(LocalScope ) && "Unknown type of local scope") ? void (0) : __assert_fail ("!isa<DILocalScope>(LocalScope) && \"Unknown type of local scope\"" , "llvm/lib/IR/Verifier.cpp", 5933, __extension__ __PRETTY_FUNCTION__ )); | ||||
5934 | return nullptr; | ||||
5935 | } | ||||
5936 | |||||
5937 | void Verifier::visitVPIntrinsic(VPIntrinsic &VPI) { | ||||
5938 | if (auto *VPCast = dyn_cast<VPCastIntrinsic>(&VPI)) { | ||||
5939 | auto *RetTy = cast<VectorType>(VPCast->getType()); | ||||
5940 | auto *ValTy = cast<VectorType>(VPCast->getOperand(0)->getType()); | ||||
5941 | Check(RetTy->getElementCount() == ValTy->getElementCount(),do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false) | ||||
5942 | "VP cast intrinsic first argument and result vector lengths must be "do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false) | ||||
5943 | "equal",do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false) | ||||
5944 | *VPCast)do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false); | ||||
5945 | |||||
5946 | switch (VPCast->getIntrinsicID()) { | ||||
5947 | default: | ||||
5948 | llvm_unreachable("Unknown VP cast intrinsic")::llvm::llvm_unreachable_internal("Unknown VP cast intrinsic" , "llvm/lib/IR/Verifier.cpp", 5948); | ||||
5949 | case Intrinsic::vp_trunc: | ||||
5950 | Check(RetTy->isIntOrIntVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false) | ||||
5951 | "llvm.vp.trunc intrinsic first argument and result element type "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false) | ||||
5952 | "must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false) | ||||
5953 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false); | ||||
5954 | Check(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
5955 | "llvm.vp.trunc intrinsic the bit size of first argument must be "do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
5956 | "larger than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
5957 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false); | ||||
5958 | break; | ||||
5959 | case Intrinsic::vp_zext: | ||||
5960 | case Intrinsic::vp_sext: | ||||
5961 | Check(RetTy->isIntOrIntVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false) | ||||
5962 | "llvm.vp.zext or llvm.vp.sext intrinsic first argument and result "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false) | ||||
5963 | "element type must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false) | ||||
5964 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false); | ||||
5965 | Check(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false) | ||||
5966 | "llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first "do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false) | ||||
5967 | "argument must be smaller than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false) | ||||
5968 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false); | ||||
5969 | break; | ||||
5970 | case Intrinsic::vp_fptoui: | ||||
5971 | case Intrinsic::vp_fptosi: | ||||
5972 | Check(do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
5973 | RetTy->isIntOrIntVectorTy() && ValTy->isFPOrFPVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
5974 | "llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
5975 | "type must be floating-point and result element type must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
5976 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false); | ||||
5977 | break; | ||||
5978 | case Intrinsic::vp_uitofp: | ||||
5979 | case Intrinsic::vp_sitofp: | ||||
5980 | Check(do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
5981 | RetTy->isFPOrFPVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
5982 | "llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element "do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
5983 | "type must be integer and result element type must be floating-point",do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
5984 | *VPCast)do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false); | ||||
5985 | break; | ||||
5986 | case Intrinsic::vp_fptrunc: | ||||
5987 | Check(RetTy->isFPOrFPVectorTy() && ValTy->isFPOrFPVectorTy(),do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
5988 | "llvm.vp.fptrunc intrinsic first argument and result element type "do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
5989 | "must be floating-point",do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
5990 | *VPCast)do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ); | ||||
5991 | Check(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
5992 | "llvm.vp.fptrunc intrinsic the bit size of first argument must be "do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
5993 | "larger than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
5994 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false); | ||||
5995 | break; | ||||
5996 | case Intrinsic::vp_fpext: | ||||
5997 | Check(RetTy->isFPOrFPVectorTy() && ValTy->isFPOrFPVectorTy(),do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
5998 | "llvm.vp.fpext intrinsic first argument and result element type "do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
5999 | "must be floating-point",do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
6000 | *VPCast)do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ); | ||||
6001 | Check(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
6002 | "llvm.vp.fpext intrinsic the bit size of first argument must be "do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
6003 | "smaller than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
6004 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false); | ||||
6005 | break; | ||||
6006 | case Intrinsic::vp_ptrtoint: | ||||
6007 | Check(RetTy->isIntOrIntVectorTy() && ValTy->isPtrOrPtrVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false) | ||||
6008 | "llvm.vp.ptrtoint intrinsic first argument element type must be "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false) | ||||
6009 | "pointer and result element type must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false) | ||||
6010 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false); | ||||
6011 | break; | ||||
6012 | case Intrinsic::vp_inttoptr: | ||||
6013 | Check(RetTy->isPtrOrPtrVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false) | ||||
6014 | "llvm.vp.inttoptr intrinsic first argument element type must be "do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false) | ||||
6015 | "integer and result element type must be pointer",do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false) | ||||
6016 | *VPCast)do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false); | ||||
6017 | break; | ||||
6018 | } | ||||
6019 | } | ||||
6020 | if (VPI.getIntrinsicID() == Intrinsic::vp_fcmp) { | ||||
6021 | auto Pred = cast<VPCmpIntrinsic>(&VPI)->getPredicate(); | ||||
6022 | Check(CmpInst::isFPPredicate(Pred),do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for VP FP comparison intrinsic" , &VPI); return; } } while (false) | ||||
6023 | "invalid predicate for VP FP comparison intrinsic", &VPI)do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for VP FP comparison intrinsic" , &VPI); return; } } while (false); | ||||
6024 | } | ||||
6025 | if (VPI.getIntrinsicID() == Intrinsic::vp_icmp) { | ||||
6026 | auto Pred = cast<VPCmpIntrinsic>(&VPI)->getPredicate(); | ||||
6027 | Check(CmpInst::isIntPredicate(Pred),do { if (!(CmpInst::isIntPredicate(Pred))) { CheckFailed("invalid predicate for VP integer comparison intrinsic" , &VPI); return; } } while (false) | ||||
6028 | "invalid predicate for VP integer comparison intrinsic", &VPI)do { if (!(CmpInst::isIntPredicate(Pred))) { CheckFailed("invalid predicate for VP integer comparison intrinsic" , &VPI); return; } } while (false); | ||||
6029 | } | ||||
6030 | } | ||||
6031 | |||||
6032 | void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { | ||||
6033 | unsigned NumOperands; | ||||
6034 | bool HasRoundingMD; | ||||
6035 | switch (FPI.getIntrinsicID()) { | ||||
6036 | #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ | ||||
6037 | case Intrinsic::INTRINSIC: \ | ||||
6038 | NumOperands = NARG; \ | ||||
6039 | HasRoundingMD = ROUND_MODE; \ | ||||
6040 | break; | ||||
6041 | #include "llvm/IR/ConstrainedOps.def" | ||||
6042 | default: | ||||
6043 | llvm_unreachable("Invalid constrained FP intrinsic!")::llvm::llvm_unreachable_internal("Invalid constrained FP intrinsic!" , "llvm/lib/IR/Verifier.cpp", 6043); | ||||
6044 | } | ||||
6045 | NumOperands += (1 + HasRoundingMD); | ||||
6046 | // Compare intrinsics carry an extra predicate metadata operand. | ||||
6047 | if (isa<ConstrainedFPCmpIntrinsic>(FPI)) | ||||
6048 | NumOperands += 1; | ||||
6049 | Check((FPI.arg_size() == NumOperands),do { if (!((FPI.arg_size() == NumOperands))) { CheckFailed("invalid arguments for constrained FP intrinsic" , &FPI); return; } } while (false) | ||||
6050 | "invalid arguments for constrained FP intrinsic", &FPI)do { if (!((FPI.arg_size() == NumOperands))) { CheckFailed("invalid arguments for constrained FP intrinsic" , &FPI); return; } } while (false); | ||||
6051 | |||||
6052 | switch (FPI.getIntrinsicID()) { | ||||
6053 | case Intrinsic::experimental_constrained_lrint: | ||||
6054 | case Intrinsic::experimental_constrained_llrint: { | ||||
6055 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
6056 | Type *ResultTy = FPI.getType(); | ||||
6057 | Check(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
6058 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
6059 | } | ||||
6060 | break; | ||||
6061 | |||||
6062 | case Intrinsic::experimental_constrained_lround: | ||||
6063 | case Intrinsic::experimental_constrained_llround: { | ||||
6064 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
6065 | Type *ResultTy = FPI.getType(); | ||||
6066 | Check(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
6067 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
6068 | break; | ||||
6069 | } | ||||
6070 | |||||
6071 | case Intrinsic::experimental_constrained_fcmp: | ||||
6072 | case Intrinsic::experimental_constrained_fcmps: { | ||||
6073 | auto Pred = cast<ConstrainedFPCmpIntrinsic>(&FPI)->getPredicate(); | ||||
6074 | Check(CmpInst::isFPPredicate(Pred),do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false) | ||||
6075 | "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); | ||||
6076 | break; | ||||
6077 | } | ||||
6078 | |||||
6079 | case Intrinsic::experimental_constrained_fptosi: | ||||
6080 | case Intrinsic::experimental_constrained_fptoui: { | ||||
6081 | Value *Operand = FPI.getArgOperand(0); | ||||
6082 | ElementCount SrcEC; | ||||
6083 | Check(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false) | ||||
6084 | "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); | ||||
6085 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
6086 | SrcEC = cast<VectorType>(OperandT)->getElementCount(); | ||||
6087 | } | ||||
6088 | |||||
6089 | Operand = &FPI; | ||||
6090 | Check(SrcEC.isNonZero() == Operand->getType()->isVectorTy(),do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
6091 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
6092 | Check(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false) | ||||
6093 | "Intrinsic result must be an integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false); | ||||
6094 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
6095 | Check(SrcEC == cast<VectorType>(OperandT)->getElementCount(),do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
6096 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
6097 | &FPI)do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
6098 | } | ||||
6099 | } | ||||
6100 | break; | ||||
6101 | |||||
6102 | case Intrinsic::experimental_constrained_sitofp: | ||||
6103 | case Intrinsic::experimental_constrained_uitofp: { | ||||
6104 | Value *Operand = FPI.getArgOperand(0); | ||||
6105 | ElementCount SrcEC; | ||||
6106 | Check(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false) | ||||
6107 | "Intrinsic first argument must be integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false); | ||||
6108 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
6109 | SrcEC = cast<VectorType>(OperandT)->getElementCount(); | ||||
6110 | } | ||||
6111 | |||||
6112 | Operand = &FPI; | ||||
6113 | Check(SrcEC.isNonZero() == Operand->getType()->isVectorTy(),do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
6114 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
6115 | Check(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false) | ||||
6116 | "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); | ||||
6117 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
6118 | Check(SrcEC == cast<VectorType>(OperandT)->getElementCount(),do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
6119 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
6120 | &FPI)do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
6121 | } | ||||
6122 | } break; | ||||
6123 | |||||
6124 | case Intrinsic::experimental_constrained_fptrunc: | ||||
6125 | case Intrinsic::experimental_constrained_fpext: { | ||||
6126 | Value *Operand = FPI.getArgOperand(0); | ||||
6127 | Type *OperandTy = Operand->getType(); | ||||
6128 | Value *Result = &FPI; | ||||
6129 | Type *ResultTy = Result->getType(); | ||||
6130 | Check(OperandTy->isFPOrFPVectorTy(),do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false) | ||||
6131 | "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); | ||||
6132 | Check(ResultTy->isFPOrFPVectorTy(),do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false) | ||||
6133 | "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); | ||||
6134 | Check(OperandTy->isVectorTy() == ResultTy->isVectorTy(),do { if (!(OperandTy->isVectorTy() == ResultTy->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
6135 | "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); | ||||
6136 | if (OperandTy->isVectorTy()) { | ||||
6137 | Check(cast<VectorType>(OperandTy)->getElementCount() ==do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
6138 | cast<VectorType>(ResultTy)->getElementCount(),do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
6139 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
6140 | &FPI)do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
6141 | } | ||||
6142 | if (FPI.getIntrinsicID() == Intrinsic::experimental_constrained_fptrunc) { | ||||
6143 | Check(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) | ||||
6144 | "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) | ||||
6145 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false); | ||||
6146 | } else { | ||||
6147 | Check(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) | ||||
6148 | "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) | ||||
6149 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false); | ||||
6150 | } | ||||
6151 | } | ||||
6152 | break; | ||||
6153 | |||||
6154 | default: | ||||
6155 | break; | ||||
6156 | } | ||||
6157 | |||||
6158 | // If a non-metadata argument is passed in a metadata slot then the | ||||
6159 | // error will be caught earlier when the incorrect argument doesn't | ||||
6160 | // match the specification in the intrinsic call table. Thus, no | ||||
6161 | // argument type check is needed here. | ||||
6162 | |||||
6163 | Check(FPI.getExceptionBehavior().has_value(),do { if (!(FPI.getExceptionBehavior().has_value())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false) | ||||
6164 | "invalid exception behavior argument", &FPI)do { if (!(FPI.getExceptionBehavior().has_value())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false); | ||||
6165 | if (HasRoundingMD) { | ||||
6166 | Check(FPI.getRoundingMode().has_value(), "invalid rounding mode argument",do { if (!(FPI.getRoundingMode().has_value())) { CheckFailed( "invalid rounding mode argument", &FPI); return; } } while (false) | ||||
6167 | &FPI)do { if (!(FPI.getRoundingMode().has_value())) { CheckFailed( "invalid rounding mode argument", &FPI); return; } } while (false); | ||||
6168 | } | ||||
6169 | } | ||||
6170 | |||||
6171 | void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { | ||||
6172 | auto *MD = DII.getRawLocation(); | ||||
6173 | CheckDI(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) | ||||
6174 | (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) | ||||
6175 | "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); | ||||
6176 | CheckDI(isa<DILocalVariable>(DII.getRawVariable()),do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
6177 | "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) | ||||
6178 | DII.getRawVariable())do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false); | ||||
6179 | CheckDI(isa<DIExpression>(DII.getRawExpression()),do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
6180 | "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 ) | ||||
6181 | DII.getRawExpression())do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ); | ||||
6182 | |||||
6183 | if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&DII)) { | ||||
6184 | CheckDI(isa<DIAssignID>(DAI->getRawAssignID()),do { if (!(isa<DIAssignID>(DAI->getRawAssignID()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic DIAssignID" , &DII, DAI->getRawAssignID()); return; } } while (false ) | ||||
6185 | "invalid llvm.dbg.assign intrinsic DIAssignID", &DII,do { if (!(isa<DIAssignID>(DAI->getRawAssignID()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic DIAssignID" , &DII, DAI->getRawAssignID()); return; } } while (false ) | ||||
6186 | DAI->getRawAssignID())do { if (!(isa<DIAssignID>(DAI->getRawAssignID()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic DIAssignID" , &DII, DAI->getRawAssignID()); return; } } while (false ); | ||||
6187 | const auto *RawAddr = DAI->getRawAddress(); | ||||
6188 | CheckDI(do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
6189 | isa<ValueAsMetadata>(RawAddr) ||do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
6190 | (isa<MDNode>(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands()),do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
6191 | "invalid llvm.dbg.assign intrinsic address", &DII,do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
6192 | DAI->getRawAddress())do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ); | ||||
6193 | CheckDI(isa<DIExpression>(DAI->getRawAddressExpression()),do { if (!(isa<DIExpression>(DAI->getRawAddressExpression ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address expression" , &DII, DAI->getRawAddressExpression()); return; } } while (false) | ||||
6194 | "invalid llvm.dbg.assign intrinsic address expression", &DII,do { if (!(isa<DIExpression>(DAI->getRawAddressExpression ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address expression" , &DII, DAI->getRawAddressExpression()); return; } } while (false) | ||||
6195 | DAI->getRawAddressExpression())do { if (!(isa<DIExpression>(DAI->getRawAddressExpression ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address expression" , &DII, DAI->getRawAddressExpression()); return; } } while (false); | ||||
6196 | // All of the linked instructions should be in the same function as DII. | ||||
6197 | for (Instruction *I : at::getAssignmentInsts(DAI)) | ||||
6198 | CheckDI(DAI->getFunction() == I->getFunction(),do { if (!(DAI->getFunction() == I->getFunction())) { DebugInfoCheckFailed ("inst not in same function as dbg.assign", I, DAI); return; } } while (false) | ||||
6199 | "inst not in same function as dbg.assign", I, DAI)do { if (!(DAI->getFunction() == I->getFunction())) { DebugInfoCheckFailed ("inst not in same function as dbg.assign", I, DAI); return; } } while (false); | ||||
6200 | } | ||||
6201 | |||||
6202 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
6203 | if (MDNode *N = DII.getDebugLoc().getAsMDNode()) | ||||
6204 | if (!isa<DILocation>(N)) | ||||
6205 | return; | ||||
6206 | |||||
6207 | BasicBlock *BB = DII.getParent(); | ||||
6208 | Function *F = BB ? BB->getParent() : nullptr; | ||||
6209 | |||||
6210 | // The scopes for variables and !dbg attachments must agree. | ||||
6211 | DILocalVariable *Var = DII.getVariable(); | ||||
6212 | DILocation *Loc = DII.getDebugLoc(); | ||||
6213 | CheckDI(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) | ||||
6214 | &DII, BB, F)do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false); | ||||
6215 | |||||
6216 | DISubprogram *VarSP = getSubprogram(Var->getRawScope()); | ||||
6217 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
6218 | if (!VarSP || !LocSP) | ||||
6219 | return; // Broken scope chains are checked elsewhere. | ||||
6220 | |||||
6221 | CheckDI(VarSP == LocSP,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) | ||||
6222 | "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) | ||||
6223 | " 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) | ||||
6224 | &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) | ||||
6225 | 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); | ||||
6226 | |||||
6227 | // This check is redundant with one in visitLocalVariable(). | ||||
6228 | CheckDI(isType(Var->getRawType()), "invalid type ref", Var,do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false) | ||||
6229 | Var->getRawType())do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false); | ||||
6230 | verifyFnArgs(DII); | ||||
6231 | } | ||||
6232 | |||||
6233 | void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) { | ||||
6234 | CheckDI(isa<DILabel>(DLI.getRawLabel()),do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
6235 | "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) | ||||
6236 | DLI.getRawLabel())do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false); | ||||
6237 | |||||
6238 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
6239 | if (MDNode *N = DLI.getDebugLoc().getAsMDNode()) | ||||
6240 | if (!isa<DILocation>(N)) | ||||
6241 | return; | ||||
6242 | |||||
6243 | BasicBlock *BB = DLI.getParent(); | ||||
6244 | Function *F = BB ? BB->getParent() : nullptr; | ||||
6245 | |||||
6246 | // The scopes for variables and !dbg attachments must agree. | ||||
6247 | DILabel *Label = DLI.getLabel(); | ||||
6248 | DILocation *Loc = DLI.getDebugLoc(); | ||||
6249 | Check(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment", &DLI,do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false) | ||||
6250 | BB, F)do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false); | ||||
6251 | |||||
6252 | DISubprogram *LabelSP = getSubprogram(Label->getRawScope()); | ||||
6253 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
6254 | if (!LabelSP || !LocSP) | ||||
6255 | return; | ||||
6256 | |||||
6257 | CheckDI(LabelSP == LocSP,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) | ||||
6258 | "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) | ||||
6259 | " 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) | ||||
6260 | &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) | ||||
6261 | 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); | ||||
6262 | } | ||||
6263 | |||||
6264 | void Verifier::verifyFragmentExpression(const DbgVariableIntrinsic &I) { | ||||
6265 | DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); | ||||
6266 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
6267 | |||||
6268 | // We don't know whether this intrinsic verified correctly. | ||||
6269 | if (!V || !E || !E->isValid()) | ||||
6270 | return; | ||||
6271 | |||||
6272 | // Nothing to do if this isn't a DW_OP_LLVM_fragment expression. | ||||
6273 | auto Fragment = E->getFragmentInfo(); | ||||
6274 | if (!Fragment) | ||||
6275 | return; | ||||
6276 | |||||
6277 | // The frontend helps out GDB by emitting the members of local anonymous | ||||
6278 | // unions as artificial local variables with shared storage. When SROA splits | ||||
6279 | // the storage for artificial local variables that are smaller than the entire | ||||
6280 | // union, the overhang piece will be outside of the allotted space for the | ||||
6281 | // variable and this check fails. | ||||
6282 | // FIXME: Remove this check as soon as clang stops doing this; it hides bugs. | ||||
6283 | if (V->isArtificial()) | ||||
6284 | return; | ||||
6285 | |||||
6286 | verifyFragmentExpression(*V, *Fragment, &I); | ||||
6287 | } | ||||
6288 | |||||
6289 | template <typename ValueOrMetadata> | ||||
6290 | void Verifier::verifyFragmentExpression(const DIVariable &V, | ||||
6291 | DIExpression::FragmentInfo Fragment, | ||||
6292 | ValueOrMetadata *Desc) { | ||||
6293 | // If there's no size, the type is broken, but that should be checked | ||||
6294 | // elsewhere. | ||||
6295 | auto VarSize = V.getSizeInBits(); | ||||
6296 | if (!VarSize) | ||||
6297 | return; | ||||
6298 | |||||
6299 | unsigned FragSize = Fragment.SizeInBits; | ||||
6300 | unsigned FragOffset = Fragment.OffsetInBits; | ||||
6301 | CheckDI(FragSize + FragOffset <= *VarSize,do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false) | ||||
6302 | "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); | ||||
6303 | CheckDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V)do { if (!(FragSize != *VarSize)) { DebugInfoCheckFailed("fragment covers entire variable" , Desc, &V); return; } } while (false); | ||||
6304 | } | ||||
6305 | |||||
6306 | void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) { | ||||
6307 | // This function does not take the scope of noninlined function arguments into | ||||
6308 | // account. Don't run it if current function is nodebug, because it may | ||||
6309 | // contain inlined debug intrinsics. | ||||
6310 | if (!HasDebugInfo) | ||||
6311 | return; | ||||
6312 | |||||
6313 | // For performance reasons only check non-inlined ones. | ||||
6314 | if (I.getDebugLoc()->getInlinedAt()) | ||||
6315 | return; | ||||
6316 | |||||
6317 | DILocalVariable *Var = I.getVariable(); | ||||
6318 | CheckDI(Var, "dbg intrinsic without variable")do { if (!(Var)) { DebugInfoCheckFailed("dbg intrinsic without variable" ); return; } } while (false); | ||||
6319 | |||||
6320 | unsigned ArgNo = Var->getArg(); | ||||
6321 | if (!ArgNo) | ||||
6322 | return; | ||||
6323 | |||||
6324 | // Verify there are no duplicate function argument debug info entries. | ||||
6325 | // These will cause hard-to-debug assertions in the DWARF backend. | ||||
6326 | if (DebugFnArgs.size() < ArgNo) | ||||
6327 | DebugFnArgs.resize(ArgNo, nullptr); | ||||
6328 | |||||
6329 | auto *Prev = DebugFnArgs[ArgNo - 1]; | ||||
6330 | DebugFnArgs[ArgNo - 1] = Var; | ||||
6331 | CheckDI(!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) | ||||
6332 | Prev, Var)do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false); | ||||
6333 | } | ||||
6334 | |||||
6335 | void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) { | ||||
6336 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
6337 | |||||
6338 | // We don't know whether this intrinsic verified correctly. | ||||
6339 | if (!E || !E->isValid()) | ||||
6340 | return; | ||||
6341 | |||||
6342 | CheckDI(!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); | ||||
6343 | } | ||||
6344 | |||||
6345 | void Verifier::verifyCompileUnits() { | ||||
6346 | // When more than one Module is imported into the same context, such as during | ||||
6347 | // an LTO build before linking the modules, ODR type uniquing may cause types | ||||
6348 | // to point to a different CU. This check does not make sense in this case. | ||||
6349 | if (M.getContext().isODRUniquingDebugTypes()) | ||||
6350 | return; | ||||
6351 | auto *CUs = M.getNamedMetadata("llvm.dbg.cu"); | ||||
6352 | SmallPtrSet<const Metadata *, 2> Listed; | ||||
6353 | if (CUs) | ||||
6354 | Listed.insert(CUs->op_begin(), CUs->op_end()); | ||||
6355 | for (const auto *CU : CUVisited) | ||||
6356 | CheckDI(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); | ||||
6357 | CUVisited.clear(); | ||||
6358 | } | ||||
6359 | |||||
6360 | void Verifier::verifyDeoptimizeCallingConvs() { | ||||
6361 | if (DeoptimizeDeclarations.empty()) | ||||
6362 | return; | ||||
6363 | |||||
6364 | const Function *First = DeoptimizeDeclarations[0]; | ||||
6365 | for (const auto *F : ArrayRef(DeoptimizeDeclarations).slice(1)) { | ||||
6366 | Check(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) | ||||
6367 | "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) | ||||
6368 | "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) | ||||
6369 | 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); | ||||
6370 | } | ||||
6371 | } | ||||
6372 | |||||
6373 | void Verifier::verifyAttachedCallBundle(const CallBase &Call, | ||||
6374 | const OperandBundleUse &BU) { | ||||
6375 | FunctionType *FTy = Call.getFunctionType(); | ||||
6376 | |||||
6377 | Check((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) | ||||
6378 | (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) | ||||
6379 | "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) | ||||
6380 | "function returning a pointer or a non-returning function that has 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) | ||||
6381 | "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) | ||||
6382 | 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); | ||||
6383 | |||||
6384 | Check(BU.Inputs.size() == 1 && isa<Function>(BU.Inputs.front()),do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false) | ||||
6385 | "operand bundle \"clang.arc.attachedcall\" requires one function as "do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false) | ||||
6386 | "an argument",do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false) | ||||
6387 | Call)do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false); | ||||
6388 | |||||
6389 | auto *Fn = cast<Function>(BU.Inputs.front()); | ||||
6390 | Intrinsic::ID IID = Fn->getIntrinsicID(); | ||||
6391 | |||||
6392 | if (IID) { | ||||
6393 | Check((IID == Intrinsic::objc_retainAutoreleasedReturnValue ||do { if (!((IID == Intrinsic::objc_retainAutoreleasedReturnValue || IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue ))) { CheckFailed("invalid function argument", Call); return; } } while (false) | ||||
6394 | IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue),do { if (!((IID == Intrinsic::objc_retainAutoreleasedReturnValue || IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue ))) { CheckFailed("invalid function argument", Call); return; } } while (false) | ||||
6395 | "invalid function argument", Call)do { if (!((IID == Intrinsic::objc_retainAutoreleasedReturnValue || IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue ))) { CheckFailed("invalid function argument", Call); return; } } while (false); | ||||
6396 | } else { | ||||
6397 | StringRef FnName = Fn->getName(); | ||||
6398 | Check((FnName == "objc_retainAutoreleasedReturnValue" ||do { if (!((FnName == "objc_retainAutoreleasedReturnValue" || FnName == "objc_unsafeClaimAutoreleasedReturnValue"))) { CheckFailed ("invalid function argument", Call); return; } } while (false ) | ||||
6399 | FnName == "objc_unsafeClaimAutoreleasedReturnValue"),do { if (!((FnName == "objc_retainAutoreleasedReturnValue" || FnName == "objc_unsafeClaimAutoreleasedReturnValue"))) { CheckFailed ("invalid function argument", Call); return; } } while (false ) | ||||
6400 | "invalid function argument", Call)do { if (!((FnName == "objc_retainAutoreleasedReturnValue" || FnName == "objc_unsafeClaimAutoreleasedReturnValue"))) { CheckFailed ("invalid function argument", Call); return; } } while (false ); | ||||
6401 | } | ||||
6402 | } | ||||
6403 | |||||
6404 | void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) { | ||||
6405 | bool HasSource = F.getSource().has_value(); | ||||
6406 | if (!HasSourceDebugInfo.count(&U)) | ||||
6407 | HasSourceDebugInfo[&U] = HasSource; | ||||
6408 | CheckDI(HasSource == HasSourceDebugInfo[&U],do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ) | ||||
6409 | "inconsistent use of embedded source")do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ); | ||||
6410 | } | ||||
6411 | |||||
6412 | void Verifier::verifyNoAliasScopeDecl() { | ||||
6413 | if (NoAliasScopeDecls.empty()) | ||||
6414 | return; | ||||
6415 | |||||
6416 | // only a single scope must be declared at a time. | ||||
6417 | for (auto *II : NoAliasScopeDecls) { | ||||
6418 | assert(II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl &&(static_cast <bool> (II->getIntrinsicID() == Intrinsic ::experimental_noalias_scope_decl && "Not a llvm.experimental.noalias.scope.decl ?" ) ? void (0) : __assert_fail ("II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl && \"Not a llvm.experimental.noalias.scope.decl ?\"" , "llvm/lib/IR/Verifier.cpp", 6419, __extension__ __PRETTY_FUNCTION__ )) | ||||
6419 | "Not a llvm.experimental.noalias.scope.decl ?")(static_cast <bool> (II->getIntrinsicID() == Intrinsic ::experimental_noalias_scope_decl && "Not a llvm.experimental.noalias.scope.decl ?" ) ? void (0) : __assert_fail ("II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl && \"Not a llvm.experimental.noalias.scope.decl ?\"" , "llvm/lib/IR/Verifier.cpp", 6419, __extension__ __PRETTY_FUNCTION__ )); | ||||
6420 | const auto *ScopeListMV = dyn_cast<MetadataAsValue>( | ||||
6421 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
6422 | Check(ScopeListMV != nullptr,do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
6423 | "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) | ||||
6424 | "argument",do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
6425 | II)do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false); | ||||
6426 | |||||
6427 | const auto *ScopeListMD = dyn_cast<MDNode>(ScopeListMV->getMetadata()); | ||||
6428 | Check(ScopeListMD != nullptr, "!id.scope.list must point to an MDNode", II)do { if (!(ScopeListMD != nullptr)) { CheckFailed("!id.scope.list must point to an MDNode" , II); return; } } while (false); | ||||
6429 | Check(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) | ||||
6430 | "!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); | ||||
6431 | visitAliasScopeListMetadata(ScopeListMD); | ||||
6432 | } | ||||
6433 | |||||
6434 | // Only check the domination rule when requested. Once all passes have been | ||||
6435 | // adapted this option can go away. | ||||
6436 | if (!VerifyNoAliasScopeDomination) | ||||
6437 | return; | ||||
6438 | |||||
6439 | // Now sort the intrinsics based on the scope MDNode so that declarations of | ||||
6440 | // the same scopes are next to each other. | ||||
6441 | auto GetScope = [](IntrinsicInst *II) { | ||||
6442 | const auto *ScopeListMV = cast<MetadataAsValue>( | ||||
6443 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
6444 | return &cast<MDNode>(ScopeListMV->getMetadata())->getOperand(0); | ||||
6445 | }; | ||||
6446 | |||||
6447 | // We are sorting on MDNode pointers here. For valid input IR this is ok. | ||||
6448 | // TODO: Sort on Metadata ID to avoid non-deterministic error messages. | ||||
6449 | auto Compare = [GetScope](IntrinsicInst *Lhs, IntrinsicInst *Rhs) { | ||||
6450 | return GetScope(Lhs) < GetScope(Rhs); | ||||
6451 | }; | ||||
6452 | |||||
6453 | llvm::sort(NoAliasScopeDecls, Compare); | ||||
6454 | |||||
6455 | // Go over the intrinsics and check that for the same scope, they are not | ||||
6456 | // dominating each other. | ||||
6457 | auto ItCurrent = NoAliasScopeDecls.begin(); | ||||
6458 | while (ItCurrent != NoAliasScopeDecls.end()) { | ||||
6459 | auto CurScope = GetScope(*ItCurrent); | ||||
6460 | auto ItNext = ItCurrent; | ||||
6461 | do { | ||||
6462 | ++ItNext; | ||||
6463 | } while (ItNext != NoAliasScopeDecls.end() && | ||||
6464 | GetScope(*ItNext) == CurScope); | ||||
6465 | |||||
6466 | // [ItCurrent, ItNext) represents the declarations for the same scope. | ||||
6467 | // Ensure they are not dominating each other.. but only if it is not too | ||||
6468 | // expensive. | ||||
6469 | if (ItNext - ItCurrent < 32) | ||||
6470 | for (auto *I : llvm::make_range(ItCurrent, ItNext)) | ||||
6471 | for (auto *J : llvm::make_range(ItCurrent, ItNext)) | ||||
6472 | if (I != J) | ||||
6473 | Check(!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) | ||||
6474 | "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) | ||||
6475 | "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) | ||||
6476 | I)do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false); | ||||
6477 | ItCurrent = ItNext; | ||||
6478 | } | ||||
6479 | } | ||||
6480 | |||||
6481 | //===----------------------------------------------------------------------===// | ||||
6482 | // Implement the public interfaces to this file... | ||||
6483 | //===----------------------------------------------------------------------===// | ||||
6484 | |||||
6485 | bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { | ||||
6486 | Function &F = const_cast<Function &>(f); | ||||
6487 | |||||
6488 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
6489 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true, *f.getParent()); | ||||
6490 | |||||
6491 | // Note that this function's return value is inverted from what you would | ||||
6492 | // expect of a function called "verify". | ||||
6493 | return !V.verify(F); | ||||
6494 | } | ||||
6495 | |||||
6496 | bool llvm::verifyModule(const Module &M, raw_ostream *OS, | ||||
6497 | bool *BrokenDebugInfo) { | ||||
6498 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
6499 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo, M); | ||||
6500 | |||||
6501 | bool Broken = false; | ||||
6502 | for (const Function &F : M) | ||||
6503 | Broken |= !V.verify(F); | ||||
6504 | |||||
6505 | Broken |= !V.verify(); | ||||
6506 | if (BrokenDebugInfo) | ||||
6507 | *BrokenDebugInfo = V.hasBrokenDebugInfo(); | ||||
6508 | // Note that this function's return value is inverted from what you would | ||||
6509 | // expect of a function called "verify". | ||||
6510 | return Broken; | ||||
6511 | } | ||||
6512 | |||||
6513 | namespace { | ||||
6514 | |||||
6515 | struct VerifierLegacyPass : public FunctionPass { | ||||
6516 | static char ID; | ||||
6517 | |||||
6518 | std::unique_ptr<Verifier> V; | ||||
6519 | bool FatalErrors = true; | ||||
6520 | |||||
6521 | VerifierLegacyPass() : FunctionPass(ID) { | ||||
6522 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
6523 | } | ||||
6524 | explicit VerifierLegacyPass(bool FatalErrors) | ||||
6525 | : FunctionPass(ID), | ||||
6526 | FatalErrors(FatalErrors) { | ||||
6527 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
6528 | } | ||||
6529 | |||||
6530 | bool doInitialization(Module &M) override { | ||||
6531 | V = std::make_unique<Verifier>( | ||||
6532 | &dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false, M); | ||||
6533 | return false; | ||||
6534 | } | ||||
6535 | |||||
6536 | bool runOnFunction(Function &F) override { | ||||
6537 | if (!V->verify(F) && FatalErrors) { | ||||
6538 | errs() << "in function " << F.getName() << '\n'; | ||||
6539 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
6540 | } | ||||
6541 | return false; | ||||
6542 | } | ||||
6543 | |||||
6544 | bool doFinalization(Module &M) override { | ||||
6545 | bool HasErrors = false; | ||||
6546 | for (Function &F : M) | ||||
6547 | if (F.isDeclaration()) | ||||
6548 | HasErrors |= !V->verify(F); | ||||
6549 | |||||
6550 | HasErrors |= !V->verify(); | ||||
6551 | if (FatalErrors && (HasErrors || V->hasBrokenDebugInfo())) | ||||
6552 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
6553 | return false; | ||||
6554 | } | ||||
6555 | |||||
6556 | void getAnalysisUsage(AnalysisUsage &AU) const override { | ||||
6557 | AU.setPreservesAll(); | ||||
6558 | } | ||||
6559 | }; | ||||
6560 | |||||
6561 | } // end anonymous namespace | ||||
6562 | |||||
6563 | /// Helper to issue failure from the TBAA verification | ||||
6564 | template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) { | ||||
6565 | if (Diagnostic) | ||||
6566 | return Diagnostic->CheckFailed(Args...); | ||||
6567 | } | ||||
6568 | |||||
6569 | #define CheckTBAA(C, ...)do { if (!(C)) { CheckFailed(...); return false; } } while (false ) \ | ||||
6570 | do { \ | ||||
6571 | if (!(C)) { \ | ||||
6572 | CheckFailed(__VA_ARGS__); \ | ||||
6573 | return false; \ | ||||
6574 | } \ | ||||
6575 | } while (false) | ||||
6576 | |||||
6577 | /// Verify that \p BaseNode can be used as the "base type" in the struct-path | ||||
6578 | /// TBAA scheme. This means \p BaseNode is either a scalar node, or a | ||||
6579 | /// struct-type node describing an aggregate data structure (like a struct). | ||||
6580 | TBAAVerifier::TBAABaseNodeSummary | ||||
6581 | TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode, | ||||
6582 | bool IsNewFormat) { | ||||
6583 | if (BaseNode->getNumOperands() < 2) { | ||||
6584 | CheckFailed("Base nodes must have at least two operands", &I, BaseNode); | ||||
6585 | return {true, ~0u}; | ||||
6586 | } | ||||
6587 | |||||
6588 | auto Itr = TBAABaseNodes.find(BaseNode); | ||||
6589 | if (Itr != TBAABaseNodes.end()) | ||||
6590 | return Itr->second; | ||||
6591 | |||||
6592 | auto Result = verifyTBAABaseNodeImpl(I, BaseNode, IsNewFormat); | ||||
6593 | auto InsertResult = TBAABaseNodes.insert({BaseNode, Result}); | ||||
6594 | (void)InsertResult; | ||||
6595 | assert(InsertResult.second && "We just checked!")(static_cast <bool> (InsertResult.second && "We just checked!" ) ? void (0) : __assert_fail ("InsertResult.second && \"We just checked!\"" , "llvm/lib/IR/Verifier.cpp", 6595, __extension__ __PRETTY_FUNCTION__ )); | ||||
6596 | return Result; | ||||
6597 | } | ||||
6598 | |||||
6599 | TBAAVerifier::TBAABaseNodeSummary | ||||
6600 | TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode, | ||||
6601 | bool IsNewFormat) { | ||||
6602 | const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u}; | ||||
6603 | |||||
6604 | if (BaseNode->getNumOperands() == 2) { | ||||
6605 | // Scalar nodes can only be accessed at offset 0. | ||||
6606 | return isValidScalarTBAANode(BaseNode) | ||||
6607 | ? TBAAVerifier::TBAABaseNodeSummary({false, 0}) | ||||
6608 | : InvalidNode; | ||||
6609 | } | ||||
6610 | |||||
6611 | if (IsNewFormat) { | ||||
6612 | if (BaseNode->getNumOperands() % 3 != 0) { | ||||
6613 | CheckFailed("Access tag nodes must have the number of operands that is a " | ||||
6614 | "multiple of 3!", BaseNode); | ||||
6615 | return InvalidNode; | ||||
6616 | } | ||||
6617 | } else { | ||||
6618 | if (BaseNode->getNumOperands() % 2 != 1) { | ||||
6619 | CheckFailed("Struct tag nodes must have an odd number of operands!", | ||||
6620 | BaseNode); | ||||
6621 | return InvalidNode; | ||||
6622 | } | ||||
6623 | } | ||||
6624 | |||||
6625 | // Check the type size field. | ||||
6626 | if (IsNewFormat) { | ||||
6627 | auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6628 | BaseNode->getOperand(1)); | ||||
6629 | if (!TypeSizeNode) { | ||||
6630 | CheckFailed("Type size nodes must be constants!", &I, BaseNode); | ||||
6631 | return InvalidNode; | ||||
6632 | } | ||||
6633 | } | ||||
6634 | |||||
6635 | // Check the type name field. In the new format it can be anything. | ||||
6636 | if (!IsNewFormat && !isa<MDString>(BaseNode->getOperand(0))) { | ||||
6637 | CheckFailed("Struct tag nodes have a string as their first operand", | ||||
6638 | BaseNode); | ||||
6639 | return InvalidNode; | ||||
6640 | } | ||||
6641 | |||||
6642 | bool Failed = false; | ||||
6643 | |||||
6644 | std::optional<APInt> PrevOffset; | ||||
6645 | unsigned BitWidth = ~0u; | ||||
6646 | |||||
6647 | // We've already checked that BaseNode is not a degenerate root node with one | ||||
6648 | // operand in \c verifyTBAABaseNode, so this loop should run at least once. | ||||
6649 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
6650 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
6651 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
6652 | Idx += NumOpsPerField) { | ||||
6653 | const MDOperand &FieldTy = BaseNode->getOperand(Idx); | ||||
6654 | const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1); | ||||
6655 | if (!isa<MDNode>(FieldTy)) { | ||||
6656 | CheckFailed("Incorrect field entry in struct type node!", &I, BaseNode); | ||||
6657 | Failed = true; | ||||
6658 | continue; | ||||
6659 | } | ||||
6660 | |||||
6661 | auto *OffsetEntryCI = | ||||
6662 | mdconst::dyn_extract_or_null<ConstantInt>(FieldOffset); | ||||
6663 | if (!OffsetEntryCI) { | ||||
6664 | CheckFailed("Offset entries must be constants!", &I, BaseNode); | ||||
6665 | Failed = true; | ||||
6666 | continue; | ||||
6667 | } | ||||
6668 | |||||
6669 | if (BitWidth == ~0u) | ||||
6670 | BitWidth = OffsetEntryCI->getBitWidth(); | ||||
6671 | |||||
6672 | if (OffsetEntryCI->getBitWidth() != BitWidth) { | ||||
6673 | CheckFailed( | ||||
6674 | "Bitwidth between the offsets and struct type entries must match", &I, | ||||
6675 | BaseNode); | ||||
6676 | Failed = true; | ||||
6677 | continue; | ||||
6678 | } | ||||
6679 | |||||
6680 | // NB! As far as I can tell, we generate a non-strictly increasing offset | ||||
6681 | // sequence only from structs that have zero size bit fields. When | ||||
6682 | // recursing into a contained struct in \c getFieldNodeFromTBAABaseNode we | ||||
6683 | // pick the field lexically the latest in struct type metadata node. This | ||||
6684 | // mirrors the actual behavior of the alias analysis implementation. | ||||
6685 | bool IsAscending = | ||||
6686 | !PrevOffset || PrevOffset->ule(OffsetEntryCI->getValue()); | ||||
6687 | |||||
6688 | if (!IsAscending) { | ||||
6689 | CheckFailed("Offsets must be increasing!", &I, BaseNode); | ||||
6690 | Failed = true; | ||||
6691 | } | ||||
6692 | |||||
6693 | PrevOffset = OffsetEntryCI->getValue(); | ||||
6694 | |||||
6695 | if (IsNewFormat) { | ||||
6696 | auto *MemberSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6697 | BaseNode->getOperand(Idx + 2)); | ||||
6698 | if (!MemberSizeNode) { | ||||
6699 | CheckFailed("Member size entries must be constants!", &I, BaseNode); | ||||
6700 | Failed = true; | ||||
6701 | continue; | ||||
6702 | } | ||||
6703 | } | ||||
6704 | } | ||||
6705 | |||||
6706 | return Failed ? InvalidNode | ||||
6707 | : TBAAVerifier::TBAABaseNodeSummary(false, BitWidth); | ||||
6708 | } | ||||
6709 | |||||
6710 | static bool IsRootTBAANode(const MDNode *MD) { | ||||
6711 | return MD->getNumOperands() < 2; | ||||
6712 | } | ||||
6713 | |||||
6714 | static bool IsScalarTBAANodeImpl(const MDNode *MD, | ||||
6715 | SmallPtrSetImpl<const MDNode *> &Visited) { | ||||
6716 | if (MD->getNumOperands() != 2 && MD->getNumOperands() != 3) | ||||
6717 | return false; | ||||
6718 | |||||
6719 | if (!isa<MDString>(MD->getOperand(0))) | ||||
6720 | return false; | ||||
6721 | |||||
6722 | if (MD->getNumOperands() == 3) { | ||||
6723 | auto *Offset = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2)); | ||||
6724 | if (!(Offset && Offset->isZero() && isa<MDString>(MD->getOperand(0)))) | ||||
6725 | return false; | ||||
6726 | } | ||||
6727 | |||||
6728 | auto *Parent = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
6729 | return Parent && Visited.insert(Parent).second && | ||||
6730 | (IsRootTBAANode(Parent) || IsScalarTBAANodeImpl(Parent, Visited)); | ||||
6731 | } | ||||
6732 | |||||
6733 | bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) { | ||||
6734 | auto ResultIt = TBAAScalarNodes.find(MD); | ||||
6735 | if (ResultIt != TBAAScalarNodes.end()) | ||||
6736 | return ResultIt->second; | ||||
6737 | |||||
6738 | SmallPtrSet<const MDNode *, 4> Visited; | ||||
6739 | bool Result = IsScalarTBAANodeImpl(MD, Visited); | ||||
6740 | auto InsertResult = TBAAScalarNodes.insert({MD, Result}); | ||||
6741 | (void)InsertResult; | ||||
6742 | assert(InsertResult.second && "Just checked!")(static_cast <bool> (InsertResult.second && "Just checked!" ) ? void (0) : __assert_fail ("InsertResult.second && \"Just checked!\"" , "llvm/lib/IR/Verifier.cpp", 6742, __extension__ __PRETTY_FUNCTION__ )); | ||||
6743 | |||||
6744 | return Result; | ||||
6745 | } | ||||
6746 | |||||
6747 | /// Returns the field node at the offset \p Offset in \p BaseNode. Update \p | ||||
6748 | /// Offset in place to be the offset within the field node returned. | ||||
6749 | /// | ||||
6750 | /// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode. | ||||
6751 | MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, | ||||
6752 | const MDNode *BaseNode, | ||||
6753 | APInt &Offset, | ||||
6754 | bool IsNewFormat) { | ||||
6755 | assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!")(static_cast <bool> (BaseNode->getNumOperands() >= 2 && "Invalid base node!") ? void (0) : __assert_fail ("BaseNode->getNumOperands() >= 2 && \"Invalid base node!\"" , "llvm/lib/IR/Verifier.cpp", 6755, __extension__ __PRETTY_FUNCTION__ )); | ||||
6756 | |||||
6757 | // Scalar nodes have only one possible "field" -- their parent in the access | ||||
6758 | // hierarchy. Offset must be zero at this point, but our caller is supposed | ||||
6759 | // to check that. | ||||
6760 | if (BaseNode->getNumOperands() == 2) | ||||
6761 | return cast<MDNode>(BaseNode->getOperand(1)); | ||||
6762 | |||||
6763 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
6764 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
6765 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
6766 | Idx += NumOpsPerField) { | ||||
6767 | auto *OffsetEntryCI = | ||||
6768 | mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1)); | ||||
6769 | if (OffsetEntryCI->getValue().ugt(Offset)) { | ||||
6770 | if (Idx == FirstFieldOpNo) { | ||||
6771 | CheckFailed("Could not find TBAA parent in struct type node", &I, | ||||
6772 | BaseNode, &Offset); | ||||
6773 | return nullptr; | ||||
6774 | } | ||||
6775 | |||||
6776 | unsigned PrevIdx = Idx - NumOpsPerField; | ||||
6777 | auto *PrevOffsetEntryCI = | ||||
6778 | mdconst::extract<ConstantInt>(BaseNode->getOperand(PrevIdx + 1)); | ||||
6779 | Offset -= PrevOffsetEntryCI->getValue(); | ||||
6780 | return cast<MDNode>(BaseNode->getOperand(PrevIdx)); | ||||
6781 | } | ||||
6782 | } | ||||
6783 | |||||
6784 | unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField; | ||||
6785 | auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( | ||||
6786 | BaseNode->getOperand(LastIdx + 1)); | ||||
6787 | Offset -= LastOffsetEntryCI->getValue(); | ||||
6788 | return cast<MDNode>(BaseNode->getOperand(LastIdx)); | ||||
6789 | } | ||||
6790 | |||||
6791 | static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { | ||||
6792 | if (!Type || Type->getNumOperands() < 3) | ||||
6793 | return false; | ||||
6794 | |||||
6795 | // In the new format type nodes shall have a reference to the parent type as | ||||
6796 | // its first operand. | ||||
6797 | return isa_and_nonnull<MDNode>(Type->getOperand(0)); | ||||
6798 | } | ||||
6799 | |||||
6800 | bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { | ||||
6801 | CheckTBAA(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) | ||||
6802 | 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) | ||||
6803 | 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) | ||||
6804 | "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); | ||||
6805 | |||||
6806 | bool IsStructPathTBAA = | ||||
6807 | isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; | ||||
6808 | |||||
6809 | CheckTBAA(IsStructPathTBAA,do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
6810 | "Old-style TBAA is no longer allowed, use struct-path TBAA instead",do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
6811 | &I)do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false); | ||||
6812 | |||||
6813 | MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0)); | ||||
6814 | MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
6815 | |||||
6816 | bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); | ||||
6817 | |||||
6818 | if (IsNewFormat) { | ||||
6819 | CheckTBAA(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) | ||||
6820 | "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); | ||||
6821 | } else { | ||||
6822 | CheckTBAA(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) | ||||
6823 | "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); | ||||
6824 | } | ||||
6825 | |||||
6826 | // Check the access size field. | ||||
6827 | if (IsNewFormat) { | ||||
6828 | auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6829 | MD->getOperand(3)); | ||||
6830 | CheckTBAA(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); | ||||
6831 | } | ||||
6832 | |||||
6833 | // Check the immutability flag. | ||||
6834 | unsigned ImmutabilityFlagOpNo = IsNewFormat ? 4 : 3; | ||||
6835 | if (MD->getNumOperands() == ImmutabilityFlagOpNo + 1) { | ||||
6836 | auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
6837 | MD->getOperand(ImmutabilityFlagOpNo)); | ||||
6838 | CheckTBAA(IsImmutableCI,do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
6839 | "Immutability tag on struct tag metadata must be a constant", &I,do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
6840 | MD)do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false); | ||||
6841 | CheckTBAA(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) | ||||
6842 | 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) | ||||
6843 | "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) | ||||
6844 | &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); | ||||
6845 | } | ||||
6846 | |||||
6847 | CheckTBAA(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) | ||||
6848 | "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) | ||||
6849 | "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) | ||||
6850 | &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); | ||||
6851 | |||||
6852 | if (!IsNewFormat) { | ||||
6853 | CheckTBAA(isValidScalarTBAANode(AccessType),do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
6854 | "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) | ||||
6855 | AccessType)do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false); | ||||
6856 | } | ||||
6857 | |||||
6858 | auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2)); | ||||
6859 | CheckTBAA(OffsetCI, "Offset must be constant integer", &I, MD)do { if (!(OffsetCI)) { CheckFailed("Offset must be constant integer" , &I, MD); return false; } } while (false); | ||||
6860 | |||||
6861 | APInt Offset = OffsetCI->getValue(); | ||||
6862 | bool SeenAccessTypeInPath = false; | ||||
6863 | |||||
6864 | SmallPtrSet<MDNode *, 4> StructPath; | ||||
6865 | |||||
6866 | for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); | ||||
6867 | BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, | ||||
6868 | IsNewFormat)) { | ||||
6869 | if (!StructPath.insert(BaseNode).second) { | ||||
6870 | CheckFailed("Cycle detected in struct path", &I, MD); | ||||
6871 | return false; | ||||
6872 | } | ||||
6873 | |||||
6874 | bool Invalid; | ||||
6875 | unsigned BaseNodeBitWidth; | ||||
6876 | std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode, | ||||
6877 | IsNewFormat); | ||||
6878 | |||||
6879 | // If the base node is invalid in itself, then we've already printed all the | ||||
6880 | // errors we wanted to print. | ||||
6881 | if (Invalid) | ||||
6882 | return false; | ||||
6883 | |||||
6884 | SeenAccessTypeInPath |= BaseNode == AccessType; | ||||
6885 | |||||
6886 | if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType) | ||||
6887 | CheckTBAA(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) | ||||
6888 | &I, MD, &Offset)do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false); | ||||
6889 | |||||
6890 | CheckTBAA(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) | ||||
6891 | (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) | ||||
6892 | (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) | ||||
6893 | "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) | ||||
6894 | 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); | ||||
6895 | |||||
6896 | if (IsNewFormat && SeenAccessTypeInPath) | ||||
6897 | break; | ||||
6898 | } | ||||
6899 | |||||
6900 | CheckTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", &I,do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false) | ||||
6901 | MD)do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false); | ||||
6902 | return true; | ||||
6903 | } | ||||
6904 | |||||
6905 | char VerifierLegacyPass::ID = 0; | ||||
6906 | 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)); } | ||||
6907 | |||||
6908 | FunctionPass *llvm::createVerifierPass(bool FatalErrors) { | ||||
6909 | return new VerifierLegacyPass(FatalErrors); | ||||
6910 | } | ||||
6911 | |||||
6912 | AnalysisKey VerifierAnalysis::Key; | ||||
6913 | VerifierAnalysis::Result VerifierAnalysis::run(Module &M, | ||||
6914 | ModuleAnalysisManager &) { | ||||
6915 | Result Res; | ||||
6916 | Res.IRBroken = llvm::verifyModule(M, &dbgs(), &Res.DebugInfoBroken); | ||||
6917 | return Res; | ||||
6918 | } | ||||
6919 | |||||
6920 | VerifierAnalysis::Result VerifierAnalysis::run(Function &F, | ||||
6921 | FunctionAnalysisManager &) { | ||||
6922 | return { llvm::verifyFunction(F, &dbgs()), false }; | ||||
6923 | } | ||||
6924 | |||||
6925 | PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { | ||||
6926 | auto Res = AM.getResult<VerifierAnalysis>(M); | ||||
6927 | if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) | ||||
6928 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
6929 | |||||
6930 | return PreservedAnalyses::all(); | ||||
6931 | } | ||||
6932 | |||||
6933 | PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { | ||||
6934 | auto res = AM.getResult<VerifierAnalysis>(F); | ||||
6935 | if (res.IRBroken && FatalErrors) | ||||
6936 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
6937 | |||||
6938 | return PreservedAnalyses::all(); | ||||
6939 | } |
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/PointerUnion.h" | ||||||||||||
19 | #include "llvm/ADT/STLExtras.h" | ||||||||||||
20 | #include "llvm/ADT/SmallVector.h" | ||||||||||||
21 | #include "llvm/ADT/StringRef.h" | ||||||||||||
22 | #include "llvm/ADT/iterator_range.h" | ||||||||||||
23 | #include "llvm/IR/Constants.h" | ||||||||||||
24 | #include "llvm/IR/Metadata.h" | ||||||||||||
25 | #include "llvm/Support/Casting.h" | ||||||||||||
26 | #include "llvm/Support/CommandLine.h" | ||||||||||||
27 | #include "llvm/Support/Discriminator.h" | ||||||||||||
28 | #include <cassert> | ||||||||||||
29 | #include <climits> | ||||||||||||
30 | #include <cstddef> | ||||||||||||
31 | #include <cstdint> | ||||||||||||
32 | #include <iterator> | ||||||||||||
33 | #include <optional> | ||||||||||||
34 | #include <vector> | ||||||||||||
35 | |||||||||||||
36 | // Helper macros for defining get() overrides. | ||||||||||||
37 | #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ | ||||||||||||
38 | #define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS | ||||||||||||
39 | #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) ); } \ | ||||||||||||
40 | static CLASS *getDistinct(LLVMContext &Context, \ | ||||||||||||
41 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
42 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ | ||||||||||||
43 | } \ | ||||||||||||
44 | static Temp##CLASS getTemporary(LLVMContext &Context, \ | ||||||||||||
45 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
46 | return Temp##CLASS( \ | ||||||||||||
47 | getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ | ||||||||||||
48 | } | ||||||||||||
49 | #define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ | ||||||||||||
50 | static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
51 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ | ||||||||||||
52 | } \ | ||||||||||||
53 | static CLASS *getIfExists(LLVMContext &Context, \ | ||||||||||||
54 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
55 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ | ||||||||||||
56 | /* ShouldCreate */ false); \ | ||||||||||||
57 | } \ | ||||||||||||
58 | 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) ); } | ||||||||||||
59 | |||||||||||||
60 | namespace llvm { | ||||||||||||
61 | |||||||||||||
62 | namespace dwarf { | ||||||||||||
63 | enum Tag : uint16_t; | ||||||||||||
64 | } | ||||||||||||
65 | |||||||||||||
66 | class DbgVariableIntrinsic; | ||||||||||||
67 | |||||||||||||
68 | extern cl::opt<bool> EnableFSDiscriminator; | ||||||||||||
69 | |||||||||||||
70 | class DITypeRefArray { | ||||||||||||
71 | const MDTuple *N = nullptr; | ||||||||||||
72 | |||||||||||||
73 | public: | ||||||||||||
74 | DITypeRefArray() = default; | ||||||||||||
75 | DITypeRefArray(const MDTuple *N) : N(N) {} | ||||||||||||
76 | |||||||||||||
77 | explicit operator bool() const { return get(); } | ||||||||||||
78 | explicit operator MDTuple *() const { return get(); } | ||||||||||||
79 | |||||||||||||
80 | MDTuple *get() const { return const_cast<MDTuple *>(N); } | ||||||||||||
81 | MDTuple *operator->() const { return get(); } | ||||||||||||
82 | MDTuple &operator*() const { return *get(); } | ||||||||||||
83 | |||||||||||||
84 | // FIXME: Fix callers and remove condition on N. | ||||||||||||
85 | unsigned size() const { return N ? N->getNumOperands() : 0u; } | ||||||||||||
86 | DIType *operator[](unsigned I) const { | ||||||||||||
87 | return cast_or_null<DIType>(N->getOperand(I)); | ||||||||||||
88 | } | ||||||||||||
89 | |||||||||||||
90 | class iterator { | ||||||||||||
91 | MDNode::op_iterator I = nullptr; | ||||||||||||
92 | |||||||||||||
93 | public: | ||||||||||||
94 | using iterator_category = std::input_iterator_tag; | ||||||||||||
95 | using value_type = DIType *; | ||||||||||||
96 | using difference_type = std::ptrdiff_t; | ||||||||||||
97 | using pointer = void; | ||||||||||||
98 | using reference = DIType *; | ||||||||||||
99 | |||||||||||||
100 | iterator() = default; | ||||||||||||
101 | explicit iterator(MDNode::op_iterator I) : I(I) {} | ||||||||||||
102 | |||||||||||||
103 | DIType *operator*() const { return cast_or_null<DIType>(*I); } | ||||||||||||
104 | |||||||||||||
105 | iterator &operator++() { | ||||||||||||
106 | ++I; | ||||||||||||
107 | return *this; | ||||||||||||
108 | } | ||||||||||||
109 | |||||||||||||
110 | iterator operator++(int) { | ||||||||||||
111 | iterator Temp(*this); | ||||||||||||
112 | ++I; | ||||||||||||
113 | return Temp; | ||||||||||||
114 | } | ||||||||||||
115 | |||||||||||||
116 | bool operator==(const iterator &X) const { return I == X.I; } | ||||||||||||
117 | bool operator!=(const iterator &X) const { return I != X.I; } | ||||||||||||
118 | }; | ||||||||||||
119 | |||||||||||||
120 | // FIXME: Fix callers and remove condition on N. | ||||||||||||
121 | iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } | ||||||||||||
122 | iterator end() const { return N ? iterator(N->op_end()) : iterator(); } | ||||||||||||
123 | }; | ||||||||||||
124 | |||||||||||||
125 | /// Tagged DWARF-like metadata node. | ||||||||||||
126 | /// | ||||||||||||
127 | /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, | ||||||||||||
128 | /// defined in llvm/BinaryFormat/Dwarf.h). Called \a DINode because it's | ||||||||||||
129 | /// potentially used for non-DWARF output. | ||||||||||||
130 | class DINode : public MDNode { | ||||||||||||
131 | friend class LLVMContextImpl; | ||||||||||||
132 | friend class MDNode; | ||||||||||||
133 | |||||||||||||
134 | protected: | ||||||||||||
135 | DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
136 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = std::nullopt) | ||||||||||||
137 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||||||||||
138 | assert(Tag < 1u << 16)(static_cast <bool> (Tag < 1u << 16) ? void (0 ) : __assert_fail ("Tag < 1u << 16", "llvm/include/llvm/IR/DebugInfoMetadata.h" , 138, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
139 | SubclassData16 = Tag; | ||||||||||||
140 | } | ||||||||||||
141 | ~DINode() = default; | ||||||||||||
142 | |||||||||||||
143 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||||||||||
144 | return cast_or_null<Ty>(getOperand(I)); | ||||||||||||
145 | } | ||||||||||||
146 | |||||||||||||
147 | StringRef getStringOperand(unsigned I) const { | ||||||||||||
148 | if (auto *S = getOperandAs<MDString>(I)) | ||||||||||||
149 | return S->getString(); | ||||||||||||
150 | return StringRef(); | ||||||||||||
151 | } | ||||||||||||
152 | |||||||||||||
153 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||||||||||
154 | if (S.empty()) | ||||||||||||
155 | return nullptr; | ||||||||||||
156 | return MDString::get(Context, S); | ||||||||||||
157 | } | ||||||||||||
158 | |||||||||||||
159 | /// Allow subclasses to mutate the tag. | ||||||||||||
160 | void setTag(unsigned Tag) { SubclassData16 = Tag; } | ||||||||||||
161 | |||||||||||||
162 | public: | ||||||||||||
163 | dwarf::Tag getTag() const; | ||||||||||||
164 | |||||||||||||
165 | /// Debug info flags. | ||||||||||||
166 | /// | ||||||||||||
167 | /// The three accessibility flags are mutually exclusive and rolled together | ||||||||||||
168 | /// in the first two bits. | ||||||||||||
169 | enum DIFlags : uint32_t { | ||||||||||||
170 | #define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, | ||||||||||||
171 | #define DI_FLAG_LARGEST_NEEDED | ||||||||||||
172 | #include "llvm/IR/DebugInfoFlags.def" | ||||||||||||
173 | FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic, | ||||||||||||
174 | FlagPtrToMemberRep = FlagSingleInheritance | FlagMultipleInheritance | | ||||||||||||
175 | FlagVirtualInheritance, | ||||||||||||
176 | LLVM_MARK_AS_BITMASK_ENUM(FlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = FlagLargest | ||||||||||||
177 | }; | ||||||||||||
178 | |||||||||||||
179 | static DIFlags getFlag(StringRef Flag); | ||||||||||||
180 | static StringRef getFlagString(DIFlags Flag); | ||||||||||||
181 | |||||||||||||
182 | /// Split up a flags bitfield. | ||||||||||||
183 | /// | ||||||||||||
184 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||||||||||
185 | /// any remaining (unrecognized) bits. | ||||||||||||
186 | static DIFlags splitFlags(DIFlags Flags, | ||||||||||||
187 | SmallVectorImpl<DIFlags> &SplitFlags); | ||||||||||||
188 | |||||||||||||
189 | static bool classof(const Metadata *MD) { | ||||||||||||
190 | switch (MD->getMetadataID()) { | ||||||||||||
191 | default: | ||||||||||||
192 | return false; | ||||||||||||
193 | case GenericDINodeKind: | ||||||||||||
194 | case DISubrangeKind: | ||||||||||||
195 | case DIEnumeratorKind: | ||||||||||||
196 | case DIBasicTypeKind: | ||||||||||||
197 | case DIStringTypeKind: | ||||||||||||
198 | case DIDerivedTypeKind: | ||||||||||||
199 | case DICompositeTypeKind: | ||||||||||||
200 | case DISubroutineTypeKind: | ||||||||||||
201 | case DIFileKind: | ||||||||||||
202 | case DICompileUnitKind: | ||||||||||||
203 | case DISubprogramKind: | ||||||||||||
204 | case DILexicalBlockKind: | ||||||||||||
205 | case DILexicalBlockFileKind: | ||||||||||||
206 | case DINamespaceKind: | ||||||||||||
207 | case DICommonBlockKind: | ||||||||||||
208 | case DITemplateTypeParameterKind: | ||||||||||||
209 | case DITemplateValueParameterKind: | ||||||||||||
210 | case DIGlobalVariableKind: | ||||||||||||
211 | case DILocalVariableKind: | ||||||||||||
212 | case DILabelKind: | ||||||||||||
213 | case DIObjCPropertyKind: | ||||||||||||
214 | case DIImportedEntityKind: | ||||||||||||
215 | case DIModuleKind: | ||||||||||||
216 | case DIGenericSubrangeKind: | ||||||||||||
217 | case DIAssignIDKind: | ||||||||||||
218 | return true; | ||||||||||||
219 | } | ||||||||||||
220 | } | ||||||||||||
221 | }; | ||||||||||||
222 | |||||||||||||
223 | /// Generic tagged DWARF-like metadata node. | ||||||||||||
224 | /// | ||||||||||||
225 | /// An un-specialized DWARF-like metadata node. The first operand is a | ||||||||||||
226 | /// (possibly empty) null-separated \a MDString header that contains arbitrary | ||||||||||||
227 | /// fields. The remaining operands are \a dwarf_operands(), and are pointers | ||||||||||||
228 | /// to other metadata. | ||||||||||||
229 | class GenericDINode : public DINode { | ||||||||||||
230 | friend class LLVMContextImpl; | ||||||||||||
231 | friend class MDNode; | ||||||||||||
232 | |||||||||||||
233 | GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, | ||||||||||||
234 | unsigned Tag, ArrayRef<Metadata *> Ops1, | ||||||||||||
235 | ArrayRef<Metadata *> Ops2) | ||||||||||||
236 | : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { | ||||||||||||
237 | setHash(Hash); | ||||||||||||
238 | } | ||||||||||||
239 | ~GenericDINode() { dropAllReferences(); } | ||||||||||||
240 | |||||||||||||
241 | void setHash(unsigned Hash) { SubclassData32 = Hash; } | ||||||||||||
242 | void recalculateHash(); | ||||||||||||
243 | |||||||||||||
244 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
245 | StringRef Header, ArrayRef<Metadata *> DwarfOps, | ||||||||||||
246 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
247 | return getImpl(Context, Tag, getCanonicalMDString(Context, Header), | ||||||||||||
248 | DwarfOps, Storage, ShouldCreate); | ||||||||||||
249 | } | ||||||||||||
250 | |||||||||||||
251 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
252 | MDString *Header, ArrayRef<Metadata *> DwarfOps, | ||||||||||||
253 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
254 | |||||||||||||
255 | TempGenericDINode cloneImpl() const { | ||||||||||||
256 | return getTemporary(getContext(), getTag(), getHeader(), | ||||||||||||
257 | SmallVector<Metadata *, 4>(dwarf_operands())); | ||||||||||||
258 | } | ||||||||||||
259 | |||||||||||||
260 | public: | ||||||||||||
261 | unsigned getHash() const { return SubclassData32; } | ||||||||||||
262 | |||||||||||||
263 | DEFINE_MDNODE_GET(GenericDINode, | ||||||||||||
264 | (unsigned Tag, StringRef Header, | ||||||||||||
265 | ArrayRef<Metadata *> DwarfOps), | ||||||||||||
266 | (Tag, Header, DwarfOps)) | ||||||||||||
267 | DEFINE_MDNODE_GET(GenericDINode, | ||||||||||||
268 | (unsigned Tag, MDString *Header, | ||||||||||||
269 | ArrayRef<Metadata *> DwarfOps), | ||||||||||||
270 | (Tag, Header, DwarfOps)) | ||||||||||||
271 | |||||||||||||
272 | /// Return a (temporary) clone of this. | ||||||||||||
273 | TempGenericDINode clone() const { return cloneImpl(); } | ||||||||||||
274 | |||||||||||||
275 | dwarf::Tag getTag() const; | ||||||||||||
276 | StringRef getHeader() const { return getStringOperand(0); } | ||||||||||||
277 | MDString *getRawHeader() const { return getOperandAs<MDString>(0); } | ||||||||||||
278 | |||||||||||||
279 | op_iterator dwarf_op_begin() const { return op_begin() + 1; } | ||||||||||||
280 | op_iterator dwarf_op_end() const { return op_end(); } | ||||||||||||
281 | op_range dwarf_operands() const { | ||||||||||||
282 | return op_range(dwarf_op_begin(), dwarf_op_end()); | ||||||||||||
283 | } | ||||||||||||
284 | |||||||||||||
285 | unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } | ||||||||||||
286 | const MDOperand &getDwarfOperand(unsigned I) const { | ||||||||||||
287 | return getOperand(I + 1); | ||||||||||||
288 | } | ||||||||||||
289 | void replaceDwarfOperandWith(unsigned I, Metadata *New) { | ||||||||||||
290 | replaceOperandWith(I + 1, New); | ||||||||||||
291 | } | ||||||||||||
292 | |||||||||||||
293 | static bool classof(const Metadata *MD) { | ||||||||||||
294 | return MD->getMetadataID() == GenericDINodeKind; | ||||||||||||
295 | } | ||||||||||||
296 | }; | ||||||||||||
297 | |||||||||||||
298 | /// Assignment ID. | ||||||||||||
299 | /// Used to link stores (as an attachment) and dbg.assigns (as an operand). | ||||||||||||
300 | /// DIAssignID metadata is never uniqued as we compare instances using | ||||||||||||
301 | /// referential equality (the instance/address is the ID). | ||||||||||||
302 | class DIAssignID : public MDNode { | ||||||||||||
303 | friend class LLVMContextImpl; | ||||||||||||
304 | friend class MDNode; | ||||||||||||
305 | |||||||||||||
306 | DIAssignID(LLVMContext &C, StorageType Storage) | ||||||||||||
307 | : MDNode(C, DIAssignIDKind, Storage, std::nullopt) {} | ||||||||||||
308 | |||||||||||||
309 | ~DIAssignID() { dropAllReferences(); } | ||||||||||||
310 | |||||||||||||
311 | static DIAssignID *getImpl(LLVMContext &Context, StorageType Storage, | ||||||||||||
312 | bool ShouldCreate = true); | ||||||||||||
313 | |||||||||||||
314 | TempDIAssignID cloneImpl() const { return getTemporary(getContext()); } | ||||||||||||
315 | |||||||||||||
316 | public: | ||||||||||||
317 | // This node has no operands to replace. | ||||||||||||
318 | void replaceOperandWith(unsigned I, Metadata *New) = delete; | ||||||||||||
319 | |||||||||||||
320 | static DIAssignID *getDistinct(LLVMContext &Context) { | ||||||||||||
321 | return getImpl(Context, Distinct); | ||||||||||||
322 | } | ||||||||||||
323 | static TempDIAssignID getTemporary(LLVMContext &Context) { | ||||||||||||
324 | return TempDIAssignID(getImpl(Context, Temporary)); | ||||||||||||
325 | } | ||||||||||||
326 | // NOTE: Do not define get(LLVMContext&) - see class comment. | ||||||||||||
327 | |||||||||||||
328 | static bool classof(const Metadata *MD) { | ||||||||||||
329 | return MD->getMetadataID() == DIAssignIDKind; | ||||||||||||
330 | } | ||||||||||||
331 | }; | ||||||||||||
332 | |||||||||||||
333 | /// Array subrange. | ||||||||||||
334 | /// | ||||||||||||
335 | /// TODO: Merge into node for DW_TAG_array_type, which should have a custom | ||||||||||||
336 | /// type. | ||||||||||||
337 | class DISubrange : public DINode { | ||||||||||||
338 | friend class LLVMContextImpl; | ||||||||||||
339 | friend class MDNode; | ||||||||||||
340 | |||||||||||||
341 | DISubrange(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops); | ||||||||||||
342 | |||||||||||||
343 | ~DISubrange() = default; | ||||||||||||
344 | |||||||||||||
345 | static DISubrange *getImpl(LLVMContext &Context, int64_t Count, | ||||||||||||
346 | int64_t LowerBound, StorageType Storage, | ||||||||||||
347 | bool ShouldCreate = true); | ||||||||||||
348 | |||||||||||||
349 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||||||||||
350 | int64_t LowerBound, StorageType Storage, | ||||||||||||
351 | bool ShouldCreate = true); | ||||||||||||
352 | |||||||||||||
353 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||||||||||
354 | Metadata *LowerBound, Metadata *UpperBound, | ||||||||||||
355 | Metadata *Stride, StorageType Storage, | ||||||||||||
356 | bool ShouldCreate = true); | ||||||||||||
357 | |||||||||||||
358 | TempDISubrange cloneImpl() const { | ||||||||||||
359 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||||||||||
360 | getRawUpperBound(), getRawStride()); | ||||||||||||
361 | } | ||||||||||||
362 | |||||||||||||
363 | public: | ||||||||||||
364 | DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), | ||||||||||||
365 | (Count, LowerBound)) | ||||||||||||
366 | |||||||||||||
367 | DEFINE_MDNODE_GET(DISubrange, (Metadata * CountNode, int64_t LowerBound = 0), | ||||||||||||
368 | (CountNode, LowerBound)) | ||||||||||||
369 | |||||||||||||
370 | DEFINE_MDNODE_GET(DISubrange, | ||||||||||||
371 | (Metadata * CountNode, Metadata *LowerBound, | ||||||||||||
372 | Metadata *UpperBound, Metadata *Stride), | ||||||||||||
373 | (CountNode, LowerBound, UpperBound, Stride)) | ||||||||||||
374 | |||||||||||||
375 | TempDISubrange clone() const { return cloneImpl(); } | ||||||||||||
376 | |||||||||||||
377 | Metadata *getRawCountNode() const { return getOperand(0).get(); } | ||||||||||||
378 | |||||||||||||
379 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||||||||||
380 | |||||||||||||
381 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||||||||||
382 | |||||||||||||
383 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||||||||||
384 | |||||||||||||
385 | typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType; | ||||||||||||
386 | |||||||||||||
387 | BoundType getCount() const; | ||||||||||||
388 | |||||||||||||
389 | BoundType getLowerBound() const; | ||||||||||||
390 | |||||||||||||
391 | BoundType getUpperBound() const; | ||||||||||||
392 | |||||||||||||
393 | BoundType getStride() const; | ||||||||||||
394 | |||||||||||||
395 | static bool classof(const Metadata *MD) { | ||||||||||||
396 | return MD->getMetadataID() == DISubrangeKind; | ||||||||||||
397 | } | ||||||||||||
398 | }; | ||||||||||||
399 | |||||||||||||
400 | class DIGenericSubrange : public DINode { | ||||||||||||
401 | friend class LLVMContextImpl; | ||||||||||||
402 | friend class MDNode; | ||||||||||||
403 | |||||||||||||
404 | DIGenericSubrange(LLVMContext &C, StorageType Storage, | ||||||||||||
405 | ArrayRef<Metadata *> Ops); | ||||||||||||
406 | |||||||||||||
407 | ~DIGenericSubrange() = default; | ||||||||||||
408 | |||||||||||||
409 | static DIGenericSubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||||||||||
410 | Metadata *LowerBound, Metadata *UpperBound, | ||||||||||||
411 | Metadata *Stride, StorageType Storage, | ||||||||||||
412 | bool ShouldCreate = true); | ||||||||||||
413 | |||||||||||||
414 | TempDIGenericSubrange cloneImpl() const { | ||||||||||||
415 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||||||||||
416 | getRawUpperBound(), getRawStride()); | ||||||||||||
417 | } | ||||||||||||
418 | |||||||||||||
419 | public: | ||||||||||||
420 | DEFINE_MDNODE_GET(DIGenericSubrange, | ||||||||||||
421 | (Metadata * CountNode, Metadata *LowerBound, | ||||||||||||
422 | Metadata *UpperBound, Metadata *Stride), | ||||||||||||
423 | (CountNode, LowerBound, UpperBound, Stride)) | ||||||||||||
424 | |||||||||||||
425 | TempDIGenericSubrange clone() const { return cloneImpl(); } | ||||||||||||
426 | |||||||||||||
427 | Metadata *getRawCountNode() const { return getOperand(0).get(); } | ||||||||||||
428 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||||||||||
429 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||||||||||
430 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||||||||||
431 | |||||||||||||
432 | using BoundType = PointerUnion<DIVariable *, DIExpression *>; | ||||||||||||
433 | |||||||||||||
434 | BoundType getCount() const; | ||||||||||||
435 | BoundType getLowerBound() const; | ||||||||||||
436 | BoundType getUpperBound() const; | ||||||||||||
437 | BoundType getStride() const; | ||||||||||||
438 | |||||||||||||
439 | static bool classof(const Metadata *MD) { | ||||||||||||
440 | return MD->getMetadataID() == DIGenericSubrangeKind; | ||||||||||||
441 | } | ||||||||||||
442 | }; | ||||||||||||
443 | |||||||||||||
444 | /// Enumeration value. | ||||||||||||
445 | /// | ||||||||||||
446 | /// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no | ||||||||||||
447 | /// longer creates a type cycle. | ||||||||||||
448 | class DIEnumerator : public DINode { | ||||||||||||
449 | friend class LLVMContextImpl; | ||||||||||||
450 | friend class MDNode; | ||||||||||||
451 | |||||||||||||
452 | APInt Value; | ||||||||||||
453 | DIEnumerator(LLVMContext &C, StorageType Storage, const APInt &Value, | ||||||||||||
454 | bool IsUnsigned, ArrayRef<Metadata *> Ops); | ||||||||||||
455 | DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, | ||||||||||||
456 | bool IsUnsigned, ArrayRef<Metadata *> Ops) | ||||||||||||
457 | : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, | ||||||||||||
458 | Ops) {} | ||||||||||||
459 | ~DIEnumerator() = default; | ||||||||||||
460 | |||||||||||||
461 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||||||||||
462 | bool IsUnsigned, StringRef Name, | ||||||||||||
463 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
464 | return getImpl(Context, Value, IsUnsigned, | ||||||||||||
465 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); | ||||||||||||
466 | } | ||||||||||||
467 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||||||||||
468 | bool IsUnsigned, MDString *Name, | ||||||||||||
469 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
470 | |||||||||||||
471 | TempDIEnumerator cloneImpl() const { | ||||||||||||
472 | return getTemporary(getContext(), getValue(), isUnsigned(), getName()); | ||||||||||||
473 | } | ||||||||||||
474 | |||||||||||||
475 | public: | ||||||||||||
476 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
477 | (int64_t Value, bool IsUnsigned, StringRef Name), | ||||||||||||
478 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||||||||||
479 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
480 | (int64_t Value, bool IsUnsigned, MDString *Name), | ||||||||||||
481 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||||||||||
482 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
483 | (APInt Value, bool IsUnsigned, StringRef Name), | ||||||||||||
484 | (Value, IsUnsigned, Name)) | ||||||||||||
485 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
486 | (APInt Value, bool IsUnsigned, MDString *Name), | ||||||||||||
487 | (Value, IsUnsigned, Name)) | ||||||||||||
488 | |||||||||||||
489 | TempDIEnumerator clone() const { return cloneImpl(); } | ||||||||||||
490 | |||||||||||||
491 | const APInt &getValue() const { return Value; } | ||||||||||||
492 | bool isUnsigned() const { return SubclassData32; } | ||||||||||||
493 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
494 | |||||||||||||
495 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
496 | |||||||||||||
497 | static bool classof(const Metadata *MD) { | ||||||||||||
498 | return MD->getMetadataID() == DIEnumeratorKind; | ||||||||||||
499 | } | ||||||||||||
500 | }; | ||||||||||||
501 | |||||||||||||
502 | /// Base class for scope-like contexts. | ||||||||||||
503 | /// | ||||||||||||
504 | /// Base class for lexical scopes and types (which are also declaration | ||||||||||||
505 | /// contexts). | ||||||||||||
506 | /// | ||||||||||||
507 | /// TODO: Separate the concepts of declaration contexts and lexical scopes. | ||||||||||||
508 | class DIScope : public DINode { | ||||||||||||
509 | protected: | ||||||||||||
510 | DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
511 | ArrayRef<Metadata *> Ops) | ||||||||||||
512 | : DINode(C, ID, Storage, Tag, Ops) {} | ||||||||||||
513 | ~DIScope() = default; | ||||||||||||
514 | |||||||||||||
515 | public: | ||||||||||||
516 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
517 | |||||||||||||
518 | inline StringRef getFilename() const; | ||||||||||||
519 | inline StringRef getDirectory() const; | ||||||||||||
520 | inline std::optional<StringRef> getSource() const; | ||||||||||||
521 | |||||||||||||
522 | StringRef getName() const; | ||||||||||||
523 | DIScope *getScope() const; | ||||||||||||
524 | |||||||||||||
525 | /// Return the raw underlying file. | ||||||||||||
526 | /// | ||||||||||||
527 | /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file (it | ||||||||||||
528 | /// \em is the file). If \c this is an \a DIFile, we need to return \c this. | ||||||||||||
529 | /// Otherwise, return the first operand, which is where all other subclasses | ||||||||||||
530 | /// store their file pointer. | ||||||||||||
531 | Metadata *getRawFile() const { | ||||||||||||
532 | return isa<DIFile>(this) ? const_cast<DIScope *>(this) | ||||||||||||
533 | : static_cast<Metadata *>(getOperand(0)); | ||||||||||||
534 | } | ||||||||||||
535 | |||||||||||||
536 | static bool classof(const Metadata *MD) { | ||||||||||||
537 | switch (MD->getMetadataID()) { | ||||||||||||
538 | default: | ||||||||||||
539 | return false; | ||||||||||||
540 | case DIBasicTypeKind: | ||||||||||||
541 | case DIStringTypeKind: | ||||||||||||
542 | case DIDerivedTypeKind: | ||||||||||||
543 | case DICompositeTypeKind: | ||||||||||||
544 | case DISubroutineTypeKind: | ||||||||||||
545 | case DIFileKind: | ||||||||||||
546 | case DICompileUnitKind: | ||||||||||||
547 | case DISubprogramKind: | ||||||||||||
548 | case DILexicalBlockKind: | ||||||||||||
549 | case DILexicalBlockFileKind: | ||||||||||||
550 | case DINamespaceKind: | ||||||||||||
551 | case DICommonBlockKind: | ||||||||||||
552 | case DIModuleKind: | ||||||||||||
553 | return true; | ||||||||||||
554 | } | ||||||||||||
555 | } | ||||||||||||
556 | }; | ||||||||||||
557 | |||||||||||||
558 | /// File. | ||||||||||||
559 | /// | ||||||||||||
560 | /// TODO: Merge with directory/file node (including users). | ||||||||||||
561 | /// TODO: Canonicalize paths on creation. | ||||||||||||
562 | class DIFile : public DIScope { | ||||||||||||
563 | friend class LLVMContextImpl; | ||||||||||||
564 | friend class MDNode; | ||||||||||||
565 | |||||||||||||
566 | public: | ||||||||||||
567 | /// Which algorithm (e.g. MD5) a checksum was generated with. | ||||||||||||
568 | /// | ||||||||||||
569 | /// The encoding is explicit because it is used directly in Bitcode. The | ||||||||||||
570 | /// value 0 is reserved to indicate the absence of a checksum in Bitcode. | ||||||||||||
571 | enum ChecksumKind { | ||||||||||||
572 | // The first variant was originally CSK_None, encoded as 0. The new | ||||||||||||
573 | // internal representation removes the need for this by wrapping the | ||||||||||||
574 | // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0 | ||||||||||||
575 | // encoding is reserved. | ||||||||||||
576 | CSK_MD5 = 1, | ||||||||||||
577 | CSK_SHA1 = 2, | ||||||||||||
578 | CSK_SHA256 = 3, | ||||||||||||
579 | CSK_Last = CSK_SHA256 // Should be last enumeration. | ||||||||||||
580 | }; | ||||||||||||
581 | |||||||||||||
582 | /// A single checksum, represented by a \a Kind and a \a Value (a string). | ||||||||||||
583 | template <typename T> struct ChecksumInfo { | ||||||||||||
584 | /// The kind of checksum which \a Value encodes. | ||||||||||||
585 | ChecksumKind Kind; | ||||||||||||
586 | /// The string value of the checksum. | ||||||||||||
587 | T Value; | ||||||||||||
588 | |||||||||||||
589 | ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) {} | ||||||||||||
590 | ~ChecksumInfo() = default; | ||||||||||||
591 | bool operator==(const ChecksumInfo<T> &X) const { | ||||||||||||
592 | return Kind == X.Kind && Value == X.Value; | ||||||||||||
593 | } | ||||||||||||
594 | bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } | ||||||||||||
595 | StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } | ||||||||||||
596 | }; | ||||||||||||
597 | |||||||||||||
598 | private: | ||||||||||||
599 | std::optional<ChecksumInfo<MDString *>> Checksum; | ||||||||||||
600 | /// An optional source. A nullptr means none. | ||||||||||||
601 | MDString *Source; | ||||||||||||
602 | |||||||||||||
603 | DIFile(LLVMContext &C, StorageType Storage, | ||||||||||||
604 | std::optional<ChecksumInfo<MDString *>> CS, MDString *Src, | ||||||||||||
605 | ArrayRef<Metadata *> Ops); | ||||||||||||
606 | ~DIFile() = default; | ||||||||||||
607 | |||||||||||||
608 | static DIFile *getImpl(LLVMContext &Context, StringRef Filename, | ||||||||||||
609 | StringRef Directory, | ||||||||||||
610 | std::optional<ChecksumInfo<StringRef>> CS, | ||||||||||||
611 | std::optional<StringRef> Source, StorageType Storage, | ||||||||||||
612 | bool ShouldCreate = true) { | ||||||||||||
613 | std::optional<ChecksumInfo<MDString *>> MDChecksum; | ||||||||||||
614 | if (CS) | ||||||||||||
615 | MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); | ||||||||||||
616 | return getImpl(Context, getCanonicalMDString(Context, Filename), | ||||||||||||
617 | getCanonicalMDString(Context, Directory), MDChecksum, | ||||||||||||
618 | Source ? MDString::get(Context, *Source) : nullptr, Storage, | ||||||||||||
619 | ShouldCreate); | ||||||||||||
620 | } | ||||||||||||
621 | static DIFile *getImpl(LLVMContext &Context, MDString *Filename, | ||||||||||||
622 | MDString *Directory, | ||||||||||||
623 | std::optional<ChecksumInfo<MDString *>> CS, | ||||||||||||
624 | MDString *Source, StorageType Storage, | ||||||||||||
625 | bool ShouldCreate = true); | ||||||||||||
626 | |||||||||||||
627 | TempDIFile cloneImpl() const { | ||||||||||||
628 | return getTemporary(getContext(), getFilename(), getDirectory(), | ||||||||||||
629 | getChecksum(), getSource()); | ||||||||||||
630 | } | ||||||||||||
631 | |||||||||||||
632 | public: | ||||||||||||
633 | DEFINE_MDNODE_GET(DIFile, | ||||||||||||
634 | (StringRef Filename, StringRef Directory, | ||||||||||||
635 | std::optional<ChecksumInfo<StringRef>> CS = std::nullopt, | ||||||||||||
636 | std::optional<StringRef> Source = std::nullopt), | ||||||||||||
637 | (Filename, Directory, CS, Source)) | ||||||||||||
638 | DEFINE_MDNODE_GET(DIFile, | ||||||||||||
639 | (MDString * Filename, MDString *Directory, | ||||||||||||
640 | std::optional<ChecksumInfo<MDString *>> CS = std::nullopt, | ||||||||||||
641 | MDString *Source = nullptr), | ||||||||||||
642 | (Filename, Directory, CS, Source)) | ||||||||||||
643 | |||||||||||||
644 | TempDIFile clone() const { return cloneImpl(); } | ||||||||||||
645 | |||||||||||||
646 | StringRef getFilename() const { return getStringOperand(0); } | ||||||||||||
647 | StringRef getDirectory() const { return getStringOperand(1); } | ||||||||||||
648 | std::optional<ChecksumInfo<StringRef>> getChecksum() const { | ||||||||||||
649 | std::optional<ChecksumInfo<StringRef>> StringRefChecksum; | ||||||||||||
650 | if (Checksum) | ||||||||||||
651 | StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); | ||||||||||||
652 | return StringRefChecksum; | ||||||||||||
653 | } | ||||||||||||
654 | std::optional<StringRef> getSource() const { | ||||||||||||
655 | return Source ? std::optional<StringRef>(Source->getString()) | ||||||||||||
656 | : std::nullopt; | ||||||||||||
657 | } | ||||||||||||
658 | |||||||||||||
659 | MDString *getRawFilename() const { return getOperandAs<MDString>(0); } | ||||||||||||
660 | MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } | ||||||||||||
661 | std::optional<ChecksumInfo<MDString *>> getRawChecksum() const { | ||||||||||||
662 | return Checksum; | ||||||||||||
663 | } | ||||||||||||
664 | MDString *getRawSource() const { return Source; } | ||||||||||||
665 | |||||||||||||
666 | static StringRef getChecksumKindAsString(ChecksumKind CSKind); | ||||||||||||
667 | static std::optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); | ||||||||||||
668 | |||||||||||||
669 | static bool classof(const Metadata *MD) { | ||||||||||||
670 | return MD->getMetadataID() == DIFileKind; | ||||||||||||
671 | } | ||||||||||||
672 | }; | ||||||||||||
673 | |||||||||||||
674 | StringRef DIScope::getFilename() const { | ||||||||||||
675 | if (auto *F = getFile()) | ||||||||||||
676 | return F->getFilename(); | ||||||||||||
677 | return ""; | ||||||||||||
678 | } | ||||||||||||
679 | |||||||||||||
680 | StringRef DIScope::getDirectory() const { | ||||||||||||
681 | if (auto *F = getFile()) | ||||||||||||
682 | return F->getDirectory(); | ||||||||||||
683 | return ""; | ||||||||||||
684 | } | ||||||||||||
685 | |||||||||||||
686 | std::optional<StringRef> DIScope::getSource() const { | ||||||||||||
687 | if (auto *F = getFile()) | ||||||||||||
688 | return F->getSource(); | ||||||||||||
689 | return std::nullopt; | ||||||||||||
690 | } | ||||||||||||
691 | |||||||||||||
692 | /// Base class for types. | ||||||||||||
693 | /// | ||||||||||||
694 | /// TODO: Remove the hardcoded name and context, since many types don't use | ||||||||||||
695 | /// them. | ||||||||||||
696 | /// TODO: Split up flags. | ||||||||||||
697 | class DIType : public DIScope { | ||||||||||||
698 | unsigned Line; | ||||||||||||
699 | DIFlags Flags; | ||||||||||||
700 | uint64_t SizeInBits; | ||||||||||||
701 | uint64_t OffsetInBits; | ||||||||||||
702 | uint32_t AlignInBits; | ||||||||||||
703 | |||||||||||||
704 | protected: | ||||||||||||
705 | DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
706 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
707 | uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||||||||||
708 | : DIScope(C, ID, Storage, Tag, Ops) { | ||||||||||||
709 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||||||||||
710 | } | ||||||||||||
711 | ~DIType() = default; | ||||||||||||
712 | |||||||||||||
713 | void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
714 | uint64_t OffsetInBits, DIFlags Flags) { | ||||||||||||
715 | this->Line = Line; | ||||||||||||
716 | this->Flags = Flags; | ||||||||||||
717 | this->SizeInBits = SizeInBits; | ||||||||||||
718 | this->AlignInBits = AlignInBits; | ||||||||||||
719 | this->OffsetInBits = OffsetInBits; | ||||||||||||
720 | } | ||||||||||||
721 | |||||||||||||
722 | /// Change fields in place. | ||||||||||||
723 | void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits, | ||||||||||||
724 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) { | ||||||||||||
725 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 725, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
726 | setTag(Tag); | ||||||||||||
727 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||||||||||
728 | } | ||||||||||||
729 | |||||||||||||
730 | public: | ||||||||||||
731 | TempDIType clone() const { | ||||||||||||
732 | return TempDIType(cast<DIType>(MDNode::clone().release())); | ||||||||||||
733 | } | ||||||||||||
734 | |||||||||||||
735 | unsigned getLine() const { return Line; } | ||||||||||||
736 | uint64_t getSizeInBits() const { return SizeInBits; } | ||||||||||||
737 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||||||||||
738 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||||||||||
739 | uint64_t getOffsetInBits() const { return OffsetInBits; } | ||||||||||||
740 | DIFlags getFlags() const { return Flags; } | ||||||||||||
741 | |||||||||||||
742 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
743 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
744 | |||||||||||||
745 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
746 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
747 | |||||||||||||
748 | /// Returns a new temporary DIType with updated Flags | ||||||||||||
749 | TempDIType cloneWithFlags(DIFlags NewFlags) const { | ||||||||||||
750 | auto NewTy = clone(); | ||||||||||||
751 | NewTy->Flags = NewFlags; | ||||||||||||
752 | return NewTy; | ||||||||||||
753 | } | ||||||||||||
754 | |||||||||||||
755 | bool isPrivate() const { | ||||||||||||
756 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||||||||||
757 | } | ||||||||||||
758 | bool isProtected() const { | ||||||||||||
759 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||||||||||
760 | } | ||||||||||||
761 | bool isPublic() const { | ||||||||||||
762 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||||||||||
763 | } | ||||||||||||
764 | bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } | ||||||||||||
765 | bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } | ||||||||||||
766 | bool isVirtual() const { return getFlags() & FlagVirtual; } | ||||||||||||
767 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||||||||||
768 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||||||||||
769 | bool isObjcClassComplete() const { | ||||||||||||
770 | return getFlags() & FlagObjcClassComplete; | ||||||||||||
771 | } | ||||||||||||
772 | bool isVector() const { return getFlags() & FlagVector; } | ||||||||||||
773 | bool isBitField() const { return getFlags() & FlagBitField; } | ||||||||||||
774 | bool isStaticMember() const { return getFlags() & FlagStaticMember; } | ||||||||||||
775 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||||||||||
776 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||||||||||
777 | bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; } | ||||||||||||
778 | bool isTypePassByReference() const { | ||||||||||||
779 | return getFlags() & FlagTypePassByReference; | ||||||||||||
780 | } | ||||||||||||
781 | bool isBigEndian() const { return getFlags() & FlagBigEndian; } | ||||||||||||
782 | bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } | ||||||||||||
783 | bool getExportSymbols() const { return getFlags() & FlagExportSymbols; } | ||||||||||||
784 | |||||||||||||
785 | static bool classof(const Metadata *MD) { | ||||||||||||
786 | switch (MD->getMetadataID()) { | ||||||||||||
787 | default: | ||||||||||||
788 | return false; | ||||||||||||
789 | case DIBasicTypeKind: | ||||||||||||
790 | case DIStringTypeKind: | ||||||||||||
791 | case DIDerivedTypeKind: | ||||||||||||
792 | case DICompositeTypeKind: | ||||||||||||
793 | case DISubroutineTypeKind: | ||||||||||||
794 | return true; | ||||||||||||
795 | } | ||||||||||||
796 | } | ||||||||||||
797 | }; | ||||||||||||
798 | |||||||||||||
799 | /// Basic type, like 'int' or 'float'. | ||||||||||||
800 | /// | ||||||||||||
801 | /// TODO: Split out DW_TAG_unspecified_type. | ||||||||||||
802 | /// TODO: Drop unused accessors. | ||||||||||||
803 | class DIBasicType : public DIType { | ||||||||||||
804 | friend class LLVMContextImpl; | ||||||||||||
805 | friend class MDNode; | ||||||||||||
806 | |||||||||||||
807 | unsigned Encoding; | ||||||||||||
808 | |||||||||||||
809 | DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
810 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
811 | DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||||||||||
812 | : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||||||||||
813 | Flags, Ops), | ||||||||||||
814 | Encoding(Encoding) {} | ||||||||||||
815 | ~DIBasicType() = default; | ||||||||||||
816 | |||||||||||||
817 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
818 | StringRef Name, uint64_t SizeInBits, | ||||||||||||
819 | uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
820 | DIFlags Flags, StorageType Storage, | ||||||||||||
821 | bool ShouldCreate = true) { | ||||||||||||
822 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||||||||||
823 | SizeInBits, AlignInBits, Encoding, Flags, Storage, | ||||||||||||
824 | ShouldCreate); | ||||||||||||
825 | } | ||||||||||||
826 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
827 | MDString *Name, uint64_t SizeInBits, | ||||||||||||
828 | uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
829 | DIFlags Flags, StorageType Storage, | ||||||||||||
830 | bool ShouldCreate = true); | ||||||||||||
831 | |||||||||||||
832 | TempDIBasicType cloneImpl() const { | ||||||||||||
833 | return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), | ||||||||||||
834 | getAlignInBits(), getEncoding(), getFlags()); | ||||||||||||
835 | } | ||||||||||||
836 | |||||||||||||
837 | public: | ||||||||||||
838 | DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), | ||||||||||||
839 | (Tag, Name, 0, 0, 0, FlagZero)) | ||||||||||||
840 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
841 | (unsigned Tag, StringRef Name, uint64_t SizeInBits), | ||||||||||||
842 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||||||||||
843 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
844 | (unsigned Tag, MDString *Name, uint64_t SizeInBits), | ||||||||||||
845 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||||||||||
846 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
847 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||||||||||
848 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||||||||||
849 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||||||||||
850 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
851 | (unsigned Tag, MDString *Name, uint64_t SizeInBits, | ||||||||||||
852 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||||||||||
853 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||||||||||
854 | |||||||||||||
855 | TempDIBasicType clone() const { return cloneImpl(); } | ||||||||||||
856 | |||||||||||||
857 | unsigned getEncoding() const { return Encoding; } | ||||||||||||
858 | |||||||||||||
859 | enum class Signedness { Signed, Unsigned }; | ||||||||||||
860 | |||||||||||||
861 | /// Return the signedness of this type, or std::nullopt if this type is | ||||||||||||
862 | /// neither signed nor unsigned. | ||||||||||||
863 | std::optional<Signedness> getSignedness() const; | ||||||||||||
864 | |||||||||||||
865 | static bool classof(const Metadata *MD) { | ||||||||||||
866 | return MD->getMetadataID() == DIBasicTypeKind; | ||||||||||||
867 | } | ||||||||||||
868 | }; | ||||||||||||
869 | |||||||||||||
870 | /// String type, Fortran CHARACTER(n) | ||||||||||||
871 | class DIStringType : public DIType { | ||||||||||||
872 | friend class LLVMContextImpl; | ||||||||||||
873 | friend class MDNode; | ||||||||||||
874 | |||||||||||||
875 | unsigned Encoding; | ||||||||||||
876 | |||||||||||||
877 | DIStringType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
878 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
879 | ArrayRef<Metadata *> Ops) | ||||||||||||
880 | : DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||||||||||
881 | FlagZero, Ops), | ||||||||||||
882 | Encoding(Encoding) {} | ||||||||||||
883 | ~DIStringType() = default; | ||||||||||||
884 | |||||||||||||
885 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
886 | StringRef Name, Metadata *StringLength, | ||||||||||||
887 | Metadata *StrLenExp, Metadata *StrLocationExp, | ||||||||||||
888 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
889 | unsigned Encoding, StorageType Storage, | ||||||||||||
890 | bool ShouldCreate = true) { | ||||||||||||
891 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||||||||||
892 | StringLength, StrLenExp, StrLocationExp, SizeInBits, | ||||||||||||
893 | AlignInBits, Encoding, Storage, ShouldCreate); | ||||||||||||
894 | } | ||||||||||||
895 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
896 | MDString *Name, Metadata *StringLength, | ||||||||||||
897 | Metadata *StrLenExp, Metadata *StrLocationExp, | ||||||||||||
898 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
899 | unsigned Encoding, StorageType Storage, | ||||||||||||
900 | bool ShouldCreate = true); | ||||||||||||
901 | |||||||||||||
902 | TempDIStringType cloneImpl() const { | ||||||||||||
903 | return getTemporary(getContext(), getTag(), getRawName(), | ||||||||||||
904 | getRawStringLength(), getRawStringLengthExp(), | ||||||||||||
905 | getRawStringLocationExp(), getSizeInBits(), | ||||||||||||
906 | getAlignInBits(), getEncoding()); | ||||||||||||
907 | } | ||||||||||||
908 | |||||||||||||
909 | public: | ||||||||||||
910 | DEFINE_MDNODE_GET(DIStringType, | ||||||||||||
911 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||||||||||
912 | uint32_t AlignInBits), | ||||||||||||
913 | (Tag, Name, nullptr, nullptr, nullptr, SizeInBits, | ||||||||||||
914 | AlignInBits, 0)) | ||||||||||||
915 | DEFINE_MDNODE_GET(DIStringType, | ||||||||||||
916 | (unsigned Tag, MDString *Name, Metadata *StringLength, | ||||||||||||
917 | Metadata *StringLengthExp, Metadata *StringLocationExp, | ||||||||||||
918 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
919 | unsigned Encoding), | ||||||||||||
920 | (Tag, Name, StringLength, StringLengthExp, | ||||||||||||
921 | StringLocationExp, SizeInBits, AlignInBits, Encoding)) | ||||||||||||
922 | DEFINE_MDNODE_GET(DIStringType, | ||||||||||||
923 | (unsigned Tag, StringRef Name, Metadata *StringLength, | ||||||||||||
924 | Metadata *StringLengthExp, Metadata *StringLocationExp, | ||||||||||||
925 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
926 | unsigned Encoding), | ||||||||||||
927 | (Tag, Name, StringLength, StringLengthExp, | ||||||||||||
928 | StringLocationExp, SizeInBits, AlignInBits, Encoding)) | ||||||||||||
929 | |||||||||||||
930 | TempDIStringType clone() const { return cloneImpl(); } | ||||||||||||
931 | |||||||||||||
932 | static bool classof(const Metadata *MD) { | ||||||||||||
933 | return MD->getMetadataID() == DIStringTypeKind; | ||||||||||||
934 | } | ||||||||||||
935 | |||||||||||||
936 | DIVariable *getStringLength() const { | ||||||||||||
937 | return cast_or_null<DIVariable>(getRawStringLength()); | ||||||||||||
938 | } | ||||||||||||
939 | |||||||||||||
940 | DIExpression *getStringLengthExp() const { | ||||||||||||
941 | return cast_or_null<DIExpression>(getRawStringLengthExp()); | ||||||||||||
942 | } | ||||||||||||
943 | |||||||||||||
944 | DIExpression *getStringLocationExp() const { | ||||||||||||
945 | return cast_or_null<DIExpression>(getRawStringLocationExp()); | ||||||||||||
946 | } | ||||||||||||
947 | |||||||||||||
948 | unsigned getEncoding() const { return Encoding; } | ||||||||||||
949 | |||||||||||||
950 | Metadata *getRawStringLength() const { return getOperand(3); } | ||||||||||||
951 | |||||||||||||
952 | Metadata *getRawStringLengthExp() const { return getOperand(4); } | ||||||||||||
953 | |||||||||||||
954 | Metadata *getRawStringLocationExp() const { return getOperand(5); } | ||||||||||||
955 | }; | ||||||||||||
956 | |||||||||||||
957 | /// Derived types. | ||||||||||||
958 | /// | ||||||||||||
959 | /// This includes qualified types, pointers, references, friends, typedefs, and | ||||||||||||
960 | /// class members. | ||||||||||||
961 | /// | ||||||||||||
962 | /// TODO: Split out members (inheritance, fields, methods, etc.). | ||||||||||||
963 | class DIDerivedType : public DIType { | ||||||||||||
964 | friend class LLVMContextImpl; | ||||||||||||
965 | friend class MDNode; | ||||||||||||
966 | |||||||||||||
967 | /// The DWARF address space of the memory pointed to or referenced by a | ||||||||||||
968 | /// pointer or reference type respectively. | ||||||||||||
969 | std::optional<unsigned> DWARFAddressSpace; | ||||||||||||
970 | |||||||||||||
971 | DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
972 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
973 | uint64_t OffsetInBits, | ||||||||||||
974 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
975 | ArrayRef<Metadata *> Ops) | ||||||||||||
976 | : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, | ||||||||||||
977 | AlignInBits, OffsetInBits, Flags, Ops), | ||||||||||||
978 | DWARFAddressSpace(DWARFAddressSpace) {} | ||||||||||||
979 | ~DIDerivedType() = default; | ||||||||||||
980 | static DIDerivedType * | ||||||||||||
981 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, | ||||||||||||
982 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
983 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
984 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
985 | Metadata *ExtraData, DINodeArray Annotations, StorageType Storage, | ||||||||||||
986 | bool ShouldCreate = true) { | ||||||||||||
987 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, | ||||||||||||
988 | Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, | ||||||||||||
989 | DWARFAddressSpace, Flags, ExtraData, Annotations.get(), | ||||||||||||
990 | Storage, ShouldCreate); | ||||||||||||
991 | } | ||||||||||||
992 | static DIDerivedType * | ||||||||||||
993 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||||||||||
994 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||||||||||
995 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
996 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
997 | Metadata *ExtraData, Metadata *Annotations, StorageType Storage, | ||||||||||||
998 | bool ShouldCreate = true); | ||||||||||||
999 | |||||||||||||
1000 | TempDIDerivedType cloneImpl() const { | ||||||||||||
1001 | return getTemporary( | ||||||||||||
1002 | getContext(), getTag(), getName(), getFile(), getLine(), getScope(), | ||||||||||||
1003 | getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), | ||||||||||||
1004 | getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations()); | ||||||||||||
1005 | } | ||||||||||||
1006 | |||||||||||||
1007 | public: | ||||||||||||
1008 | DEFINE_MDNODE_GET( | ||||||||||||
1009 | DIDerivedType, | ||||||||||||
1010 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, | ||||||||||||
1011 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, | ||||||||||||
1012 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
1013 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
1014 | Metadata *ExtraData = nullptr, Metadata *Annotations = nullptr), | ||||||||||||
1015 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||||||||||
1016 | OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Annotations)) | ||||||||||||
1017 | DEFINE_MDNODE_GET(DIDerivedType, | ||||||||||||
1018 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
1019 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
1020 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
1021 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
1022 | Metadata *ExtraData = nullptr, | ||||||||||||
1023 | DINodeArray Annotations = nullptr), | ||||||||||||
1024 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||||||||||
1025 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||||||||||
1026 | ExtraData, Annotations)) | ||||||||||||
1027 | |||||||||||||
1028 | TempDIDerivedType clone() const { return cloneImpl(); } | ||||||||||||
1029 | |||||||||||||
1030 | /// Get the base type this is derived from. | ||||||||||||
1031 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||||||||||
1032 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||||||||||
1033 | |||||||||||||
1034 | /// \returns The DWARF address space of the memory pointed to or referenced by | ||||||||||||
1035 | /// a pointer or reference type respectively. | ||||||||||||
1036 | std::optional<unsigned> getDWARFAddressSpace() const { | ||||||||||||
1037 | return DWARFAddressSpace; | ||||||||||||
1038 | } | ||||||||||||
1039 | |||||||||||||
1040 | /// Get extra data associated with this derived type. | ||||||||||||
1041 | /// | ||||||||||||
1042 | /// Class type for pointer-to-members, objective-c property node for ivars, | ||||||||||||
1043 | /// global constant wrapper for static members, or virtual base pointer offset | ||||||||||||
1044 | /// for inheritance. | ||||||||||||
1045 | /// | ||||||||||||
1046 | /// TODO: Separate out types that need this extra operand: pointer-to-member | ||||||||||||
1047 | /// types and member fields (static members and ivars). | ||||||||||||
1048 | Metadata *getExtraData() const { return getRawExtraData(); } | ||||||||||||
1049 | Metadata *getRawExtraData() const { return getOperand(4); } | ||||||||||||
1050 | |||||||||||||
1051 | /// Get annotations associated with this derived type. | ||||||||||||
1052 | DINodeArray getAnnotations() const { | ||||||||||||
1053 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
1054 | } | ||||||||||||
1055 | Metadata *getRawAnnotations() const { return getOperand(5); } | ||||||||||||
1056 | |||||||||||||
1057 | /// Get casted version of extra data. | ||||||||||||
1058 | /// @{ | ||||||||||||
1059 | DIType *getClassType() const; | ||||||||||||
1060 | |||||||||||||
1061 | DIObjCProperty *getObjCProperty() const { | ||||||||||||
1062 | return dyn_cast_or_null<DIObjCProperty>(getExtraData()); | ||||||||||||
1063 | } | ||||||||||||
1064 | |||||||||||||
1065 | uint32_t getVBPtrOffset() const; | ||||||||||||
1066 | |||||||||||||
1067 | Constant *getStorageOffsetInBits() const; | ||||||||||||
1068 | |||||||||||||
1069 | Constant *getConstant() const; | ||||||||||||
1070 | |||||||||||||
1071 | Constant *getDiscriminantValue() const; | ||||||||||||
1072 | /// @} | ||||||||||||
1073 | |||||||||||||
1074 | static bool classof(const Metadata *MD) { | ||||||||||||
1075 | return MD->getMetadataID() == DIDerivedTypeKind; | ||||||||||||
1076 | } | ||||||||||||
1077 | }; | ||||||||||||
1078 | |||||||||||||
1079 | /// Composite types. | ||||||||||||
1080 | /// | ||||||||||||
1081 | /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). | ||||||||||||
1082 | /// TODO: Create a custom, unrelated node for DW_TAG_array_type. | ||||||||||||
1083 | class DICompositeType : public DIType { | ||||||||||||
1084 | friend class LLVMContextImpl; | ||||||||||||
1085 | friend class MDNode; | ||||||||||||
1086 | |||||||||||||
1087 | unsigned RuntimeLang; | ||||||||||||
1088 | |||||||||||||
1089 | DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
1090 | unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, | ||||||||||||
1091 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
1092 | ArrayRef<Metadata *> Ops) | ||||||||||||
1093 | : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, | ||||||||||||
1094 | AlignInBits, OffsetInBits, Flags, Ops), | ||||||||||||
1095 | RuntimeLang(RuntimeLang) {} | ||||||||||||
1096 | ~DICompositeType() = default; | ||||||||||||
1097 | |||||||||||||
1098 | /// Change fields in place. | ||||||||||||
1099 | void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, | ||||||||||||
1100 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
1101 | DIFlags Flags) { | ||||||||||||
1102 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1102, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1103 | assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate")(static_cast <bool> (getRawIdentifier() && "Only ODR-uniqued nodes should mutate" ) ? void (0) : __assert_fail ("getRawIdentifier() && \"Only ODR-uniqued nodes should mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1103, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1104 | this->RuntimeLang = RuntimeLang; | ||||||||||||
1105 | DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||||||||||
1106 | } | ||||||||||||
1107 | |||||||||||||
1108 | static DICompositeType * | ||||||||||||
1109 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, | ||||||||||||
1110 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
1111 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
1112 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||||||||||
1113 | DITemplateParameterArray TemplateParams, StringRef Identifier, | ||||||||||||
1114 | DIDerivedType *Discriminator, Metadata *DataLocation, | ||||||||||||
1115 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||||||||||
1116 | DINodeArray Annotations, StorageType Storage, | ||||||||||||
1117 | bool ShouldCreate = true) { | ||||||||||||
1118 | return getImpl( | ||||||||||||
1119 | Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, | ||||||||||||
1120 | BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), | ||||||||||||
1121 | RuntimeLang, VTableHolder, TemplateParams.get(), | ||||||||||||
1122 | getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, | ||||||||||||
1123 | Associated, Allocated, Rank, Annotations.get(), Storage, ShouldCreate); | ||||||||||||
1124 | } | ||||||||||||
1125 | static DICompositeType * | ||||||||||||
1126 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||||||||||
1127 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||||||||||
1128 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
1129 | DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, | ||||||||||||
1130 | Metadata *VTableHolder, Metadata *TemplateParams, | ||||||||||||
1131 | MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, | ||||||||||||
1132 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||||||||||
1133 | Metadata *Annotations, StorageType Storage, bool ShouldCreate = true); | ||||||||||||
1134 | |||||||||||||
1135 | TempDICompositeType cloneImpl() const { | ||||||||||||
1136 | return getTemporary( | ||||||||||||
1137 | getContext(), getTag(), getName(), getFile(), getLine(), getScope(), | ||||||||||||
1138 | getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), | ||||||||||||
1139 | getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), | ||||||||||||
1140 | getTemplateParams(), getIdentifier(), getDiscriminator(), | ||||||||||||
1141 | getRawDataLocation(), getRawAssociated(), getRawAllocated(), | ||||||||||||
1142 | getRawRank(), getAnnotations()); | ||||||||||||
1143 | } | ||||||||||||
1144 | |||||||||||||
1145 | public: | ||||||||||||
1146 | DEFINE_MDNODE_GET( | ||||||||||||
1147 | DICompositeType, | ||||||||||||
1148 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
1149 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
1150 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
1151 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||||||||||
1152 | DITemplateParameterArray TemplateParams = nullptr, | ||||||||||||
1153 | StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, | ||||||||||||
1154 | Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, | ||||||||||||
1155 | Metadata *Allocated = nullptr, Metadata *Rank = nullptr, | ||||||||||||
1156 | DINodeArray Annotations = nullptr), | ||||||||||||
1157 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||||||||||
1158 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||||||||||
1159 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, | ||||||||||||
1160 | Annotations)) | ||||||||||||
1161 | DEFINE_MDNODE_GET( | ||||||||||||
1162 | DICompositeType, | ||||||||||||
1163 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, | ||||||||||||
1164 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, | ||||||||||||
1165 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
1166 | Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, | ||||||||||||
1167 | Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, | ||||||||||||
1168 | Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, | ||||||||||||
1169 | Metadata *Associated = nullptr, Metadata *Allocated = nullptr, | ||||||||||||
1170 | Metadata *Rank = nullptr, Metadata *Annotations = nullptr), | ||||||||||||
1171 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||||||||||
1172 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||||||||||
1173 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, | ||||||||||||
1174 | Annotations)) | ||||||||||||
1175 | |||||||||||||
1176 | TempDICompositeType clone() const { return cloneImpl(); } | ||||||||||||
1177 | |||||||||||||
1178 | /// Get a DICompositeType with the given ODR identifier. | ||||||||||||
1179 | /// | ||||||||||||
1180 | /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped | ||||||||||||
1181 | /// DICompositeType for the given ODR \c Identifier. If none exists, creates | ||||||||||||
1182 | /// a new node. | ||||||||||||
1183 | /// | ||||||||||||
1184 | /// Else, returns \c nullptr. | ||||||||||||
1185 | static DICompositeType * | ||||||||||||
1186 | getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||||||||||
1187 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||||||||||
1188 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
1189 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||||||||||
1190 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||||||||||
1191 | Metadata *TemplateParams, Metadata *Discriminator, | ||||||||||||
1192 | Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, | ||||||||||||
1193 | Metadata *Rank, Metadata *Annotations); | ||||||||||||
1194 | static DICompositeType *getODRTypeIfExists(LLVMContext &Context, | ||||||||||||
1195 | MDString &Identifier); | ||||||||||||
1196 | |||||||||||||
1197 | /// Build a DICompositeType with the given ODR identifier. | ||||||||||||
1198 | /// | ||||||||||||
1199 | /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If | ||||||||||||
1200 | /// it doesn't exist, creates a new one. If it does exist and \a | ||||||||||||
1201 | /// isForwardDecl(), and the new arguments would be a definition, mutates the | ||||||||||||
1202 | /// the type in place. In either case, returns the type. | ||||||||||||
1203 | /// | ||||||||||||
1204 | /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns | ||||||||||||
1205 | /// nullptr. | ||||||||||||
1206 | static DICompositeType * | ||||||||||||
1207 | buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||||||||||
1208 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||||||||||
1209 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
1210 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||||||||||
1211 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||||||||||
1212 | Metadata *TemplateParams, Metadata *Discriminator, | ||||||||||||
1213 | Metadata *DataLocation, Metadata *Associated, | ||||||||||||
1214 | Metadata *Allocated, Metadata *Rank, Metadata *Annotations); | ||||||||||||
1215 | |||||||||||||
1216 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||||||||||
1217 | DINodeArray getElements() const { | ||||||||||||
1218 | return cast_or_null<MDTuple>(getRawElements()); | ||||||||||||
1219 | } | ||||||||||||
1220 | DIType *getVTableHolder() const { | ||||||||||||
1221 | return cast_or_null<DIType>(getRawVTableHolder()); | ||||||||||||
1222 | } | ||||||||||||
1223 | DITemplateParameterArray getTemplateParams() const { | ||||||||||||
1224 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||||||||||
1225 | } | ||||||||||||
1226 | StringRef getIdentifier() const { return getStringOperand(7); } | ||||||||||||
1227 | unsigned getRuntimeLang() const { return RuntimeLang; } | ||||||||||||
1228 | |||||||||||||
1229 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||||||||||
1230 | Metadata *getRawElements() const { return getOperand(4); } | ||||||||||||
1231 | Metadata *getRawVTableHolder() const { return getOperand(5); } | ||||||||||||
1232 | Metadata *getRawTemplateParams() const { return getOperand(6); } | ||||||||||||
1233 | MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } | ||||||||||||
1234 | Metadata *getRawDiscriminator() const { return getOperand(8); } | ||||||||||||
1235 | DIDerivedType *getDiscriminator() const { | ||||||||||||
1236 | return getOperandAs<DIDerivedType>(8); | ||||||||||||
1237 | } | ||||||||||||
1238 | Metadata *getRawDataLocation() const { return getOperand(9); } | ||||||||||||
1239 | DIVariable *getDataLocation() const { | ||||||||||||
1240 | return dyn_cast_or_null<DIVariable>(getRawDataLocation()); | ||||||||||||
1241 | } | ||||||||||||
1242 | DIExpression *getDataLocationExp() const { | ||||||||||||
1243 | return dyn_cast_or_null<DIExpression>(getRawDataLocation()); | ||||||||||||
1244 | } | ||||||||||||
1245 | Metadata *getRawAssociated() const { return getOperand(10); } | ||||||||||||
1246 | DIVariable *getAssociated() const { | ||||||||||||
1247 | return dyn_cast_or_null<DIVariable>(getRawAssociated()); | ||||||||||||
1248 | } | ||||||||||||
1249 | DIExpression *getAssociatedExp() const { | ||||||||||||
1250 | return dyn_cast_or_null<DIExpression>(getRawAssociated()); | ||||||||||||
1251 | } | ||||||||||||
1252 | Metadata *getRawAllocated() const { return getOperand(11); } | ||||||||||||
1253 | DIVariable *getAllocated() const { | ||||||||||||
1254 | return dyn_cast_or_null<DIVariable>(getRawAllocated()); | ||||||||||||
1255 | } | ||||||||||||
1256 | DIExpression *getAllocatedExp() const { | ||||||||||||
1257 | return dyn_cast_or_null<DIExpression>(getRawAllocated()); | ||||||||||||
1258 | } | ||||||||||||
1259 | Metadata *getRawRank() const { return getOperand(12); } | ||||||||||||
1260 | ConstantInt *getRankConst() const { | ||||||||||||
1261 | if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawRank())) | ||||||||||||
1262 | return dyn_cast_or_null<ConstantInt>(MD->getValue()); | ||||||||||||
1263 | return nullptr; | ||||||||||||
1264 | } | ||||||||||||
1265 | DIExpression *getRankExp() const { | ||||||||||||
1266 | return dyn_cast_or_null<DIExpression>(getRawRank()); | ||||||||||||
1267 | } | ||||||||||||
1268 | |||||||||||||
1269 | Metadata *getRawAnnotations() const { return getOperand(13); } | ||||||||||||
1270 | DINodeArray getAnnotations() const { | ||||||||||||
1271 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
1272 | } | ||||||||||||
1273 | |||||||||||||
1274 | /// Replace operands. | ||||||||||||
1275 | /// | ||||||||||||
1276 | /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision | ||||||||||||
1277 | /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track | ||||||||||||
1278 | /// of its movement if necessary. | ||||||||||||
1279 | /// @{ | ||||||||||||
1280 | void replaceElements(DINodeArray Elements) { | ||||||||||||
1281 | #ifndef NDEBUG | ||||||||||||
1282 | for (DINode *Op : getElements()) | ||||||||||||
1283 | assert(is_contained(Elements->operands(), Op) &&(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a member during member list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a member during member list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1284, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
1284 | "Lost a member during member list replacement")(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a member during member list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a member during member list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1284, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1285 | #endif | ||||||||||||
1286 | replaceOperandWith(4, Elements.get()); | ||||||||||||
1287 | } | ||||||||||||
1288 | |||||||||||||
1289 | void replaceVTableHolder(DIType *VTableHolder) { | ||||||||||||
1290 | replaceOperandWith(5, VTableHolder); | ||||||||||||
1291 | } | ||||||||||||
1292 | |||||||||||||
1293 | void replaceTemplateParams(DITemplateParameterArray TemplateParams) { | ||||||||||||
1294 | replaceOperandWith(6, TemplateParams.get()); | ||||||||||||
1295 | } | ||||||||||||
1296 | /// @} | ||||||||||||
1297 | |||||||||||||
1298 | static bool classof(const Metadata *MD) { | ||||||||||||
1299 | return MD->getMetadataID() == DICompositeTypeKind; | ||||||||||||
1300 | } | ||||||||||||
1301 | }; | ||||||||||||
1302 | |||||||||||||
1303 | /// Type array for a subprogram. | ||||||||||||
1304 | /// | ||||||||||||
1305 | /// TODO: Fold the array of types in directly as operands. | ||||||||||||
1306 | class DISubroutineType : public DIType { | ||||||||||||
1307 | friend class LLVMContextImpl; | ||||||||||||
1308 | friend class MDNode; | ||||||||||||
1309 | |||||||||||||
1310 | /// The calling convention used with DW_AT_calling_convention. Actually of | ||||||||||||
1311 | /// type dwarf::CallingConvention. | ||||||||||||
1312 | uint8_t CC; | ||||||||||||
1313 | |||||||||||||
1314 | DISubroutineType(LLVMContext &C, StorageType Storage, DIFlags Flags, | ||||||||||||
1315 | uint8_t CC, ArrayRef<Metadata *> Ops); | ||||||||||||
1316 | ~DISubroutineType() = default; | ||||||||||||
1317 | |||||||||||||
1318 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||||||||||
1319 | uint8_t CC, DITypeRefArray TypeArray, | ||||||||||||
1320 | StorageType Storage, | ||||||||||||
1321 | bool ShouldCreate = true) { | ||||||||||||
1322 | return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); | ||||||||||||
1323 | } | ||||||||||||
1324 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||||||||||
1325 | uint8_t CC, Metadata *TypeArray, | ||||||||||||
1326 | StorageType Storage, | ||||||||||||
1327 | bool ShouldCreate = true); | ||||||||||||
1328 | |||||||||||||
1329 | TempDISubroutineType cloneImpl() const { | ||||||||||||
1330 | return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); | ||||||||||||
1331 | } | ||||||||||||
1332 | |||||||||||||
1333 | public: | ||||||||||||
1334 | DEFINE_MDNODE_GET(DISubroutineType, | ||||||||||||
1335 | (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), | ||||||||||||
1336 | (Flags, CC, TypeArray)) | ||||||||||||
1337 | DEFINE_MDNODE_GET(DISubroutineType, | ||||||||||||
1338 | (DIFlags Flags, uint8_t CC, Metadata *TypeArray), | ||||||||||||
1339 | (Flags, CC, TypeArray)) | ||||||||||||
1340 | |||||||||||||
1341 | TempDISubroutineType clone() const { return cloneImpl(); } | ||||||||||||
1342 | // Returns a new temporary DISubroutineType with updated CC | ||||||||||||
1343 | TempDISubroutineType cloneWithCC(uint8_t CC) const { | ||||||||||||
1344 | auto NewTy = clone(); | ||||||||||||
1345 | NewTy->CC = CC; | ||||||||||||
1346 | return NewTy; | ||||||||||||
1347 | } | ||||||||||||
1348 | |||||||||||||
1349 | uint8_t getCC() const { return CC; } | ||||||||||||
1350 | |||||||||||||
1351 | DITypeRefArray getTypeArray() const { | ||||||||||||
1352 | return cast_or_null<MDTuple>(getRawTypeArray()); | ||||||||||||
1353 | } | ||||||||||||
1354 | |||||||||||||
1355 | Metadata *getRawTypeArray() const { return getOperand(3); } | ||||||||||||
1356 | |||||||||||||
1357 | static bool classof(const Metadata *MD) { | ||||||||||||
1358 | return MD->getMetadataID() == DISubroutineTypeKind; | ||||||||||||
1359 | } | ||||||||||||
1360 | }; | ||||||||||||
1361 | |||||||||||||
1362 | /// Compile unit. | ||||||||||||
1363 | class DICompileUnit : public DIScope { | ||||||||||||
1364 | friend class LLVMContextImpl; | ||||||||||||
1365 | friend class MDNode; | ||||||||||||
1366 | |||||||||||||
1367 | public: | ||||||||||||
1368 | enum DebugEmissionKind : unsigned { | ||||||||||||
1369 | NoDebug = 0, | ||||||||||||
1370 | FullDebug, | ||||||||||||
1371 | LineTablesOnly, | ||||||||||||
1372 | DebugDirectivesOnly, | ||||||||||||
1373 | LastEmissionKind = DebugDirectivesOnly | ||||||||||||
1374 | }; | ||||||||||||
1375 | |||||||||||||
1376 | enum class DebugNameTableKind : unsigned { | ||||||||||||
1377 | Default = 0, | ||||||||||||
1378 | GNU = 1, | ||||||||||||
1379 | None = 2, | ||||||||||||
1380 | LastDebugNameTableKind = None | ||||||||||||
1381 | }; | ||||||||||||
1382 | |||||||||||||
1383 | static std::optional<DebugEmissionKind> getEmissionKind(StringRef Str); | ||||||||||||
1384 | static const char *emissionKindString(DebugEmissionKind EK); | ||||||||||||
1385 | static std::optional<DebugNameTableKind> getNameTableKind(StringRef Str); | ||||||||||||
1386 | static const char *nameTableKindString(DebugNameTableKind PK); | ||||||||||||
1387 | |||||||||||||
1388 | private: | ||||||||||||
1389 | unsigned SourceLanguage; | ||||||||||||
1390 | bool IsOptimized; | ||||||||||||
1391 | unsigned RuntimeVersion; | ||||||||||||
1392 | unsigned EmissionKind; | ||||||||||||
1393 | uint64_t DWOId; | ||||||||||||
1394 | bool SplitDebugInlining; | ||||||||||||
1395 | bool DebugInfoForProfiling; | ||||||||||||
1396 | unsigned NameTableKind; | ||||||||||||
1397 | bool RangesBaseAddress; | ||||||||||||
1398 | |||||||||||||
1399 | DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, | ||||||||||||
1400 | bool IsOptimized, unsigned RuntimeVersion, | ||||||||||||
1401 | unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, | ||||||||||||
1402 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||||||||||
1403 | bool RangesBaseAddress, ArrayRef<Metadata *> Ops); | ||||||||||||
1404 | ~DICompileUnit() = default; | ||||||||||||
1405 | |||||||||||||
1406 | static DICompileUnit * | ||||||||||||
1407 | getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, | ||||||||||||
1408 | StringRef Producer, bool IsOptimized, StringRef Flags, | ||||||||||||
1409 | unsigned RuntimeVersion, StringRef SplitDebugFilename, | ||||||||||||
1410 | unsigned EmissionKind, DICompositeTypeArray EnumTypes, | ||||||||||||
1411 | DIScopeArray RetainedTypes, | ||||||||||||
1412 | DIGlobalVariableExpressionArray GlobalVariables, | ||||||||||||
1413 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, | ||||||||||||
1414 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, | ||||||||||||
1415 | unsigned NameTableKind, bool RangesBaseAddress, StringRef SysRoot, | ||||||||||||
1416 | StringRef SDK, StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
1417 | return getImpl( | ||||||||||||
1418 | Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), | ||||||||||||
1419 | IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, | ||||||||||||
1420 | getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, | ||||||||||||
1421 | EnumTypes.get(), RetainedTypes.get(), GlobalVariables.get(), | ||||||||||||
1422 | ImportedEntities.get(), Macros.get(), DWOId, SplitDebugInlining, | ||||||||||||
1423 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, | ||||||||||||
1424 | getCanonicalMDString(Context, SysRoot), | ||||||||||||
1425 | getCanonicalMDString(Context, SDK), Storage, ShouldCreate); | ||||||||||||
1426 | } | ||||||||||||
1427 | static DICompileUnit * | ||||||||||||
1428 | getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, | ||||||||||||
1429 | MDString *Producer, bool IsOptimized, MDString *Flags, | ||||||||||||
1430 | unsigned RuntimeVersion, MDString *SplitDebugFilename, | ||||||||||||
1431 | unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, | ||||||||||||
1432 | Metadata *GlobalVariables, Metadata *ImportedEntities, | ||||||||||||
1433 | Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, | ||||||||||||
1434 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||||||||||
1435 | bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, | ||||||||||||
1436 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
1437 | |||||||||||||
1438 | TempDICompileUnit cloneImpl() const { | ||||||||||||
1439 | return getTemporary( | ||||||||||||
1440 | getContext(), getSourceLanguage(), getFile(), getProducer(), | ||||||||||||
1441 | isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), | ||||||||||||
1442 | getEmissionKind(), getEnumTypes(), getRetainedTypes(), | ||||||||||||
1443 | getGlobalVariables(), getImportedEntities(), getMacros(), DWOId, | ||||||||||||
1444 | getSplitDebugInlining(), getDebugInfoForProfiling(), getNameTableKind(), | ||||||||||||
1445 | getRangesBaseAddress(), getSysRoot(), getSDK()); | ||||||||||||
1446 | } | ||||||||||||
1447 | |||||||||||||
1448 | public: | ||||||||||||
1449 | static void get() = delete; | ||||||||||||
1450 | static void getIfExists() = delete; | ||||||||||||
1451 | |||||||||||||
1452 | 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 )); } | ||||||||||||
1453 | 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 )); } | ||||||||||||
1454 | (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 )); } | ||||||||||||
1455 | 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 )); } | ||||||||||||
1456 | 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 )); } | ||||||||||||
1457 | 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 )); } | ||||||||||||
1458 | 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 )); } | ||||||||||||
1459 | 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 )); } | ||||||||||||
1460 | 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 )); } | ||||||||||||
1461 | 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 )); } | ||||||||||||
1462 | 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 )); } | ||||||||||||
1463 | (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 )); } | ||||||||||||
1464 | 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 )); } | ||||||||||||
1465 | 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 )); } | ||||||||||||
1466 | 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 )); } | ||||||||||||
1467 | 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 )); } | ||||||||||||
1468 | 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)); } | ||||||||||||
1469 | 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)); } | ||||||||||||
1470 | (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)); } | ||||||||||||
1471 | 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)); } | ||||||||||||
1472 | 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)); } | ||||||||||||
1473 | 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)); } | ||||||||||||
1474 | 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)); } | ||||||||||||
1475 | 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)); } | ||||||||||||
1476 | 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)); } | ||||||||||||
1477 | 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)); } | ||||||||||||
1478 | (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)); } | ||||||||||||
1479 | 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)); } | ||||||||||||
1480 | 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)); } | ||||||||||||
1481 | 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)); } | ||||||||||||
1482 | |||||||||||||
1483 | TempDICompileUnit clone() const { return cloneImpl(); } | ||||||||||||
1484 | |||||||||||||
1485 | unsigned getSourceLanguage() const { return SourceLanguage; } | ||||||||||||
1486 | bool isOptimized() const { return IsOptimized; } | ||||||||||||
1487 | unsigned getRuntimeVersion() const { return RuntimeVersion; } | ||||||||||||
1488 | DebugEmissionKind getEmissionKind() const { | ||||||||||||
1489 | return (DebugEmissionKind)EmissionKind; | ||||||||||||
1490 | } | ||||||||||||
1491 | bool isDebugDirectivesOnly() const { | ||||||||||||
1492 | return EmissionKind == DebugDirectivesOnly; | ||||||||||||
1493 | } | ||||||||||||
1494 | bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; } | ||||||||||||
1495 | DebugNameTableKind getNameTableKind() const { | ||||||||||||
1496 | return (DebugNameTableKind)NameTableKind; | ||||||||||||
1497 | } | ||||||||||||
1498 | bool getRangesBaseAddress() const { return RangesBaseAddress; } | ||||||||||||
1499 | StringRef getProducer() const { return getStringOperand(1); } | ||||||||||||
1500 | StringRef getFlags() const { return getStringOperand(2); } | ||||||||||||
1501 | StringRef getSplitDebugFilename() const { return getStringOperand(3); } | ||||||||||||
1502 | DICompositeTypeArray getEnumTypes() const { | ||||||||||||
1503 | return cast_or_null<MDTuple>(getRawEnumTypes()); | ||||||||||||
1504 | } | ||||||||||||
1505 | DIScopeArray getRetainedTypes() const { | ||||||||||||
1506 | return cast_or_null<MDTuple>(getRawRetainedTypes()); | ||||||||||||
1507 | } | ||||||||||||
1508 | DIGlobalVariableExpressionArray getGlobalVariables() const { | ||||||||||||
1509 | return cast_or_null<MDTuple>(getRawGlobalVariables()); | ||||||||||||
1510 | } | ||||||||||||
1511 | DIImportedEntityArray getImportedEntities() const { | ||||||||||||
1512 | return cast_or_null<MDTuple>(getRawImportedEntities()); | ||||||||||||
1513 | } | ||||||||||||
1514 | DIMacroNodeArray getMacros() const { | ||||||||||||
1515 | return cast_or_null<MDTuple>(getRawMacros()); | ||||||||||||
1516 | } | ||||||||||||
1517 | uint64_t getDWOId() const { return DWOId; } | ||||||||||||
1518 | void setDWOId(uint64_t DwoId) { DWOId = DwoId; } | ||||||||||||
1519 | bool getSplitDebugInlining() const { return SplitDebugInlining; } | ||||||||||||
1520 | void setSplitDebugInlining(bool SplitDebugInlining) { | ||||||||||||
1521 | this->SplitDebugInlining = SplitDebugInlining; | ||||||||||||
1522 | } | ||||||||||||
1523 | StringRef getSysRoot() const { return getStringOperand(9); } | ||||||||||||
1524 | StringRef getSDK() const { return getStringOperand(10); } | ||||||||||||
1525 | |||||||||||||
1526 | MDString *getRawProducer() const { return getOperandAs<MDString>(1); } | ||||||||||||
1527 | MDString *getRawFlags() const { return getOperandAs<MDString>(2); } | ||||||||||||
1528 | MDString *getRawSplitDebugFilename() const { | ||||||||||||
1529 | return getOperandAs<MDString>(3); | ||||||||||||
1530 | } | ||||||||||||
1531 | Metadata *getRawEnumTypes() const { return getOperand(4); } | ||||||||||||
1532 | Metadata *getRawRetainedTypes() const { return getOperand(5); } | ||||||||||||
1533 | Metadata *getRawGlobalVariables() const { return getOperand(6); } | ||||||||||||
1534 | Metadata *getRawImportedEntities() const { return getOperand(7); } | ||||||||||||
1535 | Metadata *getRawMacros() const { return getOperand(8); } | ||||||||||||
1536 | MDString *getRawSysRoot() const { return getOperandAs<MDString>(9); } | ||||||||||||
1537 | MDString *getRawSDK() const { return getOperandAs<MDString>(10); } | ||||||||||||
1538 | |||||||||||||
1539 | /// Replace arrays. | ||||||||||||
1540 | /// | ||||||||||||
1541 | /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and | ||||||||||||
1542 | /// deleted on a uniquing collision. In practice, uniquing collisions on \a | ||||||||||||
1543 | /// DICompileUnit should be fairly rare. | ||||||||||||
1544 | /// @{ | ||||||||||||
1545 | void replaceEnumTypes(DICompositeTypeArray N) { | ||||||||||||
1546 | replaceOperandWith(4, N.get()); | ||||||||||||
1547 | } | ||||||||||||
1548 | void replaceRetainedTypes(DITypeArray N) { replaceOperandWith(5, N.get()); } | ||||||||||||
1549 | void replaceGlobalVariables(DIGlobalVariableExpressionArray N) { | ||||||||||||
1550 | replaceOperandWith(6, N.get()); | ||||||||||||
1551 | } | ||||||||||||
1552 | void replaceImportedEntities(DIImportedEntityArray N) { | ||||||||||||
1553 | replaceOperandWith(7, N.get()); | ||||||||||||
1554 | } | ||||||||||||
1555 | void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); } | ||||||||||||
1556 | /// @} | ||||||||||||
1557 | |||||||||||||
1558 | static bool classof(const Metadata *MD) { | ||||||||||||
1559 | return MD->getMetadataID() == DICompileUnitKind; | ||||||||||||
1560 | } | ||||||||||||
1561 | }; | ||||||||||||
1562 | |||||||||||||
1563 | /// A scope for locals. | ||||||||||||
1564 | /// | ||||||||||||
1565 | /// A legal scope for lexical blocks, local variables, and debug info | ||||||||||||
1566 | /// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a | ||||||||||||
1567 | /// DILexicalBlockFile. | ||||||||||||
1568 | class DILocalScope : public DIScope { | ||||||||||||
1569 | protected: | ||||||||||||
1570 | DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
1571 | ArrayRef<Metadata *> Ops) | ||||||||||||
1572 | : DIScope(C, ID, Storage, Tag, Ops) {} | ||||||||||||
1573 | ~DILocalScope() = default; | ||||||||||||
1574 | |||||||||||||
1575 | public: | ||||||||||||
1576 | /// Get the subprogram for this scope. | ||||||||||||
1577 | /// | ||||||||||||
1578 | /// Return this if it's an \a DISubprogram; otherwise, look up the scope | ||||||||||||
1579 | /// chain. | ||||||||||||
1580 | DISubprogram *getSubprogram() const; | ||||||||||||
1581 | |||||||||||||
1582 | /// Traverses the scope chain rooted at RootScope until it hits a Subprogram, | ||||||||||||
1583 | /// recreating the chain with "NewSP" instead. | ||||||||||||
1584 | static DILocalScope * | ||||||||||||
1585 | cloneScopeForSubprogram(DILocalScope &RootScope, DISubprogram &NewSP, | ||||||||||||
1586 | LLVMContext &Ctx, | ||||||||||||
1587 | DenseMap<const MDNode *, MDNode *> &Cache); | ||||||||||||
1588 | |||||||||||||
1589 | /// Get the first non DILexicalBlockFile scope of this scope. | ||||||||||||
1590 | /// | ||||||||||||
1591 | /// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the | ||||||||||||
1592 | /// scope chain. | ||||||||||||
1593 | DILocalScope *getNonLexicalBlockFileScope() const; | ||||||||||||
1594 | |||||||||||||
1595 | static bool classof(const Metadata *MD) { | ||||||||||||
1596 | return MD->getMetadataID() == DISubprogramKind || | ||||||||||||
1597 | MD->getMetadataID() == DILexicalBlockKind || | ||||||||||||
1598 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||||||||||
1599 | } | ||||||||||||
1600 | }; | ||||||||||||
1601 | |||||||||||||
1602 | /// Subprogram description. | ||||||||||||
1603 | class DISubprogram : public DILocalScope { | ||||||||||||
1604 | friend class LLVMContextImpl; | ||||||||||||
1605 | friend class MDNode; | ||||||||||||
1606 | |||||||||||||
1607 | unsigned Line; | ||||||||||||
1608 | unsigned ScopeLine; | ||||||||||||
1609 | unsigned VirtualIndex; | ||||||||||||
1610 | |||||||||||||
1611 | /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue | ||||||||||||
1612 | /// of method overrides from secondary bases by this amount. It may be | ||||||||||||
1613 | /// negative. | ||||||||||||
1614 | int ThisAdjustment; | ||||||||||||
1615 | |||||||||||||
1616 | public: | ||||||||||||
1617 | /// Debug info subprogram flags. | ||||||||||||
1618 | enum DISPFlags : uint32_t { | ||||||||||||
1619 | #define HANDLE_DISP_FLAG(ID, NAME) SPFlag##NAME = ID, | ||||||||||||
1620 | #define DISP_FLAG_LARGEST_NEEDED | ||||||||||||
1621 | #include "llvm/IR/DebugInfoFlags.def" | ||||||||||||
1622 | SPFlagNonvirtual = SPFlagZero, | ||||||||||||
1623 | SPFlagVirtuality = SPFlagVirtual | SPFlagPureVirtual, | ||||||||||||
1624 | LLVM_MARK_AS_BITMASK_ENUM(SPFlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = SPFlagLargest | ||||||||||||
1625 | }; | ||||||||||||
1626 | |||||||||||||
1627 | static DISPFlags getFlag(StringRef Flag); | ||||||||||||
1628 | static StringRef getFlagString(DISPFlags Flag); | ||||||||||||
1629 | |||||||||||||
1630 | /// Split up a flags bitfield for easier printing. | ||||||||||||
1631 | /// | ||||||||||||
1632 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||||||||||
1633 | /// any remaining (unrecognized) bits. | ||||||||||||
1634 | static DISPFlags splitFlags(DISPFlags Flags, | ||||||||||||
1635 | SmallVectorImpl<DISPFlags> &SplitFlags); | ||||||||||||
1636 | |||||||||||||
1637 | // Helper for converting old bitfields to new flags word. | ||||||||||||
1638 | static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
1639 | bool IsOptimized, | ||||||||||||
1640 | unsigned Virtuality = SPFlagNonvirtual, | ||||||||||||
1641 | bool IsMainSubprogram = false); | ||||||||||||
1642 | |||||||||||||
1643 | private: | ||||||||||||
1644 | DIFlags Flags; | ||||||||||||
1645 | DISPFlags SPFlags; | ||||||||||||
1646 | |||||||||||||
1647 | DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
1648 | unsigned ScopeLine, unsigned VirtualIndex, int ThisAdjustment, | ||||||||||||
1649 | DIFlags Flags, DISPFlags SPFlags, ArrayRef<Metadata *> Ops); | ||||||||||||
1650 | ~DISubprogram() = default; | ||||||||||||
1651 | |||||||||||||
1652 | static DISubprogram * | ||||||||||||
1653 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||||||||||
1654 | StringRef LinkageName, DIFile *File, unsigned Line, | ||||||||||||
1655 | DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, | ||||||||||||
1656 | unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, | ||||||||||||
1657 | DISPFlags SPFlags, DICompileUnit *Unit, | ||||||||||||
1658 | DITemplateParameterArray TemplateParams, DISubprogram *Declaration, | ||||||||||||
1659 | DINodeArray RetainedNodes, DITypeArray ThrownTypes, | ||||||||||||
1660 | DINodeArray Annotations, StringRef TargetFuncName, | ||||||||||||
1661 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
1662 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
1663 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||||||||||
1664 | ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, | ||||||||||||
1665 | Flags, SPFlags, Unit, TemplateParams.get(), Declaration, | ||||||||||||
1666 | RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), | ||||||||||||
1667 | getCanonicalMDString(Context, TargetFuncName), | ||||||||||||
1668 | Storage, ShouldCreate); | ||||||||||||
1669 | } | ||||||||||||
1670 | static DISubprogram * | ||||||||||||
1671 | getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||||||||||
1672 | MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, | ||||||||||||
1673 | unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, | ||||||||||||
1674 | int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||||||||||
1675 | Metadata *TemplateParams, Metadata *Declaration, | ||||||||||||
1676 | Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, | ||||||||||||
1677 | MDString *TargetFuncName, StorageType Storage, | ||||||||||||
1678 | bool ShouldCreate = true); | ||||||||||||
1679 | |||||||||||||
1680 | TempDISubprogram cloneImpl() const { | ||||||||||||
1681 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||||||||||
1682 | getFile(), getLine(), getType(), getScopeLine(), | ||||||||||||
1683 | getContainingType(), getVirtualIndex(), | ||||||||||||
1684 | getThisAdjustment(), getFlags(), getSPFlags(), | ||||||||||||
1685 | getUnit(), getTemplateParams(), getDeclaration(), | ||||||||||||
1686 | getRetainedNodes(), getThrownTypes(), getAnnotations(), | ||||||||||||
1687 | getTargetFuncName()); | ||||||||||||
1688 | } | ||||||||||||
1689 | |||||||||||||
1690 | public: | ||||||||||||
1691 | DEFINE_MDNODE_GET( | ||||||||||||
1692 | DISubprogram, | ||||||||||||
1693 | (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, | ||||||||||||
1694 | unsigned Line, DISubroutineType *Type, unsigned ScopeLine, | ||||||||||||
1695 | DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||||||||||
1696 | DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, | ||||||||||||
1697 | DITemplateParameterArray TemplateParams = nullptr, | ||||||||||||
1698 | DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, | ||||||||||||
1699 | DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr, | ||||||||||||
1700 | StringRef TargetFuncName = ""), | ||||||||||||
1701 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||||||||||
1702 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||||||||||
1703 | Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName)) | ||||||||||||
1704 | |||||||||||||
1705 | DEFINE_MDNODE_GET( | ||||||||||||
1706 | DISubprogram, | ||||||||||||
1707 | (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, | ||||||||||||
1708 | unsigned Line, Metadata *Type, unsigned ScopeLine, | ||||||||||||
1709 | Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||||||||||
1710 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||||||||||
1711 | Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, | ||||||||||||
1712 | Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr, | ||||||||||||
1713 | Metadata *Annotations = nullptr, MDString *TargetFuncName = nullptr), | ||||||||||||
1714 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||||||||||
1715 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||||||||||
1716 | Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName)) | ||||||||||||
1717 | |||||||||||||
1718 | TempDISubprogram clone() const { return cloneImpl(); } | ||||||||||||
1719 | |||||||||||||
1720 | /// Returns a new temporary DISubprogram with updated Flags | ||||||||||||
1721 | TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { | ||||||||||||
1722 | auto NewSP = clone(); | ||||||||||||
1723 | NewSP->Flags = NewFlags; | ||||||||||||
1724 | return NewSP; | ||||||||||||
1725 | } | ||||||||||||
1726 | |||||||||||||
1727 | public: | ||||||||||||
1728 | unsigned getLine() const { return Line; } | ||||||||||||
1729 | unsigned getVirtuality() const { return getSPFlags() & SPFlagVirtuality; } | ||||||||||||
1730 | unsigned getVirtualIndex() const { return VirtualIndex; } | ||||||||||||
1731 | int getThisAdjustment() const { return ThisAdjustment; } | ||||||||||||
1732 | unsigned getScopeLine() const { return ScopeLine; } | ||||||||||||
1733 | void setScopeLine(unsigned L) { | ||||||||||||
1734 | assert(isDistinct())(static_cast <bool> (isDistinct()) ? void (0) : __assert_fail ("isDistinct()", "llvm/include/llvm/IR/DebugInfoMetadata.h", 1734, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1735 | ScopeLine = L; | ||||||||||||
1736 | } | ||||||||||||
1737 | DIFlags getFlags() const { return Flags; } | ||||||||||||
1738 | DISPFlags getSPFlags() const { return SPFlags; } | ||||||||||||
1739 | bool isLocalToUnit() const { return getSPFlags() & SPFlagLocalToUnit; } | ||||||||||||
1740 | bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } | ||||||||||||
1741 | bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } | ||||||||||||
1742 | bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } | ||||||||||||
1743 | |||||||||||||
1744 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||||||||||
1745 | bool isPrivate() const { | ||||||||||||
1746 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||||||||||
1747 | } | ||||||||||||
1748 | bool isProtected() const { | ||||||||||||
1749 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||||||||||
1750 | } | ||||||||||||
1751 | bool isPublic() const { | ||||||||||||
1752 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||||||||||
1753 | } | ||||||||||||
1754 | bool isExplicit() const { return getFlags() & FlagExplicit; } | ||||||||||||
1755 | bool isPrototyped() const { return getFlags() & FlagPrototyped; } | ||||||||||||
1756 | bool areAllCallsDescribed() const { | ||||||||||||
1757 | return getFlags() & FlagAllCallsDescribed; | ||||||||||||
1758 | } | ||||||||||||
1759 | bool isPure() const { return getSPFlags() & SPFlagPure; } | ||||||||||||
1760 | bool isElemental() const { return getSPFlags() & SPFlagElemental; } | ||||||||||||
1761 | bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } | ||||||||||||
1762 | bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } | ||||||||||||
1763 | |||||||||||||
1764 | /// Check if this is deleted member function. | ||||||||||||
1765 | /// | ||||||||||||
1766 | /// Return true if this subprogram is a C++11 special | ||||||||||||
1767 | /// member function declared deleted. | ||||||||||||
1768 | bool isDeleted() const { return getSPFlags() & SPFlagDeleted; } | ||||||||||||
1769 | |||||||||||||
1770 | /// Check if this is reference-qualified. | ||||||||||||
1771 | /// | ||||||||||||
1772 | /// Return true if this subprogram is a C++11 reference-qualified non-static | ||||||||||||
1773 | /// member function (void foo() &). | ||||||||||||
1774 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||||||||||
1775 | |||||||||||||
1776 | /// Check if this is rvalue-reference-qualified. | ||||||||||||
1777 | /// | ||||||||||||
1778 | /// Return true if this subprogram is a C++11 rvalue-reference-qualified | ||||||||||||
1779 | /// non-static member function (void foo() &&). | ||||||||||||
1780 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||||||||||
1781 | |||||||||||||
1782 | /// Check if this is marked as noreturn. | ||||||||||||
1783 | /// | ||||||||||||
1784 | /// Return true if this subprogram is C++11 noreturn or C11 _Noreturn | ||||||||||||
1785 | bool isNoReturn() const { return getFlags() & FlagNoReturn; } | ||||||||||||
1786 | |||||||||||||
1787 | // Check if this routine is a compiler-generated thunk. | ||||||||||||
1788 | // | ||||||||||||
1789 | // Returns true if this subprogram is a thunk generated by the compiler. | ||||||||||||
1790 | bool isThunk() const { return getFlags() & FlagThunk; } | ||||||||||||
1791 | |||||||||||||
1792 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
1793 | |||||||||||||
1794 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
1795 | StringRef getLinkageName() const { return getStringOperand(3); } | ||||||||||||
1796 | /// Only used by clients of CloneFunction, and only right after the cloning. | ||||||||||||
1797 | void replaceLinkageName(MDString *LN) { replaceOperandWith(3, LN); } | ||||||||||||
1798 | |||||||||||||
1799 | DISubroutineType *getType() const { | ||||||||||||
1800 | return cast_or_null<DISubroutineType>(getRawType()); | ||||||||||||
1801 | } | ||||||||||||
1802 | DIType *getContainingType() const { | ||||||||||||
1803 | return cast_or_null<DIType>(getRawContainingType()); | ||||||||||||
1804 | } | ||||||||||||
1805 | void replaceType(DISubroutineType *Ty) { | ||||||||||||
1806 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1806, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1807 | replaceOperandWith(4, Ty); | ||||||||||||
1808 | } | ||||||||||||
1809 | |||||||||||||
1810 | DICompileUnit *getUnit() const { | ||||||||||||
1811 | return cast_or_null<DICompileUnit>(getRawUnit()); | ||||||||||||
1812 | } | ||||||||||||
1813 | void replaceUnit(DICompileUnit *CU) { replaceOperandWith(5, CU); } | ||||||||||||
1814 | DITemplateParameterArray getTemplateParams() const { | ||||||||||||
1815 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||||||||||
1816 | } | ||||||||||||
1817 | DISubprogram *getDeclaration() const { | ||||||||||||
1818 | return cast_or_null<DISubprogram>(getRawDeclaration()); | ||||||||||||
1819 | } | ||||||||||||
1820 | DINodeArray getRetainedNodes() const { | ||||||||||||
1821 | return cast_or_null<MDTuple>(getRawRetainedNodes()); | ||||||||||||
1822 | } | ||||||||||||
1823 | DITypeArray getThrownTypes() const { | ||||||||||||
1824 | return cast_or_null<MDTuple>(getRawThrownTypes()); | ||||||||||||
1825 | } | ||||||||||||
1826 | DINodeArray getAnnotations() const { | ||||||||||||
1827 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
1828 | } | ||||||||||||
1829 | StringRef getTargetFuncName() const { | ||||||||||||
1830 | return (getRawTargetFuncName()) ? getStringOperand(12) : StringRef(); | ||||||||||||
1831 | } | ||||||||||||
1832 | |||||||||||||
1833 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
1834 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
1835 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(3); } | ||||||||||||
1836 | Metadata *getRawType() const { return getOperand(4); } | ||||||||||||
1837 | Metadata *getRawUnit() const { return getOperand(5); } | ||||||||||||
1838 | Metadata *getRawDeclaration() const { return getOperand(6); } | ||||||||||||
1839 | Metadata *getRawRetainedNodes() const { return getOperand(7); } | ||||||||||||
1840 | Metadata *getRawContainingType() const { | ||||||||||||
1841 | return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr; | ||||||||||||
1842 | } | ||||||||||||
1843 | Metadata *getRawTemplateParams() const { | ||||||||||||
1844 | return getNumOperands() > 9 ? getOperandAs<Metadata>(9) : nullptr; | ||||||||||||
1845 | } | ||||||||||||
1846 | Metadata *getRawThrownTypes() const { | ||||||||||||
1847 | return getNumOperands() > 10 ? getOperandAs<Metadata>(10) : nullptr; | ||||||||||||
1848 | } | ||||||||||||
1849 | Metadata *getRawAnnotations() const { | ||||||||||||
1850 | return getNumOperands() > 11 ? getOperandAs<Metadata>(11) : nullptr; | ||||||||||||
1851 | } | ||||||||||||
1852 | MDString *getRawTargetFuncName() const { | ||||||||||||
1853 | return getNumOperands() > 12 ? getOperandAs<MDString>(12) : nullptr; | ||||||||||||
1854 | } | ||||||||||||
1855 | |||||||||||||
1856 | void replaceRawLinkageName(MDString *LinkageName) { | ||||||||||||
1857 | replaceOperandWith(3, LinkageName); | ||||||||||||
1858 | } | ||||||||||||
1859 | |||||||||||||
1860 | /// Check if this subprogram describes the given function. | ||||||||||||
1861 | /// | ||||||||||||
1862 | /// FIXME: Should this be looking through bitcasts? | ||||||||||||
1863 | bool describes(const Function *F) const; | ||||||||||||
1864 | |||||||||||||
1865 | static bool classof(const Metadata *MD) { | ||||||||||||
1866 | return MD->getMetadataID() == DISubprogramKind; | ||||||||||||
1867 | } | ||||||||||||
1868 | }; | ||||||||||||
1869 | |||||||||||||
1870 | /// Debug location. | ||||||||||||
1871 | /// | ||||||||||||
1872 | /// A debug location in source code, used for debug info and otherwise. | ||||||||||||
1873 | class DILocation : public MDNode { | ||||||||||||
1874 | friend class LLVMContextImpl; | ||||||||||||
1875 | friend class MDNode; | ||||||||||||
1876 | |||||||||||||
1877 | DILocation(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
1878 | unsigned Column, ArrayRef<Metadata *> MDs, bool ImplicitCode); | ||||||||||||
1879 | ~DILocation() { dropAllReferences(); } | ||||||||||||
1880 | |||||||||||||
1881 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||||||||||
1882 | unsigned Column, Metadata *Scope, | ||||||||||||
1883 | Metadata *InlinedAt, bool ImplicitCode, | ||||||||||||
1884 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
1885 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||||||||||
1886 | unsigned Column, DILocalScope *Scope, | ||||||||||||
1887 | DILocation *InlinedAt, bool ImplicitCode, | ||||||||||||
1888 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
1889 | return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), | ||||||||||||
1890 | static_cast<Metadata *>(InlinedAt), ImplicitCode, Storage, | ||||||||||||
1891 | ShouldCreate); | ||||||||||||
1892 | } | ||||||||||||
1893 | |||||||||||||
1894 | TempDILocation cloneImpl() const { | ||||||||||||
1895 | // Get the raw scope/inlinedAt since it is possible to invoke this on | ||||||||||||
1896 | // a DILocation containing temporary metadata. | ||||||||||||
1897 | return getTemporary(getContext(), getLine(), getColumn(), getRawScope(), | ||||||||||||
1898 | getRawInlinedAt(), isImplicitCode()); | ||||||||||||
1899 | } | ||||||||||||
1900 | |||||||||||||
1901 | public: | ||||||||||||
1902 | // Disallow replacing operands. | ||||||||||||
1903 | void replaceOperandWith(unsigned I, Metadata *New) = delete; | ||||||||||||
1904 | |||||||||||||
1905 | DEFINE_MDNODE_GET(DILocation, | ||||||||||||
1906 | (unsigned Line, unsigned Column, Metadata *Scope, | ||||||||||||
1907 | Metadata *InlinedAt = nullptr, bool ImplicitCode = false), | ||||||||||||
1908 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||||||||||
1909 | DEFINE_MDNODE_GET(DILocation, | ||||||||||||
1910 | (unsigned Line, unsigned Column, DILocalScope *Scope, | ||||||||||||
1911 | DILocation *InlinedAt = nullptr, | ||||||||||||
1912 | bool ImplicitCode = false), | ||||||||||||
1913 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||||||||||
1914 | |||||||||||||
1915 | /// Return a (temporary) clone of this. | ||||||||||||
1916 | TempDILocation clone() const { return cloneImpl(); } | ||||||||||||
1917 | |||||||||||||
1918 | unsigned getLine() const { return SubclassData32; } | ||||||||||||
1919 | unsigned getColumn() const { return SubclassData16; } | ||||||||||||
1920 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||||||||||
1921 | |||||||||||||
1922 | /// Return the linkage name of Subprogram. If the linkage name is empty, | ||||||||||||
1923 | /// return scope name (the demangled name). | ||||||||||||
1924 | StringRef getSubprogramLinkageName() const { | ||||||||||||
1925 | DISubprogram *SP = getScope()->getSubprogram(); | ||||||||||||
1926 | if (!SP) | ||||||||||||
1927 | return ""; | ||||||||||||
1928 | auto Name = SP->getLinkageName(); | ||||||||||||
1929 | if (!Name.empty()) | ||||||||||||
1930 | return Name; | ||||||||||||
1931 | return SP->getName(); | ||||||||||||
1932 | } | ||||||||||||
1933 | |||||||||||||
1934 | DILocation *getInlinedAt() const { | ||||||||||||
1935 | return cast_or_null<DILocation>(getRawInlinedAt()); | ||||||||||||
1936 | } | ||||||||||||
1937 | |||||||||||||
1938 | /// Check if the location corresponds to an implicit code. | ||||||||||||
1939 | /// When the ImplicitCode flag is true, it means that the Instruction | ||||||||||||
1940 | /// with this DILocation has been added by the front-end but it hasn't been | ||||||||||||
1941 | /// written explicitly by the user (e.g. cleanup stuff in C++ put on a closing | ||||||||||||
1942 | /// bracket). It's useful for code coverage to not show a counter on "empty" | ||||||||||||
1943 | /// lines. | ||||||||||||
1944 | bool isImplicitCode() const { return SubclassData1; } | ||||||||||||
1945 | void setImplicitCode(bool ImplicitCode) { SubclassData1 = ImplicitCode; } | ||||||||||||
1946 | |||||||||||||
1947 | DIFile *getFile() const { return getScope()->getFile(); } | ||||||||||||
1948 | StringRef getFilename() const { return getScope()->getFilename(); } | ||||||||||||
1949 | StringRef getDirectory() const { return getScope()->getDirectory(); } | ||||||||||||
1950 | std::optional<StringRef> getSource() const { return getScope()->getSource(); } | ||||||||||||
1951 | |||||||||||||
1952 | /// Get the scope where this is inlined. | ||||||||||||
1953 | /// | ||||||||||||
1954 | /// Walk through \a getInlinedAt() and return \a getScope() from the deepest | ||||||||||||
1955 | /// location. | ||||||||||||
1956 | DILocalScope *getInlinedAtScope() const { | ||||||||||||
1957 | if (auto *IA
| ||||||||||||
1958 | return IA->getInlinedAtScope(); | ||||||||||||
1959 | return getScope(); | ||||||||||||
1960 | } | ||||||||||||
1961 | |||||||||||||
1962 | /// Get the DWARF discriminator. | ||||||||||||
1963 | /// | ||||||||||||
1964 | /// DWARF discriminators distinguish identical file locations between | ||||||||||||
1965 | /// instructions that are on different basic blocks. | ||||||||||||
1966 | /// | ||||||||||||
1967 | /// There are 3 components stored in discriminator, from lower bits: | ||||||||||||
1968 | /// | ||||||||||||
1969 | /// Base discriminator: assigned by AddDiscriminators pass to identify IRs | ||||||||||||
1970 | /// that are defined by the same source line, but | ||||||||||||
1971 | /// different basic blocks. | ||||||||||||
1972 | /// Duplication factor: assigned by optimizations that will scale down | ||||||||||||
1973 | /// the execution frequency of the original IR. | ||||||||||||
1974 | /// Copy Identifier: assigned by optimizations that clones the IR. | ||||||||||||
1975 | /// Each copy of the IR will be assigned an identifier. | ||||||||||||
1976 | /// | ||||||||||||
1977 | /// Encoding: | ||||||||||||
1978 | /// | ||||||||||||
1979 | /// The above 3 components are encoded into a 32bit unsigned integer in | ||||||||||||
1980 | /// order. If the lowest bit is 1, the current component is empty, and the | ||||||||||||
1981 | /// next component will start in the next bit. Otherwise, the current | ||||||||||||
1982 | /// component is non-empty, and its content starts in the next bit. The | ||||||||||||
1983 | /// value of each components is either 5 bit or 12 bit: if the 7th bit | ||||||||||||
1984 | /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the | ||||||||||||
1985 | /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to | ||||||||||||
1986 | /// represent the component. Thus, the number of bits used for a component | ||||||||||||
1987 | /// is either 0 (if it and all the next components are empty); 1 - if it is | ||||||||||||
1988 | /// empty; 7 - if its value is up to and including 0x1f (lsb and msb are both | ||||||||||||
1989 | /// 0); or 14, if its value is up to and including 0x1ff. Note that the last | ||||||||||||
1990 | /// component is also capped at 0x1ff, even in the case when both first | ||||||||||||
1991 | /// components are 0, and we'd technically have 29 bits available. | ||||||||||||
1992 | /// | ||||||||||||
1993 | /// For precise control over the data being encoded in the discriminator, | ||||||||||||
1994 | /// use encodeDiscriminator/decodeDiscriminator. | ||||||||||||
1995 | |||||||||||||
1996 | inline unsigned getDiscriminator() const; | ||||||||||||
1997 | |||||||||||||
1998 | // For the regular discriminator, it stands for all empty components if all | ||||||||||||
1999 | // the lowest 3 bits are non-zero and all higher 29 bits are unused(zero by | ||||||||||||
2000 | // default). Here we fully leverage the higher 29 bits for pseudo probe use. | ||||||||||||
2001 | // This is the format: | ||||||||||||
2002 | // [2:0] - 0x7 | ||||||||||||
2003 | // [31:3] - pseudo probe fields guaranteed to be non-zero as a whole | ||||||||||||
2004 | // So if the lower 3 bits is non-zero and the others has at least one | ||||||||||||
2005 | // non-zero bit, it guarantees to be a pseudo probe discriminator | ||||||||||||
2006 | inline static bool isPseudoProbeDiscriminator(unsigned Discriminator) { | ||||||||||||
2007 | return ((Discriminator & 0x7) == 0x7) && (Discriminator & 0xFFFFFFF8); | ||||||||||||
2008 | } | ||||||||||||
2009 | |||||||||||||
2010 | /// Returns a new DILocation with updated \p Discriminator. | ||||||||||||
2011 | inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const; | ||||||||||||
2012 | |||||||||||||
2013 | /// Returns a new DILocation with updated base discriminator \p BD. Only the | ||||||||||||
2014 | /// base discriminator is set in the new DILocation, the other encoded values | ||||||||||||
2015 | /// are elided. | ||||||||||||
2016 | /// If the discriminator cannot be encoded, the function returns std::nullopt. | ||||||||||||
2017 | inline std::optional<const DILocation *> | ||||||||||||
2018 | cloneWithBaseDiscriminator(unsigned BD) const; | ||||||||||||
2019 | |||||||||||||
2020 | /// Returns the duplication factor stored in the discriminator, or 1 if no | ||||||||||||
2021 | /// duplication factor (or 0) is encoded. | ||||||||||||
2022 | inline unsigned getDuplicationFactor() const; | ||||||||||||
2023 | |||||||||||||
2024 | /// Returns the copy identifier stored in the discriminator. | ||||||||||||
2025 | inline unsigned getCopyIdentifier() const; | ||||||||||||
2026 | |||||||||||||
2027 | /// Returns the base discriminator stored in the discriminator. | ||||||||||||
2028 | inline unsigned getBaseDiscriminator() const; | ||||||||||||
2029 | |||||||||||||
2030 | /// Returns a new DILocation with duplication factor \p DF * current | ||||||||||||
2031 | /// duplication factor encoded in the discriminator. The current duplication | ||||||||||||
2032 | /// factor is as defined by getDuplicationFactor(). | ||||||||||||
2033 | /// Returns std::nullopt if encoding failed. | ||||||||||||
2034 | inline std::optional<const DILocation *> | ||||||||||||
2035 | cloneByMultiplyingDuplicationFactor(unsigned DF) const; | ||||||||||||
2036 | |||||||||||||
2037 | /// When two instructions are combined into a single instruction we also | ||||||||||||
2038 | /// need to combine the original locations into a single location. | ||||||||||||
2039 | /// When the locations are the same we can use either location. | ||||||||||||
2040 | /// When they differ, we need a third location which is distinct from either. | ||||||||||||
2041 | /// If they share a common scope, use this scope and compare the line/column | ||||||||||||
2042 | /// pair of the locations with the common scope: | ||||||||||||
2043 | /// * if both match, keep the line and column; | ||||||||||||
2044 | /// * if only the line number matches, keep the line and set the column as 0; | ||||||||||||
2045 | /// * otherwise set line and column as 0. | ||||||||||||
2046 | /// If they do not share a common scope the location is ambiguous and can't be | ||||||||||||
2047 | /// represented in a line entry. In this case, set line and column as 0 and | ||||||||||||
2048 | /// use the scope of any location. | ||||||||||||
2049 | /// | ||||||||||||
2050 | /// \p LocA \p LocB: The locations to be merged. | ||||||||||||
2051 | static const DILocation *getMergedLocation(const DILocation *LocA, | ||||||||||||
2052 | const DILocation *LocB); | ||||||||||||
2053 | |||||||||||||
2054 | /// Try to combine the vector of locations passed as input in a single one. | ||||||||||||
2055 | /// This function applies getMergedLocation() repeatedly left-to-right. | ||||||||||||
2056 | /// | ||||||||||||
2057 | /// \p Locs: The locations to be merged. | ||||||||||||
2058 | static const DILocation * | ||||||||||||
2059 | getMergedLocations(ArrayRef<const DILocation *> Locs); | ||||||||||||
2060 | |||||||||||||
2061 | /// Return the masked discriminator value for an input discrimnator value D | ||||||||||||
2062 | /// (i.e. zero out the (B+1)-th and above bits for D (B is 0-base). | ||||||||||||
2063 | // Example: an input of (0x1FF, 7) returns 0xFF. | ||||||||||||
2064 | static unsigned getMaskedDiscriminator(unsigned D, unsigned B) { | ||||||||||||
2065 | return (D & getN1Bits(B)); | ||||||||||||
2066 | } | ||||||||||||
2067 | |||||||||||||
2068 | /// Return the bits used for base discriminators. | ||||||||||||
2069 | static unsigned getBaseDiscriminatorBits() { return getBaseFSBitEnd(); } | ||||||||||||
2070 | |||||||||||||
2071 | /// Returns the base discriminator for a given encoded discriminator \p D. | ||||||||||||
2072 | static unsigned | ||||||||||||
2073 | getBaseDiscriminatorFromDiscriminator(unsigned D, | ||||||||||||
2074 | bool IsFSDiscriminator = false) { | ||||||||||||
2075 | if (IsFSDiscriminator) | ||||||||||||
2076 | return getMaskedDiscriminator(D, getBaseDiscriminatorBits()); | ||||||||||||
2077 | return getUnsignedFromPrefixEncoding(D); | ||||||||||||
2078 | } | ||||||||||||
2079 | |||||||||||||
2080 | /// Raw encoding of the discriminator. APIs such as cloneWithDuplicationFactor | ||||||||||||
2081 | /// have certain special case behavior (e.g. treating empty duplication factor | ||||||||||||
2082 | /// as the value '1'). | ||||||||||||
2083 | /// This API, in conjunction with cloneWithDiscriminator, may be used to | ||||||||||||
2084 | /// encode the raw values provided. | ||||||||||||
2085 | /// | ||||||||||||
2086 | /// \p BD: base discriminator | ||||||||||||
2087 | /// \p DF: duplication factor | ||||||||||||
2088 | /// \p CI: copy index | ||||||||||||
2089 | /// | ||||||||||||
2090 | /// The return is std::nullopt if the values cannot be encoded in 32 bits - | ||||||||||||
2091 | /// for example, values for BD or DF larger than 12 bits. Otherwise, the | ||||||||||||
2092 | /// return is the encoded value. | ||||||||||||
2093 | static std::optional<unsigned> encodeDiscriminator(unsigned BD, unsigned DF, | ||||||||||||
2094 | unsigned CI); | ||||||||||||
2095 | |||||||||||||
2096 | /// Raw decoder for values in an encoded discriminator D. | ||||||||||||
2097 | static void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, | ||||||||||||
2098 | unsigned &CI); | ||||||||||||
2099 | |||||||||||||
2100 | /// Returns the duplication factor for a given encoded discriminator \p D, or | ||||||||||||
2101 | /// 1 if no value or 0 is encoded. | ||||||||||||
2102 | static unsigned getDuplicationFactorFromDiscriminator(unsigned D) { | ||||||||||||
2103 | if (EnableFSDiscriminator) | ||||||||||||
2104 | return 1; | ||||||||||||
2105 | D = getNextComponentInDiscriminator(D); | ||||||||||||
2106 | unsigned Ret = getUnsignedFromPrefixEncoding(D); | ||||||||||||
2107 | if (Ret == 0) | ||||||||||||
2108 | return 1; | ||||||||||||
2109 | return Ret; | ||||||||||||
2110 | } | ||||||||||||
2111 | |||||||||||||
2112 | /// Returns the copy identifier for a given encoded discriminator \p D. | ||||||||||||
2113 | static unsigned getCopyIdentifierFromDiscriminator(unsigned D) { | ||||||||||||
2114 | return getUnsignedFromPrefixEncoding( | ||||||||||||
2115 | getNextComponentInDiscriminator(getNextComponentInDiscriminator(D))); | ||||||||||||
2116 | } | ||||||||||||
2117 | |||||||||||||
2118 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
2119 | Metadata *getRawInlinedAt() const { | ||||||||||||
2120 | if (getNumOperands() == 2) | ||||||||||||
2121 | return getOperand(1); | ||||||||||||
2122 | return nullptr; | ||||||||||||
2123 | } | ||||||||||||
2124 | |||||||||||||
2125 | static bool classof(const Metadata *MD) { | ||||||||||||
2126 | return MD->getMetadataID() == DILocationKind; | ||||||||||||
2127 | } | ||||||||||||
2128 | }; | ||||||||||||
2129 | |||||||||||||
2130 | class DILexicalBlockBase : public DILocalScope { | ||||||||||||
2131 | protected: | ||||||||||||
2132 | DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, | ||||||||||||
2133 | ArrayRef<Metadata *> Ops); | ||||||||||||
2134 | ~DILexicalBlockBase() = default; | ||||||||||||
2135 | |||||||||||||
2136 | public: | ||||||||||||
2137 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||||||||||
2138 | |||||||||||||
2139 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
2140 | |||||||||||||
2141 | void replaceScope(DIScope *Scope) { | ||||||||||||
2142 | assert(!isUniqued())(static_cast <bool> (!isUniqued()) ? void (0) : __assert_fail ("!isUniqued()", "llvm/include/llvm/IR/DebugInfoMetadata.h", 2142, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2143 | setOperand(1, Scope); | ||||||||||||
2144 | } | ||||||||||||
2145 | |||||||||||||
2146 | static bool classof(const Metadata *MD) { | ||||||||||||
2147 | return MD->getMetadataID() == DILexicalBlockKind || | ||||||||||||
2148 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||||||||||
2149 | } | ||||||||||||
2150 | }; | ||||||||||||
2151 | |||||||||||||
2152 | class DILexicalBlock : public DILexicalBlockBase { | ||||||||||||
2153 | friend class LLVMContextImpl; | ||||||||||||
2154 | friend class MDNode; | ||||||||||||
2155 | |||||||||||||
2156 | unsigned Line; | ||||||||||||
2157 | uint16_t Column; | ||||||||||||
2158 | |||||||||||||
2159 | DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
2160 | unsigned Column, ArrayRef<Metadata *> Ops) | ||||||||||||
2161 | : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), | ||||||||||||
2162 | Column(Column) { | ||||||||||||
2163 | assert(Column < (1u << 16) && "Expected 16-bit column")(static_cast <bool> (Column < (1u << 16) && "Expected 16-bit column") ? void (0) : __assert_fail ("Column < (1u << 16) && \"Expected 16-bit column\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 2163, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2164 | } | ||||||||||||
2165 | ~DILexicalBlock() = default; | ||||||||||||
2166 | |||||||||||||
2167 | static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||||||||||
2168 | DIFile *File, unsigned Line, unsigned Column, | ||||||||||||
2169 | StorageType Storage, | ||||||||||||
2170 | bool ShouldCreate = true) { | ||||||||||||
2171 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||||||||||
2172 | static_cast<Metadata *>(File), Line, Column, Storage, | ||||||||||||
2173 | ShouldCreate); | ||||||||||||
2174 | } | ||||||||||||
2175 | |||||||||||||
2176 | static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
2177 | Metadata *File, unsigned Line, unsigned Column, | ||||||||||||
2178 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
2179 | |||||||||||||
2180 | TempDILexicalBlock cloneImpl() const { | ||||||||||||
2181 | return getTemporary(getContext(), getScope(), getFile(), getLine(), | ||||||||||||
2182 | getColumn()); | ||||||||||||
2183 | } | ||||||||||||
2184 | |||||||||||||
2185 | public: | ||||||||||||
2186 | DEFINE_MDNODE_GET(DILexicalBlock, | ||||||||||||
2187 | (DILocalScope * Scope, DIFile *File, unsigned Line, | ||||||||||||
2188 | unsigned Column), | ||||||||||||
2189 | (Scope, File, Line, Column)) | ||||||||||||
2190 | DEFINE_MDNODE_GET(DILexicalBlock, | ||||||||||||
2191 | (Metadata * Scope, Metadata *File, unsigned Line, | ||||||||||||
2192 | unsigned Column), | ||||||||||||
2193 | (Scope, File, Line, Column)) | ||||||||||||
2194 | |||||||||||||
2195 | TempDILexicalBlock clone() const { return cloneImpl(); } | ||||||||||||
2196 | |||||||||||||
2197 | unsigned getLine() const { return Line; } | ||||||||||||
2198 | unsigned getColumn() const { return Column; } | ||||||||||||
2199 | |||||||||||||
2200 | static bool classof(const Metadata *MD) { | ||||||||||||
2201 | return MD->getMetadataID() == DILexicalBlockKind; | ||||||||||||
2202 | } | ||||||||||||
2203 | }; | ||||||||||||
2204 | |||||||||||||
2205 | class DILexicalBlockFile : public DILexicalBlockBase { | ||||||||||||
2206 | friend class LLVMContextImpl; | ||||||||||||
2207 | friend class MDNode; | ||||||||||||
2208 | |||||||||||||
2209 | unsigned Discriminator; | ||||||||||||
2210 | |||||||||||||
2211 | DILexicalBlockFile(LLVMContext &C, StorageType Storage, | ||||||||||||
2212 | unsigned Discriminator, ArrayRef<Metadata *> Ops) | ||||||||||||
2213 | : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), | ||||||||||||
2214 | Discriminator(Discriminator) {} | ||||||||||||
2215 | ~DILexicalBlockFile() = default; | ||||||||||||
2216 | |||||||||||||
2217 | static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||||||||||
2218 | DIFile *File, unsigned Discriminator, | ||||||||||||
2219 | StorageType Storage, | ||||||||||||
2220 | bool ShouldCreate = true) { | ||||||||||||
2221 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||||||||||
2222 | static_cast<Metadata *>(File), Discriminator, Storage, | ||||||||||||
2223 | ShouldCreate); | ||||||||||||
2224 | } | ||||||||||||
2225 | |||||||||||||
2226 | static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
2227 | Metadata *File, unsigned Discriminator, | ||||||||||||
2228 | StorageType Storage, | ||||||||||||
2229 | bool ShouldCreate = true); | ||||||||||||
2230 | |||||||||||||
2231 | TempDILexicalBlockFile cloneImpl() const { | ||||||||||||
2232 | return getTemporary(getContext(), getScope(), getFile(), | ||||||||||||
2233 | getDiscriminator()); | ||||||||||||
2234 | } | ||||||||||||
2235 | |||||||||||||
2236 | public: | ||||||||||||
2237 | DEFINE_MDNODE_GET(DILexicalBlockFile, | ||||||||||||
2238 | (DILocalScope * Scope, DIFile *File, | ||||||||||||
2239 | unsigned Discriminator), | ||||||||||||
2240 | (Scope, File, Discriminator)) | ||||||||||||
2241 | DEFINE_MDNODE_GET(DILexicalBlockFile, | ||||||||||||
2242 | (Metadata * Scope, Metadata *File, unsigned Discriminator), | ||||||||||||
2243 | (Scope, File, Discriminator)) | ||||||||||||
2244 | |||||||||||||
2245 | TempDILexicalBlockFile clone() const { return cloneImpl(); } | ||||||||||||
2246 | unsigned getDiscriminator() const { return Discriminator; } | ||||||||||||
2247 | |||||||||||||
2248 | static bool classof(const Metadata *MD) { | ||||||||||||
2249 | return MD->getMetadataID() == DILexicalBlockFileKind; | ||||||||||||
2250 | } | ||||||||||||
2251 | }; | ||||||||||||
2252 | |||||||||||||
2253 | unsigned DILocation::getDiscriminator() const { | ||||||||||||
2254 | if (auto *F = dyn_cast<DILexicalBlockFile>(getScope())) | ||||||||||||
2255 | return F->getDiscriminator(); | ||||||||||||
2256 | return 0; | ||||||||||||
2257 | } | ||||||||||||
2258 | |||||||||||||
2259 | const DILocation * | ||||||||||||
2260 | DILocation::cloneWithDiscriminator(unsigned Discriminator) const { | ||||||||||||
2261 | DIScope *Scope = getScope(); | ||||||||||||
2262 | // Skip all parent DILexicalBlockFile that already have a discriminator | ||||||||||||
2263 | // assigned. We do not want to have nested DILexicalBlockFiles that have | ||||||||||||
2264 | // mutliple discriminators because only the leaf DILexicalBlockFile's | ||||||||||||
2265 | // dominator will be used. | ||||||||||||
2266 | for (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope); | ||||||||||||
2267 | LBF && LBF->getDiscriminator() != 0; | ||||||||||||
2268 | LBF = dyn_cast<DILexicalBlockFile>(Scope)) | ||||||||||||
2269 | Scope = LBF->getScope(); | ||||||||||||
2270 | DILexicalBlockFile *NewScope = | ||||||||||||
2271 | DILexicalBlockFile::get(getContext(), Scope, getFile(), Discriminator); | ||||||||||||
2272 | return DILocation::get(getContext(), getLine(), getColumn(), NewScope, | ||||||||||||
2273 | getInlinedAt()); | ||||||||||||
2274 | } | ||||||||||||
2275 | |||||||||||||
2276 | unsigned DILocation::getBaseDiscriminator() const { | ||||||||||||
2277 | return getBaseDiscriminatorFromDiscriminator(getDiscriminator(), | ||||||||||||
2278 | EnableFSDiscriminator); | ||||||||||||
2279 | } | ||||||||||||
2280 | |||||||||||||
2281 | unsigned DILocation::getDuplicationFactor() const { | ||||||||||||
2282 | return getDuplicationFactorFromDiscriminator(getDiscriminator()); | ||||||||||||
2283 | } | ||||||||||||
2284 | |||||||||||||
2285 | unsigned DILocation::getCopyIdentifier() const { | ||||||||||||
2286 | return getCopyIdentifierFromDiscriminator(getDiscriminator()); | ||||||||||||
2287 | } | ||||||||||||
2288 | |||||||||||||
2289 | std::optional<const DILocation *> | ||||||||||||
2290 | DILocation::cloneWithBaseDiscriminator(unsigned D) const { | ||||||||||||
2291 | unsigned BD, DF, CI; | ||||||||||||
2292 | |||||||||||||
2293 | if (EnableFSDiscriminator) { | ||||||||||||
2294 | BD = getBaseDiscriminator(); | ||||||||||||
2295 | if (D == BD) | ||||||||||||
2296 | return this; | ||||||||||||
2297 | return cloneWithDiscriminator(D); | ||||||||||||
2298 | } | ||||||||||||
2299 | |||||||||||||
2300 | decodeDiscriminator(getDiscriminator(), BD, DF, CI); | ||||||||||||
2301 | if (D == BD) | ||||||||||||
2302 | return this; | ||||||||||||
2303 | if (std::optional<unsigned> Encoded = encodeDiscriminator(D, DF, CI)) | ||||||||||||
2304 | return cloneWithDiscriminator(*Encoded); | ||||||||||||
2305 | return std::nullopt; | ||||||||||||
2306 | } | ||||||||||||
2307 | |||||||||||||
2308 | std::optional<const DILocation *> | ||||||||||||
2309 | DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const { | ||||||||||||
2310 | assert(!EnableFSDiscriminator && "FSDiscriminator should not call this.")(static_cast <bool> (!EnableFSDiscriminator && "FSDiscriminator should not call this." ) ? void (0) : __assert_fail ("!EnableFSDiscriminator && \"FSDiscriminator should not call this.\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 2310, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2311 | |||||||||||||
2312 | DF *= getDuplicationFactor(); | ||||||||||||
2313 | if (DF <= 1) | ||||||||||||
2314 | return this; | ||||||||||||
2315 | |||||||||||||
2316 | unsigned BD = getBaseDiscriminator(); | ||||||||||||
2317 | unsigned CI = getCopyIdentifier(); | ||||||||||||
2318 | if (std::optional<unsigned> D = encodeDiscriminator(BD, DF, CI)) | ||||||||||||
2319 | return cloneWithDiscriminator(*D); | ||||||||||||
2320 | return std::nullopt; | ||||||||||||
2321 | } | ||||||||||||
2322 | |||||||||||||
2323 | class DINamespace : public DIScope { | ||||||||||||
2324 | friend class LLVMContextImpl; | ||||||||||||
2325 | friend class MDNode; | ||||||||||||
2326 | |||||||||||||
2327 | unsigned ExportSymbols : 1; | ||||||||||||
2328 | |||||||||||||
2329 | DINamespace(LLVMContext &Context, StorageType Storage, bool ExportSymbols, | ||||||||||||
2330 | ArrayRef<Metadata *> Ops); | ||||||||||||
2331 | ~DINamespace() = default; | ||||||||||||
2332 | |||||||||||||
2333 | static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, | ||||||||||||
2334 | StringRef Name, bool ExportSymbols, | ||||||||||||
2335 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
2336 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
2337 | ExportSymbols, Storage, ShouldCreate); | ||||||||||||
2338 | } | ||||||||||||
2339 | static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
2340 | MDString *Name, bool ExportSymbols, | ||||||||||||
2341 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
2342 | |||||||||||||
2343 | TempDINamespace cloneImpl() const { | ||||||||||||
2344 | return getTemporary(getContext(), getScope(), getName(), | ||||||||||||
2345 | getExportSymbols()); | ||||||||||||
2346 | } | ||||||||||||
2347 | |||||||||||||
2348 | public: | ||||||||||||
2349 | DEFINE_MDNODE_GET(DINamespace, | ||||||||||||
2350 | (DIScope * Scope, StringRef Name, bool ExportSymbols), | ||||||||||||
2351 | (Scope, Name, ExportSymbols)) | ||||||||||||
2352 | DEFINE_MDNODE_GET(DINamespace, | ||||||||||||
2353 | (Metadata * Scope, MDString *Name, bool ExportSymbols), | ||||||||||||
2354 | (Scope, Name, ExportSymbols)) | ||||||||||||
2355 | |||||||||||||
2356 | TempDINamespace clone() const { return cloneImpl(); } | ||||||||||||
2357 | |||||||||||||
2358 | bool getExportSymbols() const { return ExportSymbols; } | ||||||||||||
2359 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
2360 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
2361 | |||||||||||||
2362 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
2363 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
2364 | |||||||||||||
2365 | static bool classof(const Metadata *MD) { | ||||||||||||
2366 | return MD->getMetadataID() == DINamespaceKind; | ||||||||||||
2367 | } | ||||||||||||
2368 | }; | ||||||||||||
2369 | |||||||||||||
2370 | /// Represents a module in the programming language, for example, a Clang | ||||||||||||
2371 | /// module, or a Fortran module. | ||||||||||||
2372 | class DIModule : public DIScope { | ||||||||||||
2373 | friend class LLVMContextImpl; | ||||||||||||
2374 | friend class MDNode; | ||||||||||||
2375 | unsigned LineNo; | ||||||||||||
2376 | bool IsDecl; | ||||||||||||
2377 | |||||||||||||
2378 | DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||||||||||
2379 | bool IsDecl, ArrayRef<Metadata *> Ops); | ||||||||||||
2380 | ~DIModule() = default; | ||||||||||||
2381 | |||||||||||||
2382 | static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope, | ||||||||||||
2383 | StringRef Name, StringRef ConfigurationMacros, | ||||||||||||
2384 | StringRef IncludePath, StringRef APINotesFile, | ||||||||||||
2385 | unsigned LineNo, bool IsDecl, StorageType Storage, | ||||||||||||
2386 | bool ShouldCreate = true) { | ||||||||||||
2387 | return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
2388 | getCanonicalMDString(Context, ConfigurationMacros), | ||||||||||||
2389 | getCanonicalMDString(Context, IncludePath), | ||||||||||||
2390 | getCanonicalMDString(Context, APINotesFile), LineNo, IsDecl, | ||||||||||||
2391 | Storage, ShouldCreate); | ||||||||||||
2392 | } | ||||||||||||
2393 | static DIModule *getImpl(LLVMContext &Context, Metadata *File, | ||||||||||||
2394 | Metadata *Scope, MDString *Name, | ||||||||||||
2395 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||||||||||
2396 | MDString *APINotesFile, unsigned LineNo, bool IsDecl, | ||||||||||||
2397 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
2398 | |||||||||||||
2399 | TempDIModule cloneImpl() const { | ||||||||||||
2400 | return getTemporary(getContext(), getFile(), getScope(), getName(), | ||||||||||||
2401 | getConfigurationMacros(), getIncludePath(), | ||||||||||||
2402 | getAPINotesFile(), getLineNo(), getIsDecl()); | ||||||||||||
2403 | } | ||||||||||||
2404 | |||||||||||||
2405 | public: | ||||||||||||
2406 | DEFINE_MDNODE_GET(DIModule, | ||||||||||||
2407 | (DIFile * File, DIScope *Scope, StringRef Name, | ||||||||||||
2408 | StringRef ConfigurationMacros, StringRef IncludePath, | ||||||||||||
2409 | StringRef APINotesFile, unsigned LineNo, | ||||||||||||
2410 | bool IsDecl = false), | ||||||||||||
2411 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||||||||||
2412 | APINotesFile, LineNo, IsDecl)) | ||||||||||||
2413 | DEFINE_MDNODE_GET(DIModule, | ||||||||||||
2414 | (Metadata * File, Metadata *Scope, MDString *Name, | ||||||||||||
2415 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||||||||||
2416 | MDString *APINotesFile, unsigned LineNo, | ||||||||||||
2417 | bool IsDecl = false), | ||||||||||||
2418 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||||||||||
2419 | APINotesFile, LineNo, IsDecl)) | ||||||||||||
2420 | |||||||||||||
2421 | TempDIModule clone() const { return cloneImpl(); } | ||||||||||||
2422 | |||||||||||||
2423 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
2424 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
2425 | StringRef getConfigurationMacros() const { return getStringOperand(3); } | ||||||||||||
2426 | StringRef getIncludePath() const { return getStringOperand(4); } | ||||||||||||
2427 | StringRef getAPINotesFile() const { return getStringOperand(5); } | ||||||||||||
2428 | unsigned getLineNo() const { return LineNo; } | ||||||||||||
2429 | bool getIsDecl() const { return IsDecl; } | ||||||||||||
2430 | |||||||||||||
2431 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
2432 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
2433 | MDString *getRawConfigurationMacros() const { | ||||||||||||
2434 | return getOperandAs<MDString>(3); | ||||||||||||
2435 | } | ||||||||||||
2436 | MDString *getRawIncludePath() const { return getOperandAs<MDString>(4); } | ||||||||||||
2437 | MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(5); } | ||||||||||||
2438 | |||||||||||||
2439 | static bool classof(const Metadata *MD) { | ||||||||||||
2440 | return MD->getMetadataID() == DIModuleKind; | ||||||||||||
2441 | } | ||||||||||||
2442 | }; | ||||||||||||
2443 | |||||||||||||
2444 | /// Base class for template parameters. | ||||||||||||
2445 | class DITemplateParameter : public DINode { | ||||||||||||
2446 | protected: | ||||||||||||
2447 | bool IsDefault; | ||||||||||||
2448 | |||||||||||||
2449 | DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, | ||||||||||||
2450 | unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops) | ||||||||||||
2451 | : DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {} | ||||||||||||
2452 | ~DITemplateParameter() = default; | ||||||||||||
2453 | |||||||||||||
2454 | public: | ||||||||||||
2455 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
2456 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||||||||||
2457 | |||||||||||||
2458 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
2459 | Metadata *getRawType() const { return getOperand(1); } | ||||||||||||
2460 | bool isDefault() const { return IsDefault; } | ||||||||||||
2461 | |||||||||||||
2462 | static bool classof(const Metadata *MD) { | ||||||||||||
2463 | return MD->getMetadataID() == DITemplateTypeParameterKind || | ||||||||||||
2464 | MD->getMetadataID() == DITemplateValueParameterKind; | ||||||||||||
2465 | } | ||||||||||||
2466 | }; | ||||||||||||
2467 | |||||||||||||
2468 | class DITemplateTypeParameter : public DITemplateParameter { | ||||||||||||
2469 | friend class LLVMContextImpl; | ||||||||||||
2470 | friend class MDNode; | ||||||||||||
2471 | |||||||||||||
2472 | DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, | ||||||||||||
2473 | bool IsDefault, ArrayRef<Metadata *> Ops); | ||||||||||||
2474 | ~DITemplateTypeParameter() = default; | ||||||||||||
2475 | |||||||||||||
2476 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, | ||||||||||||
2477 | DIType *Type, bool IsDefault, | ||||||||||||
2478 | StorageType Storage, | ||||||||||||
2479 | bool ShouldCreate = true) { | ||||||||||||
2480 | return getImpl(Context, getCanonicalMDString(Context, Name), Type, | ||||||||||||
2481 | IsDefault, Storage, ShouldCreate); | ||||||||||||
2482 | } | ||||||||||||
2483 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, | ||||||||||||
2484 | Metadata *Type, bool IsDefault, | ||||||||||||
2485 | StorageType Storage, | ||||||||||||
2486 | bool ShouldCreate = true); | ||||||||||||
2487 | |||||||||||||
2488 | TempDITemplateTypeParameter cloneImpl() const { | ||||||||||||
2489 | return getTemporary(getContext(), getName(), getType(), isDefault()); | ||||||||||||
2490 | } | ||||||||||||
2491 | |||||||||||||
2492 | public: | ||||||||||||
2493 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||||||||||
2494 | (StringRef Name, DIType *Type, bool IsDefault), | ||||||||||||
2495 | (Name, Type, IsDefault)) | ||||||||||||
2496 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||||||||||
2497 | (MDString * Name, Metadata *Type, bool IsDefault), | ||||||||||||
2498 | (Name, Type, IsDefault)) | ||||||||||||
2499 | |||||||||||||
2500 | TempDITemplateTypeParameter clone() const { return cloneImpl(); } | ||||||||||||
2501 | |||||||||||||
2502 | static bool classof(const Metadata *MD) { | ||||||||||||
2503 | return MD->getMetadataID() == DITemplateTypeParameterKind; | ||||||||||||
2504 | } | ||||||||||||
2505 | }; | ||||||||||||
2506 | |||||||||||||
2507 | class DITemplateValueParameter : public DITemplateParameter { | ||||||||||||
2508 | friend class LLVMContextImpl; | ||||||||||||
2509 | friend class MDNode; | ||||||||||||
2510 | |||||||||||||
2511 | DITemplateValueParameter(LLVMContext &Context, StorageType Storage, | ||||||||||||
2512 | unsigned Tag, bool IsDefault, | ||||||||||||
2513 | ArrayRef<Metadata *> Ops) | ||||||||||||
2514 | : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, | ||||||||||||
2515 | IsDefault, Ops) {} | ||||||||||||
2516 | ~DITemplateValueParameter() = default; | ||||||||||||
2517 | |||||||||||||
2518 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
2519 | StringRef Name, DIType *Type, | ||||||||||||
2520 | bool IsDefault, Metadata *Value, | ||||||||||||
2521 | StorageType Storage, | ||||||||||||
2522 | bool ShouldCreate = true) { | ||||||||||||
2523 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, | ||||||||||||
2524 | IsDefault, Value, Storage, ShouldCreate); | ||||||||||||
2525 | } | ||||||||||||
2526 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
2527 | MDString *Name, Metadata *Type, | ||||||||||||
2528 | bool IsDefault, Metadata *Value, | ||||||||||||
2529 | StorageType Storage, | ||||||||||||
2530 | bool ShouldCreate = true); | ||||||||||||
2531 | |||||||||||||
2532 | TempDITemplateValueParameter cloneImpl() const { | ||||||||||||
2533 | return getTemporary(getContext(), getTag(), getName(), getType(), | ||||||||||||
2534 | isDefault(), getValue()); | ||||||||||||
2535 | } | ||||||||||||
2536 | |||||||||||||
2537 | public: | ||||||||||||
2538 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||||||||||
2539 | (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault, | ||||||||||||
2540 | Metadata *Value), | ||||||||||||
2541 | (Tag, Name, Type, IsDefault, Value)) | ||||||||||||
2542 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||||||||||
2543 | (unsigned Tag, MDString *Name, Metadata *Type, | ||||||||||||
2544 | bool IsDefault, Metadata *Value), | ||||||||||||
2545 | (Tag, Name, Type, IsDefault, Value)) | ||||||||||||
2546 | |||||||||||||
2547 | TempDITemplateValueParameter clone() const { return cloneImpl(); } | ||||||||||||
2548 | |||||||||||||
2549 | Metadata *getValue() const { return getOperand(2); } | ||||||||||||
2550 | |||||||||||||
2551 | static bool classof(const Metadata *MD) { | ||||||||||||
2552 | return MD->getMetadataID() == DITemplateValueParameterKind; | ||||||||||||
2553 | } | ||||||||||||
2554 | }; | ||||||||||||
2555 | |||||||||||||
2556 | /// Base class for variables. | ||||||||||||
2557 | class DIVariable : public DINode { | ||||||||||||
2558 | unsigned Line; | ||||||||||||
2559 | uint32_t AlignInBits; | ||||||||||||
2560 | |||||||||||||
2561 | protected: | ||||||||||||
2562 | DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, signed Line, | ||||||||||||
2563 | ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0); | ||||||||||||
2564 | ~DIVariable() = default; | ||||||||||||
2565 | |||||||||||||
2566 | public: | ||||||||||||
2567 | unsigned getLine() const { return Line; } | ||||||||||||
2568 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
2569 | StringRef getName() const { return getStringOperand(1); } | ||||||||||||
2570 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
2571 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||||||||||
2572 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||||||||||
2573 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||||||||||
2574 | /// Determines the size of the variable's type. | ||||||||||||
2575 | std::optional<uint64_t> getSizeInBits() const; | ||||||||||||
2576 | |||||||||||||
2577 | /// Return the signedness of this variable's type, or std::nullopt if this | ||||||||||||
2578 | /// type is neither signed nor unsigned. | ||||||||||||
2579 | std::optional<DIBasicType::Signedness> getSignedness() const { | ||||||||||||
2580 | if (auto *BT = dyn_cast<DIBasicType>(getType())) | ||||||||||||
2581 | return BT->getSignedness(); | ||||||||||||
2582 | return std::nullopt; | ||||||||||||
2583 | } | ||||||||||||
2584 | |||||||||||||
2585 | StringRef getFilename() const { | ||||||||||||
2586 | if (auto *F = getFile()) | ||||||||||||
2587 | return F->getFilename(); | ||||||||||||
2588 | return ""; | ||||||||||||
2589 | } | ||||||||||||
2590 | |||||||||||||
2591 | StringRef getDirectory() const { | ||||||||||||
2592 | if (auto *F = getFile()) | ||||||||||||
2593 | return F->getDirectory(); | ||||||||||||
2594 | return ""; | ||||||||||||
2595 | } | ||||||||||||
2596 | |||||||||||||
2597 | std::optional<StringRef> getSource() const { | ||||||||||||
2598 | if (auto *F = getFile()) | ||||||||||||
2599 | return F->getSource(); | ||||||||||||
2600 | return std::nullopt; | ||||||||||||
2601 | } | ||||||||||||
2602 | |||||||||||||
2603 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
2604 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||||||||||
2605 | Metadata *getRawFile() const { return getOperand(2); } | ||||||||||||
2606 | Metadata *getRawType() const { return getOperand(3); } | ||||||||||||
2607 | |||||||||||||
2608 | static bool classof(const Metadata *MD) { | ||||||||||||
2609 | return MD->getMetadataID() == DILocalVariableKind || | ||||||||||||
2610 | MD->getMetadataID() == DIGlobalVariableKind; | ||||||||||||
2611 | } | ||||||||||||
2612 | }; | ||||||||||||
2613 | |||||||||||||
2614 | /// DWARF expression. | ||||||||||||
2615 | /// | ||||||||||||
2616 | /// This is (almost) a DWARF expression that modifies the location of a | ||||||||||||
2617 | /// variable, or the location of a single piece of a variable, or (when using | ||||||||||||
2618 | /// DW_OP_stack_value) is the constant variable value. | ||||||||||||
2619 | /// | ||||||||||||
2620 | /// TODO: Co-allocate the expression elements. | ||||||||||||
2621 | /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary | ||||||||||||
2622 | /// storage types. | ||||||||||||
2623 | class DIExpression : public MDNode { | ||||||||||||
2624 | friend class LLVMContextImpl; | ||||||||||||
2625 | friend class MDNode; | ||||||||||||
2626 | |||||||||||||
2627 | std::vector<uint64_t> Elements; | ||||||||||||
2628 | |||||||||||||
2629 | DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) | ||||||||||||
2630 | : MDNode(C, DIExpressionKind, Storage, std::nullopt), | ||||||||||||
2631 | Elements(Elements.begin(), Elements.end()) {} | ||||||||||||
2632 | ~DIExpression() = default; | ||||||||||||
2633 | |||||||||||||
2634 | static DIExpression *getImpl(LLVMContext &Context, | ||||||||||||
2635 | ArrayRef<uint64_t> Elements, StorageType Storage, | ||||||||||||
2636 | bool ShouldCreate = true); | ||||||||||||
2637 | |||||||||||||
2638 | TempDIExpression cloneImpl() const { | ||||||||||||
2639 | return getTemporary(getContext(), getElements()); | ||||||||||||
2640 | } | ||||||||||||
2641 | |||||||||||||
2642 | public: | ||||||||||||
2643 | DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements)) | ||||||||||||
2644 | |||||||||||||
2645 | TempDIExpression clone() const { return cloneImpl(); } | ||||||||||||
2646 | |||||||||||||
2647 | ArrayRef<uint64_t> getElements() const { return Elements; } | ||||||||||||
2648 | |||||||||||||
2649 | unsigned getNumElements() const { return Elements.size(); } | ||||||||||||
2650 | |||||||||||||
2651 | uint64_t getElement(unsigned I) const { | ||||||||||||
2652 | assert(I < Elements.size() && "Index out of range")(static_cast <bool> (I < Elements.size() && "Index out of range" ) ? void (0) : __assert_fail ("I < Elements.size() && \"Index out of range\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 2652, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2653 | return Elements[I]; | ||||||||||||
2654 | } | ||||||||||||
2655 | |||||||||||||
2656 | enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; | ||||||||||||
2657 | /// Determine whether this represents a constant value, if so | ||||||||||||
2658 | // return it's sign information. | ||||||||||||
2659 | std::optional<SignedOrUnsignedConstant> isConstant() const; | ||||||||||||
2660 | |||||||||||||
2661 | /// Return the number of unique location operands referred to (via | ||||||||||||
2662 | /// DW_OP_LLVM_arg) in this expression; this is not necessarily the number of | ||||||||||||
2663 | /// instances of DW_OP_LLVM_arg within the expression. | ||||||||||||
2664 | /// For example, for the expression: | ||||||||||||
2665 | /// (DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_plus, | ||||||||||||
2666 | /// DW_OP_LLVM_arg 0, DW_OP_mul) | ||||||||||||
2667 | /// This function would return 2, as there are two unique location operands | ||||||||||||
2668 | /// (0 and 1). | ||||||||||||
2669 | uint64_t getNumLocationOperands() const; | ||||||||||||
2670 | |||||||||||||
2671 | using element_iterator = ArrayRef<uint64_t>::iterator; | ||||||||||||
2672 | |||||||||||||
2673 | element_iterator elements_begin() const { return getElements().begin(); } | ||||||||||||
2674 | element_iterator elements_end() const { return getElements().end(); } | ||||||||||||
2675 | |||||||||||||
2676 | /// A lightweight wrapper around an expression operand. | ||||||||||||
2677 | /// | ||||||||||||
2678 | /// TODO: Store arguments directly and change \a DIExpression to store a | ||||||||||||
2679 | /// range of these. | ||||||||||||
2680 | class ExprOperand { | ||||||||||||
2681 | const uint64_t *Op = nullptr; | ||||||||||||
2682 | |||||||||||||
2683 | public: | ||||||||||||
2684 | ExprOperand() = default; | ||||||||||||
2685 | explicit ExprOperand(const uint64_t *Op) : Op(Op) {} | ||||||||||||
2686 | |||||||||||||
2687 | const uint64_t *get() const { return Op; } | ||||||||||||
2688 | |||||||||||||
2689 | /// Get the operand code. | ||||||||||||
2690 | uint64_t getOp() const { return *Op; } | ||||||||||||
2691 | |||||||||||||
2692 | /// Get an argument to the operand. | ||||||||||||
2693 | /// | ||||||||||||
2694 | /// Never returns the operand itself. | ||||||||||||
2695 | uint64_t getArg(unsigned I) const { return Op[I + 1]; } | ||||||||||||
2696 | |||||||||||||
2697 | unsigned getNumArgs() const { return getSize() - 1; } | ||||||||||||
2698 | |||||||||||||
2699 | /// Return the size of the operand. | ||||||||||||
2700 | /// | ||||||||||||
2701 | /// Return the number of elements in the operand (1 + args). | ||||||||||||
2702 | unsigned getSize() const; | ||||||||||||
2703 | |||||||||||||
2704 | /// Append the elements of this operand to \p V. | ||||||||||||
2705 | void appendToVector(SmallVectorImpl<uint64_t> &V) const { | ||||||||||||
2706 | V.append(get(), get() + getSize()); | ||||||||||||
2707 | } | ||||||||||||
2708 | }; | ||||||||||||
2709 | |||||||||||||
2710 | /// An iterator for expression operands. | ||||||||||||
2711 | class expr_op_iterator { | ||||||||||||
2712 | ExprOperand Op; | ||||||||||||
2713 | |||||||||||||
2714 | public: | ||||||||||||
2715 | using iterator_category = std::input_iterator_tag; | ||||||||||||
2716 | using value_type = ExprOperand; | ||||||||||||
2717 | using difference_type = std::ptrdiff_t; | ||||||||||||
2718 | using pointer = value_type *; | ||||||||||||
2719 | using reference = value_type &; | ||||||||||||
2720 | |||||||||||||
2721 | expr_op_iterator() = default; | ||||||||||||
2722 | explicit expr_op_iterator(element_iterator I) : Op(I) {} | ||||||||||||
2723 | |||||||||||||
2724 | element_iterator getBase() const { return Op.get(); } | ||||||||||||
2725 | const ExprOperand &operator*() const { return Op; } | ||||||||||||
2726 | const ExprOperand *operator->() const { return &Op; } | ||||||||||||
2727 | |||||||||||||
2728 | expr_op_iterator &operator++() { | ||||||||||||
2729 | increment(); | ||||||||||||
2730 | return *this; | ||||||||||||
2731 | } | ||||||||||||
2732 | expr_op_iterator operator++(int) { | ||||||||||||
2733 | expr_op_iterator T(*this); | ||||||||||||
2734 | increment(); | ||||||||||||
2735 | return T; | ||||||||||||
2736 | } | ||||||||||||
2737 | |||||||||||||
2738 | /// Get the next iterator. | ||||||||||||
2739 | /// | ||||||||||||
2740 | /// \a std::next() doesn't work because this is technically an | ||||||||||||
2741 | /// input_iterator, but it's a perfectly valid operation. This is an | ||||||||||||
2742 | /// accessor to provide the same functionality. | ||||||||||||
2743 | expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } | ||||||||||||
2744 | |||||||||||||
2745 | bool operator==(const expr_op_iterator &X) const { | ||||||||||||
2746 | return getBase() == X.getBase(); | ||||||||||||
2747 | } | ||||||||||||
2748 | bool operator!=(const expr_op_iterator &X) const { | ||||||||||||
2749 | return getBase() != X.getBase(); | ||||||||||||
2750 | } | ||||||||||||
2751 | |||||||||||||
2752 | private: | ||||||||||||
2753 | void increment() { Op = ExprOperand(getBase() + Op.getSize()); } | ||||||||||||
2754 | }; | ||||||||||||
2755 | |||||||||||||
2756 | /// Visit the elements via ExprOperand wrappers. | ||||||||||||
2757 | /// | ||||||||||||
2758 | /// These range iterators visit elements through \a ExprOperand wrappers. | ||||||||||||
2759 | /// This is not guaranteed to be a valid range unless \a isValid() gives \c | ||||||||||||
2760 | /// true. | ||||||||||||
2761 | /// | ||||||||||||
2762 | /// \pre \a isValid() gives \c true. | ||||||||||||
2763 | /// @{ | ||||||||||||
2764 | expr_op_iterator expr_op_begin() const { | ||||||||||||
2765 | return expr_op_iterator(elements_begin()); | ||||||||||||
2766 | } | ||||||||||||
2767 | expr_op_iterator expr_op_end() const { | ||||||||||||
2768 | return expr_op_iterator(elements_end()); | ||||||||||||
2769 | } | ||||||||||||
2770 | iterator_range<expr_op_iterator> expr_ops() const { | ||||||||||||
2771 | return {expr_op_begin(), expr_op_end()}; | ||||||||||||
2772 | } | ||||||||||||
2773 | /// @} | ||||||||||||
2774 | |||||||||||||
2775 | bool isValid() const; | ||||||||||||
2776 | |||||||||||||
2777 | static bool classof(const Metadata *MD) { | ||||||||||||
2778 | return MD->getMetadataID() == DIExpressionKind; | ||||||||||||
2779 | } | ||||||||||||
2780 | |||||||||||||
2781 | /// Return whether the first element a DW_OP_deref. | ||||||||||||
2782 | bool startsWithDeref() const; | ||||||||||||
2783 | |||||||||||||
2784 | /// Return whether there is exactly one operator and it is a DW_OP_deref; | ||||||||||||
2785 | bool isDeref() const; | ||||||||||||
2786 | |||||||||||||
2787 | /// Holds the characteristics of one fragment of a larger variable. | ||||||||||||
2788 | struct FragmentInfo { | ||||||||||||
2789 | FragmentInfo() = default; | ||||||||||||
2790 | FragmentInfo(uint64_t SizeInBits, uint64_t OffsetInBits) | ||||||||||||
2791 | : SizeInBits(SizeInBits), OffsetInBits(OffsetInBits) {} | ||||||||||||
2792 | uint64_t SizeInBits; | ||||||||||||
2793 | uint64_t OffsetInBits; | ||||||||||||
2794 | /// Return the index of the first bit of the fragment. | ||||||||||||
2795 | uint64_t startInBits() const { return OffsetInBits; } | ||||||||||||
2796 | /// Return the index of the bit after the end of the fragment, e.g. for | ||||||||||||
2797 | /// fragment offset=16 and size=32 return their sum, 48. | ||||||||||||
2798 | uint64_t endInBits() const { return OffsetInBits + SizeInBits; } | ||||||||||||
2799 | |||||||||||||
2800 | /// Returns a zero-sized fragment if A and B don't intersect. | ||||||||||||
2801 | static DIExpression::FragmentInfo intersect(DIExpression::FragmentInfo A, | ||||||||||||
2802 | DIExpression::FragmentInfo B) { | ||||||||||||
2803 | uint64_t StartInBits = std::max(A.OffsetInBits, B.OffsetInBits); | ||||||||||||
2804 | uint64_t EndInBits = std::min(A.endInBits(), B.endInBits()); | ||||||||||||
2805 | if (EndInBits <= StartInBits) | ||||||||||||
2806 | return {0, 0}; | ||||||||||||
2807 | return DIExpression::FragmentInfo(EndInBits - StartInBits, StartInBits); | ||||||||||||
2808 | } | ||||||||||||
2809 | }; | ||||||||||||
2810 | |||||||||||||
2811 | /// Retrieve the details of this fragment expression. | ||||||||||||
2812 | static std::optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start, | ||||||||||||
2813 | expr_op_iterator End); | ||||||||||||
2814 | |||||||||||||
2815 | /// Retrieve the details of this fragment expression. | ||||||||||||
2816 | std::optional<FragmentInfo> getFragmentInfo() const { | ||||||||||||
2817 | return getFragmentInfo(expr_op_begin(), expr_op_end()); | ||||||||||||
2818 | } | ||||||||||||
2819 | |||||||||||||
2820 | /// Return whether this is a piece of an aggregate variable. | ||||||||||||
2821 | bool isFragment() const { return getFragmentInfo().has_value(); } | ||||||||||||
2822 | |||||||||||||
2823 | /// Return whether this is an implicit location description. | ||||||||||||
2824 | bool isImplicit() const; | ||||||||||||
2825 | |||||||||||||
2826 | /// Return whether the location is computed on the expression stack, meaning | ||||||||||||
2827 | /// it cannot be a simple register location. | ||||||||||||
2828 | bool isComplex() const; | ||||||||||||
2829 | |||||||||||||
2830 | /// Return whether the evaluated expression makes use of a single location at | ||||||||||||
2831 | /// the start of the expression, i.e. if it contains only a single | ||||||||||||
2832 | /// DW_OP_LLVM_arg op as its first operand, or if it contains none. | ||||||||||||
2833 | bool isSingleLocationExpression() const; | ||||||||||||
2834 | |||||||||||||
2835 | /// Removes all elements from \p Expr that do not apply to an undef debug | ||||||||||||
2836 | /// value, which includes every operator that computes the value/location on | ||||||||||||
2837 | /// the DWARF stack, including any DW_OP_LLVM_arg elements (making the result | ||||||||||||
2838 | /// of this function always a single-location expression) while leaving | ||||||||||||
2839 | /// everything that defines what the computed value applies to, i.e. the | ||||||||||||
2840 | /// fragment information. | ||||||||||||
2841 | static const DIExpression *convertToUndefExpression(const DIExpression *Expr); | ||||||||||||
2842 | |||||||||||||
2843 | /// If \p Expr is a non-variadic expression (i.e. one that does not contain | ||||||||||||
2844 | /// DW_OP_LLVM_arg), returns \p Expr converted to variadic form by adding a | ||||||||||||
2845 | /// leading [DW_OP_LLVM_arg, 0] to the expression; otherwise returns \p Expr. | ||||||||||||
2846 | static const DIExpression * | ||||||||||||
2847 | convertToVariadicExpression(const DIExpression *Expr); | ||||||||||||
2848 | |||||||||||||
2849 | /// If \p Expr is a valid single-location expression, i.e. it refers to only a | ||||||||||||
2850 | /// single debug operand at the start of the expression, then return that | ||||||||||||
2851 | /// expression in a non-variadic form by removing DW_OP_LLVM_arg from the | ||||||||||||
2852 | /// expression if it is present; otherwise returns std::nullopt. | ||||||||||||
2853 | static std::optional<const DIExpression *> | ||||||||||||
2854 | convertToNonVariadicExpression(const DIExpression *Expr); | ||||||||||||
2855 | |||||||||||||
2856 | /// Inserts the elements of \p Expr into \p Ops modified to a canonical form, | ||||||||||||
2857 | /// which uses DW_OP_LLVM_arg (i.e. is a variadic expression) and folds the | ||||||||||||
2858 | /// implied derefence from the \p IsIndirect flag into the expression. This | ||||||||||||
2859 | /// allows us to check equivalence between expressions with differing | ||||||||||||
2860 | /// directness or variadicness. | ||||||||||||
2861 | static void canonicalizeExpressionOps(SmallVectorImpl<uint64_t> &Ops, | ||||||||||||
2862 | const DIExpression *Expr, | ||||||||||||
2863 | bool IsIndirect); | ||||||||||||
2864 | |||||||||||||
2865 | /// Determines whether two debug values should produce equivalent DWARF | ||||||||||||
2866 | /// expressions, using their DIExpressions and directness, ignoring the | ||||||||||||
2867 | /// differences between otherwise identical expressions in variadic and | ||||||||||||
2868 | /// non-variadic form and not considering the debug operands. | ||||||||||||
2869 | /// \p FirstExpr is the DIExpression for the first debug value. | ||||||||||||
2870 | /// \p FirstIndirect should be true if the first debug value is indirect; in | ||||||||||||
2871 | /// IR this should be true for dbg.declare intrinsics and false for | ||||||||||||
2872 | /// dbg.values, and in MIR this should be true only for DBG_VALUE instructions | ||||||||||||
2873 | /// whose second operand is an immediate value. | ||||||||||||
2874 | /// \p SecondExpr and \p SecondIndirect have the same meaning as the prior | ||||||||||||
2875 | /// arguments, but apply to the second debug value. | ||||||||||||
2876 | static bool isEqualExpression(const DIExpression *FirstExpr, | ||||||||||||
2877 | bool FirstIndirect, | ||||||||||||
2878 | const DIExpression *SecondExpr, | ||||||||||||
2879 | bool SecondIndirect); | ||||||||||||
2880 | |||||||||||||
2881 | /// Append \p Ops with operations to apply the \p Offset. | ||||||||||||
2882 | static void appendOffset(SmallVectorImpl<uint64_t> &Ops, int64_t Offset); | ||||||||||||
2883 | |||||||||||||
2884 | /// If this is a constant offset, extract it. If there is no expression, | ||||||||||||
2885 | /// return true with an offset of zero. | ||||||||||||
2886 | bool extractIfOffset(int64_t &Offset) const; | ||||||||||||
2887 | |||||||||||||
2888 | /// Returns true iff this DIExpression contains at least one instance of | ||||||||||||
2889 | /// `DW_OP_LLVM_arg, n` for all n in [0, N). | ||||||||||||
2890 | bool hasAllLocationOps(unsigned N) const; | ||||||||||||
2891 | |||||||||||||
2892 | /// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF | ||||||||||||
2893 | /// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address | ||||||||||||
2894 | /// Space>. | ||||||||||||
2895 | static const DIExpression *extractAddressClass(const DIExpression *Expr, | ||||||||||||
2896 | unsigned &AddrClass); | ||||||||||||
2897 | |||||||||||||
2898 | /// Used for DIExpression::prepend. | ||||||||||||
2899 | enum PrependOps : uint8_t { | ||||||||||||
2900 | ApplyOffset = 0, | ||||||||||||
2901 | DerefBefore = 1 << 0, | ||||||||||||
2902 | DerefAfter = 1 << 1, | ||||||||||||
2903 | StackValue = 1 << 2, | ||||||||||||
2904 | EntryValue = 1 << 3 | ||||||||||||
2905 | }; | ||||||||||||
2906 | |||||||||||||
2907 | /// Prepend \p DIExpr with a deref and offset operation and optionally turn it | ||||||||||||
2908 | /// into a stack value or/and an entry value. | ||||||||||||
2909 | static DIExpression *prepend(const DIExpression *Expr, uint8_t Flags, | ||||||||||||
2910 | int64_t Offset = 0); | ||||||||||||
2911 | |||||||||||||
2912 | /// Prepend \p DIExpr with the given opcodes and optionally turn it into a | ||||||||||||
2913 | /// stack value. | ||||||||||||
2914 | static DIExpression *prependOpcodes(const DIExpression *Expr, | ||||||||||||
2915 | SmallVectorImpl<uint64_t> &Ops, | ||||||||||||
2916 | bool StackValue = false, | ||||||||||||
2917 | bool EntryValue = false); | ||||||||||||
2918 | |||||||||||||
2919 | /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the | ||||||||||||
2920 | /// returned expression is a stack value only if \p DIExpr is a stack value. | ||||||||||||
2921 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||||||||||
2922 | /// the same fragment. | ||||||||||||
2923 | static DIExpression *append(const DIExpression *Expr, ArrayRef<uint64_t> Ops); | ||||||||||||
2924 | |||||||||||||
2925 | /// Convert \p DIExpr into a stack value if it isn't one already by appending | ||||||||||||
2926 | /// DW_OP_deref if needed, and appending \p Ops to the resulting expression. | ||||||||||||
2927 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||||||||||
2928 | /// the same fragment. | ||||||||||||
2929 | static DIExpression *appendToStack(const DIExpression *Expr, | ||||||||||||
2930 | ArrayRef<uint64_t> Ops); | ||||||||||||
2931 | |||||||||||||
2932 | /// Create a copy of \p Expr by appending the given list of \p Ops to each | ||||||||||||
2933 | /// instance of the operand `DW_OP_LLVM_arg, \p ArgNo`. This is used to | ||||||||||||
2934 | /// modify a specific location used by \p Expr, such as when salvaging that | ||||||||||||
2935 | /// location. | ||||||||||||
2936 | static DIExpression *appendOpsToArg(const DIExpression *Expr, | ||||||||||||
2937 | ArrayRef<uint64_t> Ops, unsigned ArgNo, | ||||||||||||
2938 | bool StackValue = false); | ||||||||||||
2939 | |||||||||||||
2940 | /// Create a copy of \p Expr with each instance of | ||||||||||||
2941 | /// `DW_OP_LLVM_arg, \p OldArg` replaced with `DW_OP_LLVM_arg, \p NewArg`, | ||||||||||||
2942 | /// and each instance of `DW_OP_LLVM_arg, Arg` with `DW_OP_LLVM_arg, Arg - 1` | ||||||||||||
2943 | /// for all Arg > \p OldArg. | ||||||||||||
2944 | /// This is used when replacing one of the operands of a debug value list | ||||||||||||
2945 | /// with another operand in the same list and deleting the old operand. | ||||||||||||
2946 | static DIExpression *replaceArg(const DIExpression *Expr, uint64_t OldArg, | ||||||||||||
2947 | uint64_t NewArg); | ||||||||||||
2948 | |||||||||||||
2949 | /// Create a DIExpression to describe one part of an aggregate variable that | ||||||||||||
2950 | /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation | ||||||||||||
2951 | /// will be appended to the elements of \c Expr. If \c Expr already contains | ||||||||||||
2952 | /// a \c DW_OP_LLVM_fragment \c OffsetInBits is interpreted as an offset | ||||||||||||
2953 | /// into the existing fragment. | ||||||||||||
2954 | /// | ||||||||||||
2955 | /// \param OffsetInBits Offset of the piece in bits. | ||||||||||||
2956 | /// \param SizeInBits Size of the piece in bits. | ||||||||||||
2957 | /// \return Creating a fragment expression may fail if \c Expr | ||||||||||||
2958 | /// contains arithmetic operations that would be | ||||||||||||
2959 | /// truncated. | ||||||||||||
2960 | static std::optional<DIExpression *> | ||||||||||||
2961 | createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, | ||||||||||||
2962 | unsigned SizeInBits); | ||||||||||||
2963 | |||||||||||||
2964 | /// Determine the relative position of the fragments passed in. | ||||||||||||
2965 | /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, | ||||||||||||
2966 | /// 1 if this is entirely after Other. | ||||||||||||
2967 | static int fragmentCmp(const FragmentInfo &A, const FragmentInfo &B) { | ||||||||||||
2968 | uint64_t l1 = A.OffsetInBits; | ||||||||||||
2969 | uint64_t l2 = B.OffsetInBits; | ||||||||||||
2970 | uint64_t r1 = l1 + A.SizeInBits; | ||||||||||||
2971 | uint64_t r2 = l2 + B.SizeInBits; | ||||||||||||
2972 | if (r1 <= l2) | ||||||||||||
2973 | return -1; | ||||||||||||
2974 | else if (r2 <= l1) | ||||||||||||
2975 | return 1; | ||||||||||||
2976 | else | ||||||||||||
2977 | return 0; | ||||||||||||
2978 | } | ||||||||||||
2979 | |||||||||||||
2980 | using ExtOps = std::array<uint64_t, 6>; | ||||||||||||
2981 | |||||||||||||
2982 | /// Returns the ops for a zero- or sign-extension in a DIExpression. | ||||||||||||
2983 | static ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed); | ||||||||||||
2984 | |||||||||||||
2985 | /// Append a zero- or sign-extension to \p Expr. Converts the expression to a | ||||||||||||
2986 | /// stack value if it isn't one already. | ||||||||||||
2987 | static DIExpression *appendExt(const DIExpression *Expr, unsigned FromSize, | ||||||||||||
2988 | unsigned ToSize, bool Signed); | ||||||||||||
2989 | |||||||||||||
2990 | /// Check if fragments overlap between a pair of FragmentInfos. | ||||||||||||
2991 | static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B) { | ||||||||||||
2992 | return fragmentCmp(A, B) == 0; | ||||||||||||
2993 | } | ||||||||||||
2994 | |||||||||||||
2995 | /// Determine the relative position of the fragments described by this | ||||||||||||
2996 | /// DIExpression and \p Other. Calls static fragmentCmp implementation. | ||||||||||||
2997 | int fragmentCmp(const DIExpression *Other) const { | ||||||||||||
2998 | auto Fragment1 = *getFragmentInfo(); | ||||||||||||
2999 | auto Fragment2 = *Other->getFragmentInfo(); | ||||||||||||
3000 | return fragmentCmp(Fragment1, Fragment2); | ||||||||||||
3001 | } | ||||||||||||
3002 | |||||||||||||
3003 | /// Check if fragments overlap between this DIExpression and \p Other. | ||||||||||||
3004 | bool fragmentsOverlap(const DIExpression *Other) const { | ||||||||||||
3005 | if (!isFragment() || !Other->isFragment()) | ||||||||||||
3006 | return true; | ||||||||||||
3007 | return fragmentCmp(Other) == 0; | ||||||||||||
3008 | } | ||||||||||||
3009 | |||||||||||||
3010 | /// Check if the expression consists of exactly one entry value operand. | ||||||||||||
3011 | /// (This is the only configuration of entry values that is supported.) | ||||||||||||
3012 | bool isEntryValue() const; | ||||||||||||
3013 | |||||||||||||
3014 | /// Try to shorten an expression with an initial constant operand. | ||||||||||||
3015 | /// Returns a new expression and constant on success, or the original | ||||||||||||
3016 | /// expression and constant on failure. | ||||||||||||
3017 | std::pair<DIExpression *, const ConstantInt *> | ||||||||||||
3018 | constantFold(const ConstantInt *CI); | ||||||||||||
3019 | }; | ||||||||||||
3020 | |||||||||||||
3021 | inline bool operator==(const DIExpression::FragmentInfo &A, | ||||||||||||
3022 | const DIExpression::FragmentInfo &B) { | ||||||||||||
3023 | return std::tie(A.SizeInBits, A.OffsetInBits) == | ||||||||||||
3024 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||||||||||
3025 | } | ||||||||||||
3026 | |||||||||||||
3027 | inline bool operator<(const DIExpression::FragmentInfo &A, | ||||||||||||
3028 | const DIExpression::FragmentInfo &B) { | ||||||||||||
3029 | return std::tie(A.SizeInBits, A.OffsetInBits) < | ||||||||||||
3030 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||||||||||
3031 | } | ||||||||||||
3032 | |||||||||||||
3033 | template <> struct DenseMapInfo<DIExpression::FragmentInfo> { | ||||||||||||
3034 | using FragInfo = DIExpression::FragmentInfo; | ||||||||||||
3035 | static const uint64_t MaxVal = std::numeric_limits<uint64_t>::max(); | ||||||||||||
3036 | |||||||||||||
3037 | static inline FragInfo getEmptyKey() { return {MaxVal, MaxVal}; } | ||||||||||||
3038 | |||||||||||||
3039 | static inline FragInfo getTombstoneKey() { return {MaxVal - 1, MaxVal - 1}; } | ||||||||||||
3040 | |||||||||||||
3041 | static unsigned getHashValue(const FragInfo &Frag) { | ||||||||||||
3042 | return (Frag.SizeInBits & 0xffff) << 16 | (Frag.OffsetInBits & 0xffff); | ||||||||||||
3043 | } | ||||||||||||
3044 | |||||||||||||
3045 | static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } | ||||||||||||
3046 | }; | ||||||||||||
3047 | |||||||||||||
3048 | /// Global variables. | ||||||||||||
3049 | /// | ||||||||||||
3050 | /// TODO: Remove DisplayName. It's always equal to Name. | ||||||||||||
3051 | class DIGlobalVariable : public DIVariable { | ||||||||||||
3052 | friend class LLVMContextImpl; | ||||||||||||
3053 | friend class MDNode; | ||||||||||||
3054 | |||||||||||||
3055 | bool IsLocalToUnit; | ||||||||||||
3056 | bool IsDefinition; | ||||||||||||
3057 | |||||||||||||
3058 | DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
3059 | bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, | ||||||||||||
3060 | ArrayRef<Metadata *> Ops) | ||||||||||||
3061 | : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), | ||||||||||||
3062 | IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} | ||||||||||||
3063 | ~DIGlobalVariable() = default; | ||||||||||||
3064 | |||||||||||||
3065 | static DIGlobalVariable * | ||||||||||||
3066 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||||||||||
3067 | StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, | ||||||||||||
3068 | bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
3069 | DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, | ||||||||||||
3070 | uint32_t AlignInBits, DINodeArray Annotations, StorageType Storage, | ||||||||||||
3071 | bool ShouldCreate = true) { | ||||||||||||
3072 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
3073 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||||||||||
3074 | IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, | ||||||||||||
3075 | cast_or_null<Metadata>(TemplateParams), AlignInBits, | ||||||||||||
3076 | Annotations.get(), Storage, ShouldCreate); | ||||||||||||
3077 | } | ||||||||||||
3078 | static DIGlobalVariable * | ||||||||||||
3079 | getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||||||||||
3080 | MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, | ||||||||||||
3081 | bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
3082 | Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, | ||||||||||||
3083 | uint32_t AlignInBits, Metadata *Annotations, StorageType Storage, | ||||||||||||
3084 | bool ShouldCreate = true); | ||||||||||||
3085 | |||||||||||||
3086 | TempDIGlobalVariable cloneImpl() const { | ||||||||||||
3087 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||||||||||
3088 | getFile(), getLine(), getType(), isLocalToUnit(), | ||||||||||||
3089 | isDefinition(), getStaticDataMemberDeclaration(), | ||||||||||||
3090 | getTemplateParams(), getAlignInBits(), | ||||||||||||
3091 | getAnnotations()); | ||||||||||||
3092 | } | ||||||||||||
3093 | |||||||||||||
3094 | public: | ||||||||||||
3095 | DEFINE_MDNODE_GET( | ||||||||||||
3096 | DIGlobalVariable, | ||||||||||||
3097 | (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, | ||||||||||||
3098 | unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
3099 | DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, | ||||||||||||
3100 | uint32_t AlignInBits, DINodeArray Annotations), | ||||||||||||
3101 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, | ||||||||||||
3102 | StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) | ||||||||||||
3103 | DEFINE_MDNODE_GET( | ||||||||||||
3104 | DIGlobalVariable, | ||||||||||||
3105 | (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, | ||||||||||||
3106 | unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
3107 | Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, | ||||||||||||
3108 | uint32_t AlignInBits, Metadata *Annotations), | ||||||||||||
3109 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, | ||||||||||||
3110 | StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) | ||||||||||||
3111 | |||||||||||||
3112 | TempDIGlobalVariable clone() const { return cloneImpl(); } | ||||||||||||
3113 | |||||||||||||
3114 | bool isLocalToUnit() const { return IsLocalToUnit; } | ||||||||||||
3115 | bool isDefinition() const { return IsDefinition; } | ||||||||||||
3116 | StringRef getDisplayName() const { return getStringOperand(4); } | ||||||||||||
3117 | StringRef getLinkageName() const { return getStringOperand(5); } | ||||||||||||
3118 | DIDerivedType *getStaticDataMemberDeclaration() const { | ||||||||||||
3119 | return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration()); | ||||||||||||
3120 | } | ||||||||||||
3121 | DINodeArray getAnnotations() const { | ||||||||||||
3122 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
3123 | } | ||||||||||||
3124 | |||||||||||||
3125 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } | ||||||||||||
3126 | Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } | ||||||||||||
3127 | Metadata *getRawTemplateParams() const { return getOperand(7); } | ||||||||||||
3128 | MDTuple *getTemplateParams() const { return getOperandAs<MDTuple>(7); } | ||||||||||||
3129 | Metadata *getRawAnnotations() const { return getOperand(8); } | ||||||||||||
3130 | |||||||||||||
3131 | static bool classof(const Metadata *MD) { | ||||||||||||
3132 | return MD->getMetadataID() == DIGlobalVariableKind; | ||||||||||||
3133 | } | ||||||||||||
3134 | }; | ||||||||||||
3135 | |||||||||||||
3136 | class DICommonBlock : public DIScope { | ||||||||||||
3137 | unsigned LineNo; | ||||||||||||
3138 | |||||||||||||
3139 | friend class LLVMContextImpl; | ||||||||||||
3140 | friend class MDNode; | ||||||||||||
3141 | |||||||||||||
3142 | DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||||||||||
3143 | ArrayRef<Metadata *> Ops); | ||||||||||||
3144 | |||||||||||||
3145 | static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, | ||||||||||||
3146 | DIGlobalVariable *Decl, StringRef Name, | ||||||||||||
3147 | DIFile *File, unsigned LineNo, | ||||||||||||
3148 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
3149 | return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), | ||||||||||||
3150 | File, LineNo, Storage, ShouldCreate); | ||||||||||||
3151 | } | ||||||||||||
3152 | static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
3153 | Metadata *Decl, MDString *Name, Metadata *File, | ||||||||||||
3154 | unsigned LineNo, StorageType Storage, | ||||||||||||
3155 | bool ShouldCreate = true); | ||||||||||||
3156 | |||||||||||||
3157 | TempDICommonBlock cloneImpl() const { | ||||||||||||
3158 | return getTemporary(getContext(), getScope(), getDecl(), getName(), | ||||||||||||
3159 | getFile(), getLineNo()); | ||||||||||||
3160 | } | ||||||||||||
3161 | |||||||||||||
3162 | public: | ||||||||||||
3163 | DEFINE_MDNODE_GET(DICommonBlock, | ||||||||||||
3164 | (DIScope * Scope, DIGlobalVariable *Decl, StringRef Name, | ||||||||||||
3165 | DIFile *File, unsigned LineNo), | ||||||||||||
3166 | (Scope, Decl, Name, File, LineNo)) | ||||||||||||
3167 | DEFINE_MDNODE_GET(DICommonBlock, | ||||||||||||
3168 | (Metadata * Scope, Metadata *Decl, MDString *Name, | ||||||||||||
3169 | Metadata *File, unsigned LineNo), | ||||||||||||
3170 | (Scope, Decl, Name, File, LineNo)) | ||||||||||||
3171 | |||||||||||||
3172 | TempDICommonBlock clone() const { return cloneImpl(); } | ||||||||||||
3173 | |||||||||||||
3174 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
3175 | DIGlobalVariable *getDecl() const { | ||||||||||||
3176 | return cast_or_null<DIGlobalVariable>(getRawDecl()); | ||||||||||||
3177 | } | ||||||||||||
3178 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
3179 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
3180 | unsigned getLineNo() const { return LineNo; } | ||||||||||||
3181 | |||||||||||||
3182 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
3183 | Metadata *getRawDecl() const { return getOperand(1); } | ||||||||||||
3184 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
3185 | Metadata *getRawFile() const { return getOperand(3); } | ||||||||||||
3186 | |||||||||||||
3187 | static bool classof(const Metadata *MD) { | ||||||||||||
3188 | return MD->getMetadataID() == DICommonBlockKind; | ||||||||||||
3189 | } | ||||||||||||
3190 | }; | ||||||||||||
3191 | |||||||||||||
3192 | /// Local variable. | ||||||||||||
3193 | /// | ||||||||||||
3194 | /// TODO: Split up flags. | ||||||||||||
3195 | class DILocalVariable : public DIVariable { | ||||||||||||
3196 | friend class LLVMContextImpl; | ||||||||||||
3197 | friend class MDNode; | ||||||||||||
3198 | |||||||||||||
3199 | unsigned Arg : 16; | ||||||||||||
3200 | DIFlags Flags; | ||||||||||||
3201 | |||||||||||||
3202 | DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
3203 | unsigned Arg, DIFlags Flags, uint32_t AlignInBits, | ||||||||||||
3204 | ArrayRef<Metadata *> Ops) | ||||||||||||
3205 | : DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBits), | ||||||||||||
3206 | Arg(Arg), Flags(Flags) { | ||||||||||||
3207 | assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range")(static_cast <bool> (Arg < (1 << 16) && "DILocalVariable: Arg out of range") ? void (0) : __assert_fail ("Arg < (1 << 16) && \"DILocalVariable: Arg out of range\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 3207, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
3208 | } | ||||||||||||
3209 | ~DILocalVariable() = default; | ||||||||||||
3210 | |||||||||||||
3211 | static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, | ||||||||||||
3212 | StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
3213 | DIType *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
3214 | uint32_t AlignInBits, DINodeArray Annotations, | ||||||||||||
3215 | StorageType Storage, | ||||||||||||
3216 | bool ShouldCreate = true) { | ||||||||||||
3217 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||||||||||
3218 | Line, Type, Arg, Flags, AlignInBits, Annotations.get(), | ||||||||||||
3219 | Storage, ShouldCreate); | ||||||||||||
3220 | } | ||||||||||||
3221 | static DILocalVariable *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
3222 | MDString *Name, Metadata *File, unsigned Line, | ||||||||||||
3223 | Metadata *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
3224 | uint32_t AlignInBits, Metadata *Annotations, | ||||||||||||
3225 | StorageType Storage, | ||||||||||||
3226 | bool ShouldCreate = true); | ||||||||||||
3227 | |||||||||||||
3228 | TempDILocalVariable cloneImpl() const { | ||||||||||||
3229 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||||||||||
3230 | getLine(), getType(), getArg(), getFlags(), | ||||||||||||
3231 | getAlignInBits(), getAnnotations()); | ||||||||||||
3232 | } | ||||||||||||
3233 | |||||||||||||
3234 | public: | ||||||||||||
3235 | DEFINE_MDNODE_GET(DILocalVariable, | ||||||||||||
3236 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||||||||||
3237 | unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
3238 | uint32_t AlignInBits, DINodeArray Annotations), | ||||||||||||
3239 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, | ||||||||||||
3240 | Annotations)) | ||||||||||||
3241 | DEFINE_MDNODE_GET(DILocalVariable, | ||||||||||||
3242 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||||||||||
3243 | unsigned Line, Metadata *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
3244 | uint32_t AlignInBits, Metadata *Annotations), | ||||||||||||
3245 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, | ||||||||||||
3246 | Annotations)) | ||||||||||||
3247 | |||||||||||||
3248 | TempDILocalVariable clone() const { return cloneImpl(); } | ||||||||||||
3249 | |||||||||||||
3250 | /// Get the local scope for this variable. | ||||||||||||
3251 | /// | ||||||||||||
3252 | /// Variables must be defined in a local scope. | ||||||||||||
3253 | DILocalScope *getScope() const { | ||||||||||||
3254 | return cast<DILocalScope>(DIVariable::getScope()); | ||||||||||||
3255 | } | ||||||||||||
3256 | |||||||||||||
3257 | bool isParameter() const { return Arg; } | ||||||||||||
3258 | unsigned getArg() const { return Arg; } | ||||||||||||
3259 | DIFlags getFlags() const { return Flags; } | ||||||||||||
3260 | |||||||||||||
3261 | DINodeArray getAnnotations() const { | ||||||||||||
3262 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
3263 | } | ||||||||||||
3264 | Metadata *getRawAnnotations() const { return getOperand(4); } | ||||||||||||
3265 | |||||||||||||
3266 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||||||||||
3267 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||||||||||
3268 | |||||||||||||
3269 | /// Check that a location is valid for this variable. | ||||||||||||
3270 | /// | ||||||||||||
3271 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||||||||||
3272 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||||||||||
3273 | /// to a \a DbgInfoIntrinsic.) | ||||||||||||
3274 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||||||||||
3275 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||||||||||
3276 | } | ||||||||||||
3277 | |||||||||||||
3278 | static bool classof(const Metadata *MD) { | ||||||||||||
3279 | return MD->getMetadataID() == DILocalVariableKind; | ||||||||||||
3280 | } | ||||||||||||
3281 | }; | ||||||||||||
3282 | |||||||||||||
3283 | /// Label. | ||||||||||||
3284 | /// | ||||||||||||
3285 | class DILabel : public DINode { | ||||||||||||
3286 | friend class LLVMContextImpl; | ||||||||||||
3287 | friend class MDNode; | ||||||||||||
3288 | |||||||||||||
3289 | unsigned Line; | ||||||||||||
3290 | |||||||||||||
3291 | DILabel(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
3292 | ArrayRef<Metadata *> Ops); | ||||||||||||
3293 | ~DILabel() = default; | ||||||||||||
3294 | |||||||||||||
3295 | static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||||||||||
3296 | DIFile *File, unsigned Line, StorageType Storage, | ||||||||||||
3297 | bool ShouldCreate = true) { | ||||||||||||
3298 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||||||||||
3299 | Line, Storage, ShouldCreate); | ||||||||||||
3300 | } | ||||||||||||
3301 | static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||||||||||
3302 | Metadata *File, unsigned Line, StorageType Storage, | ||||||||||||
3303 | bool ShouldCreate = true); | ||||||||||||
3304 | |||||||||||||
3305 | TempDILabel cloneImpl() const { | ||||||||||||
3306 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||||||||||
3307 | getLine()); | ||||||||||||
3308 | } | ||||||||||||
3309 | |||||||||||||
3310 | public: | ||||||||||||
3311 | DEFINE_MDNODE_GET(DILabel, | ||||||||||||
3312 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||||||||||
3313 | unsigned Line), | ||||||||||||
3314 | (Scope, Name, File, Line)) | ||||||||||||
3315 | DEFINE_MDNODE_GET(DILabel, | ||||||||||||
3316 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||||||||||
3317 | unsigned Line), | ||||||||||||
3318 | (Scope, Name, File, Line)) | ||||||||||||
3319 | |||||||||||||
3320 | TempDILabel clone() const { return cloneImpl(); } | ||||||||||||
3321 | |||||||||||||
3322 | /// Get the local scope for this label. | ||||||||||||
3323 | /// | ||||||||||||
3324 | /// Labels must be defined in a local scope. | ||||||||||||
3325 | DILocalScope *getScope() const { | ||||||||||||
3326 | return cast_or_null<DILocalScope>(getRawScope()); | ||||||||||||
3327 | } | ||||||||||||
3328 | unsigned getLine() const { return Line; } | ||||||||||||
3329 | StringRef getName() const { return getStringOperand(1); } | ||||||||||||
3330 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
3331 | |||||||||||||
3332 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
3333 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||||||||||
3334 | Metadata *getRawFile() const { return getOperand(2); } | ||||||||||||
3335 | |||||||||||||
3336 | /// Check that a location is valid for this label. | ||||||||||||
3337 | /// | ||||||||||||
3338 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||||||||||
3339 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||||||||||
3340 | /// to a \a DbgInfoIntrinsic.) | ||||||||||||
3341 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||||||||||
3342 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||||||||||
3343 | } | ||||||||||||
3344 | |||||||||||||
3345 | static bool classof(const Metadata *MD) { | ||||||||||||
3346 | return MD->getMetadataID() == DILabelKind; | ||||||||||||
3347 | } | ||||||||||||
3348 | }; | ||||||||||||
3349 | |||||||||||||
3350 | class DIObjCProperty : public DINode { | ||||||||||||
3351 | friend class LLVMContextImpl; | ||||||||||||
3352 | friend class MDNode; | ||||||||||||
3353 | |||||||||||||
3354 | unsigned Line; | ||||||||||||
3355 | unsigned Attributes; | ||||||||||||
3356 | |||||||||||||
3357 | DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
3358 | unsigned Attributes, ArrayRef<Metadata *> Ops); | ||||||||||||
3359 | ~DIObjCProperty() = default; | ||||||||||||
3360 | |||||||||||||
3361 | static DIObjCProperty * | ||||||||||||
3362 | getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
3363 | StringRef GetterName, StringRef SetterName, unsigned Attributes, | ||||||||||||
3364 | DIType *Type, StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
3365 | return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, | ||||||||||||
3366 | getCanonicalMDString(Context, GetterName), | ||||||||||||
3367 | getCanonicalMDString(Context, SetterName), Attributes, Type, | ||||||||||||
3368 | Storage, ShouldCreate); | ||||||||||||
3369 | } | ||||||||||||
3370 | static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, | ||||||||||||
3371 | Metadata *File, unsigned Line, | ||||||||||||
3372 | MDString *GetterName, MDString *SetterName, | ||||||||||||
3373 | unsigned Attributes, Metadata *Type, | ||||||||||||
3374 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
3375 | |||||||||||||
3376 | TempDIObjCProperty cloneImpl() const { | ||||||||||||
3377 | return getTemporary(getContext(), getName(), getFile(), getLine(), | ||||||||||||
3378 | getGetterName(), getSetterName(), getAttributes(), | ||||||||||||
3379 | getType()); | ||||||||||||
3380 | } | ||||||||||||
3381 | |||||||||||||
3382 | public: | ||||||||||||
3383 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||||||||||
3384 | (StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
3385 | StringRef GetterName, StringRef SetterName, | ||||||||||||
3386 | unsigned Attributes, DIType *Type), | ||||||||||||
3387 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||||||||||
3388 | Type)) | ||||||||||||
3389 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||||||||||
3390 | (MDString * Name, Metadata *File, unsigned Line, | ||||||||||||
3391 | MDString *GetterName, MDString *SetterName, | ||||||||||||
3392 | unsigned Attributes, Metadata *Type), | ||||||||||||
3393 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||||||||||
3394 | Type)) | ||||||||||||
3395 | |||||||||||||
3396 | TempDIObjCProperty clone() const { return cloneImpl(); } | ||||||||||||
3397 | |||||||||||||
3398 | unsigned getLine() const { return Line; } | ||||||||||||
3399 | unsigned getAttributes() const { return Attributes; } | ||||||||||||
3400 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
3401 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
3402 | StringRef getGetterName() const { return getStringOperand(2); } | ||||||||||||
3403 | StringRef getSetterName() const { return getStringOperand(3); } | ||||||||||||
3404 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||||||||||
3405 | |||||||||||||
3406 | StringRef getFilename() const { | ||||||||||||
3407 | if (auto *F = getFile()) | ||||||||||||
3408 | return F->getFilename(); | ||||||||||||
3409 | return ""; | ||||||||||||
3410 | } | ||||||||||||
3411 | |||||||||||||
3412 | StringRef getDirectory() const { | ||||||||||||
3413 | if (auto *F = getFile()) | ||||||||||||
3414 | return F->getDirectory(); | ||||||||||||
3415 | return ""; | ||||||||||||
3416 | } | ||||||||||||
3417 | |||||||||||||
3418 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
3419 | Metadata *getRawFile() const { return getOperand(1); } | ||||||||||||
3420 | MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } | ||||||||||||
3421 | MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } | ||||||||||||
3422 | Metadata *getRawType() const { return getOperand(4); } | ||||||||||||
3423 | |||||||||||||
3424 | static bool classof(const Metadata *MD) { | ||||||||||||
3425 | return MD->getMetadataID() == DIObjCPropertyKind; | ||||||||||||
3426 | } | ||||||||||||
3427 | }; | ||||||||||||
3428 | |||||||||||||
3429 | /// An imported module (C++ using directive or similar). | ||||||||||||
3430 | class DIImportedEntity : public DINode { | ||||||||||||
3431 | friend class LLVMContextImpl; | ||||||||||||
3432 | friend class MDNode; | ||||||||||||
3433 | |||||||||||||
3434 | unsigned Line; | ||||||||||||
3435 | |||||||||||||
3436 | DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
3437 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||||||||||
3438 | : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} | ||||||||||||
3439 | ~DIImportedEntity() = default; | ||||||||||||
3440 | |||||||||||||
3441 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
3442 | DIScope *Scope, DINode *Entity, DIFile *File, | ||||||||||||
3443 | unsigned Line, StringRef Name, | ||||||||||||
3444 | DINodeArray Elements, StorageType Storage, | ||||||||||||
3445 | bool ShouldCreate = true) { | ||||||||||||
3446 | return getImpl(Context, Tag, Scope, Entity, File, Line, | ||||||||||||
3447 | getCanonicalMDString(Context, Name), Elements.get(), Storage, | ||||||||||||
3448 | ShouldCreate); | ||||||||||||
3449 | } | ||||||||||||
3450 | static DIImportedEntity * | ||||||||||||
3451 | getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, Metadata *Entity, | ||||||||||||
3452 | Metadata *File, unsigned Line, MDString *Name, Metadata *Elements, | ||||||||||||
3453 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
3454 | |||||||||||||
3455 | TempDIImportedEntity cloneImpl() const { | ||||||||||||
3456 | return getTemporary(getContext(), getTag(), getScope(), getEntity(), | ||||||||||||
3457 | getFile(), getLine(), getName(), getElements()); | ||||||||||||
3458 | } | ||||||||||||
3459 | |||||||||||||
3460 | public: | ||||||||||||
3461 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||||||||||
3462 | (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File, | ||||||||||||
3463 | unsigned Line, StringRef Name = "", | ||||||||||||
3464 | DINodeArray Elements = nullptr), | ||||||||||||
3465 | (Tag, Scope, Entity, File, Line, Name, Elements)) | ||||||||||||
3466 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||||||||||
3467 | (unsigned Tag, Metadata *Scope, Metadata *Entity, | ||||||||||||
3468 | Metadata *File, unsigned Line, MDString *Name, | ||||||||||||
3469 | Metadata *Elements = nullptr), | ||||||||||||
3470 | (Tag, Scope, Entity, File, Line, Name, Elements)) | ||||||||||||
3471 | |||||||||||||
3472 | TempDIImportedEntity clone() const { return cloneImpl(); } | ||||||||||||
3473 | |||||||||||||
3474 | unsigned getLine() const { return Line; } | ||||||||||||
3475 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
3476 | DINode *getEntity() const { return cast_or_null<DINode>(getRawEntity()); } | ||||||||||||
3477 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
3478 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
3479 | DINodeArray getElements() const { | ||||||||||||
3480 | return cast_or_null<MDTuple>(getRawElements()); | ||||||||||||
3481 | } | ||||||||||||
3482 | |||||||||||||
3483 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
3484 | Metadata *getRawEntity() const { return getOperand(1); } | ||||||||||||
3485 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
3486 | Metadata *getRawFile() const { return getOperand(3); } | ||||||||||||
3487 | Metadata *getRawElements() const { return getOperand(4); } | ||||||||||||
3488 | |||||||||||||
3489 | static bool classof(const Metadata *MD) { | ||||||||||||
3490 | return MD->getMetadataID() == DIImportedEntityKind; | ||||||||||||
3491 | } | ||||||||||||
3492 | }; | ||||||||||||
3493 | |||||||||||||
3494 | /// A pair of DIGlobalVariable and DIExpression. | ||||||||||||
3495 | class DIGlobalVariableExpression : public MDNode { | ||||||||||||
3496 | friend class LLVMContextImpl; | ||||||||||||
3497 | friend class MDNode; | ||||||||||||
3498 | |||||||||||||
3499 | DIGlobalVariableExpression(LLVMContext &C, StorageType Storage, | ||||||||||||
3500 | ArrayRef<Metadata *> Ops) | ||||||||||||
3501 | : MDNode(C, DIGlobalVariableExpressionKind, Storage, Ops) {} | ||||||||||||
3502 | ~DIGlobalVariableExpression() = default; | ||||||||||||
3503 | |||||||||||||
3504 | static DIGlobalVariableExpression * | ||||||||||||
3505 | getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Expression, | ||||||||||||
3506 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
3507 | |||||||||||||
3508 | TempDIGlobalVariableExpression cloneImpl() const { | ||||||||||||
3509 | return getTemporary(getContext(), getVariable(), getExpression()); | ||||||||||||
3510 | } | ||||||||||||
3511 | |||||||||||||
3512 | public: | ||||||||||||
3513 | DEFINE_MDNODE_GET(DIGlobalVariableExpression, | ||||||||||||
3514 | (Metadata * Variable, Metadata *Expression), | ||||||||||||
3515 | (Variable, Expression)) | ||||||||||||
3516 | |||||||||||||
3517 | TempDIGlobalVariableExpression clone() const { return cloneImpl(); } | ||||||||||||
3518 | |||||||||||||
3519 | Metadata *getRawVariable() const { return getOperand(0); } | ||||||||||||
3520 | |||||||||||||
3521 | DIGlobalVariable *getVariable() const { | ||||||||||||
3522 | return cast_or_null<DIGlobalVariable>(getRawVariable()); | ||||||||||||
3523 | } | ||||||||||||
3524 | |||||||||||||
3525 | Metadata *getRawExpression() const { return getOperand(1); } | ||||||||||||
3526 | |||||||||||||
3527 | DIExpression *getExpression() const { | ||||||||||||
3528 | return cast<DIExpression>(getRawExpression()); | ||||||||||||
3529 | } | ||||||||||||
3530 | |||||||||||||
3531 | static bool classof(const Metadata *MD) { | ||||||||||||
3532 | return MD->getMetadataID() == DIGlobalVariableExpressionKind; | ||||||||||||
3533 | } | ||||||||||||
3534 | }; | ||||||||||||
3535 | |||||||||||||
3536 | /// Macro Info DWARF-like metadata node. | ||||||||||||
3537 | /// | ||||||||||||
3538 | /// A metadata node with a DWARF macro info (i.e., a constant named | ||||||||||||
3539 | /// \c DW_MACINFO_*, defined in llvm/BinaryFormat/Dwarf.h). Called \a | ||||||||||||
3540 | /// DIMacroNode | ||||||||||||
3541 | /// because it's potentially used for non-DWARF output. | ||||||||||||
3542 | class DIMacroNode : public MDNode { | ||||||||||||
3543 | friend class LLVMContextImpl; | ||||||||||||
3544 | friend class MDNode; | ||||||||||||
3545 | |||||||||||||
3546 | protected: | ||||||||||||
3547 | DIMacroNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned MIType, | ||||||||||||
3548 | ArrayRef<Metadata *> Ops1, | ||||||||||||
3549 | ArrayRef<Metadata *> Ops2 = std::nullopt) | ||||||||||||
3550 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||||||||||
3551 | assert(MIType < 1u << 16)(static_cast <bool> (MIType < 1u << 16) ? void (0) : __assert_fail ("MIType < 1u << 16", "llvm/include/llvm/IR/DebugInfoMetadata.h" , 3551, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
3552 | SubclassData16 = MIType; | ||||||||||||
3553 | } | ||||||||||||
3554 | ~DIMacroNode() = default; | ||||||||||||
3555 | |||||||||||||
3556 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||||||||||
3557 | return cast_or_null<Ty>(getOperand(I)); | ||||||||||||
3558 | } | ||||||||||||
3559 | |||||||||||||
3560 | StringRef getStringOperand(unsigned I) const { | ||||||||||||
3561 | if (auto *S = getOperandAs<MDString>(I)) | ||||||||||||
3562 | return S->getString(); | ||||||||||||
3563 | return StringRef(); | ||||||||||||
3564 | } | ||||||||||||
3565 | |||||||||||||
3566 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||||||||||
3567 | if (S.empty()) | ||||||||||||
3568 | return nullptr; | ||||||||||||
3569 | return MDString::get(Context, S); | ||||||||||||
3570 | } | ||||||||||||
3571 | |||||||||||||
3572 | public: | ||||||||||||
3573 | unsigned getMacinfoType() const { return SubclassData16; } | ||||||||||||
3574 | |||||||||||||
3575 | static bool classof(const Metadata *MD) { | ||||||||||||
3576 | switch (MD->getMetadataID()) { | ||||||||||||
3577 | default: | ||||||||||||
3578 | return false; | ||||||||||||
3579 | case DIMacroKind: | ||||||||||||
3580 | case DIMacroFileKind: | ||||||||||||
3581 | return true; | ||||||||||||
3582 | } | ||||||||||||
3583 | } | ||||||||||||
3584 | }; | ||||||||||||
3585 | |||||||||||||
3586 | class DIMacro : public DIMacroNode { | ||||||||||||
3587 | friend class LLVMContextImpl; | ||||||||||||
3588 | friend class MDNode; | ||||||||||||
3589 | |||||||||||||
3590 | unsigned Line; | ||||||||||||
3591 | |||||||||||||
3592 | DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line, | ||||||||||||
3593 | ArrayRef<Metadata *> Ops) | ||||||||||||
3594 | : DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {} | ||||||||||||
3595 | ~DIMacro() = default; | ||||||||||||
3596 | |||||||||||||
3597 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||||||||||
3598 | StringRef Name, StringRef Value, StorageType Storage, | ||||||||||||
3599 | bool ShouldCreate = true) { | ||||||||||||
3600 | return getImpl(Context, MIType, Line, getCanonicalMDString(Context, Name), | ||||||||||||
3601 | getCanonicalMDString(Context, Value), Storage, ShouldCreate); | ||||||||||||
3602 | } | ||||||||||||
3603 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||||||||||
3604 | MDString *Name, MDString *Value, StorageType Storage, | ||||||||||||
3605 | bool ShouldCreate = true); | ||||||||||||
3606 | |||||||||||||
3607 | TempDIMacro cloneImpl() const { | ||||||||||||
3608 | return getTemporary(getContext(), getMacinfoType(), getLine(), getName(), | ||||||||||||
3609 | getValue()); | ||||||||||||
3610 | } | ||||||||||||
3611 | |||||||||||||
3612 | public: | ||||||||||||
3613 | DEFINE_MDNODE_GET(DIMacro, | ||||||||||||
3614 | (unsigned MIType, unsigned Line, StringRef Name, | ||||||||||||
3615 | StringRef Value = ""), | ||||||||||||
3616 | (MIType, Line, Name, Value)) | ||||||||||||
3617 | DEFINE_MDNODE_GET(DIMacro, | ||||||||||||
3618 | (unsigned MIType, unsigned Line, MDString *Name, | ||||||||||||
3619 | MDString *Value), | ||||||||||||
3620 | (MIType, Line, Name, Value)) | ||||||||||||
3621 | |||||||||||||
3622 | TempDIMacro clone() const { return cloneImpl(); } | ||||||||||||
3623 | |||||||||||||
3624 | unsigned getLine() const { return Line; } | ||||||||||||
3625 | |||||||||||||
3626 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
3627 | StringRef getValue() const { return getStringOperand(1); } | ||||||||||||
3628 | |||||||||||||
3629 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
3630 | MDString *getRawValue() const { return getOperandAs<MDString>(1); } | ||||||||||||
3631 | |||||||||||||
3632 | static bool classof(const Metadata *MD) { | ||||||||||||
3633 | return MD->getMetadataID() == DIMacroKind; | ||||||||||||
3634 | } | ||||||||||||
3635 | }; | ||||||||||||
3636 | |||||||||||||
3637 | class DIMacroFile : public DIMacroNode { | ||||||||||||
3638 | friend class LLVMContextImpl; | ||||||||||||
3639 | friend class MDNode; | ||||||||||||
3640 | |||||||||||||
3641 | unsigned Line; | ||||||||||||
3642 | |||||||||||||
3643 | DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType, | ||||||||||||
3644 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||||||||||
3645 | : DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {} | ||||||||||||
3646 | ~DIMacroFile() = default; | ||||||||||||
3647 | |||||||||||||
3648 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||||||||||
3649 | unsigned Line, DIFile *File, | ||||||||||||
3650 | DIMacroNodeArray Elements, StorageType Storage, | ||||||||||||
3651 | bool ShouldCreate = true) { | ||||||||||||
3652 | return getImpl(Context, MIType, Line, static_cast<Metadata *>(File), | ||||||||||||
3653 | Elements.get(), Storage, ShouldCreate); | ||||||||||||
3654 | } | ||||||||||||
3655 | |||||||||||||
3656 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||||||||||
3657 | unsigned Line, Metadata *File, Metadata *Elements, | ||||||||||||
3658 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
3659 | |||||||||||||
3660 | TempDIMacroFile cloneImpl() const { | ||||||||||||
3661 | return getTemporary(getContext(), getMacinfoType(), getLine(), getFile(), | ||||||||||||
3662 | getElements()); | ||||||||||||
3663 | } | ||||||||||||
3664 | |||||||||||||
3665 | public: | ||||||||||||
3666 | DEFINE_MDNODE_GET(DIMacroFile, | ||||||||||||
3667 | (unsigned MIType, unsigned Line, DIFile *File, | ||||||||||||
3668 | DIMacroNodeArray Elements), | ||||||||||||
3669 | (MIType, Line, File, Elements)) | ||||||||||||
3670 | DEFINE_MDNODE_GET(DIMacroFile, | ||||||||||||
3671 | (unsigned MIType, unsigned Line, Metadata *File, | ||||||||||||
3672 | Metadata *Elements), | ||||||||||||
3673 | (MIType, Line, File, Elements)) | ||||||||||||
3674 | |||||||||||||
3675 | TempDIMacroFile clone() const { return cloneImpl(); } | ||||||||||||
3676 | |||||||||||||
3677 | void replaceElements(DIMacroNodeArray Elements) { | ||||||||||||
3678 | #ifndef NDEBUG | ||||||||||||
3679 | for (DIMacroNode *Op : getElements()) | ||||||||||||
3680 | assert(is_contained(Elements->operands(), Op) &&(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a macro node during macro node list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a macro node during macro node list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 3681, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
3681 | "Lost a macro node during macro node list replacement")(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a macro node during macro node list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a macro node during macro node list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 3681, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
3682 | #endif | ||||||||||||
3683 | replaceOperandWith(1, Elements.get()); | ||||||||||||
3684 | } | ||||||||||||
3685 | |||||||||||||
3686 | unsigned getLine() const { return Line; } | ||||||||||||
3687 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
3688 | |||||||||||||
3689 | DIMacroNodeArray getElements() const { | ||||||||||||
3690 | return cast_or_null<MDTuple>(getRawElements()); | ||||||||||||
3691 | } | ||||||||||||
3692 | |||||||||||||
3693 | Metadata *getRawFile() const { return getOperand(0); } | ||||||||||||
3694 | Metadata *getRawElements() const { return getOperand(1); } | ||||||||||||
3695 | |||||||||||||
3696 | static bool classof(const Metadata *MD) { | ||||||||||||
3697 | return MD->getMetadataID() == DIMacroFileKind; | ||||||||||||
3698 | } | ||||||||||||
3699 | }; | ||||||||||||
3700 | |||||||||||||
3701 | /// List of ValueAsMetadata, to be used as an argument to a dbg.value | ||||||||||||
3702 | /// intrinsic. | ||||||||||||
3703 | class DIArgList : public MDNode { | ||||||||||||
3704 | friend class LLVMContextImpl; | ||||||||||||
3705 | friend class MDNode; | ||||||||||||
3706 | using iterator = SmallVectorImpl<ValueAsMetadata *>::iterator; | ||||||||||||
3707 | |||||||||||||
3708 | SmallVector<ValueAsMetadata *, 4> Args; | ||||||||||||
3709 | |||||||||||||
3710 | DIArgList(LLVMContext &C, StorageType Storage, | ||||||||||||
3711 | ArrayRef<ValueAsMetadata *> Args) | ||||||||||||
3712 | : MDNode(C, DIArgListKind, Storage, std::nullopt), | ||||||||||||
3713 | Args(Args.begin(), Args.end()) { | ||||||||||||
3714 | track(); | ||||||||||||
3715 | } | ||||||||||||
3716 | ~DIArgList() { untrack(); } | ||||||||||||
3717 | |||||||||||||
3718 | static DIArgList *getImpl(LLVMContext &Context, | ||||||||||||
3719 | ArrayRef<ValueAsMetadata *> Args, | ||||||||||||
3720 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
3721 | |||||||||||||
3722 | TempDIArgList cloneImpl() const { | ||||||||||||
3723 | return getTemporary(getContext(), getArgs()); | ||||||||||||
3724 | } | ||||||||||||
3725 | |||||||||||||
3726 | void track(); | ||||||||||||
3727 | void untrack(); | ||||||||||||
3728 | void dropAllReferences(); | ||||||||||||
3729 | |||||||||||||
3730 | public: | ||||||||||||
3731 | DEFINE_MDNODE_GET(DIArgList, (ArrayRef<ValueAsMetadata *> Args), (Args)) | ||||||||||||
3732 | |||||||||||||
3733 | TempDIArgList clone() const { return cloneImpl(); } | ||||||||||||
3734 | |||||||||||||
3735 | ArrayRef<ValueAsMetadata *> getArgs() const { return Args; } | ||||||||||||
3736 | |||||||||||||
3737 | iterator args_begin() { return Args.begin(); } | ||||||||||||
3738 | iterator args_end() { return Args.end(); } | ||||||||||||
3739 | |||||||||||||
3740 | static bool classof(const Metadata *MD) { | ||||||||||||
3741 | return MD->getMetadataID() == DIArgListKind; | ||||||||||||
3742 | } | ||||||||||||
3743 | |||||||||||||
3744 | void handleChangedOperand(void *Ref, Metadata *New); | ||||||||||||
3745 | }; | ||||||||||||
3746 | |||||||||||||
3747 | /// Identifies a unique instance of a variable. | ||||||||||||
3748 | /// | ||||||||||||
3749 | /// Storage for identifying a potentially inlined instance of a variable, | ||||||||||||
3750 | /// or a fragment thereof. This guarantees that exactly one variable instance | ||||||||||||
3751 | /// may be identified by this class, even when that variable is a fragment of | ||||||||||||
3752 | /// an aggregate variable and/or there is another inlined instance of the same | ||||||||||||
3753 | /// source code variable nearby. | ||||||||||||
3754 | /// This class does not necessarily uniquely identify that variable: it is | ||||||||||||
3755 | /// possible that a DebugVariable with different parameters may point to the | ||||||||||||
3756 | /// same variable instance, but not that one DebugVariable points to multiple | ||||||||||||
3757 | /// variable instances. | ||||||||||||
3758 | class DebugVariable { | ||||||||||||
3759 | using FragmentInfo = DIExpression::FragmentInfo; | ||||||||||||
3760 | |||||||||||||
3761 | const DILocalVariable *Variable; | ||||||||||||
3762 | std::optional<FragmentInfo> Fragment; | ||||||||||||
3763 | const DILocation *InlinedAt; | ||||||||||||
3764 | |||||||||||||
3765 | /// Fragment that will overlap all other fragments. Used as default when | ||||||||||||
3766 | /// caller demands a fragment. | ||||||||||||
3767 | static const FragmentInfo DefaultFragment; | ||||||||||||
3768 | |||||||||||||
3769 | public: | ||||||||||||
3770 | DebugVariable(const DbgVariableIntrinsic *DII); | ||||||||||||
3771 | |||||||||||||
3772 | DebugVariable(const DILocalVariable *Var, | ||||||||||||
3773 | std::optional<FragmentInfo> FragmentInfo, | ||||||||||||
3774 | const DILocation *InlinedAt) | ||||||||||||
3775 | : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} | ||||||||||||
3776 | |||||||||||||
3777 | DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, | ||||||||||||
3778 | const DILocation *InlinedAt) | ||||||||||||
3779 | : Variable(Var), | ||||||||||||
3780 | Fragment(DIExpr ? DIExpr->getFragmentInfo() : std::nullopt), | ||||||||||||
3781 | InlinedAt(InlinedAt) {} | ||||||||||||
3782 | |||||||||||||
3783 | const DILocalVariable *getVariable() const { return Variable; } | ||||||||||||
3784 | std::optional<FragmentInfo> getFragment() const { return Fragment; } | ||||||||||||
3785 | const DILocation *getInlinedAt() const { return InlinedAt; } | ||||||||||||
3786 | |||||||||||||
3787 | FragmentInfo getFragmentOrDefault() const { | ||||||||||||
3788 | return Fragment.value_or(DefaultFragment); | ||||||||||||
3789 | } | ||||||||||||
3790 | |||||||||||||
3791 | static bool isDefaultFragment(const FragmentInfo F) { | ||||||||||||
3792 | return F == DefaultFragment; | ||||||||||||
3793 | } | ||||||||||||
3794 | |||||||||||||
3795 | bool operator==(const DebugVariable &Other) const { | ||||||||||||
3796 | return std::tie(Variable, Fragment, InlinedAt) == | ||||||||||||
3797 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||||||||||
3798 | } | ||||||||||||
3799 | |||||||||||||
3800 | bool operator<(const DebugVariable &Other) const { | ||||||||||||
3801 | return std::tie(Variable, Fragment, InlinedAt) < | ||||||||||||
3802 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||||||||||
3803 | } | ||||||||||||
3804 | }; | ||||||||||||
3805 | |||||||||||||
3806 | template <> struct DenseMapInfo<DebugVariable> { | ||||||||||||
3807 | using FragmentInfo = DIExpression::FragmentInfo; | ||||||||||||
3808 | |||||||||||||
3809 | /// Empty key: no key should be generated that has no DILocalVariable. | ||||||||||||
3810 | static inline DebugVariable getEmptyKey() { | ||||||||||||
3811 | return DebugVariable(nullptr, std::nullopt, nullptr); | ||||||||||||
3812 | } | ||||||||||||
3813 | |||||||||||||
3814 | /// Difference in tombstone is that the Optional is meaningful. | ||||||||||||
3815 | static inline DebugVariable getTombstoneKey() { | ||||||||||||
3816 | return DebugVariable(nullptr, {{0, 0}}, nullptr); | ||||||||||||
3817 | } | ||||||||||||
3818 | |||||||||||||
3819 | static unsigned getHashValue(const DebugVariable &D) { | ||||||||||||
3820 | unsigned HV = 0; | ||||||||||||
3821 | const std::optional<FragmentInfo> Fragment = D.getFragment(); | ||||||||||||
3822 | if (Fragment) | ||||||||||||
3823 | HV = DenseMapInfo<FragmentInfo>::getHashValue(*Fragment); | ||||||||||||
3824 | |||||||||||||
3825 | return hash_combine(D.getVariable(), HV, D.getInlinedAt()); | ||||||||||||
3826 | } | ||||||||||||
3827 | |||||||||||||
3828 | static bool isEqual(const DebugVariable &A, const DebugVariable &B) { | ||||||||||||
3829 | return A == B; | ||||||||||||
3830 | } | ||||||||||||
3831 | }; | ||||||||||||
3832 | |||||||||||||
3833 | /// Identifies a unique instance of a whole variable (discards/ignores fragment | ||||||||||||
3834 | /// information). | ||||||||||||
3835 | class DebugVariableAggregate : public DebugVariable { | ||||||||||||
3836 | public: | ||||||||||||
3837 | DebugVariableAggregate(const DbgVariableIntrinsic *DVI); | ||||||||||||
3838 | DebugVariableAggregate(const DebugVariable &V) | ||||||||||||
3839 | : DebugVariable(V.getVariable(), std::nullopt, V.getInlinedAt()) {} | ||||||||||||
3840 | }; | ||||||||||||
3841 | |||||||||||||
3842 | template <> | ||||||||||||
3843 | struct DenseMapInfo<DebugVariableAggregate> | ||||||||||||
3844 | : public DenseMapInfo<DebugVariable> {}; | ||||||||||||
3845 | } // end namespace llvm | ||||||||||||
3846 | |||||||||||||
3847 | #undef DEFINE_MDNODE_GET_UNPACK_IMPL | ||||||||||||
3848 | #undef DEFINE_MDNODE_GET_UNPACK | ||||||||||||
3849 | #undef DEFINE_MDNODE_GET | ||||||||||||
3850 | |||||||||||||
3851 | #endif // LLVM_IR_DEBUGINFOMETADATA_H |