| File: | src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/IR/Verifier.cpp |
| Warning: | line 2590, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | //===-- Verifier.cpp - Implement the Module Verifier -----------------------==// | ||||
| 2 | // | ||||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
| 6 | // | ||||
| 7 | //===----------------------------------------------------------------------===// | ||||
| 8 | // | ||||
| 9 | // This file defines the function verifier interface, that can be used for some | ||||
| 10 | // sanity checking of input to the system. | ||||
| 11 | // | ||||
| 12 | // Note that this does not provide full `Java style' security and verifications, | ||||
| 13 | // instead it just tries to ensure that code is well-formed. | ||||
| 14 | // | ||||
| 15 | // * Both of a binary operator's parameters are of the same type | ||||
| 16 | // * Verify that the indices of mem access instructions match other operands | ||||
| 17 | // * Verify that arithmetic and other things are only performed on first-class | ||||
| 18 | // types. Verify that shifts & logicals only happen on integrals f.e. | ||||
| 19 | // * All of the constants in a switch statement are of the correct type | ||||
| 20 | // * The code is in valid SSA form | ||||
| 21 | // * It should be illegal to put a label into any other type (like a structure) | ||||
| 22 | // or to return one. [except constant arrays!] | ||||
| 23 | // * Only phi nodes can be self referential: 'add i32 %0, %0 ; <int>:0' is bad | ||||
| 24 | // * PHI nodes must have an entry for each predecessor, with no extras. | ||||
| 25 | // * PHI nodes must be the first thing in a basic block, all grouped together | ||||
| 26 | // * PHI nodes must have at least one entry | ||||
| 27 | // * All basic blocks should only end with terminator insts, not contain them | ||||
| 28 | // * The entry node to a function must not have predecessors | ||||
| 29 | // * All Instructions must be embedded into a basic block | ||||
| 30 | // * Functions cannot take a void-typed parameter | ||||
| 31 | // * Verify that a function's argument list agrees with it's declared type. | ||||
| 32 | // * It is illegal to specify a name for a void value. | ||||
| 33 | // * It is illegal to have a internal global value with no initializer | ||||
| 34 | // * It is illegal to have a ret instruction that returns a value that does not | ||||
| 35 | // agree with the function return value type. | ||||
| 36 | // * Function call argument types match the function prototype | ||||
| 37 | // * A landing pad is defined by a landingpad instruction, and can be jumped to | ||||
| 38 | // only by the unwind edge of an invoke instruction. | ||||
| 39 | // * A landingpad instruction must be the first non-PHI instruction in the | ||||
| 40 | // block. | ||||
| 41 | // * Landingpad instructions must be in a function with a personality function. | ||||
| 42 | // * All other things that are tested by asserts spread about the code... | ||||
| 43 | // | ||||
| 44 | //===----------------------------------------------------------------------===// | ||||
| 45 | |||||
| 46 | #include "llvm/IR/Verifier.h" | ||||
| 47 | #include "llvm/ADT/APFloat.h" | ||||
| 48 | #include "llvm/ADT/APInt.h" | ||||
| 49 | #include "llvm/ADT/ArrayRef.h" | ||||
| 50 | #include "llvm/ADT/DenseMap.h" | ||||
| 51 | #include "llvm/ADT/MapVector.h" | ||||
| 52 | #include "llvm/ADT/Optional.h" | ||||
| 53 | #include "llvm/ADT/STLExtras.h" | ||||
| 54 | #include "llvm/ADT/SmallPtrSet.h" | ||||
| 55 | #include "llvm/ADT/SmallSet.h" | ||||
| 56 | #include "llvm/ADT/SmallVector.h" | ||||
| 57 | #include "llvm/ADT/StringExtras.h" | ||||
| 58 | #include "llvm/ADT/StringMap.h" | ||||
| 59 | #include "llvm/ADT/StringRef.h" | ||||
| 60 | #include "llvm/ADT/Twine.h" | ||||
| 61 | #include "llvm/ADT/ilist.h" | ||||
| 62 | #include "llvm/BinaryFormat/Dwarf.h" | ||||
| 63 | #include "llvm/IR/Argument.h" | ||||
| 64 | #include "llvm/IR/Attributes.h" | ||||
| 65 | #include "llvm/IR/BasicBlock.h" | ||||
| 66 | #include "llvm/IR/CFG.h" | ||||
| 67 | #include "llvm/IR/CallingConv.h" | ||||
| 68 | #include "llvm/IR/Comdat.h" | ||||
| 69 | #include "llvm/IR/Constant.h" | ||||
| 70 | #include "llvm/IR/ConstantRange.h" | ||||
| 71 | #include "llvm/IR/Constants.h" | ||||
| 72 | #include "llvm/IR/DataLayout.h" | ||||
| 73 | #include "llvm/IR/DebugInfo.h" | ||||
| 74 | #include "llvm/IR/DebugInfoMetadata.h" | ||||
| 75 | #include "llvm/IR/DebugLoc.h" | ||||
| 76 | #include "llvm/IR/DerivedTypes.h" | ||||
| 77 | #include "llvm/IR/Dominators.h" | ||||
| 78 | #include "llvm/IR/Function.h" | ||||
| 79 | #include "llvm/IR/GlobalAlias.h" | ||||
| 80 | #include "llvm/IR/GlobalValue.h" | ||||
| 81 | #include "llvm/IR/GlobalVariable.h" | ||||
| 82 | #include "llvm/IR/InlineAsm.h" | ||||
| 83 | #include "llvm/IR/InstVisitor.h" | ||||
| 84 | #include "llvm/IR/InstrTypes.h" | ||||
| 85 | #include "llvm/IR/Instruction.h" | ||||
| 86 | #include "llvm/IR/Instructions.h" | ||||
| 87 | #include "llvm/IR/IntrinsicInst.h" | ||||
| 88 | #include "llvm/IR/Intrinsics.h" | ||||
| 89 | #include "llvm/IR/IntrinsicsWebAssembly.h" | ||||
| 90 | #include "llvm/IR/LLVMContext.h" | ||||
| 91 | #include "llvm/IR/Metadata.h" | ||||
| 92 | #include "llvm/IR/Module.h" | ||||
| 93 | #include "llvm/IR/ModuleSlotTracker.h" | ||||
| 94 | #include "llvm/IR/PassManager.h" | ||||
| 95 | #include "llvm/IR/Statepoint.h" | ||||
| 96 | #include "llvm/IR/Type.h" | ||||
| 97 | #include "llvm/IR/Use.h" | ||||
| 98 | #include "llvm/IR/User.h" | ||||
| 99 | #include "llvm/IR/Value.h" | ||||
| 100 | #include "llvm/InitializePasses.h" | ||||
| 101 | #include "llvm/Pass.h" | ||||
| 102 | #include "llvm/Support/AtomicOrdering.h" | ||||
| 103 | #include "llvm/Support/Casting.h" | ||||
| 104 | #include "llvm/Support/CommandLine.h" | ||||
| 105 | #include "llvm/Support/Debug.h" | ||||
| 106 | #include "llvm/Support/ErrorHandling.h" | ||||
| 107 | #include "llvm/Support/MathExtras.h" | ||||
| 108 | #include "llvm/Support/raw_ostream.h" | ||||
| 109 | #include <algorithm> | ||||
| 110 | #include <cassert> | ||||
| 111 | #include <cstdint> | ||||
| 112 | #include <memory> | ||||
| 113 | #include <string> | ||||
| 114 | #include <utility> | ||||
| 115 | |||||
| 116 | using namespace llvm; | ||||
| 117 | |||||
| 118 | static cl::opt<bool> VerifyNoAliasScopeDomination( | ||||
| 119 | "verify-noalias-scope-decl-dom", cl::Hidden, cl::init(false), | ||||
| 120 | cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical " | ||||
| 121 | "scopes are not dominating")); | ||||
| 122 | |||||
| 123 | namespace llvm { | ||||
| 124 | |||||
| 125 | struct VerifierSupport { | ||||
| 126 | raw_ostream *OS; | ||||
| 127 | const Module &M; | ||||
| 128 | ModuleSlotTracker MST; | ||||
| 129 | Triple TT; | ||||
| 130 | const DataLayout &DL; | ||||
| 131 | LLVMContext &Context; | ||||
| 132 | |||||
| 133 | /// Track the brokenness of the module while recursively visiting. | ||||
| 134 | bool Broken = false; | ||||
| 135 | /// Broken debug info can be "recovered" from by stripping the debug info. | ||||
| 136 | bool BrokenDebugInfo = false; | ||||
| 137 | /// Whether to treat broken debug info as an error. | ||||
| 138 | bool TreatBrokenDebugInfoAsError = true; | ||||
| 139 | |||||
| 140 | explicit VerifierSupport(raw_ostream *OS, const Module &M) | ||||
| 141 | : OS(OS), M(M), MST(&M), TT(M.getTargetTriple()), DL(M.getDataLayout()), | ||||
| 142 | Context(M.getContext()) {} | ||||
| 143 | |||||
| 144 | private: | ||||
| 145 | void Write(const Module *M) { | ||||
| 146 | *OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; | ||||
| 147 | } | ||||
| 148 | |||||
| 149 | void Write(const Value *V) { | ||||
| 150 | if (V) | ||||
| 151 | Write(*V); | ||||
| 152 | } | ||||
| 153 | |||||
| 154 | void Write(const Value &V) { | ||||
| 155 | if (isa<Instruction>(V)) { | ||||
| 156 | V.print(*OS, MST); | ||||
| 157 | *OS << '\n'; | ||||
| 158 | } else { | ||||
| 159 | V.printAsOperand(*OS, true, MST); | ||||
| 160 | *OS << '\n'; | ||||
| 161 | } | ||||
| 162 | } | ||||
| 163 | |||||
| 164 | void Write(const Metadata *MD) { | ||||
| 165 | if (!MD) | ||||
| 166 | return; | ||||
| 167 | MD->print(*OS, MST, &M); | ||||
| 168 | *OS << '\n'; | ||||
| 169 | } | ||||
| 170 | |||||
| 171 | template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) { | ||||
| 172 | Write(MD.get()); | ||||
| 173 | } | ||||
| 174 | |||||
| 175 | void Write(const NamedMDNode *NMD) { | ||||
| 176 | if (!NMD) | ||||
| 177 | return; | ||||
| 178 | NMD->print(*OS, MST); | ||||
| 179 | *OS << '\n'; | ||||
| 180 | } | ||||
| 181 | |||||
| 182 | void Write(Type *T) { | ||||
| 183 | if (!T) | ||||
| 184 | return; | ||||
| 185 | *OS << ' ' << *T; | ||||
| 186 | } | ||||
| 187 | |||||
| 188 | void Write(const Comdat *C) { | ||||
| 189 | if (!C) | ||||
| 190 | return; | ||||
| 191 | *OS << *C; | ||||
| 192 | } | ||||
| 193 | |||||
| 194 | void Write(const APInt *AI) { | ||||
| 195 | if (!AI) | ||||
| 196 | return; | ||||
| 197 | *OS << *AI << '\n'; | ||||
| 198 | } | ||||
| 199 | |||||
| 200 | void Write(const unsigned i) { *OS << i << '\n'; } | ||||
| 201 | |||||
| 202 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
| 203 | void Write(const Attribute *A) { | ||||
| 204 | if (!A) | ||||
| 205 | return; | ||||
| 206 | *OS << A->getAsString() << '\n'; | ||||
| 207 | } | ||||
| 208 | |||||
| 209 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
| 210 | void Write(const AttributeSet *AS) { | ||||
| 211 | if (!AS) | ||||
| 212 | return; | ||||
| 213 | *OS << AS->getAsString() << '\n'; | ||||
| 214 | } | ||||
| 215 | |||||
| 216 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
| 217 | void Write(const AttributeList *AL) { | ||||
| 218 | if (!AL) | ||||
| 219 | return; | ||||
| 220 | AL->print(*OS); | ||||
| 221 | } | ||||
| 222 | |||||
| 223 | template <typename T> void Write(ArrayRef<T> Vs) { | ||||
| 224 | for (const T &V : Vs) | ||||
| 225 | Write(V); | ||||
| 226 | } | ||||
| 227 | |||||
| 228 | template <typename T1, typename... Ts> | ||||
| 229 | void WriteTs(const T1 &V1, const Ts &... Vs) { | ||||
| 230 | Write(V1); | ||||
| 231 | WriteTs(Vs...); | ||||
| 232 | } | ||||
| 233 | |||||
| 234 | template <typename... Ts> void WriteTs() {} | ||||
| 235 | |||||
| 236 | public: | ||||
| 237 | /// A check failed, so printout out the condition and the message. | ||||
| 238 | /// | ||||
| 239 | /// This provides a nice place to put a breakpoint if you want to see why | ||||
| 240 | /// something is not correct. | ||||
| 241 | void CheckFailed(const Twine &Message) { | ||||
| 242 | if (OS) | ||||
| 243 | *OS << Message << '\n'; | ||||
| 244 | Broken = true; | ||||
| 245 | } | ||||
| 246 | |||||
| 247 | /// A check failed (with values to print). | ||||
| 248 | /// | ||||
| 249 | /// This calls the Message-only version so that the above is easier to set a | ||||
| 250 | /// breakpoint on. | ||||
| 251 | template <typename T1, typename... Ts> | ||||
| 252 | void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { | ||||
| 253 | CheckFailed(Message); | ||||
| 254 | if (OS) | ||||
| 255 | WriteTs(V1, Vs...); | ||||
| 256 | } | ||||
| 257 | |||||
| 258 | /// A debug info check failed. | ||||
| 259 | void DebugInfoCheckFailed(const Twine &Message) { | ||||
| 260 | if (OS) | ||||
| 261 | *OS << Message << '\n'; | ||||
| 262 | Broken |= TreatBrokenDebugInfoAsError; | ||||
| 263 | BrokenDebugInfo = true; | ||||
| 264 | } | ||||
| 265 | |||||
| 266 | /// A debug info check failed (with values to print). | ||||
| 267 | template <typename T1, typename... Ts> | ||||
| 268 | void DebugInfoCheckFailed(const Twine &Message, const T1 &V1, | ||||
| 269 | const Ts &... Vs) { | ||||
| 270 | DebugInfoCheckFailed(Message); | ||||
| 271 | if (OS) | ||||
| 272 | WriteTs(V1, Vs...); | ||||
| 273 | } | ||||
| 274 | }; | ||||
| 275 | |||||
| 276 | } // namespace llvm | ||||
| 277 | |||||
| 278 | namespace { | ||||
| 279 | |||||
| 280 | class Verifier : public InstVisitor<Verifier>, VerifierSupport { | ||||
| 281 | friend class InstVisitor<Verifier>; | ||||
| 282 | |||||
| 283 | DominatorTree DT; | ||||
| 284 | |||||
| 285 | /// When verifying a basic block, keep track of all of the | ||||
| 286 | /// instructions we have seen so far. | ||||
| 287 | /// | ||||
| 288 | /// This allows us to do efficient dominance checks for the case when an | ||||
| 289 | /// instruction has an operand that is an instruction in the same block. | ||||
| 290 | SmallPtrSet<Instruction *, 16> InstsInThisBlock; | ||||
| 291 | |||||
| 292 | /// Keep track of the metadata nodes that have been checked already. | ||||
| 293 | SmallPtrSet<const Metadata *, 32> MDNodes; | ||||
| 294 | |||||
| 295 | /// Keep track which DISubprogram is attached to which function. | ||||
| 296 | DenseMap<const DISubprogram *, const Function *> DISubprogramAttachments; | ||||
| 297 | |||||
| 298 | /// Track all DICompileUnits visited. | ||||
| 299 | SmallPtrSet<const Metadata *, 2> CUVisited; | ||||
| 300 | |||||
| 301 | /// The result type for a landingpad. | ||||
| 302 | Type *LandingPadResultTy; | ||||
| 303 | |||||
| 304 | /// Whether we've seen a call to @llvm.localescape in this function | ||||
| 305 | /// already. | ||||
| 306 | bool SawFrameEscape; | ||||
| 307 | |||||
| 308 | /// Whether the current function has a DISubprogram attached to it. | ||||
| 309 | bool HasDebugInfo = false; | ||||
| 310 | |||||
| 311 | /// The current source language. | ||||
| 312 | dwarf::SourceLanguage CurrentSourceLang = dwarf::DW_LANG_lo_user; | ||||
| 313 | |||||
| 314 | /// Whether source was present on the first DIFile encountered in each CU. | ||||
| 315 | DenseMap<const DICompileUnit *, bool> HasSourceDebugInfo; | ||||
| 316 | |||||
| 317 | /// Stores the count of how many objects were passed to llvm.localescape for a | ||||
| 318 | /// given function and the largest index passed to llvm.localrecover. | ||||
| 319 | DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo; | ||||
| 320 | |||||
| 321 | // Maps catchswitches and cleanuppads that unwind to siblings to the | ||||
| 322 | // terminators that indicate the unwind, used to detect cycles therein. | ||||
| 323 | MapVector<Instruction *, Instruction *> SiblingFuncletInfo; | ||||
| 324 | |||||
| 325 | /// Cache of constants visited in search of ConstantExprs. | ||||
| 326 | SmallPtrSet<const Constant *, 32> ConstantExprVisited; | ||||
| 327 | |||||
| 328 | /// Cache of declarations of the llvm.experimental.deoptimize.<ty> intrinsic. | ||||
| 329 | SmallVector<const Function *, 4> DeoptimizeDeclarations; | ||||
| 330 | |||||
| 331 | /// Cache of attribute lists verified. | ||||
| 332 | SmallPtrSet<const void *, 32> AttributeListsVisited; | ||||
| 333 | |||||
| 334 | // Verify that this GlobalValue is only used in this module. | ||||
| 335 | // This map is used to avoid visiting uses twice. We can arrive at a user | ||||
| 336 | // twice, if they have multiple operands. In particular for very large | ||||
| 337 | // constant expressions, we can arrive at a particular user many times. | ||||
| 338 | SmallPtrSet<const Value *, 32> GlobalValueVisited; | ||||
| 339 | |||||
| 340 | // Keeps track of duplicate function argument debug info. | ||||
| 341 | SmallVector<const DILocalVariable *, 16> DebugFnArgs; | ||||
| 342 | |||||
| 343 | TBAAVerifier TBAAVerifyHelper; | ||||
| 344 | |||||
| 345 | SmallVector<IntrinsicInst *, 4> NoAliasScopeDecls; | ||||
| 346 | |||||
| 347 | void checkAtomicMemAccessSize(Type *Ty, const Instruction *I); | ||||
| 348 | |||||
| 349 | public: | ||||
| 350 | explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError, | ||||
| 351 | const Module &M) | ||||
| 352 | : VerifierSupport(OS, M), LandingPadResultTy(nullptr), | ||||
| 353 | SawFrameEscape(false), TBAAVerifyHelper(this) { | ||||
| 354 | TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError; | ||||
| 355 | } | ||||
| 356 | |||||
| 357 | bool hasBrokenDebugInfo() const { return BrokenDebugInfo; } | ||||
| 358 | |||||
| 359 | bool verify(const Function &F) { | ||||
| 360 | assert(F.getParent() == &M &&((void)0) | ||||
| 361 | "An instance of this class only works with a specific module!")((void)0); | ||||
| 362 | |||||
| 363 | // First ensure the function is well-enough formed to compute dominance | ||||
| 364 | // information, and directly compute a dominance tree. We don't rely on the | ||||
| 365 | // pass manager to provide this as it isolates us from a potentially | ||||
| 366 | // out-of-date dominator tree and makes it significantly more complex to run | ||||
| 367 | // this code outside of a pass manager. | ||||
| 368 | // FIXME: It's really gross that we have to cast away constness here. | ||||
| 369 | if (!F.empty()) | ||||
| 370 | DT.recalculate(const_cast<Function &>(F)); | ||||
| 371 | |||||
| 372 | for (const BasicBlock &BB : F) { | ||||
| 373 | if (!BB.empty() && BB.back().isTerminator()) | ||||
| 374 | continue; | ||||
| 375 | |||||
| 376 | if (OS) { | ||||
| 377 | *OS << "Basic Block in function '" << F.getName() | ||||
| 378 | << "' does not have terminator!\n"; | ||||
| 379 | BB.printAsOperand(*OS, true, MST); | ||||
| 380 | *OS << "\n"; | ||||
| 381 | } | ||||
| 382 | return false; | ||||
| 383 | } | ||||
| 384 | |||||
| 385 | Broken = false; | ||||
| 386 | // FIXME: We strip const here because the inst visitor strips const. | ||||
| 387 | visit(const_cast<Function &>(F)); | ||||
| 388 | verifySiblingFuncletUnwinds(); | ||||
| 389 | InstsInThisBlock.clear(); | ||||
| 390 | DebugFnArgs.clear(); | ||||
| 391 | LandingPadResultTy = nullptr; | ||||
| 392 | SawFrameEscape = false; | ||||
| 393 | SiblingFuncletInfo.clear(); | ||||
| 394 | verifyNoAliasScopeDecl(); | ||||
| 395 | NoAliasScopeDecls.clear(); | ||||
| 396 | |||||
| 397 | return !Broken; | ||||
| 398 | } | ||||
| 399 | |||||
| 400 | /// Verify the module that this instance of \c Verifier was initialized with. | ||||
| 401 | bool verify() { | ||||
| 402 | Broken = false; | ||||
| 403 | |||||
| 404 | // Collect all declarations of the llvm.experimental.deoptimize intrinsic. | ||||
| 405 | for (const Function &F : M) | ||||
| 406 | if (F.getIntrinsicID() == Intrinsic::experimental_deoptimize) | ||||
| 407 | DeoptimizeDeclarations.push_back(&F); | ||||
| 408 | |||||
| 409 | // Now that we've visited every function, verify that we never asked to | ||||
| 410 | // recover a frame index that wasn't escaped. | ||||
| 411 | verifyFrameRecoverIndices(); | ||||
| 412 | for (const GlobalVariable &GV : M.globals()) | ||||
| 413 | visitGlobalVariable(GV); | ||||
| 414 | |||||
| 415 | for (const GlobalAlias &GA : M.aliases()) | ||||
| 416 | visitGlobalAlias(GA); | ||||
| 417 | |||||
| 418 | for (const NamedMDNode &NMD : M.named_metadata()) | ||||
| 419 | visitNamedMDNode(NMD); | ||||
| 420 | |||||
| 421 | for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) | ||||
| 422 | visitComdat(SMEC.getValue()); | ||||
| 423 | |||||
| 424 | visitModuleFlags(M); | ||||
| 425 | visitModuleIdents(M); | ||||
| 426 | visitModuleCommandLines(M); | ||||
| 427 | |||||
| 428 | verifyCompileUnits(); | ||||
| 429 | |||||
| 430 | verifyDeoptimizeCallingConvs(); | ||||
| 431 | DISubprogramAttachments.clear(); | ||||
| 432 | return !Broken; | ||||
| 433 | } | ||||
| 434 | |||||
| 435 | private: | ||||
| 436 | /// Whether a metadata node is allowed to be, or contain, a DILocation. | ||||
| 437 | enum class AreDebugLocsAllowed { No, Yes }; | ||||
| 438 | |||||
| 439 | // Verification methods... | ||||
| 440 | void visitGlobalValue(const GlobalValue &GV); | ||||
| 441 | void visitGlobalVariable(const GlobalVariable &GV); | ||||
| 442 | void visitGlobalAlias(const GlobalAlias &GA); | ||||
| 443 | void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); | ||||
| 444 | void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited, | ||||
| 445 | const GlobalAlias &A, const Constant &C); | ||||
| 446 | void visitNamedMDNode(const NamedMDNode &NMD); | ||||
| 447 | void visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs); | ||||
| 448 | void visitMetadataAsValue(const MetadataAsValue &MD, Function *F); | ||||
| 449 | void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); | ||||
| 450 | void visitComdat(const Comdat &C); | ||||
| 451 | void visitModuleIdents(const Module &M); | ||||
| 452 | void visitModuleCommandLines(const Module &M); | ||||
| 453 | void visitModuleFlags(const Module &M); | ||||
| 454 | void visitModuleFlag(const MDNode *Op, | ||||
| 455 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
| 456 | SmallVectorImpl<const MDNode *> &Requirements); | ||||
| 457 | void visitModuleFlagCGProfileEntry(const MDOperand &MDO); | ||||
| 458 | void visitFunction(const Function &F); | ||||
| 459 | void visitBasicBlock(BasicBlock &BB); | ||||
| 460 | void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); | ||||
| 461 | void visitDereferenceableMetadata(Instruction &I, MDNode *MD); | ||||
| 462 | void visitProfMetadata(Instruction &I, MDNode *MD); | ||||
| 463 | void visitAnnotationMetadata(MDNode *Annotation); | ||||
| 464 | |||||
| 465 | template <class Ty> bool isValidMetadataArray(const MDTuple &N); | ||||
| 466 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); | ||||
| 467 | #include "llvm/IR/Metadata.def" | ||||
| 468 | void visitDIScope(const DIScope &N); | ||||
| 469 | void visitDIVariable(const DIVariable &N); | ||||
| 470 | void visitDILexicalBlockBase(const DILexicalBlockBase &N); | ||||
| 471 | void visitDITemplateParameter(const DITemplateParameter &N); | ||||
| 472 | |||||
| 473 | void visitTemplateParams(const MDNode &N, const Metadata &RawParams); | ||||
| 474 | |||||
| 475 | // InstVisitor overrides... | ||||
| 476 | using InstVisitor<Verifier>::visit; | ||||
| 477 | void visit(Instruction &I); | ||||
| 478 | |||||
| 479 | void visitTruncInst(TruncInst &I); | ||||
| 480 | void visitZExtInst(ZExtInst &I); | ||||
| 481 | void visitSExtInst(SExtInst &I); | ||||
| 482 | void visitFPTruncInst(FPTruncInst &I); | ||||
| 483 | void visitFPExtInst(FPExtInst &I); | ||||
| 484 | void visitFPToUIInst(FPToUIInst &I); | ||||
| 485 | void visitFPToSIInst(FPToSIInst &I); | ||||
| 486 | void visitUIToFPInst(UIToFPInst &I); | ||||
| 487 | void visitSIToFPInst(SIToFPInst &I); | ||||
| 488 | void visitIntToPtrInst(IntToPtrInst &I); | ||||
| 489 | void visitPtrToIntInst(PtrToIntInst &I); | ||||
| 490 | void visitBitCastInst(BitCastInst &I); | ||||
| 491 | void visitAddrSpaceCastInst(AddrSpaceCastInst &I); | ||||
| 492 | void visitPHINode(PHINode &PN); | ||||
| 493 | void visitCallBase(CallBase &Call); | ||||
| 494 | void visitUnaryOperator(UnaryOperator &U); | ||||
| 495 | void visitBinaryOperator(BinaryOperator &B); | ||||
| 496 | void visitICmpInst(ICmpInst &IC); | ||||
| 497 | void visitFCmpInst(FCmpInst &FC); | ||||
| 498 | void visitExtractElementInst(ExtractElementInst &EI); | ||||
| 499 | void visitInsertElementInst(InsertElementInst &EI); | ||||
| 500 | void visitShuffleVectorInst(ShuffleVectorInst &EI); | ||||
| 501 | void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); } | ||||
| 502 | void visitCallInst(CallInst &CI); | ||||
| 503 | void visitInvokeInst(InvokeInst &II); | ||||
| 504 | void visitGetElementPtrInst(GetElementPtrInst &GEP); | ||||
| 505 | void visitLoadInst(LoadInst &LI); | ||||
| 506 | void visitStoreInst(StoreInst &SI); | ||||
| 507 | void verifyDominatesUse(Instruction &I, unsigned i); | ||||
| 508 | void visitInstruction(Instruction &I); | ||||
| 509 | void visitTerminator(Instruction &I); | ||||
| 510 | void visitBranchInst(BranchInst &BI); | ||||
| 511 | void visitReturnInst(ReturnInst &RI); | ||||
| 512 | void visitSwitchInst(SwitchInst &SI); | ||||
| 513 | void visitIndirectBrInst(IndirectBrInst &BI); | ||||
| 514 | void visitCallBrInst(CallBrInst &CBI); | ||||
| 515 | void visitSelectInst(SelectInst &SI); | ||||
| 516 | void visitUserOp1(Instruction &I); | ||||
| 517 | void visitUserOp2(Instruction &I) { visitUserOp1(I); } | ||||
| 518 | void visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call); | ||||
| 519 | void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); | ||||
| 520 | void visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII); | ||||
| 521 | void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI); | ||||
| 522 | void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); | ||||
| 523 | void visitAtomicRMWInst(AtomicRMWInst &RMWI); | ||||
| 524 | void visitFenceInst(FenceInst &FI); | ||||
| 525 | void visitAllocaInst(AllocaInst &AI); | ||||
| 526 | void visitExtractValueInst(ExtractValueInst &EVI); | ||||
| 527 | void visitInsertValueInst(InsertValueInst &IVI); | ||||
| 528 | void visitEHPadPredecessors(Instruction &I); | ||||
| 529 | void visitLandingPadInst(LandingPadInst &LPI); | ||||
| 530 | void visitResumeInst(ResumeInst &RI); | ||||
| 531 | void visitCatchPadInst(CatchPadInst &CPI); | ||||
| 532 | void visitCatchReturnInst(CatchReturnInst &CatchReturn); | ||||
| 533 | void visitCleanupPadInst(CleanupPadInst &CPI); | ||||
| 534 | void visitFuncletPadInst(FuncletPadInst &FPI); | ||||
| 535 | void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch); | ||||
| 536 | void visitCleanupReturnInst(CleanupReturnInst &CRI); | ||||
| 537 | |||||
| 538 | void verifySwiftErrorCall(CallBase &Call, const Value *SwiftErrorVal); | ||||
| 539 | void verifySwiftErrorValue(const Value *SwiftErrorVal); | ||||
| 540 | void verifyTailCCMustTailAttrs(AttrBuilder Attrs, StringRef Context); | ||||
| 541 | void verifyMustTailCall(CallInst &CI); | ||||
| 542 | bool verifyAttributeCount(AttributeList Attrs, unsigned Params); | ||||
| 543 | void verifyAttributeTypes(AttributeSet Attrs, const Value *V); | ||||
| 544 | void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V); | ||||
| 545 | void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
| 546 | const Value *V); | ||||
| 547 | void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
| 548 | const Value *V, bool IsIntrinsic); | ||||
| 549 | void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs); | ||||
| 550 | |||||
| 551 | void visitConstantExprsRecursively(const Constant *EntryC); | ||||
| 552 | void visitConstantExpr(const ConstantExpr *CE); | ||||
| 553 | void verifyStatepoint(const CallBase &Call); | ||||
| 554 | void verifyFrameRecoverIndices(); | ||||
| 555 | void verifySiblingFuncletUnwinds(); | ||||
| 556 | |||||
| 557 | void verifyFragmentExpression(const DbgVariableIntrinsic &I); | ||||
| 558 | template <typename ValueOrMetadata> | ||||
| 559 | void verifyFragmentExpression(const DIVariable &V, | ||||
| 560 | DIExpression::FragmentInfo Fragment, | ||||
| 561 | ValueOrMetadata *Desc); | ||||
| 562 | void verifyFnArgs(const DbgVariableIntrinsic &I); | ||||
| 563 | void verifyNotEntryValue(const DbgVariableIntrinsic &I); | ||||
| 564 | |||||
| 565 | /// Module-level debug info verification... | ||||
| 566 | void verifyCompileUnits(); | ||||
| 567 | |||||
| 568 | /// Module-level verification that all @llvm.experimental.deoptimize | ||||
| 569 | /// declarations share the same calling convention. | ||||
| 570 | void verifyDeoptimizeCallingConvs(); | ||||
| 571 | |||||
| 572 | /// Verify all-or-nothing property of DIFile source attribute within a CU. | ||||
| 573 | void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F); | ||||
| 574 | |||||
| 575 | /// Verify the llvm.experimental.noalias.scope.decl declarations | ||||
| 576 | void verifyNoAliasScopeDecl(); | ||||
| 577 | }; | ||||
| 578 | |||||
| 579 | } // end anonymous namespace | ||||
| 580 | |||||
| 581 | /// We know that cond should be true, if not print an error message. | ||||
| 582 | #define Assert(C, ...)do { if (!(C)) { CheckFailed(...); return; } } while (false) \ | ||||
| 583 | do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (false) | ||||
| 584 | |||||
| 585 | /// We know that a debug info condition should be true, if not print | ||||
| 586 | /// an error message. | ||||
| 587 | #define AssertDI(C, ...)do { if (!(C)) { DebugInfoCheckFailed(...); return; } } while (false) \ | ||||
| 588 | do { if (!(C)) { DebugInfoCheckFailed(__VA_ARGS__); return; } } while (false) | ||||
| 589 | |||||
| 590 | void Verifier::visit(Instruction &I) { | ||||
| 591 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) | ||||
| 592 | Assert(I.getOperand(i) != nullptr, "Operand is null", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Operand is null" , &I); return; } } while (false); | ||||
| 593 | InstVisitor<Verifier>::visit(I); | ||||
| 594 | } | ||||
| 595 | |||||
| 596 | // Helper to recursively iterate over indirect users. By | ||||
| 597 | // returning false, the callback can ask to stop recursing | ||||
| 598 | // further. | ||||
| 599 | static void forEachUser(const Value *User, | ||||
| 600 | SmallPtrSet<const Value *, 32> &Visited, | ||||
| 601 | llvm::function_ref<bool(const Value *)> Callback) { | ||||
| 602 | if (!Visited.insert(User).second) | ||||
| 603 | return; | ||||
| 604 | for (const Value *TheNextUser : User->materialized_users()) | ||||
| 605 | if (Callback(TheNextUser)) | ||||
| 606 | forEachUser(TheNextUser, Visited, Callback); | ||||
| 607 | } | ||||
| 608 | |||||
| 609 | void Verifier::visitGlobalValue(const GlobalValue &GV) { | ||||
| 610 | Assert(!GV.isDeclaration() || GV.hasValidDeclarationLinkage(),do { if (!(!GV.isDeclaration() || GV.hasValidDeclarationLinkage ())) { CheckFailed("Global is external, but doesn't have external or weak linkage!" , &GV); return; } } while (false) | ||||
| 611 | "Global is external, but doesn't have external or weak linkage!", &GV)do { if (!(!GV.isDeclaration() || GV.hasValidDeclarationLinkage ())) { CheckFailed("Global is external, but doesn't have external or weak linkage!" , &GV); return; } } while (false); | ||||
| 612 | |||||
| 613 | if (const GlobalObject *GO = dyn_cast<GlobalObject>(&GV)) | ||||
| 614 | Assert(GO->getAlignment() <= Value::MaximumAlignment,do { if (!(GO->getAlignment() <= Value::MaximumAlignment )) { CheckFailed("huge alignment values are unsupported", GO) ; return; } } while (false) | ||||
| 615 | "huge alignment values are unsupported", GO)do { if (!(GO->getAlignment() <= Value::MaximumAlignment )) { CheckFailed("huge alignment values are unsupported", GO) ; return; } } while (false); | ||||
| 616 | Assert(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),do { if (!(!GV.hasAppendingLinkage() || isa<GlobalVariable >(GV))) { CheckFailed("Only global variables can have appending linkage!" , &GV); return; } } while (false) | ||||
| 617 | "Only global variables can have appending linkage!", &GV)do { if (!(!GV.hasAppendingLinkage() || isa<GlobalVariable >(GV))) { CheckFailed("Only global variables can have appending linkage!" , &GV); return; } } while (false); | ||||
| 618 | |||||
| 619 | if (GV.hasAppendingLinkage()) { | ||||
| 620 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV); | ||||
| 621 | Assert(GVar && GVar->getValueType()->isArrayTy(),do { if (!(GVar && GVar->getValueType()->isArrayTy ())) { CheckFailed("Only global arrays can have appending linkage!" , GVar); return; } } while (false) | ||||
| 622 | "Only global arrays can have appending linkage!", GVar)do { if (!(GVar && GVar->getValueType()->isArrayTy ())) { CheckFailed("Only global arrays can have appending linkage!" , GVar); return; } } while (false); | ||||
| 623 | } | ||||
| 624 | |||||
| 625 | if (GV.isDeclarationForLinker()) | ||||
| 626 | Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV)do { if (!(!GV.hasComdat())) { CheckFailed("Declaration may not be in a Comdat!" , &GV); return; } } while (false); | ||||
| 627 | |||||
| 628 | if (GV.hasDLLImportStorageClass()) { | ||||
| 629 | Assert(!GV.isDSOLocal(),do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false) | ||||
| 630 | "GlobalValue with DLLImport Storage is dso_local!", &GV)do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false); | ||||
| 631 | |||||
| 632 | Assert((GV.isDeclaration() &&do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
| 633 | (GV.hasExternalLinkage() || GV.hasExternalWeakLinkage())) ||do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
| 634 | GV.hasAvailableExternallyLinkage(),do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
| 635 | "Global is marked as dllimport, but not external", &GV)do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false); | ||||
| 636 | } | ||||
| 637 | |||||
| 638 | if (GV.isImplicitDSOLocal()) | ||||
| 639 | Assert(GV.isDSOLocal(),do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
| 640 | "GlobalValue with local linkage or non-default "do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
| 641 | "visibility must be dso_local!",do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
| 642 | &GV)do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false); | ||||
| 643 | |||||
| 644 | forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool { | ||||
| 645 | if (const Instruction *I = dyn_cast<Instruction>(V)) { | ||||
| 646 | if (!I->getParent() || !I->getParent()->getParent()) | ||||
| 647 | CheckFailed("Global is referenced by parentless instruction!", &GV, &M, | ||||
| 648 | I); | ||||
| 649 | else if (I->getParent()->getParent()->getParent() != &M) | ||||
| 650 | CheckFailed("Global is referenced in a different module!", &GV, &M, I, | ||||
| 651 | I->getParent()->getParent(), | ||||
| 652 | I->getParent()->getParent()->getParent()); | ||||
| 653 | return false; | ||||
| 654 | } else if (const Function *F = dyn_cast<Function>(V)) { | ||||
| 655 | if (F->getParent() != &M) | ||||
| 656 | CheckFailed("Global is used by function in a different module", &GV, &M, | ||||
| 657 | F, F->getParent()); | ||||
| 658 | return false; | ||||
| 659 | } | ||||
| 660 | return true; | ||||
| 661 | }); | ||||
| 662 | } | ||||
| 663 | |||||
| 664 | void Verifier::visitGlobalVariable(const GlobalVariable &GV) { | ||||
| 665 | if (GV.hasInitializer()) { | ||||
| 666 | Assert(GV.getInitializer()->getType() == GV.getValueType(),do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
| 667 | "Global variable initializer type does not match global "do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
| 668 | "variable type!",do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
| 669 | &GV)do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false); | ||||
| 670 | // If the global has common linkage, it must have a zero initializer and | ||||
| 671 | // cannot be constant. | ||||
| 672 | if (GV.hasCommonLinkage()) { | ||||
| 673 | Assert(GV.getInitializer()->isNullValue(),do { if (!(GV.getInitializer()->isNullValue())) { CheckFailed ("'common' global must have a zero initializer!", &GV); return ; } } while (false) | ||||
| 674 | "'common' global must have a zero initializer!", &GV)do { if (!(GV.getInitializer()->isNullValue())) { CheckFailed ("'common' global must have a zero initializer!", &GV); return ; } } while (false); | ||||
| 675 | Assert(!GV.isConstant(), "'common' global may not be marked constant!",do { if (!(!GV.isConstant())) { CheckFailed("'common' global may not be marked constant!" , &GV); return; } } while (false) | ||||
| 676 | &GV)do { if (!(!GV.isConstant())) { CheckFailed("'common' global may not be marked constant!" , &GV); return; } } while (false); | ||||
| 677 | Assert(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV)do { if (!(!GV.hasComdat())) { CheckFailed("'common' global may not be in a Comdat!" , &GV); return; } } while (false); | ||||
| 678 | } | ||||
| 679 | } | ||||
| 680 | |||||
| 681 | if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || | ||||
| 682 | GV.getName() == "llvm.global_dtors")) { | ||||
| 683 | Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 684 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 685 | // Don't worry about emitting an error for it not being an array, | ||||
| 686 | // visitGlobalValue will complain on appending non-array. | ||||
| 687 | if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) { | ||||
| 688 | StructType *STy = dyn_cast<StructType>(ATy->getElementType()); | ||||
| 689 | PointerType *FuncPtrTy = | ||||
| 690 | FunctionType::get(Type::getVoidTy(Context), false)-> | ||||
| 691 | getPointerTo(DL.getProgramAddressSpace()); | ||||
| 692 | Assert(STy &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 693 | (STy->getNumElements() == 2 || STy->getNumElements() == 3) &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 694 | STy->getTypeAtIndex(0u)->isIntegerTy(32) &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 695 | STy->getTypeAtIndex(1) == FuncPtrTy,do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 696 | "wrong type for intrinsic global variable", &GV)do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 697 | Assert(STy->getNumElements() == 3,do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify i8* null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
| 698 | "the third field of the element type is mandatory, "do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify i8* null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
| 699 | "specify i8* null to migrate from the obsoleted 2-field form")do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify i8* null to migrate from the obsoleted 2-field form" ); return; } } while (false); | ||||
| 700 | Type *ETy = STy->getTypeAtIndex(2); | ||||
| 701 | Type *Int8Ty = Type::getInt8Ty(ETy->getContext()); | ||||
| 702 | Assert(ETy->isPointerTy() &&do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false) | ||||
| 703 | cast<PointerType>(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty),do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false) | ||||
| 704 | "wrong type for intrinsic global variable", &GV)do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false); | ||||
| 705 | } | ||||
| 706 | } | ||||
| 707 | |||||
| 708 | if (GV.hasName() && (GV.getName() == "llvm.used" || | ||||
| 709 | GV.getName() == "llvm.compiler.used")) { | ||||
| 710 | Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 711 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 712 | Type *GVType = GV.getValueType(); | ||||
| 713 | if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) { | ||||
| 714 | PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType()); | ||||
| 715 | Assert(PTy, "wrong type for intrinsic global variable", &GV)do { if (!(PTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 716 | if (GV.hasInitializer()) { | ||||
| 717 | const Constant *Init = GV.getInitializer(); | ||||
| 718 | const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); | ||||
| 719 | Assert(InitArray, "wrong initalizer for intrinsic global variable",do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false) | ||||
| 720 | Init)do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false); | ||||
| 721 | for (Value *Op : InitArray->operands()) { | ||||
| 722 | Value *V = Op->stripPointerCasts(); | ||||
| 723 | Assert(isa<GlobalVariable>(V) || isa<Function>(V) ||do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed("invalid llvm.used member" , V); return; } } while (false) | ||||
| 724 | isa<GlobalAlias>(V),do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed("invalid llvm.used member" , V); return; } } while (false) | ||||
| 725 | "invalid llvm.used member", V)do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed("invalid llvm.used member" , V); return; } } while (false); | ||||
| 726 | Assert(V->hasName(), "members of llvm.used must be named", V)do { if (!(V->hasName())) { CheckFailed("members of llvm.used must be named" , V); return; } } while (false); | ||||
| 727 | } | ||||
| 728 | } | ||||
| 729 | } | ||||
| 730 | } | ||||
| 731 | |||||
| 732 | // Visit any debug info attachments. | ||||
| 733 | SmallVector<MDNode *, 1> MDs; | ||||
| 734 | GV.getMetadata(LLVMContext::MD_dbg, MDs); | ||||
| 735 | for (auto *MD : MDs) { | ||||
| 736 | if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD)) | ||||
| 737 | visitDIGlobalVariableExpression(*GVE); | ||||
| 738 | else | ||||
| 739 | AssertDI(false, "!dbg attachment of global variable must be a "do { if (!(false)) { DebugInfoCheckFailed("!dbg attachment of global variable must be a " "DIGlobalVariableExpression"); return; } } while (false) | ||||
| 740 | "DIGlobalVariableExpression")do { if (!(false)) { DebugInfoCheckFailed("!dbg attachment of global variable must be a " "DIGlobalVariableExpression"); return; } } while (false); | ||||
| 741 | } | ||||
| 742 | |||||
| 743 | // Scalable vectors cannot be global variables, since we don't know | ||||
| 744 | // the runtime size. If the global is an array containing scalable vectors, | ||||
| 745 | // that will be caught by the isValidElementType methods in StructType or | ||||
| 746 | // ArrayType instead. | ||||
| 747 | Assert(!isa<ScalableVectorType>(GV.getValueType()),do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false) | ||||
| 748 | "Globals cannot contain scalable vectors", &GV)do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false); | ||||
| 749 | |||||
| 750 | if (auto *STy = dyn_cast<StructType>(GV.getValueType())) | ||||
| 751 | Assert(!STy->containsScalableVectorType(),do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false) | ||||
| 752 | "Globals cannot contain scalable vectors", &GV)do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false); | ||||
| 753 | |||||
| 754 | if (!GV.hasInitializer()) { | ||||
| 755 | visitGlobalValue(GV); | ||||
| 756 | return; | ||||
| 757 | } | ||||
| 758 | |||||
| 759 | // Walk any aggregate initializers looking for bitcasts between address spaces | ||||
| 760 | visitConstantExprsRecursively(GV.getInitializer()); | ||||
| 761 | |||||
| 762 | visitGlobalValue(GV); | ||||
| 763 | } | ||||
| 764 | |||||
| 765 | void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { | ||||
| 766 | SmallPtrSet<const GlobalAlias*, 4> Visited; | ||||
| 767 | Visited.insert(&GA); | ||||
| 768 | visitAliaseeSubExpr(Visited, GA, C); | ||||
| 769 | } | ||||
| 770 | |||||
| 771 | void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited, | ||||
| 772 | const GlobalAlias &GA, const Constant &C) { | ||||
| 773 | if (const auto *GV = dyn_cast<GlobalValue>(&C)) { | ||||
| 774 | Assert(!GV->isDeclarationForLinker(), "Alias must point to a definition",do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false) | ||||
| 775 | &GA)do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false); | ||||
| 776 | |||||
| 777 | if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { | ||||
| 778 | Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA)do { if (!(Visited.insert(GA2).second)) { CheckFailed("Aliases cannot form a cycle" , &GA); return; } } while (false); | ||||
| 779 | |||||
| 780 | Assert(!GA2->isInterposable(), "Alias cannot point to an interposable alias",do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false) | ||||
| 781 | &GA)do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false); | ||||
| 782 | } else { | ||||
| 783 | // Only continue verifying subexpressions of GlobalAliases. | ||||
| 784 | // Do not recurse into global initializers. | ||||
| 785 | return; | ||||
| 786 | } | ||||
| 787 | } | ||||
| 788 | |||||
| 789 | if (const auto *CE = dyn_cast<ConstantExpr>(&C)) | ||||
| 790 | visitConstantExprsRecursively(CE); | ||||
| 791 | |||||
| 792 | for (const Use &U : C.operands()) { | ||||
| 793 | Value *V = &*U; | ||||
| 794 | if (const auto *GA2 = dyn_cast<GlobalAlias>(V)) | ||||
| 795 | visitAliaseeSubExpr(Visited, GA, *GA2->getAliasee()); | ||||
| 796 | else if (const auto *C2 = dyn_cast<Constant>(V)) | ||||
| 797 | visitAliaseeSubExpr(Visited, GA, *C2); | ||||
| 798 | } | ||||
| 799 | } | ||||
| 800 | |||||
| 801 | void Verifier::visitGlobalAlias(const GlobalAlias &GA) { | ||||
| 802 | Assert(GlobalAlias::isValidLinkage(GA.getLinkage()),do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false) | ||||
| 803 | "Alias should have private, internal, linkonce, weak, linkonce_odr, "do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false) | ||||
| 804 | "weak_odr, or external linkage!",do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false) | ||||
| 805 | &GA)do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GA); return; } } while (false); | ||||
| 806 | const Constant *Aliasee = GA.getAliasee(); | ||||
| 807 | Assert(Aliasee, "Aliasee cannot be NULL!", &GA)do { if (!(Aliasee)) { CheckFailed("Aliasee cannot be NULL!", &GA); return; } } while (false); | ||||
| 808 | Assert(GA.getType() == Aliasee->getType(),do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false) | ||||
| 809 | "Alias and aliasee types should match!", &GA)do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false); | ||||
| 810 | |||||
| 811 | Assert(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee),do { if (!(isa<GlobalValue>(Aliasee) || isa<ConstantExpr >(Aliasee))) { CheckFailed("Aliasee should be either GlobalValue or ConstantExpr" , &GA); return; } } while (false) | ||||
| 812 | "Aliasee should be either GlobalValue or ConstantExpr", &GA)do { if (!(isa<GlobalValue>(Aliasee) || isa<ConstantExpr >(Aliasee))) { CheckFailed("Aliasee should be either GlobalValue or ConstantExpr" , &GA); return; } } while (false); | ||||
| 813 | |||||
| 814 | visitAliaseeSubExpr(GA, *Aliasee); | ||||
| 815 | |||||
| 816 | visitGlobalValue(GA); | ||||
| 817 | } | ||||
| 818 | |||||
| 819 | void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { | ||||
| 820 | // There used to be various other llvm.dbg.* nodes, but we don't support | ||||
| 821 | // upgrading them and we want to reserve the namespace for future uses. | ||||
| 822 | if (NMD.getName().startswith("llvm.dbg.")) | ||||
| 823 | AssertDI(NMD.getName() == "llvm.dbg.cu",do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false) | ||||
| 824 | "unrecognized named metadata node in the llvm.dbg namespace",do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false) | ||||
| 825 | &NMD)do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false); | ||||
| 826 | for (const MDNode *MD : NMD.operands()) { | ||||
| 827 | if (NMD.getName() == "llvm.dbg.cu") | ||||
| 828 | AssertDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD)do { if (!(MD && isa<DICompileUnit>(MD))) { DebugInfoCheckFailed ("invalid compile unit", &NMD, MD); return; } } while (false ); | ||||
| 829 | |||||
| 830 | if (!MD) | ||||
| 831 | continue; | ||||
| 832 | |||||
| 833 | visitMDNode(*MD, AreDebugLocsAllowed::Yes); | ||||
| 834 | } | ||||
| 835 | } | ||||
| 836 | |||||
| 837 | void Verifier::visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs) { | ||||
| 838 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
| 839 | // avoids infinite recursion here, as well as being an optimization. | ||||
| 840 | if (!MDNodes.insert(&MD).second) | ||||
| 841 | return; | ||||
| 842 | |||||
| 843 | Assert(&MD.getContext() == &Context,do { if (!(&MD.getContext() == &Context)) { CheckFailed ("MDNode context does not match Module context!", &MD); return ; } } while (false) | ||||
| 844 | "MDNode context does not match Module context!", &MD)do { if (!(&MD.getContext() == &Context)) { CheckFailed ("MDNode context does not match Module context!", &MD); return ; } } while (false); | ||||
| 845 | |||||
| 846 | switch (MD.getMetadataID()) { | ||||
| 847 | default: | ||||
| 848 | llvm_unreachable("Invalid MDNode subclass")__builtin_unreachable(); | ||||
| 849 | case Metadata::MDTupleKind: | ||||
| 850 | break; | ||||
| 851 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ | ||||
| 852 | case Metadata::CLASS##Kind: \ | ||||
| 853 | visit##CLASS(cast<CLASS>(MD)); \ | ||||
| 854 | break; | ||||
| 855 | #include "llvm/IR/Metadata.def" | ||||
| 856 | } | ||||
| 857 | |||||
| 858 | for (const Metadata *Op : MD.operands()) { | ||||
| 859 | if (!Op) | ||||
| 860 | continue; | ||||
| 861 | Assert(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!",do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false) | ||||
| 862 | &MD, Op)do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false); | ||||
| 863 | AssertDI(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed::Yes,do { if (!(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed ::Yes)) { DebugInfoCheckFailed("DILocation not allowed within this metadata node" , &MD, Op); return; } } while (false) | ||||
| 864 | "DILocation not allowed within this metadata node", &MD, Op)do { if (!(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed ::Yes)) { DebugInfoCheckFailed("DILocation not allowed within this metadata node" , &MD, Op); return; } } while (false); | ||||
| 865 | if (auto *N = dyn_cast<MDNode>(Op)) { | ||||
| 866 | visitMDNode(*N, AllowLocs); | ||||
| 867 | continue; | ||||
| 868 | } | ||||
| 869 | if (auto *V = dyn_cast<ValueAsMetadata>(Op)) { | ||||
| 870 | visitValueAsMetadata(*V, nullptr); | ||||
| 871 | continue; | ||||
| 872 | } | ||||
| 873 | } | ||||
| 874 | |||||
| 875 | // Check these last, so we diagnose problems in operands first. | ||||
| 876 | Assert(!MD.isTemporary(), "Expected no forward declarations!", &MD)do { if (!(!MD.isTemporary())) { CheckFailed("Expected no forward declarations!" , &MD); return; } } while (false); | ||||
| 877 | Assert(MD.isResolved(), "All nodes should be resolved!", &MD)do { if (!(MD.isResolved())) { CheckFailed("All nodes should be resolved!" , &MD); return; } } while (false); | ||||
| 878 | } | ||||
| 879 | |||||
| 880 | void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) { | ||||
| 881 | Assert(MD.getValue(), "Expected valid value", &MD)do { if (!(MD.getValue())) { CheckFailed("Expected valid value" , &MD); return; } } while (false); | ||||
| 882 | Assert(!MD.getValue()->getType()->isMetadataTy(),do { if (!(!MD.getValue()->getType()->isMetadataTy())) { CheckFailed("Unexpected metadata round-trip through values", &MD, MD.getValue()); return; } } while (false) | ||||
| 883 | "Unexpected metadata round-trip through values", &MD, MD.getValue())do { if (!(!MD.getValue()->getType()->isMetadataTy())) { CheckFailed("Unexpected metadata round-trip through values", &MD, MD.getValue()); return; } } while (false); | ||||
| 884 | |||||
| 885 | auto *L = dyn_cast<LocalAsMetadata>(&MD); | ||||
| 886 | if (!L) | ||||
| 887 | return; | ||||
| 888 | |||||
| 889 | Assert(F, "function-local metadata used outside a function", L)do { if (!(F)) { CheckFailed("function-local metadata used outside a function" , L); return; } } while (false); | ||||
| 890 | |||||
| 891 | // If this was an instruction, bb, or argument, verify that it is in the | ||||
| 892 | // function that we expect. | ||||
| 893 | Function *ActualF = nullptr; | ||||
| 894 | if (Instruction *I = dyn_cast<Instruction>(L->getValue())) { | ||||
| 895 | Assert(I->getParent(), "function-local metadata not in basic block", L, I)do { if (!(I->getParent())) { CheckFailed("function-local metadata not in basic block" , L, I); return; } } while (false); | ||||
| 896 | ActualF = I->getParent()->getParent(); | ||||
| 897 | } else if (BasicBlock *BB = dyn_cast<BasicBlock>(L->getValue())) | ||||
| 898 | ActualF = BB->getParent(); | ||||
| 899 | else if (Argument *A = dyn_cast<Argument>(L->getValue())) | ||||
| 900 | ActualF = A->getParent(); | ||||
| 901 | assert(ActualF && "Unimplemented function local metadata case!")((void)0); | ||||
| 902 | |||||
| 903 | Assert(ActualF == F, "function-local metadata used in wrong function", L)do { if (!(ActualF == F)) { CheckFailed("function-local metadata used in wrong function" , L); return; } } while (false); | ||||
| 904 | } | ||||
| 905 | |||||
| 906 | void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { | ||||
| 907 | Metadata *MD = MDV.getMetadata(); | ||||
| 908 | if (auto *N = dyn_cast<MDNode>(MD)) { | ||||
| 909 | visitMDNode(*N, AreDebugLocsAllowed::No); | ||||
| 910 | return; | ||||
| 911 | } | ||||
| 912 | |||||
| 913 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
| 914 | // avoids infinite recursion here, as well as being an optimization. | ||||
| 915 | if (!MDNodes.insert(MD).second) | ||||
| 916 | return; | ||||
| 917 | |||||
| 918 | if (auto *V = dyn_cast<ValueAsMetadata>(MD)) | ||||
| 919 | visitValueAsMetadata(*V, F); | ||||
| 920 | } | ||||
| 921 | |||||
| 922 | static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); } | ||||
| 923 | static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); } | ||||
| 924 | static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); } | ||||
| 925 | |||||
| 926 | void Verifier::visitDILocation(const DILocation &N) { | ||||
| 927 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("location requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 928 | "location requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("location requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 929 | if (auto *IA = N.getRawInlinedAt()) | ||||
| 930 | AssertDI(isa<DILocation>(IA), "inlined-at should be a location", &N, IA)do { if (!(isa<DILocation>(IA))) { DebugInfoCheckFailed ("inlined-at should be a location", &N, IA); return; } } while (false); | ||||
| 931 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
| 932 | AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
| 933 | } | ||||
| 934 | |||||
| 935 | void Verifier::visitGenericDINode(const GenericDINode &N) { | ||||
| 936 | AssertDI(N.getTag(), "invalid tag", &N)do { if (!(N.getTag())) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
| 937 | } | ||||
| 938 | |||||
| 939 | void Verifier::visitDIScope(const DIScope &N) { | ||||
| 940 | if (auto *F = N.getRawFile()) | ||||
| 941 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 942 | } | ||||
| 943 | |||||
| 944 | void Verifier::visitDISubrange(const DISubrange &N) { | ||||
| 945 | AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 946 | bool HasAssumedSizedArraySupport = dwarf::isFortran(CurrentSourceLang); | ||||
| 947 | AssertDI(HasAssumedSizedArraySupport || N.getRawCountNode() ||do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
| 948 | N.getRawUpperBound(),do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
| 949 | "Subrange must contain count or upperBound", &N)do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false); | ||||
| 950 | AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("Subrange can have any one of count or upperBound", &N); return; } } while (false) | ||||
| 951 | "Subrange can have any one of count or upperBound", &N)do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("Subrange can have any one of count or upperBound", &N); return; } } while (false); | ||||
| 952 | auto *CBound = N.getRawCountNode(); | ||||
| 953 | AssertDI(!CBound || isa<ConstantAsMetadata>(CBound) ||do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 954 | isa<DIVariable>(CBound) || isa<DIExpression>(CBound),do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 955 | "Count must be signed constant or DIVariable or DIExpression", &N)do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 956 | auto Count = N.getCount(); | ||||
| 957 | AssertDI(!Count || !Count.is<ConstantInt *>() ||do { if (!(!Count || !Count.is<ConstantInt *>() || Count .get<ConstantInt *>()->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
| 958 | Count.get<ConstantInt *>()->getSExtValue() >= -1,do { if (!(!Count || !Count.is<ConstantInt *>() || Count .get<ConstantInt *>()->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
| 959 | "invalid subrange count", &N)do { if (!(!Count || !Count.is<ConstantInt *>() || Count .get<ConstantInt *>()->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false); | ||||
| 960 | auto *LBound = N.getRawLowerBound(); | ||||
| 961 | AssertDI(!LBound || isa<ConstantAsMetadata>(LBound) ||do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 962 | isa<DIVariable>(LBound) || isa<DIExpression>(LBound),do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 963 | "LowerBound must be signed constant or DIVariable or DIExpression",do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 964 | &N)do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 965 | auto *UBound = N.getRawUpperBound(); | ||||
| 966 | AssertDI(!UBound || isa<ConstantAsMetadata>(UBound) ||do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 967 | isa<DIVariable>(UBound) || isa<DIExpression>(UBound),do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 968 | "UpperBound must be signed constant or DIVariable or DIExpression",do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 969 | &N)do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 970 | auto *Stride = N.getRawStride(); | ||||
| 971 | AssertDI(!Stride || isa<ConstantAsMetadata>(Stride) ||do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 972 | isa<DIVariable>(Stride) || isa<DIExpression>(Stride),do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 973 | "Stride must be signed constant or DIVariable or DIExpression", &N)do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 974 | } | ||||
| 975 | |||||
| 976 | void Verifier::visitDIGenericSubrange(const DIGenericSubrange &N) { | ||||
| 977 | AssertDI(N.getTag() == dwarf::DW_TAG_generic_subrange, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_generic_subrange)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 978 | AssertDI(N.getRawCountNode() || N.getRawUpperBound(),do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false) | ||||
| 979 | "GenericSubrange must contain count or upperBound", &N)do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false); | ||||
| 980 | AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange can have any one of count or upperBound", & N); return; } } while (false) | ||||
| 981 | "GenericSubrange can have any one of count or upperBound", &N)do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange can have any one of count or upperBound", & N); return; } } while (false); | ||||
| 982 | auto *CBound = N.getRawCountNode(); | ||||
| 983 | AssertDI(!CBound || isa<DIVariable>(CBound) || isa<DIExpression>(CBound),do { if (!(!CBound || isa<DIVariable>(CBound) || isa< DIExpression>(CBound))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 984 | "Count must be signed constant or DIVariable or DIExpression", &N)do { if (!(!CBound || isa<DIVariable>(CBound) || isa< DIExpression>(CBound))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 985 | auto *LBound = N.getRawLowerBound(); | ||||
| 986 | AssertDI(LBound, "GenericSubrange must contain lowerBound", &N)do { if (!(LBound)) { DebugInfoCheckFailed("GenericSubrange must contain lowerBound" , &N); return; } } while (false); | ||||
| 987 | AssertDI(isa<DIVariable>(LBound) || isa<DIExpression>(LBound),do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 988 | "LowerBound must be signed constant or DIVariable or DIExpression",do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 989 | &N)do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 990 | auto *UBound = N.getRawUpperBound(); | ||||
| 991 | AssertDI(!UBound || isa<DIVariable>(UBound) || isa<DIExpression>(UBound),do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 992 | "UpperBound must be signed constant or DIVariable or DIExpression",do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 993 | &N)do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 994 | auto *Stride = N.getRawStride(); | ||||
| 995 | AssertDI(Stride, "GenericSubrange must contain stride", &N)do { if (!(Stride)) { DebugInfoCheckFailed("GenericSubrange must contain stride" , &N); return; } } while (false); | ||||
| 996 | AssertDI(isa<DIVariable>(Stride) || isa<DIExpression>(Stride),do { if (!(isa<DIVariable>(Stride) || isa<DIExpression >(Stride))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 997 | "Stride must be signed constant or DIVariable or DIExpression", &N)do { if (!(isa<DIVariable>(Stride) || isa<DIExpression >(Stride))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 998 | } | ||||
| 999 | |||||
| 1000 | void Verifier::visitDIEnumerator(const DIEnumerator &N) { | ||||
| 1001 | AssertDI(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_enumerator)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1002 | } | ||||
| 1003 | |||||
| 1004 | void Verifier::visitDIBasicType(const DIBasicType &N) { | ||||
| 1005 | AssertDI(N.getTag() == dwarf::DW_TAG_base_type ||do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1006 | N.getTag() == dwarf::DW_TAG_unspecified_type ||do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1007 | N.getTag() == dwarf::DW_TAG_string_type,do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1008 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
| 1009 | } | ||||
| 1010 | |||||
| 1011 | void Verifier::visitDIStringType(const DIStringType &N) { | ||||
| 1012 | AssertDI(N.getTag() == dwarf::DW_TAG_string_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_string_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1013 | AssertDI(!(N.isBigEndian() && N.isLittleEndian()) ,do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false) | ||||
| 1014 | "has conflicting flags", &N)do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false); | ||||
| 1015 | } | ||||
| 1016 | |||||
| 1017 | void Verifier::visitDIDerivedType(const DIDerivedType &N) { | ||||
| 1018 | // Common scope checks. | ||||
| 1019 | visitDIScope(N); | ||||
| 1020 | |||||
| 1021 | AssertDI(N.getTag() == dwarf::DW_TAG_typedef ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1022 | N.getTag() == dwarf::DW_TAG_pointer_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1023 | N.getTag() == dwarf::DW_TAG_ptr_to_member_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1024 | N.getTag() == dwarf::DW_TAG_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1025 | N.getTag() == dwarf::DW_TAG_rvalue_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1026 | N.getTag() == dwarf::DW_TAG_const_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1027 | N.getTag() == dwarf::DW_TAG_volatile_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1028 | N.getTag() == dwarf::DW_TAG_restrict_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1029 | N.getTag() == dwarf::DW_TAG_atomic_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1030 | N.getTag() == dwarf::DW_TAG_member ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1031 | N.getTag() == dwarf::DW_TAG_inheritance ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1032 | N.getTag() == dwarf::DW_TAG_friend ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1033 | N.getTag() == dwarf::DW_TAG_set_type,do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1034 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf ::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1035 | if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) { | ||||
| 1036 | AssertDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,do { if (!(isType(N.getRawExtraData()))) { DebugInfoCheckFailed ("invalid pointer to member type", &N, N.getRawExtraData( )); return; } } while (false) | ||||
| 1037 | N.getRawExtraData())do { if (!(isType(N.getRawExtraData()))) { DebugInfoCheckFailed ("invalid pointer to member type", &N, N.getRawExtraData( )); return; } } while (false); | ||||
| 1038 | } | ||||
| 1039 | |||||
| 1040 | if (N.getTag() == dwarf::DW_TAG_set_type) { | ||||
| 1041 | if (auto *T = N.getRawBaseType()) { | ||||
| 1042 | auto *Enum = dyn_cast_or_null<DICompositeType>(T); | ||||
| 1043 | auto *Basic = dyn_cast_or_null<DIBasicType>(T); | ||||
| 1044 | AssertDI(do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1045 | (Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type) ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1046 | (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1047 | Basic->getEncoding() == dwarf::DW_ATE_signed ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1048 | Basic->getEncoding() == dwarf::DW_ATE_unsigned_char ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1049 | Basic->getEncoding() == dwarf::DW_ATE_signed_char ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1050 | Basic->getEncoding() == dwarf::DW_ATE_boolean)),do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1051 | "invalid set base type", &N, T)do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false); | ||||
| 1052 | } | ||||
| 1053 | } | ||||
| 1054 | |||||
| 1055 | AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
| 1056 | AssertDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
| 1057 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
| 1058 | |||||
| 1059 | if (N.getDWARFAddressSpace()) { | ||||
| 1060 | AssertDI(N.getTag() == dwarf::DW_TAG_pointer_type ||do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1061 | N.getTag() == dwarf::DW_TAG_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1062 | N.getTag() == dwarf::DW_TAG_rvalue_reference_type,do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1063 | "DWARF address space only applies to pointer or reference types",do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1064 | &N)do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false); | ||||
| 1065 | } | ||||
| 1066 | } | ||||
| 1067 | |||||
| 1068 | /// Detect mutually exclusive flags. | ||||
| 1069 | static bool hasConflictingReferenceFlags(unsigned Flags) { | ||||
| 1070 | return ((Flags & DINode::FlagLValueReference) && | ||||
| 1071 | (Flags & DINode::FlagRValueReference)) || | ||||
| 1072 | ((Flags & DINode::FlagTypePassByValue) && | ||||
| 1073 | (Flags & DINode::FlagTypePassByReference)); | ||||
| 1074 | } | ||||
| 1075 | |||||
| 1076 | void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) { | ||||
| 1077 | auto *Params = dyn_cast<MDTuple>(&RawParams); | ||||
| 1078 | AssertDI(Params, "invalid template params", &N, &RawParams)do { if (!(Params)) { DebugInfoCheckFailed("invalid template params" , &N, &RawParams); return; } } while (false); | ||||
| 1079 | for (Metadata *Op : Params->operands()) { | ||||
| 1080 | AssertDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false) | ||||
| 1081 | &N, Params, Op)do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false); | ||||
| 1082 | } | ||||
| 1083 | } | ||||
| 1084 | |||||
| 1085 | void Verifier::visitDICompositeType(const DICompositeType &N) { | ||||
| 1086 | // Common scope checks. | ||||
| 1087 | visitDIScope(N); | ||||
| 1088 | |||||
| 1089 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1090 | N.getTag() == dwarf::DW_TAG_structure_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1091 | N.getTag() == dwarf::DW_TAG_union_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1092 | N.getTag() == dwarf::DW_TAG_enumeration_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1093 | N.getTag() == dwarf::DW_TAG_class_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1094 | N.getTag() == dwarf::DW_TAG_variant_part,do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1095 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
| 1096 | |||||
| 1097 | AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
| 1098 | AssertDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
| 1099 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
| 1100 | |||||
| 1101 | AssertDI(!N.getRawElements() || isa<MDTuple>(N.getRawElements()),do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false) | ||||
| 1102 | "invalid composite elements", &N, N.getRawElements())do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false); | ||||
| 1103 | AssertDI(isType(N.getRawVTableHolder()), "invalid vtable holder", &N,do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false) | ||||
| 1104 | N.getRawVTableHolder())do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false); | ||||
| 1105 | AssertDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
| 1106 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
| 1107 | unsigned DIBlockByRefStruct = 1 << 4; | ||||
| 1108 | AssertDI((N.getFlags() & DIBlockByRefStruct) == 0,do { if (!((N.getFlags() & DIBlockByRefStruct) == 0)) { DebugInfoCheckFailed ("DIBlockByRefStruct on DICompositeType is no longer supported" , &N); return; } } while (false) | ||||
| 1109 | "DIBlockByRefStruct on DICompositeType is no longer supported", &N)do { if (!((N.getFlags() & DIBlockByRefStruct) == 0)) { DebugInfoCheckFailed ("DIBlockByRefStruct on DICompositeType is no longer supported" , &N); return; } } while (false); | ||||
| 1110 | |||||
| 1111 | if (N.isVector()) { | ||||
| 1112 | const DINodeArray Elements = N.getElements(); | ||||
| 1113 | AssertDI(Elements.size() == 1 &&do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false) | ||||
| 1114 | Elements[0]->getTag() == dwarf::DW_TAG_subrange_type,do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false) | ||||
| 1115 | "invalid vector, expected one element of type subrange", &N)do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false); | ||||
| 1116 | } | ||||
| 1117 | |||||
| 1118 | if (auto *Params = N.getRawTemplateParams()) | ||||
| 1119 | visitTemplateParams(N, *Params); | ||||
| 1120 | |||||
| 1121 | if (auto *D = N.getRawDiscriminator()) { | ||||
| 1122 | AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,do { if (!(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part)) { DebugInfoCheckFailed("discriminator can only appear on variant part" ); return; } } while (false) | ||||
| 1123 | "discriminator can only appear on variant part")do { if (!(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part)) { DebugInfoCheckFailed("discriminator can only appear on variant part" ); return; } } while (false); | ||||
| 1124 | } | ||||
| 1125 | |||||
| 1126 | if (N.getRawDataLocation()) { | ||||
| 1127 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("dataLocation can only appear in array type"); return; } } while (false) | ||||
| 1128 | "dataLocation can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("dataLocation can only appear in array type"); return; } } while (false); | ||||
| 1129 | } | ||||
| 1130 | |||||
| 1131 | if (N.getRawAssociated()) { | ||||
| 1132 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("associated can only appear in array type"); return; } } while (false) | ||||
| 1133 | "associated can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("associated can only appear in array type"); return; } } while (false); | ||||
| 1134 | } | ||||
| 1135 | |||||
| 1136 | if (N.getRawAllocated()) { | ||||
| 1137 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("allocated can only appear in array type"); return; } } while (false) | ||||
| 1138 | "allocated can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("allocated can only appear in array type"); return; } } while (false); | ||||
| 1139 | } | ||||
| 1140 | |||||
| 1141 | if (N.getRawRank()) { | ||||
| 1142 | AssertDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("rank can only appear in array type"); return; } } while (false ) | ||||
| 1143 | "rank can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("rank can only appear in array type"); return; } } while (false ); | ||||
| 1144 | } | ||||
| 1145 | } | ||||
| 1146 | |||||
| 1147 | void Verifier::visitDISubroutineType(const DISubroutineType &N) { | ||||
| 1148 | AssertDI(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subroutine_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1149 | if (auto *Types = N.getRawTypeArray()) { | ||||
| 1150 | AssertDI(isa<MDTuple>(Types), "invalid composite elements", &N, Types)do { if (!(isa<MDTuple>(Types))) { DebugInfoCheckFailed ("invalid composite elements", &N, Types); return; } } while (false); | ||||
| 1151 | for (Metadata *Ty : N.getTypeArray()->operands()) { | ||||
| 1152 | AssertDI(isType(Ty), "invalid subroutine type ref", &N, Types, Ty)do { if (!(isType(Ty))) { DebugInfoCheckFailed("invalid subroutine type ref" , &N, Types, Ty); return; } } while (false); | ||||
| 1153 | } | ||||
| 1154 | } | ||||
| 1155 | AssertDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
| 1156 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
| 1157 | } | ||||
| 1158 | |||||
| 1159 | void Verifier::visitDIFile(const DIFile &N) { | ||||
| 1160 | AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_file_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1161 | Optional<DIFile::ChecksumInfo<StringRef>> Checksum = N.getChecksum(); | ||||
| 1162 | if (Checksum) { | ||||
| 1163 | AssertDI(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last,do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false) | ||||
| 1164 | "invalid checksum kind", &N)do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false); | ||||
| 1165 | size_t Size; | ||||
| 1166 | switch (Checksum->Kind) { | ||||
| 1167 | case DIFile::CSK_MD5: | ||||
| 1168 | Size = 32; | ||||
| 1169 | break; | ||||
| 1170 | case DIFile::CSK_SHA1: | ||||
| 1171 | Size = 40; | ||||
| 1172 | break; | ||||
| 1173 | case DIFile::CSK_SHA256: | ||||
| 1174 | Size = 64; | ||||
| 1175 | break; | ||||
| 1176 | } | ||||
| 1177 | AssertDI(Checksum->Value.size() == Size, "invalid checksum length", &N)do { if (!(Checksum->Value.size() == Size)) { DebugInfoCheckFailed ("invalid checksum length", &N); return; } } while (false ); | ||||
| 1178 | AssertDI(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos,do { if (!(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos)) { DebugInfoCheckFailed("invalid checksum", &N); return; } } while (false) | ||||
| 1179 | "invalid checksum", &N)do { if (!(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos)) { DebugInfoCheckFailed("invalid checksum", &N); return; } } while (false); | ||||
| 1180 | } | ||||
| 1181 | } | ||||
| 1182 | |||||
| 1183 | void Verifier::visitDICompileUnit(const DICompileUnit &N) { | ||||
| 1184 | AssertDI(N.isDistinct(), "compile units must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("compile units must be distinct" , &N); return; } } while (false); | ||||
| 1185 | AssertDI(N.getTag() == dwarf::DW_TAG_compile_unit, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_compile_unit)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1186 | |||||
| 1187 | // Don't bother verifying the compilation directory or producer string | ||||
| 1188 | // as those could be empty. | ||||
| 1189 | AssertDI(N.getRawFile() && isa<DIFile>(N.getRawFile()), "invalid file", &N,do { if (!(N.getRawFile() && isa<DIFile>(N.getRawFile ()))) { DebugInfoCheckFailed("invalid file", &N, N.getRawFile ()); return; } } while (false) | ||||
| 1190 | N.getRawFile())do { if (!(N.getRawFile() && isa<DIFile>(N.getRawFile ()))) { DebugInfoCheckFailed("invalid file", &N, N.getRawFile ()); return; } } while (false); | ||||
| 1191 | AssertDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false) | ||||
| 1192 | N.getFile())do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false); | ||||
| 1193 | |||||
| 1194 | CurrentSourceLang = (dwarf::SourceLanguage)N.getSourceLanguage(); | ||||
| 1195 | |||||
| 1196 | verifySourceDebugInfo(N, *N.getFile()); | ||||
| 1197 | |||||
| 1198 | AssertDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false) | ||||
| 1199 | "invalid emission kind", &N)do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false); | ||||
| 1200 | |||||
| 1201 | if (auto *Array = N.getRawEnumTypes()) { | ||||
| 1202 | AssertDI(isa<MDTuple>(Array), "invalid enum list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid enum list", &N, Array); return; } } while (false ); | ||||
| 1203 | for (Metadata *Op : N.getEnumTypes()->operands()) { | ||||
| 1204 | auto *Enum = dyn_cast_or_null<DICompositeType>(Op); | ||||
| 1205 | AssertDI(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type,do { if (!(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type )) { DebugInfoCheckFailed("invalid enum type", &N, N.getEnumTypes (), Op); return; } } while (false) | ||||
| 1206 | "invalid enum type", &N, N.getEnumTypes(), Op)do { if (!(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type )) { DebugInfoCheckFailed("invalid enum type", &N, N.getEnumTypes (), Op); return; } } while (false); | ||||
| 1207 | } | ||||
| 1208 | } | ||||
| 1209 | if (auto *Array = N.getRawRetainedTypes()) { | ||||
| 1210 | AssertDI(isa<MDTuple>(Array), "invalid retained type list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid retained type list", &N, Array); return; } } while (false); | ||||
| 1211 | for (Metadata *Op : N.getRetainedTypes()->operands()) { | ||||
| 1212 | AssertDI(Op && (isa<DIType>(Op) ||do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
| 1213 | (isa<DISubprogram>(Op) &&do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
| 1214 | !cast<DISubprogram>(Op)->isDefinition())),do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
| 1215 | "invalid retained type", &N, Op)do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false); | ||||
| 1216 | } | ||||
| 1217 | } | ||||
| 1218 | if (auto *Array = N.getRawGlobalVariables()) { | ||||
| 1219 | AssertDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid global variable list", &N, Array); return; } } while (false); | ||||
| 1220 | for (Metadata *Op : N.getGlobalVariables()->operands()) { | ||||
| 1221 | AssertDI(Op && (isa<DIGlobalVariableExpression>(Op)),do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false) | ||||
| 1222 | "invalid global variable ref", &N, Op)do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false); | ||||
| 1223 | } | ||||
| 1224 | } | ||||
| 1225 | if (auto *Array = N.getRawImportedEntities()) { | ||||
| 1226 | AssertDI(isa<MDTuple>(Array), "invalid imported entity list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid imported entity list", &N, Array); return; } } while (false); | ||||
| 1227 | for (Metadata *Op : N.getImportedEntities()->operands()) { | ||||
| 1228 | AssertDI(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref",do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false) | ||||
| 1229 | &N, Op)do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false); | ||||
| 1230 | } | ||||
| 1231 | } | ||||
| 1232 | if (auto *Array = N.getRawMacros()) { | ||||
| 1233 | AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
| 1234 | for (Metadata *Op : N.getMacros()->operands()) { | ||||
| 1235 | AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
| 1236 | } | ||||
| 1237 | } | ||||
| 1238 | CUVisited.insert(&N); | ||||
| 1239 | } | ||||
| 1240 | |||||
| 1241 | void Verifier::visitDISubprogram(const DISubprogram &N) { | ||||
| 1242 | AssertDI(N.getTag() == dwarf::DW_TAG_subprogram, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subprogram)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1243 | AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
| 1244 | if (auto *F = N.getRawFile()) | ||||
| 1245 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1246 | else | ||||
| 1247 | AssertDI(N.getLine() == 0, "line specified with no file", &N, N.getLine())do { if (!(N.getLine() == 0)) { DebugInfoCheckFailed("line specified with no file" , &N, N.getLine()); return; } } while (false); | ||||
| 1248 | if (auto *T = N.getRawType()) | ||||
| 1249 | AssertDI(isa<DISubroutineType>(T), "invalid subroutine type", &N, T)do { if (!(isa<DISubroutineType>(T))) { DebugInfoCheckFailed ("invalid subroutine type", &N, T); return; } } while (false ); | ||||
| 1250 | AssertDI(isType(N.getRawContainingType()), "invalid containing type", &N,do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false) | ||||
| 1251 | N.getRawContainingType())do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false); | ||||
| 1252 | if (auto *Params = N.getRawTemplateParams()) | ||||
| 1253 | visitTemplateParams(N, *Params); | ||||
| 1254 | if (auto *S = N.getRawDeclaration()) | ||||
| 1255 | AssertDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(),do { if (!(isa<DISubprogram>(S) && !cast<DISubprogram >(S)->isDefinition())) { DebugInfoCheckFailed("invalid subprogram declaration" , &N, S); return; } } while (false) | ||||
| 1256 | "invalid subprogram declaration", &N, S)do { if (!(isa<DISubprogram>(S) && !cast<DISubprogram >(S)->isDefinition())) { DebugInfoCheckFailed("invalid subprogram declaration" , &N, S); return; } } while (false); | ||||
| 1257 | if (auto *RawNode = N.getRawRetainedNodes()) { | ||||
| 1258 | auto *Node = dyn_cast<MDTuple>(RawNode); | ||||
| 1259 | AssertDI(Node, "invalid retained nodes list", &N, RawNode)do { if (!(Node)) { DebugInfoCheckFailed("invalid retained nodes list" , &N, RawNode); return; } } while (false); | ||||
| 1260 | for (Metadata *Op : Node->operands()) { | ||||
| 1261 | AssertDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)),do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false) | ||||
| 1262 | "invalid retained nodes, expected DILocalVariable or DILabel",do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false) | ||||
| 1263 | &N, Node, Op)do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false); | ||||
| 1264 | } | ||||
| 1265 | } | ||||
| 1266 | AssertDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
| 1267 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
| 1268 | |||||
| 1269 | auto *Unit = N.getRawUnit(); | ||||
| 1270 | if (N.isDefinition()) { | ||||
| 1271 | // Subprogram definitions (not part of the type hierarchy). | ||||
| 1272 | AssertDI(N.isDistinct(), "subprogram definitions must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("subprogram definitions must be distinct" , &N); return; } } while (false); | ||||
| 1273 | AssertDI(Unit, "subprogram definitions must have a compile unit", &N)do { if (!(Unit)) { DebugInfoCheckFailed("subprogram definitions must have a compile unit" , &N); return; } } while (false); | ||||
| 1274 | AssertDI(isa<DICompileUnit>(Unit), "invalid unit type", &N, Unit)do { if (!(isa<DICompileUnit>(Unit))) { DebugInfoCheckFailed ("invalid unit type", &N, Unit); return; } } while (false ); | ||||
| 1275 | if (N.getFile()) | ||||
| 1276 | verifySourceDebugInfo(*N.getUnit(), *N.getFile()); | ||||
| 1277 | } else { | ||||
| 1278 | // Subprogram declarations (part of the type hierarchy). | ||||
| 1279 | AssertDI(!Unit, "subprogram declarations must not have a compile unit", &N)do { if (!(!Unit)) { DebugInfoCheckFailed("subprogram declarations must not have a compile unit" , &N); return; } } while (false); | ||||
| 1280 | } | ||||
| 1281 | |||||
| 1282 | if (auto *RawThrownTypes = N.getRawThrownTypes()) { | ||||
| 1283 | auto *ThrownTypes = dyn_cast<MDTuple>(RawThrownTypes); | ||||
| 1284 | AssertDI(ThrownTypes, "invalid thrown types list", &N, RawThrownTypes)do { if (!(ThrownTypes)) { DebugInfoCheckFailed("invalid thrown types list" , &N, RawThrownTypes); return; } } while (false); | ||||
| 1285 | for (Metadata *Op : ThrownTypes->operands()) | ||||
| 1286 | AssertDI(Op && isa<DIType>(Op), "invalid thrown type", &N, ThrownTypes,do { if (!(Op && isa<DIType>(Op))) { DebugInfoCheckFailed ("invalid thrown type", &N, ThrownTypes, Op); return; } } while (false) | ||||
| 1287 | Op)do { if (!(Op && isa<DIType>(Op))) { DebugInfoCheckFailed ("invalid thrown type", &N, ThrownTypes, Op); return; } } while (false); | ||||
| 1288 | } | ||||
| 1289 | |||||
| 1290 | if (N.areAllCallsDescribed()) | ||||
| 1291 | AssertDI(N.isDefinition(),do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false) | ||||
| 1292 | "DIFlagAllCallsDescribed must be attached to a definition")do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false); | ||||
| 1293 | } | ||||
| 1294 | |||||
| 1295 | void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { | ||||
| 1296 | AssertDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_lexical_block)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1297 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 1298 | "invalid local scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 1299 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
| 1300 | AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
| 1301 | } | ||||
| 1302 | |||||
| 1303 | void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { | ||||
| 1304 | visitDILexicalBlockBase(N); | ||||
| 1305 | |||||
| 1306 | AssertDI(N.getLine() || !N.getColumn(),do { if (!(N.getLine() || !N.getColumn())) { DebugInfoCheckFailed ("cannot have column info without line info", &N); return ; } } while (false) | ||||
| 1307 | "cannot have column info without line info", &N)do { if (!(N.getLine() || !N.getColumn())) { DebugInfoCheckFailed ("cannot have column info without line info", &N); return ; } } while (false); | ||||
| 1308 | } | ||||
| 1309 | |||||
| 1310 | void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { | ||||
| 1311 | visitDILexicalBlockBase(N); | ||||
| 1312 | } | ||||
| 1313 | |||||
| 1314 | void Verifier::visitDICommonBlock(const DICommonBlock &N) { | ||||
| 1315 | AssertDI(N.getTag() == dwarf::DW_TAG_common_block, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_common_block)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1316 | if (auto *S = N.getRawScope()) | ||||
| 1317 | AssertDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
| 1318 | if (auto *S = N.getRawDecl()) | ||||
| 1319 | AssertDI(isa<DIGlobalVariable>(S), "invalid declaration", &N, S)do { if (!(isa<DIGlobalVariable>(S))) { DebugInfoCheckFailed ("invalid declaration", &N, S); return; } } while (false); | ||||
| 1320 | } | ||||
| 1321 | |||||
| 1322 | void Verifier::visitDINamespace(const DINamespace &N) { | ||||
| 1323 | AssertDI(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_namespace)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1324 | if (auto *S = N.getRawScope()) | ||||
| 1325 | AssertDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
| 1326 | } | ||||
| 1327 | |||||
| 1328 | void Verifier::visitDIMacro(const DIMacro &N) { | ||||
| 1329 | AssertDI(N.getMacinfoType() == dwarf::DW_MACINFO_define ||do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false) | ||||
| 1330 | N.getMacinfoType() == dwarf::DW_MACINFO_undef,do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false) | ||||
| 1331 | "invalid macinfo type", &N)do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false); | ||||
| 1332 | AssertDI(!N.getName().empty(), "anonymous macro", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous macro" , &N); return; } } while (false); | ||||
| 1333 | if (!N.getValue().empty()) { | ||||
| 1334 | assert(N.getValue().data()[0] != ' ' && "Macro value has a space prefix")((void)0); | ||||
| 1335 | } | ||||
| 1336 | } | ||||
| 1337 | |||||
| 1338 | void Verifier::visitDIMacroFile(const DIMacroFile &N) { | ||||
| 1339 | AssertDI(N.getMacinfoType() == dwarf::DW_MACINFO_start_file,do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false) | ||||
| 1340 | "invalid macinfo type", &N)do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false); | ||||
| 1341 | if (auto *F = N.getRawFile()) | ||||
| 1342 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1343 | |||||
| 1344 | if (auto *Array = N.getRawElements()) { | ||||
| 1345 | AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
| 1346 | for (Metadata *Op : N.getElements()->operands()) { | ||||
| 1347 | AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
| 1348 | } | ||||
| 1349 | } | ||||
| 1350 | } | ||||
| 1351 | |||||
| 1352 | void Verifier::visitDIArgList(const DIArgList &N) { | ||||
| 1353 | AssertDI(!N.getNumOperands(),do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
| 1354 | "DIArgList should have no operands other than a list of "do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
| 1355 | "ValueAsMetadata",do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
| 1356 | &N)do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false); | ||||
| 1357 | } | ||||
| 1358 | |||||
| 1359 | void Verifier::visitDIModule(const DIModule &N) { | ||||
| 1360 | AssertDI(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_module)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1361 | AssertDI(!N.getName().empty(), "anonymous module", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous module" , &N); return; } } while (false); | ||||
| 1362 | } | ||||
| 1363 | |||||
| 1364 | void Verifier::visitDITemplateParameter(const DITemplateParameter &N) { | ||||
| 1365 | AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
| 1366 | } | ||||
| 1367 | |||||
| 1368 | void Verifier::visitDITemplateTypeParameter(const DITemplateTypeParameter &N) { | ||||
| 1369 | visitDITemplateParameter(N); | ||||
| 1370 | |||||
| 1371 | AssertDI(N.getTag() == dwarf::DW_TAG_template_type_parameter, "invalid tag",do { if (!(N.getTag() == dwarf::DW_TAG_template_type_parameter )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1372 | &N)do { if (!(N.getTag() == dwarf::DW_TAG_template_type_parameter )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
| 1373 | } | ||||
| 1374 | |||||
| 1375 | void Verifier::visitDITemplateValueParameter( | ||||
| 1376 | const DITemplateValueParameter &N) { | ||||
| 1377 | visitDITemplateParameter(N); | ||||
| 1378 | |||||
| 1379 | AssertDI(N.getTag() == dwarf::DW_TAG_template_value_parameter ||do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1380 | N.getTag() == dwarf::DW_TAG_GNU_template_template_param ||do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1381 | N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack,do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1382 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1383 | } | ||||
| 1384 | |||||
| 1385 | void Verifier::visitDIVariable(const DIVariable &N) { | ||||
| 1386 | if (auto *S = N.getRawScope()) | ||||
| 1387 | AssertDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
| 1388 | if (auto *F = N.getRawFile()) | ||||
| 1389 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1390 | } | ||||
| 1391 | |||||
| 1392 | void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { | ||||
| 1393 | // Checks common to all variables. | ||||
| 1394 | visitDIVariable(N); | ||||
| 1395 | |||||
| 1396 | AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1397 | AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
| 1398 | // Assert only if the global variable is not an extern | ||||
| 1399 | if (N.isDefinition()) | ||||
| 1400 | AssertDI(N.getType(), "missing global variable type", &N)do { if (!(N.getType())) { DebugInfoCheckFailed("missing global variable type" , &N); return; } } while (false); | ||||
| 1401 | if (auto *Member = N.getRawStaticDataMemberDeclaration()) { | ||||
| 1402 | AssertDI(isa<DIDerivedType>(Member),do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false) | ||||
| 1403 | "invalid static data member declaration", &N, Member)do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false); | ||||
| 1404 | } | ||||
| 1405 | } | ||||
| 1406 | |||||
| 1407 | void Verifier::visitDILocalVariable(const DILocalVariable &N) { | ||||
| 1408 | // Checks common to all variables. | ||||
| 1409 | visitDIVariable(N); | ||||
| 1410 | |||||
| 1411 | AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
| 1412 | AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1413 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("local variable requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 1414 | "local variable requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("local variable requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 1415 | if (auto Ty = N.getType()) | ||||
| 1416 | AssertDI(!isa<DISubroutineType>(Ty), "invalid type", &N, N.getType())do { if (!(!isa<DISubroutineType>(Ty))) { DebugInfoCheckFailed ("invalid type", &N, N.getType()); return; } } while (false ); | ||||
| 1417 | } | ||||
| 1418 | |||||
| 1419 | void Verifier::visitDILabel(const DILabel &N) { | ||||
| 1420 | if (auto *S = N.getRawScope()) | ||||
| 1421 | AssertDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
| 1422 | if (auto *F = N.getRawFile()) | ||||
| 1423 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1424 | |||||
| 1425 | AssertDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_label)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1426 | AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("label requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 1427 | "label requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("label requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 1428 | } | ||||
| 1429 | |||||
| 1430 | void Verifier::visitDIExpression(const DIExpression &N) { | ||||
| 1431 | AssertDI(N.isValid(), "invalid expression", &N)do { if (!(N.isValid())) { DebugInfoCheckFailed("invalid expression" , &N); return; } } while (false); | ||||
| 1432 | } | ||||
| 1433 | |||||
| 1434 | void Verifier::visitDIGlobalVariableExpression( | ||||
| 1435 | const DIGlobalVariableExpression &GVE) { | ||||
| 1436 | AssertDI(GVE.getVariable(), "missing variable")do { if (!(GVE.getVariable())) { DebugInfoCheckFailed("missing variable" ); return; } } while (false); | ||||
| 1437 | if (auto *Var = GVE.getVariable()) | ||||
| 1438 | visitDIGlobalVariable(*Var); | ||||
| 1439 | if (auto *Expr = GVE.getExpression()) { | ||||
| 1440 | visitDIExpression(*Expr); | ||||
| 1441 | if (auto Fragment = Expr->getFragmentInfo()) | ||||
| 1442 | verifyFragmentExpression(*GVE.getVariable(), *Fragment, &GVE); | ||||
| 1443 | } | ||||
| 1444 | } | ||||
| 1445 | |||||
| 1446 | void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { | ||||
| 1447 | AssertDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_APPLE_property)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1448 | if (auto *T = N.getRawType()) | ||||
| 1449 | AssertDI(isType(T), "invalid type ref", &N, T)do { if (!(isType(T))) { DebugInfoCheckFailed("invalid type ref" , &N, T); return; } } while (false); | ||||
| 1450 | if (auto *F = N.getRawFile()) | ||||
| 1451 | AssertDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1452 | } | ||||
| 1453 | |||||
| 1454 | void Verifier::visitDIImportedEntity(const DIImportedEntity &N) { | ||||
| 1455 | AssertDI(N.getTag() == dwarf::DW_TAG_imported_module ||do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1456 | N.getTag() == dwarf::DW_TAG_imported_declaration,do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1457 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1458 | if (auto *S = N.getRawScope()) | ||||
| 1459 | AssertDI(isa<DIScope>(S), "invalid scope for imported entity", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope for imported entity" , &N, S); return; } } while (false); | ||||
| 1460 | AssertDI(isDINode(N.getRawEntity()), "invalid imported entity", &N,do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false) | ||||
| 1461 | N.getRawEntity())do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false); | ||||
| 1462 | } | ||||
| 1463 | |||||
| 1464 | void Verifier::visitComdat(const Comdat &C) { | ||||
| 1465 | // In COFF the Module is invalid if the GlobalValue has private linkage. | ||||
| 1466 | // Entities with private linkage don't have entries in the symbol table. | ||||
| 1467 | if (TT.isOSBinFormatCOFF()) | ||||
| 1468 | if (const GlobalValue *GV = M.getNamedValue(C.getName())) | ||||
| 1469 | Assert(!GV->hasPrivateLinkage(),do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false) | ||||
| 1470 | "comdat global value has private linkage", GV)do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false); | ||||
| 1471 | } | ||||
| 1472 | |||||
| 1473 | void Verifier::visitModuleIdents(const Module &M) { | ||||
| 1474 | const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); | ||||
| 1475 | if (!Idents) | ||||
| 1476 | return; | ||||
| 1477 | |||||
| 1478 | // llvm.ident takes a list of metadata entry. Each entry has only one string. | ||||
| 1479 | // Scan each llvm.ident entry and make sure that this requirement is met. | ||||
| 1480 | for (const MDNode *N : Idents->operands()) { | ||||
| 1481 | Assert(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.ident metadata" , N); return; } } while (false) | ||||
| 1482 | "incorrect number of operands in llvm.ident metadata", N)do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.ident metadata" , N); return; } } while (false); | ||||
| 1483 | Assert(dyn_cast_or_null<MDString>(N->getOperand(0)),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1484 | ("invalid value for llvm.ident metadata entry operand"do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1485 | "(the operand should be a string)"),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1486 | N->getOperand(0))do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false); | ||||
| 1487 | } | ||||
| 1488 | } | ||||
| 1489 | |||||
| 1490 | void Verifier::visitModuleCommandLines(const Module &M) { | ||||
| 1491 | const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline"); | ||||
| 1492 | if (!CommandLines) | ||||
| 1493 | return; | ||||
| 1494 | |||||
| 1495 | // llvm.commandline takes a list of metadata entry. Each entry has only one | ||||
| 1496 | // string. Scan each llvm.commandline entry and make sure that this | ||||
| 1497 | // requirement is met. | ||||
| 1498 | for (const MDNode *N : CommandLines->operands()) { | ||||
| 1499 | Assert(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.commandline metadata" , N); return; } } while (false) | ||||
| 1500 | "incorrect number of operands in llvm.commandline metadata", N)do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.commandline metadata" , N); return; } } while (false); | ||||
| 1501 | Assert(dyn_cast_or_null<MDString>(N->getOperand(0)),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1502 | ("invalid value for llvm.commandline metadata entry operand"do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1503 | "(the operand should be a string)"),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1504 | N->getOperand(0))do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false); | ||||
| 1505 | } | ||||
| 1506 | } | ||||
| 1507 | |||||
| 1508 | void Verifier::visitModuleFlags(const Module &M) { | ||||
| 1509 | const NamedMDNode *Flags = M.getModuleFlagsMetadata(); | ||||
| 1510 | if (!Flags) return; | ||||
| 1511 | |||||
| 1512 | // Scan each flag, and track the flags and requirements. | ||||
| 1513 | DenseMap<const MDString*, const MDNode*> SeenIDs; | ||||
| 1514 | SmallVector<const MDNode*, 16> Requirements; | ||||
| 1515 | for (const MDNode *MDN : Flags->operands()) | ||||
| 1516 | visitModuleFlag(MDN, SeenIDs, Requirements); | ||||
| 1517 | |||||
| 1518 | // Validate that the requirements in the module are valid. | ||||
| 1519 | for (const MDNode *Requirement : Requirements) { | ||||
| 1520 | const MDString *Flag = cast<MDString>(Requirement->getOperand(0)); | ||||
| 1521 | const Metadata *ReqValue = Requirement->getOperand(1); | ||||
| 1522 | |||||
| 1523 | const MDNode *Op = SeenIDs.lookup(Flag); | ||||
| 1524 | if (!Op) { | ||||
| 1525 | CheckFailed("invalid requirement on flag, flag is not present in module", | ||||
| 1526 | Flag); | ||||
| 1527 | continue; | ||||
| 1528 | } | ||||
| 1529 | |||||
| 1530 | if (Op->getOperand(2) != ReqValue) { | ||||
| 1531 | CheckFailed(("invalid requirement on flag, " | ||||
| 1532 | "flag does not have the required value"), | ||||
| 1533 | Flag); | ||||
| 1534 | continue; | ||||
| 1535 | } | ||||
| 1536 | } | ||||
| 1537 | } | ||||
| 1538 | |||||
| 1539 | void | ||||
| 1540 | Verifier::visitModuleFlag(const MDNode *Op, | ||||
| 1541 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
| 1542 | SmallVectorImpl<const MDNode *> &Requirements) { | ||||
| 1543 | // Each module flag should have three arguments, the merge behavior (a | ||||
| 1544 | // constant int), the flag ID (an MDString), and the value. | ||||
| 1545 | Assert(Op->getNumOperands() == 3,do { if (!(Op->getNumOperands() == 3)) { CheckFailed("incorrect number of operands in module flag" , Op); return; } } while (false) | ||||
| 1546 | "incorrect number of operands in module flag", Op)do { if (!(Op->getNumOperands() == 3)) { CheckFailed("incorrect number of operands in module flag" , Op); return; } } while (false); | ||||
| 1547 | Module::ModFlagBehavior MFB; | ||||
| 1548 | if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { | ||||
| 1549 | Assert(do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1550 | mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0)),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1551 | "invalid behavior operand in module flag (expected constant integer)",do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1552 | Op->getOperand(0))do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false); | ||||
| 1553 | Assert(false,do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1554 | "invalid behavior operand in module flag (unexpected constant)",do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1555 | Op->getOperand(0))do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false); | ||||
| 1556 | } | ||||
| 1557 | MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1)); | ||||
| 1558 | Assert(ID, "invalid ID operand in module flag (expected metadata string)",do { if (!(ID)) { CheckFailed("invalid ID operand in module flag (expected metadata string)" , Op->getOperand(1)); return; } } while (false) | ||||
| 1559 | Op->getOperand(1))do { if (!(ID)) { CheckFailed("invalid ID operand in module flag (expected metadata string)" , Op->getOperand(1)); return; } } while (false); | ||||
| 1560 | |||||
| 1561 | // Sanity check the values for behaviors with additional requirements. | ||||
| 1562 | switch (MFB) { | ||||
| 1563 | case Module::Error: | ||||
| 1564 | case Module::Warning: | ||||
| 1565 | case Module::Override: | ||||
| 1566 | // These behavior types accept any value. | ||||
| 1567 | break; | ||||
| 1568 | |||||
| 1569 | case Module::Max: { | ||||
| 1570 | Assert(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1571 | "invalid value for 'max' module flag (expected constant integer)",do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1572 | Op->getOperand(2))do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false); | ||||
| 1573 | break; | ||||
| 1574 | } | ||||
| 1575 | |||||
| 1576 | case Module::Require: { | ||||
| 1577 | // The value should itself be an MDNode with two operands, a flag ID (an | ||||
| 1578 | // MDString), and a value. | ||||
| 1579 | MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2)); | ||||
| 1580 | Assert(Value && Value->getNumOperands() == 2,do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1581 | "invalid value for 'require' module flag (expected metadata pair)",do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1582 | Op->getOperand(2))do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false); | ||||
| 1583 | Assert(isa<MDString>(Value->getOperand(0)),do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
| 1584 | ("invalid value for 'require' module flag "do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
| 1585 | "(first value operand should be a string)"),do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
| 1586 | Value->getOperand(0))do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false); | ||||
| 1587 | |||||
| 1588 | // Append it to the list of requirements, to check once all module flags are | ||||
| 1589 | // scanned. | ||||
| 1590 | Requirements.push_back(Value); | ||||
| 1591 | break; | ||||
| 1592 | } | ||||
| 1593 | |||||
| 1594 | case Module::Append: | ||||
| 1595 | case Module::AppendUnique: { | ||||
| 1596 | // These behavior types require the operand be an MDNode. | ||||
| 1597 | Assert(isa<MDNode>(Op->getOperand(2)),do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1598 | "invalid value for 'append'-type module flag "do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1599 | "(expected a metadata node)",do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1600 | Op->getOperand(2))do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false); | ||||
| 1601 | break; | ||||
| 1602 | } | ||||
| 1603 | } | ||||
| 1604 | |||||
| 1605 | // Unless this is a "requires" flag, check the ID is unique. | ||||
| 1606 | if (MFB != Module::Require) { | ||||
| 1607 | bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; | ||||
| 1608 | Assert(Inserted,do { if (!(Inserted)) { CheckFailed("module flag identifiers must be unique (or of 'require' type)" , ID); return; } } while (false) | ||||
| 1609 | "module flag identifiers must be unique (or of 'require' type)", ID)do { if (!(Inserted)) { CheckFailed("module flag identifiers must be unique (or of 'require' type)" , ID); return; } } while (false); | ||||
| 1610 | } | ||||
| 1611 | |||||
| 1612 | if (ID->getString() == "wchar_size") { | ||||
| 1613 | ConstantInt *Value | ||||
| 1614 | = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
| 1615 | Assert(Value, "wchar_size metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("wchar_size metadata requires constant integer argument" ); return; } } while (false); | ||||
| 1616 | } | ||||
| 1617 | |||||
| 1618 | if (ID->getString() == "Linker Options") { | ||||
| 1619 | // If the llvm.linker.options named metadata exists, we assume that the | ||||
| 1620 | // bitcode reader has upgraded the module flag. Otherwise the flag might | ||||
| 1621 | // have been created by a client directly. | ||||
| 1622 | Assert(M.getNamedMetadata("llvm.linker.options"),do { if (!(M.getNamedMetadata("llvm.linker.options"))) { CheckFailed ("'Linker Options' named metadata no longer supported"); return ; } } while (false) | ||||
| 1623 | "'Linker Options' named metadata no longer supported")do { if (!(M.getNamedMetadata("llvm.linker.options"))) { CheckFailed ("'Linker Options' named metadata no longer supported"); return ; } } while (false); | ||||
| 1624 | } | ||||
| 1625 | |||||
| 1626 | if (ID->getString() == "SemanticInterposition") { | ||||
| 1627 | ConstantInt *Value = | ||||
| 1628 | mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
| 1629 | Assert(Value,do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false) | ||||
| 1630 | "SemanticInterposition metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false); | ||||
| 1631 | } | ||||
| 1632 | |||||
| 1633 | if (ID->getString() == "CG Profile") { | ||||
| 1634 | for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands()) | ||||
| 1635 | visitModuleFlagCGProfileEntry(MDO); | ||||
| 1636 | } | ||||
| 1637 | } | ||||
| 1638 | |||||
| 1639 | void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) { | ||||
| 1640 | auto CheckFunction = [&](const MDOperand &FuncMDO) { | ||||
| 1641 | if (!FuncMDO) | ||||
| 1642 | return; | ||||
| 1643 | auto F = dyn_cast<ValueAsMetadata>(FuncMDO); | ||||
| 1644 | Assert(F && isa<Function>(F->getValue()->stripPointerCasts()),do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false) | ||||
| 1645 | "expected a Function or null", FuncMDO)do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false); | ||||
| 1646 | }; | ||||
| 1647 | auto Node = dyn_cast_or_null<MDNode>(MDO); | ||||
| 1648 | Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO)do { if (!(Node && Node->getNumOperands() == 3)) { CheckFailed("expected a MDNode triple", MDO); return; } } while (false); | ||||
| 1649 | CheckFunction(Node->getOperand(0)); | ||||
| 1650 | CheckFunction(Node->getOperand(1)); | ||||
| 1651 | auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2)); | ||||
| 1652 | Assert(Count && Count->getType()->isIntegerTy(),do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false) | ||||
| 1653 | "expected an integer constant", Node->getOperand(2))do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false); | ||||
| 1654 | } | ||||
| 1655 | |||||
| 1656 | void Verifier::verifyAttributeTypes(AttributeSet Attrs, const Value *V) { | ||||
| 1657 | for (Attribute A : Attrs) { | ||||
| 1658 | |||||
| 1659 | if (A.isStringAttribute()) { | ||||
| 1660 | #define GET_ATTR_NAMES | ||||
| 1661 | #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) | ||||
| 1662 | #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \ | ||||
| 1663 | if (A.getKindAsString() == #DISPLAY_NAME) { \ | ||||
| 1664 | auto V = A.getValueAsString(); \ | ||||
| 1665 | if (!(V.empty() || V == "true" || V == "false")) \ | ||||
| 1666 | CheckFailed("invalid value for '" #DISPLAY_NAME "' attribute: " + V + \ | ||||
| 1667 | ""); \ | ||||
| 1668 | } | ||||
| 1669 | |||||
| 1670 | #include "llvm/IR/Attributes.inc" | ||||
| 1671 | continue; | ||||
| 1672 | } | ||||
| 1673 | |||||
| 1674 | if (A.isIntAttribute() != Attribute::isIntAttrKind(A.getKindAsEnum())) { | ||||
| 1675 | CheckFailed("Attribute '" + A.getAsString() + "' should have an Argument", | ||||
| 1676 | V); | ||||
| 1677 | return; | ||||
| 1678 | } | ||||
| 1679 | } | ||||
| 1680 | } | ||||
| 1681 | |||||
| 1682 | // VerifyParameterAttrs - Check the given attributes for an argument or return | ||||
| 1683 | // value of the specified type. The value V is printed in error messages. | ||||
| 1684 | void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, | ||||
| 1685 | const Value *V) { | ||||
| 1686 | if (!Attrs.hasAttributes()) | ||||
| 1687 | return; | ||||
| 1688 | |||||
| 1689 | verifyAttributeTypes(Attrs, V); | ||||
| 1690 | |||||
| 1691 | for (Attribute Attr : Attrs) | ||||
| 1692 | Assert(Attr.isStringAttribute() ||do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
| 1693 | Attribute::canUseAsParamAttr(Attr.getKindAsEnum()),do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
| 1694 | "Attribute '" + Attr.getAsString() +do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
| 1695 | "' does not apply to parameters",do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
| 1696 | V)do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false); | ||||
| 1697 | |||||
| 1698 | if (Attrs.hasAttribute(Attribute::ImmArg)) { | ||||
| 1699 | Assert(Attrs.getNumAttributes() == 1,do { if (!(Attrs.getNumAttributes() == 1)) { CheckFailed("Attribute 'immarg' is incompatible with other attributes" , V); return; } } while (false) | ||||
| 1700 | "Attribute 'immarg' is incompatible with other attributes", V)do { if (!(Attrs.getNumAttributes() == 1)) { CheckFailed("Attribute 'immarg' is incompatible with other attributes" , V); return; } } while (false); | ||||
| 1701 | } | ||||
| 1702 | |||||
| 1703 | // Check for mutually incompatible attributes. Only inreg is compatible with | ||||
| 1704 | // sret. | ||||
| 1705 | unsigned AttrCount = 0; | ||||
| 1706 | AttrCount += Attrs.hasAttribute(Attribute::ByVal); | ||||
| 1707 | AttrCount += Attrs.hasAttribute(Attribute::InAlloca); | ||||
| 1708 | AttrCount += Attrs.hasAttribute(Attribute::Preallocated); | ||||
| 1709 | AttrCount += Attrs.hasAttribute(Attribute::StructRet) || | ||||
| 1710 | Attrs.hasAttribute(Attribute::InReg); | ||||
| 1711 | AttrCount += Attrs.hasAttribute(Attribute::Nest); | ||||
| 1712 | AttrCount += Attrs.hasAttribute(Attribute::ByRef); | ||||
| 1713 | Assert(AttrCount <= 1,do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
| 1714 | "Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', "do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
| 1715 | "'byref', and 'sret' are incompatible!",do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
| 1716 | V)do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false); | ||||
| 1717 | |||||
| 1718 | Assert(!(Attrs.hasAttribute(Attribute::InAlloca) &&do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1719 | Attrs.hasAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1720 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1721 | "'inalloca and readonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1722 | V)do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false); | ||||
| 1723 | |||||
| 1724 | Assert(!(Attrs.hasAttribute(Attribute::StructRet) &&do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1725 | Attrs.hasAttribute(Attribute::Returned)),do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1726 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1727 | "'sret and returned' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1728 | V)do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false); | ||||
| 1729 | |||||
| 1730 | Assert(!(Attrs.hasAttribute(Attribute::ZExt) &&do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1731 | Attrs.hasAttribute(Attribute::SExt)),do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1732 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1733 | "'zeroext and signext' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1734 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false); | ||||
| 1735 | |||||
| 1736 | Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1737 | Attrs.hasAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1738 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1739 | "'readnone and readonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1740 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false); | ||||
| 1741 | |||||
| 1742 | Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1743 | Attrs.hasAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1744 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1745 | "'readnone and writeonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1746 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false); | ||||
| 1747 | |||||
| 1748 | Assert(!(Attrs.hasAttribute(Attribute::ReadOnly) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1749 | Attrs.hasAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1750 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1751 | "'readonly and writeonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1752 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false); | ||||
| 1753 | |||||
| 1754 | Assert(!(Attrs.hasAttribute(Attribute::NoInline) &&do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1755 | Attrs.hasAttribute(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1756 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1757 | "'noinline and alwaysinline' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1758 | V)do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false); | ||||
| 1759 | |||||
| 1760 | AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty); | ||||
| 1761 | for (Attribute Attr : Attrs) { | ||||
| 1762 | if (!Attr.isStringAttribute() && | ||||
| 1763 | IncompatibleAttrs.contains(Attr.getKindAsEnum())) { | ||||
| 1764 | CheckFailed("Attribute '" + Attr.getAsString() + | ||||
| 1765 | "' applied to incompatible type!", V); | ||||
| 1766 | return; | ||||
| 1767 | } | ||||
| 1768 | } | ||||
| 1769 | |||||
| 1770 | if (PointerType *PTy = dyn_cast<PointerType>(Ty)) { | ||||
| 1771 | if (Attrs.hasAttribute(Attribute::ByVal)) { | ||||
| 1772 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1773 | Assert(Attrs.getByValType()->isSized(&Visited),do { if (!(Attrs.getByValType()->isSized(&Visited))) { CheckFailed("Attribute 'byval' does not support unsized types!" , V); return; } } while (false) | ||||
| 1774 | "Attribute 'byval' does not support unsized types!", V)do { if (!(Attrs.getByValType()->isSized(&Visited))) { CheckFailed("Attribute 'byval' does not support unsized types!" , V); return; } } while (false); | ||||
| 1775 | } | ||||
| 1776 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
| 1777 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1778 | Assert(Attrs.getByRefType()->isSized(&Visited),do { if (!(Attrs.getByRefType()->isSized(&Visited))) { CheckFailed("Attribute 'byref' does not support unsized types!" , V); return; } } while (false) | ||||
| 1779 | "Attribute 'byref' does not support unsized types!", V)do { if (!(Attrs.getByRefType()->isSized(&Visited))) { CheckFailed("Attribute 'byref' does not support unsized types!" , V); return; } } while (false); | ||||
| 1780 | } | ||||
| 1781 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
| 1782 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1783 | Assert(Attrs.getInAllocaType()->isSized(&Visited),do { if (!(Attrs.getInAllocaType()->isSized(&Visited)) ) { CheckFailed("Attribute 'inalloca' does not support unsized types!" , V); return; } } while (false) | ||||
| 1784 | "Attribute 'inalloca' does not support unsized types!", V)do { if (!(Attrs.getInAllocaType()->isSized(&Visited)) ) { CheckFailed("Attribute 'inalloca' does not support unsized types!" , V); return; } } while (false); | ||||
| 1785 | } | ||||
| 1786 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
| 1787 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1788 | Assert(Attrs.getPreallocatedType()->isSized(&Visited),do { if (!(Attrs.getPreallocatedType()->isSized(&Visited ))) { CheckFailed("Attribute 'preallocated' does not support unsized types!" , V); return; } } while (false) | ||||
| 1789 | "Attribute 'preallocated' does not support unsized types!", V)do { if (!(Attrs.getPreallocatedType()->isSized(&Visited ))) { CheckFailed("Attribute 'preallocated' does not support unsized types!" , V); return; } } while (false); | ||||
| 1790 | } | ||||
| 1791 | if (!PTy->isOpaque()) { | ||||
| 1792 | if (!isa<PointerType>(PTy->getElementType())) | ||||
| 1793 | Assert(!Attrs.hasAttribute(Attribute::SwiftError),do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
| 1794 | "Attribute 'swifterror' only applies to parameters "do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
| 1795 | "with pointer to pointer type!",do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
| 1796 | V)do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false); | ||||
| 1797 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
| 1798 | Assert(Attrs.getByRefType() == PTy->getElementType(),do { if (!(Attrs.getByRefType() == PTy->getElementType())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false) | ||||
| 1799 | "Attribute 'byref' type does not match parameter!", V)do { if (!(Attrs.getByRefType() == PTy->getElementType())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false); | ||||
| 1800 | } | ||||
| 1801 | |||||
| 1802 | if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) { | ||||
| 1803 | Assert(Attrs.getByValType() == PTy->getElementType(),do { if (!(Attrs.getByValType() == PTy->getElementType())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false) | ||||
| 1804 | "Attribute 'byval' type does not match parameter!", V)do { if (!(Attrs.getByValType() == PTy->getElementType())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false); | ||||
| 1805 | } | ||||
| 1806 | |||||
| 1807 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
| 1808 | Assert(Attrs.getPreallocatedType() == PTy->getElementType(),do { if (!(Attrs.getPreallocatedType() == PTy->getElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false) | ||||
| 1809 | "Attribute 'preallocated' type does not match parameter!", V)do { if (!(Attrs.getPreallocatedType() == PTy->getElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false); | ||||
| 1810 | } | ||||
| 1811 | |||||
| 1812 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
| 1813 | Assert(Attrs.getInAllocaType() == PTy->getElementType(),do { if (!(Attrs.getInAllocaType() == PTy->getElementType( ))) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false) | ||||
| 1814 | "Attribute 'inalloca' type does not match parameter!", V)do { if (!(Attrs.getInAllocaType() == PTy->getElementType( ))) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false); | ||||
| 1815 | } | ||||
| 1816 | |||||
| 1817 | if (Attrs.hasAttribute(Attribute::ElementType)) { | ||||
| 1818 | Assert(Attrs.getElementType() == PTy->getElementType(),do { if (!(Attrs.getElementType() == PTy->getElementType() )) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false) | ||||
| 1819 | "Attribute 'elementtype' type does not match parameter!", V)do { if (!(Attrs.getElementType() == PTy->getElementType() )) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false); | ||||
| 1820 | } | ||||
| 1821 | } | ||||
| 1822 | } | ||||
| 1823 | } | ||||
| 1824 | |||||
| 1825 | void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
| 1826 | const Value *V) { | ||||
| 1827 | if (Attrs.hasFnAttribute(Attr)) { | ||||
| 1828 | StringRef S = Attrs.getAttribute(AttributeList::FunctionIndex, Attr) | ||||
| 1829 | .getValueAsString(); | ||||
| 1830 | unsigned N; | ||||
| 1831 | if (S.getAsInteger(10, N)) | ||||
| 1832 | CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, V); | ||||
| 1833 | } | ||||
| 1834 | } | ||||
| 1835 | |||||
| 1836 | // Check parameter attributes against a function type. | ||||
| 1837 | // The value V is printed in error messages. | ||||
| 1838 | void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
| 1839 | const Value *V, bool IsIntrinsic) { | ||||
| 1840 | if (Attrs.isEmpty()) | ||||
| 1841 | return; | ||||
| 1842 | |||||
| 1843 | if (AttributeListsVisited.insert(Attrs.getRawPointer()).second) { | ||||
| 1844 | Assert(Attrs.hasParentContext(Context),do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false) | ||||
| 1845 | "Attribute list does not match Module context!", &Attrs, V)do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false); | ||||
| 1846 | for (const auto &AttrSet : Attrs) { | ||||
| 1847 | Assert(!AttrSet.hasAttributes() || AttrSet.hasParentContext(Context),do { if (!(!AttrSet.hasAttributes() || AttrSet.hasParentContext (Context))) { CheckFailed("Attribute set does not match Module context!" , &AttrSet, V); return; } } while (false) | ||||
| 1848 | "Attribute set does not match Module context!", &AttrSet, V)do { if (!(!AttrSet.hasAttributes() || AttrSet.hasParentContext (Context))) { CheckFailed("Attribute set does not match Module context!" , &AttrSet, V); return; } } while (false); | ||||
| 1849 | for (const auto &A : AttrSet) { | ||||
| 1850 | Assert(A.hasParentContext(Context),do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false) | ||||
| 1851 | "Attribute does not match Module context!", &A, V)do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false); | ||||
| 1852 | } | ||||
| 1853 | } | ||||
| 1854 | } | ||||
| 1855 | |||||
| 1856 | bool SawNest = false; | ||||
| 1857 | bool SawReturned = false; | ||||
| 1858 | bool SawSRet = false; | ||||
| 1859 | bool SawSwiftSelf = false; | ||||
| 1860 | bool SawSwiftAsync = false; | ||||
| 1861 | bool SawSwiftError = false; | ||||
| 1862 | |||||
| 1863 | // Verify return value attributes. | ||||
| 1864 | AttributeSet RetAttrs = Attrs.getRetAttributes(); | ||||
| 1865 | for (Attribute RetAttr : RetAttrs) | ||||
| 1866 | Assert(RetAttr.isStringAttribute() ||do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 1867 | Attribute::canUseAsRetAttr(RetAttr.getKindAsEnum()),do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 1868 | "Attribute '" + RetAttr.getAsString() +do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 1869 | "' does not apply to function return values",do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 1870 | V)do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false); | ||||
| 1871 | |||||
| 1872 | verifyParameterAttrs(RetAttrs, FT->getReturnType(), V); | ||||
| 1873 | |||||
| 1874 | // Verify parameter attributes. | ||||
| 1875 | for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { | ||||
| 1876 | Type *Ty = FT->getParamType(i); | ||||
| 1877 | AttributeSet ArgAttrs = Attrs.getParamAttributes(i); | ||||
| 1878 | |||||
| 1879 | if (!IsIntrinsic) { | ||||
| 1880 | Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg),do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics",V); return; } } while (false) | ||||
| 1881 | "immarg attribute only applies to intrinsics",V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics",V); return; } } while (false); | ||||
| 1882 | Assert(!ArgAttrs.hasAttribute(Attribute::ElementType),do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics." , V); return; } } while (false) | ||||
| 1883 | "Attribute 'elementtype' can only be applied to intrinsics.", V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics." , V); return; } } while (false); | ||||
| 1884 | } | ||||
| 1885 | |||||
| 1886 | verifyParameterAttrs(ArgAttrs, Ty, V); | ||||
| 1887 | |||||
| 1888 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
| 1889 | Assert(!SawNest, "More than one parameter has attribute nest!", V)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , V); return; } } while (false); | ||||
| 1890 | SawNest = true; | ||||
| 1891 | } | ||||
| 1892 | |||||
| 1893 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
| 1894 | Assert(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false) | ||||
| 1895 | V)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false); | ||||
| 1896 | Assert(Ty->canLosslesslyBitCastTo(FT->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
| 1897 | "Incompatible argument and return types for 'returned' attribute",do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
| 1898 | V)do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false); | ||||
| 1899 | SawReturned = true; | ||||
| 1900 | } | ||||
| 1901 | |||||
| 1902 | if (ArgAttrs.hasAttribute(Attribute::StructRet)) { | ||||
| 1903 | Assert(!SawSRet, "Cannot have multiple 'sret' parameters!", V)do { if (!(!SawSRet)) { CheckFailed("Cannot have multiple 'sret' parameters!" , V); return; } } while (false); | ||||
| 1904 | Assert(i == 0 || i == 1,do { if (!(i == 0 || i == 1)) { CheckFailed("Attribute 'sret' is not on first or second parameter!" , V); return; } } while (false) | ||||
| 1905 | "Attribute 'sret' is not on first or second parameter!", V)do { if (!(i == 0 || i == 1)) { CheckFailed("Attribute 'sret' is not on first or second parameter!" , V); return; } } while (false); | ||||
| 1906 | SawSRet = true; | ||||
| 1907 | } | ||||
| 1908 | |||||
| 1909 | if (ArgAttrs.hasAttribute(Attribute::SwiftSelf)) { | ||||
| 1910 | Assert(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V)do { if (!(!SawSwiftSelf)) { CheckFailed("Cannot have multiple 'swiftself' parameters!" , V); return; } } while (false); | ||||
| 1911 | SawSwiftSelf = true; | ||||
| 1912 | } | ||||
| 1913 | |||||
| 1914 | if (ArgAttrs.hasAttribute(Attribute::SwiftAsync)) { | ||||
| 1915 | Assert(!SawSwiftAsync, "Cannot have multiple 'swiftasync' parameters!", V)do { if (!(!SawSwiftAsync)) { CheckFailed("Cannot have multiple 'swiftasync' parameters!" , V); return; } } while (false); | ||||
| 1916 | SawSwiftAsync = true; | ||||
| 1917 | } | ||||
| 1918 | |||||
| 1919 | if (ArgAttrs.hasAttribute(Attribute::SwiftError)) { | ||||
| 1920 | Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!",do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false) | ||||
| 1921 | V)do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false); | ||||
| 1922 | SawSwiftError = true; | ||||
| 1923 | } | ||||
| 1924 | |||||
| 1925 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) { | ||||
| 1926 | Assert(i == FT->getNumParams() - 1,do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false) | ||||
| 1927 | "inalloca isn't on the last parameter!", V)do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false); | ||||
| 1928 | } | ||||
| 1929 | } | ||||
| 1930 | |||||
| 1931 | if (!Attrs.hasAttributes(AttributeList::FunctionIndex)) | ||||
| 1932 | return; | ||||
| 1933 | |||||
| 1934 | verifyAttributeTypes(Attrs.getFnAttributes(), V); | ||||
| 1935 | for (Attribute FnAttr : Attrs.getFnAttributes()) | ||||
| 1936 | Assert(FnAttr.isStringAttribute() ||do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 1937 | Attribute::canUseAsFnAttr(FnAttr.getKindAsEnum()),do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 1938 | "Attribute '" + FnAttr.getAsString() +do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 1939 | "' does not apply to functions!",do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 1940 | V)do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false); | ||||
| 1941 | |||||
| 1942 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false) | ||||
| 1943 | Attrs.hasFnAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false) | ||||
| 1944 | "Attributes 'readnone and readonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes 'readnone and readonly' are incompatible!" , V); return; } } while (false); | ||||
| 1945 | |||||
| 1946 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readnone and writeonly' are incompatible!", V); return ; } } while (false) | ||||
| 1947 | Attrs.hasFnAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readnone and writeonly' are incompatible!", V); return ; } } while (false) | ||||
| 1948 | "Attributes 'readnone and writeonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readnone and writeonly' are incompatible!", V); return ; } } while (false); | ||||
| 1949 | |||||
| 1950 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadOnly) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadOnly) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readonly and writeonly' are incompatible!", V); return ; } } while (false) | ||||
| 1951 | Attrs.hasFnAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadOnly) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readonly and writeonly' are incompatible!", V); return ; } } while (false) | ||||
| 1952 | "Attributes 'readonly and writeonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadOnly) && Attrs.hasFnAttribute(Attribute::WriteOnly)))) { CheckFailed( "Attributes 'readonly and writeonly' are incompatible!", V); return ; } } while (false); | ||||
| 1953 | |||||
| 1954 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
| 1955 | Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
| 1956 | "Attributes 'readnone and inaccessiblemem_or_argmemonly' are "do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
| 1957 | "incompatible!",do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false) | ||||
| 1958 | V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly) ))) { CheckFailed("Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); return; } } while (false); | ||||
| 1959 | |||||
| 1960 | Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false) | ||||
| 1961 | Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)),do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false) | ||||
| 1962 | "Attributes 'readnone and inaccessiblememonly' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)))) { CheckFailed ("Attributes 'readnone and inaccessiblememonly' are incompatible!" , V); return; } } while (false); | ||||
| 1963 | |||||
| 1964 | Assert(!(Attrs.hasFnAttribute(Attribute::NoInline) &&do { if (!(!(Attrs.hasFnAttribute(Attribute::NoInline) && Attrs.hasFnAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes 'noinline and alwaysinline' are incompatible!", V ); return; } } while (false) | ||||
| 1965 | Attrs.hasFnAttribute(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasFnAttribute(Attribute::NoInline) && Attrs.hasFnAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes 'noinline and alwaysinline' are incompatible!", V ); return; } } while (false) | ||||
| 1966 | "Attributes 'noinline and alwaysinline' are incompatible!", V)do { if (!(!(Attrs.hasFnAttribute(Attribute::NoInline) && Attrs.hasFnAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes 'noinline and alwaysinline' are incompatible!", V ); return; } } while (false); | ||||
| 1967 | |||||
| 1968 | if (Attrs.hasFnAttribute(Attribute::OptimizeNone)) { | ||||
| 1969 | Assert(Attrs.hasFnAttribute(Attribute::NoInline),do { if (!(Attrs.hasFnAttribute(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false) | ||||
| 1970 | "Attribute 'optnone' requires 'noinline'!", V)do { if (!(Attrs.hasFnAttribute(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false); | ||||
| 1971 | |||||
| 1972 | Assert(!Attrs.hasFnAttribute(Attribute::OptimizeForSize),do { if (!(!Attrs.hasFnAttribute(Attribute::OptimizeForSize)) ) { CheckFailed("Attributes 'optsize and optnone' are incompatible!" , V); return; } } while (false) | ||||
| 1973 | "Attributes 'optsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttribute(Attribute::OptimizeForSize)) ) { CheckFailed("Attributes 'optsize and optnone' are incompatible!" , V); return; } } while (false); | ||||
| 1974 | |||||
| 1975 | Assert(!Attrs.hasFnAttribute(Attribute::MinSize),do { if (!(!Attrs.hasFnAttribute(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
| 1976 | "Attributes 'minsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttribute(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
| 1977 | } | ||||
| 1978 | |||||
| 1979 | if (Attrs.hasFnAttribute(Attribute::JumpTable)) { | ||||
| 1980 | const GlobalValue *GV = cast<GlobalValue>(V); | ||||
| 1981 | Assert(GV->hasGlobalUnnamedAddr(),do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false) | ||||
| 1982 | "Attribute 'jumptable' requires 'unnamed_addr'", V)do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false); | ||||
| 1983 | } | ||||
| 1984 | |||||
| 1985 | if (Attrs.hasFnAttribute(Attribute::AllocSize)) { | ||||
| 1986 | std::pair<unsigned, Optional<unsigned>> Args = | ||||
| 1987 | Attrs.getAllocSizeArgs(AttributeList::FunctionIndex); | ||||
| 1988 | |||||
| 1989 | auto CheckParam = [&](StringRef Name, unsigned ParamNo) { | ||||
| 1990 | if (ParamNo >= FT->getNumParams()) { | ||||
| 1991 | CheckFailed("'allocsize' " + Name + " argument is out of bounds", V); | ||||
| 1992 | return false; | ||||
| 1993 | } | ||||
| 1994 | |||||
| 1995 | if (!FT->getParamType(ParamNo)->isIntegerTy()) { | ||||
| 1996 | CheckFailed("'allocsize' " + Name + | ||||
| 1997 | " argument must refer to an integer parameter", | ||||
| 1998 | V); | ||||
| 1999 | return false; | ||||
| 2000 | } | ||||
| 2001 | |||||
| 2002 | return true; | ||||
| 2003 | }; | ||||
| 2004 | |||||
| 2005 | if (!CheckParam("element size", Args.first)) | ||||
| 2006 | return; | ||||
| 2007 | |||||
| 2008 | if (Args.second && !CheckParam("number of elements", *Args.second)) | ||||
| 2009 | return; | ||||
| 2010 | } | ||||
| 2011 | |||||
| 2012 | if (Attrs.hasFnAttribute(Attribute::VScaleRange)) { | ||||
| 2013 | std::pair<unsigned, unsigned> Args = | ||||
| 2014 | Attrs.getVScaleRangeArgs(AttributeList::FunctionIndex); | ||||
| 2015 | |||||
| 2016 | if (Args.first > Args.second && Args.second != 0) | ||||
| 2017 | CheckFailed("'vscale_range' minimum cannot be greater than maximum", V); | ||||
| 2018 | } | ||||
| 2019 | |||||
| 2020 | if (Attrs.hasFnAttribute("frame-pointer")) { | ||||
| 2021 | StringRef FP = Attrs.getAttribute(AttributeList::FunctionIndex, | ||||
| 2022 | "frame-pointer").getValueAsString(); | ||||
| 2023 | if (FP != "all" && FP != "non-leaf" && FP != "none") | ||||
| 2024 | CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V); | ||||
| 2025 | } | ||||
| 2026 | |||||
| 2027 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V); | ||||
| 2028 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V); | ||||
| 2029 | checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", V); | ||||
| 2030 | } | ||||
| 2031 | |||||
| 2032 | void Verifier::verifyFunctionMetadata( | ||||
| 2033 | ArrayRef<std::pair<unsigned, MDNode *>> MDs) { | ||||
| 2034 | for (const auto &Pair : MDs) { | ||||
| 2035 | if (Pair.first == LLVMContext::MD_prof) { | ||||
| 2036 | MDNode *MD = Pair.second; | ||||
| 2037 | Assert(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
| 2038 | "!prof annotations should have no less than 2 operands", MD)do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false); | ||||
| 2039 | |||||
| 2040 | // Check first operand. | ||||
| 2041 | Assert(MD->getOperand(0) != nullptr, "first operand should not be null",do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false) | ||||
| 2042 | MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
| 2043 | Assert(isa<MDString>(MD->getOperand(0)),do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false) | ||||
| 2044 | "expected string with name of the !prof annotation", MD)do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false); | ||||
| 2045 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
| 2046 | StringRef ProfName = MDS->getString(); | ||||
| 2047 | Assert(ProfName.equals("function_entry_count") ||do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2048 | ProfName.equals("synthetic_function_entry_count"),do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2049 | "first operand should be 'function_entry_count'"do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2050 | " or 'synthetic_function_entry_count'",do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2051 | MD)do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false); | ||||
| 2052 | |||||
| 2053 | // Check second operand. | ||||
| 2054 | Assert(MD->getOperand(1) != nullptr, "second operand should not be null",do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false) | ||||
| 2055 | MD)do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
| 2056 | Assert(isa<ConstantAsMetadata>(MD->getOperand(1)),do { if (!(isa<ConstantAsMetadata>(MD->getOperand(1) ))) { CheckFailed("expected integer argument to function_entry_count" , MD); return; } } while (false) | ||||
| 2057 | "expected integer argument to function_entry_count", MD)do { if (!(isa<ConstantAsMetadata>(MD->getOperand(1) ))) { CheckFailed("expected integer argument to function_entry_count" , MD); return; } } while (false); | ||||
| 2058 | } | ||||
| 2059 | } | ||||
| 2060 | } | ||||
| 2061 | |||||
| 2062 | void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { | ||||
| 2063 | if (!ConstantExprVisited.insert(EntryC).second) | ||||
| 2064 | return; | ||||
| 2065 | |||||
| 2066 | SmallVector<const Constant *, 16> Stack; | ||||
| 2067 | Stack.push_back(EntryC); | ||||
| 2068 | |||||
| 2069 | while (!Stack.empty()) { | ||||
| 2070 | const Constant *C = Stack.pop_back_val(); | ||||
| 2071 | |||||
| 2072 | // Check this constant expression. | ||||
| 2073 | if (const auto *CE = dyn_cast<ConstantExpr>(C)) | ||||
| 2074 | visitConstantExpr(CE); | ||||
| 2075 | |||||
| 2076 | if (const auto *GV = dyn_cast<GlobalValue>(C)) { | ||||
| 2077 | // Global Values get visited separately, but we do need to make sure | ||||
| 2078 | // that the global value is in the correct module | ||||
| 2079 | Assert(GV->getParent() == &M, "Referencing global in another module!",do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false) | ||||
| 2080 | EntryC, &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false); | ||||
| 2081 | continue; | ||||
| 2082 | } | ||||
| 2083 | |||||
| 2084 | // Visit all sub-expressions. | ||||
| 2085 | for (const Use &U : C->operands()) { | ||||
| 2086 | const auto *OpC = dyn_cast<Constant>(U); | ||||
| 2087 | if (!OpC) | ||||
| 2088 | continue; | ||||
| 2089 | if (!ConstantExprVisited.insert(OpC).second) | ||||
| 2090 | continue; | ||||
| 2091 | Stack.push_back(OpC); | ||||
| 2092 | } | ||||
| 2093 | } | ||||
| 2094 | } | ||||
| 2095 | |||||
| 2096 | void Verifier::visitConstantExpr(const ConstantExpr *CE) { | ||||
| 2097 | if (CE->getOpcode() == Instruction::BitCast) | ||||
| 2098 | Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
| 2099 | CE->getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
| 2100 | "Invalid bitcast", CE)do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false); | ||||
| 2101 | } | ||||
| 2102 | |||||
| 2103 | bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) { | ||||
| 2104 | // There shouldn't be more attribute sets than there are parameters plus the | ||||
| 2105 | // function and return value. | ||||
| 2106 | return Attrs.getNumAttrSets() <= Params + 2; | ||||
| 2107 | } | ||||
| 2108 | |||||
| 2109 | /// Verify that statepoint intrinsic is well formed. | ||||
| 2110 | void Verifier::verifyStatepoint(const CallBase &Call) { | ||||
| 2111 | assert(Call.getCalledFunction() &&((void)0) | ||||
| 2112 | Call.getCalledFunction()->getIntrinsicID() ==((void)0) | ||||
| 2113 | Intrinsic::experimental_gc_statepoint)((void)0); | ||||
| 2114 | |||||
| 2115 | Assert(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory() &&do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2116 | !Call.onlyAccessesArgMemory(),do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2117 | "gc.statepoint must read and write all memory to preserve "do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2118 | "reordering restrictions required by safepoint semantics",do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2119 | Call)do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false); | ||||
| 2120 | |||||
| 2121 | const int64_t NumPatchBytes = | ||||
| 2122 | cast<ConstantInt>(Call.getArgOperand(1))->getSExtValue(); | ||||
| 2123 | assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!")((void)0); | ||||
| 2124 | Assert(NumPatchBytes >= 0,do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
| 2125 | "gc.statepoint number of patchable bytes must be "do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
| 2126 | "positive",do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
| 2127 | Call)do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false); | ||||
| 2128 | |||||
| 2129 | const Value *Target = Call.getArgOperand(2); | ||||
| 2130 | auto *PT = dyn_cast<PointerType>(Target->getType()); | ||||
| 2131 | Assert(PT && PT->getElementType()->isFunctionTy(),do { if (!(PT && PT->getElementType()->isFunctionTy ())) { CheckFailed("gc.statepoint callee must be of function pointer type" , Call, Target); return; } } while (false) | ||||
| 2132 | "gc.statepoint callee must be of function pointer type", Call, Target)do { if (!(PT && PT->getElementType()->isFunctionTy ())) { CheckFailed("gc.statepoint callee must be of function pointer type" , Call, Target); return; } } while (false); | ||||
| 2133 | FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType()); | ||||
| 2134 | |||||
| 2135 | const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue(); | ||||
| 2136 | Assert(NumCallArgs >= 0,do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
| 2137 | "gc.statepoint number of arguments to underlying call "do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
| 2138 | "must be positive",do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
| 2139 | Call)do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false); | ||||
| 2140 | const int NumParams = (int)TargetFuncType->getNumParams(); | ||||
| 2141 | if (TargetFuncType->isVarArg()) { | ||||
| 2142 | Assert(NumCallArgs >= NumParams,do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false) | ||||
| 2143 | "gc.statepoint mismatch in number of vararg call args", Call)do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false); | ||||
| 2144 | |||||
| 2145 | // TODO: Remove this limitation | ||||
| 2146 | Assert(TargetFuncType->getReturnType()->isVoidTy(),do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
| 2147 | "gc.statepoint doesn't support wrapping non-void "do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
| 2148 | "vararg functions yet",do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
| 2149 | Call)do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false); | ||||
| 2150 | } else | ||||
| 2151 | Assert(NumCallArgs == NumParams,do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false) | ||||
| 2152 | "gc.statepoint mismatch in number of call args", Call)do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false); | ||||
| 2153 | |||||
| 2154 | const uint64_t Flags | ||||
| 2155 | = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue(); | ||||
| 2156 | Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0,do { if (!((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)) { CheckFailed("unknown flag used in gc.statepoint flags argument" , Call); return; } } while (false) | ||||
| 2157 | "unknown flag used in gc.statepoint flags argument", Call)do { if (!((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)) { CheckFailed("unknown flag used in gc.statepoint flags argument" , Call); return; } } while (false); | ||||
| 2158 | |||||
| 2159 | // Verify that the types of the call parameter arguments match | ||||
| 2160 | // the type of the wrapped callee. | ||||
| 2161 | AttributeList Attrs = Call.getAttributes(); | ||||
| 2162 | for (int i = 0; i < NumParams; i++) { | ||||
| 2163 | Type *ParamType = TargetFuncType->getParamType(i); | ||||
| 2164 | Type *ArgType = Call.getArgOperand(5 + i)->getType(); | ||||
| 2165 | Assert(ArgType == ParamType,do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
| 2166 | "gc.statepoint call argument does not match wrapped "do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
| 2167 | "function type",do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
| 2168 | Call)do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false); | ||||
| 2169 | |||||
| 2170 | if (TargetFuncType->isVarArg()) { | ||||
| 2171 | AttributeSet ArgAttrs = Attrs.getParamAttributes(5 + i); | ||||
| 2172 | Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
| 2173 | "Attribute 'sret' cannot be used for vararg call arguments!",do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
| 2174 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
| 2175 | } | ||||
| 2176 | } | ||||
| 2177 | |||||
| 2178 | const int EndCallArgsInx = 4 + NumCallArgs; | ||||
| 2179 | |||||
| 2180 | const Value *NumTransitionArgsV = Call.getArgOperand(EndCallArgsInx + 1); | ||||
| 2181 | Assert(isa<ConstantInt>(NumTransitionArgsV),do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2182 | "gc.statepoint number of transition arguments "do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2183 | "must be constant integer",do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2184 | Call)do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false); | ||||
| 2185 | const int NumTransitionArgs = | ||||
| 2186 | cast<ConstantInt>(NumTransitionArgsV)->getZExtValue(); | ||||
| 2187 | Assert(NumTransitionArgs == 0,do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false) | ||||
| 2188 | "gc.statepoint w/inline transition bundle is deprecated", Call)do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false); | ||||
| 2189 | const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; | ||||
| 2190 | |||||
| 2191 | const Value *NumDeoptArgsV = Call.getArgOperand(EndTransitionArgsInx + 1); | ||||
| 2192 | Assert(isa<ConstantInt>(NumDeoptArgsV),do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2193 | "gc.statepoint number of deoptimization arguments "do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2194 | "must be constant integer",do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2195 | Call)do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false); | ||||
| 2196 | const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue(); | ||||
| 2197 | Assert(NumDeoptArgs == 0,do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false) | ||||
| 2198 | "gc.statepoint w/inline deopt operands is deprecated", Call)do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false); | ||||
| 2199 | |||||
| 2200 | const int ExpectedNumArgs = 7 + NumCallArgs; | ||||
| 2201 | Assert(ExpectedNumArgs == (int)Call.arg_size(),do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false) | ||||
| 2202 | "gc.statepoint too many arguments", Call)do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false); | ||||
| 2203 | |||||
| 2204 | // Check that the only uses of this gc.statepoint are gc.result or | ||||
| 2205 | // gc.relocate calls which are tied to this statepoint and thus part | ||||
| 2206 | // of the same statepoint sequence | ||||
| 2207 | for (const User *U : Call.users()) { | ||||
| 2208 | const CallInst *UserCall = dyn_cast<const CallInst>(U); | ||||
| 2209 | Assert(UserCall, "illegal use of statepoint token", Call, U)do { if (!(UserCall)) { CheckFailed("illegal use of statepoint token" , Call, U); return; } } while (false); | ||||
| 2210 | if (!UserCall) | ||||
| 2211 | continue; | ||||
| 2212 | Assert(isa<GCRelocateInst>(UserCall) || isa<GCResultInst>(UserCall),do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
| 2213 | "gc.result or gc.relocate are the only value uses "do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
| 2214 | "of a gc.statepoint",do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
| 2215 | Call, U)do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false); | ||||
| 2216 | if (isa<GCResultInst>(UserCall)) { | ||||
| 2217 | Assert(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
| 2218 | "gc.result connected to wrong gc.statepoint", Call, UserCall)do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false); | ||||
| 2219 | } else if (isa<GCRelocateInst>(Call)) { | ||||
| 2220 | Assert(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
| 2221 | "gc.relocate connected to wrong gc.statepoint", Call, UserCall)do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false); | ||||
| 2222 | } | ||||
| 2223 | } | ||||
| 2224 | |||||
| 2225 | // Note: It is legal for a single derived pointer to be listed multiple | ||||
| 2226 | // times. It's non-optimal, but it is legal. It can also happen after | ||||
| 2227 | // insertion if we strip a bitcast away. | ||||
| 2228 | // Note: It is really tempting to check that each base is relocated and | ||||
| 2229 | // that a derived pointer is never reused as a base pointer. This turns | ||||
| 2230 | // out to be problematic since optimizations run after safepoint insertion | ||||
| 2231 | // can recognize equality properties that the insertion logic doesn't know | ||||
| 2232 | // about. See example statepoint.ll in the verifier subdirectory | ||||
| 2233 | } | ||||
| 2234 | |||||
| 2235 | void Verifier::verifyFrameRecoverIndices() { | ||||
| 2236 | for (auto &Counts : FrameEscapeInfo) { | ||||
| 2237 | Function *F = Counts.first; | ||||
| 2238 | unsigned EscapedObjectCount = Counts.second.first; | ||||
| 2239 | unsigned MaxRecoveredIndex = Counts.second.second; | ||||
| 2240 | Assert(MaxRecoveredIndex <= EscapedObjectCount,do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2241 | "all indices passed to llvm.localrecover must be less than the "do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2242 | "number of arguments passed to llvm.localescape in the parent "do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2243 | "function",do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2244 | F)do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false); | ||||
| 2245 | } | ||||
| 2246 | } | ||||
| 2247 | |||||
| 2248 | static Instruction *getSuccPad(Instruction *Terminator) { | ||||
| 2249 | BasicBlock *UnwindDest; | ||||
| 2250 | if (auto *II = dyn_cast<InvokeInst>(Terminator)) | ||||
| 2251 | UnwindDest = II->getUnwindDest(); | ||||
| 2252 | else if (auto *CSI = dyn_cast<CatchSwitchInst>(Terminator)) | ||||
| 2253 | UnwindDest = CSI->getUnwindDest(); | ||||
| 2254 | else | ||||
| 2255 | UnwindDest = cast<CleanupReturnInst>(Terminator)->getUnwindDest(); | ||||
| 2256 | return UnwindDest->getFirstNonPHI(); | ||||
| 2257 | } | ||||
| 2258 | |||||
| 2259 | void Verifier::verifySiblingFuncletUnwinds() { | ||||
| 2260 | SmallPtrSet<Instruction *, 8> Visited; | ||||
| 2261 | SmallPtrSet<Instruction *, 8> Active; | ||||
| 2262 | for (const auto &Pair : SiblingFuncletInfo) { | ||||
| 2263 | Instruction *PredPad = Pair.first; | ||||
| 2264 | if (Visited.count(PredPad)) | ||||
| 2265 | continue; | ||||
| 2266 | Active.insert(PredPad); | ||||
| 2267 | Instruction *Terminator = Pair.second; | ||||
| 2268 | do { | ||||
| 2269 | Instruction *SuccPad = getSuccPad(Terminator); | ||||
| 2270 | if (Active.count(SuccPad)) { | ||||
| 2271 | // Found a cycle; report error | ||||
| 2272 | Instruction *CyclePad = SuccPad; | ||||
| 2273 | SmallVector<Instruction *, 8> CycleNodes; | ||||
| 2274 | do { | ||||
| 2275 | CycleNodes.push_back(CyclePad); | ||||
| 2276 | Instruction *CycleTerminator = SiblingFuncletInfo[CyclePad]; | ||||
| 2277 | if (CycleTerminator != CyclePad) | ||||
| 2278 | CycleNodes.push_back(CycleTerminator); | ||||
| 2279 | CyclePad = getSuccPad(CycleTerminator); | ||||
| 2280 | } while (CyclePad != SuccPad); | ||||
| 2281 | Assert(false, "EH pads can't handle each other's exceptions",do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false) | ||||
| 2282 | ArrayRef<Instruction *>(CycleNodes))do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false); | ||||
| 2283 | } | ||||
| 2284 | // Don't re-walk a node we've already checked | ||||
| 2285 | if (!Visited.insert(SuccPad).second) | ||||
| 2286 | break; | ||||
| 2287 | // Walk to this successor if it has a map entry. | ||||
| 2288 | PredPad = SuccPad; | ||||
| 2289 | auto TermI = SiblingFuncletInfo.find(PredPad); | ||||
| 2290 | if (TermI == SiblingFuncletInfo.end()) | ||||
| 2291 | break; | ||||
| 2292 | Terminator = TermI->second; | ||||
| 2293 | Active.insert(PredPad); | ||||
| 2294 | } while (true); | ||||
| 2295 | // Each node only has one successor, so we've walked all the active | ||||
| 2296 | // nodes' successors. | ||||
| 2297 | Active.clear(); | ||||
| 2298 | } | ||||
| 2299 | } | ||||
| 2300 | |||||
| 2301 | // visitFunction - Verify that a function is ok. | ||||
| 2302 | // | ||||
| 2303 | void Verifier::visitFunction(const Function &F) { | ||||
| 2304 | visitGlobalValue(F); | ||||
| 2305 | |||||
| 2306 | // Check function arguments. | ||||
| 2307 | FunctionType *FT = F.getFunctionType(); | ||||
| 2308 | unsigned NumArgs = F.arg_size(); | ||||
| 2309 | |||||
| 2310 | Assert(&Context == &F.getContext(),do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false) | ||||
| |||||
| 2311 | "Function context does not match Module context!", &F)do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false); | ||||
| 2312 | |||||
| 2313 | Assert(!F.hasCommonLinkage(), "Functions may not have common linkage", &F)do { if (!(!F.hasCommonLinkage())) { CheckFailed("Functions may not have common linkage" , &F); return; } } while (false); | ||||
| 2314 | Assert(FT->getNumParams() == NumArgs,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
| 2315 | "# formal arguments must match # of arguments for function type!", &F,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
| 2316 | FT)do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false); | ||||
| 2317 | Assert(F.getReturnType()->isFirstClassType() ||do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false) | ||||
| 2318 | F.getReturnType()->isVoidTy() || F.getReturnType()->isStructTy(),do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false) | ||||
| 2319 | "Functions cannot return aggregate values!", &F)do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false); | ||||
| 2320 | |||||
| 2321 | Assert(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false) | ||||
| 2322 | "Invalid struct return type!", &F)do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false); | ||||
| 2323 | |||||
| 2324 | AttributeList Attrs = F.getAttributes(); | ||||
| 2325 | |||||
| 2326 | Assert(verifyAttributeCount(Attrs, FT->getNumParams()),do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false) | ||||
| 2327 | "Attribute after last parameter!", &F)do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false); | ||||
| 2328 | |||||
| 2329 | bool IsIntrinsic = F.isIntrinsic(); | ||||
| 2330 | |||||
| 2331 | // Check function attributes. | ||||
| 2332 | verifyFunctionAttrs(FT, Attrs, &F, IsIntrinsic); | ||||
| 2333 | |||||
| 2334 | // On function declarations/definitions, we do not support the builtin | ||||
| 2335 | // attribute. We do not check this in VerifyFunctionAttrs since that is | ||||
| 2336 | // checking for Attributes that can/can not ever be on functions. | ||||
| 2337 | Assert(!Attrs.hasFnAttribute(Attribute::Builtin),do { if (!(!Attrs.hasFnAttribute(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false) | ||||
| 2338 | "Attribute 'builtin' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasFnAttribute(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false); | ||||
| 2339 | |||||
| 2340 | Assert(!Attrs.hasAttrSomewhere(Attribute::ElementType),do { if (!(!Attrs.hasAttrSomewhere(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to a callsite." , &F); return; } } while (false) | ||||
| 2341 | "Attribute 'elementtype' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasAttrSomewhere(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to a callsite." , &F); return; } } while (false); | ||||
| 2342 | |||||
| 2343 | // Check that this function meets the restrictions on this calling convention. | ||||
| 2344 | // Sometimes varargs is used for perfectly forwarding thunks, so some of these | ||||
| 2345 | // restrictions can be lifted. | ||||
| 2346 | switch (F.getCallingConv()) { | ||||
| 2347 | default: | ||||
| 2348 | case CallingConv::C: | ||||
| 2349 | break; | ||||
| 2350 | case CallingConv::X86_INTR: { | ||||
| 2351 | Assert(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute::ByVal),do { if (!(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute ::ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false) | ||||
| 2352 | "Calling convention parameter requires byval", &F)do { if (!(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute ::ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false); | ||||
| 2353 | break; | ||||
| 2354 | } | ||||
| 2355 | case CallingConv::AMDGPU_KERNEL: | ||||
| 2356 | case CallingConv::SPIR_KERNEL: | ||||
| 2357 | Assert(F.getReturnType()->isVoidTy(),do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false) | ||||
| 2358 | "Calling convention requires void return type", &F)do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false); | ||||
| 2359 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
| 2360 | case CallingConv::AMDGPU_VS: | ||||
| 2361 | case CallingConv::AMDGPU_HS: | ||||
| 2362 | case CallingConv::AMDGPU_GS: | ||||
| 2363 | case CallingConv::AMDGPU_PS: | ||||
| 2364 | case CallingConv::AMDGPU_CS: | ||||
| 2365 | Assert(!F.hasStructRetAttr(),do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false) | ||||
| 2366 | "Calling convention does not allow sret", &F)do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false); | ||||
| 2367 | if (F.getCallingConv() != CallingConv::SPIR_KERNEL) { | ||||
| 2368 | const unsigned StackAS = DL.getAllocaAddrSpace(); | ||||
| 2369 | unsigned i = 0; | ||||
| 2370 | for (const Argument &Arg : F.args()) { | ||||
| 2371 | Assert(!Attrs.hasParamAttribute(i, Attribute::ByVal),do { if (!(!Attrs.hasParamAttribute(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false) | ||||
| 2372 | "Calling convention disallows byval", &F)do { if (!(!Attrs.hasParamAttribute(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false); | ||||
| 2373 | Assert(!Attrs.hasParamAttribute(i, Attribute::Preallocated),do { if (!(!Attrs.hasParamAttribute(i, Attribute::Preallocated ))) { CheckFailed("Calling convention disallows preallocated" , &F); return; } } while (false) | ||||
| 2374 | "Calling convention disallows preallocated", &F)do { if (!(!Attrs.hasParamAttribute(i, Attribute::Preallocated ))) { CheckFailed("Calling convention disallows preallocated" , &F); return; } } while (false); | ||||
| 2375 | Assert(!Attrs.hasParamAttribute(i, Attribute::InAlloca),do { if (!(!Attrs.hasParamAttribute(i, Attribute::InAlloca))) { CheckFailed("Calling convention disallows inalloca", & F); return; } } while (false) | ||||
| 2376 | "Calling convention disallows inalloca", &F)do { if (!(!Attrs.hasParamAttribute(i, Attribute::InAlloca))) { CheckFailed("Calling convention disallows inalloca", & F); return; } } while (false); | ||||
| 2377 | |||||
| 2378 | if (Attrs.hasParamAttribute(i, Attribute::ByRef)) { | ||||
| 2379 | // FIXME: Should also disallow LDS and GDS, but we don't have the enum | ||||
| 2380 | // value here. | ||||
| 2381 | Assert(Arg.getType()->getPointerAddressSpace() != StackAS,do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false) | ||||
| 2382 | "Calling convention disallows stack byref", &F)do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false); | ||||
| 2383 | } | ||||
| 2384 | |||||
| 2385 | ++i; | ||||
| 2386 | } | ||||
| 2387 | } | ||||
| 2388 | |||||
| 2389 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
| 2390 | case CallingConv::Fast: | ||||
| 2391 | case CallingConv::Cold: | ||||
| 2392 | case CallingConv::Intel_OCL_BI: | ||||
| 2393 | case CallingConv::PTX_Kernel: | ||||
| 2394 | case CallingConv::PTX_Device: | ||||
| 2395 | Assert(!F.isVarArg(), "Calling convention does not support varargs or "do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
| 2396 | "perfect forwarding!",do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
| 2397 | &F)do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false); | ||||
| 2398 | break; | ||||
| 2399 | } | ||||
| 2400 | |||||
| 2401 | // Check that the argument values match the function type for this function... | ||||
| 2402 | unsigned i = 0; | ||||
| 2403 | for (const Argument &Arg : F.args()) { | ||||
| 2404 | Assert(Arg.getType() == FT->getParamType(i),do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false) | ||||
| 2405 | "Argument value does not match function argument type!", &Arg,do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false) | ||||
| 2406 | FT->getParamType(i))do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false); | ||||
| 2407 | Assert(Arg.getType()->isFirstClassType(),do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false) | ||||
| 2408 | "Function arguments must have first-class types!", &Arg)do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false); | ||||
| 2409 | if (!IsIntrinsic) { | ||||
| 2410 | Assert(!Arg.getType()->isMetadataTy(),do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false) | ||||
| 2411 | "Function takes metadata but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false); | ||||
| 2412 | Assert(!Arg.getType()->isTokenTy(),do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
| 2413 | "Function takes token but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false); | ||||
| 2414 | Assert(!Arg.getType()->isX86_AMXTy(),do { if (!(!Arg.getType()->isX86_AMXTy())) { CheckFailed("Function takes x86_amx but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
| 2415 | "Function takes x86_amx but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isX86_AMXTy())) { CheckFailed("Function takes x86_amx but isn't an intrinsic" , &Arg, &F); return; } } while (false); | ||||
| 2416 | } | ||||
| 2417 | |||||
| 2418 | // Check that swifterror argument is only used by loads and stores. | ||||
| 2419 | if (Attrs.hasParamAttribute(i, Attribute::SwiftError)) { | ||||
| 2420 | verifySwiftErrorValue(&Arg); | ||||
| 2421 | } | ||||
| 2422 | ++i; | ||||
| 2423 | } | ||||
| 2424 | |||||
| 2425 | if (!IsIntrinsic) { | ||||
| 2426 | Assert(!F.getReturnType()->isTokenTy(),do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false) | ||||
| 2427 | "Function returns a token but isn't an intrinsic", &F)do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false); | ||||
| 2428 | Assert(!F.getReturnType()->isX86_AMXTy(),do { if (!(!F.getReturnType()->isX86_AMXTy())) { CheckFailed ("Function returns a x86_amx but isn't an intrinsic", &F) ; return; } } while (false) | ||||
| 2429 | "Function returns a x86_amx but isn't an intrinsic", &F)do { if (!(!F.getReturnType()->isX86_AMXTy())) { CheckFailed ("Function returns a x86_amx but isn't an intrinsic", &F) ; return; } } while (false); | ||||
| 2430 | } | ||||
| 2431 | |||||
| 2432 | // Get the function metadata attachments. | ||||
| 2433 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
| 2434 | F.getAllMetadata(MDs); | ||||
| 2435 | assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync")((void)0); | ||||
| 2436 | verifyFunctionMetadata(MDs); | ||||
| 2437 | |||||
| 2438 | // Check validity of the personality function | ||||
| 2439 | if (F.hasPersonalityFn()) { | ||||
| 2440 | auto *Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); | ||||
| 2441 | if (Per) | ||||
| 2442 | Assert(Per->getParent() == F.getParent(),do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false) | ||||
| 2443 | "Referencing personality function in another module!",do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false) | ||||
| 2444 | &F, F.getParent(), Per, Per->getParent())do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false); | ||||
| 2445 | } | ||||
| 2446 | |||||
| 2447 | if (F.isMaterializable()) { | ||||
| 2448 | // Function has a body somewhere we can't see. | ||||
| 2449 | Assert(MDs.empty(), "unmaterialized function cannot have metadata", &F,do { if (!(MDs.empty())) { CheckFailed("unmaterialized function cannot have metadata" , &F, MDs.empty() ? nullptr : MDs.front().second); return ; } } while (false) | ||||
| 2450 | MDs.empty() ? nullptr : MDs.front().second)do { if (!(MDs.empty())) { CheckFailed("unmaterialized function cannot have metadata" , &F, MDs.empty() ? nullptr : MDs.front().second); return ; } } while (false); | ||||
| 2451 | } else if (F.isDeclaration()) { | ||||
| 2452 | for (const auto &I : MDs) { | ||||
| 2453 | // This is used for call site debug information. | ||||
| 2454 | AssertDI(I.first != LLVMContext::MD_dbg ||do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
| 2455 | !cast<DISubprogram>(I.second)->isDistinct(),do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
| 2456 | "function declaration may only have a unique !dbg attachment",do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
| 2457 | &F)do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false); | ||||
| 2458 | Assert(I.first != LLVMContext::MD_prof,do { if (!(I.first != LLVMContext::MD_prof)) { CheckFailed("function declaration may not have a !prof attachment" , &F); return; } } while (false) | ||||
| 2459 | "function declaration may not have a !prof attachment", &F)do { if (!(I.first != LLVMContext::MD_prof)) { CheckFailed("function declaration may not have a !prof attachment" , &F); return; } } while (false); | ||||
| 2460 | |||||
| 2461 | // Verify the metadata itself. | ||||
| 2462 | visitMDNode(*I.second, AreDebugLocsAllowed::Yes); | ||||
| 2463 | } | ||||
| 2464 | Assert(!F.hasPersonalityFn(),do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false) | ||||
| 2465 | "Function declaration shouldn't have a personality routine", &F)do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false); | ||||
| 2466 | } else { | ||||
| 2467 | // Verify that this function (which has a body) is not named "llvm.*". It | ||||
| 2468 | // is not legal to define intrinsics. | ||||
| 2469 | Assert(!IsIntrinsic, "llvm intrinsics cannot be defined!", &F)do { if (!(!IsIntrinsic)) { CheckFailed("llvm intrinsics cannot be defined!" , &F); return; } } while (false); | ||||
| 2470 | |||||
| 2471 | // Check the entry node | ||||
| 2472 | const BasicBlock *Entry = &F.getEntryBlock(); | ||||
| 2473 | Assert(pred_empty(Entry),do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false) | ||||
| 2474 | "Entry block to function must not have predecessors!", Entry)do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false); | ||||
| 2475 | |||||
| 2476 | // The address of the entry block cannot be taken, unless it is dead. | ||||
| 2477 | if (Entry->hasAddressTaken()) { | ||||
| 2478 | Assert(!BlockAddress::lookup(Entry)->isConstantUsed(),do { if (!(!BlockAddress::lookup(Entry)->isConstantUsed()) ) { CheckFailed("blockaddress may not be used with the entry block!" , Entry); return; } } while (false) | ||||
| 2479 | "blockaddress may not be used with the entry block!", Entry)do { if (!(!BlockAddress::lookup(Entry)->isConstantUsed()) ) { CheckFailed("blockaddress may not be used with the entry block!" , Entry); return; } } while (false); | ||||
| 2480 | } | ||||
| 2481 | |||||
| 2482 | unsigned NumDebugAttachments = 0, NumProfAttachments = 0; | ||||
| 2483 | // Visit metadata attachments. | ||||
| 2484 | for (const auto &I : MDs) { | ||||
| 2485 | // Verify that the attachment is legal. | ||||
| 2486 | auto AllowLocs = AreDebugLocsAllowed::No; | ||||
| 2487 | switch (I.first) { | ||||
| 2488 | default: | ||||
| 2489 | break; | ||||
| 2490 | case LLVMContext::MD_dbg: { | ||||
| 2491 | ++NumDebugAttachments; | ||||
| 2492 | AssertDI(NumDebugAttachments == 1,do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false) | ||||
| 2493 | "function must have a single !dbg attachment", &F, I.second)do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false); | ||||
| 2494 | AssertDI(isa<DISubprogram>(I.second),do { if (!(isa<DISubprogram>(I.second))) { DebugInfoCheckFailed ("function !dbg attachment must be a subprogram", &F, I.second ); return; } } while (false) | ||||
| 2495 | "function !dbg attachment must be a subprogram", &F, I.second)do { if (!(isa<DISubprogram>(I.second))) { DebugInfoCheckFailed ("function !dbg attachment must be a subprogram", &F, I.second ); return; } } while (false); | ||||
| 2496 | AssertDI(cast<DISubprogram>(I.second)->isDistinct(),do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false) | ||||
| 2497 | "function definition may only have a distinct !dbg attachment",do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false) | ||||
| 2498 | &F)do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false); | ||||
| 2499 | |||||
| 2500 | auto *SP = cast<DISubprogram>(I.second); | ||||
| 2501 | const Function *&AttachedTo = DISubprogramAttachments[SP]; | ||||
| 2502 | AssertDI(!AttachedTo || AttachedTo == &F,do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false) | ||||
| 2503 | "DISubprogram attached to more than one function", SP, &F)do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false); | ||||
| 2504 | AttachedTo = &F; | ||||
| 2505 | AllowLocs = AreDebugLocsAllowed::Yes; | ||||
| 2506 | break; | ||||
| 2507 | } | ||||
| 2508 | case LLVMContext::MD_prof: | ||||
| 2509 | ++NumProfAttachments; | ||||
| 2510 | Assert(NumProfAttachments == 1,do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false) | ||||
| 2511 | "function must have a single !prof attachment", &F, I.second)do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false); | ||||
| 2512 | break; | ||||
| 2513 | } | ||||
| 2514 | |||||
| 2515 | // Verify the metadata itself. | ||||
| 2516 | visitMDNode(*I.second, AllowLocs); | ||||
| 2517 | } | ||||
| 2518 | } | ||||
| 2519 | |||||
| 2520 | // If this function is actually an intrinsic, verify that it is only used in | ||||
| 2521 | // direct call/invokes, never having its "address taken". | ||||
| 2522 | // Only do this if the module is materialized, otherwise we don't have all the | ||||
| 2523 | // uses. | ||||
| 2524 | if (F.isIntrinsic() && F.getParent()->isMaterialized()) { | ||||
| 2525 | const User *U; | ||||
| 2526 | if (F.hasAddressTaken(&U)) | ||||
| 2527 | Assert(false, "Invalid user of intrinsic instruction!", U)do { if (!(false)) { CheckFailed("Invalid user of intrinsic instruction!" , U); return; } } while (false); | ||||
| 2528 | } | ||||
| 2529 | |||||
| 2530 | // Check intrinsics' signatures. | ||||
| 2531 | switch (F.getIntrinsicID()) { | ||||
| 2532 | case Intrinsic::experimental_gc_get_pointer_base: { | ||||
| 2533 | FunctionType *FT = F.getFunctionType(); | ||||
| 2534 | Assert(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
| 2535 | Assert(isa<PointerType>(F.getReturnType()),do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false) | ||||
| 2536 | "gc.get.pointer.base must return a pointer", F)do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false); | ||||
| 2537 | Assert(FT->getParamType(0) == F.getReturnType(),do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false) | ||||
| 2538 | "gc.get.pointer.base operand and result must be of the same type",do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false) | ||||
| 2539 | F)do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false); | ||||
| 2540 | break; | ||||
| 2541 | } | ||||
| 2542 | case Intrinsic::experimental_gc_get_pointer_offset: { | ||||
| 2543 | FunctionType *FT = F.getFunctionType(); | ||||
| 2544 | Assert(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
| 2545 | Assert(isa<PointerType>(FT->getParamType(0)),do { if (!(isa<PointerType>(FT->getParamType(0)))) { CheckFailed("gc.get.pointer.offset operand must be a pointer" , F); return; } } while (false) | ||||
| 2546 | "gc.get.pointer.offset operand must be a pointer", F)do { if (!(isa<PointerType>(FT->getParamType(0)))) { CheckFailed("gc.get.pointer.offset operand must be a pointer" , F); return; } } while (false); | ||||
| 2547 | Assert(F.getReturnType()->isIntegerTy(),do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false) | ||||
| 2548 | "gc.get.pointer.offset must return integer", F)do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false); | ||||
| 2549 | break; | ||||
| 2550 | } | ||||
| 2551 | } | ||||
| 2552 | |||||
| 2553 | auto *N = F.getSubprogram(); | ||||
| 2554 | HasDebugInfo = (N != nullptr); | ||||
| 2555 | if (!HasDebugInfo
| ||||
| 2556 | return; | ||||
| 2557 | |||||
| 2558 | // Check that all !dbg attachments lead to back to N. | ||||
| 2559 | // | ||||
| 2560 | // FIXME: Check this incrementally while visiting !dbg attachments. | ||||
| 2561 | // FIXME: Only check when N is the canonical subprogram for F. | ||||
| 2562 | SmallPtrSet<const MDNode *, 32> Seen; | ||||
| 2563 | auto VisitDebugLoc = [&](const Instruction &I, const MDNode *Node) { | ||||
| 2564 | // Be careful about using DILocation here since we might be dealing with | ||||
| 2565 | // broken code (this is the Verifier after all). | ||||
| 2566 | const DILocation *DL = dyn_cast_or_null<DILocation>(Node); | ||||
| 2567 | if (!DL
| ||||
| 2568 | return; | ||||
| 2569 | if (!Seen.insert(DL).second) | ||||
| 2570 | return; | ||||
| 2571 | |||||
| 2572 | Metadata *Parent = DL->getRawScope(); | ||||
| 2573 | AssertDI(Parent && isa<DILocalScope>(Parent),do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false) | ||||
| 2574 | "DILocation's scope must be a DILocalScope", N, &F, &I, DL,do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false) | ||||
| 2575 | Parent)do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false); | ||||
| 2576 | |||||
| 2577 | DILocalScope *Scope = DL->getInlinedAtScope(); | ||||
| 2578 | Assert(Scope, "Failed to find DILocalScope", DL)do { if (!(Scope)) { CheckFailed("Failed to find DILocalScope" , DL); return; } } while (false); | ||||
| 2579 | |||||
| 2580 | if (!Seen.insert(Scope).second) | ||||
| 2581 | return; | ||||
| 2582 | |||||
| 2583 | DISubprogram *SP = Scope->getSubprogram(); | ||||
| 2584 | |||||
| 2585 | // Scope and SP could be the same MDNode and we don't want to skip | ||||
| 2586 | // validation in that case | ||||
| 2587 | if (SP && ((Scope != SP) && !Seen.insert(SP).second)) | ||||
| 2588 | return; | ||||
| 2589 | |||||
| 2590 | AssertDI(SP->describes(&F),do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false) | ||||
| |||||
| 2591 | "!dbg attachment points at wrong subprogram for function", N, &F,do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false) | ||||
| 2592 | &I, DL, Scope, SP)do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false); | ||||
| 2593 | }; | ||||
| 2594 | for (auto &BB : F) | ||||
| 2595 | for (auto &I : BB) { | ||||
| 2596 | VisitDebugLoc(I, I.getDebugLoc().getAsMDNode()); | ||||
| 2597 | // The llvm.loop annotations also contain two DILocations. | ||||
| 2598 | if (auto MD = I.getMetadata(LLVMContext::MD_loop)) | ||||
| 2599 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) | ||||
| 2600 | VisitDebugLoc(I, dyn_cast_or_null<MDNode>(MD->getOperand(i))); | ||||
| 2601 | if (BrokenDebugInfo) | ||||
| 2602 | return; | ||||
| 2603 | } | ||||
| 2604 | } | ||||
| 2605 | |||||
| 2606 | // verifyBasicBlock - Verify that a basic block is well formed... | ||||
| 2607 | // | ||||
| 2608 | void Verifier::visitBasicBlock(BasicBlock &BB) { | ||||
| 2609 | InstsInThisBlock.clear(); | ||||
| 2610 | |||||
| 2611 | // Ensure that basic blocks have terminators! | ||||
| 2612 | Assert(BB.getTerminator(), "Basic Block does not have terminator!", &BB)do { if (!(BB.getTerminator())) { CheckFailed("Basic Block does not have terminator!" , &BB); return; } } while (false); | ||||
| 2613 | |||||
| 2614 | // Check constraints that this basic block imposes on all of the PHI nodes in | ||||
| 2615 | // it. | ||||
| 2616 | if (isa<PHINode>(BB.front())) { | ||||
| 2617 | SmallVector<BasicBlock *, 8> Preds(predecessors(&BB)); | ||||
| 2618 | SmallVector<std::pair<BasicBlock*, Value*>, 8> Values; | ||||
| 2619 | llvm::sort(Preds); | ||||
| 2620 | for (const PHINode &PN : BB.phis()) { | ||||
| 2621 | Assert(PN.getNumIncomingValues() == Preds.size(),do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
| 2622 | "PHINode should have one entry for each predecessor of its "do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
| 2623 | "parent basic block!",do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
| 2624 | &PN)do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false); | ||||
| 2625 | |||||
| 2626 | // Get and sort all incoming values in the PHI node... | ||||
| 2627 | Values.clear(); | ||||
| 2628 | Values.reserve(PN.getNumIncomingValues()); | ||||
| 2629 | for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) | ||||
| 2630 | Values.push_back( | ||||
| 2631 | std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i))); | ||||
| 2632 | llvm::sort(Values); | ||||
| 2633 | |||||
| 2634 | for (unsigned i = 0, e = Values.size(); i != e; ++i) { | ||||
| 2635 | // Check to make sure that if there is more than one entry for a | ||||
| 2636 | // particular basic block in this PHI node, that the incoming values are | ||||
| 2637 | // all identical. | ||||
| 2638 | // | ||||
| 2639 | Assert(i == 0 || Values[i].first != Values[i - 1].first ||do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2640 | Values[i].second == Values[i - 1].second,do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2641 | "PHI node has multiple entries for the same basic block with "do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2642 | "different incoming values!",do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2643 | &PN, Values[i].first, Values[i].second, Values[i - 1].second)do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false); | ||||
| 2644 | |||||
| 2645 | // Check to make sure that the predecessors and PHI node entries are | ||||
| 2646 | // matched up. | ||||
| 2647 | Assert(Values[i].first == Preds[i],do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ) | ||||
| 2648 | "PHI node entries do not match predecessors!", &PN,do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ) | ||||
| 2649 | Values[i].first, Preds[i])do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ); | ||||
| 2650 | } | ||||
| 2651 | } | ||||
| 2652 | } | ||||
| 2653 | |||||
| 2654 | // Check that all instructions have their parent pointers set up correctly. | ||||
| 2655 | for (auto &I : BB) | ||||
| 2656 | { | ||||
| 2657 | Assert(I.getParent() == &BB, "Instruction has bogus parent pointer!")do { if (!(I.getParent() == &BB)) { CheckFailed("Instruction has bogus parent pointer!" ); return; } } while (false); | ||||
| 2658 | } | ||||
| 2659 | } | ||||
| 2660 | |||||
| 2661 | void Verifier::visitTerminator(Instruction &I) { | ||||
| 2662 | // Ensure that terminators only exist at the end of the basic block. | ||||
| 2663 | Assert(&I == I.getParent()->getTerminator(),do { if (!(&I == I.getParent()->getTerminator())) { CheckFailed ("Terminator found in the middle of a basic block!", I.getParent ()); return; } } while (false) | ||||
| 2664 | "Terminator found in the middle of a basic block!", I.getParent())do { if (!(&I == I.getParent()->getTerminator())) { CheckFailed ("Terminator found in the middle of a basic block!", I.getParent ()); return; } } while (false); | ||||
| 2665 | visitInstruction(I); | ||||
| 2666 | } | ||||
| 2667 | |||||
| 2668 | void Verifier::visitBranchInst(BranchInst &BI) { | ||||
| 2669 | if (BI.isConditional()) { | ||||
| 2670 | Assert(BI.getCondition()->getType()->isIntegerTy(1),do { if (!(BI.getCondition()->getType()->isIntegerTy(1) )) { CheckFailed("Branch condition is not 'i1' type!", &BI , BI.getCondition()); return; } } while (false) | ||||
| 2671 | "Branch condition is not 'i1' type!", &BI, BI.getCondition())do { if (!(BI.getCondition()->getType()->isIntegerTy(1) )) { CheckFailed("Branch condition is not 'i1' type!", &BI , BI.getCondition()); return; } } while (false); | ||||
| 2672 | } | ||||
| 2673 | visitTerminator(BI); | ||||
| 2674 | } | ||||
| 2675 | |||||
| 2676 | void Verifier::visitReturnInst(ReturnInst &RI) { | ||||
| 2677 | Function *F = RI.getParent()->getParent(); | ||||
| 2678 | unsigned N = RI.getNumOperands(); | ||||
| 2679 | if (F->getReturnType()->isVoidTy()) | ||||
| 2680 | Assert(N == 0,do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
| 2681 | "Found return instr that returns non-void in Function of void "do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
| 2682 | "return type!",do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
| 2683 | &RI, F->getReturnType())do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false); | ||||
| 2684 | else | ||||
| 2685 | Assert(N == 1 && F->getReturnType() == RI.getOperand(0)->getType(),do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
| 2686 | "Function return type does not match operand "do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
| 2687 | "type of return inst!",do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
| 2688 | &RI, F->getReturnType())do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false); | ||||
| 2689 | |||||
| 2690 | // Check to make sure that the return value has necessary properties for | ||||
| 2691 | // terminators... | ||||
| 2692 | visitTerminator(RI); | ||||
| 2693 | } | ||||
| 2694 | |||||
| 2695 | void Verifier::visitSwitchInst(SwitchInst &SI) { | ||||
| 2696 | // Check to make sure that all of the constants in the switch instruction | ||||
| 2697 | // have the same type as the switched-on value. | ||||
| 2698 | Type *SwitchTy = SI.getCondition()->getType(); | ||||
| 2699 | SmallPtrSet<ConstantInt*, 32> Constants; | ||||
| 2700 | for (auto &Case : SI.cases()) { | ||||
| 2701 | Assert(Case.getCaseValue()->getType() == SwitchTy,do { if (!(Case.getCaseValue()->getType() == SwitchTy)) { CheckFailed ("Switch constants must all be same type as switch value!", & SI); return; } } while (false) | ||||
| 2702 | "Switch constants must all be same type as switch value!", &SI)do { if (!(Case.getCaseValue()->getType() == SwitchTy)) { CheckFailed ("Switch constants must all be same type as switch value!", & SI); return; } } while (false); | ||||
| 2703 | Assert(Constants.insert(Case.getCaseValue()).second,do { if (!(Constants.insert(Case.getCaseValue()).second)) { CheckFailed ("Duplicate integer as switch case", &SI, Case.getCaseValue ()); return; } } while (false) | ||||
| 2704 | "Duplicate integer as switch case", &SI, Case.getCaseValue())do { if (!(Constants.insert(Case.getCaseValue()).second)) { CheckFailed ("Duplicate integer as switch case", &SI, Case.getCaseValue ()); return; } } while (false); | ||||
| 2705 | } | ||||
| 2706 | |||||
| 2707 | visitTerminator(SI); | ||||
| 2708 | } | ||||
| 2709 | |||||
| 2710 | void Verifier::visitIndirectBrInst(IndirectBrInst &BI) { | ||||
| 2711 | Assert(BI.getAddress()->getType()->isPointerTy(),do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false) | ||||
| 2712 | "Indirectbr operand must have pointer type!", &BI)do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false); | ||||
| 2713 | for (unsigned i = 0, e = BI.getNumDestinations(); i != e; ++i) | ||||
| 2714 | Assert(BI.getDestination(i)->getType()->isLabelTy(),do { if (!(BI.getDestination(i)->getType()->isLabelTy() )) { CheckFailed("Indirectbr destinations must all have pointer type!" , &BI); return; } } while (false) | ||||
| 2715 | "Indirectbr destinations must all have pointer type!", &BI)do { if (!(BI.getDestination(i)->getType()->isLabelTy() )) { CheckFailed("Indirectbr destinations must all have pointer type!" , &BI); return; } } while (false); | ||||
| 2716 | |||||
| 2717 | visitTerminator(BI); | ||||
| 2718 | } | ||||
| 2719 | |||||
| 2720 | void Verifier::visitCallBrInst(CallBrInst &CBI) { | ||||
| 2721 | Assert(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!",do { if (!(CBI.isInlineAsm())) { CheckFailed("Callbr is currently only used for asm-goto!" , &CBI); return; } } while (false) | ||||
| 2722 | &CBI)do { if (!(CBI.isInlineAsm())) { CheckFailed("Callbr is currently only used for asm-goto!" , &CBI); return; } } while (false); | ||||
| 2723 | const InlineAsm *IA = cast<InlineAsm>(CBI.getCalledOperand()); | ||||
| 2724 | Assert(!IA->canThrow(), "Unwinding from Callbr is not allowed")do { if (!(!IA->canThrow())) { CheckFailed("Unwinding from Callbr is not allowed" ); return; } } while (false); | ||||
| 2725 | for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i) | ||||
| 2726 | Assert(CBI.getSuccessor(i)->getType()->isLabelTy(),do { if (!(CBI.getSuccessor(i)->getType()->isLabelTy()) ) { CheckFailed("Callbr successors must all have pointer type!" , &CBI); return; } } while (false) | ||||
| 2727 | "Callbr successors must all have pointer type!", &CBI)do { if (!(CBI.getSuccessor(i)->getType()->isLabelTy()) ) { CheckFailed("Callbr successors must all have pointer type!" , &CBI); return; } } while (false); | ||||
| 2728 | for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) { | ||||
| 2729 | Assert(i >= CBI.getNumArgOperands() || !isa<BasicBlock>(CBI.getOperand(i)),do { if (!(i >= CBI.getNumArgOperands() || !isa<BasicBlock >(CBI.getOperand(i)))) { CheckFailed("Using an unescaped label as a callbr argument!" , &CBI); return; } } while (false) | ||||
| 2730 | "Using an unescaped label as a callbr argument!", &CBI)do { if (!(i >= CBI.getNumArgOperands() || !isa<BasicBlock >(CBI.getOperand(i)))) { CheckFailed("Using an unescaped label as a callbr argument!" , &CBI); return; } } while (false); | ||||
| 2731 | if (isa<BasicBlock>(CBI.getOperand(i))) | ||||
| 2732 | for (unsigned j = i + 1; j != e; ++j) | ||||
| 2733 | Assert(CBI.getOperand(i) != CBI.getOperand(j),do { if (!(CBI.getOperand(i) != CBI.getOperand(j))) { CheckFailed ("Duplicate callbr destination!", &CBI); return; } } while (false) | ||||
| 2734 | "Duplicate callbr destination!", &CBI)do { if (!(CBI.getOperand(i) != CBI.getOperand(j))) { CheckFailed ("Duplicate callbr destination!", &CBI); return; } } while (false); | ||||
| 2735 | } | ||||
| 2736 | { | ||||
| 2737 | SmallPtrSet<BasicBlock *, 4> ArgBBs; | ||||
| 2738 | for (Value *V : CBI.args()) | ||||
| 2739 | if (auto *BA = dyn_cast<BlockAddress>(V)) | ||||
| 2740 | ArgBBs.insert(BA->getBasicBlock()); | ||||
| 2741 | for (BasicBlock *BB : CBI.getIndirectDests()) | ||||
| 2742 | Assert(ArgBBs.count(BB), "Indirect label missing from arglist.", &CBI)do { if (!(ArgBBs.count(BB))) { CheckFailed("Indirect label missing from arglist." , &CBI); return; } } while (false); | ||||
| 2743 | } | ||||
| 2744 | |||||
| 2745 | visitTerminator(CBI); | ||||
| 2746 | } | ||||
| 2747 | |||||
| 2748 | void Verifier::visitSelectInst(SelectInst &SI) { | ||||
| 2749 | Assert(!SelectInst::areInvalidOperands(SI.getOperand(0), SI.getOperand(1),do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false) | ||||
| 2750 | SI.getOperand(2)),do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false) | ||||
| 2751 | "Invalid operands for select instruction!", &SI)do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false); | ||||
| 2752 | |||||
| 2753 | Assert(SI.getTrueValue()->getType() == SI.getType(),do { if (!(SI.getTrueValue()->getType() == SI.getType())) { CheckFailed("Select values must have same type as select instruction!" , &SI); return; } } while (false) | ||||
| 2754 | "Select values must have same type as select instruction!", &SI)do { if (!(SI.getTrueValue()->getType() == SI.getType())) { CheckFailed("Select values must have same type as select instruction!" , &SI); return; } } while (false); | ||||
| 2755 | visitInstruction(SI); | ||||
| 2756 | } | ||||
| 2757 | |||||
| 2758 | /// visitUserOp1 - User defined operators shouldn't live beyond the lifetime of | ||||
| 2759 | /// a pass, if any exist, it's an error. | ||||
| 2760 | /// | ||||
| 2761 | void Verifier::visitUserOp1(Instruction &I) { | ||||
| 2762 | Assert(false, "User-defined operators should not live outside of a pass!", &I)do { if (!(false)) { CheckFailed("User-defined operators should not live outside of a pass!" , &I); return; } } while (false); | ||||
| 2763 | } | ||||
| 2764 | |||||
| 2765 | void Verifier::visitTruncInst(TruncInst &I) { | ||||
| 2766 | // Get the source and destination types | ||||
| 2767 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2768 | Type *DestTy = I.getType(); | ||||
| 2769 | |||||
| 2770 | // Get the size of the types in bits, we'll need this later | ||||
| 2771 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 2772 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 2773 | |||||
| 2774 | Assert(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only operates on integer" , &I); return; } } while (false); | ||||
| 2775 | Assert(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only produces integer" , &I); return; } } while (false); | ||||
| 2776 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("trunc source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 2777 | "trunc source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("trunc source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 2778 | Assert(SrcBitSize > DestBitSize, "DestTy too big for Trunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for Trunc" , &I); return; } } while (false); | ||||
| 2779 | |||||
| 2780 | visitInstruction(I); | ||||
| 2781 | } | ||||
| 2782 | |||||
| 2783 | void Verifier::visitZExtInst(ZExtInst &I) { | ||||
| 2784 | // Get the source and destination types | ||||
| 2785 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2786 | Type *DestTy = I.getType(); | ||||
| 2787 | |||||
| 2788 | // Get the size of the types in bits, we'll need this later | ||||
| 2789 | Assert(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only operates on integer" , &I); return; } } while (false); | ||||
| 2790 | Assert(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only produces an integer" , &I); return; } } while (false); | ||||
| 2791 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("zext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 2792 | "zext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("zext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 2793 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 2794 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 2795 | |||||
| 2796 | Assert(SrcBitSize < DestBitSize, "Type too small for ZExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for ZExt" , &I); return; } } while (false); | ||||
| 2797 | |||||
| 2798 | visitInstruction(I); | ||||
| 2799 | } | ||||
| 2800 | |||||
| 2801 | void Verifier::visitSExtInst(SExtInst &I) { | ||||
| 2802 | // Get the source and destination types | ||||
| 2803 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2804 | Type *DestTy = I.getType(); | ||||
| 2805 | |||||
| 2806 | // Get the size of the types in bits, we'll need this later | ||||
| 2807 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 2808 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 2809 | |||||
| 2810 | Assert(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SExt only operates on integer" , &I); return; } } while (false); | ||||
| 2811 | Assert(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("SExt only produces an integer" , &I); return; } } while (false); | ||||
| 2812 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("sext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 2813 | "sext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("sext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 2814 | Assert(SrcBitSize < DestBitSize, "Type too small for SExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for SExt" , &I); return; } } while (false); | ||||
| 2815 | |||||
| 2816 | visitInstruction(I); | ||||
| 2817 | } | ||||
| 2818 | |||||
| 2819 | void Verifier::visitFPTruncInst(FPTruncInst &I) { | ||||
| 2820 | // Get the source and destination types | ||||
| 2821 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2822 | Type *DestTy = I.getType(); | ||||
| 2823 | // Get the size of the types in bits, we'll need this later | ||||
| 2824 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 2825 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 2826 | |||||
| 2827 | Assert(SrcTy->isFPOrFPVectorTy(), "FPTrunc only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only operates on FP" , &I); return; } } while (false); | ||||
| 2828 | Assert(DestTy->isFPOrFPVectorTy(), "FPTrunc only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only produces an FP" , &I); return; } } while (false); | ||||
| 2829 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fptrunc source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 2830 | "fptrunc source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fptrunc source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 2831 | Assert(SrcBitSize > DestBitSize, "DestTy too big for FPTrunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for FPTrunc" , &I); return; } } while (false); | ||||
| 2832 | |||||
| 2833 | visitInstruction(I); | ||||
| 2834 | } | ||||
| 2835 | |||||
| 2836 | void Verifier::visitFPExtInst(FPExtInst &I) { | ||||
| 2837 | // Get the source and destination types | ||||
| 2838 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2839 | Type *DestTy = I.getType(); | ||||
| 2840 | |||||
| 2841 | // Get the size of the types in bits, we'll need this later | ||||
| 2842 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 2843 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 2844 | |||||
| 2845 | Assert(SrcTy->isFPOrFPVectorTy(), "FPExt only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only operates on FP" , &I); return; } } while (false); | ||||
| 2846 | Assert(DestTy->isFPOrFPVectorTy(), "FPExt only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only produces an FP" , &I); return; } } while (false); | ||||
| 2847 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fpext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 2848 | "fpext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fpext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 2849 | Assert(SrcBitSize < DestBitSize, "DestTy too small for FPExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("DestTy too small for FPExt" , &I); return; } } while (false); | ||||
| 2850 | |||||
| 2851 | visitInstruction(I); | ||||
| 2852 | } | ||||
| 2853 | |||||
| 2854 | void Verifier::visitUIToFPInst(UIToFPInst &I) { | ||||
| 2855 | // Get the source and destination types | ||||
| 2856 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2857 | Type *DestTy = I.getType(); | ||||
| 2858 | |||||
| 2859 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 2860 | bool DstVec = DestTy->isVectorTy(); | ||||
| 2861 | |||||
| 2862 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 2863 | "UIToFP source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 2864 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
| 2865 | "UIToFP source must be integer or integer vector", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false); | ||||
| 2866 | Assert(DestTy->isFPOrFPVectorTy(), "UIToFP result must be FP or FP vector",do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false) | ||||
| 2867 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
| 2868 | |||||
| 2869 | if (SrcVec && DstVec) | ||||
| 2870 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2871 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2872 | "UIToFP source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 2873 | |||||
| 2874 | visitInstruction(I); | ||||
| 2875 | } | ||||
| 2876 | |||||
| 2877 | void Verifier::visitSIToFPInst(SIToFPInst &I) { | ||||
| 2878 | // Get the source and destination types | ||||
| 2879 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2880 | Type *DestTy = I.getType(); | ||||
| 2881 | |||||
| 2882 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 2883 | bool DstVec = DestTy->isVectorTy(); | ||||
| 2884 | |||||
| 2885 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 2886 | "SIToFP source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 2887 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
| 2888 | "SIToFP source must be integer or integer vector", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false); | ||||
| 2889 | Assert(DestTy->isFPOrFPVectorTy(), "SIToFP result must be FP or FP vector",do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false) | ||||
| 2890 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
| 2891 | |||||
| 2892 | if (SrcVec && DstVec) | ||||
| 2893 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2894 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2895 | "SIToFP source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 2896 | |||||
| 2897 | visitInstruction(I); | ||||
| 2898 | } | ||||
| 2899 | |||||
| 2900 | void Verifier::visitFPToUIInst(FPToUIInst &I) { | ||||
| 2901 | // Get the source and destination types | ||||
| 2902 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2903 | Type *DestTy = I.getType(); | ||||
| 2904 | |||||
| 2905 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 2906 | bool DstVec = DestTy->isVectorTy(); | ||||
| 2907 | |||||
| 2908 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 2909 | "FPToUI source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 2910 | Assert(SrcTy->isFPOrFPVectorTy(), "FPToUI source must be FP or FP vector",do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToUI source must be FP or FP vector" , &I); return; } } while (false) | ||||
| 2911 | &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToUI source must be FP or FP vector" , &I); return; } } while (false); | ||||
| 2912 | Assert(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false) | ||||
| 2913 | "FPToUI result must be integer or integer vector", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false); | ||||
| 2914 | |||||
| 2915 | if (SrcVec && DstVec) | ||||
| 2916 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2917 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2918 | "FPToUI source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 2919 | |||||
| 2920 | visitInstruction(I); | ||||
| 2921 | } | ||||
| 2922 | |||||
| 2923 | void Verifier::visitFPToSIInst(FPToSIInst &I) { | ||||
| 2924 | // Get the source and destination types | ||||
| 2925 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2926 | Type *DestTy = I.getType(); | ||||
| 2927 | |||||
| 2928 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 2929 | bool DstVec = DestTy->isVectorTy(); | ||||
| 2930 | |||||
| 2931 | Assert(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 2932 | "FPToSI source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 2933 | Assert(SrcTy->isFPOrFPVectorTy(), "FPToSI source must be FP or FP vector",do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToSI source must be FP or FP vector" , &I); return; } } while (false) | ||||
| 2934 | &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToSI source must be FP or FP vector" , &I); return; } } while (false); | ||||
| 2935 | Assert(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false) | ||||
| 2936 | "FPToSI result must be integer or integer vector", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false); | ||||
| 2937 | |||||
| 2938 | if (SrcVec && DstVec) | ||||
| 2939 | Assert(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2940 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 2941 | "FPToSI source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 2942 | |||||
| 2943 | visitInstruction(I); | ||||
| 2944 | } | ||||
| 2945 | |||||
| 2946 | void Verifier::visitPtrToIntInst(PtrToIntInst &I) { | ||||
| 2947 | // Get the source and destination types | ||||
| 2948 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2949 | Type *DestTy = I.getType(); | ||||
| 2950 | |||||
| 2951 | Assert(SrcTy->isPtrOrPtrVectorTy(), "PtrToInt source must be pointer", &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("PtrToInt source must be pointer" , &I); return; } } while (false); | ||||
| 2952 | |||||
| 2953 | Assert(DestTy->isIntOrIntVectorTy(), "PtrToInt result must be integral", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("PtrToInt result must be integral" , &I); return; } } while (false); | ||||
| 2954 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false) | ||||
| 2955 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false); | ||||
| 2956 | |||||
| 2957 | if (SrcTy->isVectorTy()) { | ||||
| 2958 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
| 2959 | auto *VDest = cast<VectorType>(DestTy); | ||||
| 2960 | Assert(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false) | ||||
| 2961 | "PtrToInt Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false); | ||||
| 2962 | } | ||||
| 2963 | |||||
| 2964 | visitInstruction(I); | ||||
| 2965 | } | ||||
| 2966 | |||||
| 2967 | void Verifier::visitIntToPtrInst(IntToPtrInst &I) { | ||||
| 2968 | // Get the source and destination types | ||||
| 2969 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2970 | Type *DestTy = I.getType(); | ||||
| 2971 | |||||
| 2972 | Assert(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false) | ||||
| 2973 | "IntToPtr source must be an integral", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false); | ||||
| 2974 | Assert(DestTy->isPtrOrPtrVectorTy(), "IntToPtr result must be a pointer", &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("IntToPtr result must be a pointer" , &I); return; } } while (false); | ||||
| 2975 | |||||
| 2976 | Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false) | ||||
| 2977 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false); | ||||
| 2978 | if (SrcTy->isVectorTy()) { | ||||
| 2979 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
| 2980 | auto *VDest = cast<VectorType>(DestTy); | ||||
| 2981 | Assert(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false) | ||||
| 2982 | "IntToPtr Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false); | ||||
| 2983 | } | ||||
| 2984 | visitInstruction(I); | ||||
| 2985 | } | ||||
| 2986 | |||||
| 2987 | void Verifier::visitBitCastInst(BitCastInst &I) { | ||||
| 2988 | Assert(do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
| 2989 | CastInst::castIsValid(Instruction::BitCast, I.getOperand(0), I.getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
| 2990 | "Invalid bitcast", &I)do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false); | ||||
| 2991 | visitInstruction(I); | ||||
| 2992 | } | ||||
| 2993 | |||||
| 2994 | void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { | ||||
| 2995 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2996 | Type *DestTy = I.getType(); | ||||
| 2997 | |||||
| 2998 | Assert(SrcTy->isPtrOrPtrVectorTy(), "AddrSpaceCast source must be a pointer",do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false) | ||||
| 2999 | &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false); | ||||
| 3000 | Assert(DestTy->isPtrOrPtrVectorTy(), "AddrSpaceCast result must be a pointer",do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false) | ||||
| 3001 | &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false); | ||||
| 3002 | Assert(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(),do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false) | ||||
| 3003 | "AddrSpaceCast must be between different address spaces", &I)do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false); | ||||
| 3004 | if (auto *SrcVTy = dyn_cast<VectorType>(SrcTy)) | ||||
| 3005 | Assert(SrcVTy->getElementCount() ==do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
| 3006 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
| 3007 | "AddrSpaceCast vector pointer number of elements mismatch", &I)do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false); | ||||
| 3008 | visitInstruction(I); | ||||
| 3009 | } | ||||
| 3010 | |||||
| 3011 | /// visitPHINode - Ensure that a PHI node is well formed. | ||||
| 3012 | /// | ||||
| 3013 | void Verifier::visitPHINode(PHINode &PN) { | ||||
| 3014 | // Ensure that the PHI nodes are all grouped together at the top of the block. | ||||
| 3015 | // This can be tested by checking whether the instruction before this is | ||||
| 3016 | // either nonexistent (because this is begin()) or is a PHI node. If not, | ||||
| 3017 | // then there is some other instruction before a PHI. | ||||
| 3018 | Assert(&PN == &PN.getParent()->front() ||do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false) | ||||
| 3019 | isa<PHINode>(--BasicBlock::iterator(&PN)),do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false) | ||||
| 3020 | "PHI nodes not grouped at top of basic block!", &PN, PN.getParent())do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false); | ||||
| 3021 | |||||
| 3022 | // Check that a PHI doesn't yield a Token. | ||||
| 3023 | Assert(!PN.getType()->isTokenTy(), "PHI nodes cannot have token type!")do { if (!(!PN.getType()->isTokenTy())) { CheckFailed("PHI nodes cannot have token type!" ); return; } } while (false); | ||||
| 3024 | |||||
| 3025 | // Check that all of the values of the PHI node have the same type as the | ||||
| 3026 | // result, and that the incoming blocks are really basic blocks. | ||||
| 3027 | for (Value *IncValue : PN.incoming_values()) { | ||||
| 3028 | Assert(PN.getType() == IncValue->getType(),do { if (!(PN.getType() == IncValue->getType())) { CheckFailed ("PHI node operands are not the same type as the result!", & PN); return; } } while (false) | ||||
| 3029 | "PHI node operands are not the same type as the result!", &PN)do { if (!(PN.getType() == IncValue->getType())) { CheckFailed ("PHI node operands are not the same type as the result!", & PN); return; } } while (false); | ||||
| 3030 | } | ||||
| 3031 | |||||
| 3032 | // All other PHI node constraints are checked in the visitBasicBlock method. | ||||
| 3033 | |||||
| 3034 | visitInstruction(PN); | ||||
| 3035 | } | ||||
| 3036 | |||||
| 3037 | void Verifier::visitCallBase(CallBase &Call) { | ||||
| 3038 | Assert(Call.getCalledOperand()->getType()->isPointerTy(),do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false) | ||||
| 3039 | "Called function must be a pointer!", Call)do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false); | ||||
| 3040 | PointerType *FPTy = cast<PointerType>(Call.getCalledOperand()->getType()); | ||||
| 3041 | |||||
| 3042 | Assert(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType()),do { if (!(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType ()))) { CheckFailed("Called function is not the same type as the call!" , Call); return; } } while (false) | ||||
| 3043 | "Called function is not the same type as the call!", Call)do { if (!(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType ()))) { CheckFailed("Called function is not the same type as the call!" , Call); return; } } while (false); | ||||
| 3044 | |||||
| 3045 | FunctionType *FTy = Call.getFunctionType(); | ||||
| 3046 | |||||
| 3047 | // Verify that the correct number of arguments are being passed | ||||
| 3048 | if (FTy->isVarArg()) | ||||
| 3049 | Assert(Call.arg_size() >= FTy->getNumParams(),do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false) | ||||
| 3050 | "Called function requires more parameters than were provided!",do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false) | ||||
| 3051 | Call)do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false); | ||||
| 3052 | else | ||||
| 3053 | Assert(Call.arg_size() == FTy->getNumParams(),do { if (!(Call.arg_size() == FTy->getNumParams())) { CheckFailed ("Incorrect number of arguments passed to called function!", Call ); return; } } while (false) | ||||
| 3054 | "Incorrect number of arguments passed to called function!", Call)do { if (!(Call.arg_size() == FTy->getNumParams())) { CheckFailed ("Incorrect number of arguments passed to called function!", Call ); return; } } while (false); | ||||
| 3055 | |||||
| 3056 | // Verify that all arguments to the call match the function type. | ||||
| 3057 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) | ||||
| 3058 | Assert(Call.getArgOperand(i)->getType() == FTy->getParamType(i),do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false) | ||||
| 3059 | "Call parameter type does not match function signature!",do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false) | ||||
| 3060 | Call.getArgOperand(i), FTy->getParamType(i), Call)do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false); | ||||
| 3061 | |||||
| 3062 | AttributeList Attrs = Call.getAttributes(); | ||||
| 3063 | |||||
| 3064 | Assert(verifyAttributeCount(Attrs, Call.arg_size()),do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false) | ||||
| 3065 | "Attribute after last parameter!", Call)do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false); | ||||
| 3066 | |||||
| 3067 | Function *Callee = | ||||
| 3068 | dyn_cast<Function>(Call.getCalledOperand()->stripPointerCasts()); | ||||
| 3069 | bool IsIntrinsic = Callee && Callee->isIntrinsic(); | ||||
| 3070 | if (IsIntrinsic) | ||||
| 3071 | Assert(Callee->getValueType() == FTy,do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false) | ||||
| 3072 | "Intrinsic called with incompatible signature", Call)do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false); | ||||
| 3073 | |||||
| 3074 | if (Attrs.hasFnAttribute(Attribute::Speculatable)) { | ||||
| 3075 | // Don't allow speculatable on call sites, unless the underlying function | ||||
| 3076 | // declaration is also speculatable. | ||||
| 3077 | Assert(Callee && Callee->isSpeculatable(),do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false) | ||||
| 3078 | "speculatable attribute may not apply to call sites", Call)do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false); | ||||
| 3079 | } | ||||
| 3080 | |||||
| 3081 | if (Attrs.hasFnAttribute(Attribute::Preallocated)) { | ||||
| 3082 | Assert(Call.getCalledFunction()->getIntrinsicID() ==do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
| 3083 | Intrinsic::call_preallocated_arg,do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
| 3084 | "preallocated as a call site attribute can only be on "do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
| 3085 | "llvm.call.preallocated.arg")do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false); | ||||
| 3086 | } | ||||
| 3087 | |||||
| 3088 | // Verify call attributes. | ||||
| 3089 | verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic); | ||||
| 3090 | |||||
| 3091 | // Conservatively check the inalloca argument. | ||||
| 3092 | // We have a bug if we can find that there is an underlying alloca without | ||||
| 3093 | // inalloca. | ||||
| 3094 | if (Call.hasInAllocaArgument()) { | ||||
| 3095 | Value *InAllocaArg = Call.getArgOperand(FTy->getNumParams() - 1); | ||||
| 3096 | if (auto AI = dyn_cast<AllocaInst>(InAllocaArg->stripInBoundsOffsets())) | ||||
| 3097 | Assert(AI->isUsedWithInAlloca(),do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
| 3098 | "inalloca argument for call has mismatched alloca", AI, Call)do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false); | ||||
| 3099 | } | ||||
| 3100 | |||||
| 3101 | // For each argument of the callsite, if it has the swifterror argument, | ||||
| 3102 | // make sure the underlying alloca/parameter it comes from has a swifterror as | ||||
| 3103 | // well. | ||||
| 3104 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { | ||||
| 3105 | if (Call.paramHasAttr(i, Attribute::SwiftError)) { | ||||
| 3106 | Value *SwiftErrorArg = Call.getArgOperand(i); | ||||
| 3107 | if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) { | ||||
| 3108 | Assert(AI->isSwiftError(),do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
| 3109 | "swifterror argument for call has mismatched alloca", AI, Call)do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false); | ||||
| 3110 | continue; | ||||
| 3111 | } | ||||
| 3112 | auto ArgI = dyn_cast<Argument>(SwiftErrorArg); | ||||
| 3113 | Assert(ArgI,do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false) | ||||
| 3114 | "swifterror argument should come from an alloca or parameter",do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false) | ||||
| 3115 | SwiftErrorArg, Call)do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false); | ||||
| 3116 | Assert(ArgI->hasSwiftErrorAttr(),do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
| 3117 | "swifterror argument for call has mismatched parameter", ArgI,do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
| 3118 | Call)do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false); | ||||
| 3119 | } | ||||
| 3120 | |||||
| 3121 | if (Attrs.hasParamAttribute(i, Attribute::ImmArg)) { | ||||
| 3122 | // Don't allow immarg on call sites, unless the underlying declaration | ||||
| 3123 | // also has the matching immarg. | ||||
| 3124 | Assert(Callee && Callee->hasParamAttribute(i, Attribute::ImmArg),do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false) | ||||
| 3125 | "immarg may not apply only to call sites",do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false) | ||||
| 3126 | Call.getArgOperand(i), Call)do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false); | ||||
| 3127 | } | ||||
| 3128 | |||||
| 3129 | if (Call.paramHasAttr(i, Attribute::ImmArg)) { | ||||
| 3130 | Value *ArgVal = Call.getArgOperand(i); | ||||
| 3131 | Assert(isa<ConstantInt>(ArgVal) || isa<ConstantFP>(ArgVal),do { if (!(isa<ConstantInt>(ArgVal) || isa<ConstantFP >(ArgVal))) { CheckFailed("immarg operand has non-immediate parameter" , ArgVal, Call); return; } } while (false) | ||||
| 3132 | "immarg operand has non-immediate parameter", ArgVal, Call)do { if (!(isa<ConstantInt>(ArgVal) || isa<ConstantFP >(ArgVal))) { CheckFailed("immarg operand has non-immediate parameter" , ArgVal, Call); return; } } while (false); | ||||
| 3133 | } | ||||
| 3134 | |||||
| 3135 | if (Call.paramHasAttr(i, Attribute::Preallocated)) { | ||||
| 3136 | Value *ArgVal = Call.getArgOperand(i); | ||||
| 3137 | bool hasOB = | ||||
| 3138 | Call.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0; | ||||
| 3139 | bool isMustTail = Call.isMustTailCall(); | ||||
| 3140 | Assert(hasOB != isMustTail,do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
| 3141 | "preallocated operand either requires a preallocated bundle or "do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
| 3142 | "the call to be musttail (but not both)",do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
| 3143 | ArgVal, Call)do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false); | ||||
| 3144 | } | ||||
| 3145 | } | ||||
| 3146 | |||||
| 3147 | if (FTy->isVarArg()) { | ||||
| 3148 | // FIXME? is 'nest' even legal here? | ||||
| 3149 | bool SawNest = false; | ||||
| 3150 | bool SawReturned = false; | ||||
| 3151 | |||||
| 3152 | for (unsigned Idx = 0; Idx < FTy->getNumParams(); ++Idx) { | ||||
| 3153 | if (Attrs.hasParamAttribute(Idx, Attribute::Nest)) | ||||
| 3154 | SawNest = true; | ||||
| 3155 | if (Attrs.hasParamAttribute(Idx, Attribute::Returned)) | ||||
| 3156 | SawReturned = true; | ||||
| 3157 | } | ||||
| 3158 | |||||
| 3159 | // Check attributes on the varargs part. | ||||
| 3160 | for (unsigned Idx = FTy->getNumParams(); Idx < Call.arg_size(); ++Idx) { | ||||
| 3161 | Type *Ty = Call.getArgOperand(Idx)->getType(); | ||||
| 3162 | AttributeSet ArgAttrs = Attrs.getParamAttributes(Idx); | ||||
| 3163 | verifyParameterAttrs(ArgAttrs, Ty, &Call); | ||||
| 3164 | |||||
| 3165 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
| 3166 | Assert(!SawNest, "More than one parameter has attribute nest!", Call)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , Call); return; } } while (false); | ||||
| 3167 | SawNest = true; | ||||
| 3168 | } | ||||
| 3169 | |||||
| 3170 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
| 3171 | Assert(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false) | ||||
| 3172 | Call)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false); | ||||
| 3173 | Assert(Ty->canLosslesslyBitCastTo(FTy->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
| 3174 | "Incompatible argument and return types for 'returned' "do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
| 3175 | "attribute",do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
| 3176 | Call)do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false); | ||||
| 3177 | SawReturned = true; | ||||
| 3178 | } | ||||
| 3179 | |||||
| 3180 | // Statepoint intrinsic is vararg but the wrapped function may be not. | ||||
| 3181 | // Allow sret here and check the wrapped function in verifyStatepoint. | ||||
| 3182 | if (!Call.getCalledFunction() || | ||||
| 3183 | Call.getCalledFunction()->getIntrinsicID() != | ||||
| 3184 | Intrinsic::experimental_gc_statepoint) | ||||
| 3185 | Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
| 3186 | "Attribute 'sret' cannot be used for vararg call arguments!",do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
| 3187 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
| 3188 | |||||
| 3189 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) | ||||
| 3190 | Assert(Idx == Call.arg_size() - 1,do { if (!(Idx == Call.arg_size() - 1)) { CheckFailed("inalloca isn't on the last argument!" , Call); return; } } while (false) | ||||
| 3191 | "inalloca isn't on the last argument!", Call)do { if (!(Idx == Call.arg_size() - 1)) { CheckFailed("inalloca isn't on the last argument!" , Call); return; } } while (false); | ||||
| 3192 | } | ||||
| 3193 | } | ||||
| 3194 | |||||
| 3195 | // Verify that there's no metadata unless it's a direct call to an intrinsic. | ||||
| 3196 | if (!IsIntrinsic) { | ||||
| 3197 | for (Type *ParamTy : FTy->params()) { | ||||
| 3198 | Assert(!ParamTy->isMetadataTy(),do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
| 3199 | "Function has metadata parameter but isn't an intrinsic", Call)do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false); | ||||
| 3200 | Assert(!ParamTy->isTokenTy(),do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
| 3201 | "Function has token parameter but isn't an intrinsic", Call)do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false); | ||||
| 3202 | } | ||||
| 3203 | } | ||||
| 3204 | |||||
| 3205 | // Verify that indirect calls don't return tokens. | ||||
| 3206 | if (!Call.getCalledFunction()) { | ||||
| 3207 | Assert(!FTy->getReturnType()->isTokenTy(),do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false) | ||||
| 3208 | "Return type cannot be token for indirect call!")do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false); | ||||
| 3209 | Assert(!FTy->getReturnType()->isX86_AMXTy(),do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false) | ||||
| 3210 | "Return type cannot be x86_amx for indirect call!")do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false); | ||||
| 3211 | } | ||||
| 3212 | |||||
| 3213 | if (Function *F = Call.getCalledFunction()) | ||||
| 3214 | if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) | ||||
| 3215 | visitIntrinsicCall(ID, Call); | ||||
| 3216 | |||||
| 3217 | // Verify that a callsite has at most one "deopt", at most one "funclet", at | ||||
| 3218 | // most one "gc-transition", at most one "cfguardtarget", | ||||
| 3219 | // and at most one "preallocated" operand bundle. | ||||
| 3220 | bool FoundDeoptBundle = false, FoundFuncletBundle = false, | ||||
| 3221 | FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false, | ||||
| 3222 | FoundPreallocatedBundle = false, FoundGCLiveBundle = false, | ||||
| 3223 | FoundAttachedCallBundle = false; | ||||
| 3224 | for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) { | ||||
| 3225 | OperandBundleUse BU = Call.getOperandBundleAt(i); | ||||
| 3226 | uint32_t Tag = BU.getTagID(); | ||||
| 3227 | if (Tag == LLVMContext::OB_deopt) { | ||||
| 3228 | Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", Call)do { if (!(!FoundDeoptBundle)) { CheckFailed("Multiple deopt operand bundles" , Call); return; } } while (false); | ||||
| 3229 | FoundDeoptBundle = true; | ||||
| 3230 | } else if (Tag == LLVMContext::OB_gc_transition) { | ||||
| 3231 | Assert(!FoundGCTransitionBundle, "Multiple gc-transition operand bundles",do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false) | ||||
| 3232 | Call)do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false); | ||||
| 3233 | FoundGCTransitionBundle = true; | ||||
| 3234 | } else if (Tag == LLVMContext::OB_funclet) { | ||||
| 3235 | Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", Call)do { if (!(!FoundFuncletBundle)) { CheckFailed("Multiple funclet operand bundles" , Call); return; } } while (false); | ||||
| 3236 | FoundFuncletBundle = true; | ||||
| 3237 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false) | ||||
| 3238 | "Expected exactly one funclet bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false); | ||||
| 3239 | Assert(isa<FuncletPadInst>(BU.Inputs.front()),do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false) | ||||
| 3240 | "Funclet bundle operands should correspond to a FuncletPadInst",do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false) | ||||
| 3241 | Call)do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false); | ||||
| 3242 | } else if (Tag == LLVMContext::OB_cfguardtarget) { | ||||
| 3243 | Assert(!FoundCFGuardTargetBundle,do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false) | ||||
| 3244 | "Multiple CFGuardTarget operand bundles", Call)do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false); | ||||
| 3245 | FoundCFGuardTargetBundle = true; | ||||
| 3246 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false) | ||||
| 3247 | "Expected exactly one cfguardtarget bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false); | ||||
| 3248 | } else if (Tag == LLVMContext::OB_preallocated) { | ||||
| 3249 | Assert(!FoundPreallocatedBundle, "Multiple preallocated operand bundles",do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false) | ||||
| 3250 | Call)do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false); | ||||
| 3251 | FoundPreallocatedBundle = true; | ||||
| 3252 | Assert(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false) | ||||
| 3253 | "Expected exactly one preallocated bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false); | ||||
| 3254 | auto Input = dyn_cast<IntrinsicInst>(BU.Inputs.front()); | ||||
| 3255 | Assert(Input &&do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3256 | Input->getIntrinsicID() == Intrinsic::call_preallocated_setup,do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3257 | "\"preallocated\" argument must be a token from "do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3258 | "llvm.call.preallocated.setup",do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3259 | Call)do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ); | ||||
| 3260 | } else if (Tag == LLVMContext::OB_gc_live) { | ||||
| 3261 | Assert(!FoundGCLiveBundle, "Multiple gc-live operand bundles",do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false) | ||||
| 3262 | Call)do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false); | ||||
| 3263 | FoundGCLiveBundle = true; | ||||
| 3264 | } else if (Tag == LLVMContext::OB_clang_arc_attachedcall) { | ||||
| 3265 | Assert(!FoundAttachedCallBundle,do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false) | ||||
| 3266 | "Multiple \"clang.arc.attachedcall\" operand bundles", Call)do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false); | ||||
| 3267 | FoundAttachedCallBundle = true; | ||||
| 3268 | } | ||||
| 3269 | } | ||||
| 3270 | |||||
| 3271 | if (FoundAttachedCallBundle) | ||||
| 3272 | Assert((FTy->getReturnType()->isPointerTy() ||do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
| 3273 | (Call.doesNotReturn() && FTy->getReturnType()->isVoidTy())),do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
| 3274 | "a call with operand bundle \"clang.arc.attachedcall\" must call a "do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
| 3275 | "function returning a pointer or a non-returning function that has "do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
| 3276 | "a void return type",do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false) | ||||
| 3277 | Call)do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has " "a void return type", Call); return; } } while (false); | ||||
| 3278 | |||||
| 3279 | // Verify that each inlinable callsite of a debug-info-bearing function in a | ||||
| 3280 | // debug-info-bearing function has a debug location attached to it. Failure to | ||||
| 3281 | // do so causes assertion failures when the inliner sets up inline scope info. | ||||
| 3282 | if (Call.getFunction()->getSubprogram() && Call.getCalledFunction() && | ||||
| 3283 | Call.getCalledFunction()->getSubprogram()) | ||||
| 3284 | AssertDI(Call.getDebugLoc(),do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
| 3285 | "inlinable function call in a function with "do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
| 3286 | "debug info must have a !dbg location",do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
| 3287 | Call)do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false); | ||||
| 3288 | |||||
| 3289 | visitInstruction(Call); | ||||
| 3290 | } | ||||
| 3291 | |||||
| 3292 | void Verifier::verifyTailCCMustTailAttrs(AttrBuilder Attrs, | ||||
| 3293 | StringRef Context) { | ||||
| 3294 | Assert(!Attrs.contains(Attribute::InAlloca),do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false) | ||||
| 3295 | Twine("inalloca attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false); | ||||
| 3296 | Assert(!Attrs.contains(Attribute::InReg),do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false) | ||||
| 3297 | Twine("inreg attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false); | ||||
| 3298 | Assert(!Attrs.contains(Attribute::SwiftError),do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false) | ||||
| 3299 | Twine("swifterror attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false); | ||||
| 3300 | Assert(!Attrs.contains(Attribute::Preallocated),do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false) | ||||
| 3301 | Twine("preallocated attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false); | ||||
| 3302 | Assert(!Attrs.contains(Attribute::ByRef),do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false) | ||||
| 3303 | Twine("byref attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false); | ||||
| 3304 | } | ||||
| 3305 | |||||
| 3306 | /// Two types are "congruent" if they are identical, or if they are both pointer | ||||
| 3307 | /// types with different pointee types and the same address space. | ||||
| 3308 | static bool isTypeCongruent(Type *L, Type *R) { | ||||
| 3309 | if (L == R) | ||||
| 3310 | return true; | ||||
| 3311 | PointerType *PL = dyn_cast<PointerType>(L); | ||||
| 3312 | PointerType *PR = dyn_cast<PointerType>(R); | ||||
| 3313 | if (!PL || !PR) | ||||
| 3314 | return false; | ||||
| 3315 | return PL->getAddressSpace() == PR->getAddressSpace(); | ||||
| 3316 | } | ||||
| 3317 | |||||
| 3318 | static AttrBuilder getParameterABIAttributes(int I, AttributeList Attrs) { | ||||
| 3319 | static const Attribute::AttrKind ABIAttrs[] = { | ||||
| 3320 | Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, | ||||
| 3321 | Attribute::InReg, Attribute::StackAlignment, Attribute::SwiftSelf, | ||||
| 3322 | Attribute::SwiftAsync, Attribute::SwiftError, Attribute::Preallocated, | ||||
| 3323 | Attribute::ByRef}; | ||||
| 3324 | AttrBuilder Copy; | ||||
| 3325 | for (auto AK : ABIAttrs) { | ||||
| 3326 | Attribute Attr = Attrs.getParamAttributes(I).getAttribute(AK); | ||||
| 3327 | if (Attr.isValid()) | ||||
| 3328 | Copy.addAttribute(Attr); | ||||
| 3329 | } | ||||
| 3330 | |||||
| 3331 | // `align` is ABI-affecting only in combination with `byval` or `byref`. | ||||
| 3332 | if (Attrs.hasParamAttribute(I, Attribute::Alignment) && | ||||
| 3333 | (Attrs.hasParamAttribute(I, Attribute::ByVal) || | ||||
| 3334 | Attrs.hasParamAttribute(I, Attribute::ByRef))) | ||||
| 3335 | Copy.addAlignmentAttr(Attrs.getParamAlignment(I)); | ||||
| 3336 | return Copy; | ||||
| 3337 | } | ||||
| 3338 | |||||
| 3339 | void Verifier::verifyMustTailCall(CallInst &CI) { | ||||
| 3340 | Assert(!CI.isInlineAsm(), "cannot use musttail call with inline asm", &CI)do { if (!(!CI.isInlineAsm())) { CheckFailed("cannot use musttail call with inline asm" , &CI); return; } } while (false); | ||||
| 3341 | |||||
| 3342 | Function *F = CI.getParent()->getParent(); | ||||
| 3343 | FunctionType *CallerTy = F->getFunctionType(); | ||||
| 3344 | FunctionType *CalleeTy = CI.getFunctionType(); | ||||
| 3345 | Assert(CallerTy->isVarArg() == CalleeTy->isVarArg(),do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false) | ||||
| 3346 | "cannot guarantee tail call due to mismatched varargs", &CI)do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false); | ||||
| 3347 | Assert(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()),do { if (!(isTypeCongruent(CallerTy->getReturnType(), CalleeTy ->getReturnType()))) { CheckFailed("cannot guarantee tail call due to mismatched return types" , &CI); return; } } while (false) | ||||
| 3348 | "cannot guarantee tail call due to mismatched return types", &CI)do { if (!(isTypeCongruent(CallerTy->getReturnType(), CalleeTy ->getReturnType()))) { CheckFailed("cannot guarantee tail call due to mismatched return types" , &CI); return; } } while (false); | ||||
| 3349 | |||||
| 3350 | // - The calling conventions of the caller and callee must match. | ||||
| 3351 | Assert(F->getCallingConv() == CI.getCallingConv(),do { if (!(F->getCallingConv() == CI.getCallingConv())) { CheckFailed ("cannot guarantee tail call due to mismatched calling conv", &CI); return; } } while (false) | ||||
| 3352 | "cannot guarantee tail call due to mismatched calling conv", &CI)do { if (!(F->getCallingConv() == CI.getCallingConv())) { CheckFailed ("cannot guarantee tail call due to mismatched calling conv", &CI); return; } } while (false); | ||||
| 3353 | |||||
| 3354 | // - The call must immediately precede a :ref:`ret <i_ret>` instruction, | ||||
| 3355 | // or a pointer bitcast followed by a ret instruction. | ||||
| 3356 | // - The ret instruction must return the (possibly bitcasted) value | ||||
| 3357 | // produced by the call or void. | ||||
| 3358 | Value *RetVal = &CI; | ||||
| 3359 | Instruction *Next = CI.getNextNode(); | ||||
| 3360 | |||||
| 3361 | // Handle the optional bitcast. | ||||
| 3362 | if (BitCastInst *BI = dyn_cast_or_null<BitCastInst>(Next)) { | ||||
| 3363 | Assert(BI->getOperand(0) == RetVal,do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false) | ||||
| 3364 | "bitcast following musttail call must use the call", BI)do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false); | ||||
| 3365 | RetVal = BI; | ||||
| 3366 | Next = BI->getNextNode(); | ||||
| 3367 | } | ||||
| 3368 | |||||
| 3369 | // Check the return. | ||||
| 3370 | ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next); | ||||
| 3371 | Assert(Ret, "musttail call must precede a ret with an optional bitcast",do { if (!(Ret)) { CheckFailed("musttail call must precede a ret with an optional bitcast" , &CI); return; } } while (false) | ||||
| 3372 | &CI)do { if (!(Ret)) { CheckFailed("musttail call must precede a ret with an optional bitcast" , &CI); return; } } while (false); | ||||
| 3373 | Assert(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal ||do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false) | ||||
| 3374 | isa<UndefValue>(Ret->getReturnValue()),do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false) | ||||
| 3375 | "musttail call result must be returned", Ret)do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false); | ||||
| 3376 | |||||
| 3377 | AttributeList CallerAttrs = F->getAttributes(); | ||||
| 3378 | AttributeList CalleeAttrs = CI.getAttributes(); | ||||
| 3379 | if (CI.getCallingConv() == CallingConv::SwiftTail || | ||||
| 3380 | CI.getCallingConv() == CallingConv::Tail) { | ||||
| 3381 | StringRef CCName = | ||||
| 3382 | CI.getCallingConv() == CallingConv::Tail ? "tailcc" : "swifttailcc"; | ||||
| 3383 | |||||
| 3384 | // - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes | ||||
| 3385 | // are allowed in swifttailcc call | ||||
| 3386 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
| 3387 | AttrBuilder ABIAttrs = getParameterABIAttributes(I, CallerAttrs); | ||||
| 3388 | SmallString<32> Context{CCName, StringRef(" musttail caller")}; | ||||
| 3389 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
| 3390 | } | ||||
| 3391 | for (int I = 0, E = CalleeTy->getNumParams(); I != E; ++I) { | ||||
| 3392 | AttrBuilder ABIAttrs = getParameterABIAttributes(I, CalleeAttrs); | ||||
| 3393 | SmallString<32> Context{CCName, StringRef(" musttail callee")}; | ||||
| 3394 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
| 3395 | } | ||||
| 3396 | // - Varargs functions are not allowed | ||||
| 3397 | Assert(!CallerTy->isVarArg(), Twine("cannot guarantee ") + CCName +do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false) | ||||
| 3398 | " tail call for varargs function")do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false); | ||||
| 3399 | return; | ||||
| 3400 | } | ||||
| 3401 | |||||
| 3402 | // - The caller and callee prototypes must match. Pointer types of | ||||
| 3403 | // parameters or return types may differ in pointee type, but not | ||||
| 3404 | // address space. | ||||
| 3405 | if (!CI.getCalledFunction() || !CI.getCalledFunction()->isIntrinsic()) { | ||||
| 3406 | Assert(CallerTy->getNumParams() == CalleeTy->getNumParams(),do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false) | ||||
| 3407 | "cannot guarantee tail call due to mismatched parameter counts",do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false) | ||||
| 3408 | &CI)do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false); | ||||
| 3409 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
| 3410 | Assert(do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
| 3411 | isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)),do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
| 3412 | "cannot guarantee tail call due to mismatched parameter types", &CI)do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false); | ||||
| 3413 | } | ||||
| 3414 | } | ||||
| 3415 | |||||
| 3416 | // - All ABI-impacting function attributes, such as sret, byval, inreg, | ||||
| 3417 | // returned, preallocated, and inalloca, must match. | ||||
| 3418 | for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
| 3419 | AttrBuilder CallerABIAttrs = getParameterABIAttributes(I, CallerAttrs); | ||||
| 3420 | AttrBuilder CalleeABIAttrs = getParameterABIAttributes(I, CalleeAttrs); | ||||
| 3421 | Assert(CallerABIAttrs == CalleeABIAttrs,do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
| 3422 | "cannot guarantee tail call due to mismatched ABI impacting "do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
| 3423 | "function attributes",do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
| 3424 | &CI, CI.getOperand(I))do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false); | ||||
| 3425 | } | ||||
| 3426 | } | ||||
| 3427 | |||||
| 3428 | void Verifier::visitCallInst(CallInst &CI) { | ||||
| 3429 | visitCallBase(CI); | ||||
| 3430 | |||||
| 3431 | if (CI.isMustTailCall()) | ||||
| 3432 | verifyMustTailCall(CI); | ||||
| 3433 | } | ||||
| 3434 | |||||
| 3435 | void Verifier::visitInvokeInst(InvokeInst &II) { | ||||
| 3436 | visitCallBase(II); | ||||
| 3437 | |||||
| 3438 | // Verify that the first non-PHI instruction of the unwind destination is an | ||||
| 3439 | // exception handling instruction. | ||||
| 3440 | Assert(do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
| 3441 | II.getUnwindDest()->isEHPad(),do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
| 3442 | "The unwind destination does not have an exception handling instruction!",do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
| 3443 | &II)do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false); | ||||
| 3444 | |||||
| 3445 | visitTerminator(II); | ||||
| 3446 | } | ||||
| 3447 | |||||
| 3448 | /// visitUnaryOperator - Check the argument to the unary operator. | ||||
| 3449 | /// | ||||
| 3450 | void Verifier::visitUnaryOperator(UnaryOperator &U) { | ||||
| 3451 | Assert(U.getType() == U.getOperand(0)->getType(),do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
| 3452 | "Unary operators must have same type for"do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
| 3453 | "operands and result!",do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
| 3454 | &U)do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false); | ||||
| 3455 | |||||
| 3456 | switch (U.getOpcode()) { | ||||
| 3457 | // Check that floating-point arithmetic operators are only used with | ||||
| 3458 | // floating-point operands. | ||||
| 3459 | case Instruction::FNeg: | ||||
| 3460 | Assert(U.getType()->isFPOrFPVectorTy(),do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false) | ||||
| 3461 | "FNeg operator only works with float types!", &U)do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false); | ||||
| 3462 | break; | ||||
| 3463 | default: | ||||
| 3464 | llvm_unreachable("Unknown UnaryOperator opcode!")__builtin_unreachable(); | ||||
| 3465 | } | ||||
| 3466 | |||||
| 3467 | visitInstruction(U); | ||||
| 3468 | } | ||||
| 3469 | |||||
| 3470 | /// visitBinaryOperator - Check that both arguments to the binary operator are | ||||
| 3471 | /// of the same type! | ||||
| 3472 | /// | ||||
| 3473 | void Verifier::visitBinaryOperator(BinaryOperator &B) { | ||||
| 3474 | Assert(B.getOperand(0)->getType() == B.getOperand(1)->getType(),do { if (!(B.getOperand(0)->getType() == B.getOperand(1)-> getType())) { CheckFailed("Both operands to a binary operator are not of the same type!" , &B); return; } } while (false) | ||||
| 3475 | "Both operands to a binary operator are not of the same type!", &B)do { if (!(B.getOperand(0)->getType() == B.getOperand(1)-> getType())) { CheckFailed("Both operands to a binary operator are not of the same type!" , &B); return; } } while (false); | ||||
| 3476 | |||||
| 3477 | switch (B.getOpcode()) { | ||||
| 3478 | // Check that integer arithmetic operators are only used with | ||||
| 3479 | // integral operands. | ||||
| 3480 | case Instruction::Add: | ||||
| 3481 | case Instruction::Sub: | ||||
| 3482 | case Instruction::Mul: | ||||
| 3483 | case Instruction::SDiv: | ||||
| 3484 | case Instruction::UDiv: | ||||
| 3485 | case Instruction::SRem: | ||||
| 3486 | case Instruction::URem: | ||||
| 3487 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false) | ||||
| 3488 | "Integer arithmetic operators only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false); | ||||
| 3489 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3490 | "Integer arithmetic operators must have same type "do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3491 | "for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3492 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false); | ||||
| 3493 | break; | ||||
| 3494 | // Check that floating-point arithmetic operators are only used with | ||||
| 3495 | // floating-point operands. | ||||
| 3496 | case Instruction::FAdd: | ||||
| 3497 | case Instruction::FSub: | ||||
| 3498 | case Instruction::FMul: | ||||
| 3499 | case Instruction::FDiv: | ||||
| 3500 | case Instruction::FRem: | ||||
| 3501 | Assert(B.getType()->isFPOrFPVectorTy(),do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
| 3502 | "Floating-point arithmetic operators only work with "do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
| 3503 | "floating-point types!",do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
| 3504 | &B)do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false); | ||||
| 3505 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3506 | "Floating-point arithmetic operators must have same type "do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3507 | "for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3508 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false); | ||||
| 3509 | break; | ||||
| 3510 | // Check that logical operators are only used with integral operands. | ||||
| 3511 | case Instruction::And: | ||||
| 3512 | case Instruction::Or: | ||||
| 3513 | case Instruction::Xor: | ||||
| 3514 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false) | ||||
| 3515 | "Logical operators only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false); | ||||
| 3516 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false) | ||||
| 3517 | "Logical operators must have same type for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false) | ||||
| 3518 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false); | ||||
| 3519 | break; | ||||
| 3520 | case Instruction::Shl: | ||||
| 3521 | case Instruction::LShr: | ||||
| 3522 | case Instruction::AShr: | ||||
| 3523 | Assert(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false) | ||||
| 3524 | "Shifts only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false); | ||||
| 3525 | Assert(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Shift return type must be same as operands!", &B); return ; } } while (false) | ||||
| 3526 | "Shift return type must be same as operands!", &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Shift return type must be same as operands!", &B); return ; } } while (false); | ||||
| 3527 | break; | ||||
| 3528 | default: | ||||
| 3529 | llvm_unreachable("Unknown BinaryOperator opcode!")__builtin_unreachable(); | ||||
| 3530 | } | ||||
| 3531 | |||||
| 3532 | visitInstruction(B); | ||||
| 3533 | } | ||||
| 3534 | |||||
| 3535 | void Verifier::visitICmpInst(ICmpInst &IC) { | ||||
| 3536 | // Check that the operands are the same type | ||||
| 3537 | Type *Op0Ty = IC.getOperand(0)->getType(); | ||||
| 3538 | Type *Op1Ty = IC.getOperand(1)->getType(); | ||||
| 3539 | Assert(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false) | ||||
| 3540 | "Both operands to ICmp instruction are not of the same type!", &IC)do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false); | ||||
| 3541 | // Check that the operands are the right type | ||||
| 3542 | Assert(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy(),do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false) | ||||
| 3543 | "Invalid operand types for ICmp instruction", &IC)do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false); | ||||
| 3544 | // Check that the predicate is valid. | ||||
| 3545 | Assert(IC.isIntPredicate(),do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false) | ||||
| 3546 | "Invalid predicate in ICmp instruction!", &IC)do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false); | ||||
| 3547 | |||||
| 3548 | visitInstruction(IC); | ||||
| 3549 | } | ||||
| 3550 | |||||
| 3551 | void Verifier::visitFCmpInst(FCmpInst &FC) { | ||||
| 3552 | // Check that the operands are the same type | ||||
| 3553 | Type *Op0Ty = FC.getOperand(0)->getType(); | ||||
| 3554 | Type *Op1Ty = FC.getOperand(1)->getType(); | ||||
| 3555 | Assert(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false) | ||||
| 3556 | "Both operands to FCmp instruction are not of the same type!", &FC)do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false); | ||||
| 3557 | // Check that the operands are the right type | ||||
| 3558 | Assert(Op0Ty->isFPOrFPVectorTy(),do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false) | ||||
| 3559 | "Invalid operand types for FCmp instruction", &FC)do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false); | ||||
| 3560 | // Check that the predicate is valid. | ||||
| 3561 | Assert(FC.isFPPredicate(),do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false) | ||||
| 3562 | "Invalid predicate in FCmp instruction!", &FC)do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false); | ||||
| 3563 | |||||
| 3564 | visitInstruction(FC); | ||||
| 3565 | } | ||||
| 3566 | |||||
| 3567 | void Verifier::visitExtractElementInst(ExtractElementInst &EI) { | ||||
| 3568 | Assert(do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false) | ||||
| 3569 | ExtractElementInst::isValidOperands(EI.getOperand(0), EI.getOperand(1)),do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false) | ||||
| 3570 | "Invalid extractelement operands!", &EI)do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false); | ||||
| 3571 | visitInstruction(EI); | ||||
| 3572 | } | ||||
| 3573 | |||||
| 3574 | void Verifier::visitInsertElementInst(InsertElementInst &IE) { | ||||
| 3575 | Assert(InsertElementInst::isValidOperands(IE.getOperand(0), IE.getOperand(1),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
| 3576 | IE.getOperand(2)),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
| 3577 | "Invalid insertelement operands!", &IE)do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false); | ||||
| 3578 | visitInstruction(IE); | ||||
| 3579 | } | ||||
| 3580 | |||||
| 3581 | void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) { | ||||
| 3582 | Assert(ShuffleVectorInst::isValidOperands(SV.getOperand(0), SV.getOperand(1),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
| 3583 | SV.getShuffleMask()),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
| 3584 | "Invalid shufflevector operands!", &SV)do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false); | ||||
| 3585 | visitInstruction(SV); | ||||
| 3586 | } | ||||
| 3587 | |||||
| 3588 | void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { | ||||
| 3589 | Type *TargetTy = GEP.getPointerOperandType()->getScalarType(); | ||||
| 3590 | |||||
| 3591 | Assert(isa<PointerType>(TargetTy),do { if (!(isa<PointerType>(TargetTy))) { CheckFailed("GEP base pointer is not a vector or a vector of pointers" , &GEP); return; } } while (false) | ||||
| 3592 | "GEP base pointer is not a vector or a vector of pointers", &GEP)do { if (!(isa<PointerType>(TargetTy))) { CheckFailed("GEP base pointer is not a vector or a vector of pointers" , &GEP); return; } } while (false); | ||||
| 3593 | Assert(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP)do { if (!(GEP.getSourceElementType()->isSized())) { CheckFailed ("GEP into unsized type!", &GEP); return; } } while (false ); | ||||
| 3594 | |||||
| 3595 | SmallVector<Value *, 16> Idxs(GEP.indices()); | ||||
| 3596 | Assert(all_of(do { if (!(all_of( Idxs, [](Value* V) { return V->getType( )->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
| 3597 | Idxs, [](Value* V) { return V->getType()->isIntOrIntVectorTy(); }),do { if (!(all_of( Idxs, [](Value* V) { return V->getType( )->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
| 3598 | "GEP indexes must be integers", &GEP)do { if (!(all_of( Idxs, [](Value* V) { return V->getType( )->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false); | ||||
| 3599 | Type *ElTy = | ||||
| 3600 | GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs); | ||||
| 3601 | Assert(ElTy, "Invalid indices for GEP pointer type!", &GEP)do { if (!(ElTy)) { CheckFailed("Invalid indices for GEP pointer type!" , &GEP); return; } } while (false); | ||||
| 3602 | |||||
| 3603 | Assert(GEP.getType()->isPtrOrPtrVectorTy() &&do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false) | ||||
| 3604 | GEP.getResultElementType() == ElTy,do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false) | ||||
| 3605 | "GEP is not of right type for indices!", &GEP, ElTy)do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false); | ||||
| 3606 | |||||
| 3607 | if (auto *GEPVTy = dyn_cast<VectorType>(GEP.getType())) { | ||||
| 3608 | // Additional checks for vector GEPs. | ||||
| 3609 | ElementCount GEPWidth = GEPVTy->getElementCount(); | ||||
| 3610 | if (GEP.getPointerOperandType()->isVectorTy()) | ||||
| 3611 | Assert(do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
| 3612 | GEPWidth ==do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
| 3613 | cast<VectorType>(GEP.getPointerOperandType())->getElementCount(),do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
| 3614 | "Vector GEP result width doesn't match operand's", &GEP)do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false); | ||||
| 3615 | for (Value *Idx : Idxs) { | ||||
| 3616 | Type *IndexTy = Idx->getType(); | ||||
| 3617 | if (auto *IndexVTy = dyn_cast<VectorType>(IndexTy)) { | ||||
| 3618 | ElementCount IndexWidth = IndexVTy->getElementCount(); | ||||
| 3619 | Assert(IndexWidth == GEPWidth, "Invalid GEP index vector width", &GEP)do { if (!(IndexWidth == GEPWidth)) { CheckFailed("Invalid GEP index vector width" , &GEP); return; } } while (false); | ||||
| 3620 | } | ||||
| 3621 | Assert(IndexTy->isIntOrIntVectorTy(),do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false) | ||||
| 3622 | "All GEP indices should be of integer type")do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false); | ||||
| 3623 | } | ||||
| 3624 | } | ||||
| 3625 | |||||
| 3626 | if (auto *PTy = dyn_cast<PointerType>(GEP.getType())) { | ||||
| 3627 | Assert(GEP.getAddressSpace() == PTy->getAddressSpace(),do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false) | ||||
| 3628 | "GEP address space doesn't match type", &GEP)do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false); | ||||
| 3629 | } | ||||
| 3630 | |||||
| 3631 | visitInstruction(GEP); | ||||
| 3632 | } | ||||
| 3633 | |||||
| 3634 | static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { | ||||
| 3635 | return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); | ||||
| 3636 | } | ||||
| 3637 | |||||
| 3638 | void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { | ||||
| 3639 | assert(Range && Range == I.getMetadata(LLVMContext::MD_range) &&((void)0) | ||||
| 3640 | "precondition violation")((void)0); | ||||
| 3641 | |||||
| 3642 | unsigned NumOperands = Range->getNumOperands(); | ||||
| 3643 | Assert(NumOperands % 2 == 0, "Unfinished range!", Range)do { if (!(NumOperands % 2 == 0)) { CheckFailed("Unfinished range!" , Range); return; } } while (false); | ||||
| 3644 | unsigned NumRanges = NumOperands / 2; | ||||
| 3645 | Assert(NumRanges >= 1, "It should have at least one range!", Range)do { if (!(NumRanges >= 1)) { CheckFailed("It should have at least one range!" , Range); return; } } while (false); | ||||
| 3646 | |||||
| 3647 | ConstantRange LastRange(1, true); // Dummy initial value | ||||
| 3648 | for (unsigned i = 0; i < NumRanges; ++i) { | ||||
| 3649 | ConstantInt *Low = | ||||
| 3650 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i)); | ||||
| 3651 | Assert(Low, "The lower limit must be an integer!", Low)do { if (!(Low)) { CheckFailed("The lower limit must be an integer!" , Low); return; } } while (false); | ||||
| 3652 | ConstantInt *High = | ||||
| 3653 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i + 1)); | ||||
| 3654 | Assert(High, "The upper limit must be an integer!", High)do { if (!(High)) { CheckFailed("The upper limit must be an integer!" , High); return; } } while (false); | ||||
| 3655 | Assert(High->getType() == Low->getType() && High->getType() == Ty,do { if (!(High->getType() == Low->getType() && High->getType() == Ty)) { CheckFailed("Range types must match instruction type!" , &I); return; } } while (false) | ||||
| 3656 | "Range types must match instruction type!", &I)do { if (!(High->getType() == Low->getType() && High->getType() == Ty)) { CheckFailed("Range types must match instruction type!" , &I); return; } } while (false); | ||||
| 3657 | |||||
| 3658 | APInt HighV = High->getValue(); | ||||
| 3659 | APInt LowV = Low->getValue(); | ||||
| 3660 | ConstantRange CurRange(LowV, HighV); | ||||
| 3661 | Assert(!CurRange.isEmptySet() && !CurRange.isFullSet(),do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false) | ||||
| 3662 | "Range must not be empty!", Range)do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false); | ||||
| 3663 | if (i != 0) { | ||||
| 3664 | Assert(CurRange.intersectWith(LastRange).isEmptySet(),do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
| 3665 | "Intervals are overlapping", Range)do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
| 3666 | Assert(LowV.sgt(LastRange.getLower()), "Intervals are not in order",do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false) | ||||
| 3667 | Range)do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false); | ||||
| 3668 | Assert(!isContiguous(CurRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
| 3669 | Range)do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
| 3670 | } | ||||
| 3671 | LastRange = ConstantRange(LowV, HighV); | ||||
| 3672 | } | ||||
| 3673 | if (NumRanges > 2) { | ||||
| 3674 | APInt FirstLow = | ||||
| 3675 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(0))->getValue(); | ||||
| 3676 | APInt FirstHigh = | ||||
| 3677 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(1))->getValue(); | ||||
| 3678 | ConstantRange FirstRange(FirstLow, FirstHigh); | ||||
| 3679 | Assert(FirstRange.intersectWith(LastRange).isEmptySet(),do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
| 3680 | "Intervals are overlapping", Range)do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
| 3681 | Assert(!isContiguous(FirstRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
| 3682 | Range)do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
| 3683 | } | ||||
| 3684 | } | ||||
| 3685 | |||||
| 3686 | void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) { | ||||
| 3687 | unsigned Size = DL.getTypeSizeInBits(Ty); | ||||
| 3688 | Assert(Size >= 8, "atomic memory access' size must be byte-sized", Ty, I)do { if (!(Size >= 8)) { CheckFailed("atomic memory access' size must be byte-sized" , Ty, I); return; } } while (false); | ||||
| 3689 | Assert(!(Size & (Size - 1)),do { if (!(!(Size & (Size - 1)))) { CheckFailed("atomic memory access' operand must have a power-of-two size" , Ty, I); return; } } while (false) | ||||
| 3690 | "atomic memory access' operand must have a power-of-two size", Ty, I)do { if (!(!(Size & (Size - 1)))) { CheckFailed("atomic memory access' operand must have a power-of-two size" , Ty, I); return; } } while (false); | ||||
| 3691 | } | ||||
| 3692 | |||||
| 3693 | void Verifier::visitLoadInst(LoadInst &LI) { | ||||
| 3694 | PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType()); | ||||
| 3695 | Assert(PTy, "Load operand must be a pointer.", &LI)do { if (!(PTy)) { CheckFailed("Load operand must be a pointer." , &LI); return; } } while (false); | ||||
| 3696 | Type *ElTy = LI.getType(); | ||||
| 3697 | Assert(LI.getAlignment() <= Value::MaximumAlignment,do { if (!(LI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &LI ); return; } } while (false) | ||||
| 3698 | "huge alignment values are unsupported", &LI)do { if (!(LI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &LI ); return; } } while (false); | ||||
| 3699 | Assert(ElTy->isSized(), "loading unsized types is not allowed", &LI)do { if (!(ElTy->isSized())) { CheckFailed("loading unsized types is not allowed" , &LI); return; } } while (false); | ||||
| 3700 | if (LI.isAtomic()) { | ||||
| 3701 | Assert(LI.getOrdering() != AtomicOrdering::Release &&do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
| 3702 | LI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
| 3703 | "Load cannot have Release ordering", &LI)do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false); | ||||
| 3704 | Assert(LI.getAlignment() != 0,do { if (!(LI.getAlignment() != 0)) { CheckFailed("Atomic load must specify explicit alignment" , &LI); return; } } while (false) | ||||
| 3705 | "Atomic load must specify explicit alignment", &LI)do { if (!(LI.getAlignment() != 0)) { CheckFailed("Atomic load must specify explicit alignment" , &LI); return; } } while (false); | ||||
| 3706 | Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
| 3707 | "atomic load operand must have integer, pointer, or floating point "do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
| 3708 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
| 3709 | ElTy, &LI)do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false); | ||||
| 3710 | checkAtomicMemAccessSize(ElTy, &LI); | ||||
| 3711 | } else { | ||||
| 3712 | Assert(LI.getSyncScopeID() == SyncScope::System,do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false) | ||||
| 3713 | "Non-atomic load cannot have SynchronizationScope specified", &LI)do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false); | ||||
| 3714 | } | ||||
| 3715 | |||||
| 3716 | visitInstruction(LI); | ||||
| 3717 | } | ||||
| 3718 | |||||
| 3719 | void Verifier::visitStoreInst(StoreInst &SI) { | ||||
| 3720 | PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType()); | ||||
| 3721 | Assert(PTy, "Store operand must be a pointer.", &SI)do { if (!(PTy)) { CheckFailed("Store operand must be a pointer." , &SI); return; } } while (false); | ||||
| 3722 | Type *ElTy = SI.getOperand(0)->getType(); | ||||
| 3723 | Assert(PTy->isOpaqueOrPointeeTypeMatches(ElTy),do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false) | ||||
| 3724 | "Stored value type does not match pointer operand type!", &SI, ElTy)do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false); | ||||
| 3725 | Assert(SI.getAlignment() <= Value::MaximumAlignment,do { if (!(SI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &SI ); return; } } while (false) | ||||
| 3726 | "huge alignment values are unsupported", &SI)do { if (!(SI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &SI ); return; } } while (false); | ||||
| 3727 | Assert(ElTy->isSized(), "storing unsized types is not allowed", &SI)do { if (!(ElTy->isSized())) { CheckFailed("storing unsized types is not allowed" , &SI); return; } } while (false); | ||||
| 3728 | if (SI.isAtomic()) { | ||||
| 3729 | Assert(SI.getOrdering() != AtomicOrdering::Acquire &&do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
| 3730 | SI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
| 3731 | "Store cannot have Acquire ordering", &SI)do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false); | ||||
| 3732 | Assert(SI.getAlignment() != 0,do { if (!(SI.getAlignment() != 0)) { CheckFailed("Atomic store must specify explicit alignment" , &SI); return; } } while (false) | ||||
| 3733 | "Atomic store must specify explicit alignment", &SI)do { if (!(SI.getAlignment() != 0)) { CheckFailed("Atomic store must specify explicit alignment" , &SI); return; } } while (false); | ||||
| 3734 | Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
| 3735 | "atomic store operand must have integer, pointer, or floating point "do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
| 3736 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
| 3737 | ElTy, &SI)do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false); | ||||
| 3738 | checkAtomicMemAccessSize(ElTy, &SI); | ||||
| 3739 | } else { | ||||
| 3740 | Assert(SI.getSyncScopeID() == SyncScope::System,do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false) | ||||
| 3741 | "Non-atomic store cannot have SynchronizationScope specified", &SI)do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false); | ||||
| 3742 | } | ||||
| 3743 | visitInstruction(SI); | ||||
| 3744 | } | ||||
| 3745 | |||||
| 3746 | /// Check that SwiftErrorVal is used as a swifterror argument in CS. | ||||
| 3747 | void Verifier::verifySwiftErrorCall(CallBase &Call, | ||||
| 3748 | const Value *SwiftErrorVal) { | ||||
| 3749 | for (const auto &I : llvm::enumerate(Call.args())) { | ||||
| 3750 | if (I.value() == SwiftErrorVal) { | ||||
| 3751 | Assert(Call.paramHasAttr(I.index(), Attribute::SwiftError),do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
| 3752 | "swifterror value when used in a callsite should be marked "do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
| 3753 | "with swifterror attribute",do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
| 3754 | SwiftErrorVal, Call)do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false); | ||||
| 3755 | } | ||||
| 3756 | } | ||||
| 3757 | } | ||||
| 3758 | |||||
| 3759 | void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) { | ||||
| 3760 | // Check that swifterror value is only used by loads, stores, or as | ||||
| 3761 | // a swifterror argument. | ||||
| 3762 | for (const User *U : SwiftErrorVal->users()) { | ||||
| 3763 | Assert(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) ||do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 3764 | isa<InvokeInst>(U),do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 3765 | "swifterror value can only be loaded and stored from, or "do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 3766 | "as a swifterror argument!",do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 3767 | SwiftErrorVal, U)do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false); | ||||
| 3768 | // If it is used by a store, check it is the second operand. | ||||
| 3769 | if (auto StoreI = dyn_cast<StoreInst>(U)) | ||||
| 3770 | Assert(StoreI->getOperand(1) == SwiftErrorVal,do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
| 3771 | "swifterror value should be the second operand when used "do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
| 3772 | "by stores", SwiftErrorVal, U)do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false); | ||||
| 3773 | if (auto *Call = dyn_cast<CallBase>(U)) | ||||
| 3774 | verifySwiftErrorCall(*const_cast<CallBase *>(Call), SwiftErrorVal); | ||||
| 3775 | } | ||||
| 3776 | } | ||||
| 3777 | |||||
| 3778 | void Verifier::visitAllocaInst(AllocaInst &AI) { | ||||
| 3779 | SmallPtrSet<Type*, 4> Visited; | ||||
| 3780 | Assert(AI.getAllocatedType()->isSized(&Visited),do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false) | ||||
| 3781 | "Cannot allocate unsized type", &AI)do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false); | ||||
| 3782 | Assert(AI.getArraySize()->getType()->isIntegerTy(),do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false) | ||||
| 3783 | "Alloca array size must have integer type", &AI)do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false); | ||||
| 3784 | Assert(AI.getAlignment() <= Value::MaximumAlignment,do { if (!(AI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &AI ); return; } } while (false) | ||||
| 3785 | "huge alignment values are unsupported", &AI)do { if (!(AI.getAlignment() <= Value::MaximumAlignment)) { CheckFailed("huge alignment values are unsupported", &AI ); return; } } while (false); | ||||
| 3786 | |||||
| 3787 | if (AI.isSwiftError()) { | ||||
| 3788 | verifySwiftErrorValue(&AI); | ||||
| 3789 | } | ||||
| 3790 | |||||
| 3791 | visitInstruction(AI); | ||||
| 3792 | } | ||||
| 3793 | |||||
| 3794 | void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { | ||||
| 3795 | Type *ElTy = CXI.getOperand(1)->getType(); | ||||
| 3796 | Assert(ElTy->isIntOrPtrTy(),do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false) | ||||
| 3797 | "cmpxchg operand must have integer or pointer type", ElTy, &CXI)do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false); | ||||
| 3798 | checkAtomicMemAccessSize(ElTy, &CXI); | ||||
| 3799 | visitInstruction(CXI); | ||||
| 3800 | } | ||||
| 3801 | |||||
| 3802 | void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { | ||||
| 3803 | Assert(RMWI.getOrdering() != AtomicOrdering::Unordered,do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false) | ||||
| 3804 | "atomicrmw instructions cannot be unordered.", &RMWI)do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false); | ||||
| 3805 | auto Op = RMWI.getOperation(); | ||||
| 3806 | Type *ElTy = RMWI.getOperand(1)->getType(); | ||||
| 3807 | if (Op == AtomicRMWInst::Xchg) { | ||||
| 3808 | Assert(ElTy->isIntegerTy() || ElTy->isFloatingPointTy(), "atomicrmw " +do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false) | ||||
| 3809 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false) | ||||
| 3810 | " operand must have integer or floating point type!",do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false) | ||||
| 3811 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName (Op) + " operand must have integer or floating point type!", & RMWI, ElTy); return; } } while (false); | ||||
| 3812 | } else if (AtomicRMWInst::isFPOperation(Op)) { | ||||
| 3813 | Assert(ElTy->isFloatingPointTy(), "atomicrmw " +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 3814 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 3815 | " operand must have floating point type!",do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 3816 | &RMWI, ElTy)do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false); | ||||
| 3817 | } else { | ||||
| 3818 | Assert(ElTy->isIntegerTy(), "atomicrmw " +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 3819 | AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 3820 | " operand must have integer type!",do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 3821 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false); | ||||
| 3822 | } | ||||
| 3823 | checkAtomicMemAccessSize(ElTy, &RMWI); | ||||
| 3824 | Assert(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP,do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false) | ||||
| 3825 | "Invalid binary operation!", &RMWI)do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false); | ||||
| 3826 | visitInstruction(RMWI); | ||||
| 3827 | } | ||||
| 3828 | |||||
| 3829 | void Verifier::visitFenceInst(FenceInst &FI) { | ||||
| 3830 | const AtomicOrdering Ordering = FI.getOrdering(); | ||||
| 3831 | Assert(Ordering == AtomicOrdering::Acquire ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 3832 | Ordering == AtomicOrdering::Release ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 3833 | Ordering == AtomicOrdering::AcquireRelease ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 3834 | Ordering == AtomicOrdering::SequentiallyConsistent,do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 3835 | "fence instructions may only have acquire, release, acq_rel, or "do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 3836 | "seq_cst ordering.",do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 3837 | &FI)do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false); | ||||
| 3838 | visitInstruction(FI); | ||||
| 3839 | } | ||||
| 3840 | |||||
| 3841 | void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { | ||||
| 3842 | Assert(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
| 3843 | EVI.getIndices()) == EVI.getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
| 3844 | "Invalid ExtractValueInst operands!", &EVI)do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false); | ||||
| 3845 | |||||
| 3846 | visitInstruction(EVI); | ||||
| 3847 | } | ||||
| 3848 | |||||
| 3849 | void Verifier::visitInsertValueInst(InsertValueInst &IVI) { | ||||
| 3850 | Assert(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(),do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
| 3851 | IVI.getIndices()) ==do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
| 3852 | IVI.getOperand(1)->getType(),do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
| 3853 | "Invalid InsertValueInst operands!", &IVI)do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false); | ||||
| 3854 | |||||
| 3855 | visitInstruction(IVI); | ||||
| 3856 | } | ||||
| 3857 | |||||
| 3858 | static Value *getParentPad(Value *EHPad) { | ||||
| 3859 | if (auto *FPI = dyn_cast<FuncletPadInst>(EHPad)) | ||||
| 3860 | return FPI->getParentPad(); | ||||
| 3861 | |||||
| 3862 | return cast<CatchSwitchInst>(EHPad)->getParentPad(); | ||||
| 3863 | } | ||||
| 3864 | |||||
| 3865 | void Verifier::visitEHPadPredecessors(Instruction &I) { | ||||
| 3866 | assert(I.isEHPad())((void)0); | ||||
| 3867 | |||||
| 3868 | BasicBlock *BB = I.getParent(); | ||||
| 3869 | Function *F = BB->getParent(); | ||||
| 3870 | |||||
| 3871 | Assert(BB != &F->getEntryBlock(), "EH pad cannot be in entry block.", &I)do { if (!(BB != &F->getEntryBlock())) { CheckFailed("EH pad cannot be in entry block." , &I); return; } } while (false); | ||||
| 3872 | |||||
| 3873 | if (auto *LPI = dyn_cast<LandingPadInst>(&I)) { | ||||
| 3874 | // The landingpad instruction defines its parent as a landing pad block. The | ||||
| 3875 | // landing pad block may be branched to only by the unwind edge of an | ||||
| 3876 | // invoke. | ||||
| 3877 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
| 3878 | const auto *II = dyn_cast<InvokeInst>(PredBB->getTerminator()); | ||||
| 3879 | Assert(II && II->getUnwindDest() == BB && II->getNormalDest() != BB,do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
| 3880 | "Block containing LandingPadInst must be jumped to "do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
| 3881 | "only by the unwind edge of an invoke.",do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
| 3882 | LPI)do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false); | ||||
| 3883 | } | ||||
| 3884 | return; | ||||
| 3885 | } | ||||
| 3886 | if (auto *CPI = dyn_cast<CatchPadInst>(&I)) { | ||||
| 3887 | if (!pred_empty(BB)) | ||||
| 3888 | Assert(BB->getUniquePredecessor() == CPI->getCatchSwitch()->getParent(),do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
| 3889 | "Block containg CatchPadInst must be jumped to "do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
| 3890 | "only by its catchswitch.",do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
| 3891 | CPI)do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false); | ||||
| 3892 | Assert(BB != CPI->getCatchSwitch()->getUnwindDest(),do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false) | ||||
| 3893 | "Catchswitch cannot unwind to one of its catchpads",do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false) | ||||
| 3894 | CPI->getCatchSwitch(), CPI)do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false); | ||||
| 3895 | return; | ||||
| 3896 | } | ||||
| 3897 | |||||
| 3898 | // Verify that each pred has a legal terminator with a legal to/from EH | ||||
| 3899 | // pad relationship. | ||||
| 3900 | Instruction *ToPad = &I; | ||||
| 3901 | Value *ToPadParent = getParentPad(ToPad); | ||||
| 3902 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
| 3903 | Instruction *TI = PredBB->getTerminator(); | ||||
| 3904 | Value *FromPad; | ||||
| 3905 | if (auto *II = dyn_cast<InvokeInst>(TI)) { | ||||
| 3906 | Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB,do { if (!(II->getUnwindDest() == BB && II->getNormalDest () != BB)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, II); return; } } while (false) | ||||
| 3907 | "EH pad must be jumped to via an unwind edge", ToPad, II)do { if (!(II->getUnwindDest() == BB && II->getNormalDest () != BB)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, II); return; } } while (false); | ||||
| 3908 | if (auto Bundle = II->getOperandBundle(LLVMContext::OB_funclet)) | ||||
| 3909 | FromPad = Bundle->Inputs[0]; | ||||
| 3910 | else | ||||
| 3911 | FromPad = ConstantTokenNone::get(II->getContext()); | ||||
| 3912 | } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) { | ||||
| 3913 | FromPad = CRI->getOperand(0); | ||||
| 3914 | Assert(FromPad != ToPadParent, "A cleanupret must exit its cleanup", CRI)do { if (!(FromPad != ToPadParent)) { CheckFailed("A cleanupret must exit its cleanup" , CRI); return; } } while (false); | ||||
| 3915 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) { | ||||
| 3916 | FromPad = CSI; | ||||
| 3917 | } else { | ||||
| 3918 | Assert(false, "EH pad must be jumped to via an unwind edge", ToPad, TI)do { if (!(false)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, TI); return; } } while (false); | ||||
| 3919 | } | ||||
| 3920 | |||||
| 3921 | // The edge may exit from zero or more nested pads. | ||||
| 3922 | SmallSet<Value *, 8> Seen; | ||||
| 3923 | for (;; FromPad = getParentPad(FromPad)) { | ||||
| 3924 | Assert(FromPad != ToPad,do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false) | ||||
| 3925 | "EH pad cannot handle exceptions raised within it", FromPad, TI)do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false); | ||||
| 3926 | if (FromPad == ToPadParent) { | ||||
| 3927 | // This is a legal unwind edge. | ||||
| 3928 | break; | ||||
| 3929 | } | ||||
| 3930 | Assert(!isa<ConstantTokenNone>(FromPad),do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false) | ||||
| 3931 | "A single unwind edge may only enter one EH pad", TI)do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false); | ||||
| 3932 | Assert(Seen.insert(FromPad).second,do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false) | ||||
| 3933 | "EH pad jumps through a cycle of pads", FromPad)do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false); | ||||
| 3934 | } | ||||
| 3935 | } | ||||
| 3936 | } | ||||
| 3937 | |||||
| 3938 | void Verifier::visitLandingPadInst(LandingPadInst &LPI) { | ||||
| 3939 | // The landingpad instruction is ill-formed if it doesn't have any clauses and | ||||
| 3940 | // isn't a cleanup. | ||||
| 3941 | Assert(LPI.getNumClauses() > 0 || LPI.isCleanup(),do { if (!(LPI.getNumClauses() > 0 || LPI.isCleanup())) { CheckFailed ("LandingPadInst needs at least one clause or to be a cleanup." , &LPI); return; } } while (false) | ||||
| 3942 | "LandingPadInst needs at least one clause or to be a cleanup.", &LPI)do { if (!(LPI.getNumClauses() > 0 || LPI.isCleanup())) { CheckFailed ("LandingPadInst needs at least one clause or to be a cleanup." , &LPI); return; } } while (false); | ||||
| 3943 | |||||
| 3944 | visitEHPadPredecessors(LPI); | ||||
| 3945 | |||||
| 3946 | if (!LandingPadResultTy) | ||||
| 3947 | LandingPadResultTy = LPI.getType(); | ||||
| 3948 | else | ||||
| 3949 | Assert(LandingPadResultTy == LPI.getType(),do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
| 3950 | "The landingpad instruction should have a consistent result type "do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
| 3951 | "inside a function.",do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
| 3952 | &LPI)do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false); | ||||
| 3953 | |||||
| 3954 | Function *F = LPI.getParent()->getParent(); | ||||
| 3955 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false) | ||||
| 3956 | "LandingPadInst needs to be in a function with a personality.", &LPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false); | ||||
| 3957 | |||||
| 3958 | // The landingpad instruction must be the first non-PHI instruction in the | ||||
| 3959 | // block. | ||||
| 3960 | Assert(LPI.getParent()->getLandingPadInst() == &LPI,do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false) | ||||
| 3961 | "LandingPadInst not the first non-PHI instruction in the block.",do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false) | ||||
| 3962 | &LPI)do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false); | ||||
| 3963 | |||||
| 3964 | for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) { | ||||
| 3965 | Constant *Clause = LPI.getClause(i); | ||||
| 3966 | if (LPI.isCatch(i)) { | ||||
| 3967 | Assert(isa<PointerType>(Clause->getType()),do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false) | ||||
| 3968 | "Catch operand does not have pointer type!", &LPI)do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false); | ||||
| 3969 | } else { | ||||
| 3970 | Assert(LPI.isFilter(i), "Clause is neither catch nor filter!", &LPI)do { if (!(LPI.isFilter(i))) { CheckFailed("Clause is neither catch nor filter!" , &LPI); return; } } while (false); | ||||
| 3971 | Assert(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero>(Clause),do { if (!(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero >(Clause))) { CheckFailed("Filter operand is not an array of constants!" , &LPI); return; } } while (false) | ||||
| 3972 | "Filter operand is not an array of constants!", &LPI)do { if (!(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero >(Clause))) { CheckFailed("Filter operand is not an array of constants!" , &LPI); return; } } while (false); | ||||
| 3973 | } | ||||
| 3974 | } | ||||
| 3975 | |||||
| 3976 | visitInstruction(LPI); | ||||
| 3977 | } | ||||
| 3978 | |||||
| 3979 | void Verifier::visitResumeInst(ResumeInst &RI) { | ||||
| 3980 | Assert(RI.getFunction()->hasPersonalityFn(),do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false) | ||||
| 3981 | "ResumeInst needs to be in a function with a personality.", &RI)do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false); | ||||
| 3982 | |||||
| 3983 | if (!LandingPadResultTy) | ||||
| 3984 | LandingPadResultTy = RI.getValue()->getType(); | ||||
| 3985 | else | ||||
| 3986 | Assert(LandingPadResultTy == RI.getValue()->getType(),do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
| 3987 | "The resume instruction should have a consistent result type "do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
| 3988 | "inside a function.",do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
| 3989 | &RI)do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false); | ||||
| 3990 | |||||
| 3991 | visitTerminator(RI); | ||||
| 3992 | } | ||||
| 3993 | |||||
| 3994 | void Verifier::visitCatchPadInst(CatchPadInst &CPI) { | ||||
| 3995 | BasicBlock *BB = CPI.getParent(); | ||||
| 3996 | |||||
| 3997 | Function *F = BB->getParent(); | ||||
| 3998 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
| 3999 | "CatchPadInst needs to be in a function with a personality.", &CPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false); | ||||
| 4000 | |||||
| 4001 | Assert(isa<CatchSwitchInst>(CPI.getParentPad()),do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false) | ||||
| 4002 | "CatchPadInst needs to be directly nested in a CatchSwitchInst.",do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false) | ||||
| 4003 | CPI.getParentPad())do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false); | ||||
| 4004 | |||||
| 4005 | // The catchpad instruction must be the first non-PHI instruction in the | ||||
| 4006 | // block. | ||||
| 4007 | Assert(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
| 4008 | "CatchPadInst not the first non-PHI instruction in the block.", &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
| 4009 | |||||
| 4010 | visitEHPadPredecessors(CPI); | ||||
| 4011 | visitFuncletPadInst(CPI); | ||||
| 4012 | } | ||||
| 4013 | |||||
| 4014 | void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) { | ||||
| 4015 | Assert(isa<CatchPadInst>(CatchReturn.getOperand(0)),do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false) | ||||
| 4016 | "CatchReturnInst needs to be provided a CatchPad", &CatchReturn,do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false) | ||||
| 4017 | CatchReturn.getOperand(0))do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false); | ||||
| 4018 | |||||
| 4019 | visitTerminator(CatchReturn); | ||||
| 4020 | } | ||||
| 4021 | |||||
| 4022 | void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { | ||||
| 4023 | BasicBlock *BB = CPI.getParent(); | ||||
| 4024 | |||||
| 4025 | Function *F = BB->getParent(); | ||||
| 4026 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
| 4027 | "CleanupPadInst needs to be in a function with a personality.", &CPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false); | ||||
| 4028 | |||||
| 4029 | // The cleanuppad instruction must be the first non-PHI instruction in the | ||||
| 4030 | // block. | ||||
| 4031 | Assert(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
| 4032 | "CleanupPadInst not the first non-PHI instruction in the block.",do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
| 4033 | &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
| 4034 | |||||
| 4035 | auto *ParentPad = CPI.getParentPad(); | ||||
| 4036 | Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false) | ||||
| 4037 | "CleanupPadInst has an invalid parent.", &CPI)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false); | ||||
| 4038 | |||||
| 4039 | visitEHPadPredecessors(CPI); | ||||
| 4040 | visitFuncletPadInst(CPI); | ||||
| 4041 | } | ||||
| 4042 | |||||
| 4043 | void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { | ||||
| 4044 | User *FirstUser = nullptr; | ||||
| 4045 | Value *FirstUnwindPad = nullptr; | ||||
| 4046 | SmallVector<FuncletPadInst *, 8> Worklist({&FPI}); | ||||
| 4047 | SmallSet<FuncletPadInst *, 8> Seen; | ||||
| 4048 | |||||
| 4049 | while (!Worklist.empty()) { | ||||
| 4050 | FuncletPadInst *CurrentPad = Worklist.pop_back_val(); | ||||
| 4051 | Assert(Seen.insert(CurrentPad).second,do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false) | ||||
| 4052 | "FuncletPadInst must not be nested within itself", CurrentPad)do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false); | ||||
| 4053 | Value *UnresolvedAncestorPad = nullptr; | ||||
| 4054 | for (User *U : CurrentPad->users()) { | ||||
| 4055 | BasicBlock *UnwindDest; | ||||
| 4056 | if (auto *CRI = dyn_cast<CleanupReturnInst>(U)) { | ||||
| 4057 | UnwindDest = CRI->getUnwindDest(); | ||||
| 4058 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(U)) { | ||||
| 4059 | // We allow catchswitch unwind to caller to nest | ||||
| 4060 | // within an outer pad that unwinds somewhere else, | ||||
| 4061 | // because catchswitch doesn't have a nounwind variant. | ||||
| 4062 | // See e.g. SimplifyCFGOpt::SimplifyUnreachable. | ||||
| 4063 | if (CSI->unwindsToCaller()) | ||||
| 4064 | continue; | ||||
| 4065 | UnwindDest = CSI->getUnwindDest(); | ||||
| 4066 | } else if (auto *II = dyn_cast<InvokeInst>(U)) { | ||||
| 4067 | UnwindDest = II->getUnwindDest(); | ||||
| 4068 | } else if (isa<CallInst>(U)) { | ||||
| 4069 | // Calls which don't unwind may be found inside funclet | ||||
| 4070 | // pads that unwind somewhere else. We don't *require* | ||||
| 4071 | // such calls to be annotated nounwind. | ||||
| 4072 | continue; | ||||
| 4073 | } else if (auto *CPI = dyn_cast<CleanupPadInst>(U)) { | ||||
| 4074 | // The unwind dest for a cleanup can only be found by | ||||
| 4075 | // recursive search. Add it to the worklist, and we'll | ||||
| 4076 | // search for its first use that determines where it unwinds. | ||||
| 4077 | Worklist.push_back(CPI); | ||||
| 4078 | continue; | ||||
| 4079 | } else { | ||||
| 4080 | Assert(isa<CatchReturnInst>(U), "Bogus funclet pad use", U)do { if (!(isa<CatchReturnInst>(U))) { CheckFailed("Bogus funclet pad use" , U); return; } } while (false); | ||||
| 4081 | continue; | ||||
| 4082 | } | ||||
| 4083 | |||||
| 4084 | Value *UnwindPad; | ||||
| 4085 | bool ExitsFPI; | ||||
| 4086 | if (UnwindDest) { | ||||
| 4087 | UnwindPad = UnwindDest->getFirstNonPHI(); | ||||
| 4088 | if (!cast<Instruction>(UnwindPad)->isEHPad()) | ||||
| 4089 | continue; | ||||
| 4090 | Value *UnwindParent = getParentPad(UnwindPad); | ||||
| 4091 | // Ignore unwind edges that don't exit CurrentPad. | ||||
| 4092 | if (UnwindParent == CurrentPad) | ||||
| 4093 | continue; | ||||
| 4094 | // Determine whether the original funclet pad is exited, | ||||
| 4095 | // and if we are scanning nested pads determine how many | ||||
| 4096 | // of them are exited so we can stop searching their | ||||
| 4097 | // children. | ||||
| 4098 | Value *ExitedPad = CurrentPad; | ||||
| 4099 | ExitsFPI = false; | ||||
| 4100 | do { | ||||
| 4101 | if (ExitedPad == &FPI) { | ||||
| 4102 | ExitsFPI = true; | ||||
| 4103 | // Now we can resolve any ancestors of CurrentPad up to | ||||
| 4104 | // FPI, but not including FPI since we need to make sure | ||||
| 4105 | // to check all direct users of FPI for consistency. | ||||
| 4106 | UnresolvedAncestorPad = &FPI; | ||||
| 4107 | break; | ||||
| 4108 | } | ||||
| 4109 | Value *ExitedParent = getParentPad(ExitedPad); | ||||
| 4110 | if (ExitedParent == UnwindParent) { | ||||
| 4111 | // ExitedPad is the ancestor-most pad which this unwind | ||||
| 4112 | // edge exits, so we can resolve up to it, meaning that | ||||
| 4113 | // ExitedParent is the first ancestor still unresolved. | ||||
| 4114 | UnresolvedAncestorPad = ExitedParent; | ||||
| 4115 | break; | ||||
| 4116 | } | ||||
| 4117 | ExitedPad = ExitedParent; | ||||
| 4118 | } while (!isa<ConstantTokenNone>(ExitedPad)); | ||||
| 4119 | } else { | ||||
| 4120 | // Unwinding to caller exits all pads. | ||||
| 4121 | UnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
| 4122 | ExitsFPI = true; | ||||
| 4123 | UnresolvedAncestorPad = &FPI; | ||||
| 4124 | } | ||||
| 4125 | |||||
| 4126 | if (ExitsFPI) { | ||||
| 4127 | // This unwind edge exits FPI. Make sure it agrees with other | ||||
| 4128 | // such edges. | ||||
| 4129 | if (FirstUser) { | ||||
| 4130 | Assert(UnwindPad == FirstUnwindPad, "Unwind edges out of a funclet "do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
| 4131 | "pad must have the same unwind "do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
| 4132 | "dest",do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
| 4133 | &FPI, U, FirstUser)do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false); | ||||
| 4134 | } else { | ||||
| 4135 | FirstUser = U; | ||||
| 4136 | FirstUnwindPad = UnwindPad; | ||||
| 4137 | // Record cleanup sibling unwinds for verifySiblingFuncletUnwinds | ||||
| 4138 | if (isa<CleanupPadInst>(&FPI) && !isa<ConstantTokenNone>(UnwindPad) && | ||||
| 4139 | getParentPad(UnwindPad) == getParentPad(&FPI)) | ||||
| 4140 | SiblingFuncletInfo[&FPI] = cast<Instruction>(U); | ||||
| 4141 | } | ||||
| 4142 | } | ||||
| 4143 | // Make sure we visit all uses of FPI, but for nested pads stop as | ||||
| 4144 | // soon as we know where they unwind to. | ||||
| 4145 | if (CurrentPad != &FPI) | ||||
| 4146 | break; | ||||
| 4147 | } | ||||
| 4148 | if (UnresolvedAncestorPad) { | ||||
| 4149 | if (CurrentPad == UnresolvedAncestorPad) { | ||||
| 4150 | // When CurrentPad is FPI itself, we don't mark it as resolved even if | ||||
| 4151 | // we've found an unwind edge that exits it, because we need to verify | ||||
| 4152 | // all direct uses of FPI. | ||||
| 4153 | assert(CurrentPad == &FPI)((void)0); | ||||
| 4154 | continue; | ||||
| 4155 | } | ||||
| 4156 | // Pop off the worklist any nested pads that we've found an unwind | ||||
| 4157 | // destination for. The pads on the worklist are the uncles, | ||||
| 4158 | // great-uncles, etc. of CurrentPad. We've found an unwind destination | ||||
| 4159 | // for all ancestors of CurrentPad up to but not including | ||||
| 4160 | // UnresolvedAncestorPad. | ||||
| 4161 | Value *ResolvedPad = CurrentPad; | ||||
| 4162 | while (!Worklist.empty()) { | ||||
| 4163 | Value *UnclePad = Worklist.back(); | ||||
| 4164 | Value *AncestorPad = getParentPad(UnclePad); | ||||
| 4165 | // Walk ResolvedPad up the ancestor list until we either find the | ||||
| 4166 | // uncle's parent or the last resolved ancestor. | ||||
| 4167 | while (ResolvedPad != AncestorPad) { | ||||
| 4168 | Value *ResolvedParent = getParentPad(ResolvedPad); | ||||
| 4169 | if (ResolvedParent == UnresolvedAncestorPad) { | ||||
| 4170 | break; | ||||
| 4171 | } | ||||
| 4172 | ResolvedPad = ResolvedParent; | ||||
| 4173 | } | ||||
| 4174 | // If the resolved ancestor search didn't find the uncle's parent, | ||||
| 4175 | // then the uncle is not yet resolved. | ||||
| 4176 | if (ResolvedPad != AncestorPad) | ||||
| 4177 | break; | ||||
| 4178 | // This uncle is resolved, so pop it from the worklist. | ||||
| 4179 | Worklist.pop_back(); | ||||
| 4180 | } | ||||
| 4181 | } | ||||
| 4182 | } | ||||
| 4183 | |||||
| 4184 | if (FirstUnwindPad) { | ||||
| 4185 | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FPI.getParentPad())) { | ||||
| 4186 | BasicBlock *SwitchUnwindDest = CatchSwitch->getUnwindDest(); | ||||
| 4187 | Value *SwitchUnwindPad; | ||||
| 4188 | if (SwitchUnwindDest) | ||||
| 4189 | SwitchUnwindPad = SwitchUnwindDest->getFirstNonPHI(); | ||||
| 4190 | else | ||||
| 4191 | SwitchUnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
| 4192 | Assert(SwitchUnwindPad == FirstUnwindPad,do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
| 4193 | "Unwind edges out of a catch must have the same unwind dest as "do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
| 4194 | "the parent catchswitch",do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
| 4195 | &FPI, FirstUser, CatchSwitch)do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false); | ||||
| 4196 | } | ||||
| 4197 | } | ||||
| 4198 | |||||
| 4199 | visitInstruction(FPI); | ||||
| 4200 | } | ||||
| 4201 | |||||
| 4202 | void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) { | ||||
| 4203 | BasicBlock *BB = CatchSwitch.getParent(); | ||||
| 4204 | |||||
| 4205 | Function *F = BB->getParent(); | ||||
| 4206 | Assert(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
| 4207 | "CatchSwitchInst needs to be in a function with a personality.",do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
| 4208 | &CatchSwitch)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false); | ||||
| 4209 | |||||
| 4210 | // The catchswitch instruction must be the first non-PHI instruction in the | ||||
| 4211 | // block. | ||||
| 4212 | Assert(BB->getFirstNonPHI() == &CatchSwitch,do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
| 4213 | "CatchSwitchInst not the first non-PHI instruction in the block.",do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
| 4214 | &CatchSwitch)do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false); | ||||
| 4215 | |||||
| 4216 | auto *ParentPad = CatchSwitch.getParentPad(); | ||||
| 4217 | Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false) | ||||
| 4218 | "CatchSwitchInst has an invalid parent.", ParentPad)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false); | ||||
| 4219 | |||||
| 4220 | if (BasicBlock *UnwindDest = CatchSwitch.getUnwindDest()) { | ||||
| 4221 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
| 4222 | Assert(I->isEHPad() && !isa<LandingPadInst>(I),do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
| 4223 | "CatchSwitchInst must unwind to an EH block which is not a "do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
| 4224 | "landingpad.",do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
| 4225 | &CatchSwitch)do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false); | ||||
| 4226 | |||||
| 4227 | // Record catchswitch sibling unwinds for verifySiblingFuncletUnwinds | ||||
| 4228 | if (getParentPad(I) == ParentPad) | ||||
| 4229 | SiblingFuncletInfo[&CatchSwitch] = &CatchSwitch; | ||||
| 4230 | } | ||||
| 4231 | |||||
| 4232 | Assert(CatchSwitch.getNumHandlers() != 0,do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false) | ||||
| 4233 | "CatchSwitchInst cannot have empty handler list", &CatchSwitch)do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false); | ||||
| 4234 | |||||
| 4235 | for (BasicBlock *Handler : CatchSwitch.handlers()) { | ||||
| 4236 | Assert(isa<CatchPadInst>(Handler->getFirstNonPHI()),do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false) | ||||
| 4237 | "CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler)do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false); | ||||
| 4238 | } | ||||
| 4239 | |||||
| 4240 | visitEHPadPredecessors(CatchSwitch); | ||||
| 4241 | visitTerminator(CatchSwitch); | ||||
| 4242 | } | ||||
| 4243 | |||||
| 4244 | void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) { | ||||
| 4245 | Assert(isa<CleanupPadInst>(CRI.getOperand(0)),do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false) | ||||
| 4246 | "CleanupReturnInst needs to be provided a CleanupPad", &CRI,do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false) | ||||
| 4247 | CRI.getOperand(0))do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false); | ||||
| 4248 | |||||
| 4249 | if (BasicBlock *UnwindDest = CRI.getUnwindDest()) { | ||||
| 4250 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
| 4251 | Assert(I->isEHPad() && !isa<LandingPadInst>(I),do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
| 4252 | "CleanupReturnInst must unwind to an EH block which is not a "do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
| 4253 | "landingpad.",do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
| 4254 | &CRI)do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false); | ||||
| 4255 | } | ||||
| 4256 | |||||
| 4257 | visitTerminator(CRI); | ||||
| 4258 | } | ||||
| 4259 | |||||
| 4260 | void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { | ||||
| 4261 | Instruction *Op = cast<Instruction>(I.getOperand(i)); | ||||
| 4262 | // If the we have an invalid invoke, don't try to compute the dominance. | ||||
| 4263 | // We already reject it in the invoke specific checks and the dominance | ||||
| 4264 | // computation doesn't handle multiple edges. | ||||
| 4265 | if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) { | ||||
| 4266 | if (II->getNormalDest() == II->getUnwindDest()) | ||||
| 4267 | return; | ||||
| 4268 | } | ||||
| 4269 | |||||
| 4270 | // Quick check whether the def has already been encountered in the same block. | ||||
| 4271 | // PHI nodes are not checked to prevent accepting preceding PHIs, because PHI | ||||
| 4272 | // uses are defined to happen on the incoming edge, not at the instruction. | ||||
| 4273 | // | ||||
| 4274 | // FIXME: If this operand is a MetadataAsValue (wrapping a LocalAsMetadata) | ||||
| 4275 | // wrapping an SSA value, assert that we've already encountered it. See | ||||
| 4276 | // related FIXME in Mapper::mapLocalAsMetadata in ValueMapper.cpp. | ||||
| 4277 | if (!isa<PHINode>(I) && InstsInThisBlock.count(Op)) | ||||
| 4278 | return; | ||||
| 4279 | |||||
| 4280 | const Use &U = I.getOperandUse(i); | ||||
| 4281 | Assert(DT.dominates(Op, U),do { if (!(DT.dominates(Op, U))) { CheckFailed("Instruction does not dominate all uses!" , Op, &I); return; } } while (false) | ||||
| 4282 | "Instruction does not dominate all uses!", Op, &I)do { if (!(DT.dominates(Op, U))) { CheckFailed("Instruction does not dominate all uses!" , Op, &I); return; } } while (false); | ||||
| 4283 | } | ||||
| 4284 | |||||
| 4285 | void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) { | ||||
| 4286 | Assert(I.getType()->isPointerTy(), "dereferenceable, dereferenceable_or_null "do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
| 4287 | "apply only to pointer types", &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ); | ||||
| 4288 | Assert((isa<LoadInst>(I) || isa<IntToPtrInst>(I)),do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false) | ||||
| 4289 | "dereferenceable, dereferenceable_or_null apply only to load"do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false) | ||||
| 4290 | " and inttoptr instructions, use attributes for calls or invokes", &I)do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false); | ||||
| 4291 | Assert(MD->getNumOperands() == 1, "dereferenceable, dereferenceable_or_null "do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
| 4292 | "take one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false); | ||||
| 4293 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0)); | ||||
| 4294 | Assert(CI && CI->getType()->isIntegerTy(64), "dereferenceable, "do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
| 4295 | "dereferenceable_or_null metadata value must be an i64!", &I)do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false); | ||||
| 4296 | } | ||||
| 4297 | |||||
| 4298 | void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) { | ||||
| 4299 | Assert(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
| 4300 | "!prof annotations should have no less than 2 operands", MD)do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false); | ||||
| 4301 | |||||
| 4302 | // Check first operand. | ||||
| 4303 | Assert(MD->getOperand(0) != nullptr, "first operand should not be null", MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
| 4304 | Assert(isa<MDString>(MD->getOperand(0)),do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false) | ||||
| 4305 | "expected string with name of the !prof annotation", MD)do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false); | ||||
| 4306 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
| 4307 | StringRef ProfName = MDS->getString(); | ||||
| 4308 | |||||
| 4309 | // Check consistency of !prof branch_weights metadata. | ||||
| 4310 | if (ProfName.equals("branch_weights")) { | ||||
| 4311 | if (isa<InvokeInst>(&I)) { | ||||
| 4312 | Assert(MD->getNumOperands() == 2 || MD->getNumOperands() == 3,do { if (!(MD->getNumOperands() == 2 || MD->getNumOperands () == 3)) { CheckFailed("Wrong number of InvokeInst branch_weights operands" , MD); return; } } while (false) | ||||
| 4313 | "Wrong number of InvokeInst branch_weights operands", MD)do { if (!(MD->getNumOperands() == 2 || MD->getNumOperands () == 3)) { CheckFailed("Wrong number of InvokeInst branch_weights operands" , MD); return; } } while (false); | ||||
| 4314 | } else { | ||||
| 4315 | unsigned ExpectedNumOperands = 0; | ||||
| 4316 | if (BranchInst *BI = dyn_cast<BranchInst>(&I)) | ||||
| 4317 | ExpectedNumOperands = BI->getNumSuccessors(); | ||||
| 4318 | else if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) | ||||
| 4319 | ExpectedNumOperands = SI->getNumSuccessors(); | ||||
| 4320 | else if (isa<CallInst>(&I)) | ||||
| 4321 | ExpectedNumOperands = 1; | ||||
| 4322 | else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(&I)) | ||||
| 4323 | ExpectedNumOperands = IBI->getNumDestinations(); | ||||
| 4324 | else if (isa<SelectInst>(&I)) | ||||
| 4325 | ExpectedNumOperands = 2; | ||||
| 4326 | else | ||||
| 4327 | CheckFailed("!prof branch_weights are not allowed for this instruction", | ||||
| 4328 | MD); | ||||
| 4329 | |||||
| 4330 | Assert(MD->getNumOperands() == 1 + ExpectedNumOperands,do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false) | ||||
| 4331 | "Wrong number of operands", MD)do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false); | ||||
| 4332 | } | ||||
| 4333 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) { | ||||
| 4334 | auto &MDO = MD->getOperand(i); | ||||
| 4335 | Assert(MDO, "second operand should not be null", MD)do { if (!(MDO)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
| 4336 | Assert(mdconst::dyn_extract<ConstantInt>(MDO),do { if (!(mdconst::dyn_extract<ConstantInt>(MDO))) { CheckFailed ("!prof brunch_weights operand is not a const int"); return; } } while (false) | ||||
| 4337 | "!prof brunch_weights operand is not a const int")do { if (!(mdconst::dyn_extract<ConstantInt>(MDO))) { CheckFailed ("!prof brunch_weights operand is not a const int"); return; } } while (false); | ||||
| 4338 | } | ||||
| 4339 | } | ||||
| 4340 | } | ||||
| 4341 | |||||
| 4342 | void Verifier::visitAnnotationMetadata(MDNode *Annotation) { | ||||
| 4343 | Assert(isa<MDTuple>(Annotation), "annotation must be a tuple")do { if (!(isa<MDTuple>(Annotation))) { CheckFailed("annotation must be a tuple" ); return; } } while (false); | ||||
| 4344 | Assert(Annotation->getNumOperands() >= 1,do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false) | ||||
| 4345 | "annotation must have at least one operand")do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false); | ||||
| 4346 | for (const MDOperand &Op : Annotation->operands()) | ||||
| 4347 | Assert(isa<MDString>(Op.get()), "operands must be strings")do { if (!(isa<MDString>(Op.get()))) { CheckFailed("operands must be strings" ); return; } } while (false); | ||||
| 4348 | } | ||||
| 4349 | |||||
| 4350 | /// verifyInstruction - Verify that an instruction is well formed. | ||||
| 4351 | /// | ||||
| 4352 | void Verifier::visitInstruction(Instruction &I) { | ||||
| 4353 | BasicBlock *BB = I.getParent(); | ||||
| 4354 | Assert(BB, "Instruction not embedded in basic block!", &I)do { if (!(BB)) { CheckFailed("Instruction not embedded in basic block!" , &I); return; } } while (false); | ||||
| 4355 | |||||
| 4356 | if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential | ||||
| 4357 | for (User *U : I.users()) { | ||||
| 4358 | Assert(U != (User *)&I || !DT.isReachableFromEntry(BB),do { if (!(U != (User *)&I || !DT.isReachableFromEntry(BB ))) { CheckFailed("Only PHI nodes may reference their own value!" , &I); return; } } while (false) | ||||
| 4359 | "Only PHI nodes may reference their own value!", &I)do { if (!(U != (User *)&I || !DT.isReachableFromEntry(BB ))) { CheckFailed("Only PHI nodes may reference their own value!" , &I); return; } } while (false); | ||||
| 4360 | } | ||||
| 4361 | } | ||||
| 4362 | |||||
| 4363 | // Check that void typed values don't have names | ||||
| 4364 | Assert(!I.getType()->isVoidTy() || !I.hasName(),do { if (!(!I.getType()->isVoidTy() || !I.hasName())) { CheckFailed ("Instruction has a name, but provides a void value!", &I ); return; } } while (false) | ||||
| 4365 | "Instruction has a name, but provides a void value!", &I)do { if (!(!I.getType()->isVoidTy() || !I.hasName())) { CheckFailed ("Instruction has a name, but provides a void value!", &I ); return; } } while (false); | ||||
| 4366 | |||||
| 4367 | // Check that the return value of the instruction is either void or a legal | ||||
| 4368 | // value type. | ||||
| 4369 | Assert(I.getType()->isVoidTy() || I.getType()->isFirstClassType(),do { if (!(I.getType()->isVoidTy() || I.getType()->isFirstClassType ())) { CheckFailed("Instruction returns a non-scalar type!", & I); return; } } while (false) | ||||
| 4370 | "Instruction returns a non-scalar type!", &I)do { if (!(I.getType()->isVoidTy() || I.getType()->isFirstClassType ())) { CheckFailed("Instruction returns a non-scalar type!", & I); return; } } while (false); | ||||
| 4371 | |||||
| 4372 | // Check that the instruction doesn't produce metadata. Calls are already | ||||
| 4373 | // checked against the callee type. | ||||
| 4374 | Assert(!I.getType()->isMetadataTy() || isa<CallInst>(I) || isa<InvokeInst>(I),do { if (!(!I.getType()->isMetadataTy() || isa<CallInst >(I) || isa<InvokeInst>(I))) { CheckFailed("Invalid use of metadata!" , &I); return; } } while (false) | ||||
| 4375 | "Invalid use of metadata!", &I)do { if (!(!I.getType()->isMetadataTy() || isa<CallInst >(I) || isa<InvokeInst>(I))) { CheckFailed("Invalid use of metadata!" , &I); return; } } while (false); | ||||
| 4376 | |||||
| 4377 | // Check that all uses of the instruction, if they are instructions | ||||
| 4378 | // themselves, actually have parent basic blocks. If the use is not an | ||||
| 4379 | // instruction, it is an error! | ||||
| 4380 | for (Use &U : I.uses()) { | ||||
| 4381 | if (Instruction *Used = dyn_cast<Instruction>(U.getUser())) | ||||
| 4382 | Assert(Used->getParent() != nullptr,do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
| 4383 | "Instruction referencing"do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
| 4384 | " instruction not embedded in a basic block!",do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
| 4385 | &I, Used)do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false); | ||||
| 4386 | else { | ||||
| 4387 | CheckFailed("Use of instruction is not an instruction!", U); | ||||
| 4388 | return; | ||||
| 4389 | } | ||||
| 4390 | } | ||||
| 4391 | |||||
| 4392 | // Get a pointer to the call base of the instruction if it is some form of | ||||
| 4393 | // call. | ||||
| 4394 | const CallBase *CBI = dyn_cast<CallBase>(&I); | ||||
| 4395 | |||||
| 4396 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { | ||||
| 4397 | Assert(I.getOperand(i) != nullptr, "Instruction has null operand!", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Instruction has null operand!" , &I); return; } } while (false); | ||||
| 4398 | |||||
| 4399 | // Check to make sure that only first-class-values are operands to | ||||
| 4400 | // instructions. | ||||
| 4401 | if (!I.getOperand(i)->getType()->isFirstClassType()) { | ||||
| 4402 | Assert(false, "Instruction operands must be first-class values!", &I)do { if (!(false)) { CheckFailed("Instruction operands must be first-class values!" , &I); return; } } while (false); | ||||
| 4403 | } | ||||
| 4404 | |||||
| 4405 | if (Function *F = dyn_cast<Function>(I.getOperand(i))) { | ||||
| 4406 | // Check to make sure that the "address of" an intrinsic function is never | ||||
| 4407 | // taken. | ||||
| 4408 | Assert(!F->isIntrinsic() ||do { if (!(!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)))) { CheckFailed ("Cannot take the address of an intrinsic!", &I); return; } } while (false) | ||||
| 4409 | (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)),do { if (!(!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)))) { CheckFailed ("Cannot take the address of an intrinsic!", &I); return; } } while (false) | ||||
| 4410 | "Cannot take the address of an intrinsic!", &I)do { if (!(!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)))) { CheckFailed ("Cannot take the address of an intrinsic!", &I); return; } } while (false); | ||||
| 4411 | Assert(do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4412 | !F->isIntrinsic() || isa<CallInst>(I) ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4413 | F->getIntrinsicID() == Intrinsic::donothing ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4414 | F->getIntrinsicID() == Intrinsic::seh_try_begin ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4415 | F->getIntrinsicID() == Intrinsic::seh_try_end ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4416 | F->getIntrinsicID() == Intrinsic::seh_scope_begin ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4417 | F->getIntrinsicID() == Intrinsic::seh_scope_end ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4418 | F->getIntrinsicID() == Intrinsic::coro_resume ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4419 | F->getIntrinsicID() == Intrinsic::coro_destroy ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4420 | F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4421 | F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4422 | F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4423 | F->getIntrinsicID() == Intrinsic::wasm_rethrow,do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4424 | "Cannot invoke an intrinsic other than donothing, patchpoint, "do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4425 | "statepoint, coro_resume or coro_destroy",do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false) | ||||
| 4426 | &I)do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow)) { CheckFailed("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume or coro_destroy", &I); return; } } while (false); | ||||
| 4427 | Assert(F->getParent() == &M, "Referencing function in another module!",do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ) | ||||
| 4428 | &I, &M, F, F->getParent())do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ); | ||||
| 4429 | } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { | ||||
| 4430 | Assert(OpBB->getParent() == BB->getParent(),do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false) | ||||
| 4431 | "Referring to a basic block in another function!", &I)do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false); | ||||
| 4432 | } else if (Argument *OpArg = dyn_cast<Argument>(I.getOperand(i))) { | ||||
| 4433 | Assert(OpArg->getParent() == BB->getParent(),do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false) | ||||
| 4434 | "Referring to an argument in another function!", &I)do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false); | ||||
| 4435 | } else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) { | ||||
| 4436 | Assert(GV->getParent() == &M, "Referencing global in another module!", &I,do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false) | ||||
| 4437 | &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false); | ||||
| 4438 | } else if (isa<Instruction>(I.getOperand(i))) { | ||||
| 4439 | verifyDominatesUse(I, i); | ||||
| 4440 | } else if (isa<InlineAsm>(I.getOperand(i))) { | ||||
| 4441 | Assert(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i),do { if (!(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i))) { CheckFailed("Cannot take the address of an inline asm!" , &I); return; } } while (false) | ||||
| 4442 | "Cannot take the address of an inline asm!", &I)do { if (!(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i))) { CheckFailed("Cannot take the address of an inline asm!" , &I); return; } } while (false); | ||||
| 4443 | } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { | ||||
| 4444 | if (CE->getType()->isPtrOrPtrVectorTy()) { | ||||
| 4445 | // If we have a ConstantExpr pointer, we need to see if it came from an | ||||
| 4446 | // illegal bitcast. | ||||
| 4447 | visitConstantExprsRecursively(CE); | ||||
| 4448 | } | ||||
| 4449 | } | ||||
| 4450 | } | ||||
| 4451 | |||||
| 4452 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_fpmath)) { | ||||
| 4453 | Assert(I.getType()->isFPOrFPVectorTy(),do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false) | ||||
| 4454 | "fpmath requires a floating point result!", &I)do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false); | ||||
| 4455 | Assert(MD->getNumOperands() == 1, "fpmath takes one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("fpmath takes one operand!" , &I); return; } } while (false); | ||||
| 4456 | if (ConstantFP *CFP0 = | ||||
| 4457 | mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { | ||||
| 4458 | const APFloat &Accuracy = CFP0->getValueAPF(); | ||||
| 4459 | Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle(),do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false) | ||||
| 4460 | "fpmath accuracy must have float type", &I)do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false); | ||||
| 4461 | Assert(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(),do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false) | ||||
| 4462 | "fpmath accuracy not a positive number!", &I)do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false); | ||||
| 4463 | } else { | ||||
| 4464 | Assert(false, "invalid fpmath accuracy!", &I)do { if (!(false)) { CheckFailed("invalid fpmath accuracy!", & I); return; } } while (false); | ||||
| 4465 | } | ||||
| 4466 | } | ||||
| 4467 | |||||
| 4468 | if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) { | ||||
| 4469 | Assert(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I),do { if (!(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I))) { CheckFailed("Ranges are only for loads, calls and invokes!" , &I); return; } } while (false) | ||||
| 4470 | "Ranges are only for loads, calls and invokes!", &I)do { if (!(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I))) { CheckFailed("Ranges are only for loads, calls and invokes!" , &I); return; } } while (false); | ||||
| 4471 | visitRangeMetadata(I, Range, I.getType()); | ||||
| 4472 | } | ||||
| 4473 | |||||
| 4474 | if (I.getMetadata(LLVMContext::MD_nonnull)) { | ||||
| 4475 | Assert(I.getType()->isPointerTy(), "nonnull applies only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false) | ||||
| 4476 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false); | ||||
| 4477 | Assert(isa<LoadInst>(I),do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
| 4478 | "nonnull applies only to load instructions, use attributes"do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
| 4479 | " for calls or invokes",do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
| 4480 | &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false); | ||||
| 4481 | } | ||||
| 4482 | |||||
| 4483 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable)) | ||||
| 4484 | visitDereferenceableMetadata(I, MD); | ||||
| 4485 | |||||
| 4486 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) | ||||
| 4487 | visitDereferenceableMetadata(I, MD); | ||||
| 4488 | |||||
| 4489 | if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) | ||||
| 4490 | TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); | ||||
| 4491 | |||||
| 4492 | if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { | ||||
| 4493 | Assert(I.getType()->isPointerTy(), "align applies only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false) | ||||
| 4494 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false); | ||||
| 4495 | Assert(isa<LoadInst>(I), "align applies only to load instructions, "do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false) | ||||
| 4496 | "use attributes for calls or invokes", &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false); | ||||
| 4497 | Assert(AlignMD->getNumOperands() == 1, "align takes one operand!", &I)do { if (!(AlignMD->getNumOperands() == 1)) { CheckFailed( "align takes one operand!", &I); return; } } while (false ); | ||||
| 4498 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(AlignMD->getOperand(0)); | ||||
| 4499 | Assert(CI && CI->getType()->isIntegerTy(64),do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("align metadata value must be an i64!", & I); return; } } while (false) | ||||
| 4500 | "align metadata value must be an i64!", &I)do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("align metadata value must be an i64!", & I); return; } } while (false); | ||||
| 4501 | uint64_t Align = CI->getZExtValue(); | ||||
| 4502 | Assert(isPowerOf2_64(Align),do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false) | ||||
| 4503 | "align metadata value must be a power of 2!", &I)do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false); | ||||
| 4504 | Assert(Align <= Value::MaximumAlignment,do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false) | ||||
| 4505 | "alignment is larger that implementation defined limit", &I)do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false); | ||||
| 4506 | } | ||||
| 4507 | |||||
| 4508 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_prof)) | ||||
| 4509 | visitProfMetadata(I, MD); | ||||
| 4510 | |||||
| 4511 | if (MDNode *Annotation = I.getMetadata(LLVMContext::MD_annotation)) | ||||
| 4512 | visitAnnotationMetadata(Annotation); | ||||
| 4513 | |||||
| 4514 | if (MDNode *N = I.getDebugLoc().getAsMDNode()) { | ||||
| 4515 | AssertDI(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N)do { if (!(isa<DILocation>(N))) { DebugInfoCheckFailed( "invalid !dbg metadata attachment", &I, N); return; } } while (false); | ||||
| 4516 | visitMDNode(*N, AreDebugLocsAllowed::Yes); | ||||
| 4517 | } | ||||
| 4518 | |||||
| 4519 | if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { | ||||
| 4520 | verifyFragmentExpression(*DII); | ||||
| 4521 | verifyNotEntryValue(*DII); | ||||
| 4522 | } | ||||
| 4523 | |||||
| 4524 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
| 4525 | I.getAllMetadata(MDs); | ||||
| 4526 | for (auto Attachment : MDs) { | ||||
| 4527 | unsigned Kind = Attachment.first; | ||||
| 4528 | auto AllowLocs = | ||||
| 4529 | (Kind == LLVMContext::MD_dbg || Kind == LLVMContext::MD_loop) | ||||
| 4530 | ? AreDebugLocsAllowed::Yes | ||||
| 4531 | : AreDebugLocsAllowed::No; | ||||
| 4532 | visitMDNode(*Attachment.second, AllowLocs); | ||||
| 4533 | } | ||||
| 4534 | |||||
| 4535 | InstsInThisBlock.insert(&I); | ||||
| 4536 | } | ||||
| 4537 | |||||
| 4538 | /// Allow intrinsics to be verified in different ways. | ||||
| 4539 | void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { | ||||
| 4540 | Function *IF = Call.getCalledFunction(); | ||||
| 4541 | Assert(IF->isDeclaration(), "Intrinsic functions should never be defined!",do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false) | ||||
| 4542 | IF)do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false); | ||||
| 4543 | |||||
| 4544 | // Verify that the intrinsic prototype lines up with what the .td files | ||||
| 4545 | // describe. | ||||
| 4546 | FunctionType *IFTy = IF->getFunctionType(); | ||||
| 4547 | bool IsVarArg = IFTy->isVarArg(); | ||||
| 4548 | |||||
| 4549 | SmallVector<Intrinsic::IITDescriptor, 8> Table; | ||||
| 4550 | getIntrinsicInfoTableEntries(ID, Table); | ||||
| 4551 | ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; | ||||
| 4552 | |||||
| 4553 | // Walk the descriptors to extract overloaded types. | ||||
| 4554 | SmallVector<Type *, 4> ArgTys; | ||||
| 4555 | Intrinsic::MatchIntrinsicTypesResult Res = | ||||
| 4556 | Intrinsic::matchIntrinsicSignature(IFTy, TableRef, ArgTys); | ||||
| 4557 | Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false) | ||||
| 4558 | "Intrinsic has incorrect return type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false); | ||||
| 4559 | Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false) | ||||
| 4560 | "Intrinsic has incorrect argument type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false); | ||||
| 4561 | |||||
| 4562 | // Verify if the intrinsic call matches the vararg property. | ||||
| 4563 | if (IsVarArg) | ||||
| 4564 | Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false) | ||||
| 4565 | "Intrinsic was not defined with variable arguments!", IF)do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false); | ||||
| 4566 | else | ||||
| 4567 | Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false) | ||||
| 4568 | "Callsite was not defined with variable arguments!", IF)do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false); | ||||
| 4569 | |||||
| 4570 | // All descriptors should be absorbed by now. | ||||
| 4571 | Assert(TableRef.empty(), "Intrinsic has too few arguments!", IF)do { if (!(TableRef.empty())) { CheckFailed("Intrinsic has too few arguments!" , IF); return; } } while (false); | ||||
| 4572 | |||||
| 4573 | // Now that we have the intrinsic ID and the actual argument types (and we | ||||
| 4574 | // know they are legal for the intrinsic!) get the intrinsic name through the | ||||
| 4575 | // usual means. This allows us to verify the mangling of argument types into | ||||
| 4576 | // the name. | ||||
| 4577 | const std::string ExpectedName = | ||||
| 4578 | Intrinsic::getName(ID, ArgTys, IF->getParent(), IFTy); | ||||
| 4579 | Assert(ExpectedName == IF->getName(),do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 4580 | "Intrinsic name not mangled correctly for type arguments! "do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 4581 | "Should be: " +do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 4582 | ExpectedName,do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 4583 | IF)do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false); | ||||
| 4584 | |||||
| 4585 | // If the intrinsic takes MDNode arguments, verify that they are either global | ||||
| 4586 | // or are local to *this* function. | ||||
| 4587 | for (Value *V : Call.args()) { | ||||
| 4588 | if (auto *MD = dyn_cast<MetadataAsValue>(V)) | ||||
| 4589 | visitMetadataAsValue(*MD, Call.getCaller()); | ||||
| 4590 | if (auto *Const = dyn_cast<Constant>(V)) | ||||
| 4591 | Assert(!Const->getType()->isX86_AMXTy(),do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false) | ||||
| 4592 | "const x86_amx is not allowed in argument!")do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false); | ||||
| 4593 | } | ||||
| 4594 | |||||
| 4595 | switch (ID) { | ||||
| 4596 | default: | ||||
| 4597 | break; | ||||
| 4598 | case Intrinsic::assume: { | ||||
| 4599 | for (auto &Elem : Call.bundle_op_infos()) { | ||||
| 4600 | Assert(Elem.Tag->getKey() == "ignore" ||do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" ); return; } } while (false) | ||||
| 4601 | Attribute::isExistingAttribute(Elem.Tag->getKey()),do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" ); return; } } while (false) | ||||
| 4602 | "tags must be valid attribute names")do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" ); return; } } while (false); | ||||
| 4603 | Attribute::AttrKind Kind = | ||||
| 4604 | Attribute::getAttrKindFromName(Elem.Tag->getKey()); | ||||
| 4605 | unsigned ArgCount = Elem.End - Elem.Begin; | ||||
| 4606 | if (Kind == Attribute::Alignment) { | ||||
| 4607 | Assert(ArgCount <= 3 && ArgCount >= 2,do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments"); return ; } } while (false) | ||||
| 4608 | "alignment assumptions should have 2 or 3 arguments")do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments"); return ; } } while (false); | ||||
| 4609 | Assert(Call.getOperand(Elem.Begin)->getType()->isPointerTy(),do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer"); return ; } } while (false) | ||||
| 4610 | "first argument should be a pointer")do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer"); return ; } } while (false); | ||||
| 4611 | Assert(Call.getOperand(Elem.Begin + 1)->getType()->isIntegerTy(),do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" ); return; } } while (false) | ||||
| 4612 | "second argument should be an integer")do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" ); return; } } while (false); | ||||
| 4613 | if (ArgCount == 3) | ||||
| 4614 | Assert(Call.getOperand(Elem.Begin + 2)->getType()->isIntegerTy(),do { if (!(Call.getOperand(Elem.Begin + 2)->getType()-> isIntegerTy())) { CheckFailed("third argument should be an integer if present" ); return; } } while (false) | ||||
| 4615 | "third argument should be an integer if present")do { if (!(Call.getOperand(Elem.Begin + 2)->getType()-> isIntegerTy())) { CheckFailed("third argument should be an integer if present" ); return; } } while (false); | ||||
| 4616 | return; | ||||
| 4617 | } | ||||
| 4618 | Assert(ArgCount <= 2, "to many arguments")do { if (!(ArgCount <= 2)) { CheckFailed("to many arguments" ); return; } } while (false); | ||||
| 4619 | if (Kind == Attribute::None) | ||||
| 4620 | break; | ||||
| 4621 | if (Attribute::isIntAttrKind(Kind)) { | ||||
| 4622 | Assert(ArgCount == 2, "this attribute should have 2 arguments")do { if (!(ArgCount == 2)) { CheckFailed("this attribute should have 2 arguments" ); return; } } while (false); | ||||
| 4623 | Assert(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)),do { if (!(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)))) { CheckFailed("the second argument should be a constant integral value" ); return; } } while (false) | ||||
| 4624 | "the second argument should be a constant integral value")do { if (!(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)))) { CheckFailed("the second argument should be a constant integral value" ); return; } } while (false); | ||||
| 4625 | } else if (Attribute::canUseAsParamAttr(Kind)) { | ||||
| 4626 | Assert((ArgCount) == 1, "this attribute should have one argument")do { if (!((ArgCount) == 1)) { CheckFailed("this attribute should have one argument" ); return; } } while (false); | ||||
| 4627 | } else if (Attribute::canUseAsFnAttr(Kind)) { | ||||
| 4628 | Assert((ArgCount) == 0, "this attribute has no argument")do { if (!((ArgCount) == 0)) { CheckFailed("this attribute has no argument" ); return; } } while (false); | ||||
| 4629 | } | ||||
| 4630 | } | ||||
| 4631 | break; | ||||
| 4632 | } | ||||
| 4633 | case Intrinsic::coro_id: { | ||||
| 4634 | auto *InfoArg = Call.getArgOperand(3)->stripPointerCasts(); | ||||
| 4635 | if (isa<ConstantPointerNull>(InfoArg)) | ||||
| 4636 | break; | ||||
| 4637 | auto *GV = dyn_cast<GlobalVariable>(InfoArg); | ||||
| 4638 | Assert(GV && GV->isConstant() && GV->hasDefinitiveInitializer(),do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false) | ||||
| 4639 | "info argument of llvm.coro.id must refer to an initialized "do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false) | ||||
| 4640 | "constant")do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false); | ||||
| 4641 | Constant *Init = GV->getInitializer(); | ||||
| 4642 | Assert(isa<ConstantStruct>(Init) || isa<ConstantArray>(Init),do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false) | ||||
| 4643 | "info argument of llvm.coro.id must refer to either a struct or "do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false) | ||||
| 4644 | "an array")do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false); | ||||
| 4645 | break; | ||||
| 4646 | } | ||||
| 4647 | #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ | ||||
| 4648 | case Intrinsic::INTRINSIC: | ||||
| 4649 | #include "llvm/IR/ConstrainedOps.def" | ||||
| 4650 | visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(Call)); | ||||
| 4651 | break; | ||||
| 4652 | case Intrinsic::dbg_declare: // llvm.dbg.declare | ||||
| 4653 | Assert(isa<MetadataAsValue>(Call.getArgOperand(0)),do { if (!(isa<MetadataAsValue>(Call.getArgOperand(0))) ) { CheckFailed("invalid llvm.dbg.declare intrinsic call 1", Call ); return; } } while (false) | ||||
| 4654 | "invalid llvm.dbg.declare intrinsic call 1", Call)do { if (!(isa<MetadataAsValue>(Call.getArgOperand(0))) ) { CheckFailed("invalid llvm.dbg.declare intrinsic call 1", Call ); return; } } while (false); | ||||
| 4655 | visitDbgIntrinsic("declare", cast<DbgVariableIntrinsic>(Call)); | ||||
| 4656 | break; | ||||
| 4657 | case Intrinsic::dbg_addr: // llvm.dbg.addr | ||||
| 4658 | visitDbgIntrinsic("addr", cast<DbgVariableIntrinsic>(Call)); | ||||
| 4659 | break; | ||||
| 4660 | case Intrinsic::dbg_value: // llvm.dbg.value | ||||
| 4661 | visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call)); | ||||
| 4662 | break; | ||||
| 4663 | case Intrinsic::dbg_label: // llvm.dbg.label | ||||
| 4664 | visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call)); | ||||
| 4665 | break; | ||||
| 4666 | case Intrinsic::memcpy: | ||||
| 4667 | case Intrinsic::memcpy_inline: | ||||
| 4668 | case Intrinsic::memmove: | ||||
| 4669 | case Intrinsic::memset: { | ||||
| 4670 | const auto *MI = cast<MemIntrinsic>(&Call); | ||||
| 4671 | auto IsValidAlignment = [&](unsigned Alignment) -> bool { | ||||
| 4672 | return Alignment == 0 || isPowerOf2_32(Alignment); | ||||
| 4673 | }; | ||||
| 4674 | Assert(IsValidAlignment(MI->getDestAlignment()),do { if (!(IsValidAlignment(MI->getDestAlignment()))) { CheckFailed ("alignment of arg 0 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
| 4675 | "alignment of arg 0 of memory intrinsic must be 0 or a power of 2",do { if (!(IsValidAlignment(MI->getDestAlignment()))) { CheckFailed ("alignment of arg 0 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
| 4676 | Call)do { if (!(IsValidAlignment(MI->getDestAlignment()))) { CheckFailed ("alignment of arg 0 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false); | ||||
| 4677 | if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) { | ||||
| 4678 | Assert(IsValidAlignment(MTI->getSourceAlignment()),do { if (!(IsValidAlignment(MTI->getSourceAlignment()))) { CheckFailed("alignment of arg 1 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
| 4679 | "alignment of arg 1 of memory intrinsic must be 0 or a power of 2",do { if (!(IsValidAlignment(MTI->getSourceAlignment()))) { CheckFailed("alignment of arg 1 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false) | ||||
| 4680 | Call)do { if (!(IsValidAlignment(MTI->getSourceAlignment()))) { CheckFailed("alignment of arg 1 of memory intrinsic must be 0 or a power of 2" , Call); return; } } while (false); | ||||
| 4681 | } | ||||
| 4682 | |||||
| 4683 | break; | ||||
| 4684 | } | ||||
| 4685 | case Intrinsic::memcpy_element_unordered_atomic: | ||||
| 4686 | case Intrinsic::memmove_element_unordered_atomic: | ||||
| 4687 | case Intrinsic::memset_element_unordered_atomic: { | ||||
| 4688 | const auto *AMI = cast<AtomicMemIntrinsic>(&Call); | ||||
| 4689 | |||||
| 4690 | ConstantInt *ElementSizeCI = | ||||
| 4691 | cast<ConstantInt>(AMI->getRawElementSizeInBytes()); | ||||
| 4692 | const APInt &ElementSizeVal = ElementSizeCI->getValue(); | ||||
| 4693 | Assert(ElementSizeVal.isPowerOf2(),do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
| 4694 | "element size of the element-wise atomic memory intrinsic "do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
| 4695 | "must be a power of 2",do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
| 4696 | Call)do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false); | ||||
| 4697 | |||||
| 4698 | auto IsValidAlignment = [&](uint64_t Alignment) { | ||||
| 4699 | return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment); | ||||
| 4700 | }; | ||||
| 4701 | uint64_t DstAlignment = AMI->getDestAlignment(); | ||||
| 4702 | Assert(IsValidAlignment(DstAlignment),do { if (!(IsValidAlignment(DstAlignment))) { CheckFailed("incorrect alignment of the destination argument" , Call); return; } } while (false) | ||||
| 4703 | "incorrect alignment of the destination argument", Call)do { if (!(IsValidAlignment(DstAlignment))) { CheckFailed("incorrect alignment of the destination argument" , Call); return; } } while (false); | ||||
| 4704 | if (const auto *AMT = dyn_cast<AtomicMemTransferInst>(AMI)) { | ||||
| 4705 | uint64_t SrcAlignment = AMT->getSourceAlignment(); | ||||
| 4706 | Assert(IsValidAlignment(SrcAlignment),do { if (!(IsValidAlignment(SrcAlignment))) { CheckFailed("incorrect alignment of the source argument" , Call); return; } } while (false) | ||||
| 4707 | "incorrect alignment of the source argument", Call)do { if (!(IsValidAlignment(SrcAlignment))) { CheckFailed("incorrect alignment of the source argument" , Call); return; } } while (false); | ||||
| 4708 | } | ||||
| 4709 | break; | ||||
| 4710 | } | ||||
| 4711 | case Intrinsic::call_preallocated_setup: { | ||||
| 4712 | auto *NumArgs = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
| 4713 | Assert(NumArgs != nullptr,do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false) | ||||
| 4714 | "llvm.call.preallocated.setup argument must be a constant")do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false); | ||||
| 4715 | bool FoundCall = false; | ||||
| 4716 | for (User *U : Call.users()) { | ||||
| 4717 | auto *UseCall = dyn_cast<CallBase>(U); | ||||
| 4718 | Assert(UseCall != nullptr,do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false) | ||||
| 4719 | "Uses of llvm.call.preallocated.setup must be calls")do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false); | ||||
| 4720 | const Function *Fn = UseCall->getCalledFunction(); | ||||
| 4721 | if (Fn && Fn->getIntrinsicID() == Intrinsic::call_preallocated_arg) { | ||||
| 4722 | auto *AllocArgIndex = dyn_cast<ConstantInt>(UseCall->getArgOperand(1)); | ||||
| 4723 | Assert(AllocArgIndex != nullptr,do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false) | ||||
| 4724 | "llvm.call.preallocated.alloc arg index must be a constant")do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false); | ||||
| 4725 | auto AllocArgIndexInt = AllocArgIndex->getValue(); | ||||
| 4726 | Assert(AllocArgIndexInt.sge(0) &&do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 4727 | AllocArgIndexInt.slt(NumArgs->getValue()),do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 4728 | "llvm.call.preallocated.alloc arg index must be between 0 and "do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 4729 | "corresponding "do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 4730 | "llvm.call.preallocated.setup's argument count")do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false); | ||||
| 4731 | } else if (Fn && Fn->getIntrinsicID() == | ||||
| 4732 | Intrinsic::call_preallocated_teardown) { | ||||
| 4733 | // nothing to do | ||||
| 4734 | } else { | ||||
| 4735 | Assert(!FoundCall, "Can have at most one call corresponding to a "do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
| 4736 | "llvm.call.preallocated.setup")do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
| 4737 | FoundCall = true; | ||||
| 4738 | size_t NumPreallocatedArgs = 0; | ||||
| 4739 | for (unsigned i = 0; i < UseCall->getNumArgOperands(); i++) { | ||||
| 4740 | if (UseCall->paramHasAttr(i, Attribute::Preallocated)) { | ||||
| 4741 | ++NumPreallocatedArgs; | ||||
| 4742 | } | ||||
| 4743 | } | ||||
| 4744 | Assert(NumPreallocatedArgs != 0,do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
| 4745 | "cannot use preallocated intrinsics on a call without "do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
| 4746 | "preallocated arguments")do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false); | ||||
| 4747 | Assert(NumArgs->equalsInt(NumPreallocatedArgs),do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 4748 | "llvm.call.preallocated.setup arg size must be equal to number "do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 4749 | "of preallocated arguments "do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 4750 | "at call site",do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 4751 | Call, *UseCall)do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false); | ||||
| 4752 | // getOperandBundle() cannot be called if more than one of the operand | ||||
| 4753 | // bundle exists. There is already a check elsewhere for this, so skip | ||||
| 4754 | // here if we see more than one. | ||||
| 4755 | if (UseCall->countOperandBundlesOfType(LLVMContext::OB_preallocated) > | ||||
| 4756 | 1) { | ||||
| 4757 | return; | ||||
| 4758 | } | ||||
| 4759 | auto PreallocatedBundle = | ||||
| 4760 | UseCall->getOperandBundle(LLVMContext::OB_preallocated); | ||||
| 4761 | Assert(PreallocatedBundle,do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
| 4762 | "Use of llvm.call.preallocated.setup outside intrinsics "do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
| 4763 | "must be in \"preallocated\" operand bundle")do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false); | ||||
| 4764 | Assert(PreallocatedBundle->Inputs.front().get() == &Call,do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
| 4765 | "preallocated bundle must have token from corresponding "do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
| 4766 | "llvm.call.preallocated.setup")do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
| 4767 | } | ||||
| 4768 | } | ||||
| 4769 | break; | ||||
| 4770 | } | ||||
| 4771 | case Intrinsic::call_preallocated_arg: { | ||||
| 4772 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
| 4773 | Assert(Token && Token->getCalledFunction()->getIntrinsicID() ==do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 4774 | Intrinsic::call_preallocated_setup,do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 4775 | "llvm.call.preallocated.arg token argument must be a "do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 4776 | "llvm.call.preallocated.setup")do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false); | ||||
| 4777 | Assert(Call.hasFnAttr(Attribute::Preallocated),do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false) | ||||
| 4778 | "llvm.call.preallocated.arg must be called with a \"preallocated\" "do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false) | ||||
| 4779 | "call site attribute")do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false); | ||||
| 4780 | break; | ||||
| 4781 | } | ||||
| 4782 | case Intrinsic::call_preallocated_teardown: { | ||||
| 4783 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
| 4784 | Assert(Token && Token->getCalledFunction()->getIntrinsicID() ==do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 4785 | Intrinsic::call_preallocated_setup,do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 4786 | "llvm.call.preallocated.teardown token argument must be a "do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 4787 | "llvm.call.preallocated.setup")do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false); | ||||
| 4788 | break; | ||||
| 4789 | } | ||||
| 4790 | case Intrinsic::gcroot: | ||||
| 4791 | case Intrinsic::gcwrite: | ||||
| 4792 | case Intrinsic::gcread: | ||||
| 4793 | if (ID == Intrinsic::gcroot) { | ||||
| 4794 | AllocaInst *AI = | ||||
| 4795 | dyn_cast<AllocaInst>(Call.getArgOperand(0)->stripPointerCasts()); | ||||
| 4796 | Assert(AI, "llvm.gcroot parameter #1 must be an alloca.", Call)do { if (!(AI)) { CheckFailed("llvm.gcroot parameter #1 must be an alloca." , Call); return; } } while (false); | ||||
| 4797 | Assert(isa<Constant>(Call.getArgOperand(1)),do { if (!(isa<Constant>(Call.getArgOperand(1)))) { CheckFailed ("llvm.gcroot parameter #2 must be a constant.", Call); return ; } } while (false) | ||||
| 4798 | "llvm.gcroot parameter #2 must be a constant.", Call)do { if (!(isa<Constant>(Call.getArgOperand(1)))) { CheckFailed ("llvm.gcroot parameter #2 must be a constant.", Call); return ; } } while (false); | ||||
| 4799 | if (!AI->getAllocatedType()->isPointerTy()) { | ||||
| 4800 | Assert(!isa<ConstantPointerNull>(Call.getArgOperand(1)),do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
| 4801 | "llvm.gcroot parameter #1 must either be a pointer alloca, "do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
| 4802 | "or argument #2 must be a non-null constant.",do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
| 4803 | Call)do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false); | ||||
| 4804 | } | ||||
| 4805 | } | ||||
| 4806 | |||||
| 4807 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
| 4808 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
| 4809 | break; | ||||
| 4810 | case Intrinsic::init_trampoline: | ||||
| 4811 | Assert(isa<Function>(Call.getArgOperand(1)->stripPointerCasts()),do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false) | ||||
| 4812 | "llvm.init_trampoline parameter #2 must resolve to a function.",do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false) | ||||
| 4813 | Call)do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false); | ||||
| 4814 | break; | ||||
| 4815 | case Intrinsic::prefetch: | ||||
| 4816 | Assert(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2 &&do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2 && cast<ConstantInt>(Call .getArgOperand(2))->getZExtValue() < 4)) { CheckFailed( "invalid arguments to llvm.prefetch", Call); return; } } while (false) | ||||
| 4817 | cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4,do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2 && cast<ConstantInt>(Call .getArgOperand(2))->getZExtValue() < 4)) { CheckFailed( "invalid arguments to llvm.prefetch", Call); return; } } while (false) | ||||
| 4818 | "invalid arguments to llvm.prefetch", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2 && cast<ConstantInt>(Call .getArgOperand(2))->getZExtValue() < 4)) { CheckFailed( "invalid arguments to llvm.prefetch", Call); return; } } while (false); | ||||
| 4819 | break; | ||||
| 4820 | case Intrinsic::stackprotector: | ||||
| 4821 | Assert(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts()),do { if (!(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.stackprotector parameter #2 must resolve to an alloca." , Call); return; } } while (false) | ||||
| 4822 | "llvm.stackprotector parameter #2 must resolve to an alloca.", Call)do { if (!(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.stackprotector parameter #2 must resolve to an alloca." , Call); return; } } while (false); | ||||
| 4823 | break; | ||||
| 4824 | case Intrinsic::localescape: { | ||||
| 4825 | BasicBlock *BB = Call.getParent(); | ||||
| 4826 | Assert(BB == &BB->getParent()->front(),do { if (!(BB == &BB->getParent()->front())) { CheckFailed ("llvm.localescape used outside of entry block", Call); return ; } } while (false) | ||||
| 4827 | "llvm.localescape used outside of entry block", Call)do { if (!(BB == &BB->getParent()->front())) { CheckFailed ("llvm.localescape used outside of entry block", Call); return ; } } while (false); | ||||
| 4828 | Assert(!SawFrameEscape,do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false) | ||||
| 4829 | "multiple calls to llvm.localescape in one function", Call)do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false); | ||||
| 4830 | for (Value *Arg : Call.args()) { | ||||
| 4831 | if (isa<ConstantPointerNull>(Arg)) | ||||
| 4832 | continue; // Null values are allowed as placeholders. | ||||
| 4833 | auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts()); | ||||
| 4834 | Assert(AI && AI->isStaticAlloca(),do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false) | ||||
| 4835 | "llvm.localescape only accepts static allocas", Call)do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false); | ||||
| 4836 | } | ||||
| 4837 | FrameEscapeInfo[BB->getParent()].first = Call.getNumArgOperands(); | ||||
| 4838 | SawFrameEscape = true; | ||||
| 4839 | break; | ||||
| 4840 | } | ||||
| 4841 | case Intrinsic::localrecover: { | ||||
| 4842 | Value *FnArg = Call.getArgOperand(0)->stripPointerCasts(); | ||||
| 4843 | Function *Fn = dyn_cast<Function>(FnArg); | ||||
| 4844 | Assert(Fn && !Fn->isDeclaration(),do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
| 4845 | "llvm.localrecover first "do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
| 4846 | "argument must be function defined in this module",do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
| 4847 | Call)do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false); | ||||
| 4848 | auto *IdxArg = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 4849 | auto &Entry = FrameEscapeInfo[Fn]; | ||||
| 4850 | Entry.second = unsigned( | ||||
| 4851 | std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1)); | ||||
| 4852 | break; | ||||
| 4853 | } | ||||
| 4854 | |||||
| 4855 | case Intrinsic::experimental_gc_statepoint: | ||||
| 4856 | if (auto *CI = dyn_cast<CallInst>(&Call)) | ||||
| 4857 | Assert(!CI->isInlineAsm(),do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false) | ||||
| 4858 | "gc.statepoint support for inline assembly unimplemented", CI)do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false); | ||||
| 4859 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
| 4860 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
| 4861 | |||||
| 4862 | verifyStatepoint(Call); | ||||
| 4863 | break; | ||||
| 4864 | case Intrinsic::experimental_gc_result: { | ||||
| 4865 | Assert(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
| 4866 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
| 4867 | // Are we tied to a statepoint properly? | ||||
| 4868 | const auto *StatepointCall = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
| 4869 | const Function *StatepointFn = | ||||
| 4870 | StatepointCall ? StatepointCall->getCalledFunction() : nullptr; | ||||
| 4871 | Assert(StatepointFn && StatepointFn->isDeclaration() &&do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 4872 | StatepointFn->getIntrinsicID() ==do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 4873 | Intrinsic::experimental_gc_statepoint,do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 4874 | "gc.result operand #1 must be from a statepoint", Call,do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 4875 | Call.getArgOperand(0))do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false); | ||||
| 4876 | |||||
| 4877 | // Assert that result type matches wrapped callee. | ||||
| 4878 | const Value *Target = StatepointCall->getArgOperand(2); | ||||
| 4879 | auto *PT = cast<PointerType>(Target->getType()); | ||||
| 4880 | auto *TargetFuncType = cast<FunctionType>(PT->getElementType()); | ||||
| 4881 | Assert(Call.getType() == TargetFuncType->getReturnType(),do { if (!(Call.getType() == TargetFuncType->getReturnType ())) { CheckFailed("gc.result result type does not match wrapped callee" , Call); return; } } while (false) | ||||
| 4882 | "gc.result result type does not match wrapped callee", Call)do { if (!(Call.getType() == TargetFuncType->getReturnType ())) { CheckFailed("gc.result result type does not match wrapped callee" , Call); return; } } while (false); | ||||
| 4883 | break; | ||||
| 4884 | } | ||||
| 4885 | case Intrinsic::experimental_gc_relocate: { | ||||
| 4886 | Assert(Call.getNumArgOperands() == 3, "wrong number of arguments", Call)do { if (!(Call.getNumArgOperands() == 3)) { CheckFailed("wrong number of arguments" , Call); return; } } while (false); | ||||
| 4887 | |||||
| 4888 | Assert(isa<PointerType>(Call.getType()->getScalarType()),do { if (!(isa<PointerType>(Call.getType()->getScalarType ()))) { CheckFailed("gc.relocate must return a pointer or a vector of pointers" , Call); return; } } while (false) | ||||
| 4889 | "gc.relocate must return a pointer or a vector of pointers", Call)do { if (!(isa<PointerType>(Call.getType()->getScalarType ()))) { CheckFailed("gc.relocate must return a pointer or a vector of pointers" , Call); return; } } while (false); | ||||
| 4890 | |||||
| 4891 | // Check that this relocate is correctly tied to the statepoint | ||||
| 4892 | |||||
| 4893 | // This is case for relocate on the unwinding path of an invoke statepoint | ||||
| 4894 | if (LandingPadInst *LandingPad = | ||||
| 4895 | dyn_cast<LandingPadInst>(Call.getArgOperand(0))) { | ||||
| 4896 | |||||
| 4897 | const BasicBlock *InvokeBB = | ||||
| 4898 | LandingPad->getParent()->getUniquePredecessor(); | ||||
| 4899 | |||||
| 4900 | // Landingpad relocates should have only one predecessor with invoke | ||||
| 4901 | // statepoint terminator | ||||
| 4902 | Assert(InvokeBB, "safepoints should have unique landingpads",do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false) | ||||
| 4903 | LandingPad->getParent())do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false); | ||||
| 4904 | Assert(InvokeBB->getTerminator(), "safepoint block should be well formed",do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false) | ||||
| 4905 | InvokeBB)do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false); | ||||
| 4906 | Assert(isa<GCStatepointInst>(InvokeBB->getTerminator()),do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false) | ||||
| 4907 | "gc relocate should be linked to a statepoint", InvokeBB)do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false); | ||||
| 4908 | } else { | ||||
| 4909 | // In all other cases relocate should be tied to the statepoint directly. | ||||
| 4910 | // This covers relocates on a normal return path of invoke statepoint and | ||||
| 4911 | // relocates of a call statepoint. | ||||
| 4912 | auto Token = Call.getArgOperand(0); | ||||
| 4913 | Assert(isa<GCStatepointInst>(Token),do { if (!(isa<GCStatepointInst>(Token))) { CheckFailed ("gc relocate is incorrectly tied to the statepoint", Call, Token ); return; } } while (false) | ||||
| 4914 | "gc relocate is incorrectly tied to the statepoint", Call, Token)do { if (!(isa<GCStatepointInst>(Token))) { CheckFailed ("gc relocate is incorrectly tied to the statepoint", Call, Token ); return; } } while (false); | ||||
| 4915 | } | ||||
| 4916 | |||||
| 4917 | // Verify rest of the relocate arguments. | ||||
| 4918 | const CallBase &StatepointCall = | ||||
| 4919 | *cast<GCRelocateInst>(Call).getStatepoint(); | ||||
| 4920 | |||||
| 4921 | // Both the base and derived must be piped through the safepoint. | ||||
| 4922 | Value *Base = Call.getArgOperand(1); | ||||
| 4923 | Assert(isa<ConstantInt>(Base),do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false) | ||||
| 4924 | "gc.relocate operand #2 must be integer offset", Call)do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false); | ||||
| 4925 | |||||
| 4926 | Value *Derived = Call.getArgOperand(2); | ||||
| 4927 | Assert(isa<ConstantInt>(Derived),do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false) | ||||
| 4928 | "gc.relocate operand #3 must be integer offset", Call)do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false); | ||||
| 4929 | |||||
| 4930 | const uint64_t BaseIndex = cast<ConstantInt>(Base)->getZExtValue(); | ||||
| 4931 | const uint64_t DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue(); | ||||
| 4932 | |||||
| 4933 | // Check the bounds | ||||
| 4934 | if (auto Opt = StatepointCall.getOperandBundle(LLVMContext::OB_gc_live)) { | ||||
| 4935 | Assert(BaseIndex < Opt->Inputs.size(),do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false) | ||||
| 4936 | "gc.relocate: statepoint base index out of bounds", Call)do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false); | ||||
| 4937 | Assert(DerivedIndex < Opt->Inputs.size(),do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false) | ||||
| 4938 | "gc.relocate: statepoint derived index out of bounds", Call)do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false); | ||||
| 4939 | } | ||||
| 4940 | |||||
| 4941 | // Relocated value must be either a pointer type or vector-of-pointer type, | ||||
| 4942 | // but gc_relocate does not need to return the same pointer type as the | ||||
| 4943 | // relocated pointer. It can be casted to the correct type later if it's | ||||
| 4944 | // desired. However, they must have the same address space and 'vectorness' | ||||
| 4945 | GCRelocateInst &Relocate = cast<GCRelocateInst>(Call); | ||||
| 4946 | Assert(Relocate.getDerivedPtr()->getType()->isPtrOrPtrVectorTy(),do { if (!(Relocate.getDerivedPtr()->getType()->isPtrOrPtrVectorTy ())) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false) | ||||
| 4947 | "gc.relocate: relocated value must be a gc pointer", Call)do { if (!(Relocate.getDerivedPtr()->getType()->isPtrOrPtrVectorTy ())) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false); | ||||
| 4948 | |||||
| 4949 | auto ResultType = Call.getType(); | ||||
| 4950 | auto DerivedType = Relocate.getDerivedPtr()->getType(); | ||||
| 4951 | Assert(ResultType->isVectorTy() == DerivedType->isVectorTy(),do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false) | ||||
| 4952 | "gc.relocate: vector relocates to vector and pointer to pointer",do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false) | ||||
| 4953 | Call)do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false); | ||||
| 4954 | Assert(do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 4955 | ResultType->getPointerAddressSpace() ==do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 4956 | DerivedType->getPointerAddressSpace(),do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 4957 | "gc.relocate: relocating a pointer shouldn't change its address space",do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 4958 | Call)do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false); | ||||
| 4959 | break; | ||||
| 4960 | } | ||||
| 4961 | case Intrinsic::eh_exceptioncode: | ||||
| 4962 | case Intrinsic::eh_exceptionpointer: { | ||||
| 4963 | Assert(isa<CatchPadInst>(Call.getArgOperand(0)),do { if (!(isa<CatchPadInst>(Call.getArgOperand(0)))) { CheckFailed("eh.exceptionpointer argument must be a catchpad" , Call); return; } } while (false) | ||||
| 4964 | "eh.exceptionpointer argument must be a catchpad", Call)do { if (!(isa<CatchPadInst>(Call.getArgOperand(0)))) { CheckFailed("eh.exceptionpointer argument must be a catchpad" , Call); return; } } while (false); | ||||
| 4965 | break; | ||||
| 4966 | } | ||||
| 4967 | case Intrinsic::get_active_lane_mask: { | ||||
| 4968 | Assert(Call.getType()->isVectorTy(), "get_active_lane_mask: must return a "do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false) | ||||
| 4969 | "vector", Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false); | ||||
| 4970 | auto *ElemTy = Call.getType()->getScalarType(); | ||||
| 4971 | Assert(ElemTy->isIntegerTy(1), "get_active_lane_mask: element type is not "do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false) | ||||
| 4972 | "i1", Call)do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false); | ||||
| 4973 | break; | ||||
| 4974 | } | ||||
| 4975 | case Intrinsic::masked_load: { | ||||
| 4976 | Assert(Call.getType()->isVectorTy(), "masked_load: must return a vector",do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false) | ||||
| 4977 | Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false); | ||||
| 4978 | |||||
| 4979 | Value *Ptr = Call.getArgOperand(0); | ||||
| 4980 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
| 4981 | Value *Mask = Call.getArgOperand(2); | ||||
| 4982 | Value *PassThru = Call.getArgOperand(3); | ||||
| 4983 | Assert(Mask->getType()->isVectorTy(), "masked_load: mask must be vector",do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false) | ||||
| 4984 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false); | ||||
| 4985 | Assert(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false) | ||||
| 4986 | "masked_load: alignment must be a power of 2", Call)do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false); | ||||
| 4987 | |||||
| 4988 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
| 4989 | Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false) | ||||
| 4990 | "masked_load: return must match pointer type", Call)do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false); | ||||
| 4991 | Assert(PassThru->getType() == Call.getType(),do { if (!(PassThru->getType() == Call.getType())) { CheckFailed ("masked_load: pass through and return type must match", Call ); return; } } while (false) | ||||
| 4992 | "masked_load: pass through and return type must match", Call)do { if (!(PassThru->getType() == Call.getType())) { CheckFailed ("masked_load: pass through and return type must match", Call ); return; } } while (false); | ||||
| 4993 | Assert(cast<VectorType>(Mask->getType())->getElementCount() ==do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false) | ||||
| 4994 | cast<VectorType>(Call.getType())->getElementCount(),do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false) | ||||
| 4995 | "masked_load: vector mask must be same length as return", Call)do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false); | ||||
| 4996 | break; | ||||
| 4997 | } | ||||
| 4998 | case Intrinsic::masked_store: { | ||||
| 4999 | Value *Val = Call.getArgOperand(0); | ||||
| 5000 | Value *Ptr = Call.getArgOperand(1); | ||||
| 5001 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5002 | Value *Mask = Call.getArgOperand(3); | ||||
| 5003 | Assert(Mask->getType()->isVectorTy(), "masked_store: mask must be vector",do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false) | ||||
| 5004 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false); | ||||
| 5005 | Assert(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false) | ||||
| 5006 | "masked_store: alignment must be a power of 2", Call)do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false); | ||||
| 5007 | |||||
| 5008 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
| 5009 | Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false) | ||||
| 5010 | "masked_store: storee must match pointer type", Call)do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false); | ||||
| 5011 | Assert(cast<VectorType>(Mask->getType())->getElementCount() ==do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false) | ||||
| 5012 | cast<VectorType>(Val->getType())->getElementCount(),do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false) | ||||
| 5013 | "masked_store: vector mask must be same length as value", Call)do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false); | ||||
| 5014 | break; | ||||
| 5015 | } | ||||
| 5016 | |||||
| 5017 | case Intrinsic::masked_gather: { | ||||
| 5018 | const APInt &Alignment = | ||||
| 5019 | cast<ConstantInt>(Call.getArgOperand(1))->getValue(); | ||||
| 5020 | Assert(Alignment.isNullValue() || Alignment.isPowerOf2(),do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_gather: alignment must be 0 or a power of 2" , Call); return; } } while (false) | ||||
| 5021 | "masked_gather: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_gather: alignment must be 0 or a power of 2" , Call); return; } } while (false); | ||||
| 5022 | break; | ||||
| 5023 | } | ||||
| 5024 | case Intrinsic::masked_scatter: { | ||||
| 5025 | const APInt &Alignment = | ||||
| 5026 | cast<ConstantInt>(Call.getArgOperand(2))->getValue(); | ||||
| 5027 | Assert(Alignment.isNullValue() || Alignment.isPowerOf2(),do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_scatter: alignment must be 0 or a power of 2" , Call); return; } } while (false) | ||||
| 5028 | "masked_scatter: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isNullValue() || Alignment.isPowerOf2()) ) { CheckFailed("masked_scatter: alignment must be 0 or a power of 2" , Call); return; } } while (false); | ||||
| 5029 | break; | ||||
| 5030 | } | ||||
| 5031 | |||||
| 5032 | case Intrinsic::experimental_guard: { | ||||
| 5033 | Assert(isa<CallInst>(Call), "experimental_guard cannot be invoked", Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_guard cannot be invoked" , Call); return; } } while (false); | ||||
| 5034 | Assert(Call.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1,do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5035 | "experimental_guard must have exactly one "do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5036 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
| 5037 | break; | ||||
| 5038 | } | ||||
| 5039 | |||||
| 5040 | case Intrinsic::experimental_deoptimize: { | ||||
| 5041 | Assert(isa<CallInst>(Call), "experimental_deoptimize cannot be invoked",do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false) | ||||
| 5042 | Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false); | ||||
| 5043 | Assert(Call.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1,do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5044 | "experimental_deoptimize must have exactly one "do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5045 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
| 5046 | Assert(Call.getType() == Call.getFunction()->getReturnType(),do { if (!(Call.getType() == Call.getFunction()->getReturnType ())) { CheckFailed("experimental_deoptimize return type must match caller return type" ); return; } } while (false) | ||||
| 5047 | "experimental_deoptimize return type must match caller return type")do { if (!(Call.getType() == Call.getFunction()->getReturnType ())) { CheckFailed("experimental_deoptimize return type must match caller return type" ); return; } } while (false); | ||||
| 5048 | |||||
| 5049 | if (isa<CallInst>(Call)) { | ||||
| 5050 | auto *RI = dyn_cast<ReturnInst>(Call.getNextNode()); | ||||
| 5051 | Assert(RI,do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false) | ||||
| 5052 | "calls to experimental_deoptimize must be followed by a return")do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false); | ||||
| 5053 | |||||
| 5054 | if (!Call.getType()->isVoidTy() && RI) | ||||
| 5055 | Assert(RI->getReturnValue() == &Call,do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false) | ||||
| 5056 | "calls to experimental_deoptimize must be followed by a return "do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false) | ||||
| 5057 | "of the value computed by experimental_deoptimize")do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false); | ||||
| 5058 | } | ||||
| 5059 | |||||
| 5060 | break; | ||||
| 5061 | } | ||||
| 5062 | case Intrinsic::vector_reduce_and: | ||||
| 5063 | case Intrinsic::vector_reduce_or: | ||||
| 5064 | case Intrinsic::vector_reduce_xor: | ||||
| 5065 | case Intrinsic::vector_reduce_add: | ||||
| 5066 | case Intrinsic::vector_reduce_mul: | ||||
| 5067 | case Intrinsic::vector_reduce_smax: | ||||
| 5068 | case Intrinsic::vector_reduce_smin: | ||||
| 5069 | case Intrinsic::vector_reduce_umax: | ||||
| 5070 | case Intrinsic::vector_reduce_umin: { | ||||
| 5071 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
| 5072 | Assert(ArgTy->isIntOrIntVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
| 5073 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
| 5074 | break; | ||||
| 5075 | } | ||||
| 5076 | case Intrinsic::vector_reduce_fmax: | ||||
| 5077 | case Intrinsic::vector_reduce_fmin: { | ||||
| 5078 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
| 5079 | Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
| 5080 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
| 5081 | break; | ||||
| 5082 | } | ||||
| 5083 | case Intrinsic::vector_reduce_fadd: | ||||
| 5084 | case Intrinsic::vector_reduce_fmul: { | ||||
| 5085 | // Unlike the other reductions, the first argument is a start value. The | ||||
| 5086 | // second argument is the vector to be reduced. | ||||
| 5087 | Type *ArgTy = Call.getArgOperand(1)->getType(); | ||||
| 5088 | Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
| 5089 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
| 5090 | break; | ||||
| 5091 | } | ||||
| 5092 | case Intrinsic::smul_fix: | ||||
| 5093 | case Intrinsic::smul_fix_sat: | ||||
| 5094 | case Intrinsic::umul_fix: | ||||
| 5095 | case Intrinsic::umul_fix_sat: | ||||
| 5096 | case Intrinsic::sdiv_fix: | ||||
| 5097 | case Intrinsic::sdiv_fix_sat: | ||||
| 5098 | case Intrinsic::udiv_fix: | ||||
| 5099 | case Intrinsic::udiv_fix_sat: { | ||||
| 5100 | Value *Op1 = Call.getArgOperand(0); | ||||
| 5101 | Value *Op2 = Call.getArgOperand(1); | ||||
| 5102 | Assert(Op1->getType()->isIntOrIntVectorTy(),do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5103 | "first operand of [us][mul|div]_fix[_sat] must be an int type or "do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5104 | "vector of ints")do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false); | ||||
| 5105 | Assert(Op2->getType()->isIntOrIntVectorTy(),do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5106 | "second operand of [us][mul|div]_fix[_sat] must be an int type or "do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5107 | "vector of ints")do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false); | ||||
| 5108 | |||||
| 5109 | auto *Op3 = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5110 | Assert(Op3->getType()->getBitWidth() <= 32,do { if (!(Op3->getType()->getBitWidth() <= 32)) { CheckFailed ("third argument of [us][mul|div]_fix[_sat] must fit within 32 bits" ); return; } } while (false) | ||||
| 5111 | "third argument of [us][mul|div]_fix[_sat] must fit within 32 bits")do { if (!(Op3->getType()->getBitWidth() <= 32)) { CheckFailed ("third argument of [us][mul|div]_fix[_sat] must fit within 32 bits" ); return; } } while (false); | ||||
| 5112 | |||||
| 5113 | if (ID == Intrinsic::smul_fix || ID == Intrinsic::smul_fix_sat || | ||||
| 5114 | ID == Intrinsic::sdiv_fix || ID == Intrinsic::sdiv_fix_sat) { | ||||
| 5115 | Assert(do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
| 5116 | Op3->getZExtValue() < Op1->getType()->getScalarSizeInBits(),do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
| 5117 | "the scale of s[mul|div]_fix[_sat] must be less than the width of "do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
| 5118 | "the operands")do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false); | ||||
| 5119 | } else { | ||||
| 5120 | Assert(Op3->getZExtValue() <= Op1->getType()->getScalarSizeInBits(),do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false) | ||||
| 5121 | "the scale of u[mul|div]_fix[_sat] must be less than or equal "do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false) | ||||
| 5122 | "to the width of the operands")do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false); | ||||
| 5123 | } | ||||
| 5124 | break; | ||||
| 5125 | } | ||||
| 5126 | case Intrinsic::lround: | ||||
| 5127 | case Intrinsic::llround: | ||||
| 5128 | case Intrinsic::lrint: | ||||
| 5129 | case Intrinsic::llrint: { | ||||
| 5130 | Type *ValTy = Call.getArgOperand(0)->getType(); | ||||
| 5131 | Type *ResultTy = Call.getType(); | ||||
| 5132 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false) | ||||
| 5133 | "Intrinsic does not support vectors", &Call)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false); | ||||
| 5134 | break; | ||||
| 5135 | } | ||||
| 5136 | case Intrinsic::bswap: { | ||||
| 5137 | Type *Ty = Call.getType(); | ||||
| 5138 | unsigned Size = Ty->getScalarSizeInBits(); | ||||
| 5139 | Assert(Size % 16 == 0, "bswap must be an even number of bytes", &Call)do { if (!(Size % 16 == 0)) { CheckFailed("bswap must be an even number of bytes" , &Call); return; } } while (false); | ||||
| 5140 | break; | ||||
| 5141 | } | ||||
| 5142 | case Intrinsic::invariant_start: { | ||||
| 5143 | ConstantInt *InvariantSize = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
| 5144 | Assert(InvariantSize &&do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
| 5145 | (!InvariantSize->isNegative() || InvariantSize->isMinusOne()),do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
| 5146 | "invariant_start parameter must be -1, 0 or a positive number",do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
| 5147 | &Call)do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false); | ||||
| 5148 | break; | ||||
| 5149 | } | ||||
| 5150 | case Intrinsic::matrix_multiply: | ||||
| 5151 | case Intrinsic::matrix_transpose: | ||||
| 5152 | case Intrinsic::matrix_column_major_load: | ||||
| 5153 | case Intrinsic::matrix_column_major_store: { | ||||
| 5154 | Function *IF = Call.getCalledFunction(); | ||||
| 5155 | ConstantInt *Stride = nullptr; | ||||
| 5156 | ConstantInt *NumRows; | ||||
| 5157 | ConstantInt *NumColumns; | ||||
| 5158 | VectorType *ResultTy; | ||||
| 5159 | Type *Op0ElemTy = nullptr; | ||||
| 5160 | Type *Op1ElemTy = nullptr; | ||||
| 5161 | switch (ID) { | ||||
| 5162 | case Intrinsic::matrix_multiply: | ||||
| 5163 | NumRows = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5164 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
| 5165 | ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5166 | Op0ElemTy = | ||||
| 5167 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
| 5168 | Op1ElemTy = | ||||
| 5169 | cast<VectorType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
| 5170 | break; | ||||
| 5171 | case Intrinsic::matrix_transpose: | ||||
| 5172 | NumRows = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
| 5173 | NumColumns = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5174 | ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5175 | Op0ElemTy = | ||||
| 5176 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
| 5177 | break; | ||||
| 5178 | case Intrinsic::matrix_column_major_load: | ||||
| 5179 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(1)); | ||||
| 5180 | NumRows = cast<ConstantInt>(Call.getArgOperand(3)); | ||||
| 5181 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
| 5182 | ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5183 | Op0ElemTy = | ||||
| 5184 | cast<PointerType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
| 5185 | break; | ||||
| 5186 | case Intrinsic::matrix_column_major_store: | ||||
| 5187 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5188 | NumRows = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
| 5189 | NumColumns = cast<ConstantInt>(Call.getArgOperand(5)); | ||||
| 5190 | ResultTy = cast<VectorType>(Call.getArgOperand(0)->getType()); | ||||
| 5191 | Op0ElemTy = | ||||
| 5192 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
| 5193 | Op1ElemTy = | ||||
| 5194 | cast<PointerType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
| 5195 | break; | ||||
| 5196 | default: | ||||
| 5197 | llvm_unreachable("unexpected intrinsic")__builtin_unreachable(); | ||||
| 5198 | } | ||||
| 5199 | |||||
| 5200 | Assert(ResultTy->getElementType()->isIntegerTy() ||do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false) | ||||
| 5201 | ResultTy->getElementType()->isFloatingPointTy(),do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false) | ||||
| 5202 | "Result type must be an integer or floating-point type!", IF)do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false); | ||||
| 5203 | |||||
| 5204 | Assert(ResultTy->getElementType() == Op0ElemTy,do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
| 5205 | "Vector element type mismatch of the result and first operand "do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
| 5206 | "vector!", IF)do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false); | ||||
| 5207 | |||||
| 5208 | if (Op1ElemTy) | ||||
| 5209 | Assert(ResultTy->getElementType() == Op1ElemTy,do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
| 5210 | "Vector element type mismatch of the result and second operand "do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
| 5211 | "vector!", IF)do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false); | ||||
| 5212 | |||||
| 5213 | Assert(cast<FixedVectorType>(ResultTy)->getNumElements() ==do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false) | ||||
| 5214 | NumRows->getZExtValue() * NumColumns->getZExtValue(),do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false) | ||||
| 5215 | "Result of a matrix operation does not fit in the returned vector!")do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false); | ||||
| 5216 | |||||
| 5217 | if (Stride) | ||||
| 5218 | Assert(Stride->getZExtValue() >= NumRows->getZExtValue(),do { if (!(Stride->getZExtValue() >= NumRows->getZExtValue ())) { CheckFailed("Stride must be greater or equal than the number of rows!" , IF); return; } } while (false) | ||||
| 5219 | "Stride must be greater or equal than the number of rows!", IF)do { if (!(Stride->getZExtValue() >= NumRows->getZExtValue ())) { CheckFailed("Stride must be greater or equal than the number of rows!" , IF); return; } } while (false); | ||||
| 5220 | |||||
| 5221 | break; | ||||
| 5222 | } | ||||
| 5223 | case Intrinsic::experimental_stepvector: { | ||||
| 5224 | VectorType *VecTy = dyn_cast<VectorType>(Call.getType()); | ||||
| 5225 | Assert(VecTy && VecTy->getScalarType()->isIntegerTy() &&do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5226 | VecTy->getScalarSizeInBits() >= 8,do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5227 | "experimental_stepvector only supported for vectors of integers "do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5228 | "with a bitwidth of at least 8.",do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5229 | &Call)do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false); | ||||
| 5230 | break; | ||||
| 5231 | } | ||||
| 5232 | case Intrinsic::experimental_vector_insert: { | ||||
| 5233 | Value *Vec = Call.getArgOperand(0); | ||||
| 5234 | Value *SubVec = Call.getArgOperand(1); | ||||
| 5235 | Value *Idx = Call.getArgOperand(2); | ||||
| 5236 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
| 5237 | |||||
| 5238 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
| 5239 | VectorType *SubVecTy = cast<VectorType>(SubVec->getType()); | ||||
| 5240 | |||||
| 5241 | ElementCount VecEC = VecTy->getElementCount(); | ||||
| 5242 | ElementCount SubVecEC = SubVecTy->getElementCount(); | ||||
| 5243 | Assert(VecTy->getElementType() == SubVecTy->getElementType(),do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
| 5244 | "experimental_vector_insert parameters must have the same element "do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
| 5245 | "type.",do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
| 5246 | &Call)do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("experimental_vector_insert parameters must have the same element " "type.", &Call); return; } } while (false); | ||||
| 5247 | Assert(IdxN % SubVecEC.getKnownMinValue() == 0,do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_insert index must be a constant multiple of " "the subvector's known minimum vector length."); return; } } while (false) | ||||
| 5248 | "experimental_vector_insert index must be a constant multiple of "do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_insert index must be a constant multiple of " "the subvector's known minimum vector length."); return; } } while (false) | ||||
| 5249 | "the subvector's known minimum vector length.")do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_insert index must be a constant multiple of " "the subvector's known minimum vector length."); return; } } while (false); | ||||
| 5250 | |||||
| 5251 | // If this insertion is not the 'mixed' case where a fixed vector is | ||||
| 5252 | // inserted into a scalable vector, ensure that the insertion of the | ||||
| 5253 | // subvector does not overrun the parent vector. | ||||
| 5254 | if (VecEC.isScalable() == SubVecEC.isScalable()) { | ||||
| 5255 | Assert(do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
| 5256 | IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
| 5257 | IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
| 5258 | "subvector operand of experimental_vector_insert would overrun the "do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
| 5259 | "vector being inserted into.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of experimental_vector_insert would overrun the " "vector being inserted into."); return; } } while (false); | ||||
| 5260 | } | ||||
| 5261 | break; | ||||
| 5262 | } | ||||
| 5263 | case Intrinsic::experimental_vector_extract: { | ||||
| 5264 | Value *Vec = Call.getArgOperand(0); | ||||
| 5265 | Value *Idx = Call.getArgOperand(1); | ||||
| 5266 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
| 5267 | |||||
| 5268 | VectorType *ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5269 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
| 5270 | |||||
| 5271 | ElementCount VecEC = VecTy->getElementCount(); | ||||
| 5272 | ElementCount ResultEC = ResultTy->getElementCount(); | ||||
| 5273 | |||||
| 5274 | Assert(ResultTy->getElementType() == VecTy->getElementType(),do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
| 5275 | "experimental_vector_extract result must have the same element "do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
| 5276 | "type as the input vector.",do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
| 5277 | &Call)do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("experimental_vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false); | ||||
| 5278 | Assert(IdxN % ResultEC.getKnownMinValue() == 0,do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_extract index must be a constant multiple of " "the result type's known minimum vector length."); return; } } while (false) | ||||
| 5279 | "experimental_vector_extract index must be a constant multiple of "do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_extract index must be a constant multiple of " "the result type's known minimum vector length."); return; } } while (false) | ||||
| 5280 | "the result type's known minimum vector length.")do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("experimental_vector_extract index must be a constant multiple of " "the result type's known minimum vector length."); return; } } while (false); | ||||
| 5281 | |||||
| 5282 | // If this extraction is not the 'mixed' case where a fixed vector is is | ||||
| 5283 | // extracted from a scalable vector, ensure that the extraction does not | ||||
| 5284 | // overrun the parent vector. | ||||
| 5285 | if (VecEC.isScalable() == ResultEC.isScalable()) { | ||||
| 5286 | Assert(IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false) | ||||
| 5287 | IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false) | ||||
| 5288 | "experimental_vector_extract would overrun.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("experimental_vector_extract would overrun." ); return; } } while (false); | ||||
| 5289 | } | ||||
| 5290 | break; | ||||
| 5291 | } | ||||
| 5292 | case Intrinsic::experimental_noalias_scope_decl: { | ||||
| 5293 | NoAliasScopeDecls.push_back(cast<IntrinsicInst>(&Call)); | ||||
| 5294 | break; | ||||
| 5295 | } | ||||
| 5296 | case Intrinsic::preserve_array_access_index: | ||||
| 5297 | case Intrinsic::preserve_struct_access_index: { | ||||
| 5298 | Type *ElemTy = Call.getAttributes().getParamElementType(0); | ||||
| 5299 | Assert(ElemTy,do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
| 5300 | "Intrinsic requires elementtype attribute on first argument.",do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
| 5301 | &Call)do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false); | ||||
| 5302 | break; | ||||
| 5303 | } | ||||
| 5304 | }; | ||||
| 5305 | } | ||||
| 5306 | |||||
| 5307 | /// Carefully grab the subprogram from a local scope. | ||||
| 5308 | /// | ||||
| 5309 | /// This carefully grabs the subprogram from a local scope, avoiding the | ||||
| 5310 | /// built-in assertions that would typically fire. | ||||
| 5311 | static DISubprogram *getSubprogram(Metadata *LocalScope) { | ||||
| 5312 | if (!LocalScope) | ||||
| 5313 | return nullptr; | ||||
| 5314 | |||||
| 5315 | if (auto *SP = dyn_cast<DISubprogram>(LocalScope)) | ||||
| 5316 | return SP; | ||||
| 5317 | |||||
| 5318 | if (auto *LB = dyn_cast<DILexicalBlockBase>(LocalScope)) | ||||
| 5319 | return getSubprogram(LB->getRawScope()); | ||||
| 5320 | |||||
| 5321 | // Just return null; broken scope chains are checked elsewhere. | ||||
| 5322 | assert(!isa<DILocalScope>(LocalScope) && "Unknown type of local scope")((void)0); | ||||
| 5323 | return nullptr; | ||||
| 5324 | } | ||||
| 5325 | |||||
| 5326 | void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { | ||||
| 5327 | unsigned NumOperands; | ||||
| 5328 | bool HasRoundingMD; | ||||
| 5329 | switch (FPI.getIntrinsicID()) { | ||||
| 5330 | #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ | ||||
| 5331 | case Intrinsic::INTRINSIC: \ | ||||
| 5332 | NumOperands = NARG; \ | ||||
| 5333 | HasRoundingMD = ROUND_MODE; \ | ||||
| 5334 | break; | ||||
| 5335 | #include "llvm/IR/ConstrainedOps.def" | ||||
| 5336 | default: | ||||
| 5337 | llvm_unreachable("Invalid constrained FP intrinsic!")__builtin_unreachable(); | ||||
| 5338 | } | ||||
| 5339 | NumOperands += (1 + HasRoundingMD); | ||||
| 5340 | // Compare intrinsics carry an extra predicate metadata operand. | ||||
| 5341 | if (isa<ConstrainedFPCmpIntrinsic>(FPI)) | ||||
| 5342 | NumOperands += 1; | ||||
| 5343 | Assert((FPI.getNumArgOperands() == NumOperands),do { if (!((FPI.getNumArgOperands() == NumOperands))) { CheckFailed ("invalid arguments for constrained FP intrinsic", &FPI); return; } } while (false) | ||||
| 5344 | "invalid arguments for constrained FP intrinsic", &FPI)do { if (!((FPI.getNumArgOperands() == NumOperands))) { CheckFailed ("invalid arguments for constrained FP intrinsic", &FPI); return; } } while (false); | ||||
| 5345 | |||||
| 5346 | switch (FPI.getIntrinsicID()) { | ||||
| 5347 | case Intrinsic::experimental_constrained_lrint: | ||||
| 5348 | case Intrinsic::experimental_constrained_llrint: { | ||||
| 5349 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
| 5350 | Type *ResultTy = FPI.getType(); | ||||
| 5351 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
| 5352 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
| 5353 | } | ||||
| 5354 | break; | ||||
| 5355 | |||||
| 5356 | case Intrinsic::experimental_constrained_lround: | ||||
| 5357 | case Intrinsic::experimental_constrained_llround: { | ||||
| 5358 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
| 5359 | Type *ResultTy = FPI.getType(); | ||||
| 5360 | Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
| 5361 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
| 5362 | break; | ||||
| 5363 | } | ||||
| 5364 | |||||
| 5365 | case Intrinsic::experimental_constrained_fcmp: | ||||
| 5366 | case Intrinsic::experimental_constrained_fcmps: { | ||||
| 5367 | auto Pred = cast<ConstrainedFPCmpIntrinsic>(&FPI)->getPredicate(); | ||||
| 5368 | Assert(CmpInst::isFPPredicate(Pred),do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false) | ||||
| 5369 | "invalid predicate for constrained FP comparison intrinsic", &FPI)do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false); | ||||
| 5370 | break; | ||||
| 5371 | } | ||||
| 5372 | |||||
| 5373 | case Intrinsic::experimental_constrained_fptosi: | ||||
| 5374 | case Intrinsic::experimental_constrained_fptoui: { | ||||
| 5375 | Value *Operand = FPI.getArgOperand(0); | ||||
| 5376 | uint64_t NumSrcElem = 0; | ||||
| 5377 | Assert(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false) | ||||
| 5378 | "Intrinsic first argument must be floating point", &FPI)do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false); | ||||
| 5379 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 5380 | NumSrcElem = cast<FixedVectorType>(OperandT)->getNumElements(); | ||||
| 5381 | } | ||||
| 5382 | |||||
| 5383 | Operand = &FPI; | ||||
| 5384 | Assert((NumSrcElem > 0) == Operand->getType()->isVectorTy(),do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
| 5385 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
| 5386 | Assert(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false) | ||||
| 5387 | "Intrinsic result must be an integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false); | ||||
| 5388 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 5389 | Assert(NumSrcElem == cast<FixedVectorType>(OperandT)->getNumElements(),do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 5390 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 5391 | &FPI)do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
| 5392 | } | ||||
| 5393 | } | ||||
| 5394 | break; | ||||
| 5395 | |||||
| 5396 | case Intrinsic::experimental_constrained_sitofp: | ||||
| 5397 | case Intrinsic::experimental_constrained_uitofp: { | ||||
| 5398 | Value *Operand = FPI.getArgOperand(0); | ||||
| 5399 | uint64_t NumSrcElem = 0; | ||||
| 5400 | Assert(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false) | ||||
| 5401 | "Intrinsic first argument must be integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false); | ||||
| 5402 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 5403 | NumSrcElem = cast<FixedVectorType>(OperandT)->getNumElements(); | ||||
| 5404 | } | ||||
| 5405 | |||||
| 5406 | Operand = &FPI; | ||||
| 5407 | Assert((NumSrcElem > 0) == Operand->getType()->isVectorTy(),do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
| 5408 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!((NumSrcElem > 0) == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
| 5409 | Assert(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false) | ||||
| 5410 | "Intrinsic result must be a floating point", &FPI)do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false); | ||||
| 5411 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 5412 | Assert(NumSrcElem == cast<FixedVectorType>(OperandT)->getNumElements(),do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 5413 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 5414 | &FPI)do { if (!(NumSrcElem == cast<FixedVectorType>(OperandT )->getNumElements())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
| 5415 | } | ||||
| 5416 | } break; | ||||
| 5417 | |||||
| 5418 | case Intrinsic::experimental_constrained_fptrunc: | ||||
| 5419 | case Intrinsic::experimental_constrained_fpext: { | ||||
| 5420 | Value *Operand = FPI.getArgOperand(0); | ||||
| 5421 | Type *OperandTy = Operand->getType(); | ||||
| 5422 | Value *Result = &FPI; | ||||
| 5423 | Type *ResultTy = Result->getType(); | ||||
| 5424 | Assert(OperandTy->isFPOrFPVectorTy(),do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false) | ||||
| 5425 | "Intrinsic first argument must be FP or FP vector", &FPI)do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false); | ||||
| 5426 | Assert(ResultTy->isFPOrFPVectorTy(),do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false) | ||||
| 5427 | "Intrinsic result must be FP or FP vector", &FPI)do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false); | ||||
| 5428 | Assert(OperandTy->isVectorTy() == ResultTy->isVectorTy(),do { if (!(OperandTy->isVectorTy() == ResultTy->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
| 5429 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!(OperandTy->isVectorTy() == ResultTy->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
| 5430 | if (OperandTy->isVectorTy()) { | ||||
| 5431 | Assert(cast<FixedVectorType>(OperandTy)->getNumElements() ==do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 5432 | cast<FixedVectorType>(ResultTy)->getNumElements(),do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 5433 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 5434 | &FPI)do { if (!(cast<FixedVectorType>(OperandTy)->getNumElements () == cast<FixedVectorType>(ResultTy)->getNumElements ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
| 5435 | } | ||||
| 5436 | if (FPI.getIntrinsicID() == Intrinsic::experimental_constrained_fptrunc) { | ||||
| 5437 | Assert(OperandTy->getScalarSizeInBits() > ResultTy->getScalarSizeInBits(),do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false) | ||||
| 5438 | "Intrinsic first argument's type must be larger than result type",do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false) | ||||
| 5439 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false); | ||||
| 5440 | } else { | ||||
| 5441 | Assert(OperandTy->getScalarSizeInBits() < ResultTy->getScalarSizeInBits(),do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false) | ||||
| 5442 | "Intrinsic first argument's type must be smaller than result type",do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false) | ||||
| 5443 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false); | ||||
| 5444 | } | ||||
| 5445 | } | ||||
| 5446 | break; | ||||
| 5447 | |||||
| 5448 | default: | ||||
| 5449 | break; | ||||
| 5450 | } | ||||
| 5451 | |||||
| 5452 | // If a non-metadata argument is passed in a metadata slot then the | ||||
| 5453 | // error will be caught earlier when the incorrect argument doesn't | ||||
| 5454 | // match the specification in the intrinsic call table. Thus, no | ||||
| 5455 | // argument type check is needed here. | ||||
| 5456 | |||||
| 5457 | Assert(FPI.getExceptionBehavior().hasValue(),do { if (!(FPI.getExceptionBehavior().hasValue())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false) | ||||
| 5458 | "invalid exception behavior argument", &FPI)do { if (!(FPI.getExceptionBehavior().hasValue())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false); | ||||
| 5459 | if (HasRoundingMD) { | ||||
| 5460 | Assert(FPI.getRoundingMode().hasValue(),do { if (!(FPI.getRoundingMode().hasValue())) { CheckFailed("invalid rounding mode argument" , &FPI); return; } } while (false) | ||||
| 5461 | "invalid rounding mode argument", &FPI)do { if (!(FPI.getRoundingMode().hasValue())) { CheckFailed("invalid rounding mode argument" , &FPI); return; } } while (false); | ||||
| 5462 | } | ||||
| 5463 | } | ||||
| 5464 | |||||
| 5465 | void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { | ||||
| 5466 | auto *MD = DII.getRawLocation(); | ||||
| 5467 | AssertDI(isa<ValueAsMetadata>(MD) || isa<DIArgList>(MD) ||do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false) | ||||
| 5468 | (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()),do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false) | ||||
| 5469 | "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD)do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false); | ||||
| 5470 | AssertDI(isa<DILocalVariable>(DII.getRawVariable()),do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
| 5471 | "invalid llvm.dbg." + Kind + " intrinsic variable", &DII,do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
| 5472 | DII.getRawVariable())do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false); | ||||
| 5473 | AssertDI(isa<DIExpression>(DII.getRawExpression()),do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
| 5474 | "invalid llvm.dbg." + Kind + " intrinsic expression", &DII,do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
| 5475 | DII.getRawExpression())do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ); | ||||
| 5476 | |||||
| 5477 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
| 5478 | if (MDNode *N = DII.getDebugLoc().getAsMDNode()) | ||||
| 5479 | if (!isa<DILocation>(N)) | ||||
| 5480 | return; | ||||
| 5481 | |||||
| 5482 | BasicBlock *BB = DII.getParent(); | ||||
| 5483 | Function *F = BB ? BB->getParent() : nullptr; | ||||
| 5484 | |||||
| 5485 | // The scopes for variables and !dbg attachments must agree. | ||||
| 5486 | DILocalVariable *Var = DII.getVariable(); | ||||
| 5487 | DILocation *Loc = DII.getDebugLoc(); | ||||
| 5488 | AssertDI(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false) | ||||
| 5489 | &DII, BB, F)do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false); | ||||
| 5490 | |||||
| 5491 | DISubprogram *VarSP = getSubprogram(Var->getRawScope()); | ||||
| 5492 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
| 5493 | if (!VarSP || !LocSP) | ||||
| 5494 | return; // Broken scope chains are checked elsewhere. | ||||
| 5495 | |||||
| 5496 | AssertDI(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 5497 | " variable and !dbg attachment",do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 5498 | &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 5499 | Loc->getScope()->getSubprogram())do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false); | ||||
| 5500 | |||||
| 5501 | // This check is redundant with one in visitLocalVariable(). | ||||
| 5502 | AssertDI(isType(Var->getRawType()), "invalid type ref", Var,do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false) | ||||
| 5503 | Var->getRawType())do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false); | ||||
| 5504 | verifyFnArgs(DII); | ||||
| 5505 | } | ||||
| 5506 | |||||
| 5507 | void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) { | ||||
| 5508 | AssertDI(isa<DILabel>(DLI.getRawLabel()),do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
| 5509 | "invalid llvm.dbg." + Kind + " intrinsic variable", &DLI,do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
| 5510 | DLI.getRawLabel())do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false); | ||||
| 5511 | |||||
| 5512 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
| 5513 | if (MDNode *N = DLI.getDebugLoc().getAsMDNode()) | ||||
| 5514 | if (!isa<DILocation>(N)) | ||||
| 5515 | return; | ||||
| 5516 | |||||
| 5517 | BasicBlock *BB = DLI.getParent(); | ||||
| 5518 | Function *F = BB ? BB->getParent() : nullptr; | ||||
| 5519 | |||||
| 5520 | // The scopes for variables and !dbg attachments must agree. | ||||
| 5521 | DILabel *Label = DLI.getLabel(); | ||||
| 5522 | DILocation *Loc = DLI.getDebugLoc(); | ||||
| 5523 | Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false) | ||||
| 5524 | &DLI, BB, F)do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false); | ||||
| 5525 | |||||
| 5526 | DISubprogram *LabelSP = getSubprogram(Label->getRawScope()); | ||||
| 5527 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
| 5528 | if (!LabelSP || !LocSP) | ||||
| 5529 | return; | ||||
| 5530 | |||||
| 5531 | AssertDI(LabelSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 5532 | " label and !dbg attachment",do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 5533 | &DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc,do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 5534 | Loc->getScope()->getSubprogram())do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false); | ||||
| 5535 | } | ||||
| 5536 | |||||
| 5537 | void Verifier::verifyFragmentExpression(const DbgVariableIntrinsic &I) { | ||||
| 5538 | DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); | ||||
| 5539 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
| 5540 | |||||
| 5541 | // We don't know whether this intrinsic verified correctly. | ||||
| 5542 | if (!V || !E || !E->isValid()) | ||||
| 5543 | return; | ||||
| 5544 | |||||
| 5545 | // Nothing to do if this isn't a DW_OP_LLVM_fragment expression. | ||||
| 5546 | auto Fragment = E->getFragmentInfo(); | ||||
| 5547 | if (!Fragment) | ||||
| 5548 | return; | ||||
| 5549 | |||||
| 5550 | // The frontend helps out GDB by emitting the members of local anonymous | ||||
| 5551 | // unions as artificial local variables with shared storage. When SROA splits | ||||
| 5552 | // the storage for artificial local variables that are smaller than the entire | ||||
| 5553 | // union, the overhang piece will be outside of the allotted space for the | ||||
| 5554 | // variable and this check fails. | ||||
| 5555 | // FIXME: Remove this check as soon as clang stops doing this; it hides bugs. | ||||
| 5556 | if (V->isArtificial()) | ||||
| 5557 | return; | ||||
| 5558 | |||||
| 5559 | verifyFragmentExpression(*V, *Fragment, &I); | ||||
| 5560 | } | ||||
| 5561 | |||||
| 5562 | template <typename ValueOrMetadata> | ||||
| 5563 | void Verifier::verifyFragmentExpression(const DIVariable &V, | ||||
| 5564 | DIExpression::FragmentInfo Fragment, | ||||
| 5565 | ValueOrMetadata *Desc) { | ||||
| 5566 | // If there's no size, the type is broken, but that should be checked | ||||
| 5567 | // elsewhere. | ||||
| 5568 | auto VarSize = V.getSizeInBits(); | ||||
| 5569 | if (!VarSize) | ||||
| 5570 | return; | ||||
| 5571 | |||||
| 5572 | unsigned FragSize = Fragment.SizeInBits; | ||||
| 5573 | unsigned FragOffset = Fragment.OffsetInBits; | ||||
| 5574 | AssertDI(FragSize + FragOffset <= *VarSize,do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false) | ||||
| 5575 | "fragment is larger than or outside of variable", Desc, &V)do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false); | ||||
| 5576 | AssertDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V)do { if (!(FragSize != *VarSize)) { DebugInfoCheckFailed("fragment covers entire variable" , Desc, &V); return; } } while (false); | ||||
| 5577 | } | ||||
| 5578 | |||||
| 5579 | void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) { | ||||
| 5580 | // This function does not take the scope of noninlined function arguments into | ||||
| 5581 | // account. Don't run it if current function is nodebug, because it may | ||||
| 5582 | // contain inlined debug intrinsics. | ||||
| 5583 | if (!HasDebugInfo) | ||||
| 5584 | return; | ||||
| 5585 | |||||
| 5586 | // For performance reasons only check non-inlined ones. | ||||
| 5587 | if (I.getDebugLoc()->getInlinedAt()) | ||||
| 5588 | return; | ||||
| 5589 | |||||
| 5590 | DILocalVariable *Var = I.getVariable(); | ||||
| 5591 | AssertDI(Var, "dbg intrinsic without variable")do { if (!(Var)) { DebugInfoCheckFailed("dbg intrinsic without variable" ); return; } } while (false); | ||||
| 5592 | |||||
| 5593 | unsigned ArgNo = Var->getArg(); | ||||
| 5594 | if (!ArgNo) | ||||
| 5595 | return; | ||||
| 5596 | |||||
| 5597 | // Verify there are no duplicate function argument debug info entries. | ||||
| 5598 | // These will cause hard-to-debug assertions in the DWARF backend. | ||||
| 5599 | if (DebugFnArgs.size() < ArgNo) | ||||
| 5600 | DebugFnArgs.resize(ArgNo, nullptr); | ||||
| 5601 | |||||
| 5602 | auto *Prev = DebugFnArgs[ArgNo - 1]; | ||||
| 5603 | DebugFnArgs[ArgNo - 1] = Var; | ||||
| 5604 | AssertDI(!Prev || (Prev == Var), "conflicting debug info for argument", &I,do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false) | ||||
| 5605 | Prev, Var)do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false); | ||||
| 5606 | } | ||||
| 5607 | |||||
| 5608 | void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) { | ||||
| 5609 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
| 5610 | |||||
| 5611 | // We don't know whether this intrinsic verified correctly. | ||||
| 5612 | if (!E || !E->isValid()) | ||||
| 5613 | return; | ||||
| 5614 | |||||
| 5615 | AssertDI(!E->isEntryValue(), "Entry values are only allowed in MIR", &I)do { if (!(!E->isEntryValue())) { DebugInfoCheckFailed("Entry values are only allowed in MIR" , &I); return; } } while (false); | ||||
| 5616 | } | ||||
| 5617 | |||||
| 5618 | void Verifier::verifyCompileUnits() { | ||||
| 5619 | // When more than one Module is imported into the same context, such as during | ||||
| 5620 | // an LTO build before linking the modules, ODR type uniquing may cause types | ||||
| 5621 | // to point to a different CU. This check does not make sense in this case. | ||||
| 5622 | if (M.getContext().isODRUniquingDebugTypes()) | ||||
| 5623 | return; | ||||
| 5624 | auto *CUs = M.getNamedMetadata("llvm.dbg.cu"); | ||||
| 5625 | SmallPtrSet<const Metadata *, 2> Listed; | ||||
| 5626 | if (CUs) | ||||
| 5627 | Listed.insert(CUs->op_begin(), CUs->op_end()); | ||||
| 5628 | for (auto *CU : CUVisited) | ||||
| 5629 | AssertDI(Listed.count(CU), "DICompileUnit not listed in llvm.dbg.cu", CU)do { if (!(Listed.count(CU))) { DebugInfoCheckFailed("DICompileUnit not listed in llvm.dbg.cu" , CU); return; } } while (false); | ||||
| 5630 | CUVisited.clear(); | ||||
| 5631 | } | ||||
| 5632 | |||||
| 5633 | void Verifier::verifyDeoptimizeCallingConvs() { | ||||
| 5634 | if (DeoptimizeDeclarations.empty()) | ||||
| 5635 | return; | ||||
| 5636 | |||||
| 5637 | const Function *First = DeoptimizeDeclarations[0]; | ||||
| 5638 | for (auto *F : makeArrayRef(DeoptimizeDeclarations).slice(1)) { | ||||
| 5639 | Assert(First->getCallingConv() == F->getCallingConv(),do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
| 5640 | "All llvm.experimental.deoptimize declarations must have the same "do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
| 5641 | "calling convention",do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
| 5642 | First, F)do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false); | ||||
| 5643 | } | ||||
| 5644 | } | ||||
| 5645 | |||||
| 5646 | void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) { | ||||
| 5647 | bool HasSource = F.getSource().hasValue(); | ||||
| 5648 | if (!HasSourceDebugInfo.count(&U)) | ||||
| 5649 | HasSourceDebugInfo[&U] = HasSource; | ||||
| 5650 | AssertDI(HasSource == HasSourceDebugInfo[&U],do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ) | ||||
| 5651 | "inconsistent use of embedded source")do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ); | ||||
| 5652 | } | ||||
| 5653 | |||||
| 5654 | void Verifier::verifyNoAliasScopeDecl() { | ||||
| 5655 | if (NoAliasScopeDecls.empty()) | ||||
| 5656 | return; | ||||
| 5657 | |||||
| 5658 | // only a single scope must be declared at a time. | ||||
| 5659 | for (auto *II : NoAliasScopeDecls) { | ||||
| 5660 | assert(II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl &&((void)0) | ||||
| 5661 | "Not a llvm.experimental.noalias.scope.decl ?")((void)0); | ||||
| 5662 | const auto *ScopeListMV = dyn_cast<MetadataAsValue>( | ||||
| 5663 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
| 5664 | Assert(ScopeListMV != nullptr,do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
| 5665 | "llvm.experimental.noalias.scope.decl must have a MetadataAsValue "do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
| 5666 | "argument",do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
| 5667 | II)do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false); | ||||
| 5668 | |||||
| 5669 | const auto *ScopeListMD = dyn_cast<MDNode>(ScopeListMV->getMetadata()); | ||||
| 5670 | Assert(ScopeListMD != nullptr, "!id.scope.list must point to an MDNode",do { if (!(ScopeListMD != nullptr)) { CheckFailed("!id.scope.list must point to an MDNode" , II); return; } } while (false) | ||||
| 5671 | II)do { if (!(ScopeListMD != nullptr)) { CheckFailed("!id.scope.list must point to an MDNode" , II); return; } } while (false); | ||||
| 5672 | Assert(ScopeListMD->getNumOperands() == 1,do { if (!(ScopeListMD->getNumOperands() == 1)) { CheckFailed ("!id.scope.list must point to a list with a single scope", II ); return; } } while (false) | ||||
| 5673 | "!id.scope.list must point to a list with a single scope", II)do { if (!(ScopeListMD->getNumOperands() == 1)) { CheckFailed ("!id.scope.list must point to a list with a single scope", II ); return; } } while (false); | ||||
| 5674 | } | ||||
| 5675 | |||||
| 5676 | // Only check the domination rule when requested. Once all passes have been | ||||
| 5677 | // adapted this option can go away. | ||||
| 5678 | if (!VerifyNoAliasScopeDomination) | ||||
| 5679 | return; | ||||
| 5680 | |||||
| 5681 | // Now sort the intrinsics based on the scope MDNode so that declarations of | ||||
| 5682 | // the same scopes are next to each other. | ||||
| 5683 | auto GetScope = [](IntrinsicInst *II) { | ||||
| 5684 | const auto *ScopeListMV = cast<MetadataAsValue>( | ||||
| 5685 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
| 5686 | return &cast<MDNode>(ScopeListMV->getMetadata())->getOperand(0); | ||||
| 5687 | }; | ||||
| 5688 | |||||
| 5689 | // We are sorting on MDNode pointers here. For valid input IR this is ok. | ||||
| 5690 | // TODO: Sort on Metadata ID to avoid non-deterministic error messages. | ||||
| 5691 | auto Compare = [GetScope](IntrinsicInst *Lhs, IntrinsicInst *Rhs) { | ||||
| 5692 | return GetScope(Lhs) < GetScope(Rhs); | ||||
| 5693 | }; | ||||
| 5694 | |||||
| 5695 | llvm::sort(NoAliasScopeDecls, Compare); | ||||
| 5696 | |||||
| 5697 | // Go over the intrinsics and check that for the same scope, they are not | ||||
| 5698 | // dominating each other. | ||||
| 5699 | auto ItCurrent = NoAliasScopeDecls.begin(); | ||||
| 5700 | while (ItCurrent != NoAliasScopeDecls.end()) { | ||||
| 5701 | auto CurScope = GetScope(*ItCurrent); | ||||
| 5702 | auto ItNext = ItCurrent; | ||||
| 5703 | do { | ||||
| 5704 | ++ItNext; | ||||
| 5705 | } while (ItNext != NoAliasScopeDecls.end() && | ||||
| 5706 | GetScope(*ItNext) == CurScope); | ||||
| 5707 | |||||
| 5708 | // [ItCurrent, ItNext) represents the declarations for the same scope. | ||||
| 5709 | // Ensure they are not dominating each other.. but only if it is not too | ||||
| 5710 | // expensive. | ||||
| 5711 | if (ItNext - ItCurrent < 32) | ||||
| 5712 | for (auto *I : llvm::make_range(ItCurrent, ItNext)) | ||||
| 5713 | for (auto *J : llvm::make_range(ItCurrent, ItNext)) | ||||
| 5714 | if (I != J) | ||||
| 5715 | Assert(!DT.dominates(I, J),do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
| 5716 | "llvm.experimental.noalias.scope.decl dominates another one "do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
| 5717 | "with the same scope",do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
| 5718 | I)do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false); | ||||
| 5719 | ItCurrent = ItNext; | ||||
| 5720 | } | ||||
| 5721 | } | ||||
| 5722 | |||||
| 5723 | //===----------------------------------------------------------------------===// | ||||
| 5724 | // Implement the public interfaces to this file... | ||||
| 5725 | //===----------------------------------------------------------------------===// | ||||
| 5726 | |||||
| 5727 | bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { | ||||
| 5728 | Function &F = const_cast<Function &>(f); | ||||
| 5729 | |||||
| 5730 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
| 5731 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true, *f.getParent()); | ||||
| 5732 | |||||
| 5733 | // Note that this function's return value is inverted from what you would | ||||
| 5734 | // expect of a function called "verify". | ||||
| 5735 | return !V.verify(F); | ||||
| 5736 | } | ||||
| 5737 | |||||
| 5738 | bool llvm::verifyModule(const Module &M, raw_ostream *OS, | ||||
| 5739 | bool *BrokenDebugInfo) { | ||||
| 5740 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
| 5741 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo, M); | ||||
| 5742 | |||||
| 5743 | bool Broken = false; | ||||
| 5744 | for (const Function &F : M) | ||||
| 5745 | Broken |= !V.verify(F); | ||||
| 5746 | |||||
| 5747 | Broken |= !V.verify(); | ||||
| 5748 | if (BrokenDebugInfo) | ||||
| 5749 | *BrokenDebugInfo = V.hasBrokenDebugInfo(); | ||||
| 5750 | // Note that this function's return value is inverted from what you would | ||||
| 5751 | // expect of a function called "verify". | ||||
| 5752 | return Broken; | ||||
| 5753 | } | ||||
| 5754 | |||||
| 5755 | namespace { | ||||
| 5756 | |||||
| 5757 | struct VerifierLegacyPass : public FunctionPass { | ||||
| 5758 | static char ID; | ||||
| 5759 | |||||
| 5760 | std::unique_ptr<Verifier> V; | ||||
| 5761 | bool FatalErrors = true; | ||||
| 5762 | |||||
| 5763 | VerifierLegacyPass() : FunctionPass(ID) { | ||||
| 5764 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
| 5765 | } | ||||
| 5766 | explicit VerifierLegacyPass(bool FatalErrors) | ||||
| 5767 | : FunctionPass(ID), | ||||
| 5768 | FatalErrors(FatalErrors) { | ||||
| 5769 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
| 5770 | } | ||||
| 5771 | |||||
| 5772 | bool doInitialization(Module &M) override { | ||||
| 5773 | V = std::make_unique<Verifier>( | ||||
| 5774 | &dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false, M); | ||||
| 5775 | return false; | ||||
| 5776 | } | ||||
| 5777 | |||||
| 5778 | bool runOnFunction(Function &F) override { | ||||
| 5779 | if (!V->verify(F) && FatalErrors) { | ||||
| 5780 | errs() << "in function " << F.getName() << '\n'; | ||||
| 5781 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
| 5782 | } | ||||
| 5783 | return false; | ||||
| 5784 | } | ||||
| 5785 | |||||
| 5786 | bool doFinalization(Module &M) override { | ||||
| 5787 | bool HasErrors = false; | ||||
| 5788 | for (Function &F : M) | ||||
| 5789 | if (F.isDeclaration()) | ||||
| 5790 | HasErrors |= !V->verify(F); | ||||
| 5791 | |||||
| 5792 | HasErrors |= !V->verify(); | ||||
| 5793 | if (FatalErrors && (HasErrors || V->hasBrokenDebugInfo())) | ||||
| 5794 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
| 5795 | return false; | ||||
| 5796 | } | ||||
| 5797 | |||||
| 5798 | void getAnalysisUsage(AnalysisUsage &AU) const override { | ||||
| 5799 | AU.setPreservesAll(); | ||||
| 5800 | } | ||||
| 5801 | }; | ||||
| 5802 | |||||
| 5803 | } // end anonymous namespace | ||||
| 5804 | |||||
| 5805 | /// Helper to issue failure from the TBAA verification | ||||
| 5806 | template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) { | ||||
| 5807 | if (Diagnostic) | ||||
| 5808 | return Diagnostic->CheckFailed(Args...); | ||||
| 5809 | } | ||||
| 5810 | |||||
| 5811 | #define AssertTBAA(C, ...)do { if (!(C)) { CheckFailed(...); return false; } } while (false ) \ | ||||
| 5812 | do { \ | ||||
| 5813 | if (!(C)) { \ | ||||
| 5814 | CheckFailed(__VA_ARGS__); \ | ||||
| 5815 | return false; \ | ||||
| 5816 | } \ | ||||
| 5817 | } while (false) | ||||
| 5818 | |||||
| 5819 | /// Verify that \p BaseNode can be used as the "base type" in the struct-path | ||||
| 5820 | /// TBAA scheme. This means \p BaseNode is either a scalar node, or a | ||||
| 5821 | /// struct-type node describing an aggregate data structure (like a struct). | ||||
| 5822 | TBAAVerifier::TBAABaseNodeSummary | ||||
| 5823 | TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode, | ||||
| 5824 | bool IsNewFormat) { | ||||
| 5825 | if (BaseNode->getNumOperands() < 2) { | ||||
| 5826 | CheckFailed("Base nodes must have at least two operands", &I, BaseNode); | ||||
| 5827 | return {true, ~0u}; | ||||
| 5828 | } | ||||
| 5829 | |||||
| 5830 | auto Itr = TBAABaseNodes.find(BaseNode); | ||||
| 5831 | if (Itr != TBAABaseNodes.end()) | ||||
| 5832 | return Itr->second; | ||||
| 5833 | |||||
| 5834 | auto Result = verifyTBAABaseNodeImpl(I, BaseNode, IsNewFormat); | ||||
| 5835 | auto InsertResult = TBAABaseNodes.insert({BaseNode, Result}); | ||||
| 5836 | (void)InsertResult; | ||||
| 5837 | assert(InsertResult.second && "We just checked!")((void)0); | ||||
| 5838 | return Result; | ||||
| 5839 | } | ||||
| 5840 | |||||
| 5841 | TBAAVerifier::TBAABaseNodeSummary | ||||
| 5842 | TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode, | ||||
| 5843 | bool IsNewFormat) { | ||||
| 5844 | const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u}; | ||||
| 5845 | |||||
| 5846 | if (BaseNode->getNumOperands() == 2) { | ||||
| 5847 | // Scalar nodes can only be accessed at offset 0. | ||||
| 5848 | return isValidScalarTBAANode(BaseNode) | ||||
| 5849 | ? TBAAVerifier::TBAABaseNodeSummary({false, 0}) | ||||
| 5850 | : InvalidNode; | ||||
| 5851 | } | ||||
| 5852 | |||||
| 5853 | if (IsNewFormat) { | ||||
| 5854 | if (BaseNode->getNumOperands() % 3 != 0) { | ||||
| 5855 | CheckFailed("Access tag nodes must have the number of operands that is a " | ||||
| 5856 | "multiple of 3!", BaseNode); | ||||
| 5857 | return InvalidNode; | ||||
| 5858 | } | ||||
| 5859 | } else { | ||||
| 5860 | if (BaseNode->getNumOperands() % 2 != 1) { | ||||
| 5861 | CheckFailed("Struct tag nodes must have an odd number of operands!", | ||||
| 5862 | BaseNode); | ||||
| 5863 | return InvalidNode; | ||||
| 5864 | } | ||||
| 5865 | } | ||||
| 5866 | |||||
| 5867 | // Check the type size field. | ||||
| 5868 | if (IsNewFormat) { | ||||
| 5869 | auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 5870 | BaseNode->getOperand(1)); | ||||
| 5871 | if (!TypeSizeNode) { | ||||
| 5872 | CheckFailed("Type size nodes must be constants!", &I, BaseNode); | ||||
| 5873 | return InvalidNode; | ||||
| 5874 | } | ||||
| 5875 | } | ||||
| 5876 | |||||
| 5877 | // Check the type name field. In the new format it can be anything. | ||||
| 5878 | if (!IsNewFormat && !isa<MDString>(BaseNode->getOperand(0))) { | ||||
| 5879 | CheckFailed("Struct tag nodes have a string as their first operand", | ||||
| 5880 | BaseNode); | ||||
| 5881 | return InvalidNode; | ||||
| 5882 | } | ||||
| 5883 | |||||
| 5884 | bool Failed = false; | ||||
| 5885 | |||||
| 5886 | Optional<APInt> PrevOffset; | ||||
| 5887 | unsigned BitWidth = ~0u; | ||||
| 5888 | |||||
| 5889 | // We've already checked that BaseNode is not a degenerate root node with one | ||||
| 5890 | // operand in \c verifyTBAABaseNode, so this loop should run at least once. | ||||
| 5891 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
| 5892 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
| 5893 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
| 5894 | Idx += NumOpsPerField) { | ||||
| 5895 | const MDOperand &FieldTy = BaseNode->getOperand(Idx); | ||||
| 5896 | const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1); | ||||
| 5897 | if (!isa<MDNode>(FieldTy)) { | ||||
| 5898 | CheckFailed("Incorrect field entry in struct type node!", &I, BaseNode); | ||||
| 5899 | Failed = true; | ||||
| 5900 | continue; | ||||
| 5901 | } | ||||
| 5902 | |||||
| 5903 | auto *OffsetEntryCI = | ||||
| 5904 | mdconst::dyn_extract_or_null<ConstantInt>(FieldOffset); | ||||
| 5905 | if (!OffsetEntryCI) { | ||||
| 5906 | CheckFailed("Offset entries must be constants!", &I, BaseNode); | ||||
| 5907 | Failed = true; | ||||
| 5908 | continue; | ||||
| 5909 | } | ||||
| 5910 | |||||
| 5911 | if (BitWidth == ~0u) | ||||
| 5912 | BitWidth = OffsetEntryCI->getBitWidth(); | ||||
| 5913 | |||||
| 5914 | if (OffsetEntryCI->getBitWidth() != BitWidth) { | ||||
| 5915 | CheckFailed( | ||||
| 5916 | "Bitwidth between the offsets and struct type entries must match", &I, | ||||
| 5917 | BaseNode); | ||||
| 5918 | Failed = true; | ||||
| 5919 | continue; | ||||
| 5920 | } | ||||
| 5921 | |||||
| 5922 | // NB! As far as I can tell, we generate a non-strictly increasing offset | ||||
| 5923 | // sequence only from structs that have zero size bit fields. When | ||||
| 5924 | // recursing into a contained struct in \c getFieldNodeFromTBAABaseNode we | ||||
| 5925 | // pick the field lexically the latest in struct type metadata node. This | ||||
| 5926 | // mirrors the actual behavior of the alias analysis implementation. | ||||
| 5927 | bool IsAscending = | ||||
| 5928 | !PrevOffset || PrevOffset->ule(OffsetEntryCI->getValue()); | ||||
| 5929 | |||||
| 5930 | if (!IsAscending) { | ||||
| 5931 | CheckFailed("Offsets must be increasing!", &I, BaseNode); | ||||
| 5932 | Failed = true; | ||||
| 5933 | } | ||||
| 5934 | |||||
| 5935 | PrevOffset = OffsetEntryCI->getValue(); | ||||
| 5936 | |||||
| 5937 | if (IsNewFormat) { | ||||
| 5938 | auto *MemberSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 5939 | BaseNode->getOperand(Idx + 2)); | ||||
| 5940 | if (!MemberSizeNode) { | ||||
| 5941 | CheckFailed("Member size entries must be constants!", &I, BaseNode); | ||||
| 5942 | Failed = true; | ||||
| 5943 | continue; | ||||
| 5944 | } | ||||
| 5945 | } | ||||
| 5946 | } | ||||
| 5947 | |||||
| 5948 | return Failed ? InvalidNode | ||||
| 5949 | : TBAAVerifier::TBAABaseNodeSummary(false, BitWidth); | ||||
| 5950 | } | ||||
| 5951 | |||||
| 5952 | static bool IsRootTBAANode(const MDNode *MD) { | ||||
| 5953 | return MD->getNumOperands() < 2; | ||||
| 5954 | } | ||||
| 5955 | |||||
| 5956 | static bool IsScalarTBAANodeImpl(const MDNode *MD, | ||||
| 5957 | SmallPtrSetImpl<const MDNode *> &Visited) { | ||||
| 5958 | if (MD->getNumOperands() != 2 && MD->getNumOperands() != 3) | ||||
| 5959 | return false; | ||||
| 5960 | |||||
| 5961 | if (!isa<MDString>(MD->getOperand(0))) | ||||
| 5962 | return false; | ||||
| 5963 | |||||
| 5964 | if (MD->getNumOperands() == 3) { | ||||
| 5965 | auto *Offset = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2)); | ||||
| 5966 | if (!(Offset && Offset->isZero() && isa<MDString>(MD->getOperand(0)))) | ||||
| 5967 | return false; | ||||
| 5968 | } | ||||
| 5969 | |||||
| 5970 | auto *Parent = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
| 5971 | return Parent && Visited.insert(Parent).second && | ||||
| 5972 | (IsRootTBAANode(Parent) || IsScalarTBAANodeImpl(Parent, Visited)); | ||||
| 5973 | } | ||||
| 5974 | |||||
| 5975 | bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) { | ||||
| 5976 | auto ResultIt = TBAAScalarNodes.find(MD); | ||||
| 5977 | if (ResultIt != TBAAScalarNodes.end()) | ||||
| 5978 | return ResultIt->second; | ||||
| 5979 | |||||
| 5980 | SmallPtrSet<const MDNode *, 4> Visited; | ||||
| 5981 | bool Result = IsScalarTBAANodeImpl(MD, Visited); | ||||
| 5982 | auto InsertResult = TBAAScalarNodes.insert({MD, Result}); | ||||
| 5983 | (void)InsertResult; | ||||
| 5984 | assert(InsertResult.second && "Just checked!")((void)0); | ||||
| 5985 | |||||
| 5986 | return Result; | ||||
| 5987 | } | ||||
| 5988 | |||||
| 5989 | /// Returns the field node at the offset \p Offset in \p BaseNode. Update \p | ||||
| 5990 | /// Offset in place to be the offset within the field node returned. | ||||
| 5991 | /// | ||||
| 5992 | /// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode. | ||||
| 5993 | MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, | ||||
| 5994 | const MDNode *BaseNode, | ||||
| 5995 | APInt &Offset, | ||||
| 5996 | bool IsNewFormat) { | ||||
| 5997 | assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!")((void)0); | ||||
| 5998 | |||||
| 5999 | // Scalar nodes have only one possible "field" -- their parent in the access | ||||
| 6000 | // hierarchy. Offset must be zero at this point, but our caller is supposed | ||||
| 6001 | // to Assert that. | ||||
| 6002 | if (BaseNode->getNumOperands() == 2) | ||||
| 6003 | return cast<MDNode>(BaseNode->getOperand(1)); | ||||
| 6004 | |||||
| 6005 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
| 6006 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
| 6007 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
| 6008 | Idx += NumOpsPerField) { | ||||
| 6009 | auto *OffsetEntryCI = | ||||
| 6010 | mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1)); | ||||
| 6011 | if (OffsetEntryCI->getValue().ugt(Offset)) { | ||||
| 6012 | if (Idx == FirstFieldOpNo) { | ||||
| 6013 | CheckFailed("Could not find TBAA parent in struct type node", &I, | ||||
| 6014 | BaseNode, &Offset); | ||||
| 6015 | return nullptr; | ||||
| 6016 | } | ||||
| 6017 | |||||
| 6018 | unsigned PrevIdx = Idx - NumOpsPerField; | ||||
| 6019 | auto *PrevOffsetEntryCI = | ||||
| 6020 | mdconst::extract<ConstantInt>(BaseNode->getOperand(PrevIdx + 1)); | ||||
| 6021 | Offset -= PrevOffsetEntryCI->getValue(); | ||||
| 6022 | return cast<MDNode>(BaseNode->getOperand(PrevIdx)); | ||||
| 6023 | } | ||||
| 6024 | } | ||||
| 6025 | |||||
| 6026 | unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField; | ||||
| 6027 | auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( | ||||
| 6028 | BaseNode->getOperand(LastIdx + 1)); | ||||
| 6029 | Offset -= LastOffsetEntryCI->getValue(); | ||||
| 6030 | return cast<MDNode>(BaseNode->getOperand(LastIdx)); | ||||
| 6031 | } | ||||
| 6032 | |||||
| 6033 | static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { | ||||
| 6034 | if (!Type || Type->getNumOperands() < 3) | ||||
| 6035 | return false; | ||||
| 6036 | |||||
| 6037 | // In the new format type nodes shall have a reference to the parent type as | ||||
| 6038 | // its first operand. | ||||
| 6039 | MDNode *Parent = dyn_cast_or_null<MDNode>(Type->getOperand(0)); | ||||
| 6040 | if (!Parent) | ||||
| 6041 | return false; | ||||
| 6042 | |||||
| 6043 | return true; | ||||
| 6044 | } | ||||
| 6045 | |||||
| 6046 | bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { | ||||
| 6047 | AssertTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
| 6048 | isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
| 6049 | isa<AtomicCmpXchgInst>(I),do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
| 6050 | "This instruction shall not have a TBAA access tag!", &I)do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false); | ||||
| 6051 | |||||
| 6052 | bool IsStructPathTBAA = | ||||
| 6053 | isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; | ||||
| 6054 | |||||
| 6055 | AssertTBAA(do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
| 6056 | IsStructPathTBAA,do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
| 6057 | "Old-style TBAA is no longer allowed, use struct-path TBAA instead", &I)do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false); | ||||
| 6058 | |||||
| 6059 | MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0)); | ||||
| 6060 | MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
| 6061 | |||||
| 6062 | bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); | ||||
| 6063 | |||||
| 6064 | if (IsNewFormat) { | ||||
| 6065 | AssertTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5,do { if (!(MD->getNumOperands() == 4 || MD->getNumOperands () == 5)) { CheckFailed("Access tag metadata must have either 4 or 5 operands" , &I, MD); return false; } } while (false) | ||||
| 6066 | "Access tag metadata must have either 4 or 5 operands", &I, MD)do { if (!(MD->getNumOperands() == 4 || MD->getNumOperands () == 5)) { CheckFailed("Access tag metadata must have either 4 or 5 operands" , &I, MD); return false; } } while (false); | ||||
| 6067 | } else { | ||||
| 6068 | AssertTBAA(MD->getNumOperands() < 5,do { if (!(MD->getNumOperands() < 5)) { CheckFailed("Struct tag metadata must have either 3 or 4 operands" , &I, MD); return false; } } while (false) | ||||
| 6069 | "Struct tag metadata must have either 3 or 4 operands", &I, MD)do { if (!(MD->getNumOperands() < 5)) { CheckFailed("Struct tag metadata must have either 3 or 4 operands" , &I, MD); return false; } } while (false); | ||||
| 6070 | } | ||||
| 6071 | |||||
| 6072 | // Check the access size field. | ||||
| 6073 | if (IsNewFormat) { | ||||
| 6074 | auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 6075 | MD->getOperand(3)); | ||||
| 6076 | AssertTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD)do { if (!(AccessSizeNode)) { CheckFailed("Access size field must be a constant" , &I, MD); return false; } } while (false); | ||||
| 6077 | } | ||||
| 6078 | |||||
| 6079 | // Check the immutability flag. | ||||
| 6080 | unsigned ImmutabilityFlagOpNo = IsNewFormat ? 4 : 3; | ||||
| 6081 | if (MD->getNumOperands() == ImmutabilityFlagOpNo + 1) { | ||||
| 6082 | auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 6083 | MD->getOperand(ImmutabilityFlagOpNo)); | ||||
| 6084 | AssertTBAA(IsImmutableCI,do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
| 6085 | "Immutability tag on struct tag metadata must be a constant",do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
| 6086 | &I, MD)do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false); | ||||
| 6087 | AssertTBAA(do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
| 6088 | IsImmutableCI->isZero() || IsImmutableCI->isOne(),do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
| 6089 | "Immutability part of the struct tag metadata must be either 0 or 1",do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
| 6090 | &I, MD)do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false); | ||||
| 6091 | } | ||||
| 6092 | |||||
| 6093 | AssertTBAA(BaseNode && AccessType,do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
| 6094 | "Malformed struct tag metadata: base and access-type "do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
| 6095 | "should be non-null and point to Metadata nodes",do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
| 6096 | &I, MD, BaseNode, AccessType)do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false); | ||||
| 6097 | |||||
| 6098 | if (!IsNewFormat) { | ||||
| 6099 | AssertTBAA(isValidScalarTBAANode(AccessType),do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
| 6100 | "Access type node must be a valid scalar type", &I, MD,do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
| 6101 | AccessType)do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false); | ||||
| 6102 | } | ||||
| 6103 | |||||
| 6104 | auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2)); | ||||
| 6105 | AssertTBAA(OffsetCI, "Offset must be constant integer", &I, MD)do { if (!(OffsetCI)) { CheckFailed("Offset must be constant integer" , &I, MD); return false; } } while (false); | ||||
| 6106 | |||||
| 6107 | APInt Offset = OffsetCI->getValue(); | ||||
| 6108 | bool SeenAccessTypeInPath = false; | ||||
| 6109 | |||||
| 6110 | SmallPtrSet<MDNode *, 4> StructPath; | ||||
| 6111 | |||||
| 6112 | for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); | ||||
| 6113 | BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, | ||||
| 6114 | IsNewFormat)) { | ||||
| 6115 | if (!StructPath.insert(BaseNode).second) { | ||||
| 6116 | CheckFailed("Cycle detected in struct path", &I, MD); | ||||
| 6117 | return false; | ||||
| 6118 | } | ||||
| 6119 | |||||
| 6120 | bool Invalid; | ||||
| 6121 | unsigned BaseNodeBitWidth; | ||||
| 6122 | std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode, | ||||
| 6123 | IsNewFormat); | ||||
| 6124 | |||||
| 6125 | // If the base node is invalid in itself, then we've already printed all the | ||||
| 6126 | // errors we wanted to print. | ||||
| 6127 | if (Invalid) | ||||
| 6128 | return false; | ||||
| 6129 | |||||
| 6130 | SeenAccessTypeInPath |= BaseNode == AccessType; | ||||
| 6131 | |||||
| 6132 | if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType) | ||||
| 6133 | AssertTBAA(Offset == 0, "Offset not zero at the point of scalar access",do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false) | ||||
| 6134 | &I, MD, &Offset)do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false); | ||||
| 6135 | |||||
| 6136 | AssertTBAA(BaseNodeBitWidth == Offset.getBitWidth() ||do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6137 | (BaseNodeBitWidth == 0 && Offset == 0) ||do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6138 | (IsNewFormat && BaseNodeBitWidth == ~0u),do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6139 | "Access bit-width not the same as description bit-width", &I, MD,do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6140 | BaseNodeBitWidth, Offset.getBitWidth())do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false); | ||||
| 6141 | |||||
| 6142 | if (IsNewFormat && SeenAccessTypeInPath) | ||||
| 6143 | break; | ||||
| 6144 | } | ||||
| 6145 | |||||
| 6146 | AssertTBAA(SeenAccessTypeInPath, "Did not see access type in access path!",do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false) | ||||
| 6147 | &I, MD)do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false); | ||||
| 6148 | return true; | ||||
| 6149 | } | ||||
| 6150 | |||||
| 6151 | char VerifierLegacyPass::ID = 0; | ||||
| 6152 | INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false)static void *initializeVerifierLegacyPassPassOnce(PassRegistry &Registry) { PassInfo *PI = new PassInfo( "Module Verifier" , "verify", &VerifierLegacyPass::ID, PassInfo::NormalCtor_t (callDefaultCtor<VerifierLegacyPass>), false, false); Registry .registerPass(*PI, true); return PI; } static llvm::once_flag InitializeVerifierLegacyPassPassFlag; void llvm::initializeVerifierLegacyPassPass (PassRegistry &Registry) { llvm::call_once(InitializeVerifierLegacyPassPassFlag , initializeVerifierLegacyPassPassOnce, std::ref(Registry)); } | ||||
| 6153 | |||||
| 6154 | FunctionPass *llvm::createVerifierPass(bool FatalErrors) { | ||||
| 6155 | return new VerifierLegacyPass(FatalErrors); | ||||
| 6156 | } | ||||
| 6157 | |||||
| 6158 | AnalysisKey VerifierAnalysis::Key; | ||||
| 6159 | VerifierAnalysis::Result VerifierAnalysis::run(Module &M, | ||||
| 6160 | ModuleAnalysisManager &) { | ||||
| 6161 | Result Res; | ||||
| 6162 | Res.IRBroken = llvm::verifyModule(M, &dbgs(), &Res.DebugInfoBroken); | ||||
| 6163 | return Res; | ||||
| 6164 | } | ||||
| 6165 | |||||
| 6166 | VerifierAnalysis::Result VerifierAnalysis::run(Function &F, | ||||
| 6167 | FunctionAnalysisManager &) { | ||||
| 6168 | return { llvm::verifyFunction(F, &dbgs()), false }; | ||||
| 6169 | } | ||||
| 6170 | |||||
| 6171 | PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { | ||||
| 6172 | auto Res = AM.getResult<VerifierAnalysis>(M); | ||||
| 6173 | if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) | ||||
| 6174 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
| 6175 | |||||
| 6176 | return PreservedAnalyses::all(); | ||||
| 6177 | } | ||||
| 6178 | |||||
| 6179 | PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { | ||||
| 6180 | auto res = AM.getResult<VerifierAnalysis>(F); | ||||
| 6181 | if (res.IRBroken && FatalErrors) | ||||
| 6182 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
| 6183 | |||||
| 6184 | return PreservedAnalyses::all(); | ||||
| 6185 | } |
| 1 | //===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// | ||||
| 2 | // | ||||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
| 6 | // | ||||
| 7 | //===----------------------------------------------------------------------===// | ||||
| 8 | // | ||||
| 9 | // Declarations for metadata specific to debug info. | ||||
| 10 | // | ||||
| 11 | //===----------------------------------------------------------------------===// | ||||
| 12 | |||||
| 13 | #ifndef LLVM_IR_DEBUGINFOMETADATA_H | ||||
| 14 | #define LLVM_IR_DEBUGINFOMETADATA_H | ||||
| 15 | |||||
| 16 | #include "llvm/ADT/ArrayRef.h" | ||||
| 17 | #include "llvm/ADT/BitmaskEnum.h" | ||||
| 18 | #include "llvm/ADT/None.h" | ||||
| 19 | #include "llvm/ADT/Optional.h" | ||||
| 20 | #include "llvm/ADT/PointerUnion.h" | ||||
| 21 | #include "llvm/ADT/STLExtras.h" | ||||
| 22 | #include "llvm/ADT/SmallVector.h" | ||||
| 23 | #include "llvm/ADT/StringRef.h" | ||||
| 24 | #include "llvm/ADT/iterator_range.h" | ||||
| 25 | #include "llvm/BinaryFormat/Dwarf.h" | ||||
| 26 | #include "llvm/IR/Constants.h" | ||||
| 27 | #include "llvm/IR/Metadata.h" | ||||
| 28 | #include "llvm/Support/Casting.h" | ||||
| 29 | #include "llvm/Support/CommandLine.h" | ||||
| 30 | #include "llvm/Support/Discriminator.h" | ||||
| 31 | #include <cassert> | ||||
| 32 | #include <climits> | ||||
| 33 | #include <cstddef> | ||||
| 34 | #include <cstdint> | ||||
| 35 | #include <iterator> | ||||
| 36 | #include <type_traits> | ||||
| 37 | #include <vector> | ||||
| 38 | |||||
| 39 | // Helper macros for defining get() overrides. | ||||
| 40 | #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ | ||||
| 41 | #define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS | ||||
| 42 | #define DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)static CLASS *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK (FORMAL)) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK( ARGS), Distinct); } static TempCLASS getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { return TempCLASS ( getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary) ); } \ | ||||
| 43 | static CLASS *getDistinct(LLVMContext &Context, \ | ||||
| 44 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
| 45 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ | ||||
| 46 | } \ | ||||
| 47 | static Temp##CLASS getTemporary(LLVMContext &Context, \ | ||||
| 48 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
| 49 | return Temp##CLASS( \ | ||||
| 50 | getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ | ||||
| 51 | } | ||||
| 52 | #define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ | ||||
| 53 | static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
| 54 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ | ||||
| 55 | } \ | ||||
| 56 | static CLASS *getIfExists(LLVMContext &Context, \ | ||||
| 57 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||
| 58 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ | ||||
| 59 | /* ShouldCreate */ false); \ | ||||
| 60 | } \ | ||||
| 61 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)static CLASS *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK (FORMAL)) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK( ARGS), Distinct); } static TempCLASS getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { return TempCLASS ( getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary) ); } | ||||
| 62 | |||||
| 63 | namespace llvm { | ||||
| 64 | |||||
| 65 | extern cl::opt<bool> EnableFSDiscriminator; | ||||
| 66 | |||||
| 67 | class DITypeRefArray { | ||||
| 68 | const MDTuple *N = nullptr; | ||||
| 69 | |||||
| 70 | public: | ||||
| 71 | DITypeRefArray() = default; | ||||
| 72 | DITypeRefArray(const MDTuple *N) : N(N) {} | ||||
| 73 | |||||
| 74 | explicit operator bool() const { return get(); } | ||||
| 75 | explicit operator MDTuple *() const { return get(); } | ||||
| 76 | |||||
| 77 | MDTuple *get() const { return const_cast<MDTuple *>(N); } | ||||
| 78 | MDTuple *operator->() const { return get(); } | ||||
| 79 | MDTuple &operator*() const { return *get(); } | ||||
| 80 | |||||
| 81 | // FIXME: Fix callers and remove condition on N. | ||||
| 82 | unsigned size() const { return N ? N->getNumOperands() : 0u; } | ||||
| 83 | DIType *operator[](unsigned I) const { | ||||
| 84 | return cast_or_null<DIType>(N->getOperand(I)); | ||||
| 85 | } | ||||
| 86 | |||||
| 87 | class iterator { | ||||
| 88 | MDNode::op_iterator I = nullptr; | ||||
| 89 | |||||
| 90 | public: | ||||
| 91 | using iterator_category = std::input_iterator_tag; | ||||
| 92 | using value_type = DIType *; | ||||
| 93 | using difference_type = std::ptrdiff_t; | ||||
| 94 | using pointer = void; | ||||
| 95 | using reference = DIType *; | ||||
| 96 | |||||
| 97 | iterator() = default; | ||||
| 98 | explicit iterator(MDNode::op_iterator I) : I(I) {} | ||||
| 99 | |||||
| 100 | DIType *operator*() const { return cast_or_null<DIType>(*I); } | ||||
| 101 | |||||
| 102 | iterator &operator++() { | ||||
| 103 | ++I; | ||||
| 104 | return *this; | ||||
| 105 | } | ||||
| 106 | |||||
| 107 | iterator operator++(int) { | ||||
| 108 | iterator Temp(*this); | ||||
| 109 | ++I; | ||||
| 110 | return Temp; | ||||
| 111 | } | ||||
| 112 | |||||
| 113 | bool operator==(const iterator &X) const { return I == X.I; } | ||||
| 114 | bool operator!=(const iterator &X) const { return I != X.I; } | ||||
| 115 | }; | ||||
| 116 | |||||
| 117 | // FIXME: Fix callers and remove condition on N. | ||||
| 118 | iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } | ||||
| 119 | iterator end() const { return N ? iterator(N->op_end()) : iterator(); } | ||||
| 120 | }; | ||||
| 121 | |||||
| 122 | /// Tagged DWARF-like metadata node. | ||||
| 123 | /// | ||||
| 124 | /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, | ||||
| 125 | /// defined in llvm/BinaryFormat/Dwarf.h). Called \a DINode because it's | ||||
| 126 | /// potentially used for non-DWARF output. | ||||
| 127 | class DINode : public MDNode { | ||||
| 128 | friend class LLVMContextImpl; | ||||
| 129 | friend class MDNode; | ||||
| 130 | |||||
| 131 | protected: | ||||
| 132 | DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
| 133 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) | ||||
| 134 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||
| 135 | assert(Tag < 1u << 16)((void)0); | ||||
| 136 | SubclassData16 = Tag; | ||||
| 137 | } | ||||
| 138 | ~DINode() = default; | ||||
| 139 | |||||
| 140 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||
| 141 | return cast_or_null<Ty>(getOperand(I)); | ||||
| 142 | } | ||||
| 143 | |||||
| 144 | StringRef getStringOperand(unsigned I) const { | ||||
| 145 | if (auto *S = getOperandAs<MDString>(I)) | ||||
| 146 | return S->getString(); | ||||
| 147 | return StringRef(); | ||||
| 148 | } | ||||
| 149 | |||||
| 150 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||
| 151 | if (S.empty()) | ||||
| 152 | return nullptr; | ||||
| 153 | return MDString::get(Context, S); | ||||
| 154 | } | ||||
| 155 | |||||
| 156 | /// Allow subclasses to mutate the tag. | ||||
| 157 | void setTag(unsigned Tag) { SubclassData16 = Tag; } | ||||
| 158 | |||||
| 159 | public: | ||||
| 160 | dwarf::Tag getTag() const { return (dwarf::Tag)SubclassData16; } | ||||
| 161 | |||||
| 162 | /// Debug info flags. | ||||
| 163 | /// | ||||
| 164 | /// The three accessibility flags are mutually exclusive and rolled together | ||||
| 165 | /// in the first two bits. | ||||
| 166 | enum DIFlags : uint32_t { | ||||
| 167 | #define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, | ||||
| 168 | #define DI_FLAG_LARGEST_NEEDED | ||||
| 169 | #include "llvm/IR/DebugInfoFlags.def" | ||||
| 170 | FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic, | ||||
| 171 | FlagPtrToMemberRep = FlagSingleInheritance | FlagMultipleInheritance | | ||||
| 172 | FlagVirtualInheritance, | ||||
| 173 | LLVM_MARK_AS_BITMASK_ENUM(FlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = FlagLargest | ||||
| 174 | }; | ||||
| 175 | |||||
| 176 | static DIFlags getFlag(StringRef Flag); | ||||
| 177 | static StringRef getFlagString(DIFlags Flag); | ||||
| 178 | |||||
| 179 | /// Split up a flags bitfield. | ||||
| 180 | /// | ||||
| 181 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||
| 182 | /// any remaining (unrecognized) bits. | ||||
| 183 | static DIFlags splitFlags(DIFlags Flags, | ||||
| 184 | SmallVectorImpl<DIFlags> &SplitFlags); | ||||
| 185 | |||||
| 186 | static bool classof(const Metadata *MD) { | ||||
| 187 | switch (MD->getMetadataID()) { | ||||
| 188 | default: | ||||
| 189 | return false; | ||||
| 190 | case GenericDINodeKind: | ||||
| 191 | case DISubrangeKind: | ||||
| 192 | case DIEnumeratorKind: | ||||
| 193 | case DIBasicTypeKind: | ||||
| 194 | case DIStringTypeKind: | ||||
| 195 | case DIDerivedTypeKind: | ||||
| 196 | case DICompositeTypeKind: | ||||
| 197 | case DISubroutineTypeKind: | ||||
| 198 | case DIFileKind: | ||||
| 199 | case DICompileUnitKind: | ||||
| 200 | case DISubprogramKind: | ||||
| 201 | case DILexicalBlockKind: | ||||
| 202 | case DILexicalBlockFileKind: | ||||
| 203 | case DINamespaceKind: | ||||
| 204 | case DICommonBlockKind: | ||||
| 205 | case DITemplateTypeParameterKind: | ||||
| 206 | case DITemplateValueParameterKind: | ||||
| 207 | case DIGlobalVariableKind: | ||||
| 208 | case DILocalVariableKind: | ||||
| 209 | case DILabelKind: | ||||
| 210 | case DIObjCPropertyKind: | ||||
| 211 | case DIImportedEntityKind: | ||||
| 212 | case DIModuleKind: | ||||
| 213 | case DIGenericSubrangeKind: | ||||
| 214 | return true; | ||||
| 215 | } | ||||
| 216 | } | ||||
| 217 | }; | ||||
| 218 | |||||
| 219 | /// Generic tagged DWARF-like metadata node. | ||||
| 220 | /// | ||||
| 221 | /// An un-specialized DWARF-like metadata node. The first operand is a | ||||
| 222 | /// (possibly empty) null-separated \a MDString header that contains arbitrary | ||||
| 223 | /// fields. The remaining operands are \a dwarf_operands(), and are pointers | ||||
| 224 | /// to other metadata. | ||||
| 225 | class GenericDINode : public DINode { | ||||
| 226 | friend class LLVMContextImpl; | ||||
| 227 | friend class MDNode; | ||||
| 228 | |||||
| 229 | GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, | ||||
| 230 | unsigned Tag, ArrayRef<Metadata *> Ops1, | ||||
| 231 | ArrayRef<Metadata *> Ops2) | ||||
| 232 | : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { | ||||
| 233 | setHash(Hash); | ||||
| 234 | } | ||||
| 235 | ~GenericDINode() { dropAllReferences(); } | ||||
| 236 | |||||
| 237 | void setHash(unsigned Hash) { SubclassData32 = Hash; } | ||||
| 238 | void recalculateHash(); | ||||
| 239 | |||||
| 240 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 241 | StringRef Header, ArrayRef<Metadata *> DwarfOps, | ||||
| 242 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 243 | return getImpl(Context, Tag, getCanonicalMDString(Context, Header), | ||||
| 244 | DwarfOps, Storage, ShouldCreate); | ||||
| 245 | } | ||||
| 246 | |||||
| 247 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 248 | MDString *Header, ArrayRef<Metadata *> DwarfOps, | ||||
| 249 | StorageType Storage, bool ShouldCreate = true); | ||||
| 250 | |||||
| 251 | TempGenericDINode cloneImpl() const { | ||||
| 252 | return getTemporary(getContext(), getTag(), getHeader(), | ||||
| 253 | SmallVector<Metadata *, 4>(dwarf_operands())); | ||||
| 254 | } | ||||
| 255 | |||||
| 256 | public: | ||||
| 257 | unsigned getHash() const { return SubclassData32; } | ||||
| 258 | |||||
| 259 | DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef Header, | ||||
| 260 | ArrayRef<Metadata *> DwarfOps), | ||||
| 261 | (Tag, Header, DwarfOps)) | ||||
| 262 | DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *Header, | ||||
| 263 | ArrayRef<Metadata *> DwarfOps), | ||||
| 264 | (Tag, Header, DwarfOps)) | ||||
| 265 | |||||
| 266 | /// Return a (temporary) clone of this. | ||||
| 267 | TempGenericDINode clone() const { return cloneImpl(); } | ||||
| 268 | |||||
| 269 | dwarf::Tag getTag() const { return (dwarf::Tag)SubclassData16; } | ||||
| 270 | StringRef getHeader() const { return getStringOperand(0); } | ||||
| 271 | MDString *getRawHeader() const { return getOperandAs<MDString>(0); } | ||||
| 272 | |||||
| 273 | op_iterator dwarf_op_begin() const { return op_begin() + 1; } | ||||
| 274 | op_iterator dwarf_op_end() const { return op_end(); } | ||||
| 275 | op_range dwarf_operands() const { | ||||
| 276 | return op_range(dwarf_op_begin(), dwarf_op_end()); | ||||
| 277 | } | ||||
| 278 | |||||
| 279 | unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } | ||||
| 280 | const MDOperand &getDwarfOperand(unsigned I) const { | ||||
| 281 | return getOperand(I + 1); | ||||
| 282 | } | ||||
| 283 | void replaceDwarfOperandWith(unsigned I, Metadata *New) { | ||||
| 284 | replaceOperandWith(I + 1, New); | ||||
| 285 | } | ||||
| 286 | |||||
| 287 | static bool classof(const Metadata *MD) { | ||||
| 288 | return MD->getMetadataID() == GenericDINodeKind; | ||||
| 289 | } | ||||
| 290 | }; | ||||
| 291 | |||||
| 292 | /// Array subrange. | ||||
| 293 | /// | ||||
| 294 | /// TODO: Merge into node for DW_TAG_array_type, which should have a custom | ||||
| 295 | /// type. | ||||
| 296 | class DISubrange : public DINode { | ||||
| 297 | friend class LLVMContextImpl; | ||||
| 298 | friend class MDNode; | ||||
| 299 | |||||
| 300 | DISubrange(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) | ||||
| 301 | : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {} | ||||
| 302 | |||||
| 303 | ~DISubrange() = default; | ||||
| 304 | |||||
| 305 | static DISubrange *getImpl(LLVMContext &Context, int64_t Count, | ||||
| 306 | int64_t LowerBound, StorageType Storage, | ||||
| 307 | bool ShouldCreate = true); | ||||
| 308 | |||||
| 309 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||
| 310 | int64_t LowerBound, StorageType Storage, | ||||
| 311 | bool ShouldCreate = true); | ||||
| 312 | |||||
| 313 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||
| 314 | Metadata *LowerBound, Metadata *UpperBound, | ||||
| 315 | Metadata *Stride, StorageType Storage, | ||||
| 316 | bool ShouldCreate = true); | ||||
| 317 | |||||
| 318 | TempDISubrange cloneImpl() const { | ||||
| 319 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||
| 320 | getRawUpperBound(), getRawStride()); | ||||
| 321 | } | ||||
| 322 | |||||
| 323 | public: | ||||
| 324 | DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), | ||||
| 325 | (Count, LowerBound)) | ||||
| 326 | |||||
| 327 | DEFINE_MDNODE_GET(DISubrange, (Metadata *CountNode, int64_t LowerBound = 0), | ||||
| 328 | (CountNode, LowerBound)) | ||||
| 329 | |||||
| 330 | DEFINE_MDNODE_GET(DISubrange, | ||||
| 331 | (Metadata * CountNode, Metadata *LowerBound, | ||||
| 332 | Metadata *UpperBound, Metadata *Stride), | ||||
| 333 | (CountNode, LowerBound, UpperBound, Stride)) | ||||
| 334 | |||||
| 335 | TempDISubrange clone() const { return cloneImpl(); } | ||||
| 336 | |||||
| 337 | Metadata *getRawCountNode() const { | ||||
| 338 | return getOperand(0).get(); | ||||
| 339 | } | ||||
| 340 | |||||
| 341 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||
| 342 | |||||
| 343 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||
| 344 | |||||
| 345 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||
| 346 | |||||
| 347 | typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType; | ||||
| 348 | |||||
| 349 | BoundType getCount() const; | ||||
| 350 | |||||
| 351 | BoundType getLowerBound() const; | ||||
| 352 | |||||
| 353 | BoundType getUpperBound() const; | ||||
| 354 | |||||
| 355 | BoundType getStride() const; | ||||
| 356 | |||||
| 357 | static bool classof(const Metadata *MD) { | ||||
| 358 | return MD->getMetadataID() == DISubrangeKind; | ||||
| 359 | } | ||||
| 360 | }; | ||||
| 361 | |||||
| 362 | class DIGenericSubrange : public DINode { | ||||
| 363 | friend class LLVMContextImpl; | ||||
| 364 | friend class MDNode; | ||||
| 365 | |||||
| 366 | DIGenericSubrange(LLVMContext &C, StorageType Storage, | ||||
| 367 | ArrayRef<Metadata *> Ops) | ||||
| 368 | : DINode(C, DIGenericSubrangeKind, Storage, | ||||
| 369 | dwarf::DW_TAG_generic_subrange, Ops) {} | ||||
| 370 | |||||
| 371 | ~DIGenericSubrange() = default; | ||||
| 372 | |||||
| 373 | static DIGenericSubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||
| 374 | Metadata *LowerBound, Metadata *UpperBound, | ||||
| 375 | Metadata *Stride, StorageType Storage, | ||||
| 376 | bool ShouldCreate = true); | ||||
| 377 | |||||
| 378 | TempDIGenericSubrange cloneImpl() const { | ||||
| 379 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||
| 380 | getRawUpperBound(), getRawStride()); | ||||
| 381 | } | ||||
| 382 | |||||
| 383 | public: | ||||
| 384 | DEFINE_MDNODE_GET(DIGenericSubrange, | ||||
| 385 | (Metadata * CountNode, Metadata *LowerBound, | ||||
| 386 | Metadata *UpperBound, Metadata *Stride), | ||||
| 387 | (CountNode, LowerBound, UpperBound, Stride)) | ||||
| 388 | |||||
| 389 | TempDIGenericSubrange clone() const { return cloneImpl(); } | ||||
| 390 | |||||
| 391 | Metadata *getRawCountNode() const { return getOperand(0).get(); } | ||||
| 392 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||
| 393 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||
| 394 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||
| 395 | |||||
| 396 | using BoundType = PointerUnion<DIVariable *, DIExpression *>; | ||||
| 397 | |||||
| 398 | BoundType getCount() const; | ||||
| 399 | BoundType getLowerBound() const; | ||||
| 400 | BoundType getUpperBound() const; | ||||
| 401 | BoundType getStride() const; | ||||
| 402 | |||||
| 403 | static bool classof(const Metadata *MD) { | ||||
| 404 | return MD->getMetadataID() == DIGenericSubrangeKind; | ||||
| 405 | } | ||||
| 406 | }; | ||||
| 407 | |||||
| 408 | /// Enumeration value. | ||||
| 409 | /// | ||||
| 410 | /// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no | ||||
| 411 | /// longer creates a type cycle. | ||||
| 412 | class DIEnumerator : public DINode { | ||||
| 413 | friend class LLVMContextImpl; | ||||
| 414 | friend class MDNode; | ||||
| 415 | |||||
| 416 | APInt Value; | ||||
| 417 | DIEnumerator(LLVMContext &C, StorageType Storage, const APInt &Value, | ||||
| 418 | bool IsUnsigned, ArrayRef<Metadata *> Ops) | ||||
| 419 | : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), | ||||
| 420 | Value(Value) { | ||||
| 421 | SubclassData32 = IsUnsigned; | ||||
| 422 | } | ||||
| 423 | DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, | ||||
| 424 | bool IsUnsigned, ArrayRef<Metadata *> Ops) | ||||
| 425 | : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, | ||||
| 426 | Ops) {} | ||||
| 427 | ~DIEnumerator() = default; | ||||
| 428 | |||||
| 429 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||
| 430 | bool IsUnsigned, StringRef Name, | ||||
| 431 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 432 | return getImpl(Context, Value, IsUnsigned, | ||||
| 433 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); | ||||
| 434 | } | ||||
| 435 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||
| 436 | bool IsUnsigned, MDString *Name, | ||||
| 437 | StorageType Storage, bool ShouldCreate = true); | ||||
| 438 | |||||
| 439 | TempDIEnumerator cloneImpl() const { | ||||
| 440 | return getTemporary(getContext(), getValue(), isUnsigned(), getName()); | ||||
| 441 | } | ||||
| 442 | |||||
| 443 | public: | ||||
| 444 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
| 445 | (int64_t Value, bool IsUnsigned, StringRef Name), | ||||
| 446 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||
| 447 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
| 448 | (int64_t Value, bool IsUnsigned, MDString *Name), | ||||
| 449 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||
| 450 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
| 451 | (APInt Value, bool IsUnsigned, StringRef Name), | ||||
| 452 | (Value, IsUnsigned, Name)) | ||||
| 453 | DEFINE_MDNODE_GET(DIEnumerator, | ||||
| 454 | (APInt Value, bool IsUnsigned, MDString *Name), | ||||
| 455 | (Value, IsUnsigned, Name)) | ||||
| 456 | |||||
| 457 | TempDIEnumerator clone() const { return cloneImpl(); } | ||||
| 458 | |||||
| 459 | const APInt &getValue() const { return Value; } | ||||
| 460 | bool isUnsigned() const { return SubclassData32; } | ||||
| 461 | StringRef getName() const { return getStringOperand(0); } | ||||
| 462 | |||||
| 463 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
| 464 | |||||
| 465 | static bool classof(const Metadata *MD) { | ||||
| 466 | return MD->getMetadataID() == DIEnumeratorKind; | ||||
| 467 | } | ||||
| 468 | }; | ||||
| 469 | |||||
| 470 | /// Base class for scope-like contexts. | ||||
| 471 | /// | ||||
| 472 | /// Base class for lexical scopes and types (which are also declaration | ||||
| 473 | /// contexts). | ||||
| 474 | /// | ||||
| 475 | /// TODO: Separate the concepts of declaration contexts and lexical scopes. | ||||
| 476 | class DIScope : public DINode { | ||||
| 477 | protected: | ||||
| 478 | DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
| 479 | ArrayRef<Metadata *> Ops) | ||||
| 480 | : DINode(C, ID, Storage, Tag, Ops) {} | ||||
| 481 | ~DIScope() = default; | ||||
| 482 | |||||
| 483 | public: | ||||
| 484 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
| 485 | |||||
| 486 | inline StringRef getFilename() const; | ||||
| 487 | inline StringRef getDirectory() const; | ||||
| 488 | inline Optional<StringRef> getSource() const; | ||||
| 489 | |||||
| 490 | StringRef getName() const; | ||||
| 491 | DIScope *getScope() const; | ||||
| 492 | |||||
| 493 | /// Return the raw underlying file. | ||||
| 494 | /// | ||||
| 495 | /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file (it | ||||
| 496 | /// \em is the file). If \c this is an \a DIFile, we need to return \c this. | ||||
| 497 | /// Otherwise, return the first operand, which is where all other subclasses | ||||
| 498 | /// store their file pointer. | ||||
| 499 | Metadata *getRawFile() const { | ||||
| 500 | return isa<DIFile>(this) ? const_cast<DIScope *>(this) | ||||
| 501 | : static_cast<Metadata *>(getOperand(0)); | ||||
| 502 | } | ||||
| 503 | |||||
| 504 | static bool classof(const Metadata *MD) { | ||||
| 505 | switch (MD->getMetadataID()) { | ||||
| 506 | default: | ||||
| 507 | return false; | ||||
| 508 | case DIBasicTypeKind: | ||||
| 509 | case DIStringTypeKind: | ||||
| 510 | case DIDerivedTypeKind: | ||||
| 511 | case DICompositeTypeKind: | ||||
| 512 | case DISubroutineTypeKind: | ||||
| 513 | case DIFileKind: | ||||
| 514 | case DICompileUnitKind: | ||||
| 515 | case DISubprogramKind: | ||||
| 516 | case DILexicalBlockKind: | ||||
| 517 | case DILexicalBlockFileKind: | ||||
| 518 | case DINamespaceKind: | ||||
| 519 | case DICommonBlockKind: | ||||
| 520 | case DIModuleKind: | ||||
| 521 | return true; | ||||
| 522 | } | ||||
| 523 | } | ||||
| 524 | }; | ||||
| 525 | |||||
| 526 | /// File. | ||||
| 527 | /// | ||||
| 528 | /// TODO: Merge with directory/file node (including users). | ||||
| 529 | /// TODO: Canonicalize paths on creation. | ||||
| 530 | class DIFile : public DIScope { | ||||
| 531 | friend class LLVMContextImpl; | ||||
| 532 | friend class MDNode; | ||||
| 533 | |||||
| 534 | public: | ||||
| 535 | /// Which algorithm (e.g. MD5) a checksum was generated with. | ||||
| 536 | /// | ||||
| 537 | /// The encoding is explicit because it is used directly in Bitcode. The | ||||
| 538 | /// value 0 is reserved to indicate the absence of a checksum in Bitcode. | ||||
| 539 | enum ChecksumKind { | ||||
| 540 | // The first variant was originally CSK_None, encoded as 0. The new | ||||
| 541 | // internal representation removes the need for this by wrapping the | ||||
| 542 | // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0 | ||||
| 543 | // encoding is reserved. | ||||
| 544 | CSK_MD5 = 1, | ||||
| 545 | CSK_SHA1 = 2, | ||||
| 546 | CSK_SHA256 = 3, | ||||
| 547 | CSK_Last = CSK_SHA256 // Should be last enumeration. | ||||
| 548 | }; | ||||
| 549 | |||||
| 550 | /// A single checksum, represented by a \a Kind and a \a Value (a string). | ||||
| 551 | template <typename T> | ||||
| 552 | struct ChecksumInfo { | ||||
| 553 | /// The kind of checksum which \a Value encodes. | ||||
| 554 | ChecksumKind Kind; | ||||
| 555 | /// The string value of the checksum. | ||||
| 556 | T Value; | ||||
| 557 | |||||
| 558 | ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) { } | ||||
| 559 | ~ChecksumInfo() = default; | ||||
| 560 | bool operator==(const ChecksumInfo<T> &X) const { | ||||
| 561 | return Kind == X.Kind && Value == X.Value; | ||||
| 562 | } | ||||
| 563 | bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } | ||||
| 564 | StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } | ||||
| 565 | }; | ||||
| 566 | |||||
| 567 | private: | ||||
| 568 | Optional<ChecksumInfo<MDString *>> Checksum; | ||||
| 569 | Optional<MDString *> Source; | ||||
| 570 | |||||
| 571 | DIFile(LLVMContext &C, StorageType Storage, | ||||
| 572 | Optional<ChecksumInfo<MDString *>> CS, Optional<MDString *> Src, | ||||
| 573 | ArrayRef<Metadata *> Ops) | ||||
| 574 | : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), | ||||
| 575 | Checksum(CS), Source(Src) {} | ||||
| 576 | ~DIFile() = default; | ||||
| 577 | |||||
| 578 | static DIFile *getImpl(LLVMContext &Context, StringRef Filename, | ||||
| 579 | StringRef Directory, | ||||
| 580 | Optional<ChecksumInfo<StringRef>> CS, | ||||
| 581 | Optional<StringRef> Source, | ||||
| 582 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 583 | Optional<ChecksumInfo<MDString *>> MDChecksum; | ||||
| 584 | if (CS) | ||||
| 585 | MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); | ||||
| 586 | return getImpl(Context, getCanonicalMDString(Context, Filename), | ||||
| 587 | getCanonicalMDString(Context, Directory), MDChecksum, | ||||
| 588 | Source ? Optional<MDString *>(getCanonicalMDString(Context, *Source)) : None, | ||||
| 589 | Storage, ShouldCreate); | ||||
| 590 | } | ||||
| 591 | static DIFile *getImpl(LLVMContext &Context, MDString *Filename, | ||||
| 592 | MDString *Directory, | ||||
| 593 | Optional<ChecksumInfo<MDString *>> CS, | ||||
| 594 | Optional<MDString *> Source, StorageType Storage, | ||||
| 595 | bool ShouldCreate = true); | ||||
| 596 | |||||
| 597 | TempDIFile cloneImpl() const { | ||||
| 598 | return getTemporary(getContext(), getFilename(), getDirectory(), | ||||
| 599 | getChecksum(), getSource()); | ||||
| 600 | } | ||||
| 601 | |||||
| 602 | public: | ||||
| 603 | DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory, | ||||
| 604 | Optional<ChecksumInfo<StringRef>> CS = None, | ||||
| 605 | Optional<StringRef> Source = None), | ||||
| 606 | (Filename, Directory, CS, Source)) | ||||
| 607 | DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory, | ||||
| 608 | Optional<ChecksumInfo<MDString *>> CS = None, | ||||
| 609 | Optional<MDString *> Source = None), | ||||
| 610 | (Filename, Directory, CS, Source)) | ||||
| 611 | |||||
| 612 | TempDIFile clone() const { return cloneImpl(); } | ||||
| 613 | |||||
| 614 | StringRef getFilename() const { return getStringOperand(0); } | ||||
| 615 | StringRef getDirectory() const { return getStringOperand(1); } | ||||
| 616 | Optional<ChecksumInfo<StringRef>> getChecksum() const { | ||||
| 617 | Optional<ChecksumInfo<StringRef>> StringRefChecksum; | ||||
| 618 | if (Checksum) | ||||
| 619 | StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); | ||||
| 620 | return StringRefChecksum; | ||||
| 621 | } | ||||
| 622 | Optional<StringRef> getSource() const { | ||||
| 623 | return Source ? Optional<StringRef>((*Source)->getString()) : None; | ||||
| 624 | } | ||||
| 625 | |||||
| 626 | MDString *getRawFilename() const { return getOperandAs<MDString>(0); } | ||||
| 627 | MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } | ||||
| 628 | Optional<ChecksumInfo<MDString *>> getRawChecksum() const { return Checksum; } | ||||
| 629 | Optional<MDString *> getRawSource() const { return Source; } | ||||
| 630 | |||||
| 631 | static StringRef getChecksumKindAsString(ChecksumKind CSKind); | ||||
| 632 | static Optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); | ||||
| 633 | |||||
| 634 | static bool classof(const Metadata *MD) { | ||||
| 635 | return MD->getMetadataID() == DIFileKind; | ||||
| 636 | } | ||||
| 637 | }; | ||||
| 638 | |||||
| 639 | StringRef DIScope::getFilename() const { | ||||
| 640 | if (auto *F = getFile()) | ||||
| 641 | return F->getFilename(); | ||||
| 642 | return ""; | ||||
| 643 | } | ||||
| 644 | |||||
| 645 | StringRef DIScope::getDirectory() const { | ||||
| 646 | if (auto *F = getFile()) | ||||
| 647 | return F->getDirectory(); | ||||
| 648 | return ""; | ||||
| 649 | } | ||||
| 650 | |||||
| 651 | Optional<StringRef> DIScope::getSource() const { | ||||
| 652 | if (auto *F = getFile()) | ||||
| 653 | return F->getSource(); | ||||
| 654 | return None; | ||||
| 655 | } | ||||
| 656 | |||||
| 657 | /// Base class for types. | ||||
| 658 | /// | ||||
| 659 | /// TODO: Remove the hardcoded name and context, since many types don't use | ||||
| 660 | /// them. | ||||
| 661 | /// TODO: Split up flags. | ||||
| 662 | class DIType : public DIScope { | ||||
| 663 | unsigned Line; | ||||
| 664 | DIFlags Flags; | ||||
| 665 | uint64_t SizeInBits; | ||||
| 666 | uint64_t OffsetInBits; | ||||
| 667 | uint32_t AlignInBits; | ||||
| 668 | |||||
| 669 | protected: | ||||
| 670 | DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
| 671 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 672 | uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||
| 673 | : DIScope(C, ID, Storage, Tag, Ops) { | ||||
| 674 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||
| 675 | } | ||||
| 676 | ~DIType() = default; | ||||
| 677 | |||||
| 678 | void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 679 | uint64_t OffsetInBits, DIFlags Flags) { | ||||
| 680 | this->Line = Line; | ||||
| 681 | this->Flags = Flags; | ||||
| 682 | this->SizeInBits = SizeInBits; | ||||
| 683 | this->AlignInBits = AlignInBits; | ||||
| 684 | this->OffsetInBits = OffsetInBits; | ||||
| 685 | } | ||||
| 686 | |||||
| 687 | /// Change fields in place. | ||||
| 688 | void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits, | ||||
| 689 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) { | ||||
| 690 | assert(isDistinct() && "Only distinct nodes can mutate")((void)0); | ||||
| 691 | setTag(Tag); | ||||
| 692 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||
| 693 | } | ||||
| 694 | |||||
| 695 | public: | ||||
| 696 | TempDIType clone() const { | ||||
| 697 | return TempDIType(cast<DIType>(MDNode::clone().release())); | ||||
| 698 | } | ||||
| 699 | |||||
| 700 | unsigned getLine() const { return Line; } | ||||
| 701 | uint64_t getSizeInBits() const { return SizeInBits; } | ||||
| 702 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||
| 703 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||
| 704 | uint64_t getOffsetInBits() const { return OffsetInBits; } | ||||
| 705 | DIFlags getFlags() const { return Flags; } | ||||
| 706 | |||||
| 707 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
| 708 | StringRef getName() const { return getStringOperand(2); } | ||||
| 709 | |||||
| 710 | |||||
| 711 | Metadata *getRawScope() const { return getOperand(1); } | ||||
| 712 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
| 713 | |||||
| 714 | /// Returns a new temporary DIType with updated Flags | ||||
| 715 | TempDIType cloneWithFlags(DIFlags NewFlags) const { | ||||
| 716 | auto NewTy = clone(); | ||||
| 717 | NewTy->Flags = NewFlags; | ||||
| 718 | return NewTy; | ||||
| 719 | } | ||||
| 720 | |||||
| 721 | bool isPrivate() const { | ||||
| 722 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||
| 723 | } | ||||
| 724 | bool isProtected() const { | ||||
| 725 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||
| 726 | } | ||||
| 727 | bool isPublic() const { | ||||
| 728 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||
| 729 | } | ||||
| 730 | bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } | ||||
| 731 | bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } | ||||
| 732 | bool isVirtual() const { return getFlags() & FlagVirtual; } | ||||
| 733 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
| 734 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||
| 735 | bool isObjcClassComplete() const { | ||||
| 736 | return getFlags() & FlagObjcClassComplete; | ||||
| 737 | } | ||||
| 738 | bool isVector() const { return getFlags() & FlagVector; } | ||||
| 739 | bool isBitField() const { return getFlags() & FlagBitField; } | ||||
| 740 | bool isStaticMember() const { return getFlags() & FlagStaticMember; } | ||||
| 741 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||
| 742 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||
| 743 | bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; } | ||||
| 744 | bool isTypePassByReference() const { | ||||
| 745 | return getFlags() & FlagTypePassByReference; | ||||
| 746 | } | ||||
| 747 | bool isBigEndian() const { return getFlags() & FlagBigEndian; } | ||||
| 748 | bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } | ||||
| 749 | bool getExportSymbols() const { return getFlags() & FlagExportSymbols; } | ||||
| 750 | |||||
| 751 | static bool classof(const Metadata *MD) { | ||||
| 752 | switch (MD->getMetadataID()) { | ||||
| 753 | default: | ||||
| 754 | return false; | ||||
| 755 | case DIBasicTypeKind: | ||||
| 756 | case DIStringTypeKind: | ||||
| 757 | case DIDerivedTypeKind: | ||||
| 758 | case DICompositeTypeKind: | ||||
| 759 | case DISubroutineTypeKind: | ||||
| 760 | return true; | ||||
| 761 | } | ||||
| 762 | } | ||||
| 763 | }; | ||||
| 764 | |||||
| 765 | /// Basic type, like 'int' or 'float'. | ||||
| 766 | /// | ||||
| 767 | /// TODO: Split out DW_TAG_unspecified_type. | ||||
| 768 | /// TODO: Drop unused accessors. | ||||
| 769 | class DIBasicType : public DIType { | ||||
| 770 | friend class LLVMContextImpl; | ||||
| 771 | friend class MDNode; | ||||
| 772 | |||||
| 773 | unsigned Encoding; | ||||
| 774 | |||||
| 775 | DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
| 776 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||
| 777 | DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||
| 778 | : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||
| 779 | Flags, Ops), | ||||
| 780 | Encoding(Encoding) {} | ||||
| 781 | ~DIBasicType() = default; | ||||
| 782 | |||||
| 783 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 784 | StringRef Name, uint64_t SizeInBits, | ||||
| 785 | uint32_t AlignInBits, unsigned Encoding, | ||||
| 786 | DIFlags Flags, StorageType Storage, | ||||
| 787 | bool ShouldCreate = true) { | ||||
| 788 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||
| 789 | SizeInBits, AlignInBits, Encoding, Flags, Storage, | ||||
| 790 | ShouldCreate); | ||||
| 791 | } | ||||
| 792 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 793 | MDString *Name, uint64_t SizeInBits, | ||||
| 794 | uint32_t AlignInBits, unsigned Encoding, | ||||
| 795 | DIFlags Flags, StorageType Storage, | ||||
| 796 | bool ShouldCreate = true); | ||||
| 797 | |||||
| 798 | TempDIBasicType cloneImpl() const { | ||||
| 799 | return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), | ||||
| 800 | getAlignInBits(), getEncoding(), getFlags()); | ||||
| 801 | } | ||||
| 802 | |||||
| 803 | public: | ||||
| 804 | DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), | ||||
| 805 | (Tag, Name, 0, 0, 0, FlagZero)) | ||||
| 806 | DEFINE_MDNODE_GET(DIBasicType, | ||||
| 807 | (unsigned Tag, StringRef Name, uint64_t SizeInBits), | ||||
| 808 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||
| 809 | DEFINE_MDNODE_GET(DIBasicType, | ||||
| 810 | (unsigned Tag, MDString *Name, uint64_t SizeInBits), | ||||
| 811 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||
| 812 | DEFINE_MDNODE_GET(DIBasicType, | ||||
| 813 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||
| 814 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||
| 815 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||
| 816 | DEFINE_MDNODE_GET(DIBasicType, | ||||
| 817 | (unsigned Tag, MDString *Name, uint64_t SizeInBits, | ||||
| 818 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||
| 819 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||
| 820 | |||||
| 821 | TempDIBasicType clone() const { return cloneImpl(); } | ||||
| 822 | |||||
| 823 | unsigned getEncoding() const { return Encoding; } | ||||
| 824 | |||||
| 825 | enum class Signedness { Signed, Unsigned }; | ||||
| 826 | |||||
| 827 | /// Return the signedness of this type, or None if this type is neither | ||||
| 828 | /// signed nor unsigned. | ||||
| 829 | Optional<Signedness> getSignedness() const; | ||||
| 830 | |||||
| 831 | static bool classof(const Metadata *MD) { | ||||
| 832 | return MD->getMetadataID() == DIBasicTypeKind; | ||||
| 833 | } | ||||
| 834 | }; | ||||
| 835 | |||||
| 836 | /// String type, Fortran CHARACTER(n) | ||||
| 837 | class DIStringType : public DIType { | ||||
| 838 | friend class LLVMContextImpl; | ||||
| 839 | friend class MDNode; | ||||
| 840 | |||||
| 841 | unsigned Encoding; | ||||
| 842 | |||||
| 843 | DIStringType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
| 844 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||
| 845 | ArrayRef<Metadata *> Ops) | ||||
| 846 | : DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||
| 847 | FlagZero, Ops), | ||||
| 848 | Encoding(Encoding) {} | ||||
| 849 | ~DIStringType() = default; | ||||
| 850 | |||||
| 851 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 852 | StringRef Name, Metadata *StringLength, | ||||
| 853 | Metadata *StrLenExp, uint64_t SizeInBits, | ||||
| 854 | uint32_t AlignInBits, unsigned Encoding, | ||||
| 855 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 856 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||
| 857 | StringLength, StrLenExp, SizeInBits, AlignInBits, Encoding, | ||||
| 858 | Storage, ShouldCreate); | ||||
| 859 | } | ||||
| 860 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 861 | MDString *Name, Metadata *StringLength, | ||||
| 862 | Metadata *StrLenExp, uint64_t SizeInBits, | ||||
| 863 | uint32_t AlignInBits, unsigned Encoding, | ||||
| 864 | StorageType Storage, bool ShouldCreate = true); | ||||
| 865 | |||||
| 866 | TempDIStringType cloneImpl() const { | ||||
| 867 | return getTemporary(getContext(), getTag(), getRawName(), | ||||
| 868 | getRawStringLength(), getRawStringLengthExp(), | ||||
| 869 | getSizeInBits(), getAlignInBits(), getEncoding()); | ||||
| 870 | } | ||||
| 871 | |||||
| 872 | public: | ||||
| 873 | DEFINE_MDNODE_GET(DIStringType, | ||||
| 874 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||
| 875 | uint32_t AlignInBits), | ||||
| 876 | (Tag, Name, nullptr, nullptr, SizeInBits, AlignInBits, 0)) | ||||
| 877 | DEFINE_MDNODE_GET(DIStringType, | ||||
| 878 | (unsigned Tag, MDString *Name, Metadata *StringLength, | ||||
| 879 | Metadata *StringLengthExp, uint64_t SizeInBits, | ||||
| 880 | uint32_t AlignInBits, unsigned Encoding), | ||||
| 881 | (Tag, Name, StringLength, StringLengthExp, SizeInBits, | ||||
| 882 | AlignInBits, Encoding)) | ||||
| 883 | DEFINE_MDNODE_GET(DIStringType, | ||||
| 884 | (unsigned Tag, StringRef Name, Metadata *StringLength, | ||||
| 885 | Metadata *StringLengthExp, uint64_t SizeInBits, | ||||
| 886 | uint32_t AlignInBits, unsigned Encoding), | ||||
| 887 | (Tag, Name, StringLength, StringLengthExp, SizeInBits, | ||||
| 888 | AlignInBits, Encoding)) | ||||
| 889 | |||||
| 890 | TempDIStringType clone() const { return cloneImpl(); } | ||||
| 891 | |||||
| 892 | static bool classof(const Metadata *MD) { | ||||
| 893 | return MD->getMetadataID() == DIStringTypeKind; | ||||
| 894 | } | ||||
| 895 | |||||
| 896 | DIVariable *getStringLength() const { | ||||
| 897 | return cast_or_null<DIVariable>(getRawStringLength()); | ||||
| 898 | } | ||||
| 899 | |||||
| 900 | DIExpression *getStringLengthExp() const { | ||||
| 901 | return cast_or_null<DIExpression>(getRawStringLengthExp()); | ||||
| 902 | } | ||||
| 903 | |||||
| 904 | unsigned getEncoding() const { return Encoding; } | ||||
| 905 | |||||
| 906 | Metadata *getRawStringLength() const { return getOperand(3); } | ||||
| 907 | |||||
| 908 | Metadata *getRawStringLengthExp() const { return getOperand(4); } | ||||
| 909 | }; | ||||
| 910 | |||||
| 911 | /// Derived types. | ||||
| 912 | /// | ||||
| 913 | /// This includes qualified types, pointers, references, friends, typedefs, and | ||||
| 914 | /// class members. | ||||
| 915 | /// | ||||
| 916 | /// TODO: Split out members (inheritance, fields, methods, etc.). | ||||
| 917 | class DIDerivedType : public DIType { | ||||
| 918 | friend class LLVMContextImpl; | ||||
| 919 | friend class MDNode; | ||||
| 920 | |||||
| 921 | /// The DWARF address space of the memory pointed to or referenced by a | ||||
| 922 | /// pointer or reference type respectively. | ||||
| 923 | Optional<unsigned> DWARFAddressSpace; | ||||
| 924 | |||||
| 925 | DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
| 926 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 927 | uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace, | ||||
| 928 | DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||
| 929 | : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, | ||||
| 930 | AlignInBits, OffsetInBits, Flags, Ops), | ||||
| 931 | DWARFAddressSpace(DWARFAddressSpace) {} | ||||
| 932 | ~DIDerivedType() = default; | ||||
| 933 | |||||
| 934 | static DIDerivedType * | ||||
| 935 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, | ||||
| 936 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
| 937 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
| 938 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
| 939 | Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true) { | ||||
| 940 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, | ||||
| 941 | Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, | ||||
| 942 | DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate); | ||||
| 943 | } | ||||
| 944 | static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 945 | MDString *Name, Metadata *File, unsigned Line, | ||||
| 946 | Metadata *Scope, Metadata *BaseType, | ||||
| 947 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 948 | uint64_t OffsetInBits, | ||||
| 949 | Optional<unsigned> DWARFAddressSpace, | ||||
| 950 | DIFlags Flags, Metadata *ExtraData, | ||||
| 951 | StorageType Storage, bool ShouldCreate = true); | ||||
| 952 | |||||
| 953 | TempDIDerivedType cloneImpl() const { | ||||
| 954 | return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), | ||||
| 955 | getScope(), getBaseType(), getSizeInBits(), | ||||
| 956 | getAlignInBits(), getOffsetInBits(), | ||||
| 957 | getDWARFAddressSpace(), getFlags(), getExtraData()); | ||||
| 958 | } | ||||
| 959 | |||||
| 960 | public: | ||||
| 961 | DEFINE_MDNODE_GET(DIDerivedType, | ||||
| 962 | (unsigned Tag, MDString *Name, Metadata *File, | ||||
| 963 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||
| 964 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 965 | uint64_t OffsetInBits, | ||||
| 966 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
| 967 | Metadata *ExtraData = nullptr), | ||||
| 968 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||
| 969 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||
| 970 | ExtraData)) | ||||
| 971 | DEFINE_MDNODE_GET(DIDerivedType, | ||||
| 972 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||
| 973 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
| 974 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
| 975 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||
| 976 | Metadata *ExtraData = nullptr), | ||||
| 977 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||
| 978 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||
| 979 | ExtraData)) | ||||
| 980 | |||||
| 981 | TempDIDerivedType clone() const { return cloneImpl(); } | ||||
| 982 | |||||
| 983 | /// Get the base type this is derived from. | ||||
| 984 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||
| 985 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||
| 986 | |||||
| 987 | /// \returns The DWARF address space of the memory pointed to or referenced by | ||||
| 988 | /// a pointer or reference type respectively. | ||||
| 989 | Optional<unsigned> getDWARFAddressSpace() const { return DWARFAddressSpace; } | ||||
| 990 | |||||
| 991 | /// Get extra data associated with this derived type. | ||||
| 992 | /// | ||||
| 993 | /// Class type for pointer-to-members, objective-c property node for ivars, | ||||
| 994 | /// global constant wrapper for static members, or virtual base pointer offset | ||||
| 995 | /// for inheritance. | ||||
| 996 | /// | ||||
| 997 | /// TODO: Separate out types that need this extra operand: pointer-to-member | ||||
| 998 | /// types and member fields (static members and ivars). | ||||
| 999 | Metadata *getExtraData() const { return getRawExtraData(); } | ||||
| 1000 | Metadata *getRawExtraData() const { return getOperand(4); } | ||||
| 1001 | |||||
| 1002 | /// Get casted version of extra data. | ||||
| 1003 | /// @{ | ||||
| 1004 | DIType *getClassType() const { | ||||
| 1005 | assert(getTag() == dwarf::DW_TAG_ptr_to_member_type)((void)0); | ||||
| 1006 | return cast_or_null<DIType>(getExtraData()); | ||||
| 1007 | } | ||||
| 1008 | |||||
| 1009 | DIObjCProperty *getObjCProperty() const { | ||||
| 1010 | return dyn_cast_or_null<DIObjCProperty>(getExtraData()); | ||||
| 1011 | } | ||||
| 1012 | |||||
| 1013 | uint32_t getVBPtrOffset() const { | ||||
| 1014 | assert(getTag() == dwarf::DW_TAG_inheritance)((void)0); | ||||
| 1015 | if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
| 1016 | if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue())) | ||||
| 1017 | return static_cast<uint32_t>(CI->getZExtValue()); | ||||
| 1018 | return 0; | ||||
| 1019 | } | ||||
| 1020 | |||||
| 1021 | Constant *getStorageOffsetInBits() const { | ||||
| 1022 | assert(getTag() == dwarf::DW_TAG_member && isBitField())((void)0); | ||||
| 1023 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
| 1024 | return C->getValue(); | ||||
| 1025 | return nullptr; | ||||
| 1026 | } | ||||
| 1027 | |||||
| 1028 | Constant *getConstant() const { | ||||
| 1029 | assert(getTag() == dwarf::DW_TAG_member && isStaticMember())((void)0); | ||||
| 1030 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
| 1031 | return C->getValue(); | ||||
| 1032 | return nullptr; | ||||
| 1033 | } | ||||
| 1034 | Constant *getDiscriminantValue() const { | ||||
| 1035 | assert(getTag() == dwarf::DW_TAG_member && !isStaticMember())((void)0); | ||||
| 1036 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) | ||||
| 1037 | return C->getValue(); | ||||
| 1038 | return nullptr; | ||||
| 1039 | } | ||||
| 1040 | /// @} | ||||
| 1041 | |||||
| 1042 | static bool classof(const Metadata *MD) { | ||||
| 1043 | return MD->getMetadataID() == DIDerivedTypeKind; | ||||
| 1044 | } | ||||
| 1045 | }; | ||||
| 1046 | |||||
| 1047 | /// Composite types. | ||||
| 1048 | /// | ||||
| 1049 | /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). | ||||
| 1050 | /// TODO: Create a custom, unrelated node for DW_TAG_array_type. | ||||
| 1051 | class DICompositeType : public DIType { | ||||
| 1052 | friend class LLVMContextImpl; | ||||
| 1053 | friend class MDNode; | ||||
| 1054 | |||||
| 1055 | unsigned RuntimeLang; | ||||
| 1056 | |||||
| 1057 | DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
| 1058 | unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, | ||||
| 1059 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
| 1060 | ArrayRef<Metadata *> Ops) | ||||
| 1061 | : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, | ||||
| 1062 | AlignInBits, OffsetInBits, Flags, Ops), | ||||
| 1063 | RuntimeLang(RuntimeLang) {} | ||||
| 1064 | ~DICompositeType() = default; | ||||
| 1065 | |||||
| 1066 | /// Change fields in place. | ||||
| 1067 | void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, | ||||
| 1068 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 1069 | uint64_t OffsetInBits, DIFlags Flags) { | ||||
| 1070 | assert(isDistinct() && "Only distinct nodes can mutate")((void)0); | ||||
| 1071 | assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate")((void)0); | ||||
| 1072 | this->RuntimeLang = RuntimeLang; | ||||
| 1073 | DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||
| 1074 | } | ||||
| 1075 | |||||
| 1076 | static DICompositeType * | ||||
| 1077 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, | ||||
| 1078 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
| 1079 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
| 1080 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||
| 1081 | DITemplateParameterArray TemplateParams, StringRef Identifier, | ||||
| 1082 | DIDerivedType *Discriminator, Metadata *DataLocation, | ||||
| 1083 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||
| 1084 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 1085 | return getImpl( | ||||
| 1086 | Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, | ||||
| 1087 | BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), | ||||
| 1088 | RuntimeLang, VTableHolder, TemplateParams.get(), | ||||
| 1089 | getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, | ||||
| 1090 | Associated, Allocated, Rank, Storage, ShouldCreate); | ||||
| 1091 | } | ||||
| 1092 | static DICompositeType * | ||||
| 1093 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||
| 1094 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||
| 1095 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||
| 1096 | DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, | ||||
| 1097 | Metadata *VTableHolder, Metadata *TemplateParams, | ||||
| 1098 | MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, | ||||
| 1099 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||
| 1100 | StorageType Storage, bool ShouldCreate = true); | ||||
| 1101 | |||||
| 1102 | TempDICompositeType cloneImpl() const { | ||||
| 1103 | return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), | ||||
| 1104 | getScope(), getBaseType(), getSizeInBits(), | ||||
| 1105 | getAlignInBits(), getOffsetInBits(), getFlags(), | ||||
| 1106 | getElements(), getRuntimeLang(), getVTableHolder(), | ||||
| 1107 | getTemplateParams(), getIdentifier(), | ||||
| 1108 | getDiscriminator(), getRawDataLocation(), | ||||
| 1109 | getRawAssociated(), getRawAllocated(), getRawRank()); | ||||
| 1110 | } | ||||
| 1111 | |||||
| 1112 | public: | ||||
| 1113 | DEFINE_MDNODE_GET( | ||||
| 1114 | DICompositeType, | ||||
| 1115 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||
| 1116 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||
| 1117 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
| 1118 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||
| 1119 | DITemplateParameterArray TemplateParams = nullptr, | ||||
| 1120 | StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, | ||||
| 1121 | Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, | ||||
| 1122 | Metadata *Allocated = nullptr, Metadata *Rank = nullptr), | ||||
| 1123 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||
| 1124 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||
| 1125 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) | ||||
| 1126 | DEFINE_MDNODE_GET( | ||||
| 1127 | DICompositeType, | ||||
| 1128 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, | ||||
| 1129 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, | ||||
| 1130 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||
| 1131 | Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, | ||||
| 1132 | Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, | ||||
| 1133 | Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, | ||||
| 1134 | Metadata *Associated = nullptr, Metadata *Allocated = nullptr, | ||||
| 1135 | Metadata *Rank = nullptr), | ||||
| 1136 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||
| 1137 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||
| 1138 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) | ||||
| 1139 | |||||
| 1140 | TempDICompositeType clone() const { return cloneImpl(); } | ||||
| 1141 | |||||
| 1142 | /// Get a DICompositeType with the given ODR identifier. | ||||
| 1143 | /// | ||||
| 1144 | /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped | ||||
| 1145 | /// DICompositeType for the given ODR \c Identifier. If none exists, creates | ||||
| 1146 | /// a new node. | ||||
| 1147 | /// | ||||
| 1148 | /// Else, returns \c nullptr. | ||||
| 1149 | static DICompositeType * | ||||
| 1150 | getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||
| 1151 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||
| 1152 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 1153 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||
| 1154 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||
| 1155 | Metadata *TemplateParams, Metadata *Discriminator, | ||||
| 1156 | Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, | ||||
| 1157 | Metadata *Rank); | ||||
| 1158 | static DICompositeType *getODRTypeIfExists(LLVMContext &Context, | ||||
| 1159 | MDString &Identifier); | ||||
| 1160 | |||||
| 1161 | /// Build a DICompositeType with the given ODR identifier. | ||||
| 1162 | /// | ||||
| 1163 | /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If | ||||
| 1164 | /// it doesn't exist, creates a new one. If it does exist and \a | ||||
| 1165 | /// isForwardDecl(), and the new arguments would be a definition, mutates the | ||||
| 1166 | /// the type in place. In either case, returns the type. | ||||
| 1167 | /// | ||||
| 1168 | /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns | ||||
| 1169 | /// nullptr. | ||||
| 1170 | static DICompositeType * | ||||
| 1171 | buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||
| 1172 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||
| 1173 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||
| 1174 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||
| 1175 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||
| 1176 | Metadata *TemplateParams, Metadata *Discriminator, | ||||
| 1177 | Metadata *DataLocation, Metadata *Associated, | ||||
| 1178 | Metadata *Allocated, Metadata *Rank); | ||||
| 1179 | |||||
| 1180 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||
| 1181 | DINodeArray getElements() const { | ||||
| 1182 | return cast_or_null<MDTuple>(getRawElements()); | ||||
| 1183 | } | ||||
| 1184 | DIType *getVTableHolder() const { | ||||
| 1185 | return cast_or_null<DIType>(getRawVTableHolder()); | ||||
| 1186 | } | ||||
| 1187 | DITemplateParameterArray getTemplateParams() const { | ||||
| 1188 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||
| 1189 | } | ||||
| 1190 | StringRef getIdentifier() const { return getStringOperand(7); } | ||||
| 1191 | unsigned getRuntimeLang() const { return RuntimeLang; } | ||||
| 1192 | |||||
| 1193 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||
| 1194 | Metadata *getRawElements() const { return getOperand(4); } | ||||
| 1195 | Metadata *getRawVTableHolder() const { return getOperand(5); } | ||||
| 1196 | Metadata *getRawTemplateParams() const { return getOperand(6); } | ||||
| 1197 | MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } | ||||
| 1198 | Metadata *getRawDiscriminator() const { return getOperand(8); } | ||||
| 1199 | DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); } | ||||
| 1200 | Metadata *getRawDataLocation() const { return getOperand(9); } | ||||
| 1201 | DIVariable *getDataLocation() const { | ||||
| 1202 | return dyn_cast_or_null<DIVariable>(getRawDataLocation()); | ||||
| 1203 | } | ||||
| 1204 | DIExpression *getDataLocationExp() const { | ||||
| 1205 | return dyn_cast_or_null<DIExpression>(getRawDataLocation()); | ||||
| 1206 | } | ||||
| 1207 | Metadata *getRawAssociated() const { return getOperand(10); } | ||||
| 1208 | DIVariable *getAssociated() const { | ||||
| 1209 | return dyn_cast_or_null<DIVariable>(getRawAssociated()); | ||||
| 1210 | } | ||||
| 1211 | DIExpression *getAssociatedExp() const { | ||||
| 1212 | return dyn_cast_or_null<DIExpression>(getRawAssociated()); | ||||
| 1213 | } | ||||
| 1214 | Metadata *getRawAllocated() const { return getOperand(11); } | ||||
| 1215 | DIVariable *getAllocated() const { | ||||
| 1216 | return dyn_cast_or_null<DIVariable>(getRawAllocated()); | ||||
| 1217 | } | ||||
| 1218 | DIExpression *getAllocatedExp() const { | ||||
| 1219 | return dyn_cast_or_null<DIExpression>(getRawAllocated()); | ||||
| 1220 | } | ||||
| 1221 | Metadata *getRawRank() const { return getOperand(12); } | ||||
| 1222 | ConstantInt *getRankConst() const { | ||||
| 1223 | if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawRank())) | ||||
| 1224 | return dyn_cast_or_null<ConstantInt>(MD->getValue()); | ||||
| 1225 | return nullptr; | ||||
| 1226 | } | ||||
| 1227 | DIExpression *getRankExp() const { | ||||
| 1228 | return dyn_cast_or_null<DIExpression>(getRawRank()); | ||||
| 1229 | } | ||||
| 1230 | |||||
| 1231 | /// Replace operands. | ||||
| 1232 | /// | ||||
| 1233 | /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision | ||||
| 1234 | /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track | ||||
| 1235 | /// of its movement if necessary. | ||||
| 1236 | /// @{ | ||||
| 1237 | void replaceElements(DINodeArray Elements) { | ||||
| 1238 | #ifndef NDEBUG1 | ||||
| 1239 | for (DINode *Op : getElements()) | ||||
| 1240 | assert(is_contained(Elements->operands(), Op) &&((void)0) | ||||
| 1241 | "Lost a member during member list replacement")((void)0); | ||||
| 1242 | #endif | ||||
| 1243 | replaceOperandWith(4, Elements.get()); | ||||
| 1244 | } | ||||
| 1245 | |||||
| 1246 | void replaceVTableHolder(DIType *VTableHolder) { | ||||
| 1247 | replaceOperandWith(5, VTableHolder); | ||||
| 1248 | } | ||||
| 1249 | |||||
| 1250 | void replaceTemplateParams(DITemplateParameterArray TemplateParams) { | ||||
| 1251 | replaceOperandWith(6, TemplateParams.get()); | ||||
| 1252 | } | ||||
| 1253 | /// @} | ||||
| 1254 | |||||
| 1255 | static bool classof(const Metadata *MD) { | ||||
| 1256 | return MD->getMetadataID() == DICompositeTypeKind; | ||||
| 1257 | } | ||||
| 1258 | }; | ||||
| 1259 | |||||
| 1260 | /// Type array for a subprogram. | ||||
| 1261 | /// | ||||
| 1262 | /// TODO: Fold the array of types in directly as operands. | ||||
| 1263 | class DISubroutineType : public DIType { | ||||
| 1264 | friend class LLVMContextImpl; | ||||
| 1265 | friend class MDNode; | ||||
| 1266 | |||||
| 1267 | /// The calling convention used with DW_AT_calling_convention. Actually of | ||||
| 1268 | /// type dwarf::CallingConvention. | ||||
| 1269 | uint8_t CC; | ||||
| 1270 | |||||
| 1271 | DISubroutineType(LLVMContext &C, StorageType Storage, DIFlags Flags, | ||||
| 1272 | uint8_t CC, ArrayRef<Metadata *> Ops) | ||||
| 1273 | : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, | ||||
| 1274 | 0, 0, 0, 0, Flags, Ops), | ||||
| 1275 | CC(CC) {} | ||||
| 1276 | ~DISubroutineType() = default; | ||||
| 1277 | |||||
| 1278 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||
| 1279 | uint8_t CC, DITypeRefArray TypeArray, | ||||
| 1280 | StorageType Storage, | ||||
| 1281 | bool ShouldCreate = true) { | ||||
| 1282 | return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); | ||||
| 1283 | } | ||||
| 1284 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||
| 1285 | uint8_t CC, Metadata *TypeArray, | ||||
| 1286 | StorageType Storage, | ||||
| 1287 | bool ShouldCreate = true); | ||||
| 1288 | |||||
| 1289 | TempDISubroutineType cloneImpl() const { | ||||
| 1290 | return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); | ||||
| 1291 | } | ||||
| 1292 | |||||
| 1293 | public: | ||||
| 1294 | DEFINE_MDNODE_GET(DISubroutineType, | ||||
| 1295 | (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), | ||||
| 1296 | (Flags, CC, TypeArray)) | ||||
| 1297 | DEFINE_MDNODE_GET(DISubroutineType, | ||||
| 1298 | (DIFlags Flags, uint8_t CC, Metadata *TypeArray), | ||||
| 1299 | (Flags, CC, TypeArray)) | ||||
| 1300 | |||||
| 1301 | TempDISubroutineType clone() const { return cloneImpl(); } | ||||
| 1302 | |||||
| 1303 | uint8_t getCC() const { return CC; } | ||||
| 1304 | |||||
| 1305 | DITypeRefArray getTypeArray() const { | ||||
| 1306 | return cast_or_null<MDTuple>(getRawTypeArray()); | ||||
| 1307 | } | ||||
| 1308 | |||||
| 1309 | Metadata *getRawTypeArray() const { return getOperand(3); } | ||||
| 1310 | |||||
| 1311 | static bool classof(const Metadata *MD) { | ||||
| 1312 | return MD->getMetadataID() == DISubroutineTypeKind; | ||||
| 1313 | } | ||||
| 1314 | }; | ||||
| 1315 | |||||
| 1316 | /// Compile unit. | ||||
| 1317 | class DICompileUnit : public DIScope { | ||||
| 1318 | friend class LLVMContextImpl; | ||||
| 1319 | friend class MDNode; | ||||
| 1320 | |||||
| 1321 | public: | ||||
| 1322 | enum DebugEmissionKind : unsigned { | ||||
| 1323 | NoDebug = 0, | ||||
| 1324 | FullDebug, | ||||
| 1325 | LineTablesOnly, | ||||
| 1326 | DebugDirectivesOnly, | ||||
| 1327 | LastEmissionKind = DebugDirectivesOnly | ||||
| 1328 | }; | ||||
| 1329 | |||||
| 1330 | enum class DebugNameTableKind : unsigned { | ||||
| 1331 | Default = 0, | ||||
| 1332 | GNU = 1, | ||||
| 1333 | None = 2, | ||||
| 1334 | LastDebugNameTableKind = None | ||||
| 1335 | }; | ||||
| 1336 | |||||
| 1337 | static Optional<DebugEmissionKind> getEmissionKind(StringRef Str); | ||||
| 1338 | static const char *emissionKindString(DebugEmissionKind EK); | ||||
| 1339 | static Optional<DebugNameTableKind> getNameTableKind(StringRef Str); | ||||
| 1340 | static const char *nameTableKindString(DebugNameTableKind PK); | ||||
| 1341 | |||||
| 1342 | private: | ||||
| 1343 | unsigned SourceLanguage; | ||||
| 1344 | bool IsOptimized; | ||||
| 1345 | unsigned RuntimeVersion; | ||||
| 1346 | unsigned EmissionKind; | ||||
| 1347 | uint64_t DWOId; | ||||
| 1348 | bool SplitDebugInlining; | ||||
| 1349 | bool DebugInfoForProfiling; | ||||
| 1350 | unsigned NameTableKind; | ||||
| 1351 | bool RangesBaseAddress; | ||||
| 1352 | |||||
| 1353 | DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, | ||||
| 1354 | bool IsOptimized, unsigned RuntimeVersion, | ||||
| 1355 | unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, | ||||
| 1356 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||
| 1357 | bool RangesBaseAddress, ArrayRef<Metadata *> Ops) | ||||
| 1358 | : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), | ||||
| 1359 | SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), | ||||
| 1360 | RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), | ||||
| 1361 | DWOId(DWOId), SplitDebugInlining(SplitDebugInlining), | ||||
| 1362 | DebugInfoForProfiling(DebugInfoForProfiling), | ||||
| 1363 | NameTableKind(NameTableKind), RangesBaseAddress(RangesBaseAddress) { | ||||
| 1364 | assert(Storage != Uniqued)((void)0); | ||||
| 1365 | } | ||||
| 1366 | ~DICompileUnit() = default; | ||||
| 1367 | |||||
| 1368 | static DICompileUnit * | ||||
| 1369 | getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, | ||||
| 1370 | StringRef Producer, bool IsOptimized, StringRef Flags, | ||||
| 1371 | unsigned RuntimeVersion, StringRef SplitDebugFilename, | ||||
| 1372 | unsigned EmissionKind, DICompositeTypeArray EnumTypes, | ||||
| 1373 | DIScopeArray RetainedTypes, | ||||
| 1374 | DIGlobalVariableExpressionArray GlobalVariables, | ||||
| 1375 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, | ||||
| 1376 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, | ||||
| 1377 | unsigned NameTableKind, bool RangesBaseAddress, StringRef SysRoot, | ||||
| 1378 | StringRef SDK, StorageType Storage, bool ShouldCreate = true) { | ||||
| 1379 | return getImpl( | ||||
| 1380 | Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), | ||||
| 1381 | IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, | ||||
| 1382 | getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, | ||||
| 1383 | EnumTypes.get(), RetainedTypes.get(), GlobalVariables.get(), | ||||
| 1384 | ImportedEntities.get(), Macros.get(), DWOId, SplitDebugInlining, | ||||
| 1385 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, | ||||
| 1386 | getCanonicalMDString(Context, SysRoot), | ||||
| 1387 | getCanonicalMDString(Context, SDK), Storage, ShouldCreate); | ||||
| 1388 | } | ||||
| 1389 | static DICompileUnit * | ||||
| 1390 | getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, | ||||
| 1391 | MDString *Producer, bool IsOptimized, MDString *Flags, | ||||
| 1392 | unsigned RuntimeVersion, MDString *SplitDebugFilename, | ||||
| 1393 | unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, | ||||
| 1394 | Metadata *GlobalVariables, Metadata *ImportedEntities, | ||||
| 1395 | Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, | ||||
| 1396 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||
| 1397 | bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, | ||||
| 1398 | StorageType Storage, bool ShouldCreate = true); | ||||
| 1399 | |||||
| 1400 | TempDICompileUnit cloneImpl() const { | ||||
| 1401 | return getTemporary( | ||||
| 1402 | getContext(), getSourceLanguage(), getFile(), getProducer(), | ||||
| 1403 | isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), | ||||
| 1404 | getEmissionKind(), getEnumTypes(), getRetainedTypes(), | ||||
| 1405 | getGlobalVariables(), getImportedEntities(), getMacros(), DWOId, | ||||
| 1406 | getSplitDebugInlining(), getDebugInfoForProfiling(), getNameTableKind(), | ||||
| 1407 | getRangesBaseAddress(), getSysRoot(), getSDK()); | ||||
| 1408 | } | ||||
| 1409 | |||||
| 1410 | public: | ||||
| 1411 | static void get() = delete; | ||||
| 1412 | static void getIfExists() = delete; | ||||
| 1413 | |||||
| 1414 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1415 | DICompileUnit,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1416 | (unsigned SourceLanguage, DIFile *File, StringRef Producer,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1417 | bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1418 | StringRef SplitDebugFilename, DebugEmissionKind EmissionKind,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1419 | DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1420 | DIGlobalVariableExpressionArray GlobalVariables,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1421 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1422 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1423 | DebugNameTableKind NameTableKind, bool RangesBaseAddress,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1424 | StringRef SysRoot, StringRef SDK),static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1425 | (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1426 | SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1427 | GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1428 | DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1429 | SysRoot, SDK))static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||
| 1430 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1431 | DICompileUnit,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1432 | (unsigned SourceLanguage, Metadata *File, MDString *Producer,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1433 | bool IsOptimized, MDString *Flags, unsigned RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1434 | MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1435 | Metadata *RetainedTypes, Metadata *GlobalVariables,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1436 | Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1437 | bool SplitDebugInlining, bool DebugInfoForProfiling,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1438 | unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1439 | MDString *SDK),static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1440 | (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1441 | SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1442 | GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1443 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot, SDK))static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||
| 1444 | |||||
| 1445 | TempDICompileUnit clone() const { return cloneImpl(); } | ||||
| 1446 | |||||
| 1447 | unsigned getSourceLanguage() const { return SourceLanguage; } | ||||
| 1448 | bool isOptimized() const { return IsOptimized; } | ||||
| 1449 | unsigned getRuntimeVersion() const { return RuntimeVersion; } | ||||
| 1450 | DebugEmissionKind getEmissionKind() const { | ||||
| 1451 | return (DebugEmissionKind)EmissionKind; | ||||
| 1452 | } | ||||
| 1453 | bool isDebugDirectivesOnly() const { | ||||
| 1454 | return EmissionKind == DebugDirectivesOnly; | ||||
| 1455 | } | ||||
| 1456 | bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; } | ||||
| 1457 | DebugNameTableKind getNameTableKind() const { | ||||
| 1458 | return (DebugNameTableKind)NameTableKind; | ||||
| 1459 | } | ||||
| 1460 | bool getRangesBaseAddress() const { return RangesBaseAddress; } | ||||
| 1461 | StringRef getProducer() const { return getStringOperand(1); } | ||||
| 1462 | StringRef getFlags() const { return getStringOperand(2); } | ||||
| 1463 | StringRef getSplitDebugFilename() const { return getStringOperand(3); } | ||||
| 1464 | DICompositeTypeArray getEnumTypes() const { | ||||
| 1465 | return cast_or_null<MDTuple>(getRawEnumTypes()); | ||||
| 1466 | } | ||||
| 1467 | DIScopeArray getRetainedTypes() const { | ||||
| 1468 | return cast_or_null<MDTuple>(getRawRetainedTypes()); | ||||
| 1469 | } | ||||
| 1470 | DIGlobalVariableExpressionArray getGlobalVariables() const { | ||||
| 1471 | return cast_or_null<MDTuple>(getRawGlobalVariables()); | ||||
| 1472 | } | ||||
| 1473 | DIImportedEntityArray getImportedEntities() const { | ||||
| 1474 | return cast_or_null<MDTuple>(getRawImportedEntities()); | ||||
| 1475 | } | ||||
| 1476 | DIMacroNodeArray getMacros() const { | ||||
| 1477 | return cast_or_null<MDTuple>(getRawMacros()); | ||||
| 1478 | } | ||||
| 1479 | uint64_t getDWOId() const { return DWOId; } | ||||
| 1480 | void setDWOId(uint64_t DwoId) { DWOId = DwoId; } | ||||
| 1481 | bool getSplitDebugInlining() const { return SplitDebugInlining; } | ||||
| 1482 | void setSplitDebugInlining(bool SplitDebugInlining) { | ||||
| 1483 | this->SplitDebugInlining = SplitDebugInlining; | ||||
| 1484 | } | ||||
| 1485 | StringRef getSysRoot() const { return getStringOperand(9); } | ||||
| 1486 | StringRef getSDK() const { return getStringOperand(10); } | ||||
| 1487 | |||||
| 1488 | MDString *getRawProducer() const { return getOperandAs<MDString>(1); } | ||||
| 1489 | MDString *getRawFlags() const { return getOperandAs<MDString>(2); } | ||||
| 1490 | MDString *getRawSplitDebugFilename() const { | ||||
| 1491 | return getOperandAs<MDString>(3); | ||||
| 1492 | } | ||||
| 1493 | Metadata *getRawEnumTypes() const { return getOperand(4); } | ||||
| 1494 | Metadata *getRawRetainedTypes() const { return getOperand(5); } | ||||
| 1495 | Metadata *getRawGlobalVariables() const { return getOperand(6); } | ||||
| 1496 | Metadata *getRawImportedEntities() const { return getOperand(7); } | ||||
| 1497 | Metadata *getRawMacros() const { return getOperand(8); } | ||||
| 1498 | MDString *getRawSysRoot() const { return getOperandAs<MDString>(9); } | ||||
| 1499 | MDString *getRawSDK() const { return getOperandAs<MDString>(10); } | ||||
| 1500 | |||||
| 1501 | /// Replace arrays. | ||||
| 1502 | /// | ||||
| 1503 | /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and | ||||
| 1504 | /// deleted on a uniquing collision. In practice, uniquing collisions on \a | ||||
| 1505 | /// DICompileUnit should be fairly rare. | ||||
| 1506 | /// @{ | ||||
| 1507 | void replaceEnumTypes(DICompositeTypeArray N) { | ||||
| 1508 | replaceOperandWith(4, N.get()); | ||||
| 1509 | } | ||||
| 1510 | void replaceRetainedTypes(DITypeArray N) { | ||||
| 1511 | replaceOperandWith(5, N.get()); | ||||
| 1512 | } | ||||
| 1513 | void replaceGlobalVariables(DIGlobalVariableExpressionArray N) { | ||||
| 1514 | replaceOperandWith(6, N.get()); | ||||
| 1515 | } | ||||
| 1516 | void replaceImportedEntities(DIImportedEntityArray N) { | ||||
| 1517 | replaceOperandWith(7, N.get()); | ||||
| 1518 | } | ||||
| 1519 | void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); } | ||||
| 1520 | /// @} | ||||
| 1521 | |||||
| 1522 | static bool classof(const Metadata *MD) { | ||||
| 1523 | return MD->getMetadataID() == DICompileUnitKind; | ||||
| 1524 | } | ||||
| 1525 | }; | ||||
| 1526 | |||||
| 1527 | /// A scope for locals. | ||||
| 1528 | /// | ||||
| 1529 | /// A legal scope for lexical blocks, local variables, and debug info | ||||
| 1530 | /// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a | ||||
| 1531 | /// DILexicalBlockFile. | ||||
| 1532 | class DILocalScope : public DIScope { | ||||
| 1533 | protected: | ||||
| 1534 | DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||
| 1535 | ArrayRef<Metadata *> Ops) | ||||
| 1536 | : DIScope(C, ID, Storage, Tag, Ops) {} | ||||
| 1537 | ~DILocalScope() = default; | ||||
| 1538 | |||||
| 1539 | public: | ||||
| 1540 | /// Get the subprogram for this scope. | ||||
| 1541 | /// | ||||
| 1542 | /// Return this if it's an \a DISubprogram; otherwise, look up the scope | ||||
| 1543 | /// chain. | ||||
| 1544 | DISubprogram *getSubprogram() const; | ||||
| 1545 | |||||
| 1546 | /// Get the first non DILexicalBlockFile scope of this scope. | ||||
| 1547 | /// | ||||
| 1548 | /// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the | ||||
| 1549 | /// scope chain. | ||||
| 1550 | DILocalScope *getNonLexicalBlockFileScope() const; | ||||
| 1551 | |||||
| 1552 | static bool classof(const Metadata *MD) { | ||||
| 1553 | return MD->getMetadataID() == DISubprogramKind || | ||||
| 1554 | MD->getMetadataID() == DILexicalBlockKind || | ||||
| 1555 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||
| 1556 | } | ||||
| 1557 | }; | ||||
| 1558 | |||||
| 1559 | /// Debug location. | ||||
| 1560 | /// | ||||
| 1561 | /// A debug location in source code, used for debug info and otherwise. | ||||
| 1562 | class DILocation : public MDNode { | ||||
| 1563 | friend class LLVMContextImpl; | ||||
| 1564 | friend class MDNode; | ||||
| 1565 | |||||
| 1566 | DILocation(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
| 1567 | unsigned Column, ArrayRef<Metadata *> MDs, bool ImplicitCode); | ||||
| 1568 | ~DILocation() { dropAllReferences(); } | ||||
| 1569 | |||||
| 1570 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||
| 1571 | unsigned Column, Metadata *Scope, | ||||
| 1572 | Metadata *InlinedAt, bool ImplicitCode, | ||||
| 1573 | StorageType Storage, bool ShouldCreate = true); | ||||
| 1574 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||
| 1575 | unsigned Column, DILocalScope *Scope, | ||||
| 1576 | DILocation *InlinedAt, bool ImplicitCode, | ||||
| 1577 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 1578 | return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), | ||||
| 1579 | static_cast<Metadata *>(InlinedAt), ImplicitCode, Storage, | ||||
| 1580 | ShouldCreate); | ||||
| 1581 | } | ||||
| 1582 | |||||
| 1583 | TempDILocation cloneImpl() const { | ||||
| 1584 | // Get the raw scope/inlinedAt since it is possible to invoke this on | ||||
| 1585 | // a DILocation containing temporary metadata. | ||||
| 1586 | return getTemporary(getContext(), getLine(), getColumn(), getRawScope(), | ||||
| 1587 | getRawInlinedAt(), isImplicitCode()); | ||||
| 1588 | } | ||||
| 1589 | |||||
| 1590 | public: | ||||
| 1591 | // Disallow replacing operands. | ||||
| 1592 | void replaceOperandWith(unsigned I, Metadata *New) = delete; | ||||
| 1593 | |||||
| 1594 | DEFINE_MDNODE_GET(DILocation, | ||||
| 1595 | (unsigned Line, unsigned Column, Metadata *Scope, | ||||
| 1596 | Metadata *InlinedAt = nullptr, bool ImplicitCode = false), | ||||
| 1597 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||
| 1598 | DEFINE_MDNODE_GET(DILocation, | ||||
| 1599 | (unsigned Line, unsigned Column, DILocalScope *Scope, | ||||
| 1600 | DILocation *InlinedAt = nullptr, | ||||
| 1601 | bool ImplicitCode = false), | ||||
| 1602 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||
| 1603 | |||||
| 1604 | /// Return a (temporary) clone of this. | ||||
| 1605 | TempDILocation clone() const { return cloneImpl(); } | ||||
| 1606 | |||||
| 1607 | unsigned getLine() const { return SubclassData32; } | ||||
| 1608 | unsigned getColumn() const { return SubclassData16; } | ||||
| 1609 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||
| 1610 | |||||
| 1611 | DILocation *getInlinedAt() const { | ||||
| 1612 | return cast_or_null<DILocation>(getRawInlinedAt()); | ||||
| 1613 | } | ||||
| 1614 | |||||
| 1615 | /// Check if the location corresponds to an implicit code. | ||||
| 1616 | /// When the ImplicitCode flag is true, it means that the Instruction | ||||
| 1617 | /// with this DILocation has been added by the front-end but it hasn't been | ||||
| 1618 | /// written explicitly by the user (e.g. cleanup stuff in C++ put on a closing | ||||
| 1619 | /// bracket). It's useful for code coverage to not show a counter on "empty" | ||||
| 1620 | /// lines. | ||||
| 1621 | bool isImplicitCode() const { return SubclassData1; } | ||||
| 1622 | void setImplicitCode(bool ImplicitCode) { SubclassData1 = ImplicitCode; } | ||||
| 1623 | |||||
| 1624 | DIFile *getFile() const { return getScope()->getFile(); } | ||||
| 1625 | StringRef getFilename() const { return getScope()->getFilename(); } | ||||
| 1626 | StringRef getDirectory() const { return getScope()->getDirectory(); } | ||||
| 1627 | Optional<StringRef> getSource() const { return getScope()->getSource(); } | ||||
| 1628 | |||||
| 1629 | /// Get the scope where this is inlined. | ||||
| 1630 | /// | ||||
| 1631 | /// Walk through \a getInlinedAt() and return \a getScope() from the deepest | ||||
| 1632 | /// location. | ||||
| 1633 | DILocalScope *getInlinedAtScope() const { | ||||
| 1634 | if (auto *IA
| ||||
| 1635 | return IA->getInlinedAtScope(); | ||||
| 1636 | return getScope(); | ||||
| 1637 | } | ||||
| 1638 | |||||
| 1639 | /// Get the DWARF discriminator. | ||||
| 1640 | /// | ||||
| 1641 | /// DWARF discriminators distinguish identical file locations between | ||||
| 1642 | /// instructions that are on different basic blocks. | ||||
| 1643 | /// | ||||
| 1644 | /// There are 3 components stored in discriminator, from lower bits: | ||||
| 1645 | /// | ||||
| 1646 | /// Base discriminator: assigned by AddDiscriminators pass to identify IRs | ||||
| 1647 | /// that are defined by the same source line, but | ||||
| 1648 | /// different basic blocks. | ||||
| 1649 | /// Duplication factor: assigned by optimizations that will scale down | ||||
| 1650 | /// the execution frequency of the original IR. | ||||
| 1651 | /// Copy Identifier: assigned by optimizations that clones the IR. | ||||
| 1652 | /// Each copy of the IR will be assigned an identifier. | ||||
| 1653 | /// | ||||
| 1654 | /// Encoding: | ||||
| 1655 | /// | ||||
| 1656 | /// The above 3 components are encoded into a 32bit unsigned integer in | ||||
| 1657 | /// order. If the lowest bit is 1, the current component is empty, and the | ||||
| 1658 | /// next component will start in the next bit. Otherwise, the current | ||||
| 1659 | /// component is non-empty, and its content starts in the next bit. The | ||||
| 1660 | /// value of each components is either 5 bit or 12 bit: if the 7th bit | ||||
| 1661 | /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the | ||||
| 1662 | /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to | ||||
| 1663 | /// represent the component. Thus, the number of bits used for a component | ||||
| 1664 | /// is either 0 (if it and all the next components are empty); 1 - if it is | ||||
| 1665 | /// empty; 7 - if its value is up to and including 0x1f (lsb and msb are both | ||||
| 1666 | /// 0); or 14, if its value is up to and including 0x1ff. Note that the last | ||||
| 1667 | /// component is also capped at 0x1ff, even in the case when both first | ||||
| 1668 | /// components are 0, and we'd technically have 29 bits available. | ||||
| 1669 | /// | ||||
| 1670 | /// For precise control over the data being encoded in the discriminator, | ||||
| 1671 | /// use encodeDiscriminator/decodeDiscriminator. | ||||
| 1672 | |||||
| 1673 | inline unsigned getDiscriminator() const; | ||||
| 1674 | |||||
| 1675 | // For the regular discriminator, it stands for all empty components if all | ||||
| 1676 | // the lowest 3 bits are non-zero and all higher 29 bits are unused(zero by | ||||
| 1677 | // default). Here we fully leverage the higher 29 bits for pseudo probe use. | ||||
| 1678 | // This is the format: | ||||
| 1679 | // [2:0] - 0x7 | ||||
| 1680 | // [31:3] - pseudo probe fields guaranteed to be non-zero as a whole | ||||
| 1681 | // So if the lower 3 bits is non-zero and the others has at least one | ||||
| 1682 | // non-zero bit, it guarantees to be a pseudo probe discriminator | ||||
| 1683 | inline static bool isPseudoProbeDiscriminator(unsigned Discriminator) { | ||||
| 1684 | return ((Discriminator & 0x7) == 0x7) && (Discriminator & 0xFFFFFFF8); | ||||
| 1685 | } | ||||
| 1686 | |||||
| 1687 | /// Returns a new DILocation with updated \p Discriminator. | ||||
| 1688 | inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const; | ||||
| 1689 | |||||
| 1690 | /// Returns a new DILocation with updated base discriminator \p BD. Only the | ||||
| 1691 | /// base discriminator is set in the new DILocation, the other encoded values | ||||
| 1692 | /// are elided. | ||||
| 1693 | /// If the discriminator cannot be encoded, the function returns None. | ||||
| 1694 | inline Optional<const DILocation *> cloneWithBaseDiscriminator(unsigned BD) const; | ||||
| 1695 | |||||
| 1696 | /// Returns the duplication factor stored in the discriminator, or 1 if no | ||||
| 1697 | /// duplication factor (or 0) is encoded. | ||||
| 1698 | inline unsigned getDuplicationFactor() const; | ||||
| 1699 | |||||
| 1700 | /// Returns the copy identifier stored in the discriminator. | ||||
| 1701 | inline unsigned getCopyIdentifier() const; | ||||
| 1702 | |||||
| 1703 | /// Returns the base discriminator stored in the discriminator. | ||||
| 1704 | inline unsigned getBaseDiscriminator() const; | ||||
| 1705 | |||||
| 1706 | /// Returns a new DILocation with duplication factor \p DF * current | ||||
| 1707 | /// duplication factor encoded in the discriminator. The current duplication | ||||
| 1708 | /// factor is as defined by getDuplicationFactor(). | ||||
| 1709 | /// Returns None if encoding failed. | ||||
| 1710 | inline Optional<const DILocation *> cloneByMultiplyingDuplicationFactor(unsigned DF) const; | ||||
| 1711 | |||||
| 1712 | /// When two instructions are combined into a single instruction we also | ||||
| 1713 | /// need to combine the original locations into a single location. | ||||
| 1714 | /// | ||||
| 1715 | /// When the locations are the same we can use either location. When they | ||||
| 1716 | /// differ, we need a third location which is distinct from either. If they | ||||
| 1717 | /// have the same file/line but have a different discriminator we could | ||||
| 1718 | /// create a location with a new discriminator. If they are from different | ||||
| 1719 | /// files/lines the location is ambiguous and can't be represented in a line | ||||
| 1720 | /// entry. In this case, if \p GenerateLocation is true, we will set the | ||||
| 1721 | /// merged debug location as line 0 of the nearest common scope where the two | ||||
| 1722 | /// locations are inlined from. | ||||
| 1723 | /// | ||||
| 1724 | /// \p GenerateLocation: Whether the merged location can be generated when | ||||
| 1725 | /// \p LocA and \p LocB differ. | ||||
| 1726 | static const DILocation *getMergedLocation(const DILocation *LocA, | ||||
| 1727 | const DILocation *LocB); | ||||
| 1728 | |||||
| 1729 | /// Try to combine the vector of locations passed as input in a single one. | ||||
| 1730 | /// This function applies getMergedLocation() repeatedly left-to-right. | ||||
| 1731 | /// | ||||
| 1732 | /// \p Locs: The locations to be merged. | ||||
| 1733 | static | ||||
| 1734 | const DILocation *getMergedLocations(ArrayRef<const DILocation *> Locs); | ||||
| 1735 | |||||
| 1736 | /// Return the masked discriminator value for an input discrimnator value D | ||||
| 1737 | /// (i.e. zero out the (B+1)-th and above bits for D (B is 0-base). | ||||
| 1738 | // Example: an input of (0x1FF, 7) returns 0xFF. | ||||
| 1739 | static unsigned getMaskedDiscriminator(unsigned D, unsigned B) { | ||||
| 1740 | return (D & getN1Bits(B)); | ||||
| 1741 | } | ||||
| 1742 | |||||
| 1743 | /// Return the bits used for base discriminators. | ||||
| 1744 | static unsigned getBaseDiscriminatorBits() { return getBaseFSBitEnd(); } | ||||
| 1745 | |||||
| 1746 | /// Returns the base discriminator for a given encoded discriminator \p D. | ||||
| 1747 | static unsigned | ||||
| 1748 | getBaseDiscriminatorFromDiscriminator(unsigned D, | ||||
| 1749 | bool IsFSDiscriminator = false) { | ||||
| 1750 | if (IsFSDiscriminator) | ||||
| 1751 | return getMaskedDiscriminator(D, getBaseDiscriminatorBits()); | ||||
| 1752 | return getUnsignedFromPrefixEncoding(D); | ||||
| 1753 | } | ||||
| 1754 | |||||
| 1755 | /// Raw encoding of the discriminator. APIs such as cloneWithDuplicationFactor | ||||
| 1756 | /// have certain special case behavior (e.g. treating empty duplication factor | ||||
| 1757 | /// as the value '1'). | ||||
| 1758 | /// This API, in conjunction with cloneWithDiscriminator, may be used to encode | ||||
| 1759 | /// the raw values provided. \p BD: base discriminator \p DF: duplication factor | ||||
| 1760 | /// \p CI: copy index | ||||
| 1761 | /// The return is None if the values cannot be encoded in 32 bits - for | ||||
| 1762 | /// example, values for BD or DF larger than 12 bits. Otherwise, the return | ||||
| 1763 | /// is the encoded value. | ||||
| 1764 | static Optional<unsigned> encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI); | ||||
| 1765 | |||||
| 1766 | /// Raw decoder for values in an encoded discriminator D. | ||||
| 1767 | static void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, | ||||
| 1768 | unsigned &CI); | ||||
| 1769 | |||||
| 1770 | /// Returns the duplication factor for a given encoded discriminator \p D, or | ||||
| 1771 | /// 1 if no value or 0 is encoded. | ||||
| 1772 | static unsigned getDuplicationFactorFromDiscriminator(unsigned D) { | ||||
| 1773 | if (EnableFSDiscriminator) | ||||
| 1774 | return 1; | ||||
| 1775 | D = getNextComponentInDiscriminator(D); | ||||
| 1776 | unsigned Ret = getUnsignedFromPrefixEncoding(D); | ||||
| 1777 | if (Ret == 0) | ||||
| 1778 | return 1; | ||||
| 1779 | return Ret; | ||||
| 1780 | } | ||||
| 1781 | |||||
| 1782 | /// Returns the copy identifier for a given encoded discriminator \p D. | ||||
| 1783 | static unsigned getCopyIdentifierFromDiscriminator(unsigned D) { | ||||
| 1784 | return getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator( | ||||
| 1785 | getNextComponentInDiscriminator(D))); | ||||
| 1786 | } | ||||
| 1787 | |||||
| 1788 | |||||
| 1789 | Metadata *getRawScope() const { return getOperand(0); } | ||||
| 1790 | Metadata *getRawInlinedAt() const { | ||||
| 1791 | if (getNumOperands() == 2) | ||||
| 1792 | return getOperand(1); | ||||
| 1793 | return nullptr; | ||||
| 1794 | } | ||||
| 1795 | |||||
| 1796 | static bool classof(const Metadata *MD) { | ||||
| 1797 | return MD->getMetadataID() == DILocationKind; | ||||
| 1798 | } | ||||
| 1799 | }; | ||||
| 1800 | |||||
| 1801 | /// Subprogram description. | ||||
| 1802 | class DISubprogram : public DILocalScope { | ||||
| 1803 | friend class LLVMContextImpl; | ||||
| 1804 | friend class MDNode; | ||||
| 1805 | |||||
| 1806 | unsigned Line; | ||||
| 1807 | unsigned ScopeLine; | ||||
| 1808 | unsigned VirtualIndex; | ||||
| 1809 | |||||
| 1810 | /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue | ||||
| 1811 | /// of method overrides from secondary bases by this amount. It may be | ||||
| 1812 | /// negative. | ||||
| 1813 | int ThisAdjustment; | ||||
| 1814 | |||||
| 1815 | public: | ||||
| 1816 | /// Debug info subprogram flags. | ||||
| 1817 | enum DISPFlags : uint32_t { | ||||
| 1818 | #define HANDLE_DISP_FLAG(ID, NAME) SPFlag##NAME = ID, | ||||
| 1819 | #define DISP_FLAG_LARGEST_NEEDED | ||||
| 1820 | #include "llvm/IR/DebugInfoFlags.def" | ||||
| 1821 | SPFlagNonvirtual = SPFlagZero, | ||||
| 1822 | SPFlagVirtuality = SPFlagVirtual | SPFlagPureVirtual, | ||||
| 1823 | LLVM_MARK_AS_BITMASK_ENUM(SPFlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = SPFlagLargest | ||||
| 1824 | }; | ||||
| 1825 | |||||
| 1826 | static DISPFlags getFlag(StringRef Flag); | ||||
| 1827 | static StringRef getFlagString(DISPFlags Flag); | ||||
| 1828 | |||||
| 1829 | /// Split up a flags bitfield for easier printing. | ||||
| 1830 | /// | ||||
| 1831 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||
| 1832 | /// any remaining (unrecognized) bits. | ||||
| 1833 | static DISPFlags splitFlags(DISPFlags Flags, | ||||
| 1834 | SmallVectorImpl<DISPFlags> &SplitFlags); | ||||
| 1835 | |||||
| 1836 | // Helper for converting old bitfields to new flags word. | ||||
| 1837 | static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, | ||||
| 1838 | bool IsOptimized, | ||||
| 1839 | unsigned Virtuality = SPFlagNonvirtual, | ||||
| 1840 | bool IsMainSubprogram = false) { | ||||
| 1841 | // We're assuming virtuality is the low-order field. | ||||
| 1842 | static_assert( | ||||
| 1843 | int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) && | ||||
| 1844 | int(SPFlagPureVirtual) == int(dwarf::DW_VIRTUALITY_pure_virtual), | ||||
| 1845 | "Virtuality constant mismatch"); | ||||
| 1846 | return static_cast<DISPFlags>( | ||||
| 1847 | (Virtuality & SPFlagVirtuality) | | ||||
| 1848 | (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) | | ||||
| 1849 | (IsDefinition ? SPFlagDefinition : SPFlagZero) | | ||||
| 1850 | (IsOptimized ? SPFlagOptimized : SPFlagZero) | | ||||
| 1851 | (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero)); | ||||
| 1852 | } | ||||
| 1853 | |||||
| 1854 | private: | ||||
| 1855 | DIFlags Flags; | ||||
| 1856 | DISPFlags SPFlags; | ||||
| 1857 | |||||
| 1858 | DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
| 1859 | unsigned ScopeLine, unsigned VirtualIndex, int ThisAdjustment, | ||||
| 1860 | DIFlags Flags, DISPFlags SPFlags, ArrayRef<Metadata *> Ops) | ||||
| 1861 | : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, | ||||
| 1862 | Ops), | ||||
| 1863 | Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex), | ||||
| 1864 | ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) { | ||||
| 1865 | static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range"); | ||||
| 1866 | } | ||||
| 1867 | ~DISubprogram() = default; | ||||
| 1868 | |||||
| 1869 | static DISubprogram * | ||||
| 1870 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||
| 1871 | StringRef LinkageName, DIFile *File, unsigned Line, | ||||
| 1872 | DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, | ||||
| 1873 | unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, | ||||
| 1874 | DISPFlags SPFlags, DICompileUnit *Unit, | ||||
| 1875 | DITemplateParameterArray TemplateParams, DISubprogram *Declaration, | ||||
| 1876 | DINodeArray RetainedNodes, DITypeArray ThrownTypes, | ||||
| 1877 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 1878 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
| 1879 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||
| 1880 | ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, | ||||
| 1881 | Flags, SPFlags, Unit, TemplateParams.get(), Declaration, | ||||
| 1882 | RetainedNodes.get(), ThrownTypes.get(), Storage, | ||||
| 1883 | ShouldCreate); | ||||
| 1884 | } | ||||
| 1885 | static DISubprogram *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
| 1886 | MDString *Name, MDString *LinkageName, | ||||
| 1887 | Metadata *File, unsigned Line, Metadata *Type, | ||||
| 1888 | unsigned ScopeLine, Metadata *ContainingType, | ||||
| 1889 | unsigned VirtualIndex, int ThisAdjustment, | ||||
| 1890 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||
| 1891 | Metadata *TemplateParams, Metadata *Declaration, | ||||
| 1892 | Metadata *RetainedNodes, Metadata *ThrownTypes, | ||||
| 1893 | StorageType Storage, bool ShouldCreate = true); | ||||
| 1894 | |||||
| 1895 | TempDISubprogram cloneImpl() const { | ||||
| 1896 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||
| 1897 | getFile(), getLine(), getType(), getScopeLine(), | ||||
| 1898 | getContainingType(), getVirtualIndex(), | ||||
| 1899 | getThisAdjustment(), getFlags(), getSPFlags(), | ||||
| 1900 | getUnit(), getTemplateParams(), getDeclaration(), | ||||
| 1901 | getRetainedNodes(), getThrownTypes()); | ||||
| 1902 | } | ||||
| 1903 | |||||
| 1904 | public: | ||||
| 1905 | DEFINE_MDNODE_GET( | ||||
| 1906 | DISubprogram, | ||||
| 1907 | (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, | ||||
| 1908 | unsigned Line, DISubroutineType *Type, unsigned ScopeLine, | ||||
| 1909 | DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||
| 1910 | DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, | ||||
| 1911 | DITemplateParameterArray TemplateParams = nullptr, | ||||
| 1912 | DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, | ||||
| 1913 | DITypeArray ThrownTypes = nullptr), | ||||
| 1914 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||
| 1915 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||
| 1916 | Declaration, RetainedNodes, ThrownTypes)) | ||||
| 1917 | |||||
| 1918 | DEFINE_MDNODE_GET( | ||||
| 1919 | DISubprogram, | ||||
| 1920 | (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, | ||||
| 1921 | unsigned Line, Metadata *Type, unsigned ScopeLine, | ||||
| 1922 | Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||
| 1923 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||
| 1924 | Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, | ||||
| 1925 | Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr), | ||||
| 1926 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||
| 1927 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||
| 1928 | Declaration, RetainedNodes, ThrownTypes)) | ||||
| 1929 | |||||
| 1930 | TempDISubprogram clone() const { return cloneImpl(); } | ||||
| 1931 | |||||
| 1932 | /// Returns a new temporary DISubprogram with updated Flags | ||||
| 1933 | TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { | ||||
| 1934 | auto NewSP = clone(); | ||||
| 1935 | NewSP->Flags = NewFlags; | ||||
| 1936 | return NewSP; | ||||
| 1937 | } | ||||
| 1938 | |||||
| 1939 | public: | ||||
| 1940 | unsigned getLine() const { return Line; } | ||||
| 1941 | unsigned getVirtuality() const { return getSPFlags() & SPFlagVirtuality; } | ||||
| 1942 | unsigned getVirtualIndex() const { return VirtualIndex; } | ||||
| 1943 | int getThisAdjustment() const { return ThisAdjustment; } | ||||
| 1944 | unsigned getScopeLine() const { return ScopeLine; } | ||||
| 1945 | void setScopeLine(unsigned L) { assert(isDistinct())((void)0); ScopeLine = L; } | ||||
| 1946 | DIFlags getFlags() const { return Flags; } | ||||
| 1947 | DISPFlags getSPFlags() const { return SPFlags; } | ||||
| 1948 | bool isLocalToUnit() const { return getSPFlags() & SPFlagLocalToUnit; } | ||||
| 1949 | bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } | ||||
| 1950 | bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } | ||||
| 1951 | bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } | ||||
| 1952 | |||||
| 1953 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
| 1954 | bool isPrivate() const { | ||||
| 1955 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||
| 1956 | } | ||||
| 1957 | bool isProtected() const { | ||||
| 1958 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||
| 1959 | } | ||||
| 1960 | bool isPublic() const { | ||||
| 1961 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||
| 1962 | } | ||||
| 1963 | bool isExplicit() const { return getFlags() & FlagExplicit; } | ||||
| 1964 | bool isPrototyped() const { return getFlags() & FlagPrototyped; } | ||||
| 1965 | bool areAllCallsDescribed() const { | ||||
| 1966 | return getFlags() & FlagAllCallsDescribed; | ||||
| 1967 | } | ||||
| 1968 | bool isPure() const { return getSPFlags() & SPFlagPure; } | ||||
| 1969 | bool isElemental() const { return getSPFlags() & SPFlagElemental; } | ||||
| 1970 | bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } | ||||
| 1971 | bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } | ||||
| 1972 | |||||
| 1973 | /// Check if this is deleted member function. | ||||
| 1974 | /// | ||||
| 1975 | /// Return true if this subprogram is a C++11 special | ||||
| 1976 | /// member function declared deleted. | ||||
| 1977 | bool isDeleted() const { return getSPFlags() & SPFlagDeleted; } | ||||
| 1978 | |||||
| 1979 | /// Check if this is reference-qualified. | ||||
| 1980 | /// | ||||
| 1981 | /// Return true if this subprogram is a C++11 reference-qualified non-static | ||||
| 1982 | /// member function (void foo() &). | ||||
| 1983 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||
| 1984 | |||||
| 1985 | /// Check if this is rvalue-reference-qualified. | ||||
| 1986 | /// | ||||
| 1987 | /// Return true if this subprogram is a C++11 rvalue-reference-qualified | ||||
| 1988 | /// non-static member function (void foo() &&). | ||||
| 1989 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||
| 1990 | |||||
| 1991 | /// Check if this is marked as noreturn. | ||||
| 1992 | /// | ||||
| 1993 | /// Return true if this subprogram is C++11 noreturn or C11 _Noreturn | ||||
| 1994 | bool isNoReturn() const { return getFlags() & FlagNoReturn; } | ||||
| 1995 | |||||
| 1996 | // Check if this routine is a compiler-generated thunk. | ||||
| 1997 | // | ||||
| 1998 | // Returns true if this subprogram is a thunk generated by the compiler. | ||||
| 1999 | bool isThunk() const { return getFlags() & FlagThunk; } | ||||
| 2000 | |||||
| 2001 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
| 2002 | |||||
| 2003 | StringRef getName() const { return getStringOperand(2); } | ||||
| 2004 | StringRef getLinkageName() const { return getStringOperand(3); } | ||||
| 2005 | /// Only used by clients of CloneFunction, and only right after the cloning. | ||||
| 2006 | void replaceLinkageName(MDString *LN) { replaceOperandWith(3, LN); } | ||||
| 2007 | |||||
| 2008 | DISubroutineType *getType() const { | ||||
| 2009 | return cast_or_null<DISubroutineType>(getRawType()); | ||||
| 2010 | } | ||||
| 2011 | DIType *getContainingType() const { | ||||
| 2012 | return cast_or_null<DIType>(getRawContainingType()); | ||||
| 2013 | } | ||||
| 2014 | |||||
| 2015 | DICompileUnit *getUnit() const { | ||||
| 2016 | return cast_or_null<DICompileUnit>(getRawUnit()); | ||||
| 2017 | } | ||||
| 2018 | void replaceUnit(DICompileUnit *CU) { replaceOperandWith(5, CU); } | ||||
| 2019 | DITemplateParameterArray getTemplateParams() const { | ||||
| 2020 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||
| 2021 | } | ||||
| 2022 | DISubprogram *getDeclaration() const { | ||||
| 2023 | return cast_or_null<DISubprogram>(getRawDeclaration()); | ||||
| 2024 | } | ||||
| 2025 | DINodeArray getRetainedNodes() const { | ||||
| 2026 | return cast_or_null<MDTuple>(getRawRetainedNodes()); | ||||
| 2027 | } | ||||
| 2028 | DITypeArray getThrownTypes() const { | ||||
| 2029 | return cast_or_null<MDTuple>(getRawThrownTypes()); | ||||
| 2030 | } | ||||
| 2031 | |||||
| 2032 | Metadata *getRawScope() const { return getOperand(1); } | ||||
| 2033 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
| 2034 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(3); } | ||||
| 2035 | Metadata *getRawType() const { return getOperand(4); } | ||||
| 2036 | Metadata *getRawUnit() const { return getOperand(5); } | ||||
| 2037 | Metadata *getRawDeclaration() const { return getOperand(6); } | ||||
| 2038 | Metadata *getRawRetainedNodes() const { return getOperand(7); } | ||||
| 2039 | Metadata *getRawContainingType() const { | ||||
| 2040 | return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr; | ||||
| 2041 | } | ||||
| 2042 | Metadata *getRawTemplateParams() const { | ||||
| 2043 | return getNumOperands() > 9 ? getOperandAs<Metadata>(9) : nullptr; | ||||
| 2044 | } | ||||
| 2045 | Metadata *getRawThrownTypes() const { | ||||
| 2046 | return getNumOperands() > 10 ? getOperandAs<Metadata>(10) : nullptr; | ||||
| 2047 | } | ||||
| 2048 | |||||
| 2049 | void replaceRawLinkageName(MDString *LinkageName) { | ||||
| 2050 | replaceOperandWith(3, LinkageName); | ||||
| 2051 | } | ||||
| 2052 | |||||
| 2053 | /// Check if this subprogram describes the given function. | ||||
| 2054 | /// | ||||
| 2055 | /// FIXME: Should this be looking through bitcasts? | ||||
| 2056 | bool describes(const Function *F) const; | ||||
| 2057 | |||||
| 2058 | static bool classof(const Metadata *MD) { | ||||
| 2059 | return MD->getMetadataID() == DISubprogramKind; | ||||
| 2060 | } | ||||
| 2061 | }; | ||||
| 2062 | |||||
| 2063 | class DILexicalBlockBase : public DILocalScope { | ||||
| 2064 | protected: | ||||
| 2065 | DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, | ||||
| 2066 | ArrayRef<Metadata *> Ops) | ||||
| 2067 | : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} | ||||
| 2068 | ~DILexicalBlockBase() = default; | ||||
| 2069 | |||||
| 2070 | public: | ||||
| 2071 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||
| 2072 | |||||
| 2073 | Metadata *getRawScope() const { return getOperand(1); } | ||||
| 2074 | |||||
| 2075 | static bool classof(const Metadata *MD) { | ||||
| 2076 | return MD->getMetadataID() == DILexicalBlockKind || | ||||
| 2077 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||
| 2078 | } | ||||
| 2079 | }; | ||||
| 2080 | |||||
| 2081 | class DILexicalBlock : public DILexicalBlockBase { | ||||
| 2082 | friend class LLVMContextImpl; | ||||
| 2083 | friend class MDNode; | ||||
| 2084 | |||||
| 2085 | unsigned Line; | ||||
| 2086 | uint16_t Column; | ||||
| 2087 | |||||
| 2088 | DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
| 2089 | unsigned Column, ArrayRef<Metadata *> Ops) | ||||
| 2090 | : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), | ||||
| 2091 | Column(Column) { | ||||
| 2092 | assert(Column < (1u << 16) && "Expected 16-bit column")((void)0); | ||||
| 2093 | } | ||||
| 2094 | ~DILexicalBlock() = default; | ||||
| 2095 | |||||
| 2096 | static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||
| 2097 | DIFile *File, unsigned Line, unsigned Column, | ||||
| 2098 | StorageType Storage, | ||||
| 2099 | bool ShouldCreate = true) { | ||||
| 2100 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||
| 2101 | static_cast<Metadata *>(File), Line, Column, Storage, | ||||
| 2102 | ShouldCreate); | ||||
| 2103 | } | ||||
| 2104 | |||||
| 2105 | static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
| 2106 | Metadata *File, unsigned Line, unsigned Column, | ||||
| 2107 | StorageType Storage, bool ShouldCreate = true); | ||||
| 2108 | |||||
| 2109 | TempDILexicalBlock cloneImpl() const { | ||||
| 2110 | return getTemporary(getContext(), getScope(), getFile(), getLine(), | ||||
| 2111 | getColumn()); | ||||
| 2112 | } | ||||
| 2113 | |||||
| 2114 | public: | ||||
| 2115 | DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File, | ||||
| 2116 | unsigned Line, unsigned Column), | ||||
| 2117 | (Scope, File, Line, Column)) | ||||
| 2118 | DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File, | ||||
| 2119 | unsigned Line, unsigned Column), | ||||
| 2120 | (Scope, File, Line, Column)) | ||||
| 2121 | |||||
| 2122 | TempDILexicalBlock clone() const { return cloneImpl(); } | ||||
| 2123 | |||||
| 2124 | unsigned getLine() const { return Line; } | ||||
| 2125 | unsigned getColumn() const { return Column; } | ||||
| 2126 | |||||
| 2127 | static bool classof(const Metadata *MD) { | ||||
| 2128 | return MD->getMetadataID() == DILexicalBlockKind; | ||||
| 2129 | } | ||||
| 2130 | }; | ||||
| 2131 | |||||
| 2132 | class DILexicalBlockFile : public DILexicalBlockBase { | ||||
| 2133 | friend class LLVMContextImpl; | ||||
| 2134 | friend class MDNode; | ||||
| 2135 | |||||
| 2136 | unsigned Discriminator; | ||||
| 2137 | |||||
| 2138 | DILexicalBlockFile(LLVMContext &C, StorageType Storage, | ||||
| 2139 | unsigned Discriminator, ArrayRef<Metadata *> Ops) | ||||
| 2140 | : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), | ||||
| 2141 | Discriminator(Discriminator) {} | ||||
| 2142 | ~DILexicalBlockFile() = default; | ||||
| 2143 | |||||
| 2144 | static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||
| 2145 | DIFile *File, unsigned Discriminator, | ||||
| 2146 | StorageType Storage, | ||||
| 2147 | bool ShouldCreate = true) { | ||||
| 2148 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||
| 2149 | static_cast<Metadata *>(File), Discriminator, Storage, | ||||
| 2150 | ShouldCreate); | ||||
| 2151 | } | ||||
| 2152 | |||||
| 2153 | static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
| 2154 | Metadata *File, unsigned Discriminator, | ||||
| 2155 | StorageType Storage, | ||||
| 2156 | bool ShouldCreate = true); | ||||
| 2157 | |||||
| 2158 | TempDILexicalBlockFile cloneImpl() const { | ||||
| 2159 | return getTemporary(getContext(), getScope(), getFile(), | ||||
| 2160 | getDiscriminator()); | ||||
| 2161 | } | ||||
| 2162 | |||||
| 2163 | public: | ||||
| 2164 | DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File, | ||||
| 2165 | unsigned Discriminator), | ||||
| 2166 | (Scope, File, Discriminator)) | ||||
| 2167 | DEFINE_MDNODE_GET(DILexicalBlockFile, | ||||
| 2168 | (Metadata * Scope, Metadata *File, unsigned Discriminator), | ||||
| 2169 | (Scope, File, Discriminator)) | ||||
| 2170 | |||||
| 2171 | TempDILexicalBlockFile clone() const { return cloneImpl(); } | ||||
| 2172 | unsigned getDiscriminator() const { return Discriminator; } | ||||
| 2173 | |||||
| 2174 | static bool classof(const Metadata *MD) { | ||||
| 2175 | return MD->getMetadataID() == DILexicalBlockFileKind; | ||||
| 2176 | } | ||||
| 2177 | }; | ||||
| 2178 | |||||
| 2179 | unsigned DILocation::getDiscriminator() const { | ||||
| 2180 | if (auto *F = dyn_cast<DILexicalBlockFile>(getScope())) | ||||
| 2181 | return F->getDiscriminator(); | ||||
| 2182 | return 0; | ||||
| 2183 | } | ||||
| 2184 | |||||
| 2185 | const DILocation * | ||||
| 2186 | DILocation::cloneWithDiscriminator(unsigned Discriminator) const { | ||||
| 2187 | DIScope *Scope = getScope(); | ||||
| 2188 | // Skip all parent DILexicalBlockFile that already have a discriminator | ||||
| 2189 | // assigned. We do not want to have nested DILexicalBlockFiles that have | ||||
| 2190 | // mutliple discriminators because only the leaf DILexicalBlockFile's | ||||
| 2191 | // dominator will be used. | ||||
| 2192 | for (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope); | ||||
| 2193 | LBF && LBF->getDiscriminator() != 0; | ||||
| 2194 | LBF = dyn_cast<DILexicalBlockFile>(Scope)) | ||||
| 2195 | Scope = LBF->getScope(); | ||||
| 2196 | DILexicalBlockFile *NewScope = | ||||
| 2197 | DILexicalBlockFile::get(getContext(), Scope, getFile(), Discriminator); | ||||
| 2198 | return DILocation::get(getContext(), getLine(), getColumn(), NewScope, | ||||
| 2199 | getInlinedAt()); | ||||
| 2200 | } | ||||
| 2201 | |||||
| 2202 | unsigned DILocation::getBaseDiscriminator() const { | ||||
| 2203 | return getBaseDiscriminatorFromDiscriminator(getDiscriminator(), | ||||
| 2204 | EnableFSDiscriminator); | ||||
| 2205 | } | ||||
| 2206 | |||||
| 2207 | unsigned DILocation::getDuplicationFactor() const { | ||||
| 2208 | return getDuplicationFactorFromDiscriminator(getDiscriminator()); | ||||
| 2209 | } | ||||
| 2210 | |||||
| 2211 | unsigned DILocation::getCopyIdentifier() const { | ||||
| 2212 | return getCopyIdentifierFromDiscriminator(getDiscriminator()); | ||||
| 2213 | } | ||||
| 2214 | |||||
| 2215 | Optional<const DILocation *> DILocation::cloneWithBaseDiscriminator(unsigned D) const { | ||||
| 2216 | unsigned BD, DF, CI; | ||||
| 2217 | |||||
| 2218 | if (EnableFSDiscriminator) { | ||||
| 2219 | BD = getBaseDiscriminator(); | ||||
| 2220 | if (D == BD) | ||||
| 2221 | return this; | ||||
| 2222 | return cloneWithDiscriminator(D); | ||||
| 2223 | } | ||||
| 2224 | |||||
| 2225 | decodeDiscriminator(getDiscriminator(), BD, DF, CI); | ||||
| 2226 | if (D == BD) | ||||
| 2227 | return this; | ||||
| 2228 | if (Optional<unsigned> Encoded = encodeDiscriminator(D, DF, CI)) | ||||
| 2229 | return cloneWithDiscriminator(*Encoded); | ||||
| 2230 | return None; | ||||
| 2231 | } | ||||
| 2232 | |||||
| 2233 | Optional<const DILocation *> DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const { | ||||
| 2234 | assert(!EnableFSDiscriminator && "FSDiscriminator should not call this.")((void)0); | ||||
| 2235 | |||||
| 2236 | DF *= getDuplicationFactor(); | ||||
| 2237 | if (DF <= 1) | ||||
| 2238 | return this; | ||||
| 2239 | |||||
| 2240 | unsigned BD = getBaseDiscriminator(); | ||||
| 2241 | unsigned CI = getCopyIdentifier(); | ||||
| 2242 | if (Optional<unsigned> D = encodeDiscriminator(BD, DF, CI)) | ||||
| 2243 | return cloneWithDiscriminator(*D); | ||||
| 2244 | return None; | ||||
| 2245 | } | ||||
| 2246 | |||||
| 2247 | class DINamespace : public DIScope { | ||||
| 2248 | friend class LLVMContextImpl; | ||||
| 2249 | friend class MDNode; | ||||
| 2250 | |||||
| 2251 | unsigned ExportSymbols : 1; | ||||
| 2252 | |||||
| 2253 | DINamespace(LLVMContext &Context, StorageType Storage, bool ExportSymbols, | ||||
| 2254 | ArrayRef<Metadata *> Ops) | ||||
| 2255 | : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, | ||||
| 2256 | Ops), | ||||
| 2257 | ExportSymbols(ExportSymbols) {} | ||||
| 2258 | ~DINamespace() = default; | ||||
| 2259 | |||||
| 2260 | static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
| 2261 | StringRef Name, bool ExportSymbols, | ||||
| 2262 | StorageType Storage, bool ShouldCreate = true) { | ||||
| 2263 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
| 2264 | ExportSymbols, Storage, ShouldCreate); | ||||
| 2265 | } | ||||
| 2266 | static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
| 2267 | MDString *Name, bool ExportSymbols, | ||||
| 2268 | StorageType Storage, bool ShouldCreate = true); | ||||
| 2269 | |||||
| 2270 | TempDINamespace cloneImpl() const { | ||||
| 2271 | return getTemporary(getContext(), getScope(), getName(), | ||||
| 2272 | getExportSymbols()); | ||||
| 2273 | } | ||||
| 2274 | |||||
| 2275 | public: | ||||
| 2276 | DEFINE_MDNODE_GET(DINamespace, | ||||
| 2277 | (DIScope *Scope, StringRef Name, bool ExportSymbols), | ||||
| 2278 | (Scope, Name, ExportSymbols)) | ||||
| 2279 | DEFINE_MDNODE_GET(DINamespace, | ||||
| 2280 | (Metadata *Scope, MDString *Name, bool ExportSymbols), | ||||
| 2281 | (Scope, Name, ExportSymbols)) | ||||
| 2282 | |||||
| 2283 | TempDINamespace clone() const { return cloneImpl(); } | ||||
| 2284 | |||||
| 2285 | bool getExportSymbols() const { return ExportSymbols; } | ||||
| 2286 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
| 2287 | StringRef getName() const { return getStringOperand(2); } | ||||
| 2288 | |||||
| 2289 | Metadata *getRawScope() const { return getOperand(1); } | ||||
| 2290 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
| 2291 | |||||
| 2292 | static bool classof(const Metadata *MD) { | ||||
| 2293 | return MD->getMetadataID() == DINamespaceKind; | ||||
| 2294 | } | ||||
| 2295 | }; | ||||
| 2296 | |||||
| 2297 | /// Represents a module in the programming language, for example, a Clang | ||||
| 2298 | /// module, or a Fortran module. | ||||
| 2299 | class DIModule : public DIScope { | ||||
| 2300 | friend class LLVMContextImpl; | ||||
| 2301 | friend class MDNode; | ||||
| 2302 | unsigned LineNo; | ||||
| 2303 | bool IsDecl; | ||||
| 2304 | |||||
| 2305 | DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||
| 2306 | bool IsDecl, ArrayRef<Metadata *> Ops) | ||||
| 2307 | : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops), | ||||
| 2308 | LineNo(LineNo), IsDecl(IsDecl) {} | ||||
| 2309 | ~DIModule() = default; | ||||
| 2310 | |||||
| 2311 | static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope, | ||||
| 2312 | StringRef Name, StringRef ConfigurationMacros, | ||||
| 2313 | StringRef IncludePath, StringRef APINotesFile, | ||||
| 2314 | unsigned LineNo, bool IsDecl, StorageType Storage, | ||||
| 2315 | bool ShouldCreate = true) { | ||||
| 2316 | return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name), | ||||
| 2317 | getCanonicalMDString(Context, ConfigurationMacros), | ||||
| 2318 | getCanonicalMDString(Context, IncludePath), | ||||
| 2319 | getCanonicalMDString(Context, APINotesFile), LineNo, IsDecl, | ||||
| 2320 | Storage, ShouldCreate); | ||||
| 2321 | } | ||||
| 2322 | static DIModule *getImpl(LLVMContext &Context, Metadata *File, | ||||
| 2323 | Metadata *Scope, MDString *Name, | ||||
| 2324 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||
| 2325 | MDString *APINotesFile, unsigned LineNo, bool IsDecl, | ||||
| 2326 | StorageType Storage, bool ShouldCreate = true); | ||||
| 2327 | |||||
| 2328 | TempDIModule cloneImpl() const { | ||||
| 2329 | return getTemporary(getContext(), getFile(), getScope(), getName(), | ||||
| 2330 | getConfigurationMacros(), getIncludePath(), | ||||
| 2331 | getAPINotesFile(), getLineNo(), getIsDecl()); | ||||
| 2332 | } | ||||
| 2333 | |||||
| 2334 | public: | ||||
| 2335 | DEFINE_MDNODE_GET(DIModule, | ||||
| 2336 | (DIFile * File, DIScope *Scope, StringRef Name, | ||||
| 2337 | StringRef ConfigurationMacros, StringRef IncludePath, | ||||
| 2338 | StringRef APINotesFile, unsigned LineNo, | ||||
| 2339 | bool IsDecl = false), | ||||
| 2340 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||
| 2341 | APINotesFile, LineNo, IsDecl)) | ||||
| 2342 | DEFINE_MDNODE_GET(DIModule, | ||||
| 2343 | (Metadata * File, Metadata *Scope, MDString *Name, | ||||
| 2344 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||
| 2345 | MDString *APINotesFile, unsigned LineNo, | ||||
| 2346 | bool IsDecl = false), | ||||
| 2347 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||
| 2348 | APINotesFile, LineNo, IsDecl)) | ||||
| 2349 | |||||
| 2350 | TempDIModule clone() const { return cloneImpl(); } | ||||
| 2351 | |||||
| 2352 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
| 2353 | StringRef getName() const { return getStringOperand(2); } | ||||
| 2354 | StringRef getConfigurationMacros() const { return getStringOperand(3); } | ||||
| 2355 | StringRef getIncludePath() const { return getStringOperand(4); } | ||||
| 2356 | StringRef getAPINotesFile() const { return getStringOperand(5); } | ||||
| 2357 | unsigned getLineNo() const { return LineNo; } | ||||
| 2358 | bool getIsDecl() const { return IsDecl; } | ||||
| 2359 | |||||
| 2360 | Metadata *getRawScope() const { return getOperand(1); } | ||||
| 2361 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
| 2362 | MDString *getRawConfigurationMacros() const { | ||||
| 2363 | return getOperandAs<MDString>(3); | ||||
| 2364 | } | ||||
| 2365 | MDString *getRawIncludePath() const { return getOperandAs<MDString>(4); } | ||||
| 2366 | MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(5); } | ||||
| 2367 | |||||
| 2368 | static bool classof(const Metadata *MD) { | ||||
| 2369 | return MD->getMetadataID() == DIModuleKind; | ||||
| 2370 | } | ||||
| 2371 | }; | ||||
| 2372 | |||||
| 2373 | /// Base class for template parameters. | ||||
| 2374 | class DITemplateParameter : public DINode { | ||||
| 2375 | protected: | ||||
| 2376 | bool IsDefault; | ||||
| 2377 | |||||
| 2378 | DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, | ||||
| 2379 | unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops) | ||||
| 2380 | : DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {} | ||||
| 2381 | ~DITemplateParameter() = default; | ||||
| 2382 | |||||
| 2383 | public: | ||||
| 2384 | StringRef getName() const { return getStringOperand(0); } | ||||
| 2385 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
| 2386 | |||||
| 2387 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
| 2388 | Metadata *getRawType() const { return getOperand(1); } | ||||
| 2389 | bool isDefault() const { return IsDefault; } | ||||
| 2390 | |||||
| 2391 | static bool classof(const Metadata *MD) { | ||||
| 2392 | return MD->getMetadataID() == DITemplateTypeParameterKind || | ||||
| 2393 | MD->getMetadataID() == DITemplateValueParameterKind; | ||||
| 2394 | } | ||||
| 2395 | }; | ||||
| 2396 | |||||
| 2397 | class DITemplateTypeParameter : public DITemplateParameter { | ||||
| 2398 | friend class LLVMContextImpl; | ||||
| 2399 | friend class MDNode; | ||||
| 2400 | |||||
| 2401 | DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, | ||||
| 2402 | bool IsDefault, ArrayRef<Metadata *> Ops) | ||||
| 2403 | : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, | ||||
| 2404 | dwarf::DW_TAG_template_type_parameter, IsDefault, | ||||
| 2405 | Ops) {} | ||||
| 2406 | ~DITemplateTypeParameter() = default; | ||||
| 2407 | |||||
| 2408 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, | ||||
| 2409 | DIType *Type, bool IsDefault, | ||||
| 2410 | StorageType Storage, | ||||
| 2411 | bool ShouldCreate = true) { | ||||
| 2412 | return getImpl(Context, getCanonicalMDString(Context, Name), Type, | ||||
| 2413 | IsDefault, Storage, ShouldCreate); | ||||
| 2414 | } | ||||
| 2415 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, | ||||
| 2416 | Metadata *Type, bool IsDefault, | ||||
| 2417 | StorageType Storage, | ||||
| 2418 | bool ShouldCreate = true); | ||||
| 2419 | |||||
| 2420 | TempDITemplateTypeParameter cloneImpl() const { | ||||
| 2421 | return getTemporary(getContext(), getName(), getType(), isDefault()); | ||||
| 2422 | } | ||||
| 2423 | |||||
| 2424 | public: | ||||
| 2425 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||
| 2426 | (StringRef Name, DIType *Type, bool IsDefault), | ||||
| 2427 | (Name, Type, IsDefault)) | ||||
| 2428 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||
| 2429 | (MDString *Name, Metadata *Type, bool IsDefault), | ||||
| 2430 | (Name, Type, IsDefault)) | ||||
| 2431 | |||||
| 2432 | TempDITemplateTypeParameter clone() const { return cloneImpl(); } | ||||
| 2433 | |||||
| 2434 | static bool classof(const Metadata *MD) { | ||||
| 2435 | return MD->getMetadataID() == DITemplateTypeParameterKind; | ||||
| 2436 | } | ||||
| 2437 | }; | ||||
| 2438 | |||||
| 2439 | class DITemplateValueParameter : public DITemplateParameter { | ||||
| 2440 | friend class LLVMContextImpl; | ||||
| 2441 | friend class MDNode; | ||||
| 2442 | |||||
| 2443 | DITemplateValueParameter(LLVMContext &Context, StorageType Storage, | ||||
| 2444 | unsigned Tag, bool IsDefault, | ||||
| 2445 | ArrayRef<Metadata *> Ops) | ||||
| 2446 | : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, | ||||
| 2447 | IsDefault, Ops) {} | ||||
| 2448 | ~DITemplateValueParameter() = default; | ||||
| 2449 | |||||
| 2450 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 2451 | StringRef Name, DIType *Type, | ||||
| 2452 | bool IsDefault, Metadata *Value, | ||||
| 2453 | StorageType Storage, | ||||
| 2454 | bool ShouldCreate = true) { | ||||
| 2455 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, | ||||
| 2456 | IsDefault, Value, Storage, ShouldCreate); | ||||
| 2457 | } | ||||
| 2458 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 2459 | MDString *Name, Metadata *Type, | ||||
| 2460 | bool IsDefault, Metadata *Value, | ||||
| 2461 | StorageType Storage, | ||||
| 2462 | bool ShouldCreate = true); | ||||
| 2463 | |||||
| 2464 | TempDITemplateValueParameter cloneImpl() const { | ||||
| 2465 | return getTemporary(getContext(), getTag(), getName(), getType(), | ||||
| 2466 | isDefault(), getValue()); | ||||
| 2467 | } | ||||
| 2468 | |||||
| 2469 | public: | ||||
| 2470 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||
| 2471 | (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault, | ||||
| 2472 | Metadata *Value), | ||||
| 2473 | (Tag, Name, Type, IsDefault, Value)) | ||||
| 2474 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||
| 2475 | (unsigned Tag, MDString *Name, Metadata *Type, | ||||
| 2476 | bool IsDefault, Metadata *Value), | ||||
| 2477 | (Tag, Name, Type, IsDefault, Value)) | ||||
| 2478 | |||||
| 2479 | TempDITemplateValueParameter clone() const { return cloneImpl(); } | ||||
| 2480 | |||||
| 2481 | Metadata *getValue() const { return getOperand(2); } | ||||
| 2482 | |||||
| 2483 | static bool classof(const Metadata *MD) { | ||||
| 2484 | return MD->getMetadataID() == DITemplateValueParameterKind; | ||||
| 2485 | } | ||||
| 2486 | }; | ||||
| 2487 | |||||
| 2488 | /// Base class for variables. | ||||
| 2489 | class DIVariable : public DINode { | ||||
| 2490 | unsigned Line; | ||||
| 2491 | uint32_t AlignInBits; | ||||
| 2492 | |||||
| 2493 | protected: | ||||
| 2494 | DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line, | ||||
| 2495 | ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0) | ||||
| 2496 | : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line), | ||||
| 2497 | AlignInBits(AlignInBits) {} | ||||
| 2498 | ~DIVariable() = default; | ||||
| 2499 | |||||
| 2500 | public: | ||||
| 2501 | unsigned getLine() const { return Line; } | ||||
| 2502 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
| 2503 | StringRef getName() const { return getStringOperand(1); } | ||||
| 2504 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
| 2505 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
| 2506 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||
| 2507 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||
| 2508 | /// Determines the size of the variable's type. | ||||
| 2509 | Optional<uint64_t> getSizeInBits() const; | ||||
| 2510 | |||||
| 2511 | /// Return the signedness of this variable's type, or None if this type is | ||||
| 2512 | /// neither signed nor unsigned. | ||||
| 2513 | Optional<DIBasicType::Signedness> getSignedness() const { | ||||
| 2514 | if (auto *BT = dyn_cast<DIBasicType>(getType())) | ||||
| 2515 | return BT->getSignedness(); | ||||
| 2516 | return None; | ||||
| 2517 | } | ||||
| 2518 | |||||
| 2519 | StringRef getFilename() const { | ||||
| 2520 | if (auto *F = getFile()) | ||||
| 2521 | return F->getFilename(); | ||||
| 2522 | return ""; | ||||
| 2523 | } | ||||
| 2524 | |||||
| 2525 | StringRef getDirectory() const { | ||||
| 2526 | if (auto *F = getFile()) | ||||
| 2527 | return F->getDirectory(); | ||||
| 2528 | return ""; | ||||
| 2529 | } | ||||
| 2530 | |||||
| 2531 | Optional<StringRef> getSource() const { | ||||
| 2532 | if (auto *F = getFile()) | ||||
| 2533 | return F->getSource(); | ||||
| 2534 | return None; | ||||
| 2535 | } | ||||
| 2536 | |||||
| 2537 | Metadata *getRawScope() const { return getOperand(0); } | ||||
| 2538 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||
| 2539 | Metadata *getRawFile() const { return getOperand(2); } | ||||
| 2540 | Metadata *getRawType() const { return getOperand(3); } | ||||
| 2541 | |||||
| 2542 | static bool classof(const Metadata *MD) { | ||||
| 2543 | return MD->getMetadataID() == DILocalVariableKind || | ||||
| 2544 | MD->getMetadataID() == DIGlobalVariableKind; | ||||
| 2545 | } | ||||
| 2546 | }; | ||||
| 2547 | |||||
| 2548 | /// DWARF expression. | ||||
| 2549 | /// | ||||
| 2550 | /// This is (almost) a DWARF expression that modifies the location of a | ||||
| 2551 | /// variable, or the location of a single piece of a variable, or (when using | ||||
| 2552 | /// DW_OP_stack_value) is the constant variable value. | ||||
| 2553 | /// | ||||
| 2554 | /// TODO: Co-allocate the expression elements. | ||||
| 2555 | /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary | ||||
| 2556 | /// storage types. | ||||
| 2557 | class DIExpression : public MDNode { | ||||
| 2558 | friend class LLVMContextImpl; | ||||
| 2559 | friend class MDNode; | ||||
| 2560 | |||||
| 2561 | std::vector<uint64_t> Elements; | ||||
| 2562 | |||||
| 2563 | DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) | ||||
| 2564 | : MDNode(C, DIExpressionKind, Storage, None), | ||||
| 2565 | Elements(Elements.begin(), Elements.end()) {} | ||||
| 2566 | ~DIExpression() = default; | ||||
| 2567 | |||||
| 2568 | static DIExpression *getImpl(LLVMContext &Context, | ||||
| 2569 | ArrayRef<uint64_t> Elements, StorageType Storage, | ||||
| 2570 | bool ShouldCreate = true); | ||||
| 2571 | |||||
| 2572 | TempDIExpression cloneImpl() const { | ||||
| 2573 | return getTemporary(getContext(), getElements()); | ||||
| 2574 | } | ||||
| 2575 | |||||
| 2576 | public: | ||||
| 2577 | DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements)) | ||||
| 2578 | |||||
| 2579 | TempDIExpression clone() const { return cloneImpl(); } | ||||
| 2580 | |||||
| 2581 | ArrayRef<uint64_t> getElements() const { return Elements; } | ||||
| 2582 | |||||
| 2583 | unsigned getNumElements() const { return Elements.size(); } | ||||
| 2584 | |||||
| 2585 | uint64_t getElement(unsigned I) const { | ||||
| 2586 | assert(I < Elements.size() && "Index out of range")((void)0); | ||||
| 2587 | return Elements[I]; | ||||
| 2588 | } | ||||
| 2589 | |||||
| 2590 | enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; | ||||
| 2591 | /// Determine whether this represents a constant value, if so | ||||
| 2592 | // return it's sign information. | ||||
| 2593 | llvm::Optional<SignedOrUnsignedConstant> isConstant() const; | ||||
| 2594 | |||||
| 2595 | /// Return the number of unique location operands referred to (via | ||||
| 2596 | /// DW_OP_LLVM_arg) in this expression; this is not necessarily the number of | ||||
| 2597 | /// instances of DW_OP_LLVM_arg within the expression. | ||||
| 2598 | /// For example, for the expression: | ||||
| 2599 | /// (DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_plus, | ||||
| 2600 | /// DW_OP_LLVM_arg 0, DW_OP_mul) | ||||
| 2601 | /// This function would return 2, as there are two unique location operands | ||||
| 2602 | /// (0 and 1). | ||||
| 2603 | uint64_t getNumLocationOperands() const; | ||||
| 2604 | |||||
| 2605 | using element_iterator = ArrayRef<uint64_t>::iterator; | ||||
| 2606 | |||||
| 2607 | element_iterator elements_begin() const { return getElements().begin(); } | ||||
| 2608 | element_iterator elements_end() const { return getElements().end(); } | ||||
| 2609 | |||||
| 2610 | /// A lightweight wrapper around an expression operand. | ||||
| 2611 | /// | ||||
| 2612 | /// TODO: Store arguments directly and change \a DIExpression to store a | ||||
| 2613 | /// range of these. | ||||
| 2614 | class ExprOperand { | ||||
| 2615 | const uint64_t *Op = nullptr; | ||||
| 2616 | |||||
| 2617 | public: | ||||
| 2618 | ExprOperand() = default; | ||||
| 2619 | explicit ExprOperand(const uint64_t *Op) : Op(Op) {} | ||||
| 2620 | |||||
| 2621 | const uint64_t *get() const { return Op; } | ||||
| 2622 | |||||
| 2623 | /// Get the operand code. | ||||
| 2624 | uint64_t getOp() const { return *Op; } | ||||
| 2625 | |||||
| 2626 | /// Get an argument to the operand. | ||||
| 2627 | /// | ||||
| 2628 | /// Never returns the operand itself. | ||||
| 2629 | uint64_t getArg(unsigned I) const { return Op[I + 1]; } | ||||
| 2630 | |||||
| 2631 | unsigned getNumArgs() const { return getSize() - 1; } | ||||
| 2632 | |||||
| 2633 | /// Return the size of the operand. | ||||
| 2634 | /// | ||||
| 2635 | /// Return the number of elements in the operand (1 + args). | ||||
| 2636 | unsigned getSize() const; | ||||
| 2637 | |||||
| 2638 | /// Append the elements of this operand to \p V. | ||||
| 2639 | void appendToVector(SmallVectorImpl<uint64_t> &V) const { | ||||
| 2640 | V.append(get(), get() + getSize()); | ||||
| 2641 | } | ||||
| 2642 | }; | ||||
| 2643 | |||||
| 2644 | /// An iterator for expression operands. | ||||
| 2645 | class expr_op_iterator { | ||||
| 2646 | ExprOperand Op; | ||||
| 2647 | |||||
| 2648 | public: | ||||
| 2649 | using iterator_category = std::input_iterator_tag; | ||||
| 2650 | using value_type = ExprOperand; | ||||
| 2651 | using difference_type = std::ptrdiff_t; | ||||
| 2652 | using pointer = value_type *; | ||||
| 2653 | using reference = value_type &; | ||||
| 2654 | |||||
| 2655 | expr_op_iterator() = default; | ||||
| 2656 | explicit expr_op_iterator(element_iterator I) : Op(I) {} | ||||
| 2657 | |||||
| 2658 | element_iterator getBase() const { return Op.get(); } | ||||
| 2659 | const ExprOperand &operator*() const { return Op; } | ||||
| 2660 | const ExprOperand *operator->() const { return &Op; } | ||||
| 2661 | |||||
| 2662 | expr_op_iterator &operator++() { | ||||
| 2663 | increment(); | ||||
| 2664 | return *this; | ||||
| 2665 | } | ||||
| 2666 | expr_op_iterator operator++(int) { | ||||
| 2667 | expr_op_iterator T(*this); | ||||
| 2668 | increment(); | ||||
| 2669 | return T; | ||||
| 2670 | } | ||||
| 2671 | |||||
| 2672 | /// Get the next iterator. | ||||
| 2673 | /// | ||||
| 2674 | /// \a std::next() doesn't work because this is technically an | ||||
| 2675 | /// input_iterator, but it's a perfectly valid operation. This is an | ||||
| 2676 | /// accessor to provide the same functionality. | ||||
| 2677 | expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } | ||||
| 2678 | |||||
| 2679 | bool operator==(const expr_op_iterator &X) const { | ||||
| 2680 | return getBase() == X.getBase(); | ||||
| 2681 | } | ||||
| 2682 | bool operator!=(const expr_op_iterator &X) const { | ||||
| 2683 | return getBase() != X.getBase(); | ||||
| 2684 | } | ||||
| 2685 | |||||
| 2686 | private: | ||||
| 2687 | void increment() { Op = ExprOperand(getBase() + Op.getSize()); } | ||||
| 2688 | }; | ||||
| 2689 | |||||
| 2690 | /// Visit the elements via ExprOperand wrappers. | ||||
| 2691 | /// | ||||
| 2692 | /// These range iterators visit elements through \a ExprOperand wrappers. | ||||
| 2693 | /// This is not guaranteed to be a valid range unless \a isValid() gives \c | ||||
| 2694 | /// true. | ||||
| 2695 | /// | ||||
| 2696 | /// \pre \a isValid() gives \c true. | ||||
| 2697 | /// @{ | ||||
| 2698 | expr_op_iterator expr_op_begin() const { | ||||
| 2699 | return expr_op_iterator(elements_begin()); | ||||
| 2700 | } | ||||
| 2701 | expr_op_iterator expr_op_end() const { | ||||
| 2702 | return expr_op_iterator(elements_end()); | ||||
| 2703 | } | ||||
| 2704 | iterator_range<expr_op_iterator> expr_ops() const { | ||||
| 2705 | return {expr_op_begin(), expr_op_end()}; | ||||
| 2706 | } | ||||
| 2707 | /// @} | ||||
| 2708 | |||||
| 2709 | bool isValid() const; | ||||
| 2710 | |||||
| 2711 | static bool classof(const Metadata *MD) { | ||||
| 2712 | return MD->getMetadataID() == DIExpressionKind; | ||||
| 2713 | } | ||||
| 2714 | |||||
| 2715 | /// Return whether the first element a DW_OP_deref. | ||||
| 2716 | bool startsWithDeref() const { | ||||
| 2717 | return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref; | ||||
| 2718 | } | ||||
| 2719 | |||||
| 2720 | /// Holds the characteristics of one fragment of a larger variable. | ||||
| 2721 | struct FragmentInfo { | ||||
| 2722 | uint64_t SizeInBits; | ||||
| 2723 | uint64_t OffsetInBits; | ||||
| 2724 | }; | ||||
| 2725 | |||||
| 2726 | /// Retrieve the details of this fragment expression. | ||||
| 2727 | static Optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start, | ||||
| 2728 | expr_op_iterator End); | ||||
| 2729 | |||||
| 2730 | /// Retrieve the details of this fragment expression. | ||||
| 2731 | Optional<FragmentInfo> getFragmentInfo() const { | ||||
| 2732 | return getFragmentInfo(expr_op_begin(), expr_op_end()); | ||||
| 2733 | } | ||||
| 2734 | |||||
| 2735 | /// Return whether this is a piece of an aggregate variable. | ||||
| 2736 | bool isFragment() const { return getFragmentInfo().hasValue(); } | ||||
| 2737 | |||||
| 2738 | /// Return whether this is an implicit location description. | ||||
| 2739 | bool isImplicit() const; | ||||
| 2740 | |||||
| 2741 | /// Return whether the location is computed on the expression stack, meaning | ||||
| 2742 | /// it cannot be a simple register location. | ||||
| 2743 | bool isComplex() const; | ||||
| 2744 | |||||
| 2745 | /// Append \p Ops with operations to apply the \p Offset. | ||||
| 2746 | static void appendOffset(SmallVectorImpl<uint64_t> &Ops, int64_t Offset); | ||||
| 2747 | |||||
| 2748 | /// If this is a constant offset, extract it. If there is no expression, | ||||
| 2749 | /// return true with an offset of zero. | ||||
| 2750 | bool extractIfOffset(int64_t &Offset) const; | ||||
| 2751 | |||||
| 2752 | /// Returns true iff this DIExpression contains at least one instance of | ||||
| 2753 | /// `DW_OP_LLVM_arg, n` for all n in [0, N). | ||||
| 2754 | bool hasAllLocationOps(unsigned N) const; | ||||
| 2755 | |||||
| 2756 | /// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF | ||||
| 2757 | /// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address | ||||
| 2758 | /// Space>. | ||||
| 2759 | static const DIExpression *extractAddressClass(const DIExpression *Expr, | ||||
| 2760 | unsigned &AddrClass); | ||||
| 2761 | |||||
| 2762 | /// Used for DIExpression::prepend. | ||||
| 2763 | enum PrependOps : uint8_t { | ||||
| 2764 | ApplyOffset = 0, | ||||
| 2765 | DerefBefore = 1 << 0, | ||||
| 2766 | DerefAfter = 1 << 1, | ||||
| 2767 | StackValue = 1 << 2, | ||||
| 2768 | EntryValue = 1 << 3 | ||||
| 2769 | }; | ||||
| 2770 | |||||
| 2771 | /// Prepend \p DIExpr with a deref and offset operation and optionally turn it | ||||
| 2772 | /// into a stack value or/and an entry value. | ||||
| 2773 | static DIExpression *prepend(const DIExpression *Expr, uint8_t Flags, | ||||
| 2774 | int64_t Offset = 0); | ||||
| 2775 | |||||
| 2776 | /// Prepend \p DIExpr with the given opcodes and optionally turn it into a | ||||
| 2777 | /// stack value. | ||||
| 2778 | static DIExpression *prependOpcodes(const DIExpression *Expr, | ||||
| 2779 | SmallVectorImpl<uint64_t> &Ops, | ||||
| 2780 | bool StackValue = false, | ||||
| 2781 | bool EntryValue = false); | ||||
| 2782 | |||||
| 2783 | /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the | ||||
| 2784 | /// returned expression is a stack value only if \p DIExpr is a stack value. | ||||
| 2785 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||
| 2786 | /// the same fragment. | ||||
| 2787 | static DIExpression *append(const DIExpression *Expr, ArrayRef<uint64_t> Ops); | ||||
| 2788 | |||||
| 2789 | /// Convert \p DIExpr into a stack value if it isn't one already by appending | ||||
| 2790 | /// DW_OP_deref if needed, and appending \p Ops to the resulting expression. | ||||
| 2791 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||
| 2792 | /// the same fragment. | ||||
| 2793 | static DIExpression *appendToStack(const DIExpression *Expr, | ||||
| 2794 | ArrayRef<uint64_t> Ops); | ||||
| 2795 | |||||
| 2796 | /// Create a copy of \p Expr by appending the given list of \p Ops to each | ||||
| 2797 | /// instance of the operand `DW_OP_LLVM_arg, \p ArgNo`. This is used to | ||||
| 2798 | /// modify a specific location used by \p Expr, such as when salvaging that | ||||
| 2799 | /// location. | ||||
| 2800 | static DIExpression *appendOpsToArg(const DIExpression *Expr, | ||||
| 2801 | ArrayRef<uint64_t> Ops, unsigned ArgNo, | ||||
| 2802 | bool StackValue = false); | ||||
| 2803 | |||||
| 2804 | /// Create a copy of \p Expr with each instance of | ||||
| 2805 | /// `DW_OP_LLVM_arg, \p OldArg` replaced with `DW_OP_LLVM_arg, \p NewArg`, | ||||
| 2806 | /// and each instance of `DW_OP_LLVM_arg, Arg` with `DW_OP_LLVM_arg, Arg - 1` | ||||
| 2807 | /// for all Arg > \p OldArg. | ||||
| 2808 | /// This is used when replacing one of the operands of a debug value list | ||||
| 2809 | /// with another operand in the same list and deleting the old operand. | ||||
| 2810 | static DIExpression *replaceArg(const DIExpression *Expr, uint64_t OldArg, | ||||
| 2811 | uint64_t NewArg); | ||||
| 2812 | |||||
| 2813 | /// Create a DIExpression to describe one part of an aggregate variable that | ||||
| 2814 | /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation | ||||
| 2815 | /// will be appended to the elements of \c Expr. If \c Expr already contains | ||||
| 2816 | /// a \c DW_OP_LLVM_fragment \c OffsetInBits is interpreted as an offset | ||||
| 2817 | /// into the existing fragment. | ||||
| 2818 | /// | ||||
| 2819 | /// \param OffsetInBits Offset of the piece in bits. | ||||
| 2820 | /// \param SizeInBits Size of the piece in bits. | ||||
| 2821 | /// \return Creating a fragment expression may fail if \c Expr | ||||
| 2822 | /// contains arithmetic operations that would be truncated. | ||||
| 2823 | static Optional<DIExpression *> | ||||
| 2824 | createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, | ||||
| 2825 | unsigned SizeInBits); | ||||
| 2826 | |||||
| 2827 | /// Determine the relative position of the fragments passed in. | ||||
| 2828 | /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, | ||||
| 2829 | /// 1 if this is entirely after Other. | ||||
| 2830 | static int fragmentCmp(const FragmentInfo &A, const FragmentInfo &B) { | ||||
| 2831 | uint64_t l1 = A.OffsetInBits; | ||||
| 2832 | uint64_t l2 = B.OffsetInBits; | ||||
| 2833 | uint64_t r1 = l1 + A.SizeInBits; | ||||
| 2834 | uint64_t r2 = l2 + B.SizeInBits; | ||||
| 2835 | if (r1 <= l2) | ||||
| 2836 | return -1; | ||||
| 2837 | else if (r2 <= l1) | ||||
| 2838 | return 1; | ||||
| 2839 | else | ||||
| 2840 | return 0; | ||||
| 2841 | } | ||||
| 2842 | |||||
| 2843 | using ExtOps = std::array<uint64_t, 6>; | ||||
| 2844 | |||||
| 2845 | /// Returns the ops for a zero- or sign-extension in a DIExpression. | ||||
| 2846 | static ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed); | ||||
| 2847 | |||||
| 2848 | /// Append a zero- or sign-extension to \p Expr. Converts the expression to a | ||||
| 2849 | /// stack value if it isn't one already. | ||||
| 2850 | static DIExpression *appendExt(const DIExpression *Expr, unsigned FromSize, | ||||
| 2851 | unsigned ToSize, bool Signed); | ||||
| 2852 | |||||
| 2853 | /// Check if fragments overlap between a pair of FragmentInfos. | ||||
| 2854 | static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B) { | ||||
| 2855 | return fragmentCmp(A, B) == 0; | ||||
| 2856 | } | ||||
| 2857 | |||||
| 2858 | /// Determine the relative position of the fragments described by this | ||||
| 2859 | /// DIExpression and \p Other. Calls static fragmentCmp implementation. | ||||
| 2860 | int fragmentCmp(const DIExpression *Other) const { | ||||
| 2861 | auto Fragment1 = *getFragmentInfo(); | ||||
| 2862 | auto Fragment2 = *Other->getFragmentInfo(); | ||||
| 2863 | return fragmentCmp(Fragment1, Fragment2); | ||||
| 2864 | } | ||||
| 2865 | |||||
| 2866 | /// Check if fragments overlap between this DIExpression and \p Other. | ||||
| 2867 | bool fragmentsOverlap(const DIExpression *Other) const { | ||||
| 2868 | if (!isFragment() || !Other->isFragment()) | ||||
| 2869 | return true; | ||||
| 2870 | return fragmentCmp(Other) == 0; | ||||
| 2871 | } | ||||
| 2872 | |||||
| 2873 | /// Check if the expression consists of exactly one entry value operand. | ||||
| 2874 | /// (This is the only configuration of entry values that is supported.) | ||||
| 2875 | bool isEntryValue() const { | ||||
| 2876 | return getNumElements() > 0 && | ||||
| 2877 | getElement(0) == dwarf::DW_OP_LLVM_entry_value; | ||||
| 2878 | } | ||||
| 2879 | }; | ||||
| 2880 | |||||
| 2881 | inline bool operator==(const DIExpression::FragmentInfo &A, | ||||
| 2882 | const DIExpression::FragmentInfo &B) { | ||||
| 2883 | return std::tie(A.SizeInBits, A.OffsetInBits) == | ||||
| 2884 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||
| 2885 | } | ||||
| 2886 | |||||
| 2887 | inline bool operator<(const DIExpression::FragmentInfo &A, | ||||
| 2888 | const DIExpression::FragmentInfo &B) { | ||||
| 2889 | return std::tie(A.SizeInBits, A.OffsetInBits) < | ||||
| 2890 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||
| 2891 | } | ||||
| 2892 | |||||
| 2893 | template <> struct DenseMapInfo<DIExpression::FragmentInfo> { | ||||
| 2894 | using FragInfo = DIExpression::FragmentInfo; | ||||
| 2895 | static const uint64_t MaxVal = std::numeric_limits<uint64_t>::max(); | ||||
| 2896 | |||||
| 2897 | static inline FragInfo getEmptyKey() { return {MaxVal, MaxVal}; } | ||||
| 2898 | |||||
| 2899 | static inline FragInfo getTombstoneKey() { return {MaxVal - 1, MaxVal - 1}; } | ||||
| 2900 | |||||
| 2901 | static unsigned getHashValue(const FragInfo &Frag) { | ||||
| 2902 | return (Frag.SizeInBits & 0xffff) << 16 | (Frag.OffsetInBits & 0xffff); | ||||
| 2903 | } | ||||
| 2904 | |||||
| 2905 | static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } | ||||
| 2906 | }; | ||||
| 2907 | |||||
| 2908 | /// Global variables. | ||||
| 2909 | /// | ||||
| 2910 | /// TODO: Remove DisplayName. It's always equal to Name. | ||||
| 2911 | class DIGlobalVariable : public DIVariable { | ||||
| 2912 | friend class LLVMContextImpl; | ||||
| 2913 | friend class MDNode; | ||||
| 2914 | |||||
| 2915 | bool IsLocalToUnit; | ||||
| 2916 | bool IsDefinition; | ||||
| 2917 | |||||
| 2918 | DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
| 2919 | bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, | ||||
| 2920 | ArrayRef<Metadata *> Ops) | ||||
| 2921 | : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), | ||||
| 2922 | IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} | ||||
| 2923 | ~DIGlobalVariable() = default; | ||||
| 2924 | |||||
| 2925 | static DIGlobalVariable * | ||||
| 2926 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||
| 2927 | StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, | ||||
| 2928 | bool IsLocalToUnit, bool IsDefinition, | ||||
| 2929 | DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, | ||||
| 2930 | uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true) { | ||||
| 2931 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||
| 2932 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||
| 2933 | IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, | ||||
| 2934 | cast_or_null<Metadata>(TemplateParams), AlignInBits, Storage, | ||||
| 2935 | ShouldCreate); | ||||
| 2936 | } | ||||
| 2937 | static DIGlobalVariable * | ||||
| 2938 | getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||
| 2939 | MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, | ||||
| 2940 | bool IsLocalToUnit, bool IsDefinition, | ||||
| 2941 | Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, | ||||
| 2942 | uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true); | ||||
| 2943 | |||||
| 2944 | TempDIGlobalVariable cloneImpl() const { | ||||
| 2945 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||
| 2946 | getFile(), getLine(), getType(), isLocalToUnit(), | ||||
| 2947 | isDefinition(), getStaticDataMemberDeclaration(), | ||||
| 2948 | getTemplateParams(), getAlignInBits()); | ||||
| 2949 | } | ||||
| 2950 | |||||
| 2951 | public: | ||||
| 2952 | DEFINE_MDNODE_GET(DIGlobalVariable, | ||||
| 2953 | (DIScope * Scope, StringRef Name, StringRef LinkageName, | ||||
| 2954 | DIFile *File, unsigned Line, DIType *Type, | ||||
| 2955 | bool IsLocalToUnit, bool IsDefinition, | ||||
| 2956 | DIDerivedType *StaticDataMemberDeclaration, | ||||
| 2957 | MDTuple *TemplateParams, uint32_t AlignInBits), | ||||
| 2958 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, | ||||
| 2959 | IsDefinition, StaticDataMemberDeclaration, TemplateParams, | ||||
| 2960 | AlignInBits)) | ||||
| 2961 | DEFINE_MDNODE_GET(DIGlobalVariable, | ||||
| 2962 | (Metadata * Scope, MDString *Name, MDString *LinkageName, | ||||
| 2963 | Metadata *File, unsigned Line, Metadata *Type, | ||||
| 2964 | bool IsLocalToUnit, bool IsDefinition, | ||||
| 2965 | Metadata *StaticDataMemberDeclaration, | ||||
| 2966 | Metadata *TemplateParams, uint32_t AlignInBits), | ||||
| 2967 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, | ||||
| 2968 | IsDefinition, StaticDataMemberDeclaration, TemplateParams, | ||||
| 2969 | AlignInBits)) | ||||
| 2970 | |||||
| 2971 | TempDIGlobalVariable clone() const { return cloneImpl(); } | ||||
| 2972 | |||||
| 2973 | bool isLocalToUnit() const { return IsLocalToUnit; } | ||||
| 2974 | bool isDefinition() const { return IsDefinition; } | ||||
| 2975 | StringRef getDisplayName() const { return getStringOperand(4); } | ||||
| 2976 | StringRef getLinkageName() const { return getStringOperand(5); } | ||||
| 2977 | DIDerivedType *getStaticDataMemberDeclaration() const { | ||||
| 2978 | return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration()); | ||||
| 2979 | } | ||||
| 2980 | |||||
| 2981 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } | ||||
| 2982 | Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } | ||||
| 2983 | Metadata *getRawTemplateParams() const { return getOperand(7); } | ||||
| 2984 | MDTuple *getTemplateParams() const { return getOperandAs<MDTuple>(7); } | ||||
| 2985 | |||||
| 2986 | static bool classof(const Metadata *MD) { | ||||
| 2987 | return MD->getMetadataID() == DIGlobalVariableKind; | ||||
| 2988 | } | ||||
| 2989 | }; | ||||
| 2990 | |||||
| 2991 | class DICommonBlock : public DIScope { | ||||
| 2992 | unsigned LineNo; | ||||
| 2993 | |||||
| 2994 | friend class LLVMContextImpl; | ||||
| 2995 | friend class MDNode; | ||||
| 2996 | |||||
| 2997 | DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||
| 2998 | ArrayRef<Metadata *> Ops) | ||||
| 2999 | : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block, | ||||
| 3000 | Ops), LineNo(LineNo) {} | ||||
| 3001 | |||||
| 3002 | static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
| 3003 | DIGlobalVariable *Decl, StringRef Name, | ||||
| 3004 | DIFile *File, unsigned LineNo, | ||||
| 3005 | StorageType Storage, | ||||
| 3006 | bool ShouldCreate = true) { | ||||
| 3007 | return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), | ||||
| 3008 | File, LineNo, Storage, ShouldCreate); | ||||
| 3009 | } | ||||
| 3010 | static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
| 3011 | Metadata *Decl, MDString *Name, Metadata *File, | ||||
| 3012 | unsigned LineNo, | ||||
| 3013 | StorageType Storage, bool ShouldCreate = true); | ||||
| 3014 | |||||
| 3015 | TempDICommonBlock cloneImpl() const { | ||||
| 3016 | return getTemporary(getContext(), getScope(), getDecl(), getName(), | ||||
| 3017 | getFile(), getLineNo()); | ||||
| 3018 | } | ||||
| 3019 | |||||
| 3020 | public: | ||||
| 3021 | DEFINE_MDNODE_GET(DICommonBlock, | ||||
| 3022 | (DIScope *Scope, DIGlobalVariable *Decl, StringRef Name, | ||||
| 3023 | DIFile *File, unsigned LineNo), | ||||
| 3024 | (Scope, Decl, Name, File, LineNo)) | ||||
| 3025 | DEFINE_MDNODE_GET(DICommonBlock, | ||||
| 3026 | (Metadata *Scope, Metadata *Decl, MDString *Name, | ||||
| 3027 | Metadata *File, unsigned LineNo), | ||||
| 3028 | (Scope, Decl, Name, File, LineNo)) | ||||
| 3029 | |||||
| 3030 | TempDICommonBlock clone() const { return cloneImpl(); } | ||||
| 3031 | |||||
| 3032 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
| 3033 | DIGlobalVariable *getDecl() const { | ||||
| 3034 | return cast_or_null<DIGlobalVariable>(getRawDecl()); | ||||
| 3035 | } | ||||
| 3036 | StringRef getName() const { return getStringOperand(2); } | ||||
| 3037 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
| 3038 | unsigned getLineNo() const { return LineNo; } | ||||
| 3039 | |||||
| 3040 | Metadata *getRawScope() const { return getOperand(0); } | ||||
| 3041 | Metadata *getRawDecl() const { return getOperand(1); } | ||||
| 3042 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
| 3043 | Metadata *getRawFile() const { return getOperand(3); } | ||||
| 3044 | |||||
| 3045 | static bool classof(const Metadata *MD) { | ||||
| 3046 | return MD->getMetadataID() == DICommonBlockKind; | ||||
| 3047 | } | ||||
| 3048 | }; | ||||
| 3049 | |||||
| 3050 | /// Local variable. | ||||
| 3051 | /// | ||||
| 3052 | /// TODO: Split up flags. | ||||
| 3053 | class DILocalVariable : public DIVariable { | ||||
| 3054 | friend class LLVMContextImpl; | ||||
| 3055 | friend class MDNode; | ||||
| 3056 | |||||
| 3057 | unsigned Arg : 16; | ||||
| 3058 | DIFlags Flags; | ||||
| 3059 | |||||
| 3060 | DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
| 3061 | unsigned Arg, DIFlags Flags, uint32_t AlignInBits, | ||||
| 3062 | ArrayRef<Metadata *> Ops) | ||||
| 3063 | : DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBits), | ||||
| 3064 | Arg(Arg), Flags(Flags) { | ||||
| 3065 | assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range")((void)0); | ||||
| 3066 | } | ||||
| 3067 | ~DILocalVariable() = default; | ||||
| 3068 | |||||
| 3069 | static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
| 3070 | StringRef Name, DIFile *File, unsigned Line, | ||||
| 3071 | DIType *Type, unsigned Arg, DIFlags Flags, | ||||
| 3072 | uint32_t AlignInBits, StorageType Storage, | ||||
| 3073 | bool ShouldCreate = true) { | ||||
| 3074 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||
| 3075 | Line, Type, Arg, Flags, AlignInBits, Storage, ShouldCreate); | ||||
| 3076 | } | ||||
| 3077 | static DILocalVariable *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
| 3078 | MDString *Name, Metadata *File, unsigned Line, | ||||
| 3079 | Metadata *Type, unsigned Arg, DIFlags Flags, | ||||
| 3080 | uint32_t AlignInBits, StorageType Storage, | ||||
| 3081 | bool ShouldCreate = true); | ||||
| 3082 | |||||
| 3083 | TempDILocalVariable cloneImpl() const { | ||||
| 3084 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||
| 3085 | getLine(), getType(), getArg(), getFlags(), | ||||
| 3086 | getAlignInBits()); | ||||
| 3087 | } | ||||
| 3088 | |||||
| 3089 | public: | ||||
| 3090 | DEFINE_MDNODE_GET(DILocalVariable, | ||||
| 3091 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||
| 3092 | unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags, | ||||
| 3093 | uint32_t AlignInBits), | ||||
| 3094 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits)) | ||||
| 3095 | DEFINE_MDNODE_GET(DILocalVariable, | ||||
| 3096 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||
| 3097 | unsigned Line, Metadata *Type, unsigned Arg, | ||||
| 3098 | DIFlags Flags, uint32_t AlignInBits), | ||||
| 3099 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits)) | ||||
| 3100 | |||||
| 3101 | TempDILocalVariable clone() const { return cloneImpl(); } | ||||
| 3102 | |||||
| 3103 | /// Get the local scope for this variable. | ||||
| 3104 | /// | ||||
| 3105 | /// Variables must be defined in a local scope. | ||||
| 3106 | DILocalScope *getScope() const { | ||||
| 3107 | return cast<DILocalScope>(DIVariable::getScope()); | ||||
| 3108 | } | ||||
| 3109 | |||||
| 3110 | bool isParameter() const { return Arg; } | ||||
| 3111 | unsigned getArg() const { return Arg; } | ||||
| 3112 | DIFlags getFlags() const { return Flags; } | ||||
| 3113 | |||||
| 3114 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||
| 3115 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||
| 3116 | |||||
| 3117 | /// Check that a location is valid for this variable. | ||||
| 3118 | /// | ||||
| 3119 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||
| 3120 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||
| 3121 | /// to a \a DbgInfoIntrinsic.) | ||||
| 3122 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||
| 3123 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||
| 3124 | } | ||||
| 3125 | |||||
| 3126 | static bool classof(const Metadata *MD) { | ||||
| 3127 | return MD->getMetadataID() == DILocalVariableKind; | ||||
| 3128 | } | ||||
| 3129 | }; | ||||
| 3130 | |||||
| 3131 | /// Label. | ||||
| 3132 | /// | ||||
| 3133 | class DILabel : public DINode { | ||||
| 3134 | friend class LLVMContextImpl; | ||||
| 3135 | friend class MDNode; | ||||
| 3136 | |||||
| 3137 | unsigned Line; | ||||
| 3138 | |||||
| 3139 | DILabel(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
| 3140 | ArrayRef<Metadata *> Ops) | ||||
| 3141 | : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {} | ||||
| 3142 | ~DILabel() = default; | ||||
| 3143 | |||||
| 3144 | static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, | ||||
| 3145 | StringRef Name, DIFile *File, unsigned Line, | ||||
| 3146 | StorageType Storage, | ||||
| 3147 | bool ShouldCreate = true) { | ||||
| 3148 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||
| 3149 | Line, Storage, ShouldCreate); | ||||
| 3150 | } | ||||
| 3151 | static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, | ||||
| 3152 | MDString *Name, Metadata *File, unsigned Line, | ||||
| 3153 | StorageType Storage, | ||||
| 3154 | bool ShouldCreate = true); | ||||
| 3155 | |||||
| 3156 | TempDILabel cloneImpl() const { | ||||
| 3157 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||
| 3158 | getLine()); | ||||
| 3159 | } | ||||
| 3160 | |||||
| 3161 | public: | ||||
| 3162 | DEFINE_MDNODE_GET(DILabel, | ||||
| 3163 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||
| 3164 | unsigned Line), | ||||
| 3165 | (Scope, Name, File, Line)) | ||||
| 3166 | DEFINE_MDNODE_GET(DILabel, | ||||
| 3167 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||
| 3168 | unsigned Line), | ||||
| 3169 | (Scope, Name, File, Line)) | ||||
| 3170 | |||||
| 3171 | TempDILabel clone() const { return cloneImpl(); } | ||||
| 3172 | |||||
| 3173 | /// Get the local scope for this label. | ||||
| 3174 | /// | ||||
| 3175 | /// Labels must be defined in a local scope. | ||||
| 3176 | DILocalScope *getScope() const { | ||||
| 3177 | return cast_or_null<DILocalScope>(getRawScope()); | ||||
| 3178 | } | ||||
| 3179 | unsigned getLine() const { return Line; } | ||||
| 3180 | StringRef getName() const { return getStringOperand(1); } | ||||
| 3181 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
| 3182 | |||||
| 3183 | Metadata *getRawScope() const { return getOperand(0); } | ||||
| 3184 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||
| 3185 | Metadata *getRawFile() const { return getOperand(2); } | ||||
| 3186 | |||||
| 3187 | /// Check that a location is valid for this label. | ||||
| 3188 | /// | ||||
| 3189 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||
| 3190 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||
| 3191 | /// to a \a DbgInfoIntrinsic.) | ||||
| 3192 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||
| 3193 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||
| 3194 | } | ||||
| 3195 | |||||
| 3196 | static bool classof(const Metadata *MD) { | ||||
| 3197 | return MD->getMetadataID() == DILabelKind; | ||||
| 3198 | } | ||||
| 3199 | }; | ||||
| 3200 | |||||
| 3201 | class DIObjCProperty : public DINode { | ||||
| 3202 | friend class LLVMContextImpl; | ||||
| 3203 | friend class MDNode; | ||||
| 3204 | |||||
| 3205 | unsigned Line; | ||||
| 3206 | unsigned Attributes; | ||||
| 3207 | |||||
| 3208 | DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, | ||||
| 3209 | unsigned Attributes, ArrayRef<Metadata *> Ops) | ||||
| 3210 | : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, | ||||
| 3211 | Ops), | ||||
| 3212 | Line(Line), Attributes(Attributes) {} | ||||
| 3213 | ~DIObjCProperty() = default; | ||||
| 3214 | |||||
| 3215 | static DIObjCProperty * | ||||
| 3216 | getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, | ||||
| 3217 | StringRef GetterName, StringRef SetterName, unsigned Attributes, | ||||
| 3218 | DIType *Type, StorageType Storage, bool ShouldCreate = true) { | ||||
| 3219 | return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, | ||||
| 3220 | getCanonicalMDString(Context, GetterName), | ||||
| 3221 | getCanonicalMDString(Context, SetterName), Attributes, Type, | ||||
| 3222 | Storage, ShouldCreate); | ||||
| 3223 | } | ||||
| 3224 | static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, | ||||
| 3225 | Metadata *File, unsigned Line, | ||||
| 3226 | MDString *GetterName, MDString *SetterName, | ||||
| 3227 | unsigned Attributes, Metadata *Type, | ||||
| 3228 | StorageType Storage, bool ShouldCreate = true); | ||||
| 3229 | |||||
| 3230 | TempDIObjCProperty cloneImpl() const { | ||||
| 3231 | return getTemporary(getContext(), getName(), getFile(), getLine(), | ||||
| 3232 | getGetterName(), getSetterName(), getAttributes(), | ||||
| 3233 | getType()); | ||||
| 3234 | } | ||||
| 3235 | |||||
| 3236 | public: | ||||
| 3237 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||
| 3238 | (StringRef Name, DIFile *File, unsigned Line, | ||||
| 3239 | StringRef GetterName, StringRef SetterName, | ||||
| 3240 | unsigned Attributes, DIType *Type), | ||||
| 3241 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||
| 3242 | Type)) | ||||
| 3243 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||
| 3244 | (MDString * Name, Metadata *File, unsigned Line, | ||||
| 3245 | MDString *GetterName, MDString *SetterName, | ||||
| 3246 | unsigned Attributes, Metadata *Type), | ||||
| 3247 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||
| 3248 | Type)) | ||||
| 3249 | |||||
| 3250 | TempDIObjCProperty clone() const { return cloneImpl(); } | ||||
| 3251 | |||||
| 3252 | unsigned getLine() const { return Line; } | ||||
| 3253 | unsigned getAttributes() const { return Attributes; } | ||||
| 3254 | StringRef getName() const { return getStringOperand(0); } | ||||
| 3255 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
| 3256 | StringRef getGetterName() const { return getStringOperand(2); } | ||||
| 3257 | StringRef getSetterName() const { return getStringOperand(3); } | ||||
| 3258 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||
| 3259 | |||||
| 3260 | StringRef getFilename() const { | ||||
| 3261 | if (auto *F = getFile()) | ||||
| 3262 | return F->getFilename(); | ||||
| 3263 | return ""; | ||||
| 3264 | } | ||||
| 3265 | |||||
| 3266 | StringRef getDirectory() const { | ||||
| 3267 | if (auto *F = getFile()) | ||||
| 3268 | return F->getDirectory(); | ||||
| 3269 | return ""; | ||||
| 3270 | } | ||||
| 3271 | |||||
| 3272 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
| 3273 | Metadata *getRawFile() const { return getOperand(1); } | ||||
| 3274 | MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } | ||||
| 3275 | MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } | ||||
| 3276 | Metadata *getRawType() const { return getOperand(4); } | ||||
| 3277 | |||||
| 3278 | static bool classof(const Metadata *MD) { | ||||
| 3279 | return MD->getMetadataID() == DIObjCPropertyKind; | ||||
| 3280 | } | ||||
| 3281 | }; | ||||
| 3282 | |||||
| 3283 | /// An imported module (C++ using directive or similar). | ||||
| 3284 | class DIImportedEntity : public DINode { | ||||
| 3285 | friend class LLVMContextImpl; | ||||
| 3286 | friend class MDNode; | ||||
| 3287 | |||||
| 3288 | unsigned Line; | ||||
| 3289 | |||||
| 3290 | DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||
| 3291 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||
| 3292 | : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} | ||||
| 3293 | ~DIImportedEntity() = default; | ||||
| 3294 | |||||
| 3295 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 3296 | DIScope *Scope, DINode *Entity, DIFile *File, | ||||
| 3297 | unsigned Line, StringRef Name, | ||||
| 3298 | StorageType Storage, | ||||
| 3299 | bool ShouldCreate = true) { | ||||
| 3300 | return getImpl(Context, Tag, Scope, Entity, File, Line, | ||||
| 3301 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); | ||||
| 3302 | } | ||||
| 3303 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||
| 3304 | Metadata *Scope, Metadata *Entity, | ||||
| 3305 | Metadata *File, unsigned Line, | ||||
| 3306 | MDString *Name, StorageType Storage, | ||||
| 3307 | bool ShouldCreate = true); | ||||
| 3308 | |||||
| 3309 | TempDIImportedEntity cloneImpl() const { | ||||
| 3310 | return getTemporary(getContext(), getTag(), getScope(), getEntity(), | ||||
| 3311 | getFile(), getLine(), getName()); | ||||
| 3312 | } | ||||
| 3313 | |||||
| 3314 | public: | ||||
| 3315 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||
| 3316 | (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File, | ||||
| 3317 | unsigned Line, StringRef Name = ""), | ||||
| 3318 | (Tag, Scope, Entity, File, Line, Name)) | ||||
| 3319 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||
| 3320 | (unsigned Tag, Metadata *Scope, Metadata *Entity, | ||||
| 3321 | Metadata *File, unsigned Line, MDString *Name), | ||||
| 3322 | (Tag, Scope, Entity, File, Line, Name)) | ||||
| 3323 | |||||
| 3324 | TempDIImportedEntity clone() const { return cloneImpl(); } | ||||
| 3325 | |||||
| 3326 | unsigned getLine() const { return Line; } | ||||
| 3327 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||
| 3328 | DINode *getEntity() const { return cast_or_null<DINode>(getRawEntity()); } | ||||
| 3329 | StringRef getName() const { return getStringOperand(2); } | ||||
| 3330 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
| 3331 | |||||
| 3332 | Metadata *getRawScope() const { return getOperand(0); } | ||||
| 3333 | Metadata *getRawEntity() const { return getOperand(1); } | ||||
| 3334 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||
| 3335 | Metadata *getRawFile() const { return getOperand(3); } | ||||
| 3336 | |||||
| 3337 | static bool classof(const Metadata *MD) { | ||||
| 3338 | return MD->getMetadataID() == DIImportedEntityKind; | ||||
| 3339 | } | ||||
| 3340 | }; | ||||
| 3341 | |||||
| 3342 | /// A pair of DIGlobalVariable and DIExpression. | ||||
| 3343 | class DIGlobalVariableExpression : public MDNode { | ||||
| 3344 | friend class LLVMContextImpl; | ||||
| 3345 | friend class MDNode; | ||||
| 3346 | |||||
| 3347 | DIGlobalVariableExpression(LLVMContext &C, StorageType Storage, | ||||
| 3348 | ArrayRef<Metadata *> Ops) | ||||
| 3349 | : MDNode(C, DIGlobalVariableExpressionKind, Storage, Ops) {} | ||||
| 3350 | ~DIGlobalVariableExpression() = default; | ||||
| 3351 | |||||
| 3352 | static DIGlobalVariableExpression * | ||||
| 3353 | getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Expression, | ||||
| 3354 | StorageType Storage, bool ShouldCreate = true); | ||||
| 3355 | |||||
| 3356 | TempDIGlobalVariableExpression cloneImpl() const { | ||||
| 3357 | return getTemporary(getContext(), getVariable(), getExpression()); | ||||
| 3358 | } | ||||
| 3359 | |||||
| 3360 | public: | ||||
| 3361 | DEFINE_MDNODE_GET(DIGlobalVariableExpression, | ||||
| 3362 | (Metadata * Variable, Metadata *Expression), | ||||
| 3363 | (Variable, Expression)) | ||||
| 3364 | |||||
| 3365 | TempDIGlobalVariableExpression clone() const { return cloneImpl(); } | ||||
| 3366 | |||||
| 3367 | Metadata *getRawVariable() const { return getOperand(0); } | ||||
| 3368 | |||||
| 3369 | DIGlobalVariable *getVariable() const { | ||||
| 3370 | return cast_or_null<DIGlobalVariable>(getRawVariable()); | ||||
| 3371 | } | ||||
| 3372 | |||||
| 3373 | Metadata *getRawExpression() const { return getOperand(1); } | ||||
| 3374 | |||||
| 3375 | DIExpression *getExpression() const { | ||||
| 3376 | return cast<DIExpression>(getRawExpression()); | ||||
| 3377 | } | ||||
| 3378 | |||||
| 3379 | static bool classof(const Metadata *MD) { | ||||
| 3380 | return MD->getMetadataID() == DIGlobalVariableExpressionKind; | ||||
| 3381 | } | ||||
| 3382 | }; | ||||
| 3383 | |||||
| 3384 | /// Macro Info DWARF-like metadata node. | ||||
| 3385 | /// | ||||
| 3386 | /// A metadata node with a DWARF macro info (i.e., a constant named | ||||
| 3387 | /// \c DW_MACINFO_*, defined in llvm/BinaryFormat/Dwarf.h). Called \a | ||||
| 3388 | /// DIMacroNode | ||||
| 3389 | /// because it's potentially used for non-DWARF output. | ||||
| 3390 | class DIMacroNode : public MDNode { | ||||
| 3391 | friend class LLVMContextImpl; | ||||
| 3392 | friend class MDNode; | ||||
| 3393 | |||||
| 3394 | protected: | ||||
| 3395 | DIMacroNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned MIType, | ||||
| 3396 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) | ||||
| 3397 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||
| 3398 | assert(MIType < 1u << 16)((void)0); | ||||
| 3399 | SubclassData16 = MIType; | ||||
| 3400 | } | ||||
| 3401 | ~DIMacroNode() = default; | ||||
| 3402 | |||||
| 3403 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||
| 3404 | return cast_or_null<Ty>(getOperand(I)); | ||||
| 3405 | } | ||||
| 3406 | |||||
| 3407 | StringRef getStringOperand(unsigned I) const { | ||||
| 3408 | if (auto *S = getOperandAs<MDString>(I)) | ||||
| 3409 | return S->getString(); | ||||
| 3410 | return StringRef(); | ||||
| 3411 | } | ||||
| 3412 | |||||
| 3413 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||
| 3414 | if (S.empty()) | ||||
| 3415 | return nullptr; | ||||
| 3416 | return MDString::get(Context, S); | ||||
| 3417 | } | ||||
| 3418 | |||||
| 3419 | public: | ||||
| 3420 | unsigned getMacinfoType() const { return SubclassData16; } | ||||
| 3421 | |||||
| 3422 | static bool classof(const Metadata *MD) { | ||||
| 3423 | switch (MD->getMetadataID()) { | ||||
| 3424 | default: | ||||
| 3425 | return false; | ||||
| 3426 | case DIMacroKind: | ||||
| 3427 | case DIMacroFileKind: | ||||
| 3428 | return true; | ||||
| 3429 | } | ||||
| 3430 | } | ||||
| 3431 | }; | ||||
| 3432 | |||||
| 3433 | class DIMacro : public DIMacroNode { | ||||
| 3434 | friend class LLVMContextImpl; | ||||
| 3435 | friend class MDNode; | ||||
| 3436 | |||||
| 3437 | unsigned Line; | ||||
| 3438 | |||||
| 3439 | DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line, | ||||
| 3440 | ArrayRef<Metadata *> Ops) | ||||
| 3441 | : DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {} | ||||
| 3442 | ~DIMacro() = default; | ||||
| 3443 | |||||
| 3444 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||
| 3445 | StringRef Name, StringRef Value, StorageType Storage, | ||||
| 3446 | bool ShouldCreate = true) { | ||||
| 3447 | return getImpl(Context, MIType, Line, getCanonicalMDString(Context, Name), | ||||
| 3448 | getCanonicalMDString(Context, Value), Storage, ShouldCreate); | ||||
| 3449 | } | ||||
| 3450 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||
| 3451 | MDString *Name, MDString *Value, StorageType Storage, | ||||
| 3452 | bool ShouldCreate = true); | ||||
| 3453 | |||||
| 3454 | TempDIMacro cloneImpl() const { | ||||
| 3455 | return getTemporary(getContext(), getMacinfoType(), getLine(), getName(), | ||||
| 3456 | getValue()); | ||||
| 3457 | } | ||||
| 3458 | |||||
| 3459 | public: | ||||
| 3460 | DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, StringRef Name, | ||||
| 3461 | StringRef Value = ""), | ||||
| 3462 | (MIType, Line, Name, Value)) | ||||
| 3463 | DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, MDString *Name, | ||||
| 3464 | MDString *Value), | ||||
| 3465 | (MIType, Line, Name, Value)) | ||||
| 3466 | |||||
| 3467 | TempDIMacro clone() const { return cloneImpl(); } | ||||
| 3468 | |||||
| 3469 | unsigned getLine() const { return Line; } | ||||
| 3470 | |||||
| 3471 | StringRef getName() const { return getStringOperand(0); } | ||||
| 3472 | StringRef getValue() const { return getStringOperand(1); } | ||||
| 3473 | |||||
| 3474 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||
| 3475 | MDString *getRawValue() const { return getOperandAs<MDString>(1); } | ||||
| 3476 | |||||
| 3477 | static bool classof(const Metadata *MD) { | ||||
| 3478 | return MD->getMetadataID() == DIMacroKind; | ||||
| 3479 | } | ||||
| 3480 | }; | ||||
| 3481 | |||||
| 3482 | class DIMacroFile : public DIMacroNode { | ||||
| 3483 | friend class LLVMContextImpl; | ||||
| 3484 | friend class MDNode; | ||||
| 3485 | |||||
| 3486 | unsigned Line; | ||||
| 3487 | |||||
| 3488 | DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType, | ||||
| 3489 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||
| 3490 | : DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {} | ||||
| 3491 | ~DIMacroFile() = default; | ||||
| 3492 | |||||
| 3493 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||
| 3494 | unsigned Line, DIFile *File, | ||||
| 3495 | DIMacroNodeArray Elements, StorageType Storage, | ||||
| 3496 | bool ShouldCreate = true) { | ||||
| 3497 | return getImpl(Context, MIType, Line, static_cast<Metadata *>(File), | ||||
| 3498 | Elements.get(), Storage, ShouldCreate); | ||||
| 3499 | } | ||||
| 3500 | |||||
| 3501 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||
| 3502 | unsigned Line, Metadata *File, Metadata *Elements, | ||||
| 3503 | StorageType Storage, bool ShouldCreate = true); | ||||
| 3504 | |||||
| 3505 | TempDIMacroFile cloneImpl() const { | ||||
| 3506 | return getTemporary(getContext(), getMacinfoType(), getLine(), getFile(), | ||||
| 3507 | getElements()); | ||||
| 3508 | } | ||||
| 3509 | |||||
| 3510 | public: | ||||
| 3511 | DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, DIFile *File, | ||||
| 3512 | DIMacroNodeArray Elements), | ||||
| 3513 | (MIType, Line, File, Elements)) | ||||
| 3514 | DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, | ||||
| 3515 | Metadata *File, Metadata *Elements), | ||||
| 3516 | (MIType, Line, File, Elements)) | ||||
| 3517 | |||||
| 3518 | TempDIMacroFile clone() const { return cloneImpl(); } | ||||
| 3519 | |||||
| 3520 | void replaceElements(DIMacroNodeArray Elements) { | ||||
| 3521 | #ifndef NDEBUG1 | ||||
| 3522 | for (DIMacroNode *Op : getElements()) | ||||
| 3523 | assert(is_contained(Elements->operands(), Op) &&((void)0) | ||||
| 3524 | "Lost a macro node during macro node list replacement")((void)0); | ||||
| 3525 | #endif | ||||
| 3526 | replaceOperandWith(1, Elements.get()); | ||||
| 3527 | } | ||||
| 3528 | |||||
| 3529 | unsigned getLine() const { return Line; } | ||||
| 3530 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||
| 3531 | |||||
| 3532 | DIMacroNodeArray getElements() const { | ||||
| 3533 | return cast_or_null<MDTuple>(getRawElements()); | ||||
| 3534 | } | ||||
| 3535 | |||||
| 3536 | Metadata *getRawFile() const { return getOperand(0); } | ||||
| 3537 | Metadata *getRawElements() const { return getOperand(1); } | ||||
| 3538 | |||||
| 3539 | static bool classof(const Metadata *MD) { | ||||
| 3540 | return MD->getMetadataID() == DIMacroFileKind; | ||||
| 3541 | } | ||||
| 3542 | }; | ||||
| 3543 | |||||
| 3544 | /// List of ValueAsMetadata, to be used as an argument to a dbg.value | ||||
| 3545 | /// intrinsic. | ||||
| 3546 | class DIArgList : public MDNode { | ||||
| 3547 | friend class LLVMContextImpl; | ||||
| 3548 | friend class MDNode; | ||||
| 3549 | using iterator = SmallVectorImpl<ValueAsMetadata *>::iterator; | ||||
| 3550 | |||||
| 3551 | SmallVector<ValueAsMetadata *, 4> Args; | ||||
| 3552 | |||||
| 3553 | DIArgList(LLVMContext &C, StorageType Storage, | ||||
| 3554 | ArrayRef<ValueAsMetadata *> Args) | ||||
| 3555 | : MDNode(C, DIArgListKind, Storage, None), | ||||
| 3556 | Args(Args.begin(), Args.end()) { | ||||
| 3557 | track(); | ||||
| 3558 | } | ||||
| 3559 | ~DIArgList() { untrack(); } | ||||
| 3560 | |||||
| 3561 | static DIArgList *getImpl(LLVMContext &Context, | ||||
| 3562 | ArrayRef<ValueAsMetadata *> Args, | ||||
| 3563 | StorageType Storage, bool ShouldCreate = true); | ||||
| 3564 | |||||
| 3565 | TempDIArgList cloneImpl() const { | ||||
| 3566 | return getTemporary(getContext(), getArgs()); | ||||
| 3567 | } | ||||
| 3568 | |||||
| 3569 | void track(); | ||||
| 3570 | void untrack(); | ||||
| 3571 | void dropAllReferences(); | ||||
| 3572 | |||||
| 3573 | public: | ||||
| 3574 | DEFINE_MDNODE_GET(DIArgList, (ArrayRef<ValueAsMetadata *> Args), (Args)) | ||||
| 3575 | |||||
| 3576 | TempDIArgList clone() const { return cloneImpl(); } | ||||
| 3577 | |||||
| 3578 | ArrayRef<ValueAsMetadata *> getArgs() const { return Args; } | ||||
| 3579 | |||||
| 3580 | iterator args_begin() { return Args.begin(); } | ||||
| 3581 | iterator args_end() { return Args.end(); } | ||||
| 3582 | |||||
| 3583 | static bool classof(const Metadata *MD) { | ||||
| 3584 | return MD->getMetadataID() == DIArgListKind; | ||||
| 3585 | } | ||||
| 3586 | |||||
| 3587 | void handleChangedOperand(void *Ref, Metadata *New); | ||||
| 3588 | }; | ||||
| 3589 | |||||
| 3590 | /// Identifies a unique instance of a variable. | ||||
| 3591 | /// | ||||
| 3592 | /// Storage for identifying a potentially inlined instance of a variable, | ||||
| 3593 | /// or a fragment thereof. This guarantees that exactly one variable instance | ||||
| 3594 | /// may be identified by this class, even when that variable is a fragment of | ||||
| 3595 | /// an aggregate variable and/or there is another inlined instance of the same | ||||
| 3596 | /// source code variable nearby. | ||||
| 3597 | /// This class does not necessarily uniquely identify that variable: it is | ||||
| 3598 | /// possible that a DebugVariable with different parameters may point to the | ||||
| 3599 | /// same variable instance, but not that one DebugVariable points to multiple | ||||
| 3600 | /// variable instances. | ||||
| 3601 | class DebugVariable { | ||||
| 3602 | using FragmentInfo = DIExpression::FragmentInfo; | ||||
| 3603 | |||||
| 3604 | const DILocalVariable *Variable; | ||||
| 3605 | Optional<FragmentInfo> Fragment; | ||||
| 3606 | const DILocation *InlinedAt; | ||||
| 3607 | |||||
| 3608 | /// Fragment that will overlap all other fragments. Used as default when | ||||
| 3609 | /// caller demands a fragment. | ||||
| 3610 | static const FragmentInfo DefaultFragment; | ||||
| 3611 | |||||
| 3612 | public: | ||||
| 3613 | DebugVariable(const DILocalVariable *Var, Optional<FragmentInfo> FragmentInfo, | ||||
| 3614 | const DILocation *InlinedAt) | ||||
| 3615 | : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} | ||||
| 3616 | |||||
| 3617 | DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, | ||||
| 3618 | const DILocation *InlinedAt) | ||||
| 3619 | : Variable(Var), | ||||
| 3620 | Fragment(DIExpr ? DIExpr->getFragmentInfo() : NoneType()), | ||||
| 3621 | InlinedAt(InlinedAt) {} | ||||
| 3622 | |||||
| 3623 | const DILocalVariable *getVariable() const { return Variable; } | ||||
| 3624 | Optional<FragmentInfo> getFragment() const { return Fragment; } | ||||
| 3625 | const DILocation *getInlinedAt() const { return InlinedAt; } | ||||
| 3626 | |||||
| 3627 | FragmentInfo getFragmentOrDefault() const { | ||||
| 3628 | return Fragment.getValueOr(DefaultFragment); | ||||
| 3629 | } | ||||
| 3630 | |||||
| 3631 | static bool isDefaultFragment(const FragmentInfo F) { | ||||
| 3632 | return F == DefaultFragment; | ||||
| 3633 | } | ||||
| 3634 | |||||
| 3635 | bool operator==(const DebugVariable &Other) const { | ||||
| 3636 | return std::tie(Variable, Fragment, InlinedAt) == | ||||
| 3637 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||
| 3638 | } | ||||
| 3639 | |||||
| 3640 | bool operator<(const DebugVariable &Other) const { | ||||
| 3641 | return std::tie(Variable, Fragment, InlinedAt) < | ||||
| 3642 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||
| 3643 | } | ||||
| 3644 | }; | ||||
| 3645 | |||||
| 3646 | template <> struct DenseMapInfo<DebugVariable> { | ||||
| 3647 | using FragmentInfo = DIExpression::FragmentInfo; | ||||
| 3648 | |||||
| 3649 | /// Empty key: no key should be generated that has no DILocalVariable. | ||||
| 3650 | static inline DebugVariable getEmptyKey() { | ||||
| 3651 | return DebugVariable(nullptr, NoneType(), nullptr); | ||||
| 3652 | } | ||||
| 3653 | |||||
| 3654 | /// Difference in tombstone is that the Optional is meaningful. | ||||
| 3655 | static inline DebugVariable getTombstoneKey() { | ||||
| 3656 | return DebugVariable(nullptr, {{0, 0}}, nullptr); | ||||
| 3657 | } | ||||
| 3658 | |||||
| 3659 | static unsigned getHashValue(const DebugVariable &D) { | ||||
| 3660 | unsigned HV = 0; | ||||
| 3661 | const Optional<FragmentInfo> Fragment = D.getFragment(); | ||||
| 3662 | if (Fragment) | ||||
| 3663 | HV = DenseMapInfo<FragmentInfo>::getHashValue(*Fragment); | ||||
| 3664 | |||||
| 3665 | return hash_combine(D.getVariable(), HV, D.getInlinedAt()); | ||||
| 3666 | } | ||||
| 3667 | |||||
| 3668 | static bool isEqual(const DebugVariable &A, const DebugVariable &B) { | ||||
| 3669 | return A == B; | ||||
| 3670 | } | ||||
| 3671 | }; | ||||
| 3672 | |||||
| 3673 | } // end namespace llvm | ||||
| 3674 | |||||
| 3675 | #undef DEFINE_MDNODE_GET_UNPACK_IMPL | ||||
| 3676 | #undef DEFINE_MDNODE_GET_UNPACK | ||||
| 3677 | #undef DEFINE_MDNODE_GET | ||||
| 3678 | |||||
| 3679 | #endif // LLVM_IR_DEBUGINFOMETADATA_H |